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