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