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