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 dbg!(meta);
827
828 let value = bind.value().expect("Is not null");
829 let value = MysqlValue::new_internal(value.as_bytes(), meta);
830
831 dbg!(T::from_sql(value))
832 }
833
834 #[cfg(feature = "extras")]
835 #[diesel_test_helper::test]
836 fn check_all_the_types() {
837 let conn = &mut crate::test_helpers::connection();
838
839 crate::sql_query("DROP TABLE IF EXISTS all_mysql_types CASCADE")
840 .execute(conn)
841 .unwrap();
842 crate::sql_query(
843 "CREATE TABLE all_mysql_types (
844 tiny_int TINYINT NOT NULL,
845 small_int SMALLINT NOT NULL,
846 medium_int MEDIUMINT NOT NULL,
847 int_col INTEGER NOT NULL,
848 big_int BIGINT NOT NULL,
849 unsigned_int INTEGER UNSIGNED NOT NULL,
850 zero_fill_int INTEGER ZEROFILL NOT NULL,
851 numeric_col NUMERIC(20,5) NOT NULL,
852 decimal_col DECIMAL(20,5) NOT NULL,
853 float_col FLOAT NOT NULL,
854 double_col DOUBLE NOT NULL,
855 bit_col BIT(8) NOT NULL,
856 date_col DATE NOT NULL,
857 date_time DATETIME NOT NULL,
858 timestamp_col TIMESTAMP NOT NULL,
859 time_col TIME NOT NULL,
860 year_col YEAR NOT NULL,
861 char_col CHAR(30) NOT NULL,
862 varchar_col VARCHAR(30) NOT NULL,
863 binary_col BINARY(30) NOT NULL,
864 varbinary_col VARBINARY(30) NOT NULL,
865 blob_col BLOB NOT NULL,
866 text_col TEXT NOT NULL,
867 enum_col ENUM('red', 'green', 'blue') NOT NULL,
868 set_col SET('one', 'two') NOT NULL,
869 geom GEOMETRY NOT NULL,
870 point_col POINT NOT NULL,
871 linestring_col LINESTRING NOT NULL,
872 polygon_col POLYGON NOT NULL,
873 multipoint_col MULTIPOINT NOT NULL,
874 multilinestring_col MULTILINESTRING NOT NULL,
875 multipolygon_col MULTIPOLYGON NOT NULL,
876 geometry_collection GEOMETRYCOLLECTION NOT NULL,
877 json_col JSON NOT NULL
878 )",
879 )
880 .execute(conn)
881 .unwrap();
882 crate::sql_query(
883 "INSERT INTO all_mysql_types VALUES (
884 0, -- tiny_int
885 1, -- small_int
886 2, -- medium_int
887 3, -- int_col
888 -5, -- big_int
889 42, -- unsigned_int
890 1, -- zero_fill_int
891 -999.999, -- numeric_col,
892 3.14, -- decimal_col,
893 1.23, -- float_col
894 4.5678, -- double_col
895 b'10101010', -- bit_col
896 '1000-01-01', -- date_col
897 '9999-12-31 12:34:45.012345', -- date_time
898 '2020-01-01 10:10:10', -- timestamp_col
899 '23:01:01', -- time_col
900 2020, -- year_col
901 'abc', -- char_col
902 'foo', -- varchar_col
903 'a ', -- binary_col
904 'a ', -- varbinary_col
905 'binary', -- blob_col
906 'some text whatever', -- text_col
907 'red', -- enum_col
908 'one', -- set_col
909 ST_GeomFromText('POINT(1 1)'), -- geom
910 ST_PointFromText('POINT(1 1)'), -- point_col
911 ST_LineStringFromText('LINESTRING(0 0,1 1,2 2)'), -- linestring_col
912 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
913 ST_MultiPointFromText('MULTIPOINT(0 0,10 10,10 20,20 20)'), -- multipoint_col
914 ST_MultiLineStringFromText('MULTILINESTRING((10 48,10 21,10 0),(16 0,16 23,16 48))'), -- multilinestring_col
915 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
916 ST_GeomCollFromText('GEOMETRYCOLLECTION(POINT(1 1),LINESTRING(0 0,1 1,2 2,3 3,4 4))'), -- geometry_collection
917 '{\"key1\": \"value1\", \"key2\": \"value2\"}' -- json_col
918)",
919 ).execute(conn)
920 .unwrap();
921
922 let stmt = crate::mysql::connection::prepared_query(
923 &crate::sql_query(
924 "SELECT
925 tiny_int, small_int, medium_int, int_col,
926 big_int, unsigned_int, zero_fill_int,
927 numeric_col, decimal_col, float_col, double_col, bit_col,
928 date_col, date_time, timestamp_col, time_col, year_col,
929 char_col, varchar_col, binary_col, varbinary_col, blob_col,
930 text_col, enum_col, set_col, ST_AsText(geom), ST_AsText(point_col), ST_AsText(linestring_col),
931 ST_AsText(polygon_col), ST_AsText(multipoint_col), ST_AsText(multilinestring_col),
932 ST_AsText(multipolygon_col), ST_AsText(geometry_collection), json_col
933 FROM all_mysql_types",
934 ),
935 &mut conn.statement_cache,
936 &mut conn.raw_connection,
937 &mut *conn.instrumentation,
938 ).unwrap();
939
940 let metadata = stmt.metadata().unwrap();
941 let mut output_binds =
942 OutputBinds::from_output_types(&vec![None; metadata.fields().len()], &metadata);
943 let stmt = stmt.execute_statement(&mut output_binds).unwrap();
944 stmt.populate_row_buffers(&mut output_binds).unwrap();
945
946 let results: Vec<(BindData, &_)> = output_binds
947 .0
948 .data
949 .into_iter()
950 .zip(metadata.fields())
951 .collect::<Vec<_>>();
952
953 let tiny_int_col = &results[0].0;
954 assert_eq!(tiny_int_col.tpe, ffi::enum_field_types::MYSQL_TYPE_TINY);
955 assert!(tiny_int_col.flags.contains(Flags::NUM_FLAG));
956 assert!(!tiny_int_col.flags.contains(Flags::UNSIGNED_FLAG));
957 assert!(matches!(to_value::<TinyInt, i8>(tiny_int_col), Ok(0)));
958
959 let small_int_col = &results[1].0;
960 assert_eq!(small_int_col.tpe, ffi::enum_field_types::MYSQL_TYPE_SHORT);
961 assert!(small_int_col.flags.contains(Flags::NUM_FLAG));
962 assert!(!small_int_col.flags.contains(Flags::UNSIGNED_FLAG));
963 assert!(matches!(to_value::<SmallInt, i16>(small_int_col), Ok(1)));
964
965 let medium_int_col = &results[2].0;
966 assert_eq!(medium_int_col.tpe, ffi::enum_field_types::MYSQL_TYPE_INT24);
967 assert!(medium_int_col.flags.contains(Flags::NUM_FLAG));
968 assert!(!medium_int_col.flags.contains(Flags::UNSIGNED_FLAG));
969 assert!(matches!(to_value::<Integer, i32>(medium_int_col), Ok(2)));
970
971 let int_col = &results[3].0;
972 assert_eq!(int_col.tpe, ffi::enum_field_types::MYSQL_TYPE_LONG);
973 assert!(int_col.flags.contains(Flags::NUM_FLAG));
974 assert!(!int_col.flags.contains(Flags::UNSIGNED_FLAG));
975 assert!(matches!(to_value::<Integer, i32>(int_col), Ok(3)));
976
977 let big_int_col = &results[4].0;
978 assert_eq!(big_int_col.tpe, ffi::enum_field_types::MYSQL_TYPE_LONGLONG);
979 assert!(big_int_col.flags.contains(Flags::NUM_FLAG));
980 assert!(!big_int_col.flags.contains(Flags::UNSIGNED_FLAG));
981 assert!(matches!(to_value::<TinyInt, i8>(big_int_col), Ok(-5)));
982
983 let unsigned_int_col = &results[5].0;
984 assert_eq!(unsigned_int_col.tpe, ffi::enum_field_types::MYSQL_TYPE_LONG);
985 assert!(unsigned_int_col.flags.contains(Flags::NUM_FLAG));
986 assert!(unsigned_int_col.flags.contains(Flags::UNSIGNED_FLAG));
987 assert!(matches!(
988 to_value::<Unsigned<Integer>, u32>(unsigned_int_col),
989 Ok(42)
990 ));
991
992 let zero_fill_int_col = &results[6].0;
993 assert_eq!(
994 zero_fill_int_col.tpe,
995 ffi::enum_field_types::MYSQL_TYPE_LONG
996 );
997 assert!(zero_fill_int_col.flags.contains(Flags::NUM_FLAG));
998 assert!(zero_fill_int_col.flags.contains(Flags::ZEROFILL_FLAG));
999 assert!(matches!(to_value::<Integer, i32>(zero_fill_int_col), Ok(1)));
1000
1001 let numeric_col = &results[7].0;
1002 assert_eq!(
1003 numeric_col.tpe,
1004 ffi::enum_field_types::MYSQL_TYPE_NEWDECIMAL
1005 );
1006 assert!(numeric_col.flags.contains(Flags::NUM_FLAG));
1007 assert!(!numeric_col.flags.contains(Flags::UNSIGNED_FLAG));
1008 assert_eq!(
1009 to_value::<Numeric, bigdecimal::BigDecimal>(numeric_col).unwrap(),
1010 bigdecimal::BigDecimal::from_str("-999.99900").unwrap()
1011 );
1012
1013 let decimal_col = &results[8].0;
1014 assert_eq!(
1015 decimal_col.tpe,
1016 ffi::enum_field_types::MYSQL_TYPE_NEWDECIMAL
1017 );
1018 assert!(decimal_col.flags.contains(Flags::NUM_FLAG));
1019 assert!(!decimal_col.flags.contains(Flags::UNSIGNED_FLAG));
1020 assert_eq!(
1021 to_value::<Numeric, bigdecimal::BigDecimal>(decimal_col).unwrap(),
1022 bigdecimal::BigDecimal::from_str("3.14000").unwrap()
1023 );
1024
1025 let float_col = &results[9].0;
1026 assert_eq!(float_col.tpe, ffi::enum_field_types::MYSQL_TYPE_FLOAT);
1027 assert!(float_col.flags.contains(Flags::NUM_FLAG));
1028 assert!(!float_col.flags.contains(Flags::UNSIGNED_FLAG));
1029 assert_eq!(to_value::<Float, f32>(float_col).unwrap(), 1.23);
1030
1031 let double_col = &results[10].0;
1032 assert_eq!(double_col.tpe, ffi::enum_field_types::MYSQL_TYPE_DOUBLE);
1033 assert!(double_col.flags.contains(Flags::NUM_FLAG));
1034 assert!(!double_col.flags.contains(Flags::UNSIGNED_FLAG));
1035 assert_eq!(to_value::<Double, f64>(double_col).unwrap(), 4.5678);
1036
1037 let bit_col = &results[11].0;
1038 assert_eq!(bit_col.tpe, ffi::enum_field_types::MYSQL_TYPE_BIT);
1039 assert!(!bit_col.flags.contains(Flags::NUM_FLAG));
1040 assert!(bit_col.flags.contains(Flags::UNSIGNED_FLAG));
1041 assert!(!bit_col.flags.contains(Flags::BINARY_FLAG));
1042 assert_eq!(to_value::<Blob, Vec<u8>>(bit_col).unwrap(), vec![170]);
1043
1044 let date_col = &results[12].0;
1045 assert_eq!(date_col.tpe, ffi::enum_field_types::MYSQL_TYPE_DATE);
1046 assert!(!date_col.flags.contains(Flags::NUM_FLAG));
1047 assert_eq!(
1048 to_value::<Date, chrono::NaiveDate>(date_col).unwrap(),
1049 chrono::NaiveDate::from_ymd_opt(1000, 1, 1).unwrap(),
1050 );
1051
1052 let date_time_col = &results[13].0;
1053 assert_eq!(
1054 date_time_col.tpe,
1055 ffi::enum_field_types::MYSQL_TYPE_DATETIME
1056 );
1057 assert!(!date_time_col.flags.contains(Flags::NUM_FLAG));
1058 assert_eq!(
1059 to_value::<Datetime, chrono::NaiveDateTime>(date_time_col).unwrap(),
1060 chrono::NaiveDateTime::parse_from_str("9999-12-31 12:34:45", "%Y-%m-%d %H:%M:%S")
1061 .unwrap()
1062 );
1063
1064 let timestamp_col = &results[14].0;
1065 assert_eq!(
1066 timestamp_col.tpe,
1067 ffi::enum_field_types::MYSQL_TYPE_TIMESTAMP
1068 );
1069 assert!(!timestamp_col.flags.contains(Flags::NUM_FLAG));
1070 assert_eq!(
1071 to_value::<Datetime, chrono::NaiveDateTime>(timestamp_col).unwrap(),
1072 chrono::NaiveDateTime::parse_from_str("2020-01-01 10:10:10", "%Y-%m-%d %H:%M:%S")
1073 .unwrap()
1074 );
1075
1076 let time_col = &results[15].0;
1077 assert_eq!(time_col.tpe, ffi::enum_field_types::MYSQL_TYPE_TIME);
1078 assert!(!time_col.flags.contains(Flags::NUM_FLAG));
1079 assert_eq!(
1080 to_value::<Time, chrono::NaiveTime>(time_col).unwrap(),
1081 chrono::NaiveTime::from_hms_opt(23, 1, 1).unwrap()
1082 );
1083
1084 let year_col = &results[16].0;
1085 assert_eq!(year_col.tpe, ffi::enum_field_types::MYSQL_TYPE_YEAR);
1086 assert!(year_col.flags.contains(Flags::NUM_FLAG));
1087 assert!(year_col.flags.contains(Flags::UNSIGNED_FLAG));
1088 assert!(matches!(to_value::<SmallInt, i16>(year_col), Ok(2020)));
1089
1090 let char_col = &results[17].0;
1091 assert_eq!(char_col.tpe, ffi::enum_field_types::MYSQL_TYPE_STRING);
1092 assert!(!char_col.flags.contains(Flags::NUM_FLAG));
1093 assert!(!char_col.flags.contains(Flags::BLOB_FLAG));
1094 assert!(!char_col.flags.contains(Flags::SET_FLAG));
1095 assert!(!char_col.flags.contains(Flags::ENUM_FLAG));
1096 assert!(!char_col.flags.contains(Flags::BINARY_FLAG));
1097 assert_eq!(to_value::<Text, String>(char_col).unwrap(), "abc");
1098
1099 let varchar_col = &results[18].0;
1100 assert_eq!(
1101 varchar_col.tpe,
1102 ffi::enum_field_types::MYSQL_TYPE_VAR_STRING
1103 );
1104 assert!(!varchar_col.flags.contains(Flags::NUM_FLAG));
1105 assert!(!varchar_col.flags.contains(Flags::BLOB_FLAG));
1106 assert!(!varchar_col.flags.contains(Flags::SET_FLAG));
1107 assert!(!varchar_col.flags.contains(Flags::ENUM_FLAG));
1108 assert!(!varchar_col.flags.contains(Flags::BINARY_FLAG));
1109 assert_eq!(to_value::<Text, String>(varchar_col).unwrap(), "foo");
1110
1111 let binary_col = &results[19].0;
1112 assert_eq!(binary_col.tpe, ffi::enum_field_types::MYSQL_TYPE_STRING);
1113 assert!(!binary_col.flags.contains(Flags::NUM_FLAG));
1114 assert!(!binary_col.flags.contains(Flags::BLOB_FLAG));
1115 assert!(!binary_col.flags.contains(Flags::SET_FLAG));
1116 assert!(!binary_col.flags.contains(Flags::ENUM_FLAG));
1117 assert!(binary_col.flags.contains(Flags::BINARY_FLAG));
1118 assert_eq!(
1119 to_value::<Blob, Vec<u8>>(binary_col).unwrap(),
1120 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"
1121 );
1122
1123 let varbinary_col = &results[20].0;
1124 assert_eq!(
1125 varbinary_col.tpe,
1126 ffi::enum_field_types::MYSQL_TYPE_VAR_STRING
1127 );
1128 assert!(!varbinary_col.flags.contains(Flags::NUM_FLAG));
1129 assert!(!varbinary_col.flags.contains(Flags::BLOB_FLAG));
1130 assert!(!varbinary_col.flags.contains(Flags::SET_FLAG));
1131 assert!(!varbinary_col.flags.contains(Flags::ENUM_FLAG));
1132 assert!(varbinary_col.flags.contains(Flags::BINARY_FLAG));
1133 assert_eq!(to_value::<Blob, Vec<u8>>(varbinary_col).unwrap(), b"a ");
1134
1135 let blob_col = &results[21].0;
1136 assert_eq!(blob_col.tpe, ffi::enum_field_types::MYSQL_TYPE_BLOB);
1137 assert!(!blob_col.flags.contains(Flags::NUM_FLAG));
1138 assert!(blob_col.flags.contains(Flags::BLOB_FLAG));
1139 assert!(!blob_col.flags.contains(Flags::SET_FLAG));
1140 assert!(!blob_col.flags.contains(Flags::ENUM_FLAG));
1141 assert!(blob_col.flags.contains(Flags::BINARY_FLAG));
1142 assert_eq!(to_value::<Blob, Vec<u8>>(blob_col).unwrap(), b"binary");
1143
1144 let text_col = &results[22].0;
1145 assert_eq!(text_col.tpe, ffi::enum_field_types::MYSQL_TYPE_BLOB);
1146 assert!(!text_col.flags.contains(Flags::NUM_FLAG));
1147 assert!(text_col.flags.contains(Flags::BLOB_FLAG));
1148 assert!(!text_col.flags.contains(Flags::SET_FLAG));
1149 assert!(!text_col.flags.contains(Flags::ENUM_FLAG));
1150 assert!(!text_col.flags.contains(Flags::BINARY_FLAG));
1151 assert_eq!(
1152 to_value::<Text, String>(text_col).unwrap(),
1153 "some text whatever"
1154 );
1155
1156 let enum_col = &results[23].0;
1157 assert_eq!(enum_col.tpe, ffi::enum_field_types::MYSQL_TYPE_STRING);
1158 assert!(!enum_col.flags.contains(Flags::NUM_FLAG));
1159 assert!(!enum_col.flags.contains(Flags::BLOB_FLAG));
1160 assert!(!enum_col.flags.contains(Flags::SET_FLAG));
1161 assert!(enum_col.flags.contains(Flags::ENUM_FLAG));
1162 assert!(!enum_col.flags.contains(Flags::BINARY_FLAG));
1163 assert_eq!(to_value::<Text, String>(enum_col).unwrap(), "red");
1164
1165 let set_col = &results[24].0;
1166 assert_eq!(set_col.tpe, ffi::enum_field_types::MYSQL_TYPE_STRING);
1167 assert!(!set_col.flags.contains(Flags::NUM_FLAG));
1168 assert!(!set_col.flags.contains(Flags::BLOB_FLAG));
1169 assert!(set_col.flags.contains(Flags::SET_FLAG));
1170 assert!(!set_col.flags.contains(Flags::ENUM_FLAG));
1171 assert!(!set_col.flags.contains(Flags::BINARY_FLAG));
1172 assert_eq!(to_value::<Text, String>(set_col).unwrap(), "one");
1173
1174 let geom = &results[25].0;
1175 assert_eq!(geom.tpe, ffi::enum_field_types::MYSQL_TYPE_LONG_BLOB);
1176 assert!(!geom.flags.contains(Flags::NUM_FLAG));
1177 assert!(!geom.flags.contains(Flags::BLOB_FLAG));
1178 assert!(!geom.flags.contains(Flags::SET_FLAG));
1179 assert!(!geom.flags.contains(Flags::ENUM_FLAG));
1180 assert!(!geom.flags.contains(Flags::BINARY_FLAG));
1181 assert_eq!(to_value::<Text, String>(geom).unwrap(), "POINT(1 1)");
1182
1183 let point_col = &results[26].0;
1184 assert_eq!(point_col.tpe, ffi::enum_field_types::MYSQL_TYPE_LONG_BLOB);
1185 assert!(!point_col.flags.contains(Flags::NUM_FLAG));
1186 assert!(!point_col.flags.contains(Flags::BLOB_FLAG));
1187 assert!(!point_col.flags.contains(Flags::SET_FLAG));
1188 assert!(!point_col.flags.contains(Flags::ENUM_FLAG));
1189 assert!(!point_col.flags.contains(Flags::BINARY_FLAG));
1190 assert_eq!(to_value::<Text, String>(point_col).unwrap(), "POINT(1 1)");
1191
1192 let linestring_col = &results[27].0;
1193 assert_eq!(
1194 linestring_col.tpe,
1195 ffi::enum_field_types::MYSQL_TYPE_LONG_BLOB
1196 );
1197 assert!(!linestring_col.flags.contains(Flags::NUM_FLAG));
1198 assert!(!linestring_col.flags.contains(Flags::BLOB_FLAG));
1199 assert!(!linestring_col.flags.contains(Flags::SET_FLAG));
1200 assert!(!linestring_col.flags.contains(Flags::ENUM_FLAG));
1201 assert!(!linestring_col.flags.contains(Flags::BINARY_FLAG));
1202 assert_eq!(
1203 to_value::<Text, String>(linestring_col).unwrap(),
1204 "LINESTRING(0 0,1 1,2 2)"
1205 );
1206
1207 let polygon_col = &results[28].0;
1208 assert_eq!(polygon_col.tpe, ffi::enum_field_types::MYSQL_TYPE_LONG_BLOB);
1209 assert!(!polygon_col.flags.contains(Flags::NUM_FLAG));
1210 assert!(!polygon_col.flags.contains(Flags::BLOB_FLAG));
1211 assert!(!polygon_col.flags.contains(Flags::SET_FLAG));
1212 assert!(!polygon_col.flags.contains(Flags::ENUM_FLAG));
1213 assert!(!polygon_col.flags.contains(Flags::BINARY_FLAG));
1214 assert_eq!(
1215 to_value::<Text, String>(polygon_col).unwrap(),
1216 "POLYGON((0 0,10 0,10 10,0 10,0 0),(5 5,7 5,7 7,5 7,5 5))"
1217 );
1218
1219 let multipoint_col = &results[29].0;
1220 assert_eq!(
1221 multipoint_col.tpe,
1222 ffi::enum_field_types::MYSQL_TYPE_LONG_BLOB
1223 );
1224 assert!(!multipoint_col.flags.contains(Flags::NUM_FLAG));
1225 assert!(!multipoint_col.flags.contains(Flags::BLOB_FLAG));
1226 assert!(!multipoint_col.flags.contains(Flags::SET_FLAG));
1227 assert!(!multipoint_col.flags.contains(Flags::ENUM_FLAG));
1228 assert!(!multipoint_col.flags.contains(Flags::BINARY_FLAG));
1229 let multipoint_res = to_value::<Text, String>(multipoint_col).unwrap();
1233 assert!(
1234 multipoint_res == "MULTIPOINT((0 0),(10 10),(10 20),(20 20))"
1235 || multipoint_res == "MULTIPOINT(0 0,10 10,10 20,20 20)"
1236 );
1237
1238 let multilinestring_col = &results[30].0;
1239 assert_eq!(
1240 multilinestring_col.tpe,
1241 ffi::enum_field_types::MYSQL_TYPE_LONG_BLOB
1242 );
1243 assert!(!multilinestring_col.flags.contains(Flags::NUM_FLAG));
1244 assert!(!multilinestring_col.flags.contains(Flags::BLOB_FLAG));
1245 assert!(!multilinestring_col.flags.contains(Flags::SET_FLAG));
1246 assert!(!multilinestring_col.flags.contains(Flags::ENUM_FLAG));
1247 assert!(!multilinestring_col.flags.contains(Flags::BINARY_FLAG));
1248 assert_eq!(
1249 to_value::<Text, String>(multilinestring_col).unwrap(),
1250 "MULTILINESTRING((10 48,10 21,10 0),(16 0,16 23,16 48))"
1251 );
1252
1253 let polygon_col = &results[31].0;
1254 assert_eq!(polygon_col.tpe, ffi::enum_field_types::MYSQL_TYPE_LONG_BLOB);
1255 assert!(!polygon_col.flags.contains(Flags::NUM_FLAG));
1256 assert!(!polygon_col.flags.contains(Flags::BLOB_FLAG));
1257 assert!(!polygon_col.flags.contains(Flags::SET_FLAG));
1258 assert!(!polygon_col.flags.contains(Flags::ENUM_FLAG));
1259 assert!(!polygon_col.flags.contains(Flags::BINARY_FLAG));
1260 assert_eq!(
1261 to_value::<Text, String>(polygon_col).unwrap(),
1262 "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)))"
1263 );
1264
1265 let geometry_collection = &results[32].0;
1266 assert_eq!(
1267 geometry_collection.tpe,
1268 ffi::enum_field_types::MYSQL_TYPE_LONG_BLOB
1269 );
1270 assert!(!geometry_collection.flags.contains(Flags::NUM_FLAG));
1271 assert!(!geometry_collection.flags.contains(Flags::BLOB_FLAG));
1272 assert!(!geometry_collection.flags.contains(Flags::SET_FLAG));
1273 assert!(!geometry_collection.flags.contains(Flags::ENUM_FLAG));
1274 assert!(!geometry_collection.flags.contains(Flags::BINARY_FLAG));
1275 assert_eq!(
1276 to_value::<Text, String>(geometry_collection).unwrap(),
1277 "GEOMETRYCOLLECTION(POINT(1 1),LINESTRING(0 0,1 1,2 2,3 3,4 4))"
1278 );
1279
1280 let json_col = &results[33].0;
1281 assert!(
1286 json_col.tpe == ffi::enum_field_types::MYSQL_TYPE_JSON
1287 || json_col.tpe == ffi::enum_field_types::MYSQL_TYPE_BLOB
1288 );
1289 assert!(!json_col.flags.contains(Flags::NUM_FLAG));
1290 assert!(json_col.flags.contains(Flags::BLOB_FLAG));
1291 assert!(!json_col.flags.contains(Flags::SET_FLAG));
1292 assert!(!json_col.flags.contains(Flags::ENUM_FLAG));
1293 assert!(json_col.flags.contains(Flags::BINARY_FLAG));
1294 assert_eq!(
1295 to_value::<Text, String>(json_col).unwrap(),
1296 "{\"key1\": \"value1\", \"key2\": \"value2\"}"
1297 );
1298 }
1299
1300 fn query_single_table(
1301 query: &'static str,
1302 conn: &MysqlConnection,
1303 bind_tpe: impl Into<(ffi::enum_field_types, Flags)>,
1304 ) -> BindData {
1305 let stmt: Statement = conn
1306 .raw_connection
1307 .prepare(query, PrepareForCache::No, &[])
1308 .unwrap();
1309 let stmt = MaybeCached::CannotCache(stmt);
1310
1311 let bind = BindData::from_tpe_and_flags(bind_tpe.into());
1312
1313 let mut binds = OutputBinds(Binds { data: vec![bind] });
1314
1315 let stmt = stmt.execute_statement(&mut binds).unwrap();
1316 stmt.populate_row_buffers(&mut binds).unwrap();
1317
1318 binds.0.data.remove(0)
1319 }
1320
1321 fn input_bind(
1322 query: &'static str,
1323 conn: &MysqlConnection,
1324 id: i32,
1325 (field, tpe): (Vec<u8>, impl Into<(ffi::enum_field_types, Flags)>),
1326 ) {
1327 let mut stmt = conn
1328 .raw_connection
1329 .prepare(query, PrepareForCache::No, &[])
1330 .unwrap();
1331 let length = field.len() as _;
1332 let (tpe, flags) = tpe.into();
1333 let (ptr, _length, capacity) = bind_buffer(field);
1334
1335 let field_bind = BindData {
1336 tpe,
1337 bytes: ptr,
1338 capacity,
1339 length,
1340 flags,
1341 is_null: ffi::FALSE,
1342 is_truncated: None,
1343 };
1344
1345 let (ptr, length, capacity) = bind_buffer(id.to_be_bytes().to_vec());
1346
1347 let id_bind = BindData {
1348 tpe: ffi::enum_field_types::MYSQL_TYPE_LONG,
1349 bytes: ptr,
1350 capacity,
1351 length,
1352 flags: Flags::empty(),
1353 is_null: ffi::FALSE,
1354 is_truncated: None,
1355 };
1356
1357 let binds = PreparedStatementBinds(Binds {
1358 data: vec![id_bind, field_bind],
1359 });
1360 stmt.input_bind(binds).unwrap();
1361 stmt.did_an_error_occur().unwrap();
1362 let stmt = MaybeCached::CannotCache(stmt);
1363 unsafe {
1364 stmt.execute().unwrap();
1365 }
1366 }
1367
1368 #[diesel_test_helper::test]
1369 fn check_json_bind() {
1370 table! {
1371 json_test {
1372 id -> Integer,
1373 json_field -> Text,
1374 }
1375 }
1376
1377 let conn = &mut crate::test_helpers::connection();
1378
1379 crate::sql_query("DROP TABLE IF EXISTS json_test CASCADE")
1380 .execute(conn)
1381 .unwrap();
1382
1383 crate::sql_query(
1384 "CREATE TABLE json_test(id INTEGER PRIMARY KEY, json_field JSON NOT NULL)",
1385 )
1386 .execute(conn)
1387 .unwrap();
1388
1389 crate::sql_query("INSERT INTO json_test(id, json_field) VALUES (1, '{\"key1\": \"value1\", \"key2\": \"value2\"}')").execute(conn).unwrap();
1390
1391 let json_col_as_json = query_single_table(
1392 "SELECT json_field FROM json_test",
1393 conn,
1394 (ffi::enum_field_types::MYSQL_TYPE_JSON, Flags::empty()),
1395 );
1396
1397 assert_eq!(json_col_as_json.tpe, ffi::enum_field_types::MYSQL_TYPE_JSON);
1398 assert!(!json_col_as_json.flags.contains(Flags::NUM_FLAG));
1399 assert!(!json_col_as_json.flags.contains(Flags::BLOB_FLAG));
1400 assert!(!json_col_as_json.flags.contains(Flags::SET_FLAG));
1401 assert!(!json_col_as_json.flags.contains(Flags::ENUM_FLAG));
1402 assert!(!json_col_as_json.flags.contains(Flags::BINARY_FLAG));
1403 assert_eq!(
1404 to_value::<Text, String>(&json_col_as_json).unwrap(),
1405 "{\"key1\": \"value1\", \"key2\": \"value2\"}"
1406 );
1407
1408 let json_col_as_text = query_single_table(
1409 "SELECT json_field FROM json_test",
1410 conn,
1411 (ffi::enum_field_types::MYSQL_TYPE_BLOB, Flags::empty()),
1412 );
1413
1414 assert_eq!(json_col_as_text.tpe, ffi::enum_field_types::MYSQL_TYPE_BLOB);
1415 assert!(!json_col_as_text.flags.contains(Flags::NUM_FLAG));
1416 assert!(!json_col_as_text.flags.contains(Flags::BLOB_FLAG));
1417 assert!(!json_col_as_text.flags.contains(Flags::SET_FLAG));
1418 assert!(!json_col_as_text.flags.contains(Flags::ENUM_FLAG));
1419 assert!(!json_col_as_text.flags.contains(Flags::BINARY_FLAG));
1420 assert_eq!(
1421 to_value::<Text, String>(&json_col_as_text).unwrap(),
1422 "{\"key1\": \"value1\", \"key2\": \"value2\"}"
1423 );
1424 assert_eq!(
1425 json_col_as_json.value().unwrap().as_bytes(),
1426 json_col_as_text.value().unwrap().as_bytes()
1427 );
1428
1429 crate::sql_query("DELETE FROM json_test")
1430 .execute(conn)
1431 .unwrap();
1432
1433 input_bind(
1434 "INSERT INTO json_test(id, json_field) VALUES (?, ?)",
1435 conn,
1436 41,
1437 (
1438 b"{\"abc\": 42}".to_vec(),
1439 MysqlType::String,
1440 ),
1442 );
1443
1444 let json_col_as_json = query_single_table(
1445 "SELECT json_field FROM json_test",
1446 conn,
1447 (ffi::enum_field_types::MYSQL_TYPE_JSON, Flags::empty()),
1448 );
1449
1450 assert_eq!(json_col_as_json.tpe, ffi::enum_field_types::MYSQL_TYPE_JSON);
1451 assert!(!json_col_as_json.flags.contains(Flags::NUM_FLAG));
1452 assert!(!json_col_as_json.flags.contains(Flags::BLOB_FLAG));
1453 assert!(!json_col_as_json.flags.contains(Flags::SET_FLAG));
1454 assert!(!json_col_as_json.flags.contains(Flags::ENUM_FLAG));
1455 assert!(!json_col_as_json.flags.contains(Flags::BINARY_FLAG));
1456 assert_eq!(
1457 to_value::<Text, String>(&json_col_as_json).unwrap(),
1458 "{\"abc\": 42}"
1459 );
1460
1461 let json_col_as_text = query_single_table(
1462 "SELECT json_field FROM json_test",
1463 conn,
1464 (ffi::enum_field_types::MYSQL_TYPE_BLOB, Flags::empty()),
1465 );
1466
1467 assert_eq!(json_col_as_text.tpe, ffi::enum_field_types::MYSQL_TYPE_BLOB);
1468 assert!(!json_col_as_text.flags.contains(Flags::NUM_FLAG));
1469 assert!(!json_col_as_text.flags.contains(Flags::BLOB_FLAG));
1470 assert!(!json_col_as_text.flags.contains(Flags::SET_FLAG));
1471 assert!(!json_col_as_text.flags.contains(Flags::ENUM_FLAG));
1472 assert!(!json_col_as_text.flags.contains(Flags::BINARY_FLAG));
1473 assert_eq!(
1474 to_value::<Text, String>(&json_col_as_text).unwrap(),
1475 "{\"abc\": 42}"
1476 );
1477 assert_eq!(
1478 json_col_as_json.value().unwrap().as_bytes(),
1479 json_col_as_text.value().unwrap().as_bytes()
1480 );
1481
1482 crate::sql_query("DELETE FROM json_test")
1483 .execute(conn)
1484 .unwrap();
1485
1486 input_bind(
1487 "INSERT INTO json_test(id, json_field) VALUES (?, ?)",
1488 conn,
1489 41,
1490 (b"{\"abca\": 42}".to_vec(), MysqlType::String),
1491 );
1492
1493 let json_col_as_json = query_single_table(
1494 "SELECT json_field FROM json_test",
1495 conn,
1496 (ffi::enum_field_types::MYSQL_TYPE_JSON, Flags::empty()),
1497 );
1498
1499 assert_eq!(json_col_as_json.tpe, ffi::enum_field_types::MYSQL_TYPE_JSON);
1500 assert!(!json_col_as_json.flags.contains(Flags::NUM_FLAG));
1501 assert!(!json_col_as_json.flags.contains(Flags::BLOB_FLAG));
1502 assert!(!json_col_as_json.flags.contains(Flags::SET_FLAG));
1503 assert!(!json_col_as_json.flags.contains(Flags::ENUM_FLAG));
1504 assert!(!json_col_as_json.flags.contains(Flags::BINARY_FLAG));
1505 assert_eq!(
1506 to_value::<Text, String>(&json_col_as_json).unwrap(),
1507 "{\"abca\": 42}"
1508 );
1509
1510 let json_col_as_text = query_single_table(
1511 "SELECT json_field FROM json_test",
1512 conn,
1513 (ffi::enum_field_types::MYSQL_TYPE_BLOB, Flags::empty()),
1514 );
1515
1516 assert_eq!(json_col_as_text.tpe, ffi::enum_field_types::MYSQL_TYPE_BLOB);
1517 assert!(!json_col_as_text.flags.contains(Flags::NUM_FLAG));
1518 assert!(!json_col_as_text.flags.contains(Flags::BLOB_FLAG));
1519 assert!(!json_col_as_text.flags.contains(Flags::SET_FLAG));
1520 assert!(!json_col_as_text.flags.contains(Flags::ENUM_FLAG));
1521 assert!(!json_col_as_text.flags.contains(Flags::BINARY_FLAG));
1522 assert_eq!(
1523 to_value::<Text, String>(&json_col_as_text).unwrap(),
1524 "{\"abca\": 42}"
1525 );
1526 assert_eq!(
1527 json_col_as_json.value().unwrap().as_bytes(),
1528 json_col_as_text.value().unwrap().as_bytes()
1529 );
1530 }
1531
1532 #[diesel_test_helper::test]
1533 fn check_enum_bind() {
1534 let conn = &mut crate::test_helpers::connection();
1535
1536 crate::sql_query("DROP TABLE IF EXISTS enum_test CASCADE")
1537 .execute(conn)
1538 .unwrap();
1539
1540 crate::sql_query("CREATE TABLE enum_test(id INTEGER PRIMARY KEY, enum_field ENUM('red', 'green', 'blue') NOT NULL)").execute(conn)
1541 .unwrap();
1542
1543 crate::sql_query("INSERT INTO enum_test(id, enum_field) VALUES (1, 'green')")
1544 .execute(conn)
1545 .unwrap();
1546
1547 let enum_col_as_enum: BindData =
1548 query_single_table("SELECT enum_field FROM enum_test", conn, MysqlType::Enum);
1549
1550 assert_eq!(
1551 enum_col_as_enum.tpe,
1552 ffi::enum_field_types::MYSQL_TYPE_STRING
1553 );
1554 assert!(!enum_col_as_enum.flags.contains(Flags::NUM_FLAG));
1555 assert!(!enum_col_as_enum.flags.contains(Flags::BLOB_FLAG));
1556 assert!(!enum_col_as_enum.flags.contains(Flags::SET_FLAG));
1557 assert!(enum_col_as_enum.flags.contains(Flags::ENUM_FLAG));
1558 assert!(!enum_col_as_enum.flags.contains(Flags::BINARY_FLAG));
1559 assert_eq!(
1560 to_value::<Text, String>(&enum_col_as_enum).unwrap(),
1561 "green"
1562 );
1563
1564 for tpe in &[
1565 ffi::enum_field_types::MYSQL_TYPE_BLOB,
1566 ffi::enum_field_types::MYSQL_TYPE_VAR_STRING,
1567 ffi::enum_field_types::MYSQL_TYPE_TINY_BLOB,
1568 ffi::enum_field_types::MYSQL_TYPE_MEDIUM_BLOB,
1569 ffi::enum_field_types::MYSQL_TYPE_LONG_BLOB,
1570 ] {
1571 let enum_col_as_text = query_single_table(
1572 "SELECT enum_field FROM enum_test",
1573 conn,
1574 (*tpe, Flags::ENUM_FLAG),
1575 );
1576
1577 assert_eq!(enum_col_as_text.tpe, *tpe);
1578 assert!(!enum_col_as_text.flags.contains(Flags::NUM_FLAG));
1579 assert!(!enum_col_as_text.flags.contains(Flags::BLOB_FLAG));
1580 assert!(!enum_col_as_text.flags.contains(Flags::SET_FLAG));
1581 assert!(enum_col_as_text.flags.contains(Flags::ENUM_FLAG));
1582 assert!(!enum_col_as_text.flags.contains(Flags::BINARY_FLAG));
1583 assert_eq!(
1584 to_value::<Text, String>(&enum_col_as_text).unwrap(),
1585 "green"
1586 );
1587 assert_eq!(
1588 enum_col_as_enum.value().unwrap().as_bytes(),
1589 enum_col_as_text.value().unwrap().as_bytes()
1590 );
1591 }
1592
1593 let enum_col_as_text = query_single_table(
1594 "SELECT enum_field FROM enum_test",
1595 conn,
1596 (ffi::enum_field_types::MYSQL_TYPE_BLOB, Flags::empty()),
1597 );
1598
1599 assert_eq!(enum_col_as_text.tpe, ffi::enum_field_types::MYSQL_TYPE_BLOB);
1600 assert!(!enum_col_as_text.flags.contains(Flags::NUM_FLAG));
1601 assert!(!enum_col_as_text.flags.contains(Flags::BLOB_FLAG));
1602 assert!(!enum_col_as_text.flags.contains(Flags::SET_FLAG));
1603 assert!(!enum_col_as_text.flags.contains(Flags::ENUM_FLAG));
1604 assert!(!enum_col_as_text.flags.contains(Flags::BINARY_FLAG));
1605 assert_eq!(
1606 to_value::<Text, String>(&enum_col_as_text).unwrap(),
1607 "green"
1608 );
1609 assert_eq!(
1610 enum_col_as_enum.value().unwrap().as_bytes(),
1611 enum_col_as_text.value().unwrap().as_bytes()
1612 );
1613
1614 crate::sql_query("DELETE FROM enum_test")
1615 .execute(conn)
1616 .unwrap();
1617
1618 input_bind(
1619 "INSERT INTO enum_test(id, enum_field) VALUES (?, ?)",
1620 conn,
1621 41,
1622 (b"blue".to_vec(), MysqlType::Enum),
1623 );
1624
1625 let enum_col_as_enum =
1626 query_single_table("SELECT enum_field FROM enum_test", conn, MysqlType::Enum);
1627
1628 assert_eq!(
1629 enum_col_as_enum.tpe,
1630 ffi::enum_field_types::MYSQL_TYPE_STRING
1631 );
1632 assert!(!enum_col_as_enum.flags.contains(Flags::NUM_FLAG));
1633 assert!(!enum_col_as_enum.flags.contains(Flags::BLOB_FLAG));
1634 assert!(!enum_col_as_enum.flags.contains(Flags::SET_FLAG));
1635 assert!(enum_col_as_enum.flags.contains(Flags::ENUM_FLAG));
1636 assert!(!enum_col_as_enum.flags.contains(Flags::BINARY_FLAG));
1637 assert_eq!(to_value::<Text, String>(&enum_col_as_enum).unwrap(), "blue");
1638
1639 let enum_col_as_text = query_single_table(
1640 "SELECT enum_field FROM enum_test",
1641 conn,
1642 (ffi::enum_field_types::MYSQL_TYPE_BLOB, Flags::ENUM_FLAG),
1643 );
1644
1645 assert_eq!(enum_col_as_text.tpe, ffi::enum_field_types::MYSQL_TYPE_BLOB);
1646 assert!(!enum_col_as_text.flags.contains(Flags::NUM_FLAG));
1647 assert!(!enum_col_as_text.flags.contains(Flags::BLOB_FLAG));
1648 assert!(!enum_col_as_text.flags.contains(Flags::SET_FLAG));
1649 assert!(enum_col_as_text.flags.contains(Flags::ENUM_FLAG));
1650 assert!(!enum_col_as_text.flags.contains(Flags::BINARY_FLAG));
1651 assert_eq!(to_value::<Text, String>(&enum_col_as_text).unwrap(), "blue");
1652 assert_eq!(
1653 enum_col_as_enum.value().unwrap().as_bytes(),
1654 enum_col_as_text.value().unwrap().as_bytes()
1655 );
1656
1657 let enum_col_as_text = query_single_table(
1658 "SELECT enum_field FROM enum_test",
1659 conn,
1660 (ffi::enum_field_types::MYSQL_TYPE_BLOB, Flags::ENUM_FLAG),
1661 );
1662
1663 assert_eq!(enum_col_as_text.tpe, ffi::enum_field_types::MYSQL_TYPE_BLOB);
1664 assert!(!enum_col_as_text.flags.contains(Flags::NUM_FLAG));
1665 assert!(!enum_col_as_text.flags.contains(Flags::BLOB_FLAG));
1666 assert!(!enum_col_as_text.flags.contains(Flags::SET_FLAG));
1667 assert!(enum_col_as_text.flags.contains(Flags::ENUM_FLAG));
1668 assert!(!enum_col_as_text.flags.contains(Flags::BINARY_FLAG));
1669 assert_eq!(to_value::<Text, String>(&enum_col_as_text).unwrap(), "blue");
1670 assert_eq!(
1671 enum_col_as_enum.value().unwrap().as_bytes(),
1672 enum_col_as_text.value().unwrap().as_bytes()
1673 );
1674
1675 crate::sql_query("DELETE FROM enum_test")
1676 .execute(conn)
1677 .unwrap();
1678
1679 input_bind(
1680 "INSERT INTO enum_test(id, enum_field) VALUES (?, ?)",
1681 conn,
1682 41,
1683 (
1684 b"red".to_vec(),
1685 (ffi::enum_field_types::MYSQL_TYPE_BLOB, Flags::ENUM_FLAG),
1686 ),
1687 );
1688
1689 let enum_col_as_enum =
1690 query_single_table("SELECT enum_field FROM enum_test", conn, MysqlType::Enum);
1691
1692 assert_eq!(
1693 enum_col_as_enum.tpe,
1694 ffi::enum_field_types::MYSQL_TYPE_STRING
1695 );
1696 assert!(!enum_col_as_enum.flags.contains(Flags::NUM_FLAG));
1697 assert!(!enum_col_as_enum.flags.contains(Flags::BLOB_FLAG));
1698 assert!(!enum_col_as_enum.flags.contains(Flags::SET_FLAG));
1699 assert!(enum_col_as_enum.flags.contains(Flags::ENUM_FLAG));
1700 assert!(!enum_col_as_enum.flags.contains(Flags::BINARY_FLAG));
1701 assert_eq!(to_value::<Text, String>(&enum_col_as_enum).unwrap(), "red");
1702
1703 let enum_col_as_text = query_single_table(
1704 "SELECT enum_field FROM enum_test",
1705 conn,
1706 (ffi::enum_field_types::MYSQL_TYPE_BLOB, Flags::ENUM_FLAG),
1707 );
1708
1709 assert_eq!(enum_col_as_text.tpe, ffi::enum_field_types::MYSQL_TYPE_BLOB);
1710 assert!(!enum_col_as_text.flags.contains(Flags::NUM_FLAG));
1711 assert!(!enum_col_as_text.flags.contains(Flags::BLOB_FLAG));
1712 assert!(!enum_col_as_text.flags.contains(Flags::SET_FLAG));
1713 assert!(enum_col_as_text.flags.contains(Flags::ENUM_FLAG));
1714 assert!(!enum_col_as_text.flags.contains(Flags::BINARY_FLAG));
1715 assert_eq!(to_value::<Text, String>(&enum_col_as_text).unwrap(), "red");
1716 assert_eq!(
1717 enum_col_as_enum.value().unwrap().as_bytes(),
1718 enum_col_as_text.value().unwrap().as_bytes()
1719 );
1720 }
1721
1722 #[diesel_test_helper::test]
1723 fn check_set_bind() {
1724 let conn = &mut crate::test_helpers::connection();
1725
1726 crate::sql_query("DROP TABLE IF EXISTS set_test CASCADE")
1727 .execute(conn)
1728 .unwrap();
1729
1730 crate::sql_query("CREATE TABLE set_test(id INTEGER PRIMARY KEY, set_field SET('red', 'green', 'blue') NOT NULL)").execute(conn)
1731 .unwrap();
1732
1733 crate::sql_query("INSERT INTO set_test(id, set_field) VALUES (1, 'green')")
1734 .execute(conn)
1735 .unwrap();
1736
1737 let set_col_as_set: BindData =
1738 query_single_table("SELECT set_field FROM set_test", conn, MysqlType::Set);
1739
1740 assert_eq!(set_col_as_set.tpe, ffi::enum_field_types::MYSQL_TYPE_STRING);
1741 assert!(!set_col_as_set.flags.contains(Flags::NUM_FLAG));
1742 assert!(!set_col_as_set.flags.contains(Flags::BLOB_FLAG));
1743 assert!(set_col_as_set.flags.contains(Flags::SET_FLAG));
1744 assert!(!set_col_as_set.flags.contains(Flags::ENUM_FLAG));
1745 assert!(!set_col_as_set.flags.contains(Flags::BINARY_FLAG));
1746 assert_eq!(to_value::<Text, String>(&set_col_as_set).unwrap(), "green");
1747
1748 for tpe in &[
1749 ffi::enum_field_types::MYSQL_TYPE_BLOB,
1750 ffi::enum_field_types::MYSQL_TYPE_VAR_STRING,
1751 ffi::enum_field_types::MYSQL_TYPE_TINY_BLOB,
1752 ffi::enum_field_types::MYSQL_TYPE_MEDIUM_BLOB,
1753 ffi::enum_field_types::MYSQL_TYPE_LONG_BLOB,
1754 ] {
1755 let set_col_as_text = query_single_table(
1756 "SELECT set_field FROM set_test",
1757 conn,
1758 (*tpe, Flags::SET_FLAG),
1759 );
1760
1761 assert_eq!(set_col_as_text.tpe, *tpe);
1762 assert!(!set_col_as_text.flags.contains(Flags::NUM_FLAG));
1763 assert!(!set_col_as_text.flags.contains(Flags::BLOB_FLAG));
1764 assert!(set_col_as_text.flags.contains(Flags::SET_FLAG));
1765 assert!(!set_col_as_text.flags.contains(Flags::ENUM_FLAG));
1766 assert!(!set_col_as_text.flags.contains(Flags::BINARY_FLAG));
1767 assert_eq!(to_value::<Text, String>(&set_col_as_text).unwrap(), "green");
1768 assert_eq!(
1769 set_col_as_set.value().unwrap().as_bytes(),
1770 set_col_as_text.value().unwrap().as_bytes()
1771 );
1772 }
1773 let set_col_as_text = query_single_table(
1774 "SELECT set_field FROM set_test",
1775 conn,
1776 (ffi::enum_field_types::MYSQL_TYPE_BLOB, Flags::empty()),
1777 );
1778
1779 assert_eq!(set_col_as_text.tpe, ffi::enum_field_types::MYSQL_TYPE_BLOB);
1780 assert!(!set_col_as_text.flags.contains(Flags::NUM_FLAG));
1781 assert!(!set_col_as_text.flags.contains(Flags::BLOB_FLAG));
1782 assert!(!set_col_as_text.flags.contains(Flags::SET_FLAG));
1783 assert!(!set_col_as_text.flags.contains(Flags::ENUM_FLAG));
1784 assert!(!set_col_as_text.flags.contains(Flags::BINARY_FLAG));
1785 assert_eq!(to_value::<Text, String>(&set_col_as_text).unwrap(), "green");
1786 assert_eq!(
1787 set_col_as_set.value().unwrap().as_bytes(),
1788 set_col_as_text.value().unwrap().as_bytes()
1789 );
1790
1791 crate::sql_query("DELETE FROM set_test")
1792 .execute(conn)
1793 .unwrap();
1794
1795 input_bind(
1796 "INSERT INTO set_test(id, set_field) VALUES (?, ?)",
1797 conn,
1798 41,
1799 (b"blue".to_vec(), MysqlType::Set),
1800 );
1801
1802 let set_col_as_set =
1803 query_single_table("SELECT set_field FROM set_test", conn, MysqlType::Set);
1804
1805 assert_eq!(set_col_as_set.tpe, ffi::enum_field_types::MYSQL_TYPE_STRING);
1806 assert!(!set_col_as_set.flags.contains(Flags::NUM_FLAG));
1807 assert!(!set_col_as_set.flags.contains(Flags::BLOB_FLAG));
1808 assert!(set_col_as_set.flags.contains(Flags::SET_FLAG));
1809 assert!(!set_col_as_set.flags.contains(Flags::ENUM_FLAG));
1810 assert!(!set_col_as_set.flags.contains(Flags::BINARY_FLAG));
1811 assert_eq!(to_value::<Text, String>(&set_col_as_set).unwrap(), "blue");
1812
1813 let set_col_as_text = query_single_table(
1814 "SELECT set_field FROM set_test",
1815 conn,
1816 (ffi::enum_field_types::MYSQL_TYPE_BLOB, Flags::SET_FLAG),
1817 );
1818
1819 assert_eq!(set_col_as_text.tpe, ffi::enum_field_types::MYSQL_TYPE_BLOB);
1820 assert!(!set_col_as_text.flags.contains(Flags::NUM_FLAG));
1821 assert!(!set_col_as_text.flags.contains(Flags::BLOB_FLAG));
1822 assert!(set_col_as_text.flags.contains(Flags::SET_FLAG));
1823 assert!(!set_col_as_text.flags.contains(Flags::ENUM_FLAG));
1824 assert!(!set_col_as_text.flags.contains(Flags::BINARY_FLAG));
1825 assert_eq!(to_value::<Text, String>(&set_col_as_text).unwrap(), "blue");
1826 assert_eq!(
1827 set_col_as_set.value().unwrap().as_bytes(),
1828 set_col_as_text.value().unwrap().as_bytes()
1829 );
1830
1831 crate::sql_query("DELETE FROM set_test")
1832 .execute(conn)
1833 .unwrap();
1834
1835 input_bind(
1836 "INSERT INTO set_test(id, set_field) VALUES (?, ?)",
1837 conn,
1838 41,
1839 (b"red".to_vec(), MysqlType::String),
1840 );
1841
1842 let set_col_as_set =
1843 query_single_table("SELECT set_field FROM set_test", conn, MysqlType::Set);
1844
1845 assert_eq!(set_col_as_set.tpe, ffi::enum_field_types::MYSQL_TYPE_STRING);
1846 assert!(!set_col_as_set.flags.contains(Flags::NUM_FLAG));
1847 assert!(!set_col_as_set.flags.contains(Flags::BLOB_FLAG));
1848 assert!(set_col_as_set.flags.contains(Flags::SET_FLAG));
1849 assert!(!set_col_as_set.flags.contains(Flags::ENUM_FLAG));
1850 assert!(!set_col_as_set.flags.contains(Flags::BINARY_FLAG));
1851 assert_eq!(to_value::<Text, String>(&set_col_as_set).unwrap(), "red");
1852
1853 let set_col_as_text = query_single_table(
1854 "SELECT set_field FROM set_test",
1855 conn,
1856 (ffi::enum_field_types::MYSQL_TYPE_BLOB, Flags::SET_FLAG),
1857 );
1858
1859 assert_eq!(set_col_as_text.tpe, ffi::enum_field_types::MYSQL_TYPE_BLOB);
1860 assert!(!set_col_as_text.flags.contains(Flags::NUM_FLAG));
1861 assert!(!set_col_as_text.flags.contains(Flags::BLOB_FLAG));
1862 assert!(set_col_as_text.flags.contains(Flags::SET_FLAG));
1863 assert!(!set_col_as_text.flags.contains(Flags::ENUM_FLAG));
1864 assert!(!set_col_as_text.flags.contains(Flags::BINARY_FLAG));
1865 assert_eq!(to_value::<Text, String>(&set_col_as_text).unwrap(), "red");
1866 assert_eq!(
1867 set_col_as_set.value().unwrap().as_bytes(),
1868 set_col_as_text.value().unwrap().as_bytes()
1869 );
1870 }
1871}