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