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