odbc_api/buffers/
item.rs

1use odbc_sys::{Date, Time, Timestamp};
2
3use super::{AnySlice, AnySliceMut, BufferDesc, NullableSlice, NullableSliceMut};
4use crate::Bit;
5
6/// Can either be extracted as a slice or a [`NullableSlice`] from an [`AnySlice`]. This allows
7/// the user to avoid matching on all possibile variants of an [`AnySlice`] in case the
8/// buffered type is known at compile time.
9///
10/// Usually used in generic code. E.g.:
11///
12/// ```
13/// use odbc_api::{Connection, buffers::Item};
14///
15/// fn insert_tuple2_vec<A: Item, B: Item>(
16///     conn: &Connection<'_>,
17///     insert_sql: &str,
18///     source: &[(A, B)],
19/// ) {
20///     let mut prepared = conn.prepare(insert_sql).unwrap();
21///     // Number of rows submitted in one round trip
22///     let capacity = source.len();
23///     // We do not need a nullable buffer since elements of source are not optional
24///     let descriptions = [A::buffer_desc(false), B::buffer_desc(false)];
25///     let mut inserter = prepared.column_inserter(capacity, descriptions).unwrap();
26///     // We send everything in one go.
27///     inserter.set_num_rows(source.len());
28///     // Now let's copy the row based tuple into the columnar structure
29///     for (index, (a, b)) in source.iter().enumerate() {
30///         inserter.column_mut(0).as_slice::<A>().unwrap()[index] = *a;
31///         inserter.column_mut(1).as_slice::<B>().unwrap()[index] = *b;
32///     }
33///     inserter.execute().unwrap();
34/// }
35/// ```
36pub trait Item: Sized + Copy {
37    /// Can be used to instantiate a [`super::ColumnarBuffer`]. This is useful to allocate the
38    /// correct buffers in generic code.
39    ///
40    /// # Example:
41    ///
42    /// Specification:
43    ///
44    /// ```
45    /// use odbc_api::buffers::{Item, BufferDesc};
46    ///
47    /// assert_eq!(BufferDesc::I64{ nullable: true }, i64::buffer_desc(true));
48    /// assert_eq!(BufferDesc::I64{ nullable: false }, i64::buffer_desc(false));
49    /// ```
50    fn buffer_desc(nullable: bool) -> BufferDesc;
51
52    /// Extract the array type from an [`AnySlice`].
53    fn as_slice(variant: AnySlice<'_>) -> Option<&[Self]>;
54    /// Extract the typed nullable buffer from an [`AnySlice`].
55    fn as_nullable_slice(variant: AnySlice<'_>) -> Option<NullableSlice<Self>>;
56
57    /// Extract the array type from an [`AnySliceMut`].
58    fn as_slice_mut(variant: AnySliceMut<'_>) -> Option<&'_ mut [Self]>;
59
60    /// Extract the typed nullable buffer from an [`AnySliceMut`].
61    fn as_nullable_slice_mut(variant: AnySliceMut<'_>) -> Option<NullableSliceMut<'_, Self>>;
62}
63
64macro_rules! impl_item {
65    ($t:ident, $plain:ident, $null:ident) => {
66        impl Item for $t {
67            fn buffer_desc(nullable: bool) -> BufferDesc {
68                BufferDesc::$plain { nullable }
69            }
70
71            fn as_slice(variant: AnySlice<'_>) -> Option<&[Self]> {
72                match variant {
73                    AnySlice::$plain(vals) => Some(vals),
74                    _ => None,
75                }
76            }
77
78            fn as_nullable_slice(variant: AnySlice<'_>) -> Option<NullableSlice<Self>> {
79                match variant {
80                    AnySlice::$null(vals) => Some(vals),
81                    _ => None,
82                }
83            }
84
85            fn as_slice_mut(variant: AnySliceMut<'_>) -> Option<&'_ mut [Self]> {
86                match variant {
87                    AnySliceMut::$plain(vals) => Some(vals),
88                    _ => None,
89                }
90            }
91
92            fn as_nullable_slice_mut(
93                variant: AnySliceMut<'_>,
94            ) -> Option<NullableSliceMut<'_, Self>> {
95                match variant {
96                    AnySliceMut::$null(vals) => Some(vals),
97                    _ => None,
98                }
99            }
100        }
101    };
102}
103
104impl_item!(f64, F64, NullableF64);
105impl_item!(f32, F32, NullableF32);
106impl_item!(u8, U8, NullableU8);
107impl_item!(i8, I8, NullableI8);
108impl_item!(i16, I16, NullableI16);
109impl_item!(i32, I32, NullableI32);
110impl_item!(i64, I64, NullableI64);
111impl_item!(Date, Date, NullableDate);
112impl_item!(Bit, Bit, NullableBit);
113impl_item!(Time, Time, NullableTime);
114impl_item!(Timestamp, Timestamp, NullableTimestamp);