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