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