odbc_api/buffers/
any_buffer.rs

1use std::{collections::HashSet, ffi::c_void};
2
3use odbc_sys::{CDataType, Date, Time, Timestamp};
4
5use crate::{
6    columnar_bulk_inserter::BoundInputSlice,
7    error::TooLargeBufferSize,
8    handles::{CData, CDataMut, HasDataType, StatementRef},
9    Bit, DataType, Error,
10};
11
12use super::{
13    bin_column::BinColumnSliceMut,
14    column_with_indicator::{
15        OptBitColumn, OptDateColumn, OptF32Column, OptF64Column, OptI16Column, OptI32Column,
16        OptI64Column, OptI8Column, OptTimeColumn, OptTimestampColumn, OptU8Column,
17    },
18    columnar::ColumnBuffer,
19    text_column::TextColumnSliceMut,
20    BinColumn, BinColumnView, BufferDesc, CharColumn, ColumnarBuffer, Indicator, Item,
21    NullableSlice, NullableSliceMut, TextColumn, TextColumnView, WCharColumn,
22};
23
24/// Since buffer shapes are same for all time / timestamps independent of the precision and we do
25/// not know the precise SQL type. In order to still be able to bind time / timestamp buffer as
26/// input without requiring the user to separately specify the precision, we declare 100 Nano second
27/// precision. This was the highest precision still supported by MSSQL in the tests.
28const DEFAULT_TIME_PRECISION: i16 = 7;
29
30/// Buffer holding a single column of either a result set or paramater
31#[derive(Debug)]
32pub enum AnyBuffer {
33    /// A buffer for holding both nullable and required binary data.
34    Binary(BinColumn),
35    /// A buffer for holding both nullable and required text data. Uses the system encoding for
36    /// character data.
37    Text(CharColumn),
38    /// A buffer for holding both nullable and required text data. Uses UTF-16 encoding
39    WText(WCharColumn),
40    Date(Vec<Date>),
41    Time(Vec<Time>),
42    Timestamp(Vec<Timestamp>),
43    F64(Vec<f64>),
44    F32(Vec<f32>),
45    I8(Vec<i8>),
46    I16(Vec<i16>),
47    I32(Vec<i32>),
48    I64(Vec<i64>),
49    U8(Vec<u8>),
50    Bit(Vec<Bit>),
51    NullableDate(OptDateColumn),
52    NullableTime(OptTimeColumn),
53    NullableTimestamp(OptTimestampColumn),
54    NullableF64(OptF64Column),
55    NullableF32(OptF32Column),
56    NullableI8(OptI8Column),
57    NullableI16(OptI16Column),
58    NullableI32(OptI32Column),
59    NullableI64(OptI64Column),
60    NullableU8(OptU8Column),
61    NullableBit(OptBitColumn),
62}
63
64impl AnyBuffer {
65    /// Map buffer description to actual buffer.
66    pub fn try_from_desc(max_rows: usize, desc: BufferDesc) -> Result<Self, TooLargeBufferSize> {
67        let fallible_allocations = true;
68        Self::impl_from_desc(max_rows, desc, fallible_allocations)
69    }
70
71    /// Map buffer description to actual buffer.
72    pub fn from_desc(max_rows: usize, desc: BufferDesc) -> Self {
73        let fallible_allocations = false;
74        Self::impl_from_desc(max_rows, desc, fallible_allocations).unwrap()
75    }
76
77    /// Map buffer description to actual buffer.
78    fn impl_from_desc(
79        max_rows: usize,
80        desc: BufferDesc,
81        fallible_allocations: bool,
82    ) -> Result<Self, TooLargeBufferSize> {
83        let buffer = match desc {
84            BufferDesc::Binary { length } => {
85                if fallible_allocations {
86                    AnyBuffer::Binary(BinColumn::try_new(max_rows, length)?)
87                } else {
88                    AnyBuffer::Binary(BinColumn::new(max_rows, length))
89                }
90            }
91            BufferDesc::Text { max_str_len } => {
92                if fallible_allocations {
93                    AnyBuffer::Text(TextColumn::try_new(max_rows, max_str_len)?)
94                } else {
95                    AnyBuffer::Text(TextColumn::new(max_rows, max_str_len))
96                }
97            }
98            BufferDesc::WText { max_str_len } => {
99                if fallible_allocations {
100                    AnyBuffer::WText(TextColumn::try_new(max_rows, max_str_len)?)
101                } else {
102                    AnyBuffer::WText(TextColumn::new(max_rows, max_str_len))
103                }
104            }
105            BufferDesc::Date { nullable: false } => {
106                AnyBuffer::Date(vec![Date::default(); max_rows])
107            }
108            BufferDesc::Time { nullable: false } => {
109                AnyBuffer::Time(vec![Time::default(); max_rows])
110            }
111            BufferDesc::Timestamp { nullable: false } => {
112                AnyBuffer::Timestamp(vec![Timestamp::default(); max_rows])
113            }
114            BufferDesc::F64 { nullable: false } => AnyBuffer::F64(vec![f64::default(); max_rows]),
115            BufferDesc::F32 { nullable: false } => AnyBuffer::F32(vec![f32::default(); max_rows]),
116            BufferDesc::I8 { nullable: false } => AnyBuffer::I8(vec![i8::default(); max_rows]),
117            BufferDesc::I16 { nullable: false } => AnyBuffer::I16(vec![i16::default(); max_rows]),
118            BufferDesc::I32 { nullable: false } => AnyBuffer::I32(vec![i32::default(); max_rows]),
119            BufferDesc::I64 { nullable: false } => AnyBuffer::I64(vec![i64::default(); max_rows]),
120            BufferDesc::U8 { nullable: false } => AnyBuffer::U8(vec![u8::default(); max_rows]),
121            BufferDesc::Bit { nullable: false } => AnyBuffer::Bit(vec![Bit::default(); max_rows]),
122            BufferDesc::Date { nullable: true } => {
123                AnyBuffer::NullableDate(OptDateColumn::new(max_rows))
124            }
125            BufferDesc::Time { nullable: true } => {
126                AnyBuffer::NullableTime(OptTimeColumn::new(max_rows))
127            }
128            BufferDesc::Timestamp { nullable: true } => {
129                AnyBuffer::NullableTimestamp(OptTimestampColumn::new(max_rows))
130            }
131            BufferDesc::F64 { nullable: true } => {
132                AnyBuffer::NullableF64(OptF64Column::new(max_rows))
133            }
134            BufferDesc::F32 { nullable: true } => {
135                AnyBuffer::NullableF32(OptF32Column::new(max_rows))
136            }
137            BufferDesc::I8 { nullable: true } => AnyBuffer::NullableI8(OptI8Column::new(max_rows)),
138            BufferDesc::I16 { nullable: true } => {
139                AnyBuffer::NullableI16(OptI16Column::new(max_rows))
140            }
141            BufferDesc::I32 { nullable: true } => {
142                AnyBuffer::NullableI32(OptI32Column::new(max_rows))
143            }
144            BufferDesc::I64 { nullable: true } => {
145                AnyBuffer::NullableI64(OptI64Column::new(max_rows))
146            }
147            BufferDesc::U8 { nullable: true } => AnyBuffer::NullableU8(OptU8Column::new(max_rows)),
148            BufferDesc::Bit { nullable: true } => {
149                AnyBuffer::NullableBit(OptBitColumn::new(max_rows))
150            }
151        };
152        Ok(buffer)
153    }
154
155    fn fill_default_slice<T: Default + Copy>(col: &mut [T]) {
156        let element = T::default();
157        for item in col {
158            *item = element;
159        }
160    }
161
162    fn inner_cdata(&self) -> &dyn CData {
163        match self {
164            AnyBuffer::Binary(col) => col,
165            AnyBuffer::Text(col) => col,
166            AnyBuffer::WText(col) => col,
167            AnyBuffer::F64(col) => col,
168            AnyBuffer::F32(col) => col,
169            AnyBuffer::Date(col) => col,
170            AnyBuffer::Time(col) => col,
171            AnyBuffer::Timestamp(col) => col,
172            AnyBuffer::I8(col) => col,
173            AnyBuffer::I16(col) => col,
174            AnyBuffer::I32(col) => col,
175            AnyBuffer::I64(col) => col,
176            AnyBuffer::Bit(col) => col,
177            AnyBuffer::U8(col) => col,
178            AnyBuffer::NullableF64(col) => col,
179            AnyBuffer::NullableF32(col) => col,
180            AnyBuffer::NullableDate(col) => col,
181            AnyBuffer::NullableTime(col) => col,
182            AnyBuffer::NullableTimestamp(col) => col,
183            AnyBuffer::NullableI8(col) => col,
184            AnyBuffer::NullableI16(col) => col,
185            AnyBuffer::NullableI32(col) => col,
186            AnyBuffer::NullableI64(col) => col,
187            AnyBuffer::NullableBit(col) => col,
188            AnyBuffer::NullableU8(col) => col,
189        }
190    }
191
192    fn inner_cdata_mut(&mut self) -> &mut dyn CDataMut {
193        match self {
194            AnyBuffer::Binary(col) => col,
195            AnyBuffer::Text(col) => col,
196            AnyBuffer::WText(col) => col,
197            AnyBuffer::F64(col) => col,
198            AnyBuffer::F32(col) => col,
199            AnyBuffer::Date(col) => col,
200            AnyBuffer::Time(col) => col,
201            AnyBuffer::Timestamp(col) => col,
202            AnyBuffer::I8(col) => col,
203            AnyBuffer::I16(col) => col,
204            AnyBuffer::I32(col) => col,
205            AnyBuffer::I64(col) => col,
206            AnyBuffer::Bit(col) => col,
207            AnyBuffer::U8(col) => col,
208            AnyBuffer::NullableF64(col) => col,
209            AnyBuffer::NullableF32(col) => col,
210            AnyBuffer::NullableDate(col) => col,
211            AnyBuffer::NullableTime(col) => col,
212            AnyBuffer::NullableTimestamp(col) => col,
213            AnyBuffer::NullableI8(col) => col,
214            AnyBuffer::NullableI16(col) => col,
215            AnyBuffer::NullableI32(col) => col,
216            AnyBuffer::NullableI64(col) => col,
217            AnyBuffer::NullableBit(col) => col,
218            AnyBuffer::NullableU8(col) => col,
219        }
220    }
221}
222
223unsafe impl CData for AnyBuffer {
224    fn cdata_type(&self) -> CDataType {
225        self.inner_cdata().cdata_type()
226    }
227
228    fn indicator_ptr(&self) -> *const isize {
229        self.inner_cdata().indicator_ptr()
230    }
231
232    fn value_ptr(&self) -> *const c_void {
233        self.inner_cdata().value_ptr()
234    }
235
236    fn buffer_length(&self) -> isize {
237        self.inner_cdata().buffer_length()
238    }
239}
240
241unsafe impl CDataMut for AnyBuffer {
242    fn mut_indicator_ptr(&mut self) -> *mut isize {
243        self.inner_cdata_mut().mut_indicator_ptr()
244    }
245
246    fn mut_value_ptr(&mut self) -> *mut c_void {
247        self.inner_cdata_mut().mut_value_ptr()
248    }
249}
250
251impl HasDataType for AnyBuffer {
252    fn data_type(&self) -> DataType {
253        match self {
254            AnyBuffer::Binary(col) => col.data_type(),
255            AnyBuffer::Text(col) => col.data_type(),
256            AnyBuffer::WText(col) => col.data_type(),
257            AnyBuffer::Date(_) | AnyBuffer::NullableDate(_) => DataType::Date,
258            AnyBuffer::Time(_) | AnyBuffer::NullableTime(_) => DataType::Time {
259                precision: DEFAULT_TIME_PRECISION,
260            },
261            AnyBuffer::Timestamp(_) | AnyBuffer::NullableTimestamp(_) => DataType::Timestamp {
262                precision: DEFAULT_TIME_PRECISION,
263            },
264            AnyBuffer::F64(_) | AnyBuffer::NullableF64(_) => DataType::Double,
265            AnyBuffer::F32(_) | AnyBuffer::NullableF32(_) => DataType::Real,
266            AnyBuffer::I8(_) | AnyBuffer::NullableI8(_) => DataType::TinyInt,
267            AnyBuffer::I16(_) | AnyBuffer::NullableI16(_) => DataType::SmallInt,
268            AnyBuffer::I32(_) | AnyBuffer::NullableI32(_) => DataType::Integer,
269            AnyBuffer::I64(_) | AnyBuffer::NullableI64(_) => DataType::BigInt,
270            // Few databases support unsigned types, binding U8 as tiny int might lead to weird
271            // stuff if the database has type is signed. I guess. Let's bind it as SmallInt by
272            // default, just to be on the safe side.
273            AnyBuffer::U8(_) | AnyBuffer::NullableU8(_) => DataType::SmallInt,
274            AnyBuffer::Bit(_) | AnyBuffer::NullableBit(_) => DataType::Bit,
275        }
276    }
277}
278
279/// Flexible columnar buffer implementation. Bind this to a cursor to fetch values in bulk, or pass
280/// this as a parameter to a statement, to submit many parameters at once.
281pub type ColumnarAnyBuffer = ColumnarBuffer<AnyBuffer>;
282
283impl ColumnarAnyBuffer {
284    /// Allocates a [`ColumnarBuffer`] fitting the buffer descriptions.
285    pub fn from_descs(capacity: usize, descs: impl IntoIterator<Item = BufferDesc>) -> Self {
286        let mut column_index = 0;
287        let columns = descs
288            .into_iter()
289            .map(move |desc| {
290                let buffer = AnyBuffer::from_desc(capacity, desc);
291                column_index += 1;
292                (column_index, buffer)
293            })
294            .collect();
295        unsafe { ColumnarBuffer::new_unchecked(capacity, columns) }
296    }
297
298    /// Allocates a [`ColumnarBuffer`] fitting the buffer descriptions. If not enough memory is
299    /// available to allocate the buffers this function fails with
300    /// [`Error::TooLargeColumnBufferSize`]. This function is slower than [`Self::from_descs`]
301    /// which would just panic if not enough memory is available for allocation.
302    pub fn try_from_descs(
303        capacity: usize,
304        descs: impl IntoIterator<Item = BufferDesc>,
305    ) -> Result<Self, Error> {
306        let mut column_index = 0;
307        let columns = descs
308            .into_iter()
309            .map(move |desc| {
310                let buffer = AnyBuffer::try_from_desc(capacity, desc)
311                    .map_err(|source| source.add_context(column_index))?;
312                column_index += 1;
313                Ok::<_, Error>((column_index, buffer))
314            })
315            .collect::<Result<_, _>>()?;
316        Ok(unsafe { ColumnarBuffer::new_unchecked(capacity, columns) })
317    }
318
319    /// Allows you to pass the buffer descriptions together with a one based column index referring
320    /// the column, the buffer is supposed to bind to. This allows you also to ignore columns in a
321    /// result set, by not binding them at all. There is no restriction on the order of column
322    /// indices passed, but the function will panic, if the indices are not unique.
323    pub fn from_descs_and_indices(
324        max_rows: usize,
325        description: impl Iterator<Item = (u16, BufferDesc)>,
326    ) -> ColumnarBuffer<AnyBuffer> {
327        let columns: Vec<_> = description
328            .map(|(col_index, buffer_desc)| {
329                (col_index, AnyBuffer::from_desc(max_rows, buffer_desc))
330            })
331            .collect();
332
333        // Assert uniqueness of indices
334        let mut indices = HashSet::new();
335        if columns
336            .iter()
337            .any(move |&(col_index, _)| !indices.insert(col_index))
338        {
339            panic!("Column indices must be unique.")
340        }
341
342        ColumnarBuffer::new(columns)
343    }
344}
345
346/// A borrowed view on the valid rows in a column of a [`crate::buffers::ColumnarBuffer`].
347///
348/// For columns of fixed size types, which are guaranteed to not contain null, a direct access to
349/// the slice is offered. Buffers over nullable columns can be accessed via an iterator over
350/// options.
351#[derive(Debug, Clone, Copy)]
352pub enum AnySlice<'a> {
353    /// Nullable character data in the system encoding.
354    Text(TextColumnView<'a, u8>),
355    /// Nullable character data encoded in UTF-16.
356    WText(TextColumnView<'a, u16>),
357    Binary(BinColumnView<'a>),
358    Date(&'a [Date]),
359    Time(&'a [Time]),
360    Timestamp(&'a [Timestamp]),
361    F64(&'a [f64]),
362    F32(&'a [f32]),
363    I8(&'a [i8]),
364    I16(&'a [i16]),
365    I32(&'a [i32]),
366    I64(&'a [i64]),
367    U8(&'a [u8]),
368    Bit(&'a [Bit]),
369    NullableDate(NullableSlice<'a, Date>),
370    NullableTime(NullableSlice<'a, Time>),
371    NullableTimestamp(NullableSlice<'a, Timestamp>),
372    NullableF64(NullableSlice<'a, f64>),
373    NullableF32(NullableSlice<'a, f32>),
374    NullableI8(NullableSlice<'a, i8>),
375    NullableI16(NullableSlice<'a, i16>),
376    NullableI32(NullableSlice<'a, i32>),
377    NullableI64(NullableSlice<'a, i64>),
378    NullableU8(NullableSlice<'a, u8>),
379    NullableBit(NullableSlice<'a, Bit>),
380}
381
382impl<'a> AnySlice<'a> {
383    /// This method is useful if you expect the variant to be [`AnySlice::Text`]. It allows you to
384    /// unwrap the inner column view without explictly matching it.
385    pub fn as_text_view(self) -> Option<TextColumnView<'a, u8>> {
386        if let Self::Text(view) = self {
387            Some(view)
388        } else {
389            None
390        }
391    }
392
393    /// This method is useful if you expect the variant to be [`AnySlice::WText`]. It allows you to
394    /// unwrap the inner column view without explictly matching it.
395    pub fn as_w_text_view(self) -> Option<TextColumnView<'a, u16>> {
396        if let Self::WText(view) = self {
397            Some(view)
398        } else {
399            None
400        }
401    }
402
403    /// This method is useful if you expect the variant to be [`AnySlice::Binary`]. It allows you to
404    /// unwrap the inner column view without explictly matching it.
405    pub fn as_bin_view(self) -> Option<BinColumnView<'a>> {
406        if let Self::Binary(view) = self {
407            Some(view)
408        } else {
409            None
410        }
411    }
412
413    /// Extract the array type from an [`AnySlice`].
414    pub fn as_slice<I: Item>(self) -> Option<&'a [I]> {
415        I::as_slice(self)
416    }
417
418    /// Extract the typed nullable buffer from an [`AnySlice`].
419    pub fn as_nullable_slice<I: Item>(self) -> Option<NullableSlice<'a, I>> {
420        I::as_nullable_slice(self)
421    }
422}
423
424unsafe impl<'a> BoundInputSlice<'a> for AnyBuffer {
425    type SliceMut = AnySliceMut<'a>;
426
427    unsafe fn as_view_mut(
428        &'a mut self,
429        parameter_index: u16,
430        stmt: StatementRef<'a>,
431    ) -> Self::SliceMut {
432        let num_rows = self.capacity();
433        match self {
434            AnyBuffer::Binary(column) => {
435                AnySliceMut::Binary(column.as_view_mut(parameter_index, stmt))
436            }
437            AnyBuffer::Text(column) => AnySliceMut::Text(column.as_view_mut(parameter_index, stmt)),
438            AnyBuffer::WText(column) => {
439                AnySliceMut::WText(column.as_view_mut(parameter_index, stmt))
440            }
441            AnyBuffer::Date(column) => AnySliceMut::Date(column),
442            AnyBuffer::Time(column) => AnySliceMut::Time(column),
443            AnyBuffer::Timestamp(column) => AnySliceMut::Timestamp(column),
444            AnyBuffer::F64(column) => AnySliceMut::F64(column),
445            AnyBuffer::F32(column) => AnySliceMut::F32(column),
446            AnyBuffer::I8(column) => AnySliceMut::I8(column),
447            AnyBuffer::I16(column) => AnySliceMut::I16(column),
448            AnyBuffer::I32(column) => AnySliceMut::I32(column),
449            AnyBuffer::I64(column) => AnySliceMut::I64(column),
450            AnyBuffer::U8(column) => AnySliceMut::U8(column),
451            AnyBuffer::Bit(column) => AnySliceMut::Bit(column),
452            AnyBuffer::NullableDate(column) => AnySliceMut::NullableDate(column.writer_n(num_rows)),
453            AnyBuffer::NullableTime(column) => AnySliceMut::NullableTime(column.writer_n(num_rows)),
454            AnyBuffer::NullableTimestamp(column) => {
455                AnySliceMut::NullableTimestamp(column.writer_n(num_rows))
456            }
457            AnyBuffer::NullableF64(column) => AnySliceMut::NullableF64(column.writer_n(num_rows)),
458            AnyBuffer::NullableF32(column) => AnySliceMut::NullableF32(column.writer_n(num_rows)),
459            AnyBuffer::NullableI8(column) => AnySliceMut::NullableI8(column.writer_n(num_rows)),
460            AnyBuffer::NullableI16(column) => AnySliceMut::NullableI16(column.writer_n(num_rows)),
461            AnyBuffer::NullableI32(column) => AnySliceMut::NullableI32(column.writer_n(num_rows)),
462            AnyBuffer::NullableI64(column) => AnySliceMut::NullableI64(column.writer_n(num_rows)),
463            AnyBuffer::NullableU8(column) => AnySliceMut::NullableU8(column.writer_n(num_rows)),
464            AnyBuffer::NullableBit(column) => AnySliceMut::NullableBit(column.writer_n(num_rows)),
465        }
466    }
467}
468
469/// A mutable slice of an input buffer, with runtime type information. Edit values in this slice in
470/// order to send parameters in bulk to a database.
471pub enum AnySliceMut<'a> {
472    Text(TextColumnSliceMut<'a, u8>),
473    /// Nullable character data encoded in UTF-16.
474    WText(TextColumnSliceMut<'a, u16>),
475    Binary(BinColumnSliceMut<'a>),
476    Date(&'a mut [Date]),
477    Time(&'a mut [Time]),
478    Timestamp(&'a mut [Timestamp]),
479    F64(&'a mut [f64]),
480    F32(&'a mut [f32]),
481    I8(&'a mut [i8]),
482    I16(&'a mut [i16]),
483    I32(&'a mut [i32]),
484    I64(&'a mut [i64]),
485    U8(&'a mut [u8]),
486    Bit(&'a mut [Bit]),
487    NullableDate(NullableSliceMut<'a, Date>),
488    NullableTime(NullableSliceMut<'a, Time>),
489    NullableTimestamp(NullableSliceMut<'a, Timestamp>),
490    NullableF64(NullableSliceMut<'a, f64>),
491    NullableF32(NullableSliceMut<'a, f32>),
492    NullableI8(NullableSliceMut<'a, i8>),
493    NullableI16(NullableSliceMut<'a, i16>),
494    NullableI32(NullableSliceMut<'a, i32>),
495    NullableI64(NullableSliceMut<'a, i64>),
496    NullableU8(NullableSliceMut<'a, u8>),
497    NullableBit(NullableSliceMut<'a, Bit>),
498}
499
500impl<'a> AnySliceMut<'a> {
501    /// This method is useful if you expect the variant to be [`AnySliceMut::Binary`]. It allows you
502    /// to unwrap the inner column view without explictly matching it.
503    pub fn as_bin_view(self) -> Option<BinColumnSliceMut<'a>> {
504        if let Self::Binary(view) = self {
505            Some(view)
506        } else {
507            None
508        }
509    }
510
511    /// This method is useful if you expect the variant to be [`AnySliceMut::Text`]. It allows you
512    /// to unwrap the inner column view without explictly matching it.
513    pub fn as_text_view(self) -> Option<TextColumnSliceMut<'a, u8>> {
514        if let Self::Text(view) = self {
515            Some(view)
516        } else {
517            None
518        }
519    }
520
521    /// This method is useful if you expect the variant to be [`AnySliceMut::WText`]. It allows you
522    /// to unwrap the inner column view without explictly matching it.
523    pub fn as_w_text_view(self) -> Option<TextColumnSliceMut<'a, u16>> {
524        if let Self::WText(view) = self {
525            Some(view)
526        } else {
527            None
528        }
529    }
530
531    /// Extract the array type from an [`AnySliceMut`].
532    pub fn as_slice<I: Item>(self) -> Option<&'a mut [I]> {
533        I::as_slice_mut(self)
534    }
535
536    /// Extract the typed nullable buffer from an [`AnySliceMut`].
537    pub fn as_nullable_slice<I: Item>(self) -> Option<NullableSliceMut<'a, I>> {
538        I::as_nullable_slice_mut(self)
539    }
540}
541
542unsafe impl ColumnBuffer for AnyBuffer {
543    type View<'a> = AnySlice<'a>;
544
545    fn capacity(&self) -> usize {
546        match self {
547            AnyBuffer::Binary(col) => col.capacity(),
548            AnyBuffer::Text(col) => col.capacity(),
549            AnyBuffer::WText(col) => col.capacity(),
550            AnyBuffer::Date(col) => col.capacity(),
551            AnyBuffer::Time(col) => col.capacity(),
552            AnyBuffer::Timestamp(col) => col.capacity(),
553            AnyBuffer::F64(col) => col.capacity(),
554            AnyBuffer::F32(col) => col.capacity(),
555            AnyBuffer::I8(col) => col.capacity(),
556            AnyBuffer::I16(col) => col.capacity(),
557            AnyBuffer::I32(col) => col.capacity(),
558            AnyBuffer::I64(col) => col.capacity(),
559            AnyBuffer::U8(col) => col.capacity(),
560            AnyBuffer::Bit(col) => col.capacity(),
561            AnyBuffer::NullableDate(col) => col.capacity(),
562            AnyBuffer::NullableTime(col) => col.capacity(),
563            AnyBuffer::NullableTimestamp(col) => col.capacity(),
564            AnyBuffer::NullableF64(col) => col.capacity(),
565            AnyBuffer::NullableF32(col) => col.capacity(),
566            AnyBuffer::NullableI8(col) => col.capacity(),
567            AnyBuffer::NullableI16(col) => col.capacity(),
568            AnyBuffer::NullableI32(col) => col.capacity(),
569            AnyBuffer::NullableI64(col) => col.capacity(),
570            AnyBuffer::NullableU8(col) => col.capacity(),
571            AnyBuffer::NullableBit(col) => col.capacity(),
572        }
573    }
574
575    fn view(&self, valid_rows: usize) -> AnySlice {
576        match self {
577            AnyBuffer::Binary(col) => AnySlice::Binary(col.view(valid_rows)),
578            AnyBuffer::Text(col) => AnySlice::Text(col.view(valid_rows)),
579            AnyBuffer::WText(col) => AnySlice::WText(col.view(valid_rows)),
580            AnyBuffer::Date(col) => AnySlice::Date(&col[0..valid_rows]),
581            AnyBuffer::Time(col) => AnySlice::Time(&col[0..valid_rows]),
582            AnyBuffer::Timestamp(col) => AnySlice::Timestamp(&col[0..valid_rows]),
583            AnyBuffer::F64(col) => AnySlice::F64(&col[0..valid_rows]),
584            AnyBuffer::F32(col) => AnySlice::F32(&col[0..valid_rows]),
585            AnyBuffer::I8(col) => AnySlice::I8(&col[0..valid_rows]),
586            AnyBuffer::I16(col) => AnySlice::I16(&col[0..valid_rows]),
587            AnyBuffer::I32(col) => AnySlice::I32(&col[0..valid_rows]),
588            AnyBuffer::I64(col) => AnySlice::I64(&col[0..valid_rows]),
589            AnyBuffer::U8(col) => AnySlice::U8(&col[0..valid_rows]),
590            AnyBuffer::Bit(col) => AnySlice::Bit(&col[0..valid_rows]),
591            AnyBuffer::NullableDate(col) => AnySlice::NullableDate(col.iter(valid_rows)),
592            AnyBuffer::NullableTime(col) => AnySlice::NullableTime(col.iter(valid_rows)),
593            AnyBuffer::NullableTimestamp(col) => AnySlice::NullableTimestamp(col.iter(valid_rows)),
594            AnyBuffer::NullableF64(col) => AnySlice::NullableF64(col.iter(valid_rows)),
595            AnyBuffer::NullableF32(col) => AnySlice::NullableF32(col.iter(valid_rows)),
596            AnyBuffer::NullableI8(col) => AnySlice::NullableI8(col.iter(valid_rows)),
597            AnyBuffer::NullableI16(col) => AnySlice::NullableI16(col.iter(valid_rows)),
598            AnyBuffer::NullableI32(col) => AnySlice::NullableI32(col.iter(valid_rows)),
599            AnyBuffer::NullableI64(col) => AnySlice::NullableI64(col.iter(valid_rows)),
600            AnyBuffer::NullableU8(col) => AnySlice::NullableU8(col.iter(valid_rows)),
601            AnyBuffer::NullableBit(col) => AnySlice::NullableBit(col.iter(valid_rows)),
602        }
603    }
604
605    /// Fills the column with the default representation of values, between `from` and `to` index.
606    fn fill_default(&mut self, from: usize, to: usize) {
607        match self {
608            AnyBuffer::Binary(col) => col.fill_null(from, to),
609            AnyBuffer::Text(col) => col.fill_null(from, to),
610            AnyBuffer::WText(col) => col.fill_null(from, to),
611            AnyBuffer::Date(col) => Self::fill_default_slice(&mut col[from..to]),
612            AnyBuffer::Time(col) => Self::fill_default_slice(&mut col[from..to]),
613            AnyBuffer::Timestamp(col) => Self::fill_default_slice(&mut col[from..to]),
614            AnyBuffer::F64(col) => Self::fill_default_slice(&mut col[from..to]),
615            AnyBuffer::F32(col) => Self::fill_default_slice(&mut col[from..to]),
616            AnyBuffer::I8(col) => Self::fill_default_slice(&mut col[from..to]),
617            AnyBuffer::I16(col) => Self::fill_default_slice(&mut col[from..to]),
618            AnyBuffer::I32(col) => Self::fill_default_slice(&mut col[from..to]),
619            AnyBuffer::I64(col) => Self::fill_default_slice(&mut col[from..to]),
620            AnyBuffer::U8(col) => Self::fill_default_slice(&mut col[from..to]),
621            AnyBuffer::Bit(col) => Self::fill_default_slice(&mut col[from..to]),
622            AnyBuffer::NullableDate(col) => col.fill_null(from, to),
623            AnyBuffer::NullableTime(col) => col.fill_null(from, to),
624            AnyBuffer::NullableTimestamp(col) => col.fill_null(from, to),
625            AnyBuffer::NullableF64(col) => col.fill_null(from, to),
626            AnyBuffer::NullableF32(col) => col.fill_null(from, to),
627            AnyBuffer::NullableI8(col) => col.fill_null(from, to),
628            AnyBuffer::NullableI16(col) => col.fill_null(from, to),
629            AnyBuffer::NullableI32(col) => col.fill_null(from, to),
630            AnyBuffer::NullableI64(col) => col.fill_null(from, to),
631            AnyBuffer::NullableU8(col) => col.fill_null(from, to),
632            AnyBuffer::NullableBit(col) => col.fill_null(from, to),
633        }
634    }
635
636    fn has_truncated_values(&self, num_rows: usize) -> Option<Indicator> {
637        match self {
638            AnyBuffer::Binary(col) => col.has_truncated_values(num_rows),
639            AnyBuffer::Text(col) => col.has_truncated_values(num_rows),
640            AnyBuffer::WText(col) => col.has_truncated_values(num_rows),
641            _ => None,
642        }
643    }
644}
645
646#[cfg(test)]
647mod tests {
648    use crate::buffers::{AnySlice, AnySliceMut, ColumnBuffer};
649
650    use super::AnyBuffer;
651
652    #[test]
653    fn slice_should_only_contain_part_of_the_buffer() {
654        let buffer = AnyBuffer::I32(vec![1, 2, 3]);
655
656        let view = buffer.view(2);
657
658        assert_eq!(Some([1, 2].as_slice()), view.as_slice::<i32>());
659    }
660
661    #[test]
662    fn slice_should_be_none_if_types_mismatch() {
663        let buffer = [1, 2, 3];
664        let view = AnySlice::I32(&buffer);
665        assert_eq!(None, view.as_slice::<i16>());
666    }
667
668    #[test]
669    fn slice_mut_should_be_none_if_types_mismatch() {
670        let mut buffer = [1, 2, 3];
671        let view = AnySliceMut::I32(&mut buffer);
672        assert_eq!(None, view.as_slice::<i16>());
673    }
674
675    #[test]
676    fn nullable_slice_should_be_none_if_buffer_is_non_nullable() {
677        let buffer = [1, 2, 3];
678        let view = AnySlice::I32(&buffer);
679        assert!(view.as_nullable_slice::<i32>().is_none());
680    }
681
682    #[test]
683    fn nullable_slice_mut_should_be_none_if_buffer_is_non_nullable() {
684        let mut buffer = [1, 2, 3];
685        let view = AnySliceMut::I32(&mut buffer);
686        assert!(view.as_nullable_slice::<i32>().is_none());
687    }
688}