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