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