Skip to main content

diesel/mysql_like/connection/
bind.rs

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