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