1#![allow(unsafe_code)] use mysqlclient_sys as ffi;
3use std::mem::MaybeUninit;
4use std::mem::{self, ManuallyDrop};
5use std::ops::Index;
6use std::os::raw as libc;
7use std::ptr::NonNull;
8
9use super::stmt::{MysqlFieldMetadata, StatementUse};
10use crate::mysql::connection::stmt::StatementMetadata;
11use crate::mysql::types::date_and_time::MysqlTime;
12use crate::mysql::{MysqlType, MysqlValue};
13use crate::result::QueryResult;
14
15fn bind_buffer(data: Vec<u8>) -> (Option<NonNull<u8>>, libc::c_ulong, usize) {
16 let mut data = ManuallyDrop::new(data);
17 (
18 NonNull::new(data.as_mut_ptr()),
19 data.len() as libc::c_ulong,
20 data.capacity(),
21 )
22}
23
24pub(super) struct PreparedStatementBinds(Binds);
25
26pub(super) struct OutputBinds(Binds);
27
28impl Clone for OutputBinds {
29 fn clone(&self) -> Self {
30 Self(Binds {
31 data: self.0.data.clone(),
32 })
33 }
34}
35
36struct Binds {
37 data: Vec<BindData>,
38}
39
40impl PreparedStatementBinds {
41 pub(super) fn from_input_data<Iter>(input: Iter) -> Self
42 where
43 Iter: IntoIterator<Item = (MysqlType, Option<Vec<u8>>)>,
44 {
45 let data = input
46 .into_iter()
47 .map(BindData::for_input)
48 .collect::<Vec<_>>();
49
50 Self(Binds { data })
51 }
52
53 pub(super) fn with_mysql_binds<F, T>(&mut self, f: F) -> T
54 where
55 F: FnOnce(*mut ffi::MYSQL_BIND) -> T,
56 {
57 self.0.with_mysql_binds(f)
58 }
59}
60
61impl OutputBinds {
62 pub(super) fn from_output_types(
63 types: &[Option<MysqlType>],
64 metadata: &StatementMetadata,
65 ) -> Self {
66 let data = metadata
67 .fields()
68 .iter()
69 .zip(types.iter().copied().chain(std::iter::repeat(None)))
70 .map(|(field, tpe)| BindData::for_output(tpe, field))
71 .collect();
72
73 Self(Binds { data })
74 }
75
76 pub(super) fn populate_dynamic_buffers(&mut self, stmt: &StatementUse<'_>) -> QueryResult<()> {
77 for (i, data) in self.0.data.iter_mut().enumerate() {
78 data.did_numeric_overflow_occur()?;
79 unsafe {
82 if let Some((mut bind, offset)) = data.bind_for_truncated_data() {
83 stmt.fetch_column(&mut bind, i, offset)?
84 } else {
85 data.update_buffer_length()
86 }
87 }
88 }
89
90 unsafe { self.with_mysql_binds(|bind_ptr| stmt.bind_result(bind_ptr)) }
91 }
92
93 pub(super) fn update_buffer_lengths(&mut self) {
94 for data in &mut self.0.data {
95 data.update_buffer_length();
96 }
97 }
98
99 pub(super) fn with_mysql_binds<F, T>(&mut self, f: F) -> T
100 where
101 F: FnOnce(*mut ffi::MYSQL_BIND) -> T,
102 {
103 self.0.with_mysql_binds(f)
104 }
105}
106
107impl Binds {
108 fn with_mysql_binds<F, T>(&mut self, f: F) -> T
109 where
110 F: FnOnce(*mut ffi::MYSQL_BIND) -> T,
111 {
112 let mut binds = self
113 .data
114 .iter_mut()
115 .map(|x| unsafe { x.mysql_bind() })
116 .collect::<Vec<_>>();
117 f(binds.as_mut_ptr())
118 }
119}
120
121impl Index<usize> for OutputBinds {
122 type Output = BindData;
123 fn index(&self, index: usize) -> &Self::Output {
124 &self.0.data[index]
125 }
126}
127
128bitflags::bitflags! {
129 #[derive(#[automatically_derived]
impl ::core::clone::Clone for Flags {
#[inline]
fn clone(&self) -> Flags {
let _:
::core::clone::AssertParamIsClone<<Flags as
::bitflags::__private::PublicFlags>::Internal>;
*self
}
}
impl Flags {
#[allow(deprecated, non_upper_case_globals,)]
pub const NOT_NULL_FLAG: Self = Self::from_bits_retain(1);
#[allow(deprecated, non_upper_case_globals,)]
pub const PRI_KEY_FLAG: Self = Self::from_bits_retain(2);
#[allow(deprecated, non_upper_case_globals,)]
pub const UNIQUE_KEY_FLAG: Self = Self::from_bits_retain(4);
#[allow(deprecated, non_upper_case_globals,)]
pub const MULTIPLE_KEY_FLAG: Self = Self::from_bits_retain(8);
#[allow(deprecated, non_upper_case_globals,)]
pub const BLOB_FLAG: Self = Self::from_bits_retain(16);
#[allow(deprecated, non_upper_case_globals,)]
pub const UNSIGNED_FLAG: Self = Self::from_bits_retain(32);
#[allow(deprecated, non_upper_case_globals,)]
pub const ZEROFILL_FLAG: Self = Self::from_bits_retain(64);
#[allow(deprecated, non_upper_case_globals,)]
pub const BINARY_FLAG: Self = Self::from_bits_retain(128);
#[allow(deprecated, non_upper_case_globals,)]
pub const ENUM_FLAG: Self = Self::from_bits_retain(256);
#[allow(deprecated, non_upper_case_globals,)]
pub const AUTO_INCREMENT_FLAG: Self = Self::from_bits_retain(512);
#[allow(deprecated, non_upper_case_globals,)]
pub const TIMESTAMP_FLAG: Self = Self::from_bits_retain(1024);
#[allow(deprecated, non_upper_case_globals,)]
pub const SET_FLAG: Self = Self::from_bits_retain(2048);
#[allow(deprecated, non_upper_case_globals,)]
pub const NO_DEFAULT_VALUE_FLAG: Self = Self::from_bits_retain(4096);
#[allow(deprecated, non_upper_case_globals,)]
pub const ON_UPDATE_NOW_FLAG: Self = Self::from_bits_retain(8192);
#[allow(deprecated, non_upper_case_globals,)]
pub const NUM_FLAG: Self = Self::from_bits_retain(32768);
#[allow(deprecated, non_upper_case_globals,)]
pub const PART_KEY_FLAG: Self = Self::from_bits_retain(16384);
#[allow(deprecated, non_upper_case_globals,)]
pub const GROUP_FLAG: Self = Self::from_bits_retain(32768);
#[allow(deprecated, non_upper_case_globals,)]
pub const UNIQUE_FLAG: Self = Self::from_bits_retain(65536);
#[allow(deprecated, non_upper_case_globals,)]
pub const BINCMP_FLAG: Self = Self::from_bits_retain(130_172);
#[allow(deprecated, non_upper_case_globals,)]
pub const GET_FIXED_FIELDS_FLAG: Self = Self::from_bits_retain((1 << 18));
#[allow(deprecated, non_upper_case_globals,)]
pub const FIELD_IN_PART_FUNC_FLAG: Self =
Self::from_bits_retain((1 << 19));
}
impl ::bitflags::Flags for Flags {
const FLAGS: &'static [::bitflags::Flag<Flags>] =
&[{
#[allow(deprecated, non_upper_case_globals,)]
::bitflags::Flag::new("NOT_NULL_FLAG", Flags::NOT_NULL_FLAG)
},
{
#[allow(deprecated, non_upper_case_globals,)]
::bitflags::Flag::new("PRI_KEY_FLAG", Flags::PRI_KEY_FLAG)
},
{
#[allow(deprecated, non_upper_case_globals,)]
::bitflags::Flag::new("UNIQUE_KEY_FLAG",
Flags::UNIQUE_KEY_FLAG)
},
{
#[allow(deprecated, non_upper_case_globals,)]
::bitflags::Flag::new("MULTIPLE_KEY_FLAG",
Flags::MULTIPLE_KEY_FLAG)
},
{
#[allow(deprecated, non_upper_case_globals,)]
::bitflags::Flag::new("BLOB_FLAG", Flags::BLOB_FLAG)
},
{
#[allow(deprecated, non_upper_case_globals,)]
::bitflags::Flag::new("UNSIGNED_FLAG", Flags::UNSIGNED_FLAG)
},
{
#[allow(deprecated, non_upper_case_globals,)]
::bitflags::Flag::new("ZEROFILL_FLAG", Flags::ZEROFILL_FLAG)
},
{
#[allow(deprecated, non_upper_case_globals,)]
::bitflags::Flag::new("BINARY_FLAG", Flags::BINARY_FLAG)
},
{
#[allow(deprecated, non_upper_case_globals,)]
::bitflags::Flag::new("ENUM_FLAG", Flags::ENUM_FLAG)
},
{
#[allow(deprecated, non_upper_case_globals,)]
::bitflags::Flag::new("AUTO_INCREMENT_FLAG",
Flags::AUTO_INCREMENT_FLAG)
},
{
#[allow(deprecated, non_upper_case_globals,)]
::bitflags::Flag::new("TIMESTAMP_FLAG",
Flags::TIMESTAMP_FLAG)
},
{
#[allow(deprecated, non_upper_case_globals,)]
::bitflags::Flag::new("SET_FLAG", Flags::SET_FLAG)
},
{
#[allow(deprecated, non_upper_case_globals,)]
::bitflags::Flag::new("NO_DEFAULT_VALUE_FLAG",
Flags::NO_DEFAULT_VALUE_FLAG)
},
{
#[allow(deprecated, non_upper_case_globals,)]
::bitflags::Flag::new("ON_UPDATE_NOW_FLAG",
Flags::ON_UPDATE_NOW_FLAG)
},
{
#[allow(deprecated, non_upper_case_globals,)]
::bitflags::Flag::new("NUM_FLAG", Flags::NUM_FLAG)
},
{
#[allow(deprecated, non_upper_case_globals,)]
::bitflags::Flag::new("PART_KEY_FLAG", Flags::PART_KEY_FLAG)
},
{
#[allow(deprecated, non_upper_case_globals,)]
::bitflags::Flag::new("GROUP_FLAG", Flags::GROUP_FLAG)
},
{
#[allow(deprecated, non_upper_case_globals,)]
::bitflags::Flag::new("UNIQUE_FLAG", Flags::UNIQUE_FLAG)
},
{
#[allow(deprecated, non_upper_case_globals,)]
::bitflags::Flag::new("BINCMP_FLAG", Flags::BINCMP_FLAG)
},
{
#[allow(deprecated, non_upper_case_globals,)]
::bitflags::Flag::new("GET_FIXED_FIELDS_FLAG",
Flags::GET_FIXED_FIELDS_FLAG)
},
{
#[allow(deprecated, non_upper_case_globals,)]
::bitflags::Flag::new("FIELD_IN_PART_FUNC_FLAG",
Flags::FIELD_IN_PART_FUNC_FLAG)
}];
type Bits = u32;
fn bits(&self) -> u32 { Flags::bits(self) }
fn from_bits_retain(bits: u32) -> Flags { Flags::from_bits_retain(bits) }
}
#[allow(dead_code, deprecated, unused_doc_comments, unused_attributes,
unused_mut, unused_imports, non_upper_case_globals, clippy ::
assign_op_pattern, clippy :: indexing_slicing, clippy :: same_name_method,
clippy :: iter_without_into_iter,)]
const _: () =
{
#[repr(transparent)]
pub(crate) struct InternalBitFlags(u32);
#[automatically_derived]
#[doc(hidden)]
unsafe impl ::core::clone::TrivialClone for InternalBitFlags { }
#[automatically_derived]
impl ::core::clone::Clone for InternalBitFlags {
#[inline]
fn clone(&self) -> InternalBitFlags {
let _: ::core::clone::AssertParamIsClone<u32>;
*self
}
}
#[automatically_derived]
impl ::core::marker::Copy for InternalBitFlags { }
#[automatically_derived]
impl ::core::marker::StructuralPartialEq for InternalBitFlags { }
#[automatically_derived]
impl ::core::cmp::PartialEq for InternalBitFlags {
#[inline]
fn eq(&self, other: &InternalBitFlags) -> bool {
self.0 == other.0
}
}
#[automatically_derived]
impl ::core::cmp::Eq for InternalBitFlags {
#[inline]
#[doc(hidden)]
#[coverage(off)]
fn assert_receiver_is_total_eq(&self) -> () {
let _: ::core::cmp::AssertParamIsEq<u32>;
}
}
#[automatically_derived]
impl ::core::cmp::PartialOrd for InternalBitFlags {
#[inline]
fn partial_cmp(&self, other: &InternalBitFlags)
-> ::core::option::Option<::core::cmp::Ordering> {
::core::cmp::PartialOrd::partial_cmp(&self.0, &other.0)
}
}
#[automatically_derived]
impl ::core::cmp::Ord for InternalBitFlags {
#[inline]
fn cmp(&self, other: &InternalBitFlags) -> ::core::cmp::Ordering {
::core::cmp::Ord::cmp(&self.0, &other.0)
}
}
#[automatically_derived]
impl ::core::hash::Hash for InternalBitFlags {
#[inline]
fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) -> () {
::core::hash::Hash::hash(&self.0, state)
}
}
impl ::bitflags::__private::PublicFlags for Flags {
type Primitive = u32;
type Internal = InternalBitFlags;
}
impl ::bitflags::__private::core::default::Default for
InternalBitFlags {
#[inline]
fn default() -> Self { InternalBitFlags::empty() }
}
impl ::bitflags::__private::core::fmt::Debug for InternalBitFlags {
fn fmt(&self,
f: &mut ::bitflags::__private::core::fmt::Formatter<'_>)
-> ::bitflags::__private::core::fmt::Result {
if self.is_empty() {
f.write_fmt(format_args!("{0:#x}",
<u32 as ::bitflags::Bits>::EMPTY))
} else {
::bitflags::__private::core::fmt::Display::fmt(self, f)
}
}
}
impl ::bitflags::__private::core::fmt::Display for InternalBitFlags {
fn fmt(&self,
f: &mut ::bitflags::__private::core::fmt::Formatter<'_>)
-> ::bitflags::__private::core::fmt::Result {
::bitflags::parser::to_writer(&Flags(*self), f)
}
}
impl ::bitflags::__private::core::str::FromStr for InternalBitFlags {
type Err = ::bitflags::parser::ParseError;
fn from_str(s: &str)
->
::bitflags::__private::core::result::Result<Self,
Self::Err> {
::bitflags::parser::from_str::<Flags>(s).map(|flags| flags.0)
}
}
impl ::bitflags::__private::core::convert::AsRef<u32> for
InternalBitFlags {
fn as_ref(&self) -> &u32 { &self.0 }
}
impl ::bitflags::__private::core::convert::From<u32> for
InternalBitFlags {
fn from(bits: u32) -> Self { Self::from_bits_retain(bits) }
}
#[allow(dead_code, deprecated, unused_attributes)]
impl InternalBitFlags {
#[inline]
pub const fn empty() -> Self {
Self(<u32 as ::bitflags::Bits>::EMPTY)
}
#[inline]
pub const fn all() -> Self {
let mut truncated = <u32 as ::bitflags::Bits>::EMPTY;
let mut i = 0;
{
{
let flag =
<Flags as ::bitflags::Flags>::FLAGS[i].value().bits();
truncated = truncated | flag;
i += 1;
}
};
{
{
let flag =
<Flags as ::bitflags::Flags>::FLAGS[i].value().bits();
truncated = truncated | flag;
i += 1;
}
};
{
{
let flag =
<Flags as ::bitflags::Flags>::FLAGS[i].value().bits();
truncated = truncated | flag;
i += 1;
}
};
{
{
let flag =
<Flags as ::bitflags::Flags>::FLAGS[i].value().bits();
truncated = truncated | flag;
i += 1;
}
};
{
{
let flag =
<Flags as ::bitflags::Flags>::FLAGS[i].value().bits();
truncated = truncated | flag;
i += 1;
}
};
{
{
let flag =
<Flags as ::bitflags::Flags>::FLAGS[i].value().bits();
truncated = truncated | flag;
i += 1;
}
};
{
{
let flag =
<Flags as ::bitflags::Flags>::FLAGS[i].value().bits();
truncated = truncated | flag;
i += 1;
}
};
{
{
let flag =
<Flags as ::bitflags::Flags>::FLAGS[i].value().bits();
truncated = truncated | flag;
i += 1;
}
};
{
{
let flag =
<Flags as ::bitflags::Flags>::FLAGS[i].value().bits();
truncated = truncated | flag;
i += 1;
}
};
{
{
let flag =
<Flags as ::bitflags::Flags>::FLAGS[i].value().bits();
truncated = truncated | flag;
i += 1;
}
};
{
{
let flag =
<Flags as ::bitflags::Flags>::FLAGS[i].value().bits();
truncated = truncated | flag;
i += 1;
}
};
{
{
let flag =
<Flags as ::bitflags::Flags>::FLAGS[i].value().bits();
truncated = truncated | flag;
i += 1;
}
};
{
{
let flag =
<Flags as ::bitflags::Flags>::FLAGS[i].value().bits();
truncated = truncated | flag;
i += 1;
}
};
{
{
let flag =
<Flags as ::bitflags::Flags>::FLAGS[i].value().bits();
truncated = truncated | flag;
i += 1;
}
};
{
{
let flag =
<Flags as ::bitflags::Flags>::FLAGS[i].value().bits();
truncated = truncated | flag;
i += 1;
}
};
{
{
let flag =
<Flags as ::bitflags::Flags>::FLAGS[i].value().bits();
truncated = truncated | flag;
i += 1;
}
};
{
{
let flag =
<Flags as ::bitflags::Flags>::FLAGS[i].value().bits();
truncated = truncated | flag;
i += 1;
}
};
{
{
let flag =
<Flags as ::bitflags::Flags>::FLAGS[i].value().bits();
truncated = truncated | flag;
i += 1;
}
};
{
{
let flag =
<Flags as ::bitflags::Flags>::FLAGS[i].value().bits();
truncated = truncated | flag;
i += 1;
}
};
{
{
let flag =
<Flags as ::bitflags::Flags>::FLAGS[i].value().bits();
truncated = truncated | flag;
i += 1;
}
};
{
{
let flag =
<Flags as ::bitflags::Flags>::FLAGS[i].value().bits();
truncated = truncated | flag;
i += 1;
}
};
let _ = i;
Self(truncated)
}
#[inline]
pub const fn bits(&self) -> u32 { self.0 }
#[inline]
pub const fn from_bits(bits: u32)
-> ::bitflags::__private::core::option::Option<Self> {
let truncated = Self::from_bits_truncate(bits).0;
if truncated == bits {
::bitflags::__private::core::option::Option::Some(Self(bits))
} else { ::bitflags::__private::core::option::Option::None }
}
#[inline]
pub const fn from_bits_truncate(bits: u32) -> Self {
Self(bits & Self::all().0)
}
#[inline]
pub const fn from_bits_retain(bits: u32) -> Self { Self(bits) }
#[inline]
pub fn from_name(name: &str)
-> ::bitflags::__private::core::option::Option<Self> {
{
if name == "NOT_NULL_FLAG" {
return ::bitflags::__private::core::option::Option::Some(Self(Flags::NOT_NULL_FLAG.bits()));
}
};
;
{
if name == "PRI_KEY_FLAG" {
return ::bitflags::__private::core::option::Option::Some(Self(Flags::PRI_KEY_FLAG.bits()));
}
};
;
{
if name == "UNIQUE_KEY_FLAG" {
return ::bitflags::__private::core::option::Option::Some(Self(Flags::UNIQUE_KEY_FLAG.bits()));
}
};
;
{
if name == "MULTIPLE_KEY_FLAG" {
return ::bitflags::__private::core::option::Option::Some(Self(Flags::MULTIPLE_KEY_FLAG.bits()));
}
};
;
{
if name == "BLOB_FLAG" {
return ::bitflags::__private::core::option::Option::Some(Self(Flags::BLOB_FLAG.bits()));
}
};
;
{
if name == "UNSIGNED_FLAG" {
return ::bitflags::__private::core::option::Option::Some(Self(Flags::UNSIGNED_FLAG.bits()));
}
};
;
{
if name == "ZEROFILL_FLAG" {
return ::bitflags::__private::core::option::Option::Some(Self(Flags::ZEROFILL_FLAG.bits()));
}
};
;
{
if name == "BINARY_FLAG" {
return ::bitflags::__private::core::option::Option::Some(Self(Flags::BINARY_FLAG.bits()));
}
};
;
{
if name == "ENUM_FLAG" {
return ::bitflags::__private::core::option::Option::Some(Self(Flags::ENUM_FLAG.bits()));
}
};
;
{
if name == "AUTO_INCREMENT_FLAG" {
return ::bitflags::__private::core::option::Option::Some(Self(Flags::AUTO_INCREMENT_FLAG.bits()));
}
};
;
{
if name == "TIMESTAMP_FLAG" {
return ::bitflags::__private::core::option::Option::Some(Self(Flags::TIMESTAMP_FLAG.bits()));
}
};
;
{
if name == "SET_FLAG" {
return ::bitflags::__private::core::option::Option::Some(Self(Flags::SET_FLAG.bits()));
}
};
;
{
if name == "NO_DEFAULT_VALUE_FLAG" {
return ::bitflags::__private::core::option::Option::Some(Self(Flags::NO_DEFAULT_VALUE_FLAG.bits()));
}
};
;
{
if name == "ON_UPDATE_NOW_FLAG" {
return ::bitflags::__private::core::option::Option::Some(Self(Flags::ON_UPDATE_NOW_FLAG.bits()));
}
};
;
{
if name == "NUM_FLAG" {
return ::bitflags::__private::core::option::Option::Some(Self(Flags::NUM_FLAG.bits()));
}
};
;
{
if name == "PART_KEY_FLAG" {
return ::bitflags::__private::core::option::Option::Some(Self(Flags::PART_KEY_FLAG.bits()));
}
};
;
{
if name == "GROUP_FLAG" {
return ::bitflags::__private::core::option::Option::Some(Self(Flags::GROUP_FLAG.bits()));
}
};
;
{
if name == "UNIQUE_FLAG" {
return ::bitflags::__private::core::option::Option::Some(Self(Flags::UNIQUE_FLAG.bits()));
}
};
;
{
if name == "BINCMP_FLAG" {
return ::bitflags::__private::core::option::Option::Some(Self(Flags::BINCMP_FLAG.bits()));
}
};
;
{
if name == "GET_FIXED_FIELDS_FLAG" {
return ::bitflags::__private::core::option::Option::Some(Self(Flags::GET_FIXED_FIELDS_FLAG.bits()));
}
};
;
{
if name == "FIELD_IN_PART_FUNC_FLAG" {
return ::bitflags::__private::core::option::Option::Some(Self(Flags::FIELD_IN_PART_FUNC_FLAG.bits()));
}
};
;
let _ = name;
::bitflags::__private::core::option::Option::None
}
#[inline]
pub const fn is_empty(&self) -> bool {
self.0 == <u32 as ::bitflags::Bits>::EMPTY
}
#[inline]
pub const fn is_all(&self) -> bool {
Self::all().0 | self.0 == self.0
}
#[inline]
pub const fn intersects(&self, other: Self) -> bool {
self.0 & other.0 != <u32 as ::bitflags::Bits>::EMPTY
}
#[inline]
pub const fn contains(&self, other: Self) -> bool {
self.0 & other.0 == other.0
}
#[inline]
pub fn insert(&mut self, other: Self) {
*self = Self(self.0).union(other);
}
#[inline]
pub fn remove(&mut self, other: Self) {
*self = Self(self.0).difference(other);
}
#[inline]
pub fn toggle(&mut self, other: Self) {
*self = Self(self.0).symmetric_difference(other);
}
#[inline]
pub fn set(&mut self, other: Self, value: bool) {
if value { self.insert(other); } else { self.remove(other); }
}
#[inline]
#[must_use]
pub const fn intersection(self, other: Self) -> Self {
Self(self.0 & other.0)
}
#[inline]
#[must_use]
pub const fn union(self, other: Self) -> Self {
Self(self.0 | other.0)
}
#[inline]
#[must_use]
pub const fn difference(self, other: Self) -> Self {
Self(self.0 & !other.0)
}
#[inline]
#[must_use]
pub const fn symmetric_difference(self, other: Self) -> Self {
Self(self.0 ^ other.0)
}
#[inline]
#[must_use]
pub const fn complement(self) -> Self {
Self::from_bits_truncate(!self.0)
}
}
impl ::bitflags::__private::core::fmt::Binary for InternalBitFlags {
fn fmt(&self, f: &mut ::bitflags::__private::core::fmt::Formatter)
-> ::bitflags::__private::core::fmt::Result {
let inner = self.0;
::bitflags::__private::core::fmt::Binary::fmt(&inner, f)
}
}
impl ::bitflags::__private::core::fmt::Octal for InternalBitFlags {
fn fmt(&self, f: &mut ::bitflags::__private::core::fmt::Formatter)
-> ::bitflags::__private::core::fmt::Result {
let inner = self.0;
::bitflags::__private::core::fmt::Octal::fmt(&inner, f)
}
}
impl ::bitflags::__private::core::fmt::LowerHex for InternalBitFlags {
fn fmt(&self, f: &mut ::bitflags::__private::core::fmt::Formatter)
-> ::bitflags::__private::core::fmt::Result {
let inner = self.0;
::bitflags::__private::core::fmt::LowerHex::fmt(&inner, f)
}
}
impl ::bitflags::__private::core::fmt::UpperHex for InternalBitFlags {
fn fmt(&self, f: &mut ::bitflags::__private::core::fmt::Formatter)
-> ::bitflags::__private::core::fmt::Result {
let inner = self.0;
::bitflags::__private::core::fmt::UpperHex::fmt(&inner, f)
}
}
impl ::bitflags::__private::core::ops::BitOr for InternalBitFlags {
type Output = Self;
#[inline]
fn bitor(self, other: InternalBitFlags) -> Self {
self.union(other)
}
}
impl ::bitflags::__private::core::ops::BitOrAssign for
InternalBitFlags {
#[inline]
fn bitor_assign(&mut self, other: Self) { self.insert(other); }
}
impl ::bitflags::__private::core::ops::BitXor for InternalBitFlags {
type Output = Self;
#[inline]
fn bitxor(self, other: Self) -> Self {
self.symmetric_difference(other)
}
}
impl ::bitflags::__private::core::ops::BitXorAssign for
InternalBitFlags {
#[inline]
fn bitxor_assign(&mut self, other: Self) { self.toggle(other); }
}
impl ::bitflags::__private::core::ops::BitAnd for InternalBitFlags {
type Output = Self;
#[inline]
fn bitand(self, other: Self) -> Self { self.intersection(other) }
}
impl ::bitflags::__private::core::ops::BitAndAssign for
InternalBitFlags {
#[inline]
fn bitand_assign(&mut self, other: Self) {
*self =
Self::from_bits_retain(self.bits()).intersection(other);
}
}
impl ::bitflags::__private::core::ops::Sub for InternalBitFlags {
type Output = Self;
#[inline]
fn sub(self, other: Self) -> Self { self.difference(other) }
}
impl ::bitflags::__private::core::ops::SubAssign for InternalBitFlags
{
#[inline]
fn sub_assign(&mut self, other: Self) { self.remove(other); }
}
impl ::bitflags::__private::core::ops::Not for InternalBitFlags {
type Output = Self;
#[inline]
fn not(self) -> Self { self.complement() }
}
impl ::bitflags::__private::core::iter::Extend<InternalBitFlags> for
InternalBitFlags {
fn extend<T: ::bitflags::__private::core::iter::IntoIterator<Item
= Self>>(&mut self, iterator: T) {
for item in iterator { self.insert(item) }
}
}
impl ::bitflags::__private::core::iter::FromIterator<InternalBitFlags>
for InternalBitFlags {
fn from_iter<T: ::bitflags::__private::core::iter::IntoIterator<Item
= Self>>(iterator: T) -> Self {
use ::bitflags::__private::core::iter::Extend;
let mut result = Self::empty();
result.extend(iterator);
result
}
}
impl InternalBitFlags {
#[inline]
pub const fn iter(&self) -> ::bitflags::iter::Iter<Flags> {
::bitflags::iter::Iter::__private_const_new(<Flags as
::bitflags::Flags>::FLAGS,
Flags::from_bits_retain(self.bits()),
Flags::from_bits_retain(self.bits()))
}
#[inline]
pub const fn iter_names(&self)
-> ::bitflags::iter::IterNames<Flags> {
::bitflags::iter::IterNames::__private_const_new(<Flags as
::bitflags::Flags>::FLAGS,
Flags::from_bits_retain(self.bits()),
Flags::from_bits_retain(self.bits()))
}
}
impl ::bitflags::__private::core::iter::IntoIterator for
InternalBitFlags {
type Item = Flags;
type IntoIter = ::bitflags::iter::Iter<Flags>;
fn into_iter(self) -> Self::IntoIter { self.iter() }
}
impl InternalBitFlags {
#[inline]
pub fn bits_mut(&mut self) -> &mut u32 { &mut self.0 }
}
#[allow(dead_code, deprecated, unused_attributes)]
impl Flags {
#[inline]
pub const fn empty() -> Self { Self(InternalBitFlags::empty()) }
#[inline]
pub const fn all() -> Self { Self(InternalBitFlags::all()) }
#[inline]
pub const fn bits(&self) -> u32 { self.0.bits() }
#[inline]
pub const fn from_bits(bits: u32)
-> ::bitflags::__private::core::option::Option<Self> {
match InternalBitFlags::from_bits(bits) {
::bitflags::__private::core::option::Option::Some(bits) =>
::bitflags::__private::core::option::Option::Some(Self(bits)),
::bitflags::__private::core::option::Option::None =>
::bitflags::__private::core::option::Option::None,
}
}
#[inline]
pub const fn from_bits_truncate(bits: u32) -> Self {
Self(InternalBitFlags::from_bits_truncate(bits))
}
#[inline]
pub const fn from_bits_retain(bits: u32) -> Self {
Self(InternalBitFlags::from_bits_retain(bits))
}
#[inline]
pub fn from_name(name: &str)
-> ::bitflags::__private::core::option::Option<Self> {
match InternalBitFlags::from_name(name) {
::bitflags::__private::core::option::Option::Some(bits) =>
::bitflags::__private::core::option::Option::Some(Self(bits)),
::bitflags::__private::core::option::Option::None =>
::bitflags::__private::core::option::Option::None,
}
}
#[inline]
pub const fn is_empty(&self) -> bool { self.0.is_empty() }
#[inline]
pub const fn is_all(&self) -> bool { self.0.is_all() }
#[inline]
pub const fn intersects(&self, other: Self) -> bool {
self.0.intersects(other.0)
}
#[inline]
pub const fn contains(&self, other: Self) -> bool {
self.0.contains(other.0)
}
#[inline]
pub fn insert(&mut self, other: Self) { self.0.insert(other.0) }
#[inline]
pub fn remove(&mut self, other: Self) { self.0.remove(other.0) }
#[inline]
pub fn toggle(&mut self, other: Self) { self.0.toggle(other.0) }
#[inline]
pub fn set(&mut self, other: Self, value: bool) {
self.0.set(other.0, value)
}
#[inline]
#[must_use]
pub const fn intersection(self, other: Self) -> Self {
Self(self.0.intersection(other.0))
}
#[inline]
#[must_use]
pub const fn union(self, other: Self) -> Self {
Self(self.0.union(other.0))
}
#[inline]
#[must_use]
pub const fn difference(self, other: Self) -> Self {
Self(self.0.difference(other.0))
}
#[inline]
#[must_use]
pub const fn symmetric_difference(self, other: Self) -> Self {
Self(self.0.symmetric_difference(other.0))
}
#[inline]
#[must_use]
pub const fn complement(self) -> Self {
Self(self.0.complement())
}
}
impl ::bitflags::__private::core::fmt::Binary for Flags {
fn fmt(&self, f: &mut ::bitflags::__private::core::fmt::Formatter)
-> ::bitflags::__private::core::fmt::Result {
let inner = self.0;
::bitflags::__private::core::fmt::Binary::fmt(&inner, f)
}
}
impl ::bitflags::__private::core::fmt::Octal for Flags {
fn fmt(&self, f: &mut ::bitflags::__private::core::fmt::Formatter)
-> ::bitflags::__private::core::fmt::Result {
let inner = self.0;
::bitflags::__private::core::fmt::Octal::fmt(&inner, f)
}
}
impl ::bitflags::__private::core::fmt::LowerHex for Flags {
fn fmt(&self, f: &mut ::bitflags::__private::core::fmt::Formatter)
-> ::bitflags::__private::core::fmt::Result {
let inner = self.0;
::bitflags::__private::core::fmt::LowerHex::fmt(&inner, f)
}
}
impl ::bitflags::__private::core::fmt::UpperHex for Flags {
fn fmt(&self, f: &mut ::bitflags::__private::core::fmt::Formatter)
-> ::bitflags::__private::core::fmt::Result {
let inner = self.0;
::bitflags::__private::core::fmt::UpperHex::fmt(&inner, f)
}
}
impl ::bitflags::__private::core::ops::BitOr for Flags {
type Output = Self;
#[inline]
fn bitor(self, other: Flags) -> Self { self.union(other) }
}
impl ::bitflags::__private::core::ops::BitOrAssign for Flags {
#[inline]
fn bitor_assign(&mut self, other: Self) { self.insert(other); }
}
impl ::bitflags::__private::core::ops::BitXor for Flags {
type Output = Self;
#[inline]
fn bitxor(self, other: Self) -> Self {
self.symmetric_difference(other)
}
}
impl ::bitflags::__private::core::ops::BitXorAssign for Flags {
#[inline]
fn bitxor_assign(&mut self, other: Self) { self.toggle(other); }
}
impl ::bitflags::__private::core::ops::BitAnd for Flags {
type Output = Self;
#[inline]
fn bitand(self, other: Self) -> Self { self.intersection(other) }
}
impl ::bitflags::__private::core::ops::BitAndAssign for Flags {
#[inline]
fn bitand_assign(&mut self, other: Self) {
*self =
Self::from_bits_retain(self.bits()).intersection(other);
}
}
impl ::bitflags::__private::core::ops::Sub for Flags {
type Output = Self;
#[inline]
fn sub(self, other: Self) -> Self { self.difference(other) }
}
impl ::bitflags::__private::core::ops::SubAssign for Flags {
#[inline]
fn sub_assign(&mut self, other: Self) { self.remove(other); }
}
impl ::bitflags::__private::core::ops::Not for Flags {
type Output = Self;
#[inline]
fn not(self) -> Self { self.complement() }
}
impl ::bitflags::__private::core::iter::Extend<Flags> for Flags {
fn extend<T: ::bitflags::__private::core::iter::IntoIterator<Item
= Self>>(&mut self, iterator: T) {
for item in iterator { self.insert(item) }
}
}
impl ::bitflags::__private::core::iter::FromIterator<Flags> for Flags
{
fn from_iter<T: ::bitflags::__private::core::iter::IntoIterator<Item
= Self>>(iterator: T) -> Self {
use ::bitflags::__private::core::iter::Extend;
let mut result = Self::empty();
result.extend(iterator);
result
}
}
impl Flags {
#[inline]
pub const fn iter(&self) -> ::bitflags::iter::Iter<Flags> {
::bitflags::iter::Iter::__private_const_new(<Flags as
::bitflags::Flags>::FLAGS,
Flags::from_bits_retain(self.bits()),
Flags::from_bits_retain(self.bits()))
}
#[inline]
pub const fn iter_names(&self)
-> ::bitflags::iter::IterNames<Flags> {
::bitflags::iter::IterNames::__private_const_new(<Flags as
::bitflags::Flags>::FLAGS,
Flags::from_bits_retain(self.bits()),
Flags::from_bits_retain(self.bits()))
}
}
impl ::bitflags::__private::core::iter::IntoIterator for Flags {
type Item = Flags;
type IntoIter = ::bitflags::iter::Iter<Flags>;
fn into_iter(self) -> Self::IntoIter { self.iter() }
}
};Clone, #[automatically_derived]
impl ::core::marker::Copy for Flags { }Copy, #[automatically_derived]
impl ::core::fmt::Debug for Flags {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::debug_tuple_field1_finish(f, "Flags",
&&self.0)
}
}Debug)]
130 pub(crate) struct Flags: u32 {
131 const NOT_NULL_FLAG = 1;
132 const PRI_KEY_FLAG = 2;
133 const UNIQUE_KEY_FLAG = 4;
134 const MULTIPLE_KEY_FLAG = 8;
135 const BLOB_FLAG = 16;
136 const UNSIGNED_FLAG = 32;
137 const ZEROFILL_FLAG = 64;
138 const BINARY_FLAG = 128;
139 const ENUM_FLAG = 256;
140 const AUTO_INCREMENT_FLAG = 512;
141 const TIMESTAMP_FLAG = 1024;
142 const SET_FLAG = 2048;
143 const NO_DEFAULT_VALUE_FLAG = 4096;
144 const ON_UPDATE_NOW_FLAG = 8192;
145 const NUM_FLAG = 32768;
146 const PART_KEY_FLAG = 16384;
147 const GROUP_FLAG = 32768;
148 const UNIQUE_FLAG = 65536;
149 const BINCMP_FLAG = 130_172;
150 const GET_FIXED_FIELDS_FLAG = (1<<18);
151 const FIELD_IN_PART_FUNC_FLAG = (1 << 19);
152 }
153}
154
155impl From<u32> for Flags {
156 fn from(flags: u32) -> Self {
157 Flags::from_bits(flags).expect(
158 "We encountered an unknown type flag while parsing \
159 Mysql's type information. If you see this error message \
160 please open an issue at diesels github page.",
161 )
162 }
163}
164
165#[derive(#[automatically_derived]
impl ::core::fmt::Debug for BindData {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
let names: &'static _ =
&["tpe", "bytes", "length", "capacity", "flags", "is_null",
"is_truncated"];
let values: &[&dyn ::core::fmt::Debug] =
&[&self.tpe, &self.bytes, &self.length, &self.capacity,
&self.flags, &self.is_null, &&self.is_truncated];
::core::fmt::Formatter::debug_struct_fields_finish(f, "BindData",
names, values)
}
}Debug)]
166pub(super) struct BindData {
167 tpe: ffi::enum_field_types,
168 bytes: Option<NonNull<u8>>,
169 length: libc::c_ulong,
170 capacity: usize,
171 flags: Flags,
172 is_null: ffi::my_bool,
173 is_truncated: Option<ffi::my_bool>,
174}
175
176impl Clone for BindData {
180 fn clone(&self) -> Self {
181 let (ptr, len, capacity) = if let Some(ptr) = self.bytes {
182 let slice = unsafe {
183 std::slice::from_raw_parts(
191 ptr.as_ptr(),
192 self.length.try_into().expect("usize is at least 32bit"),
193 )
194 };
195 bind_buffer(slice.to_owned())
196 } else {
197 (None, 0, 0)
198 };
199 Self {
200 tpe: self.tpe,
201 bytes: ptr,
202 length: len,
203 capacity,
204 flags: self.flags,
205 is_null: self.is_null,
206 is_truncated: self.is_truncated,
207 }
208 }
209}
210
211impl Drop for BindData {
212 fn drop(&mut self) {
213 if let Some(bytes) = self.bytes {
214 std::mem::drop(unsafe {
215 Vec::from_raw_parts(bytes.as_ptr(), 0, self.capacity)
222 });
223 self.bytes = None;
224 }
225 }
226}
227
228impl BindData {
229 fn for_input((tpe, data): (MysqlType, Option<Vec<u8>>)) -> Self {
230 let (tpe, flags) = tpe.into();
231 let is_null = ffi::my_bool::from(data.is_none());
232 let (ptr, len, capacity) = bind_buffer(data.unwrap_or_default());
233 Self {
234 tpe,
235 bytes: ptr,
236 length: len,
237 capacity,
238 flags,
239 is_null,
240 is_truncated: None,
241 }
242 }
243
244 fn for_output(tpe: Option<MysqlType>, metadata: &MysqlFieldMetadata<'_>) -> Self {
245 let (tpe, flags) = if let Some(tpe) = tpe {
246 match (tpe, metadata.field_type()) {
247 (MysqlType::Tiny, ffi::enum_field_types::MYSQL_TYPE_DECIMAL)
250 | (MysqlType::Tiny, ffi::enum_field_types::MYSQL_TYPE_TINY)
251 | (MysqlType::Tiny, ffi::enum_field_types::MYSQL_TYPE_SHORT)
252 | (MysqlType::Tiny, ffi::enum_field_types::MYSQL_TYPE_LONG)
253 | (MysqlType::Tiny, ffi::enum_field_types::MYSQL_TYPE_FLOAT)
254 | (MysqlType::Tiny, ffi::enum_field_types::MYSQL_TYPE_DOUBLE)
255 | (MysqlType::Tiny, ffi::enum_field_types::MYSQL_TYPE_INT24)
256 | (MysqlType::Tiny, ffi::enum_field_types::MYSQL_TYPE_NEWDECIMAL)
257 | (MysqlType::Tiny, ffi::enum_field_types::MYSQL_TYPE_LONGLONG)
258 | (MysqlType::UnsignedTiny, ffi::enum_field_types::MYSQL_TYPE_DECIMAL)
259 | (MysqlType::UnsignedTiny, ffi::enum_field_types::MYSQL_TYPE_TINY)
260 | (MysqlType::UnsignedTiny, ffi::enum_field_types::MYSQL_TYPE_SHORT)
261 | (MysqlType::UnsignedTiny, ffi::enum_field_types::MYSQL_TYPE_LONG)
262 | (MysqlType::UnsignedTiny, ffi::enum_field_types::MYSQL_TYPE_FLOAT)
263 | (MysqlType::UnsignedTiny, ffi::enum_field_types::MYSQL_TYPE_DOUBLE)
264 | (MysqlType::UnsignedTiny, ffi::enum_field_types::MYSQL_TYPE_INT24)
265 | (MysqlType::UnsignedTiny, ffi::enum_field_types::MYSQL_TYPE_NEWDECIMAL)
266 | (MysqlType::UnsignedTiny, ffi::enum_field_types::MYSQL_TYPE_LONGLONG)
267 | (MysqlType::Short, ffi::enum_field_types::MYSQL_TYPE_DECIMAL)
268 | (MysqlType::Short, ffi::enum_field_types::MYSQL_TYPE_TINY)
269 | (MysqlType::Short, ffi::enum_field_types::MYSQL_TYPE_SHORT)
270 | (MysqlType::Short, ffi::enum_field_types::MYSQL_TYPE_LONG)
271 | (MysqlType::Short, ffi::enum_field_types::MYSQL_TYPE_FLOAT)
272 | (MysqlType::Short, ffi::enum_field_types::MYSQL_TYPE_DOUBLE)
273 | (MysqlType::Short, ffi::enum_field_types::MYSQL_TYPE_INT24)
274 | (MysqlType::Short, ffi::enum_field_types::MYSQL_TYPE_NEWDECIMAL)
275 | (MysqlType::Short, ffi::enum_field_types::MYSQL_TYPE_LONGLONG)
276 | (MysqlType::UnsignedShort, ffi::enum_field_types::MYSQL_TYPE_DECIMAL)
277 | (MysqlType::UnsignedShort, ffi::enum_field_types::MYSQL_TYPE_TINY)
278 | (MysqlType::UnsignedShort, ffi::enum_field_types::MYSQL_TYPE_SHORT)
279 | (MysqlType::UnsignedShort, ffi::enum_field_types::MYSQL_TYPE_LONG)
280 | (MysqlType::UnsignedShort, ffi::enum_field_types::MYSQL_TYPE_FLOAT)
281 | (MysqlType::UnsignedShort, ffi::enum_field_types::MYSQL_TYPE_DOUBLE)
282 | (MysqlType::UnsignedShort, ffi::enum_field_types::MYSQL_TYPE_INT24)
283 | (MysqlType::UnsignedShort, ffi::enum_field_types::MYSQL_TYPE_NEWDECIMAL)
284 | (MysqlType::UnsignedShort, ffi::enum_field_types::MYSQL_TYPE_LONGLONG)
285 | (MysqlType::Long, ffi::enum_field_types::MYSQL_TYPE_DECIMAL)
286 | (MysqlType::Long, ffi::enum_field_types::MYSQL_TYPE_TINY)
287 | (MysqlType::Long, ffi::enum_field_types::MYSQL_TYPE_SHORT)
288 | (MysqlType::Long, ffi::enum_field_types::MYSQL_TYPE_LONG)
289 | (MysqlType::Long, ffi::enum_field_types::MYSQL_TYPE_FLOAT)
290 | (MysqlType::Long, ffi::enum_field_types::MYSQL_TYPE_DOUBLE)
291 | (MysqlType::Long, ffi::enum_field_types::MYSQL_TYPE_INT24)
292 | (MysqlType::Long, ffi::enum_field_types::MYSQL_TYPE_NEWDECIMAL)
293 | (MysqlType::Long, ffi::enum_field_types::MYSQL_TYPE_LONGLONG)
294 | (MysqlType::UnsignedLong, ffi::enum_field_types::MYSQL_TYPE_DECIMAL)
295 | (MysqlType::UnsignedLong, ffi::enum_field_types::MYSQL_TYPE_TINY)
296 | (MysqlType::UnsignedLong, ffi::enum_field_types::MYSQL_TYPE_SHORT)
297 | (MysqlType::UnsignedLong, ffi::enum_field_types::MYSQL_TYPE_LONG)
298 | (MysqlType::UnsignedLong, ffi::enum_field_types::MYSQL_TYPE_FLOAT)
299 | (MysqlType::UnsignedLong, ffi::enum_field_types::MYSQL_TYPE_DOUBLE)
300 | (MysqlType::UnsignedLong, ffi::enum_field_types::MYSQL_TYPE_INT24)
301 | (MysqlType::UnsignedLong, ffi::enum_field_types::MYSQL_TYPE_NEWDECIMAL)
302 | (MysqlType::UnsignedLong, ffi::enum_field_types::MYSQL_TYPE_LONGLONG)
303 | (MysqlType::LongLong, ffi::enum_field_types::MYSQL_TYPE_DECIMAL)
304 | (MysqlType::LongLong, ffi::enum_field_types::MYSQL_TYPE_TINY)
305 | (MysqlType::LongLong, ffi::enum_field_types::MYSQL_TYPE_SHORT)
306 | (MysqlType::LongLong, ffi::enum_field_types::MYSQL_TYPE_LONG)
307 | (MysqlType::LongLong, ffi::enum_field_types::MYSQL_TYPE_FLOAT)
308 | (MysqlType::LongLong, ffi::enum_field_types::MYSQL_TYPE_DOUBLE)
309 | (MysqlType::LongLong, ffi::enum_field_types::MYSQL_TYPE_INT24)
310 | (MysqlType::LongLong, ffi::enum_field_types::MYSQL_TYPE_NEWDECIMAL)
311 | (MysqlType::LongLong, ffi::enum_field_types::MYSQL_TYPE_LONGLONG)
312 | (MysqlType::UnsignedLongLong, ffi::enum_field_types::MYSQL_TYPE_DECIMAL)
313 | (MysqlType::UnsignedLongLong, ffi::enum_field_types::MYSQL_TYPE_TINY)
314 | (MysqlType::UnsignedLongLong, ffi::enum_field_types::MYSQL_TYPE_SHORT)
315 | (MysqlType::UnsignedLongLong, ffi::enum_field_types::MYSQL_TYPE_LONG)
316 | (MysqlType::UnsignedLongLong, ffi::enum_field_types::MYSQL_TYPE_FLOAT)
317 | (MysqlType::UnsignedLongLong, ffi::enum_field_types::MYSQL_TYPE_DOUBLE)
318 | (MysqlType::UnsignedLongLong, ffi::enum_field_types::MYSQL_TYPE_INT24)
319 | (MysqlType::UnsignedLongLong, ffi::enum_field_types::MYSQL_TYPE_NEWDECIMAL)
320 | (MysqlType::UnsignedLongLong, ffi::enum_field_types::MYSQL_TYPE_LONGLONG)
321 | (MysqlType::Float, ffi::enum_field_types::MYSQL_TYPE_DECIMAL)
322 | (MysqlType::Float, ffi::enum_field_types::MYSQL_TYPE_TINY)
323 | (MysqlType::Float, ffi::enum_field_types::MYSQL_TYPE_SHORT)
324 | (MysqlType::Float, ffi::enum_field_types::MYSQL_TYPE_LONG)
325 | (MysqlType::Float, ffi::enum_field_types::MYSQL_TYPE_FLOAT)
326 | (MysqlType::Float, ffi::enum_field_types::MYSQL_TYPE_DOUBLE)
327 | (MysqlType::Float, ffi::enum_field_types::MYSQL_TYPE_INT24)
328 | (MysqlType::Float, ffi::enum_field_types::MYSQL_TYPE_NEWDECIMAL)
329 | (MysqlType::Float, ffi::enum_field_types::MYSQL_TYPE_LONGLONG)
330 | (MysqlType::Numeric, ffi::enum_field_types::MYSQL_TYPE_DECIMAL)
331 | (MysqlType::Numeric, ffi::enum_field_types::MYSQL_TYPE_TINY)
332 | (MysqlType::Numeric, ffi::enum_field_types::MYSQL_TYPE_SHORT)
333 | (MysqlType::Numeric, ffi::enum_field_types::MYSQL_TYPE_LONG)
334 | (MysqlType::Numeric, ffi::enum_field_types::MYSQL_TYPE_FLOAT)
335 | (MysqlType::Numeric, ffi::enum_field_types::MYSQL_TYPE_DOUBLE)
336 | (MysqlType::Numeric, ffi::enum_field_types::MYSQL_TYPE_INT24)
337 | (MysqlType::Numeric, ffi::enum_field_types::MYSQL_TYPE_NEWDECIMAL)
338 | (MysqlType::Numeric, ffi::enum_field_types::MYSQL_TYPE_LONGLONG)
339 | (MysqlType::String, ffi::enum_field_types::MYSQL_TYPE_JSON)
340 | (MysqlType::String, ffi::enum_field_types::MYSQL_TYPE_ENUM)
341 | (MysqlType::String, ffi::enum_field_types::MYSQL_TYPE_SET)
342 | (MysqlType::String, ffi::enum_field_types::MYSQL_TYPE_TINY_BLOB)
343 | (MysqlType::String, ffi::enum_field_types::MYSQL_TYPE_MEDIUM_BLOB)
344 | (MysqlType::String, ffi::enum_field_types::MYSQL_TYPE_LONG_BLOB)
345 | (MysqlType::String, ffi::enum_field_types::MYSQL_TYPE_BLOB)
346 | (MysqlType::String, ffi::enum_field_types::MYSQL_TYPE_VAR_STRING)
347 | (MysqlType::String, ffi::enum_field_types::MYSQL_TYPE_STRING)
348 | (MysqlType::Blob, ffi::enum_field_types::MYSQL_TYPE_TINY_BLOB)
349 | (MysqlType::Blob, ffi::enum_field_types::MYSQL_TYPE_MEDIUM_BLOB)
350 | (MysqlType::Blob, ffi::enum_field_types::MYSQL_TYPE_LONG_BLOB)
351 | (MysqlType::Blob, ffi::enum_field_types::MYSQL_TYPE_BLOB)
352 | (MysqlType::Set, ffi::enum_field_types::MYSQL_TYPE_ENUM)
353 | (MysqlType::Set, ffi::enum_field_types::MYSQL_TYPE_SET)
354 | (MysqlType::Set, ffi::enum_field_types::MYSQL_TYPE_TINY_BLOB)
355 | (MysqlType::Set, ffi::enum_field_types::MYSQL_TYPE_MEDIUM_BLOB)
356 | (MysqlType::Set, ffi::enum_field_types::MYSQL_TYPE_LONG_BLOB)
357 | (MysqlType::Set, ffi::enum_field_types::MYSQL_TYPE_BLOB)
358 | (MysqlType::Set, ffi::enum_field_types::MYSQL_TYPE_VAR_STRING)
359 | (MysqlType::Set, ffi::enum_field_types::MYSQL_TYPE_STRING)
360 | (MysqlType::Enum, ffi::enum_field_types::MYSQL_TYPE_ENUM)
361 | (MysqlType::Enum, ffi::enum_field_types::MYSQL_TYPE_SET)
362 | (MysqlType::Enum, ffi::enum_field_types::MYSQL_TYPE_TINY_BLOB)
363 | (MysqlType::Enum, ffi::enum_field_types::MYSQL_TYPE_MEDIUM_BLOB)
364 | (MysqlType::Enum, ffi::enum_field_types::MYSQL_TYPE_LONG_BLOB)
365 | (MysqlType::Enum, ffi::enum_field_types::MYSQL_TYPE_BLOB)
366 | (MysqlType::Enum, ffi::enum_field_types::MYSQL_TYPE_VAR_STRING)
367 | (MysqlType::Enum, ffi::enum_field_types::MYSQL_TYPE_STRING) => {
368 (metadata.field_type(), metadata.flags())
369 }
370
371 (tpe, _) => tpe.into(),
372 }
373 } else {
374 (metadata.field_type(), metadata.flags())
375 };
376 Self::from_tpe_and_flags((tpe, flags))
377 }
378
379 fn from_tpe_and_flags((tpe, flags): (ffi::enum_field_types, Flags)) -> Self {
380 let len = known_buffer_size_for_ffi_type(tpe).unwrap_or(1);
382 let (ptr, length, capacity) = bind_buffer(::alloc::vec::from_elem(0, len)vec![0; len]);
386
387 Self {
388 tpe,
389 bytes: ptr,
390 length,
391 capacity,
392 flags,
393 is_null: super::raw::ffi_false(),
394 is_truncated: Some(super::raw::ffi_false()),
395 }
396 }
397
398 fn is_truncated(&self) -> bool {
399 self.is_truncated.unwrap_or(super::raw::ffi_false()) != super::raw::ffi_false()
400 }
401
402 fn is_fixed_size_buffer(&self) -> bool {
403 known_buffer_size_for_ffi_type(self.tpe).is_some()
404 }
405
406 pub(super) fn value(&'_ self) -> Option<MysqlValue<'_>> {
407 if self.is_null() {
408 None
409 } else {
410 let data = self.bytes?;
411 let tpe = (self.tpe, self.flags).into();
412
413 let length = if let Some(length) = known_buffer_size_for_ffi_type(self.tpe) {
430 if true {
if !(length <= self.length.try_into().expect("Usize is at least 32 bit"))
{
{
::core::panicking::panic_fmt(format_args!("Libmysqlclient reported a larger size for a fixed size buffer without setting the truncated flag. \nThis is a bug somewhere. Please open an issue with reproduction steps at https://github.com/diesel-rs/diesel/issues/new \nLength: {2}, Capacity: {0}, Type: {1:?}",
self.capacity, self.tpe, length));
}
};
};debug_assert!(length <= self.length.try_into().expect("Usize is at least 32 bit"),
431 "Libmysqlclient reported a larger size for a fixed size buffer without setting the truncated flag. \n\
432 This is a bug somewhere. Please open an issue with reproduction steps at \
433 https://github.com/diesel-rs/diesel/issues/new \n\
434 Length: {length}, Capacity: {}, Type: {:?}", self.capacity, self.tpe
435 );
436 length
437 } else {
438 self.length.try_into().expect("Usize is at least 32 bit")
439 };
440 if !(length <= self.capacity) {
{
::core::panicking::panic_fmt(format_args!("Got a buffer size larger than the underlying allocation. \nIf you see this message, please open an issue at https://github.com/diesel-rs/diesel/issues/new.\nSuch an issue should contain exact reproduction steps how to trigger this message\nLength: {2}, Capacity: {0}, Type: {1:?}",
self.capacity, self.tpe, length));
}
};assert!(
441 length <= self.capacity,
442 "Got a buffer size larger than the underlying allocation. \n\
443 If you see this message, please open an issue at https://github.com/diesel-rs/diesel/issues/new.\n\
444 Such an issue should contain exact reproduction steps how to trigger this message\n\
445 Length: {length}, Capacity: {}, Type: {:?}", self.capacity, self.tpe
446 );
447
448 let slice = unsafe {
449 std::slice::from_raw_parts(data.as_ptr(), length)
457 };
458 Some(MysqlValue::new_internal(slice, tpe))
459 }
460 }
461
462 pub(super) fn is_null(&self) -> bool {
463 self.is_null != ffi::my_bool::default()
464 }
465
466 fn update_buffer_length(&mut self) {
467 use std::cmp::min;
468
469 let actual_bytes_in_buffer = min(
470 self.capacity,
471 self.length.try_into().expect("Usize is at least 32 bit"),
472 );
473 self.length = actual_bytes_in_buffer as libc::c_ulong;
474 }
475
476 unsafe fn mysql_bind(&mut self) -> ffi::MYSQL_BIND {
480 use std::ptr::addr_of_mut;
481
482 let mut bind: MaybeUninit<ffi::MYSQL_BIND> = mem::MaybeUninit::zeroed();
483 let ptr = bind.as_mut_ptr();
484
485 unsafe {
486 &raw mut (*ptr).buffer_typeaddr_of_mut!((*ptr).buffer_type).write(self.tpe);
487 &raw mut (*ptr).bufferaddr_of_mut!((*ptr).buffer).write(
488 self.bytes
489 .map(|p| p.as_ptr())
490 .unwrap_or(std::ptr::null_mut()) as *mut libc::c_void,
491 );
492 &raw mut (*ptr).buffer_lengthaddr_of_mut!((*ptr).buffer_length).write(self.capacity as libc::c_ulong);
493 &raw mut (*ptr).lengthaddr_of_mut!((*ptr).length).write(&mut self.length);
494 &raw mut (*ptr).is_nulladdr_of_mut!((*ptr).is_null).write(&mut self.is_null);
495 &raw mut (*ptr).is_unsignedaddr_of_mut!((*ptr).is_unsigned)
496 .write(self.flags.contains(Flags::UNSIGNED_FLAG) as ffi::my_bool);
497
498 if let Some(ref mut is_truncated) = self.is_truncated {
499 &raw mut (*ptr).erroraddr_of_mut!((*ptr).error).write(is_truncated);
500 }
501
502 bind.assume_init()
504 }
505 }
506
507 unsafe fn bind_for_truncated_data(&mut self) -> Option<(ffi::MYSQL_BIND, usize)> {
514 if self.is_truncated() {
515 if let Some(bytes) = self.bytes {
516 let mut bytes =
517 unsafe { Vec::from_raw_parts(bytes.as_ptr(), self.capacity, self.capacity) };
518 self.bytes = None;
519
520 let offset = self.capacity;
521 let length = usize::try_from(self.length).expect("Usize is at least 32 bit");
522 let truncated_amount = length - offset;
523
524 if true {
if !(truncated_amount > 0) {
{
::core::panicking::panic_fmt(format_args!("output buffers were invalidated without calling `mysql_stmt_bind_result`"));
}
};
};debug_assert!(
525 truncated_amount > 0,
526 "output buffers were invalidated \
527 without calling `mysql_stmt_bind_result`"
528 );
529
530 bytes.resize(length, 0);
536 let (ptr, _length, capacity) = bind_buffer(bytes);
537 self.capacity = capacity;
538 self.bytes = ptr;
539
540 let mut bind = unsafe { self.mysql_bind() };
541
542 if let Some(ptr) = self.bytes {
543 bind.buffer = unsafe { ptr.as_ptr().add(offset) as *mut libc::c_void };
546 bind.buffer_length = truncated_amount as libc::c_ulong;
547 } else {
548 bind.buffer_length = 0;
549 }
550 Some((bind, offset))
551 } else {
552 let (ptr, _length, capacity) = bind_buffer(::alloc::vec::from_elem(0_u8,
self.length.try_into().expect("usize is at least 32 bit"))vec![
556 0_u8;
557 self.length.try_into().expect(
558 "usize is at least 32 bit"
559 )
560 ]);
561 self.capacity = capacity;
562 self.bytes = ptr;
563
564 let bind = unsafe { self.mysql_bind() };
565 Some((bind, 0))
569 }
570 } else {
571 None
572 }
573 }
574
575 fn did_numeric_overflow_occur(&self) -> QueryResult<()> {
576 use crate::result::Error::DeserializationError;
577
578 if self.is_truncated() && self.is_fixed_size_buffer() {
579 Err(DeserializationError(
580 "Numeric overflow/underflow occurred".into(),
581 ))
582 } else {
583 Ok(())
584 }
585 }
586}
587
588impl From<MysqlType> for (ffi::enum_field_types, Flags) {
589 fn from(tpe: MysqlType) -> Self {
590 use self::ffi::enum_field_types;
591 let mut flags = Flags::empty();
592 let tpe = match tpe {
593 MysqlType::Tiny => enum_field_types::MYSQL_TYPE_TINY,
594 MysqlType::Short => enum_field_types::MYSQL_TYPE_SHORT,
595 MysqlType::Long => enum_field_types::MYSQL_TYPE_LONG,
596 MysqlType::LongLong => enum_field_types::MYSQL_TYPE_LONGLONG,
597 MysqlType::Float => enum_field_types::MYSQL_TYPE_FLOAT,
598 MysqlType::Double => enum_field_types::MYSQL_TYPE_DOUBLE,
599 MysqlType::Time => enum_field_types::MYSQL_TYPE_TIME,
600 MysqlType::Date => enum_field_types::MYSQL_TYPE_DATE,
601 MysqlType::DateTime => enum_field_types::MYSQL_TYPE_DATETIME,
602 MysqlType::Timestamp => enum_field_types::MYSQL_TYPE_TIMESTAMP,
603 MysqlType::String => enum_field_types::MYSQL_TYPE_STRING,
604 MysqlType::Blob => enum_field_types::MYSQL_TYPE_BLOB,
605 MysqlType::Numeric => enum_field_types::MYSQL_TYPE_NEWDECIMAL,
606 MysqlType::Bit => enum_field_types::MYSQL_TYPE_BIT,
607 MysqlType::UnsignedTiny => {
608 flags = Flags::UNSIGNED_FLAG;
609 enum_field_types::MYSQL_TYPE_TINY
610 }
611 MysqlType::UnsignedShort => {
612 flags = Flags::UNSIGNED_FLAG;
613 enum_field_types::MYSQL_TYPE_SHORT
614 }
615 MysqlType::UnsignedLong => {
616 flags = Flags::UNSIGNED_FLAG;
617 enum_field_types::MYSQL_TYPE_LONG
618 }
619 MysqlType::UnsignedLongLong => {
620 flags = Flags::UNSIGNED_FLAG;
621 enum_field_types::MYSQL_TYPE_LONGLONG
622 }
623 MysqlType::Set => {
624 flags = Flags::SET_FLAG;
625 enum_field_types::MYSQL_TYPE_STRING
626 }
627 MysqlType::Enum => {
628 flags = Flags::ENUM_FLAG;
629 enum_field_types::MYSQL_TYPE_STRING
630 }
631 };
632 (tpe, flags)
633 }
634}
635
636impl From<(ffi::enum_field_types, Flags)> for MysqlType {
637 fn from((tpe, flags): (ffi::enum_field_types, Flags)) -> Self {
638 use self::ffi::enum_field_types;
639
640 let is_unsigned = flags.contains(Flags::UNSIGNED_FLAG);
641
642 match tpe {
647 enum_field_types::MYSQL_TYPE_TINY if is_unsigned => MysqlType::UnsignedTiny,
648 enum_field_types::MYSQL_TYPE_YEAR | enum_field_types::MYSQL_TYPE_SHORT
649 if is_unsigned =>
650 {
651 MysqlType::UnsignedShort
652 }
653 enum_field_types::MYSQL_TYPE_INT24 | enum_field_types::MYSQL_TYPE_LONG
654 if is_unsigned =>
655 {
656 MysqlType::UnsignedLong
657 }
658 enum_field_types::MYSQL_TYPE_LONGLONG if is_unsigned => MysqlType::UnsignedLongLong,
659 enum_field_types::MYSQL_TYPE_TINY => MysqlType::Tiny,
660 enum_field_types::MYSQL_TYPE_SHORT => MysqlType::Short,
661 enum_field_types::MYSQL_TYPE_INT24 | enum_field_types::MYSQL_TYPE_LONG => {
662 MysqlType::Long
663 }
664 enum_field_types::MYSQL_TYPE_LONGLONG => MysqlType::LongLong,
665 enum_field_types::MYSQL_TYPE_FLOAT => MysqlType::Float,
666 enum_field_types::MYSQL_TYPE_DOUBLE => MysqlType::Double,
667 enum_field_types::MYSQL_TYPE_DECIMAL | enum_field_types::MYSQL_TYPE_NEWDECIMAL => {
668 MysqlType::Numeric
669 }
670 enum_field_types::MYSQL_TYPE_BIT => MysqlType::Bit,
671
672 enum_field_types::MYSQL_TYPE_TIME => MysqlType::Time,
673 enum_field_types::MYSQL_TYPE_DATE => MysqlType::Date,
674 enum_field_types::MYSQL_TYPE_DATETIME => MysqlType::DateTime,
675 enum_field_types::MYSQL_TYPE_TIMESTAMP => MysqlType::Timestamp,
676 enum_field_types::MYSQL_TYPE_JSON => MysqlType::String,
679
680 enum_field_types::MYSQL_TYPE_BLOB
686 | enum_field_types::MYSQL_TYPE_TINY_BLOB
687 | enum_field_types::MYSQL_TYPE_MEDIUM_BLOB
688 | enum_field_types::MYSQL_TYPE_LONG_BLOB
689 | enum_field_types::MYSQL_TYPE_VAR_STRING
690 | enum_field_types::MYSQL_TYPE_STRING
691 if flags.contains(Flags::ENUM_FLAG) =>
692 {
693 MysqlType::Enum
694 }
695 enum_field_types::MYSQL_TYPE_BLOB
696 | enum_field_types::MYSQL_TYPE_TINY_BLOB
697 | enum_field_types::MYSQL_TYPE_MEDIUM_BLOB
698 | enum_field_types::MYSQL_TYPE_LONG_BLOB
699 | enum_field_types::MYSQL_TYPE_VAR_STRING
700 | enum_field_types::MYSQL_TYPE_STRING
701 if flags.contains(Flags::SET_FLAG) =>
702 {
703 MysqlType::Set
704 }
705
706 enum_field_types::MYSQL_TYPE_BLOB
711 | enum_field_types::MYSQL_TYPE_TINY_BLOB
712 | enum_field_types::MYSQL_TYPE_MEDIUM_BLOB
713 | enum_field_types::MYSQL_TYPE_LONG_BLOB
714 | enum_field_types::MYSQL_TYPE_VAR_STRING
715 | enum_field_types::MYSQL_TYPE_STRING
716 if flags.contains(Flags::BINARY_FLAG) =>
717 {
718 MysqlType::Blob
719 }
720
721 enum_field_types::MYSQL_TYPE_BLOB
723 | enum_field_types::MYSQL_TYPE_TINY_BLOB
724 | enum_field_types::MYSQL_TYPE_MEDIUM_BLOB
725 | enum_field_types::MYSQL_TYPE_LONG_BLOB
726 | enum_field_types::MYSQL_TYPE_VAR_STRING
727 | enum_field_types::MYSQL_TYPE_STRING => MysqlType::String,
728
729 enum_field_types::MYSQL_TYPE_YEAR => {
::core::panicking::panic_fmt(format_args!("internal error: entered unreachable code: {0}",
format_args!("The year type should have set the unsigned flag. If you ever see this error message, something has gone very wrong. Please open an issue at the diesel github repo in this case")));
}unreachable!(
731 "The year type should have set the unsigned flag. If you ever \
732 see this error message, something has gone very wrong. Please \
733 open an issue at the diesel github repo in this case"
734 ),
735 enum_field_types::MYSQL_TYPE_NULL => {
::core::panicking::panic_fmt(format_args!("internal error: entered unreachable code: {0}",
format_args!("We ensure at the call side that we do not hit this type here. If you ever see this error, something has gone very wrong. Please open an issue at the diesel github repo in this case")));
}unreachable!(
737 "We ensure at the call side that we do not hit this type here. \
738 If you ever see this error, something has gone very wrong. \
739 Please open an issue at the diesel github repo in this case"
740 ),
741 enum_field_types::MYSQL_TYPE_VARCHAR
745 | enum_field_types::MYSQL_TYPE_ENUM
746 | enum_field_types::MYSQL_TYPE_SET
747 | enum_field_types::MYSQL_TYPE_GEOMETRY => {
748 {
::core::panicking::panic_fmt(format_args!("not implemented: {0}",
format_args!("Hit a type that should be unsupported in libmysqlclient. If you ever see this error, they probably have added support for one of those types. Please open an issue at the diesel github repo in this case.")));
}unimplemented!(
749 "Hit a type that should be unsupported in libmysqlclient. If \
750 you ever see this error, they probably have added support for \
751 one of those types. Please open an issue at the diesel github \
752 repo in this case."
753 )
754 }
755
756 enum_field_types::MYSQL_TYPE_NEWDATE
757 | enum_field_types::MYSQL_TYPE_TIME2
758 | enum_field_types::MYSQL_TYPE_DATETIME2
759 | enum_field_types::MYSQL_TYPE_TIMESTAMP2 => {
::core::panicking::panic_fmt(format_args!("internal error: entered unreachable code: {0}",
format_args!("The mysql documentation states that these types are only used on the server side, so if you see this error something has gone wrong. Please open an issue at the diesel github repo.")));
}unreachable!(
760 "The mysql documentation states that these types are \
761 only used on the server side, so if you see this error \
762 something has gone wrong. Please open an issue at \
763 the diesel github repo."
764 ),
765 #[allow(unreachable_patterns)]
768 t => {
::core::panicking::panic_fmt(format_args!("internal error: entered unreachable code: {0}",
format_args!("Unsupported type encountered: {0:?}. If you ever see this error, something has gone wrong. Please open an issue at the diesel github repo in this case.",
t)));
}unreachable!(
769 "Unsupported type encountered: {t:?}. \
770 If you ever see this error, something has gone wrong. \
771 Please open an issue at the diesel github \
772 repo in this case."
773 ),
774 }
775 }
776}
777
778fn known_buffer_size_for_ffi_type(tpe: ffi::enum_field_types) -> Option<usize> {
779 use self::ffi::enum_field_types as t;
780 use std::mem::size_of;
781
782 match tpe {
783 t::MYSQL_TYPE_TINY => Some(1),
784 t::MYSQL_TYPE_YEAR | t::MYSQL_TYPE_SHORT => Some(2),
785 t::MYSQL_TYPE_INT24 | t::MYSQL_TYPE_LONG | t::MYSQL_TYPE_FLOAT => Some(4),
786 t::MYSQL_TYPE_LONGLONG | t::MYSQL_TYPE_DOUBLE => Some(8),
787 t::MYSQL_TYPE_TIME
788 | t::MYSQL_TYPE_DATE
789 | t::MYSQL_TYPE_DATETIME
790 | t::MYSQL_TYPE_TIMESTAMP => Some(size_of::<MysqlTime>()),
791 _ => None,
792 }
793}
794
795#[cfg(test)]
796mod tests {
797 use super::*;
798 use crate::connection::statement_cache::{MaybeCached, PrepareForCache};
799 use crate::deserialize::FromSql;
800 use crate::mysql::connection::stmt::Statement;
801 use crate::prelude::*;
802 use crate::sql_types::*;
803 #[cfg(feature = "numeric")]
804 use std::str::FromStr;
805
806 fn to_value<ST, T>(
807 bind: &BindData,
808 ) -> Result<T, Box<dyn std::error::Error + Send + Sync + 'static>>
809 where
810 T: FromSql<ST, crate::mysql::Mysql> + std::fmt::Debug,
811 {
812 let meta = (bind.tpe, bind.flags).into();
813 dbg!(meta);
814
815 let value = bind.value().expect("Is not null");
816 let value = MysqlValue::new_internal(value.as_bytes(), meta);
817
818 dbg!(T::from_sql(value))
819 }
820
821 #[cfg(feature = "extras")]
822 #[diesel_test_helper::test]
823 fn check_all_the_types() {
824 let conn = &mut crate::test_helpers::connection();
825
826 crate::sql_query("DROP TABLE IF EXISTS all_mysql_types CASCADE")
827 .execute(conn)
828 .unwrap();
829 crate::sql_query(
830 "CREATE TABLE all_mysql_types (
831 tiny_int TINYINT NOT NULL,
832 small_int SMALLINT NOT NULL,
833 medium_int MEDIUMINT NOT NULL,
834 int_col INTEGER NOT NULL,
835 big_int BIGINT NOT NULL,
836 unsigned_int INTEGER UNSIGNED NOT NULL,
837 zero_fill_int INTEGER ZEROFILL NOT NULL,
838 numeric_col NUMERIC(20,5) NOT NULL,
839 decimal_col DECIMAL(20,5) NOT NULL,
840 float_col FLOAT NOT NULL,
841 double_col DOUBLE NOT NULL,
842 bit_col BIT(8) NOT NULL,
843 date_col DATE NOT NULL,
844 date_time DATETIME NOT NULL,
845 timestamp_col TIMESTAMP NOT NULL,
846 time_col TIME NOT NULL,
847 year_col YEAR NOT NULL,
848 char_col CHAR(30) NOT NULL,
849 varchar_col VARCHAR(30) NOT NULL,
850 binary_col BINARY(30) NOT NULL,
851 varbinary_col VARBINARY(30) NOT NULL,
852 blob_col BLOB NOT NULL,
853 text_col TEXT NOT NULL,
854 enum_col ENUM('red', 'green', 'blue') NOT NULL,
855 set_col SET('one', 'two') NOT NULL,
856 geom GEOMETRY NOT NULL,
857 point_col POINT NOT NULL,
858 linestring_col LINESTRING NOT NULL,
859 polygon_col POLYGON NOT NULL,
860 multipoint_col MULTIPOINT NOT NULL,
861 multilinestring_col MULTILINESTRING NOT NULL,
862 multipolygon_col MULTIPOLYGON NOT NULL,
863 geometry_collection GEOMETRYCOLLECTION NOT NULL,
864 json_col JSON NOT NULL
865 )",
866 )
867 .execute(conn)
868 .unwrap();
869 crate::sql_query(
870 "INSERT INTO all_mysql_types VALUES (
871 0, -- tiny_int
872 1, -- small_int
873 2, -- medium_int
874 3, -- int_col
875 -5, -- big_int
876 42, -- unsigned_int
877 1, -- zero_fill_int
878 -999.999, -- numeric_col,
879 3.14, -- decimal_col,
880 1.23, -- float_col
881 4.5678, -- double_col
882 b'10101010', -- bit_col
883 '1000-01-01', -- date_col
884 '9999-12-31 12:34:45.012345', -- date_time
885 '2020-01-01 10:10:10', -- timestamp_col
886 '23:01:01', -- time_col
887 2020, -- year_col
888 'abc', -- char_col
889 'foo', -- varchar_col
890 'a ', -- binary_col
891 'a ', -- varbinary_col
892 'binary', -- blob_col
893 'some text whatever', -- text_col
894 'red', -- enum_col
895 'one', -- set_col
896 ST_GeomFromText('POINT(1 1)'), -- geom
897 ST_PointFromText('POINT(1 1)'), -- point_col
898 ST_LineStringFromText('LINESTRING(0 0,1 1,2 2)'), -- linestring_col
899 ST_PolygonFromText('POLYGON((0 0,10 0,10 10,0 10,0 0),(5 5,7 5,7 7,5 7, 5 5))'), -- polygon_col
900 ST_MultiPointFromText('MULTIPOINT(0 0,10 10,10 20,20 20)'), -- multipoint_col
901 ST_MultiLineStringFromText('MULTILINESTRING((10 48,10 21,10 0),(16 0,16 23,16 48))'), -- multilinestring_col
902 ST_MultiPolygonFromText('MULTIPOLYGON(((28 26,28 0,84 0,84 42,28 26),(52 18,66 23,73 9,48 6,52 18)),((59 18,67 18,67 13,59 13,59 18)))'), -- multipolygon_col
903 ST_GeomCollFromText('GEOMETRYCOLLECTION(POINT(1 1),LINESTRING(0 0,1 1,2 2,3 3,4 4))'), -- geometry_collection
904 '{\"key1\": \"value1\", \"key2\": \"value2\"}' -- json_col
905)",
906 ).execute(conn)
907 .unwrap();
908
909 let stmt = crate::mysql::connection::prepared_query(
910 &crate::sql_query(
911 "SELECT
912 tiny_int, small_int, medium_int, int_col,
913 big_int, unsigned_int, zero_fill_int,
914 numeric_col, decimal_col, float_col, double_col, bit_col,
915 date_col, date_time, timestamp_col, time_col, year_col,
916 char_col, varchar_col, binary_col, varbinary_col, blob_col,
917 text_col, enum_col, set_col, ST_AsText(geom), ST_AsText(point_col), ST_AsText(linestring_col),
918 ST_AsText(polygon_col), ST_AsText(multipoint_col), ST_AsText(multilinestring_col),
919 ST_AsText(multipolygon_col), ST_AsText(geometry_collection), json_col
920 FROM all_mysql_types",
921 ),
922 &mut conn.statement_cache,
923 &mut conn.raw_connection,
924 &mut *conn.instrumentation,
925 ).unwrap();
926
927 let metadata = stmt.metadata().unwrap();
928 let mut output_binds =
929 OutputBinds::from_output_types(&vec![None; metadata.fields().len()], &metadata);
930 let stmt = stmt.execute_statement(&mut output_binds).unwrap();
931 stmt.populate_row_buffers(&mut output_binds).unwrap();
932
933 let results: Vec<(BindData, &_)> = output_binds
934 .0
935 .data
936 .into_iter()
937 .zip(metadata.fields())
938 .collect::<Vec<_>>();
939
940 let tiny_int_col = &results[0].0;
941 assert_eq!(tiny_int_col.tpe, ffi::enum_field_types::MYSQL_TYPE_TINY);
942 assert!(tiny_int_col.flags.contains(Flags::NUM_FLAG));
943 assert!(!tiny_int_col.flags.contains(Flags::UNSIGNED_FLAG));
944 assert!(matches!(to_value::<TinyInt, i8>(tiny_int_col), Ok(0)));
945
946 let small_int_col = &results[1].0;
947 assert_eq!(small_int_col.tpe, ffi::enum_field_types::MYSQL_TYPE_SHORT);
948 assert!(small_int_col.flags.contains(Flags::NUM_FLAG));
949 assert!(!small_int_col.flags.contains(Flags::UNSIGNED_FLAG));
950 assert!(matches!(to_value::<SmallInt, i16>(small_int_col), Ok(1)));
951
952 let medium_int_col = &results[2].0;
953 assert_eq!(medium_int_col.tpe, ffi::enum_field_types::MYSQL_TYPE_INT24);
954 assert!(medium_int_col.flags.contains(Flags::NUM_FLAG));
955 assert!(!medium_int_col.flags.contains(Flags::UNSIGNED_FLAG));
956 assert!(matches!(to_value::<Integer, i32>(medium_int_col), Ok(2)));
957
958 let int_col = &results[3].0;
959 assert_eq!(int_col.tpe, ffi::enum_field_types::MYSQL_TYPE_LONG);
960 assert!(int_col.flags.contains(Flags::NUM_FLAG));
961 assert!(!int_col.flags.contains(Flags::UNSIGNED_FLAG));
962 assert!(matches!(to_value::<Integer, i32>(int_col), Ok(3)));
963
964 let big_int_col = &results[4].0;
965 assert_eq!(big_int_col.tpe, ffi::enum_field_types::MYSQL_TYPE_LONGLONG);
966 assert!(big_int_col.flags.contains(Flags::NUM_FLAG));
967 assert!(!big_int_col.flags.contains(Flags::UNSIGNED_FLAG));
968 assert!(matches!(to_value::<TinyInt, i8>(big_int_col), Ok(-5)));
969
970 let unsigned_int_col = &results[5].0;
971 assert_eq!(unsigned_int_col.tpe, ffi::enum_field_types::MYSQL_TYPE_LONG);
972 assert!(unsigned_int_col.flags.contains(Flags::NUM_FLAG));
973 assert!(unsigned_int_col.flags.contains(Flags::UNSIGNED_FLAG));
974 assert!(matches!(
975 to_value::<Unsigned<Integer>, u32>(unsigned_int_col),
976 Ok(42)
977 ));
978
979 let zero_fill_int_col = &results[6].0;
980 assert_eq!(
981 zero_fill_int_col.tpe,
982 ffi::enum_field_types::MYSQL_TYPE_LONG
983 );
984 assert!(zero_fill_int_col.flags.contains(Flags::NUM_FLAG));
985 assert!(zero_fill_int_col.flags.contains(Flags::ZEROFILL_FLAG));
986 assert!(matches!(to_value::<Integer, i32>(zero_fill_int_col), Ok(1)));
987
988 let numeric_col = &results[7].0;
989 assert_eq!(
990 numeric_col.tpe,
991 ffi::enum_field_types::MYSQL_TYPE_NEWDECIMAL
992 );
993 assert!(numeric_col.flags.contains(Flags::NUM_FLAG));
994 assert!(!numeric_col.flags.contains(Flags::UNSIGNED_FLAG));
995 assert_eq!(
996 to_value::<Numeric, bigdecimal::BigDecimal>(numeric_col).unwrap(),
997 bigdecimal::BigDecimal::from_str("-999.99900").unwrap()
998 );
999
1000 let decimal_col = &results[8].0;
1001 assert_eq!(
1002 decimal_col.tpe,
1003 ffi::enum_field_types::MYSQL_TYPE_NEWDECIMAL
1004 );
1005 assert!(decimal_col.flags.contains(Flags::NUM_FLAG));
1006 assert!(!decimal_col.flags.contains(Flags::UNSIGNED_FLAG));
1007 assert_eq!(
1008 to_value::<Numeric, bigdecimal::BigDecimal>(decimal_col).unwrap(),
1009 bigdecimal::BigDecimal::from_str("3.14000").unwrap()
1010 );
1011
1012 let float_col = &results[9].0;
1013 assert_eq!(float_col.tpe, ffi::enum_field_types::MYSQL_TYPE_FLOAT);
1014 assert!(float_col.flags.contains(Flags::NUM_FLAG));
1015 assert!(!float_col.flags.contains(Flags::UNSIGNED_FLAG));
1016 assert_eq!(to_value::<Float, f32>(float_col).unwrap(), 1.23);
1017
1018 let double_col = &results[10].0;
1019 assert_eq!(double_col.tpe, ffi::enum_field_types::MYSQL_TYPE_DOUBLE);
1020 assert!(double_col.flags.contains(Flags::NUM_FLAG));
1021 assert!(!double_col.flags.contains(Flags::UNSIGNED_FLAG));
1022 assert_eq!(to_value::<Double, f64>(double_col).unwrap(), 4.5678);
1023
1024 let bit_col = &results[11].0;
1025 assert_eq!(bit_col.tpe, ffi::enum_field_types::MYSQL_TYPE_BIT);
1026 assert!(!bit_col.flags.contains(Flags::NUM_FLAG));
1027 assert!(bit_col.flags.contains(Flags::UNSIGNED_FLAG));
1028 assert!(!bit_col.flags.contains(Flags::BINARY_FLAG));
1029 assert_eq!(to_value::<Blob, Vec<u8>>(bit_col).unwrap(), vec![170]);
1030
1031 let date_col = &results[12].0;
1032 assert_eq!(date_col.tpe, ffi::enum_field_types::MYSQL_TYPE_DATE);
1033 assert!(!date_col.flags.contains(Flags::NUM_FLAG));
1034 assert_eq!(
1035 to_value::<Date, chrono::NaiveDate>(date_col).unwrap(),
1036 chrono::NaiveDate::from_ymd_opt(1000, 1, 1).unwrap(),
1037 );
1038
1039 let date_time_col = &results[13].0;
1040 assert_eq!(
1041 date_time_col.tpe,
1042 ffi::enum_field_types::MYSQL_TYPE_DATETIME
1043 );
1044 assert!(!date_time_col.flags.contains(Flags::NUM_FLAG));
1045 assert_eq!(
1046 to_value::<Datetime, chrono::NaiveDateTime>(date_time_col).unwrap(),
1047 chrono::NaiveDateTime::parse_from_str("9999-12-31 12:34:45", "%Y-%m-%d %H:%M:%S")
1048 .unwrap()
1049 );
1050
1051 let timestamp_col = &results[14].0;
1052 assert_eq!(
1053 timestamp_col.tpe,
1054 ffi::enum_field_types::MYSQL_TYPE_TIMESTAMP
1055 );
1056 assert!(!timestamp_col.flags.contains(Flags::NUM_FLAG));
1057 assert_eq!(
1058 to_value::<Datetime, chrono::NaiveDateTime>(timestamp_col).unwrap(),
1059 chrono::NaiveDateTime::parse_from_str("2020-01-01 10:10:10", "%Y-%m-%d %H:%M:%S")
1060 .unwrap()
1061 );
1062
1063 let time_col = &results[15].0;
1064 assert_eq!(time_col.tpe, ffi::enum_field_types::MYSQL_TYPE_TIME);
1065 assert!(!time_col.flags.contains(Flags::NUM_FLAG));
1066 assert_eq!(
1067 to_value::<Time, chrono::NaiveTime>(time_col).unwrap(),
1068 chrono::NaiveTime::from_hms_opt(23, 1, 1).unwrap()
1069 );
1070
1071 let year_col = &results[16].0;
1072 assert_eq!(year_col.tpe, ffi::enum_field_types::MYSQL_TYPE_YEAR);
1073 assert!(year_col.flags.contains(Flags::NUM_FLAG));
1074 assert!(year_col.flags.contains(Flags::UNSIGNED_FLAG));
1075 assert!(matches!(to_value::<SmallInt, i16>(year_col), Ok(2020)));
1076
1077 let char_col = &results[17].0;
1078 assert_eq!(char_col.tpe, ffi::enum_field_types::MYSQL_TYPE_STRING);
1079 assert!(!char_col.flags.contains(Flags::NUM_FLAG));
1080 assert!(!char_col.flags.contains(Flags::BLOB_FLAG));
1081 assert!(!char_col.flags.contains(Flags::SET_FLAG));
1082 assert!(!char_col.flags.contains(Flags::ENUM_FLAG));
1083 assert!(!char_col.flags.contains(Flags::BINARY_FLAG));
1084 assert_eq!(to_value::<Text, String>(char_col).unwrap(), "abc");
1085
1086 let varchar_col = &results[18].0;
1087 assert_eq!(
1088 varchar_col.tpe,
1089 ffi::enum_field_types::MYSQL_TYPE_VAR_STRING
1090 );
1091 assert!(!varchar_col.flags.contains(Flags::NUM_FLAG));
1092 assert!(!varchar_col.flags.contains(Flags::BLOB_FLAG));
1093 assert!(!varchar_col.flags.contains(Flags::SET_FLAG));
1094 assert!(!varchar_col.flags.contains(Flags::ENUM_FLAG));
1095 assert!(!varchar_col.flags.contains(Flags::BINARY_FLAG));
1096 assert_eq!(to_value::<Text, String>(varchar_col).unwrap(), "foo");
1097
1098 let binary_col = &results[19].0;
1099 assert_eq!(binary_col.tpe, ffi::enum_field_types::MYSQL_TYPE_STRING);
1100 assert!(!binary_col.flags.contains(Flags::NUM_FLAG));
1101 assert!(!binary_col.flags.contains(Flags::BLOB_FLAG));
1102 assert!(!binary_col.flags.contains(Flags::SET_FLAG));
1103 assert!(!binary_col.flags.contains(Flags::ENUM_FLAG));
1104 assert!(binary_col.flags.contains(Flags::BINARY_FLAG));
1105 assert_eq!(
1106 to_value::<Blob, Vec<u8>>(binary_col).unwrap(),
1107 b"a \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
1108 );
1109
1110 let varbinary_col = &results[20].0;
1111 assert_eq!(
1112 varbinary_col.tpe,
1113 ffi::enum_field_types::MYSQL_TYPE_VAR_STRING
1114 );
1115 assert!(!varbinary_col.flags.contains(Flags::NUM_FLAG));
1116 assert!(!varbinary_col.flags.contains(Flags::BLOB_FLAG));
1117 assert!(!varbinary_col.flags.contains(Flags::SET_FLAG));
1118 assert!(!varbinary_col.flags.contains(Flags::ENUM_FLAG));
1119 assert!(varbinary_col.flags.contains(Flags::BINARY_FLAG));
1120 assert_eq!(to_value::<Blob, Vec<u8>>(varbinary_col).unwrap(), b"a ");
1121
1122 let blob_col = &results[21].0;
1123 assert_eq!(blob_col.tpe, ffi::enum_field_types::MYSQL_TYPE_BLOB);
1124 assert!(!blob_col.flags.contains(Flags::NUM_FLAG));
1125 assert!(blob_col.flags.contains(Flags::BLOB_FLAG));
1126 assert!(!blob_col.flags.contains(Flags::SET_FLAG));
1127 assert!(!blob_col.flags.contains(Flags::ENUM_FLAG));
1128 assert!(blob_col.flags.contains(Flags::BINARY_FLAG));
1129 assert_eq!(to_value::<Blob, Vec<u8>>(blob_col).unwrap(), b"binary");
1130
1131 let text_col = &results[22].0;
1132 assert_eq!(text_col.tpe, ffi::enum_field_types::MYSQL_TYPE_BLOB);
1133 assert!(!text_col.flags.contains(Flags::NUM_FLAG));
1134 assert!(text_col.flags.contains(Flags::BLOB_FLAG));
1135 assert!(!text_col.flags.contains(Flags::SET_FLAG));
1136 assert!(!text_col.flags.contains(Flags::ENUM_FLAG));
1137 assert!(!text_col.flags.contains(Flags::BINARY_FLAG));
1138 assert_eq!(
1139 to_value::<Text, String>(text_col).unwrap(),
1140 "some text whatever"
1141 );
1142
1143 let enum_col = &results[23].0;
1144 assert_eq!(enum_col.tpe, ffi::enum_field_types::MYSQL_TYPE_STRING);
1145 assert!(!enum_col.flags.contains(Flags::NUM_FLAG));
1146 assert!(!enum_col.flags.contains(Flags::BLOB_FLAG));
1147 assert!(!enum_col.flags.contains(Flags::SET_FLAG));
1148 assert!(enum_col.flags.contains(Flags::ENUM_FLAG));
1149 assert!(!enum_col.flags.contains(Flags::BINARY_FLAG));
1150 assert_eq!(to_value::<Text, String>(enum_col).unwrap(), "red");
1151
1152 let set_col = &results[24].0;
1153 assert_eq!(set_col.tpe, ffi::enum_field_types::MYSQL_TYPE_STRING);
1154 assert!(!set_col.flags.contains(Flags::NUM_FLAG));
1155 assert!(!set_col.flags.contains(Flags::BLOB_FLAG));
1156 assert!(set_col.flags.contains(Flags::SET_FLAG));
1157 assert!(!set_col.flags.contains(Flags::ENUM_FLAG));
1158 assert!(!set_col.flags.contains(Flags::BINARY_FLAG));
1159 assert_eq!(to_value::<Text, String>(set_col).unwrap(), "one");
1160
1161 let geom = &results[25].0;
1162 assert_eq!(geom.tpe, ffi::enum_field_types::MYSQL_TYPE_LONG_BLOB);
1163 assert!(!geom.flags.contains(Flags::NUM_FLAG));
1164 assert!(!geom.flags.contains(Flags::BLOB_FLAG));
1165 assert!(!geom.flags.contains(Flags::SET_FLAG));
1166 assert!(!geom.flags.contains(Flags::ENUM_FLAG));
1167 assert!(!geom.flags.contains(Flags::BINARY_FLAG));
1168 assert_eq!(to_value::<Text, String>(geom).unwrap(), "POINT(1 1)");
1169
1170 let point_col = &results[26].0;
1171 assert_eq!(point_col.tpe, ffi::enum_field_types::MYSQL_TYPE_LONG_BLOB);
1172 assert!(!point_col.flags.contains(Flags::NUM_FLAG));
1173 assert!(!point_col.flags.contains(Flags::BLOB_FLAG));
1174 assert!(!point_col.flags.contains(Flags::SET_FLAG));
1175 assert!(!point_col.flags.contains(Flags::ENUM_FLAG));
1176 assert!(!point_col.flags.contains(Flags::BINARY_FLAG));
1177 assert_eq!(to_value::<Text, String>(point_col).unwrap(), "POINT(1 1)");
1178
1179 let linestring_col = &results[27].0;
1180 assert_eq!(
1181 linestring_col.tpe,
1182 ffi::enum_field_types::MYSQL_TYPE_LONG_BLOB
1183 );
1184 assert!(!linestring_col.flags.contains(Flags::NUM_FLAG));
1185 assert!(!linestring_col.flags.contains(Flags::BLOB_FLAG));
1186 assert!(!linestring_col.flags.contains(Flags::SET_FLAG));
1187 assert!(!linestring_col.flags.contains(Flags::ENUM_FLAG));
1188 assert!(!linestring_col.flags.contains(Flags::BINARY_FLAG));
1189 assert_eq!(
1190 to_value::<Text, String>(linestring_col).unwrap(),
1191 "LINESTRING(0 0,1 1,2 2)"
1192 );
1193
1194 let polygon_col = &results[28].0;
1195 assert_eq!(polygon_col.tpe, ffi::enum_field_types::MYSQL_TYPE_LONG_BLOB);
1196 assert!(!polygon_col.flags.contains(Flags::NUM_FLAG));
1197 assert!(!polygon_col.flags.contains(Flags::BLOB_FLAG));
1198 assert!(!polygon_col.flags.contains(Flags::SET_FLAG));
1199 assert!(!polygon_col.flags.contains(Flags::ENUM_FLAG));
1200 assert!(!polygon_col.flags.contains(Flags::BINARY_FLAG));
1201 assert_eq!(
1202 to_value::<Text, String>(polygon_col).unwrap(),
1203 "POLYGON((0 0,10 0,10 10,0 10,0 0),(5 5,7 5,7 7,5 7,5 5))"
1204 );
1205
1206 let multipoint_col = &results[29].0;
1207 assert_eq!(
1208 multipoint_col.tpe,
1209 ffi::enum_field_types::MYSQL_TYPE_LONG_BLOB
1210 );
1211 assert!(!multipoint_col.flags.contains(Flags::NUM_FLAG));
1212 assert!(!multipoint_col.flags.contains(Flags::BLOB_FLAG));
1213 assert!(!multipoint_col.flags.contains(Flags::SET_FLAG));
1214 assert!(!multipoint_col.flags.contains(Flags::ENUM_FLAG));
1215 assert!(!multipoint_col.flags.contains(Flags::BINARY_FLAG));
1216 let multipoint_res = to_value::<Text, String>(multipoint_col).unwrap();
1220 assert!(
1221 multipoint_res == "MULTIPOINT((0 0),(10 10),(10 20),(20 20))"
1222 || multipoint_res == "MULTIPOINT(0 0,10 10,10 20,20 20)"
1223 );
1224
1225 let multilinestring_col = &results[30].0;
1226 assert_eq!(
1227 multilinestring_col.tpe,
1228 ffi::enum_field_types::MYSQL_TYPE_LONG_BLOB
1229 );
1230 assert!(!multilinestring_col.flags.contains(Flags::NUM_FLAG));
1231 assert!(!multilinestring_col.flags.contains(Flags::BLOB_FLAG));
1232 assert!(!multilinestring_col.flags.contains(Flags::SET_FLAG));
1233 assert!(!multilinestring_col.flags.contains(Flags::ENUM_FLAG));
1234 assert!(!multilinestring_col.flags.contains(Flags::BINARY_FLAG));
1235 assert_eq!(
1236 to_value::<Text, String>(multilinestring_col).unwrap(),
1237 "MULTILINESTRING((10 48,10 21,10 0),(16 0,16 23,16 48))"
1238 );
1239
1240 let polygon_col = &results[31].0;
1241 assert_eq!(polygon_col.tpe, ffi::enum_field_types::MYSQL_TYPE_LONG_BLOB);
1242 assert!(!polygon_col.flags.contains(Flags::NUM_FLAG));
1243 assert!(!polygon_col.flags.contains(Flags::BLOB_FLAG));
1244 assert!(!polygon_col.flags.contains(Flags::SET_FLAG));
1245 assert!(!polygon_col.flags.contains(Flags::ENUM_FLAG));
1246 assert!(!polygon_col.flags.contains(Flags::BINARY_FLAG));
1247 assert_eq!(
1248 to_value::<Text, String>(polygon_col).unwrap(),
1249 "MULTIPOLYGON(((28 26,28 0,84 0,84 42,28 26),(52 18,66 23,73 9,48 6,52 18)),((59 18,67 18,67 13,59 13,59 18)))"
1250 );
1251
1252 let geometry_collection = &results[32].0;
1253 assert_eq!(
1254 geometry_collection.tpe,
1255 ffi::enum_field_types::MYSQL_TYPE_LONG_BLOB
1256 );
1257 assert!(!geometry_collection.flags.contains(Flags::NUM_FLAG));
1258 assert!(!geometry_collection.flags.contains(Flags::BLOB_FLAG));
1259 assert!(!geometry_collection.flags.contains(Flags::SET_FLAG));
1260 assert!(!geometry_collection.flags.contains(Flags::ENUM_FLAG));
1261 assert!(!geometry_collection.flags.contains(Flags::BINARY_FLAG));
1262 assert_eq!(
1263 to_value::<Text, String>(geometry_collection).unwrap(),
1264 "GEOMETRYCOLLECTION(POINT(1 1),LINESTRING(0 0,1 1,2 2,3 3,4 4))"
1265 );
1266
1267 let json_col = &results[33].0;
1268 assert!(
1273 json_col.tpe == ffi::enum_field_types::MYSQL_TYPE_JSON
1274 || json_col.tpe == ffi::enum_field_types::MYSQL_TYPE_BLOB
1275 );
1276 assert!(!json_col.flags.contains(Flags::NUM_FLAG));
1277 assert!(json_col.flags.contains(Flags::BLOB_FLAG));
1278 assert!(!json_col.flags.contains(Flags::SET_FLAG));
1279 assert!(!json_col.flags.contains(Flags::ENUM_FLAG));
1280 assert!(json_col.flags.contains(Flags::BINARY_FLAG));
1281 assert_eq!(
1282 to_value::<Text, String>(json_col).unwrap(),
1283 "{\"key1\": \"value1\", \"key2\": \"value2\"}"
1284 );
1285 }
1286
1287 fn query_single_table(
1288 query: &'static str,
1289 conn: &MysqlConnection,
1290 bind_tpe: impl Into<(ffi::enum_field_types, Flags)>,
1291 ) -> BindData {
1292 let stmt: Statement = conn
1293 .raw_connection
1294 .prepare(query, PrepareForCache::No, &[])
1295 .unwrap();
1296 let stmt = MaybeCached::CannotCache(stmt);
1297
1298 let bind = BindData::from_tpe_and_flags(bind_tpe.into());
1299
1300 let mut binds = OutputBinds(Binds { data: vec![bind] });
1301
1302 let stmt = stmt.execute_statement(&mut binds).unwrap();
1303 stmt.populate_row_buffers(&mut binds).unwrap();
1304
1305 binds.0.data.remove(0)
1306 }
1307
1308 fn input_bind(
1309 query: &'static str,
1310 conn: &MysqlConnection,
1311 id: i32,
1312 (field, tpe): (Vec<u8>, impl Into<(ffi::enum_field_types, Flags)>),
1313 ) {
1314 let mut stmt = conn
1315 .raw_connection
1316 .prepare(query, PrepareForCache::No, &[])
1317 .unwrap();
1318 let length = field.len() as _;
1319 let (tpe, flags) = tpe.into();
1320 let (ptr, _length, capacity) = bind_buffer(field);
1321
1322 let field_bind = BindData {
1323 tpe,
1324 bytes: ptr,
1325 capacity,
1326 length,
1327 flags,
1328 is_null: ffi::FALSE,
1329 is_truncated: None,
1330 };
1331
1332 let (ptr, length, capacity) = bind_buffer(id.to_be_bytes().to_vec());
1333
1334 let id_bind = BindData {
1335 tpe: ffi::enum_field_types::MYSQL_TYPE_LONG,
1336 bytes: ptr,
1337 capacity,
1338 length,
1339 flags: Flags::empty(),
1340 is_null: ffi::FALSE,
1341 is_truncated: None,
1342 };
1343
1344 let binds = PreparedStatementBinds(Binds {
1345 data: vec![id_bind, field_bind],
1346 });
1347 stmt.input_bind(binds).unwrap();
1348 stmt.did_an_error_occur().unwrap();
1349 let stmt = MaybeCached::CannotCache(stmt);
1350 unsafe {
1351 stmt.execute().unwrap();
1352 }
1353 }
1354
1355 #[diesel_test_helper::test]
1356 fn check_json_bind() {
1357 table! {
1358 json_test {
1359 id -> Integer,
1360 json_field -> Text,
1361 }
1362 }
1363
1364 let conn = &mut crate::test_helpers::connection();
1365
1366 crate::sql_query("DROP TABLE IF EXISTS json_test CASCADE")
1367 .execute(conn)
1368 .unwrap();
1369
1370 crate::sql_query(
1371 "CREATE TABLE json_test(id INTEGER PRIMARY KEY, json_field JSON NOT NULL)",
1372 )
1373 .execute(conn)
1374 .unwrap();
1375
1376 crate::sql_query("INSERT INTO json_test(id, json_field) VALUES (1, '{\"key1\": \"value1\", \"key2\": \"value2\"}')").execute(conn).unwrap();
1377
1378 let json_col_as_json = query_single_table(
1379 "SELECT json_field FROM json_test",
1380 conn,
1381 (ffi::enum_field_types::MYSQL_TYPE_JSON, Flags::empty()),
1382 );
1383
1384 assert_eq!(json_col_as_json.tpe, ffi::enum_field_types::MYSQL_TYPE_JSON);
1385 assert!(!json_col_as_json.flags.contains(Flags::NUM_FLAG));
1386 assert!(!json_col_as_json.flags.contains(Flags::BLOB_FLAG));
1387 assert!(!json_col_as_json.flags.contains(Flags::SET_FLAG));
1388 assert!(!json_col_as_json.flags.contains(Flags::ENUM_FLAG));
1389 assert!(!json_col_as_json.flags.contains(Flags::BINARY_FLAG));
1390 assert_eq!(
1391 to_value::<Text, String>(&json_col_as_json).unwrap(),
1392 "{\"key1\": \"value1\", \"key2\": \"value2\"}"
1393 );
1394
1395 let json_col_as_text = query_single_table(
1396 "SELECT json_field FROM json_test",
1397 conn,
1398 (ffi::enum_field_types::MYSQL_TYPE_BLOB, Flags::empty()),
1399 );
1400
1401 assert_eq!(json_col_as_text.tpe, ffi::enum_field_types::MYSQL_TYPE_BLOB);
1402 assert!(!json_col_as_text.flags.contains(Flags::NUM_FLAG));
1403 assert!(!json_col_as_text.flags.contains(Flags::BLOB_FLAG));
1404 assert!(!json_col_as_text.flags.contains(Flags::SET_FLAG));
1405 assert!(!json_col_as_text.flags.contains(Flags::ENUM_FLAG));
1406 assert!(!json_col_as_text.flags.contains(Flags::BINARY_FLAG));
1407 assert_eq!(
1408 to_value::<Text, String>(&json_col_as_text).unwrap(),
1409 "{\"key1\": \"value1\", \"key2\": \"value2\"}"
1410 );
1411 assert_eq!(
1412 json_col_as_json.value().unwrap().as_bytes(),
1413 json_col_as_text.value().unwrap().as_bytes()
1414 );
1415
1416 crate::sql_query("DELETE FROM json_test")
1417 .execute(conn)
1418 .unwrap();
1419
1420 input_bind(
1421 "INSERT INTO json_test(id, json_field) VALUES (?, ?)",
1422 conn,
1423 41,
1424 (
1425 b"{\"abc\": 42}".to_vec(),
1426 MysqlType::String,
1427 ),
1429 );
1430
1431 let json_col_as_json = query_single_table(
1432 "SELECT json_field FROM json_test",
1433 conn,
1434 (ffi::enum_field_types::MYSQL_TYPE_JSON, Flags::empty()),
1435 );
1436
1437 assert_eq!(json_col_as_json.tpe, ffi::enum_field_types::MYSQL_TYPE_JSON);
1438 assert!(!json_col_as_json.flags.contains(Flags::NUM_FLAG));
1439 assert!(!json_col_as_json.flags.contains(Flags::BLOB_FLAG));
1440 assert!(!json_col_as_json.flags.contains(Flags::SET_FLAG));
1441 assert!(!json_col_as_json.flags.contains(Flags::ENUM_FLAG));
1442 assert!(!json_col_as_json.flags.contains(Flags::BINARY_FLAG));
1443 assert_eq!(
1444 to_value::<Text, String>(&json_col_as_json).unwrap(),
1445 "{\"abc\": 42}"
1446 );
1447
1448 let json_col_as_text = query_single_table(
1449 "SELECT json_field FROM json_test",
1450 conn,
1451 (ffi::enum_field_types::MYSQL_TYPE_BLOB, Flags::empty()),
1452 );
1453
1454 assert_eq!(json_col_as_text.tpe, ffi::enum_field_types::MYSQL_TYPE_BLOB);
1455 assert!(!json_col_as_text.flags.contains(Flags::NUM_FLAG));
1456 assert!(!json_col_as_text.flags.contains(Flags::BLOB_FLAG));
1457 assert!(!json_col_as_text.flags.contains(Flags::SET_FLAG));
1458 assert!(!json_col_as_text.flags.contains(Flags::ENUM_FLAG));
1459 assert!(!json_col_as_text.flags.contains(Flags::BINARY_FLAG));
1460 assert_eq!(
1461 to_value::<Text, String>(&json_col_as_text).unwrap(),
1462 "{\"abc\": 42}"
1463 );
1464 assert_eq!(
1465 json_col_as_json.value().unwrap().as_bytes(),
1466 json_col_as_text.value().unwrap().as_bytes()
1467 );
1468
1469 crate::sql_query("DELETE FROM json_test")
1470 .execute(conn)
1471 .unwrap();
1472
1473 input_bind(
1474 "INSERT INTO json_test(id, json_field) VALUES (?, ?)",
1475 conn,
1476 41,
1477 (b"{\"abca\": 42}".to_vec(), MysqlType::String),
1478 );
1479
1480 let json_col_as_json = query_single_table(
1481 "SELECT json_field FROM json_test",
1482 conn,
1483 (ffi::enum_field_types::MYSQL_TYPE_JSON, Flags::empty()),
1484 );
1485
1486 assert_eq!(json_col_as_json.tpe, ffi::enum_field_types::MYSQL_TYPE_JSON);
1487 assert!(!json_col_as_json.flags.contains(Flags::NUM_FLAG));
1488 assert!(!json_col_as_json.flags.contains(Flags::BLOB_FLAG));
1489 assert!(!json_col_as_json.flags.contains(Flags::SET_FLAG));
1490 assert!(!json_col_as_json.flags.contains(Flags::ENUM_FLAG));
1491 assert!(!json_col_as_json.flags.contains(Flags::BINARY_FLAG));
1492 assert_eq!(
1493 to_value::<Text, String>(&json_col_as_json).unwrap(),
1494 "{\"abca\": 42}"
1495 );
1496
1497 let json_col_as_text = query_single_table(
1498 "SELECT json_field FROM json_test",
1499 conn,
1500 (ffi::enum_field_types::MYSQL_TYPE_BLOB, Flags::empty()),
1501 );
1502
1503 assert_eq!(json_col_as_text.tpe, ffi::enum_field_types::MYSQL_TYPE_BLOB);
1504 assert!(!json_col_as_text.flags.contains(Flags::NUM_FLAG));
1505 assert!(!json_col_as_text.flags.contains(Flags::BLOB_FLAG));
1506 assert!(!json_col_as_text.flags.contains(Flags::SET_FLAG));
1507 assert!(!json_col_as_text.flags.contains(Flags::ENUM_FLAG));
1508 assert!(!json_col_as_text.flags.contains(Flags::BINARY_FLAG));
1509 assert_eq!(
1510 to_value::<Text, String>(&json_col_as_text).unwrap(),
1511 "{\"abca\": 42}"
1512 );
1513 assert_eq!(
1514 json_col_as_json.value().unwrap().as_bytes(),
1515 json_col_as_text.value().unwrap().as_bytes()
1516 );
1517 }
1518
1519 #[diesel_test_helper::test]
1520 fn check_enum_bind() {
1521 let conn = &mut crate::test_helpers::connection();
1522
1523 crate::sql_query("DROP TABLE IF EXISTS enum_test CASCADE")
1524 .execute(conn)
1525 .unwrap();
1526
1527 crate::sql_query("CREATE TABLE enum_test(id INTEGER PRIMARY KEY, enum_field ENUM('red', 'green', 'blue') NOT NULL)").execute(conn)
1528 .unwrap();
1529
1530 crate::sql_query("INSERT INTO enum_test(id, enum_field) VALUES (1, 'green')")
1531 .execute(conn)
1532 .unwrap();
1533
1534 let enum_col_as_enum: BindData =
1535 query_single_table("SELECT enum_field FROM enum_test", conn, MysqlType::Enum);
1536
1537 assert_eq!(
1538 enum_col_as_enum.tpe,
1539 ffi::enum_field_types::MYSQL_TYPE_STRING
1540 );
1541 assert!(!enum_col_as_enum.flags.contains(Flags::NUM_FLAG));
1542 assert!(!enum_col_as_enum.flags.contains(Flags::BLOB_FLAG));
1543 assert!(!enum_col_as_enum.flags.contains(Flags::SET_FLAG));
1544 assert!(enum_col_as_enum.flags.contains(Flags::ENUM_FLAG));
1545 assert!(!enum_col_as_enum.flags.contains(Flags::BINARY_FLAG));
1546 assert_eq!(
1547 to_value::<Text, String>(&enum_col_as_enum).unwrap(),
1548 "green"
1549 );
1550
1551 for tpe in &[
1552 ffi::enum_field_types::MYSQL_TYPE_BLOB,
1553 ffi::enum_field_types::MYSQL_TYPE_VAR_STRING,
1554 ffi::enum_field_types::MYSQL_TYPE_TINY_BLOB,
1555 ffi::enum_field_types::MYSQL_TYPE_MEDIUM_BLOB,
1556 ffi::enum_field_types::MYSQL_TYPE_LONG_BLOB,
1557 ] {
1558 let enum_col_as_text = query_single_table(
1559 "SELECT enum_field FROM enum_test",
1560 conn,
1561 (*tpe, Flags::ENUM_FLAG),
1562 );
1563
1564 assert_eq!(enum_col_as_text.tpe, *tpe);
1565 assert!(!enum_col_as_text.flags.contains(Flags::NUM_FLAG));
1566 assert!(!enum_col_as_text.flags.contains(Flags::BLOB_FLAG));
1567 assert!(!enum_col_as_text.flags.contains(Flags::SET_FLAG));
1568 assert!(enum_col_as_text.flags.contains(Flags::ENUM_FLAG));
1569 assert!(!enum_col_as_text.flags.contains(Flags::BINARY_FLAG));
1570 assert_eq!(
1571 to_value::<Text, String>(&enum_col_as_text).unwrap(),
1572 "green"
1573 );
1574 assert_eq!(
1575 enum_col_as_enum.value().unwrap().as_bytes(),
1576 enum_col_as_text.value().unwrap().as_bytes()
1577 );
1578 }
1579
1580 let enum_col_as_text = query_single_table(
1581 "SELECT enum_field FROM enum_test",
1582 conn,
1583 (ffi::enum_field_types::MYSQL_TYPE_BLOB, Flags::empty()),
1584 );
1585
1586 assert_eq!(enum_col_as_text.tpe, ffi::enum_field_types::MYSQL_TYPE_BLOB);
1587 assert!(!enum_col_as_text.flags.contains(Flags::NUM_FLAG));
1588 assert!(!enum_col_as_text.flags.contains(Flags::BLOB_FLAG));
1589 assert!(!enum_col_as_text.flags.contains(Flags::SET_FLAG));
1590 assert!(!enum_col_as_text.flags.contains(Flags::ENUM_FLAG));
1591 assert!(!enum_col_as_text.flags.contains(Flags::BINARY_FLAG));
1592 assert_eq!(
1593 to_value::<Text, String>(&enum_col_as_text).unwrap(),
1594 "green"
1595 );
1596 assert_eq!(
1597 enum_col_as_enum.value().unwrap().as_bytes(),
1598 enum_col_as_text.value().unwrap().as_bytes()
1599 );
1600
1601 crate::sql_query("DELETE FROM enum_test")
1602 .execute(conn)
1603 .unwrap();
1604
1605 input_bind(
1606 "INSERT INTO enum_test(id, enum_field) VALUES (?, ?)",
1607 conn,
1608 41,
1609 (b"blue".to_vec(), MysqlType::Enum),
1610 );
1611
1612 let enum_col_as_enum =
1613 query_single_table("SELECT enum_field FROM enum_test", conn, MysqlType::Enum);
1614
1615 assert_eq!(
1616 enum_col_as_enum.tpe,
1617 ffi::enum_field_types::MYSQL_TYPE_STRING
1618 );
1619 assert!(!enum_col_as_enum.flags.contains(Flags::NUM_FLAG));
1620 assert!(!enum_col_as_enum.flags.contains(Flags::BLOB_FLAG));
1621 assert!(!enum_col_as_enum.flags.contains(Flags::SET_FLAG));
1622 assert!(enum_col_as_enum.flags.contains(Flags::ENUM_FLAG));
1623 assert!(!enum_col_as_enum.flags.contains(Flags::BINARY_FLAG));
1624 assert_eq!(to_value::<Text, String>(&enum_col_as_enum).unwrap(), "blue");
1625
1626 let enum_col_as_text = query_single_table(
1627 "SELECT enum_field FROM enum_test",
1628 conn,
1629 (ffi::enum_field_types::MYSQL_TYPE_BLOB, Flags::ENUM_FLAG),
1630 );
1631
1632 assert_eq!(enum_col_as_text.tpe, ffi::enum_field_types::MYSQL_TYPE_BLOB);
1633 assert!(!enum_col_as_text.flags.contains(Flags::NUM_FLAG));
1634 assert!(!enum_col_as_text.flags.contains(Flags::BLOB_FLAG));
1635 assert!(!enum_col_as_text.flags.contains(Flags::SET_FLAG));
1636 assert!(enum_col_as_text.flags.contains(Flags::ENUM_FLAG));
1637 assert!(!enum_col_as_text.flags.contains(Flags::BINARY_FLAG));
1638 assert_eq!(to_value::<Text, String>(&enum_col_as_text).unwrap(), "blue");
1639 assert_eq!(
1640 enum_col_as_enum.value().unwrap().as_bytes(),
1641 enum_col_as_text.value().unwrap().as_bytes()
1642 );
1643
1644 let enum_col_as_text = query_single_table(
1645 "SELECT enum_field FROM enum_test",
1646 conn,
1647 (ffi::enum_field_types::MYSQL_TYPE_BLOB, Flags::ENUM_FLAG),
1648 );
1649
1650 assert_eq!(enum_col_as_text.tpe, ffi::enum_field_types::MYSQL_TYPE_BLOB);
1651 assert!(!enum_col_as_text.flags.contains(Flags::NUM_FLAG));
1652 assert!(!enum_col_as_text.flags.contains(Flags::BLOB_FLAG));
1653 assert!(!enum_col_as_text.flags.contains(Flags::SET_FLAG));
1654 assert!(enum_col_as_text.flags.contains(Flags::ENUM_FLAG));
1655 assert!(!enum_col_as_text.flags.contains(Flags::BINARY_FLAG));
1656 assert_eq!(to_value::<Text, String>(&enum_col_as_text).unwrap(), "blue");
1657 assert_eq!(
1658 enum_col_as_enum.value().unwrap().as_bytes(),
1659 enum_col_as_text.value().unwrap().as_bytes()
1660 );
1661
1662 crate::sql_query("DELETE FROM enum_test")
1663 .execute(conn)
1664 .unwrap();
1665
1666 input_bind(
1667 "INSERT INTO enum_test(id, enum_field) VALUES (?, ?)",
1668 conn,
1669 41,
1670 (
1671 b"red".to_vec(),
1672 (ffi::enum_field_types::MYSQL_TYPE_BLOB, Flags::ENUM_FLAG),
1673 ),
1674 );
1675
1676 let enum_col_as_enum =
1677 query_single_table("SELECT enum_field FROM enum_test", conn, MysqlType::Enum);
1678
1679 assert_eq!(
1680 enum_col_as_enum.tpe,
1681 ffi::enum_field_types::MYSQL_TYPE_STRING
1682 );
1683 assert!(!enum_col_as_enum.flags.contains(Flags::NUM_FLAG));
1684 assert!(!enum_col_as_enum.flags.contains(Flags::BLOB_FLAG));
1685 assert!(!enum_col_as_enum.flags.contains(Flags::SET_FLAG));
1686 assert!(enum_col_as_enum.flags.contains(Flags::ENUM_FLAG));
1687 assert!(!enum_col_as_enum.flags.contains(Flags::BINARY_FLAG));
1688 assert_eq!(to_value::<Text, String>(&enum_col_as_enum).unwrap(), "red");
1689
1690 let enum_col_as_text = query_single_table(
1691 "SELECT enum_field FROM enum_test",
1692 conn,
1693 (ffi::enum_field_types::MYSQL_TYPE_BLOB, Flags::ENUM_FLAG),
1694 );
1695
1696 assert_eq!(enum_col_as_text.tpe, ffi::enum_field_types::MYSQL_TYPE_BLOB);
1697 assert!(!enum_col_as_text.flags.contains(Flags::NUM_FLAG));
1698 assert!(!enum_col_as_text.flags.contains(Flags::BLOB_FLAG));
1699 assert!(!enum_col_as_text.flags.contains(Flags::SET_FLAG));
1700 assert!(enum_col_as_text.flags.contains(Flags::ENUM_FLAG));
1701 assert!(!enum_col_as_text.flags.contains(Flags::BINARY_FLAG));
1702 assert_eq!(to_value::<Text, String>(&enum_col_as_text).unwrap(), "red");
1703 assert_eq!(
1704 enum_col_as_enum.value().unwrap().as_bytes(),
1705 enum_col_as_text.value().unwrap().as_bytes()
1706 );
1707 }
1708
1709 #[diesel_test_helper::test]
1710 fn check_set_bind() {
1711 let conn = &mut crate::test_helpers::connection();
1712
1713 crate::sql_query("DROP TABLE IF EXISTS set_test CASCADE")
1714 .execute(conn)
1715 .unwrap();
1716
1717 crate::sql_query("CREATE TABLE set_test(id INTEGER PRIMARY KEY, set_field SET('red', 'green', 'blue') NOT NULL)").execute(conn)
1718 .unwrap();
1719
1720 crate::sql_query("INSERT INTO set_test(id, set_field) VALUES (1, 'green')")
1721 .execute(conn)
1722 .unwrap();
1723
1724 let set_col_as_set: BindData =
1725 query_single_table("SELECT set_field FROM set_test", conn, MysqlType::Set);
1726
1727 assert_eq!(set_col_as_set.tpe, ffi::enum_field_types::MYSQL_TYPE_STRING);
1728 assert!(!set_col_as_set.flags.contains(Flags::NUM_FLAG));
1729 assert!(!set_col_as_set.flags.contains(Flags::BLOB_FLAG));
1730 assert!(set_col_as_set.flags.contains(Flags::SET_FLAG));
1731 assert!(!set_col_as_set.flags.contains(Flags::ENUM_FLAG));
1732 assert!(!set_col_as_set.flags.contains(Flags::BINARY_FLAG));
1733 assert_eq!(to_value::<Text, String>(&set_col_as_set).unwrap(), "green");
1734
1735 for tpe in &[
1736 ffi::enum_field_types::MYSQL_TYPE_BLOB,
1737 ffi::enum_field_types::MYSQL_TYPE_VAR_STRING,
1738 ffi::enum_field_types::MYSQL_TYPE_TINY_BLOB,
1739 ffi::enum_field_types::MYSQL_TYPE_MEDIUM_BLOB,
1740 ffi::enum_field_types::MYSQL_TYPE_LONG_BLOB,
1741 ] {
1742 let set_col_as_text = query_single_table(
1743 "SELECT set_field FROM set_test",
1744 conn,
1745 (*tpe, Flags::SET_FLAG),
1746 );
1747
1748 assert_eq!(set_col_as_text.tpe, *tpe);
1749 assert!(!set_col_as_text.flags.contains(Flags::NUM_FLAG));
1750 assert!(!set_col_as_text.flags.contains(Flags::BLOB_FLAG));
1751 assert!(set_col_as_text.flags.contains(Flags::SET_FLAG));
1752 assert!(!set_col_as_text.flags.contains(Flags::ENUM_FLAG));
1753 assert!(!set_col_as_text.flags.contains(Flags::BINARY_FLAG));
1754 assert_eq!(to_value::<Text, String>(&set_col_as_text).unwrap(), "green");
1755 assert_eq!(
1756 set_col_as_set.value().unwrap().as_bytes(),
1757 set_col_as_text.value().unwrap().as_bytes()
1758 );
1759 }
1760 let set_col_as_text = query_single_table(
1761 "SELECT set_field FROM set_test",
1762 conn,
1763 (ffi::enum_field_types::MYSQL_TYPE_BLOB, Flags::empty()),
1764 );
1765
1766 assert_eq!(set_col_as_text.tpe, ffi::enum_field_types::MYSQL_TYPE_BLOB);
1767 assert!(!set_col_as_text.flags.contains(Flags::NUM_FLAG));
1768 assert!(!set_col_as_text.flags.contains(Flags::BLOB_FLAG));
1769 assert!(!set_col_as_text.flags.contains(Flags::SET_FLAG));
1770 assert!(!set_col_as_text.flags.contains(Flags::ENUM_FLAG));
1771 assert!(!set_col_as_text.flags.contains(Flags::BINARY_FLAG));
1772 assert_eq!(to_value::<Text, String>(&set_col_as_text).unwrap(), "green");
1773 assert_eq!(
1774 set_col_as_set.value().unwrap().as_bytes(),
1775 set_col_as_text.value().unwrap().as_bytes()
1776 );
1777
1778 crate::sql_query("DELETE FROM set_test")
1779 .execute(conn)
1780 .unwrap();
1781
1782 input_bind(
1783 "INSERT INTO set_test(id, set_field) VALUES (?, ?)",
1784 conn,
1785 41,
1786 (b"blue".to_vec(), MysqlType::Set),
1787 );
1788
1789 let set_col_as_set =
1790 query_single_table("SELECT set_field FROM set_test", conn, MysqlType::Set);
1791
1792 assert_eq!(set_col_as_set.tpe, ffi::enum_field_types::MYSQL_TYPE_STRING);
1793 assert!(!set_col_as_set.flags.contains(Flags::NUM_FLAG));
1794 assert!(!set_col_as_set.flags.contains(Flags::BLOB_FLAG));
1795 assert!(set_col_as_set.flags.contains(Flags::SET_FLAG));
1796 assert!(!set_col_as_set.flags.contains(Flags::ENUM_FLAG));
1797 assert!(!set_col_as_set.flags.contains(Flags::BINARY_FLAG));
1798 assert_eq!(to_value::<Text, String>(&set_col_as_set).unwrap(), "blue");
1799
1800 let set_col_as_text = query_single_table(
1801 "SELECT set_field FROM set_test",
1802 conn,
1803 (ffi::enum_field_types::MYSQL_TYPE_BLOB, Flags::SET_FLAG),
1804 );
1805
1806 assert_eq!(set_col_as_text.tpe, ffi::enum_field_types::MYSQL_TYPE_BLOB);
1807 assert!(!set_col_as_text.flags.contains(Flags::NUM_FLAG));
1808 assert!(!set_col_as_text.flags.contains(Flags::BLOB_FLAG));
1809 assert!(set_col_as_text.flags.contains(Flags::SET_FLAG));
1810 assert!(!set_col_as_text.flags.contains(Flags::ENUM_FLAG));
1811 assert!(!set_col_as_text.flags.contains(Flags::BINARY_FLAG));
1812 assert_eq!(to_value::<Text, String>(&set_col_as_text).unwrap(), "blue");
1813 assert_eq!(
1814 set_col_as_set.value().unwrap().as_bytes(),
1815 set_col_as_text.value().unwrap().as_bytes()
1816 );
1817
1818 crate::sql_query("DELETE FROM set_test")
1819 .execute(conn)
1820 .unwrap();
1821
1822 input_bind(
1823 "INSERT INTO set_test(id, set_field) VALUES (?, ?)",
1824 conn,
1825 41,
1826 (b"red".to_vec(), MysqlType::String),
1827 );
1828
1829 let set_col_as_set =
1830 query_single_table("SELECT set_field FROM set_test", conn, MysqlType::Set);
1831
1832 assert_eq!(set_col_as_set.tpe, ffi::enum_field_types::MYSQL_TYPE_STRING);
1833 assert!(!set_col_as_set.flags.contains(Flags::NUM_FLAG));
1834 assert!(!set_col_as_set.flags.contains(Flags::BLOB_FLAG));
1835 assert!(set_col_as_set.flags.contains(Flags::SET_FLAG));
1836 assert!(!set_col_as_set.flags.contains(Flags::ENUM_FLAG));
1837 assert!(!set_col_as_set.flags.contains(Flags::BINARY_FLAG));
1838 assert_eq!(to_value::<Text, String>(&set_col_as_set).unwrap(), "red");
1839
1840 let set_col_as_text = query_single_table(
1841 "SELECT set_field FROM set_test",
1842 conn,
1843 (ffi::enum_field_types::MYSQL_TYPE_BLOB, Flags::SET_FLAG),
1844 );
1845
1846 assert_eq!(set_col_as_text.tpe, ffi::enum_field_types::MYSQL_TYPE_BLOB);
1847 assert!(!set_col_as_text.flags.contains(Flags::NUM_FLAG));
1848 assert!(!set_col_as_text.flags.contains(Flags::BLOB_FLAG));
1849 assert!(set_col_as_text.flags.contains(Flags::SET_FLAG));
1850 assert!(!set_col_as_text.flags.contains(Flags::ENUM_FLAG));
1851 assert!(!set_col_as_text.flags.contains(Flags::BINARY_FLAG));
1852 assert_eq!(to_value::<Text, String>(&set_col_as_text).unwrap(), "red");
1853 assert_eq!(
1854 set_col_as_set.value().unwrap().as_bytes(),
1855 set_col_as_text.value().unwrap().as_bytes()
1856 );
1857 }
1858}