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