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