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