Skip to main content

diesel/mysql/connection/
bind.rs

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