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