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