proof_of_sql/base/database/
column.rs

1use super::{LiteralValue, OwnedColumn, TableRef};
2use crate::base::{
3    math::decimal::Precision,
4    scalar::{Scalar, ScalarExt},
5    slice_ops::slice_cast_with,
6};
7use alloc::vec::Vec;
8use bumpalo::Bump;
9use core::{
10    fmt,
11    fmt::{Display, Formatter},
12    mem::size_of,
13};
14use proof_of_sql_parser::posql_time::{PoSQLTimeUnit, PoSQLTimeZone};
15use serde::{Deserialize, Serialize};
16use sqlparser::ast::Ident;
17
18/// Represents a read-only view of a column in an in-memory,
19/// column-oriented database.
20///
21/// Note: The types here should correspond to native SQL database types.
22/// See `<https://ignite.apache.org/docs/latest/sql-reference/data-types>` for
23/// a description of the native types used by Apache Ignite.
24#[derive(Debug, Eq, PartialEq, Clone, Copy)]
25#[non_exhaustive]
26pub enum Column<'a, S: Scalar> {
27    /// Boolean columns
28    Boolean(&'a [bool]),
29    /// u8 columns
30    Uint8(&'a [u8]),
31    /// i8 columns
32    TinyInt(&'a [i8]),
33    /// i16 columns
34    SmallInt(&'a [i16]),
35    /// i32 columns
36    Int(&'a [i32]),
37    /// i64 columns
38    BigInt(&'a [i64]),
39    /// i128 columns
40    Int128(&'a [i128]),
41    /// Decimal columns with a max width of 252 bits
42    ///  - the backing store maps to the type `S`
43    Decimal75(Precision, i8, &'a [S]),
44    /// Scalar columns
45    Scalar(&'a [S]),
46    /// String columns
47    ///  - the first element maps to the str values.
48    ///  - the second element maps to the str hashes (see [`crate::base::scalar::Scalar`]).
49    VarChar((&'a [&'a str], &'a [S])),
50    /// Timestamp columns with timezone
51    /// - the first element maps to the stored `TimeUnit`
52    /// - the second element maps to a timezone
53    /// - the third element maps to columns of timeunits since unix epoch
54    TimestampTZ(PoSQLTimeUnit, PoSQLTimeZone, &'a [i64]),
55    /// Variable length binary columns
56    VarBinary((&'a [&'a [u8]], &'a [S])),
57}
58
59impl<'a, S: Scalar> Column<'a, S> {
60    /// Provides the column type associated with the column
61    #[must_use]
62    pub fn column_type(&self) -> ColumnType {
63        match self {
64            Self::Boolean(_) => ColumnType::Boolean,
65            Self::Uint8(_) => ColumnType::Uint8,
66            Self::TinyInt(_) => ColumnType::TinyInt,
67            Self::SmallInt(_) => ColumnType::SmallInt,
68            Self::Int(_) => ColumnType::Int,
69            Self::BigInt(_) => ColumnType::BigInt,
70            Self::VarChar(_) => ColumnType::VarChar,
71            Self::Int128(_) => ColumnType::Int128,
72            Self::Scalar(_) => ColumnType::Scalar,
73            Self::Decimal75(precision, scale, _) => ColumnType::Decimal75(*precision, *scale),
74            Self::TimestampTZ(time_unit, timezone, _) => {
75                ColumnType::TimestampTZ(*time_unit, *timezone)
76            }
77            Self::VarBinary(..) => ColumnType::VarBinary,
78        }
79    }
80    /// Returns the length of the column.
81    /// # Panics
82    /// this function requires that `col` and `scals` have the same length.
83    #[must_use]
84    pub fn len(&self) -> usize {
85        match self {
86            Self::Boolean(col) => col.len(),
87            Self::Uint8(col) => col.len(),
88            Self::TinyInt(col) => col.len(),
89            Self::SmallInt(col) => col.len(),
90            Self::Int(col) => col.len(),
91            Self::BigInt(col) | Self::TimestampTZ(_, _, col) => col.len(),
92            Self::VarChar((col, scals)) => {
93                assert_eq!(col.len(), scals.len());
94                col.len()
95            }
96            Self::VarBinary((col, scals)) => {
97                assert_eq!(col.len(), scals.len());
98                col.len()
99            }
100            Self::Int128(col) => col.len(),
101            Self::Scalar(col) | Self::Decimal75(_, _, col) => col.len(),
102        }
103    }
104    /// Returns `true` if the column has no elements.
105    #[must_use]
106    pub fn is_empty(&self) -> bool {
107        self.len() == 0
108    }
109
110    /// Generate a constant column from a literal value with a given length
111    pub fn from_literal_with_length(
112        literal: &LiteralValue,
113        length: usize,
114        alloc: &'a Bump,
115    ) -> Self {
116        match literal {
117            LiteralValue::Boolean(value) => {
118                Column::Boolean(alloc.alloc_slice_fill_copy(length, *value))
119            }
120            LiteralValue::Uint8(value) => {
121                Column::Uint8(alloc.alloc_slice_fill_copy(length, *value))
122            }
123            LiteralValue::TinyInt(value) => {
124                Column::TinyInt(alloc.alloc_slice_fill_copy(length, *value))
125            }
126            LiteralValue::SmallInt(value) => {
127                Column::SmallInt(alloc.alloc_slice_fill_copy(length, *value))
128            }
129            LiteralValue::Int(value) => Column::Int(alloc.alloc_slice_fill_copy(length, *value)),
130            LiteralValue::BigInt(value) => {
131                Column::BigInt(alloc.alloc_slice_fill_copy(length, *value))
132            }
133            LiteralValue::Int128(value) => {
134                Column::Int128(alloc.alloc_slice_fill_copy(length, *value))
135            }
136            LiteralValue::Scalar(value) => {
137                Column::Scalar(alloc.alloc_slice_fill_copy(length, (*value).into()))
138            }
139            LiteralValue::Decimal75(precision, scale, value) => Column::Decimal75(
140                *precision,
141                *scale,
142                alloc.alloc_slice_fill_copy(length, value.into_scalar()),
143            ),
144            LiteralValue::TimeStampTZ(tu, tz, value) => {
145                Column::TimestampTZ(*tu, *tz, alloc.alloc_slice_fill_copy(length, *value))
146            }
147            LiteralValue::VarChar(string) => Column::VarChar((
148                alloc.alloc_slice_fill_with(length, |_| alloc.alloc_str(string) as &str),
149                alloc.alloc_slice_fill_copy(length, S::from(string)),
150            )),
151        }
152    }
153
154    /// Generate a `Int128` `rho` column [0, 1, 2, ..., length - 1]
155    pub fn rho(length: usize, alloc: &'a Bump) -> Self {
156        let raw_rho = (0..length as i128).collect::<Vec<_>>();
157        let rho = alloc.alloc_slice_copy(raw_rho.as_slice());
158        Column::<S>::Int128(rho as &[_])
159    }
160
161    /// Convert an `OwnedColumn` to a `Column`
162    pub fn from_owned_column(owned_column: &'a OwnedColumn<S>, alloc: &'a Bump) -> Self {
163        match owned_column {
164            OwnedColumn::Boolean(col) => Column::Boolean(col.as_slice()),
165            OwnedColumn::Uint8(col) => Column::Uint8(col.as_slice()),
166            OwnedColumn::TinyInt(col) => Column::TinyInt(col.as_slice()),
167            OwnedColumn::SmallInt(col) => Column::SmallInt(col.as_slice()),
168            OwnedColumn::Int(col) => Column::Int(col.as_slice()),
169            OwnedColumn::BigInt(col) => Column::BigInt(col.as_slice()),
170            OwnedColumn::Int128(col) => Column::Int128(col.as_slice()),
171            OwnedColumn::Decimal75(precision, scale, col) => {
172                Column::Decimal75(*precision, *scale, col.as_slice())
173            }
174            OwnedColumn::Scalar(col) => Column::Scalar(col.as_slice()),
175            OwnedColumn::VarChar(col) => {
176                let scalars = col.iter().map(S::from).collect::<Vec<_>>();
177                let strs = col
178                    .iter()
179                    .map(|s| s.as_str() as &'a str)
180                    .collect::<Vec<_>>();
181                Column::VarChar((
182                    alloc.alloc_slice_clone(strs.as_slice()),
183                    alloc.alloc_slice_copy(scalars.as_slice()),
184                ))
185            }
186            OwnedColumn::VarBinary(col) => {
187                let scalars = col
188                    .iter()
189                    .map(|b| S::from_byte_slice_via_hash(b))
190                    .collect::<Vec<_>>();
191                let bytes = col.iter().map(|s| s as &'a [u8]).collect::<Vec<_>>();
192                Column::VarBinary((
193                    alloc.alloc_slice_clone(&bytes),
194                    alloc.alloc_slice_copy(scalars.as_slice()),
195                ))
196            }
197            OwnedColumn::TimestampTZ(tu, tz, col) => Column::TimestampTZ(*tu, *tz, col.as_slice()),
198        }
199    }
200
201    /// Returns the column as a slice of booleans if it is a boolean column. Otherwise, returns None.
202    pub(crate) fn as_boolean(&self) -> Option<&'a [bool]> {
203        match self {
204            Self::Boolean(col) => Some(col),
205            _ => None,
206        }
207    }
208
209    /// Returns the column as a slice of u8 if it is a uint8 column. Otherwise, returns None.
210    pub(crate) fn as_uint8(&self) -> Option<&'a [u8]> {
211        match self {
212            Self::Uint8(col) => Some(col),
213            _ => None,
214        }
215    }
216
217    /// Returns the column as a slice of i8 if it is a tinyint column. Otherwise, returns None.
218    pub(crate) fn as_tinyint(&self) -> Option<&'a [i8]> {
219        match self {
220            Self::TinyInt(col) => Some(col),
221            _ => None,
222        }
223    }
224
225    /// Returns the column as a slice of i16 if it is a smallint column. Otherwise, returns None.
226    pub(crate) fn as_smallint(&self) -> Option<&'a [i16]> {
227        match self {
228            Self::SmallInt(col) => Some(col),
229            _ => None,
230        }
231    }
232
233    /// Returns the column as a slice of i32 if it is an int column. Otherwise, returns None.
234    pub(crate) fn as_int(&self) -> Option<&'a [i32]> {
235        match self {
236            Self::Int(col) => Some(col),
237            _ => None,
238        }
239    }
240
241    /// Returns the column as a slice of i64 if it is a bigint column. Otherwise, returns None.
242    pub(crate) fn as_bigint(&self) -> Option<&'a [i64]> {
243        match self {
244            Self::BigInt(col) => Some(col),
245            _ => None,
246        }
247    }
248
249    /// Returns the column as a slice of i128 if it is an int128 column. Otherwise, returns None.
250    pub(crate) fn as_int128(&self) -> Option<&'a [i128]> {
251        match self {
252            Self::Int128(col) => Some(col),
253            _ => None,
254        }
255    }
256
257    /// Returns the column as a slice of scalars if it is a scalar column. Otherwise, returns None.
258    pub(crate) fn as_scalar(&self) -> Option<&'a [S]> {
259        match self {
260            Self::Scalar(col) => Some(col),
261            _ => None,
262        }
263    }
264
265    /// Returns the column as a slice of scalars if it is a decimal75 column. Otherwise, returns None.
266    pub(crate) fn as_decimal75(&self) -> Option<&'a [S]> {
267        match self {
268            Self::Decimal75(_, _, col) => Some(col),
269            _ => None,
270        }
271    }
272
273    /// Returns the column as a slice of strings and a slice of scalars if it is a varchar column. Otherwise, returns None.
274    pub(crate) fn as_varchar(&self) -> Option<(&'a [&'a str], &'a [S])> {
275        match self {
276            Self::VarChar((col, scals)) => Some((col, scals)),
277            _ => None,
278        }
279    }
280
281    /// Returns the column as a slice of strings and a slice of scalars if it is a varchar column. Otherwise, returns None.
282    pub(crate) fn as_varbinary(&self) -> Option<(&'a [&'a [u8]], &'a [S])> {
283        match self {
284            Self::VarBinary((col, scals)) => Some((col, scals)),
285            _ => None,
286        }
287    }
288
289    /// Returns the column as a slice of i64 if it is a timestamp column. Otherwise, returns None.
290    pub(crate) fn as_timestamptz(&self) -> Option<&'a [i64]> {
291        match self {
292            Self::TimestampTZ(_, _, col) => Some(col),
293            _ => None,
294        }
295    }
296
297    /// Returns element at index as scalar
298    ///
299    /// Note that if index is out of bounds, this function will return None
300    pub(crate) fn scalar_at(&self, index: usize) -> Option<S> {
301        (index < self.len()).then_some(match self {
302            Self::Boolean(col) => S::from(col[index]),
303            Self::Uint8(col) => S::from(col[index]),
304            Self::TinyInt(col) => S::from(col[index]),
305            Self::SmallInt(col) => S::from(col[index]),
306            Self::Int(col) => S::from(col[index]),
307            Self::BigInt(col) | Self::TimestampTZ(_, _, col) => S::from(col[index]),
308            Self::Int128(col) => S::from(col[index]),
309            Self::Scalar(col) | Self::Decimal75(_, _, col) => col[index],
310            Self::VarChar((_, scals)) | Self::VarBinary((_, scals)) => scals[index],
311        })
312    }
313
314    /// Convert a column to a vector of Scalar values with scaling
315    #[allow(clippy::missing_panics_doc)]
316    pub(crate) fn to_scalar_with_scaling(self, scale: i8) -> Vec<S> {
317        let scale_factor = S::pow10(u8::try_from(scale).expect("Upscale factor is nonnegative"));
318        match self {
319            Self::Boolean(col) => slice_cast_with(col, |b| S::from(b) * scale_factor),
320            Self::Decimal75(_, _, col) => slice_cast_with(col, |s| *s * scale_factor),
321            Self::VarChar((_, values)) => slice_cast_with(values, |s| *s * scale_factor),
322            Self::VarBinary((_, values)) => slice_cast_with(values, |s| *s * scale_factor),
323            Self::Uint8(col) => slice_cast_with(col, |i| S::from(i) * scale_factor),
324            Self::TinyInt(col) => slice_cast_with(col, |i| S::from(i) * scale_factor),
325            Self::SmallInt(col) => slice_cast_with(col, |i| S::from(i) * scale_factor),
326            Self::Int(col) => slice_cast_with(col, |i| S::from(i) * scale_factor),
327            Self::BigInt(col) => slice_cast_with(col, |i| S::from(i) * scale_factor),
328            Self::Int128(col) => slice_cast_with(col, |i| S::from(i) * scale_factor),
329            Self::Scalar(col) => slice_cast_with(col, |i| S::from(i) * scale_factor),
330            Self::TimestampTZ(_, _, col) => slice_cast_with(col, |i| S::from(i) * scale_factor),
331        }
332    }
333}
334
335/// Represents the supported data types of a column in an in-memory,
336/// column-oriented database.
337///
338/// See `<https://ignite.apache.org/docs/latest/sql-reference/data-types>` for
339/// a description of the native types used by Apache Ignite.
340#[derive(Eq, PartialEq, Debug, Clone, Hash, Serialize, Deserialize, Copy)]
341#[cfg_attr(test, derive(proptest_derive::Arbitrary))]
342pub enum ColumnType {
343    /// Mapped to bool
344    #[serde(alias = "BOOLEAN", alias = "boolean")]
345    Boolean,
346    /// Mapped to u8
347    #[serde(alias = "UINT8", alias = "uint8")]
348    Uint8,
349    /// Mapped to i8
350    #[serde(alias = "TINYINT", alias = "tinyint")]
351    TinyInt,
352    /// Mapped to i16
353    #[serde(alias = "SMALLINT", alias = "smallint")]
354    SmallInt,
355    /// Mapped to i32
356    #[serde(alias = "INT", alias = "int")]
357    Int,
358    /// Mapped to i64
359    #[serde(alias = "BIGINT", alias = "bigint")]
360    BigInt,
361    /// Mapped to i128
362    #[serde(rename = "Decimal", alias = "DECIMAL", alias = "decimal")]
363    Int128,
364    /// Mapped to String
365    #[serde(alias = "VARCHAR", alias = "varchar")]
366    VarChar,
367    /// Mapped to i256
368    #[serde(rename = "Decimal75", alias = "DECIMAL75", alias = "decimal75")]
369    Decimal75(Precision, i8),
370    /// Mapped to i64
371    #[serde(alias = "TIMESTAMP", alias = "timestamp")]
372    #[cfg_attr(test, proptest(skip))]
373    TimestampTZ(PoSQLTimeUnit, PoSQLTimeZone),
374    /// Mapped to `S`
375    #[serde(alias = "SCALAR", alias = "scalar")]
376    #[cfg_attr(test, proptest(skip))]
377    Scalar,
378    /// Mapped to [u8]
379    #[serde(alias = "BINARY", alias = "BINARY")]
380    VarBinary,
381}
382
383impl ColumnType {
384    /// Returns true if this column is numeric and false otherwise
385    #[must_use]
386    pub fn is_numeric(&self) -> bool {
387        matches!(
388            self,
389            ColumnType::Uint8
390                | ColumnType::TinyInt
391                | ColumnType::SmallInt
392                | ColumnType::Int
393                | ColumnType::BigInt
394                | ColumnType::Int128
395                | ColumnType::Scalar
396                | ColumnType::Decimal75(_, _)
397        )
398    }
399
400    /// Returns true if this column is an integer and false otherwise
401    #[must_use]
402    pub fn is_integer(&self) -> bool {
403        matches!(
404            self,
405            ColumnType::Uint8
406                | ColumnType::TinyInt
407                | ColumnType::SmallInt
408                | ColumnType::Int
409                | ColumnType::BigInt
410                | ColumnType::Int128
411        )
412    }
413
414    /// Returns the number of bits in the integer type if it is an integer type. Otherwise, return None.
415    fn to_integer_bits(self) -> Option<usize> {
416        match self {
417            ColumnType::Uint8 | ColumnType::TinyInt => Some(8),
418            ColumnType::SmallInt => Some(16),
419            ColumnType::Int => Some(32),
420            ColumnType::BigInt => Some(64),
421            ColumnType::Int128 => Some(128),
422            _ => None,
423        }
424    }
425
426    /// Returns the [`ColumnType`] of the signed integer type with the given number of bits if it is a valid integer type.
427    ///
428    /// Otherwise, return None.
429    fn from_signed_integer_bits(bits: usize) -> Option<Self> {
430        match bits {
431            8 => Some(ColumnType::TinyInt),
432            16 => Some(ColumnType::SmallInt),
433            32 => Some(ColumnType::Int),
434            64 => Some(ColumnType::BigInt),
435            128 => Some(ColumnType::Int128),
436            _ => None,
437        }
438    }
439
440    /// Returns the [`ColumnType`] of the unsigned integer type with the given number of bits if it is a valid integer type.
441    ///
442    /// Otherwise, return None.
443    fn from_unsigned_integer_bits(bits: usize) -> Option<Self> {
444        match bits {
445            8 => Some(ColumnType::Uint8),
446            _ => None,
447        }
448    }
449
450    /// Returns the larger integer type of two [`ColumnType`]s if they are both integers.
451    ///
452    /// If either of the columns is not an integer, return None.
453    #[must_use]
454    pub fn max_integer_type(&self, other: &Self) -> Option<Self> {
455        // If either of the columns is not an integer, return None
456        if !self.is_integer() || !other.is_integer() {
457            return None;
458        }
459        self.to_integer_bits().and_then(|self_bits| {
460            other
461                .to_integer_bits()
462                .and_then(|other_bits| Self::from_signed_integer_bits(self_bits.max(other_bits)))
463        })
464    }
465
466    /// Returns the larger integer type of two [`ColumnType`]s if they are both integers.
467    ///
468    /// If either of the columns is not an integer, return None.
469    #[must_use]
470    pub fn max_unsigned_integer_type(&self, other: &Self) -> Option<Self> {
471        // If either of the columns is not an integer, return None
472        if !self.is_integer() || !other.is_integer() {
473            return None;
474        }
475        self.to_integer_bits().and_then(|self_bits| {
476            other
477                .to_integer_bits()
478                .and_then(|other_bits| Self::from_unsigned_integer_bits(self_bits.max(other_bits)))
479        })
480    }
481
482    /// Returns the precision of a [`ColumnType`] if it is converted to a decimal wrapped in `Some()`. If it can not be converted to a decimal, return None.
483    #[must_use]
484    pub fn precision_value(&self) -> Option<u8> {
485        match self {
486            Self::Uint8 | Self::TinyInt => Some(3_u8),
487            Self::SmallInt => Some(5_u8),
488            Self::Int => Some(10_u8),
489            Self::BigInt | Self::TimestampTZ(_, _) => Some(19_u8),
490            Self::Int128 => Some(39_u8),
491            Self::Decimal75(precision, _) => Some(precision.value()),
492            // Scalars are not in database & are only used for typeless comparisons for testing so we return 0
493            // so that they do not cause errors when used in comparisons.
494            Self::Scalar => Some(0_u8),
495            Self::Boolean | Self::VarChar | Self::VarBinary => None,
496        }
497    }
498    /// Returns scale of a [`ColumnType`] if it is convertible to a decimal wrapped in `Some()`. Otherwise return None.
499    #[must_use]
500    pub fn scale(&self) -> Option<i8> {
501        match self {
502            Self::Decimal75(_, scale) => Some(*scale),
503            Self::TinyInt
504            | Self::Uint8
505            | Self::SmallInt
506            | Self::Int
507            | Self::BigInt
508            | Self::Int128
509            | Self::Scalar => Some(0),
510            Self::Boolean | Self::VarBinary | Self::VarChar => None,
511            Self::TimestampTZ(tu, _) => match tu {
512                PoSQLTimeUnit::Second => Some(0),
513                PoSQLTimeUnit::Millisecond => Some(3),
514                PoSQLTimeUnit::Microsecond => Some(6),
515                PoSQLTimeUnit::Nanosecond => Some(9),
516            },
517        }
518    }
519
520    /// Returns the byte size of the column type.
521    #[must_use]
522    pub fn byte_size(&self) -> usize {
523        match self {
524            Self::Boolean => size_of::<bool>(),
525            Self::Uint8 => size_of::<u8>(),
526            Self::TinyInt => size_of::<i8>(),
527            Self::SmallInt => size_of::<i16>(),
528            Self::Int => size_of::<i32>(),
529            Self::BigInt | Self::TimestampTZ(_, _) => size_of::<i64>(),
530            Self::Int128 => size_of::<i128>(),
531            Self::Scalar | Self::Decimal75(_, _) | Self::VarBinary | Self::VarChar => {
532                size_of::<[u64; 4]>()
533            }
534        }
535    }
536
537    #[allow(clippy::cast_possible_truncation)]
538    /// Returns the bit size of the column type.
539    #[must_use]
540    pub fn bit_size(&self) -> u32 {
541        self.byte_size() as u32 * 8
542    }
543
544    /// Returns if the column type supports signed values.
545    #[must_use]
546    pub const fn is_signed(&self) -> bool {
547        match self {
548            Self::TinyInt
549            | Self::SmallInt
550            | Self::Int
551            | Self::BigInt
552            | Self::Int128
553            | Self::TimestampTZ(_, _) => true,
554            Self::Decimal75(_, _)
555            | Self::Scalar
556            | Self::VarBinary
557            | Self::VarChar
558            | Self::Boolean
559            | Self::Uint8 => false,
560        }
561    }
562
563    /// Returns if the column type supports signed values.
564    #[must_use]
565    pub fn min_scalar<S: Scalar>(&self) -> Option<S> {
566        match self {
567            ColumnType::TinyInt => Some(S::from(i8::MIN)),
568            ColumnType::SmallInt => Some(S::from(i16::MIN)),
569            ColumnType::Int => Some(S::from(i32::MIN)),
570            ColumnType::BigInt => Some(S::from(i64::MIN)),
571            ColumnType::Int128 => Some(S::from(i128::MIN)),
572            _ => None,
573        }
574    }
575}
576
577/// Display the column type as a str name (in all caps)
578impl Display for ColumnType {
579    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
580        match self {
581            ColumnType::Boolean => write!(f, "BOOLEAN"),
582            ColumnType::Uint8 => write!(f, "UINT8"),
583            ColumnType::TinyInt => write!(f, "TINYINT"),
584            ColumnType::SmallInt => write!(f, "SMALLINT"),
585            ColumnType::Int => write!(f, "INT"),
586            ColumnType::BigInt => write!(f, "BIGINT"),
587            ColumnType::Int128 => write!(f, "DECIMAL"),
588            ColumnType::Decimal75(precision, scale) => {
589                write!(
590                    f,
591                    "DECIMAL75(PRECISION: {:?}, SCALE: {scale})",
592                    precision.value()
593                )
594            }
595            ColumnType::VarChar => write!(f, "VARCHAR"),
596            ColumnType::VarBinary => write!(f, "BINARY"),
597            ColumnType::Scalar => write!(f, "SCALAR"),
598            ColumnType::TimestampTZ(timeunit, timezone) => {
599                write!(f, "TIMESTAMP(TIMEUNIT: {timeunit}, TIMEZONE: {timezone})")
600            }
601        }
602    }
603}
604
605/// Reference of a SQL column
606#[derive(Debug, PartialEq, Eq, Clone, Hash, Serialize, Deserialize)]
607pub struct ColumnRef {
608    column_id: Ident,
609    table_ref: TableRef,
610    column_type: ColumnType,
611}
612
613impl ColumnRef {
614    /// Create a new `ColumnRef` from a table, column identifier and column type
615    #[must_use]
616    pub fn new(table_ref: TableRef, column_id: Ident, column_type: ColumnType) -> Self {
617        Self {
618            column_id,
619            table_ref,
620            column_type,
621        }
622    }
623
624    /// Returns the table reference of this column
625    #[must_use]
626    pub fn table_ref(&self) -> TableRef {
627        self.table_ref.clone()
628    }
629
630    /// Returns the column identifier of this column
631    #[must_use]
632    pub fn column_id(&self) -> Ident {
633        self.column_id.clone()
634    }
635
636    /// Returns the column type of this column
637    #[must_use]
638    pub fn column_type(&self) -> &ColumnType {
639        &self.column_type
640    }
641}
642
643/// This type is used to represent the metadata
644/// of a column in a table. Namely: it's name and type.
645///
646/// This is the analog of a `Field` in Apache Arrow.
647#[derive(Debug, PartialEq, Eq, Clone, Hash, Serialize, Deserialize)]
648pub struct ColumnField {
649    name: Ident,
650    data_type: ColumnType,
651}
652
653impl ColumnField {
654    /// Create a new `ColumnField` from a name and a type
655    #[must_use]
656    pub fn new(name: Ident, data_type: ColumnType) -> ColumnField {
657        ColumnField { name, data_type }
658    }
659
660    /// Returns the name of the column
661    #[must_use]
662    pub fn name(&self) -> Ident {
663        self.name.clone()
664    }
665
666    /// Returns the type of the column
667    #[must_use]
668    pub fn data_type(&self) -> ColumnType {
669        self.data_type
670    }
671}
672
673#[cfg(test)]
674mod tests {
675    use super::*;
676    use crate::{base::scalar::test_scalar::TestScalar, proof_primitive::dory::DoryScalar};
677    use alloc::{string::String, vec};
678
679    #[test]
680    fn column_type_serializes_to_string() {
681        let column_type = ColumnType::TimestampTZ(PoSQLTimeUnit::Second, PoSQLTimeZone::utc());
682        let serialized = serde_json::to_string(&column_type).unwrap();
683        assert_eq!(serialized, r#"{"TimestampTZ":["Second",{"offset":0}]}"#);
684
685        let column_type = ColumnType::Boolean;
686        let serialized = serde_json::to_string(&column_type).unwrap();
687        assert_eq!(serialized, r#""Boolean""#);
688
689        let column_type = ColumnType::TinyInt;
690        let serialized = serde_json::to_string(&column_type).unwrap();
691        assert_eq!(serialized, r#""TinyInt""#);
692
693        let column_type = ColumnType::SmallInt;
694        let serialized = serde_json::to_string(&column_type).unwrap();
695        assert_eq!(serialized, r#""SmallInt""#);
696
697        let column_type = ColumnType::Int;
698        let serialized = serde_json::to_string(&column_type).unwrap();
699        assert_eq!(serialized, r#""Int""#);
700
701        let column_type = ColumnType::BigInt;
702        let serialized = serde_json::to_string(&column_type).unwrap();
703        assert_eq!(serialized, r#""BigInt""#);
704
705        let column_type = ColumnType::Int128;
706        let serialized = serde_json::to_string(&column_type).unwrap();
707        assert_eq!(serialized, r#""Decimal""#);
708
709        let column_type = ColumnType::VarChar;
710        let serialized = serde_json::to_string(&column_type).unwrap();
711        assert_eq!(serialized, r#""VarChar""#);
712
713        let column_type = ColumnType::Scalar;
714        let serialized = serde_json::to_string(&column_type).unwrap();
715        assert_eq!(serialized, r#""Scalar""#);
716
717        let column_type = ColumnType::Decimal75(Precision::new(1).unwrap(), 0);
718        let serialized = serde_json::to_string(&column_type).unwrap();
719        assert_eq!(serialized, r#"{"Decimal75":[1,0]}"#);
720    }
721
722    #[test]
723    fn we_can_deserialize_columns_from_valid_strings() {
724        let expected_column_type =
725            ColumnType::TimestampTZ(PoSQLTimeUnit::Second, PoSQLTimeZone::utc());
726        let deserialized: ColumnType =
727            serde_json::from_str(r#"{"TimestampTZ":["Second",{"offset":0}]}"#).unwrap();
728        assert_eq!(deserialized, expected_column_type);
729
730        let expected_column_type = ColumnType::Boolean;
731        let deserialized: ColumnType = serde_json::from_str(r#""Boolean""#).unwrap();
732        assert_eq!(deserialized, expected_column_type);
733
734        let expected_column_type = ColumnType::TinyInt;
735        let deserialized: ColumnType = serde_json::from_str(r#""TinyInt""#).unwrap();
736        assert_eq!(deserialized, expected_column_type);
737
738        let expected_column_type = ColumnType::SmallInt;
739        let deserialized: ColumnType = serde_json::from_str(r#""SmallInt""#).unwrap();
740        assert_eq!(deserialized, expected_column_type);
741
742        let expected_column_type = ColumnType::Int;
743        let deserialized: ColumnType = serde_json::from_str(r#""Int""#).unwrap();
744        assert_eq!(deserialized, expected_column_type);
745
746        let expected_column_type = ColumnType::BigInt;
747        let deserialized: ColumnType = serde_json::from_str(r#""BigInt""#).unwrap();
748        assert_eq!(deserialized, expected_column_type);
749
750        let expected_column_type = ColumnType::TinyInt;
751        let deserialized: ColumnType = serde_json::from_str(r#""TINYINT""#).unwrap();
752        assert_eq!(deserialized, expected_column_type);
753
754        let expected_column_type = ColumnType::SmallInt;
755        let deserialized: ColumnType = serde_json::from_str(r#""SMALLINT""#).unwrap();
756        assert_eq!(deserialized, expected_column_type);
757
758        let expected_column_type = ColumnType::Int128;
759        let deserialized: ColumnType = serde_json::from_str(r#""DECIMAL""#).unwrap();
760        assert_eq!(deserialized, expected_column_type);
761
762        let expected_column_type = ColumnType::Int128;
763        let deserialized: ColumnType = serde_json::from_str(r#""Decimal""#).unwrap();
764        assert_eq!(deserialized, expected_column_type);
765
766        let expected_column_type = ColumnType::VarChar;
767        let deserialized: ColumnType = serde_json::from_str(r#""VarChar""#).unwrap();
768        assert_eq!(deserialized, expected_column_type);
769
770        let expected_column_type = ColumnType::Scalar;
771        let deserialized: ColumnType = serde_json::from_str(r#""SCALAR""#).unwrap();
772        assert_eq!(deserialized, expected_column_type);
773
774        let expected_column_type = ColumnType::Decimal75(Precision::new(75).unwrap(), i8::MAX);
775        let deserialized: ColumnType = serde_json::from_str(r#"{"Decimal75":[75, 127]}"#).unwrap();
776        assert_eq!(deserialized, expected_column_type);
777
778        let expected_column_type =
779            ColumnType::Decimal75(Precision::new(u8::MIN + 1).unwrap(), i8::MIN);
780        let deserialized: ColumnType = serde_json::from_str(r#"{"Decimal75":[1, -128]}"#).unwrap();
781        assert_eq!(deserialized, expected_column_type);
782
783        let expected_column_type = ColumnType::Decimal75(Precision::new(1).unwrap(), 0);
784        let deserialized: ColumnType = serde_json::from_str(r#"{"Decimal75":[1, 0]}"#).unwrap();
785        assert_eq!(deserialized, expected_column_type);
786    }
787
788    #[test]
789    fn we_can_deserialize_columns_from_lowercase_or_uppercase_strings() {
790        assert_eq!(
791            serde_json::from_str::<ColumnType>(r#""boolean""#).unwrap(),
792            ColumnType::Boolean
793        );
794        assert_eq!(
795            serde_json::from_str::<ColumnType>(r#""BOOLEAN""#).unwrap(),
796            ColumnType::Boolean
797        );
798
799        assert_eq!(
800            serde_json::from_str::<ColumnType>(r#""bigint""#).unwrap(),
801            ColumnType::BigInt
802        );
803        assert_eq!(
804            serde_json::from_str::<ColumnType>(r#""BIGINT""#).unwrap(),
805            ColumnType::BigInt
806        );
807        assert_eq!(
808            serde_json::from_str::<ColumnType>(r#""TINYINT""#).unwrap(),
809            ColumnType::TinyInt
810        );
811        assert_eq!(
812            serde_json::from_str::<ColumnType>(r#""tinyint""#).unwrap(),
813            ColumnType::TinyInt
814        );
815        assert_eq!(
816            serde_json::from_str::<ColumnType>(r#""SMALLINT""#).unwrap(),
817            ColumnType::SmallInt
818        );
819        assert_eq!(
820            serde_json::from_str::<ColumnType>(r#""smallint""#).unwrap(),
821            ColumnType::SmallInt
822        );
823        assert_eq!(
824            serde_json::from_str::<ColumnType>(r#""int""#).unwrap(),
825            ColumnType::Int
826        );
827        assert_eq!(
828            serde_json::from_str::<ColumnType>(r#""INT""#).unwrap(),
829            ColumnType::Int
830        );
831        assert_eq!(
832            serde_json::from_str::<ColumnType>(r#""decimal""#).unwrap(),
833            ColumnType::Int128
834        );
835        assert_eq!(
836            serde_json::from_str::<ColumnType>(r#""DECIMAL""#).unwrap(),
837            ColumnType::Int128
838        );
839
840        assert_eq!(
841            serde_json::from_str::<ColumnType>(r#""VARCHAR""#).unwrap(),
842            ColumnType::VarChar
843        );
844        assert_eq!(
845            serde_json::from_str::<ColumnType>(r#""varchar""#).unwrap(),
846            ColumnType::VarChar
847        );
848
849        assert_eq!(
850            serde_json::from_str::<ColumnType>(r#""SCALAR""#).unwrap(),
851            ColumnType::Scalar
852        );
853        assert_eq!(
854            serde_json::from_str::<ColumnType>(r#""scalar""#).unwrap(),
855            ColumnType::Scalar
856        );
857        assert_eq!(
858            serde_json::from_str::<ColumnType>(r#"{"decimal75":[1,0]}"#).unwrap(),
859            ColumnType::Decimal75(Precision::new(1).unwrap(), 0)
860        );
861        assert_eq!(
862            serde_json::from_str::<ColumnType>(r#"{"DECIMAL75":[1,0]}"#).unwrap(),
863            ColumnType::Decimal75(Precision::new(1).unwrap(), 0)
864        );
865
866        assert_eq!(
867            serde_json::from_str::<ColumnType>(r#"{"decimal75":[10,5]}"#).unwrap(),
868            ColumnType::Decimal75(Precision::new(10).unwrap(), 5)
869        );
870
871        assert_eq!(
872            serde_json::from_str::<ColumnType>(r#"{"DECIMAL75":[1,-128]}"#).unwrap(),
873            ColumnType::Decimal75(Precision::new(1).unwrap(), -128)
874        );
875    }
876
877    #[test]
878    fn we_cannot_deserialize_columns_from_invalid_strings() {
879        let deserialized: Result<ColumnType, _> = serde_json::from_str(r#""BooLean""#);
880        assert!(deserialized.is_err());
881
882        let deserialized: Result<ColumnType, _> = serde_json::from_str(r#""Tinyint""#);
883        assert!(deserialized.is_err());
884
885        let deserialized: Result<ColumnType, _> = serde_json::from_str(r#""Smallint""#);
886        assert!(deserialized.is_err());
887
888        let deserialized: Result<ColumnType, _> = serde_json::from_str(r#""iNt""#);
889        assert!(deserialized.is_err());
890
891        let deserialized: Result<ColumnType, _> = serde_json::from_str(r#""Bigint""#);
892        assert!(deserialized.is_err());
893
894        let deserialized: Result<ColumnType, _> = serde_json::from_str(r#""DecImal""#);
895        assert!(deserialized.is_err());
896
897        let deserialized: Result<ColumnType, _> = serde_json::from_str(r#""DecImal75""#);
898        assert!(deserialized.is_err());
899
900        let deserialized: Result<ColumnType, _> =
901            serde_json::from_str(r#"{"TimestampTZ":["Utc","Second"]}"#);
902        assert!(deserialized.is_err());
903
904        let deserialized: Result<ColumnType, _> = serde_json::from_str(r#""Varchar""#);
905        assert!(deserialized.is_err());
906
907        let deserialized: Result<ColumnType, _> = serde_json::from_str(r#""ScaLar""#);
908        assert!(deserialized.is_err());
909    }
910
911    #[test]
912    fn we_can_convert_columntype_to_json_string_and_back() {
913        let boolean = ColumnType::Boolean;
914        let boolean_json = serde_json::to_string(&boolean).unwrap();
915        assert_eq!(boolean_json, "\"Boolean\"");
916        assert_eq!(
917            serde_json::from_str::<ColumnType>(&boolean_json).unwrap(),
918            boolean
919        );
920
921        let tinyint = ColumnType::TinyInt;
922        let tinyint_json = serde_json::to_string(&tinyint).unwrap();
923        assert_eq!(tinyint_json, "\"TinyInt\"");
924        assert_eq!(
925            serde_json::from_str::<ColumnType>(&tinyint_json).unwrap(),
926            tinyint
927        );
928
929        let smallint = ColumnType::SmallInt;
930        let smallint_json = serde_json::to_string(&smallint).unwrap();
931        assert_eq!(smallint_json, "\"SmallInt\"");
932        assert_eq!(
933            serde_json::from_str::<ColumnType>(&smallint_json).unwrap(),
934            smallint
935        );
936
937        let int = ColumnType::Int;
938        let int_json = serde_json::to_string(&int).unwrap();
939        assert_eq!(int_json, "\"Int\"");
940        assert_eq!(serde_json::from_str::<ColumnType>(&int_json).unwrap(), int);
941
942        let bigint = ColumnType::BigInt;
943        let bigint_json = serde_json::to_string(&bigint).unwrap();
944        assert_eq!(bigint_json, "\"BigInt\"");
945        assert_eq!(
946            serde_json::from_str::<ColumnType>(&bigint_json).unwrap(),
947            bigint
948        );
949
950        let int128 = ColumnType::Int128;
951        let int128_json = serde_json::to_string(&int128).unwrap();
952        assert_eq!(int128_json, "\"Decimal\"");
953        assert_eq!(
954            serde_json::from_str::<ColumnType>(&int128_json).unwrap(),
955            int128
956        );
957
958        let varchar = ColumnType::VarChar;
959        let varchar_json = serde_json::to_string(&varchar).unwrap();
960        assert_eq!(varchar_json, "\"VarChar\"");
961        assert_eq!(
962            serde_json::from_str::<ColumnType>(&varchar_json).unwrap(),
963            varchar
964        );
965
966        let scalar = ColumnType::Scalar;
967        let scalar_json = serde_json::to_string(&scalar).unwrap();
968        assert_eq!(scalar_json, "\"Scalar\"");
969        assert_eq!(
970            serde_json::from_str::<ColumnType>(&scalar_json).unwrap(),
971            scalar
972        );
973
974        let decimal75 = ColumnType::Decimal75(Precision::new(75).unwrap(), 0);
975        let decimal75_json = serde_json::to_string(&decimal75).unwrap();
976        assert_eq!(decimal75_json, r#"{"Decimal75":[75,0]}"#);
977        assert_eq!(
978            serde_json::from_str::<ColumnType>(&decimal75_json).unwrap(),
979            decimal75
980        );
981    }
982
983    #[test]
984    fn we_can_get_the_len_of_a_column() {
985        let precision = 10;
986        let scale = 2;
987
988        let scalar_values = [
989            TestScalar::from(1),
990            TestScalar::from(2),
991            TestScalar::from(3),
992        ];
993
994        // Test non-empty columns
995        let column = Column::<DoryScalar>::Boolean(&[true, false, true]);
996        assert_eq!(column.len(), 3);
997        assert!(!column.is_empty());
998
999        let column = Column::<DoryScalar>::TinyInt(&[1, 2, 3]);
1000        assert_eq!(column.len(), 3);
1001        assert!(!column.is_empty());
1002
1003        let column = Column::<TestScalar>::SmallInt(&[1, 2, 3]);
1004        assert_eq!(column.len(), 3);
1005        assert!(!column.is_empty());
1006
1007        let column = Column::<TestScalar>::Int(&[1, 2, 3]);
1008        assert_eq!(column.len(), 3);
1009        assert!(!column.is_empty());
1010
1011        let column = Column::<TestScalar>::BigInt(&[1, 2, 3]);
1012        assert_eq!(column.len(), 3);
1013        assert!(!column.is_empty());
1014
1015        let column = Column::VarChar((&["a", "b", "c"], &scalar_values));
1016        assert_eq!(column.len(), 3);
1017        assert!(!column.is_empty());
1018
1019        let column = Column::<DoryScalar>::Int128(&[1, 2, 3]);
1020        assert_eq!(column.len(), 3);
1021        assert!(!column.is_empty());
1022
1023        let column = Column::Scalar(&scalar_values);
1024        assert_eq!(column.len(), 3);
1025        assert!(!column.is_empty());
1026
1027        let decimal_data = [
1028            TestScalar::from(1),
1029            TestScalar::from(2),
1030            TestScalar::from(3),
1031        ];
1032
1033        let precision = Precision::new(precision).unwrap();
1034        let column = Column::Decimal75(precision, scale, &decimal_data);
1035        assert_eq!(column.len(), 3);
1036        assert!(!column.is_empty());
1037
1038        // Test empty columns
1039        let column = Column::<DoryScalar>::Boolean(&[]);
1040        assert_eq!(column.len(), 0);
1041        assert!(column.is_empty());
1042
1043        let column = Column::<DoryScalar>::TinyInt(&[]);
1044        assert_eq!(column.len(), 0);
1045        assert!(column.is_empty());
1046
1047        let column = Column::<TestScalar>::SmallInt(&[]);
1048        assert_eq!(column.len(), 0);
1049        assert!(column.is_empty());
1050
1051        let column = Column::<TestScalar>::Int(&[]);
1052        assert_eq!(column.len(), 0);
1053        assert!(column.is_empty());
1054
1055        let column = Column::<TestScalar>::BigInt(&[]);
1056        assert_eq!(column.len(), 0);
1057        assert!(column.is_empty());
1058
1059        let column = Column::<DoryScalar>::VarChar((&[], &[]));
1060        assert_eq!(column.len(), 0);
1061        assert!(column.is_empty());
1062
1063        let column = Column::<TestScalar>::Int128(&[]);
1064        assert_eq!(column.len(), 0);
1065        assert!(column.is_empty());
1066
1067        let column = Column::<DoryScalar>::Scalar(&[]);
1068        assert_eq!(column.len(), 0);
1069        assert!(column.is_empty());
1070
1071        let column: Column<'_, TestScalar> = Column::Decimal75(precision, scale, &[]);
1072        assert_eq!(column.len(), 0);
1073        assert!(column.is_empty());
1074    }
1075
1076    #[test]
1077    fn we_can_convert_owned_columns_to_columns_round_trip() {
1078        let alloc = Bump::new();
1079        // Integers
1080        let owned_col: OwnedColumn<TestScalar> = OwnedColumn::Int128(vec![1, 2, 3, 4, 5]);
1081        let col = Column::<TestScalar>::from_owned_column(&owned_col, &alloc);
1082        assert_eq!(col, Column::Int128(&[1, 2, 3, 4, 5]));
1083        let new_owned_col = (&col).into();
1084        assert_eq!(owned_col, new_owned_col);
1085
1086        // Booleans
1087        let owned_col: OwnedColumn<TestScalar> =
1088            OwnedColumn::Boolean(vec![true, false, true, false, true]);
1089        let col = Column::<TestScalar>::from_owned_column(&owned_col, &alloc);
1090        assert_eq!(col, Column::Boolean(&[true, false, true, false, true]));
1091        let new_owned_col = (&col).into();
1092        assert_eq!(owned_col, new_owned_col);
1093
1094        // Strings
1095        let strs = [
1096            "Space and Time",
1097            "Tér és Idő",
1098            "Пространство и время",
1099            "Spațiu și Timp",
1100            "Spazju u Ħin",
1101        ];
1102        let scalars = strs.iter().map(TestScalar::from).collect::<Vec<_>>();
1103        let owned_col = OwnedColumn::VarChar(
1104            strs.iter()
1105                .map(ToString::to_string)
1106                .collect::<Vec<String>>(),
1107        );
1108        let col = Column::<TestScalar>::from_owned_column(&owned_col, &alloc);
1109        assert_eq!(col, Column::VarChar((&strs, &scalars)));
1110        let new_owned_col = (&col).into();
1111        assert_eq!(owned_col, new_owned_col);
1112
1113        // Decimals
1114        let scalars: Vec<TestScalar> = [1, 2, 3, 4, 5].iter().map(TestScalar::from).collect();
1115        let owned_col: OwnedColumn<TestScalar> =
1116            OwnedColumn::Decimal75(Precision::new(75).unwrap(), 127, scalars.clone());
1117        let col = Column::<TestScalar>::from_owned_column(&owned_col, &alloc);
1118        assert_eq!(
1119            col,
1120            Column::Decimal75(Precision::new(75).unwrap(), 127, &scalars)
1121        );
1122        let new_owned_col = (&col).into();
1123        assert_eq!(owned_col, new_owned_col);
1124    }
1125
1126    #[test]
1127    fn we_can_get_the_data_size_of_a_column() {
1128        let column = Column::<DoryScalar>::Boolean(&[true, false, true]);
1129        assert_eq!(column.column_type().byte_size(), 1);
1130        assert_eq!(column.column_type().bit_size(), 8);
1131
1132        let column = Column::<TestScalar>::TinyInt(&[1, 2, 3, 4]);
1133        assert_eq!(column.column_type().byte_size(), 1);
1134        assert_eq!(column.column_type().bit_size(), 8);
1135
1136        let column = Column::<TestScalar>::SmallInt(&[1, 2, 3, 4]);
1137        assert_eq!(column.column_type().byte_size(), 2);
1138        assert_eq!(column.column_type().bit_size(), 16);
1139
1140        let column = Column::<TestScalar>::Int(&[1, 2, 3]);
1141        assert_eq!(column.column_type().byte_size(), 4);
1142        assert_eq!(column.column_type().bit_size(), 32);
1143
1144        let column = Column::<TestScalar>::BigInt(&[1]);
1145        assert_eq!(column.column_type().byte_size(), 8);
1146        assert_eq!(column.column_type().bit_size(), 64);
1147
1148        let column = Column::<DoryScalar>::Int128(&[1, 2]);
1149        assert_eq!(column.column_type().byte_size(), 16);
1150        assert_eq!(column.column_type().bit_size(), 128);
1151
1152        let scalar_values = [
1153            TestScalar::from(1),
1154            TestScalar::from(2),
1155            TestScalar::from(3),
1156        ];
1157
1158        let column = Column::VarChar((&["a", "b", "c", "d", "e"], &scalar_values));
1159        assert_eq!(column.column_type().byte_size(), 32);
1160        assert_eq!(column.column_type().bit_size(), 256);
1161
1162        let column = Column::Scalar(&scalar_values);
1163        assert_eq!(column.column_type().byte_size(), 32);
1164        assert_eq!(column.column_type().bit_size(), 256);
1165
1166        let precision = 10;
1167        let scale = 2;
1168        let decimal_data = [
1169            TestScalar::from(1),
1170            TestScalar::from(2),
1171            TestScalar::from(3),
1172        ];
1173
1174        let precision = Precision::new(precision).unwrap();
1175        let column = Column::Decimal75(precision, scale, &decimal_data);
1176        assert_eq!(column.column_type().byte_size(), 32);
1177        assert_eq!(column.column_type().bit_size(), 256);
1178
1179        let column: Column<'_, DoryScalar> =
1180            Column::TimestampTZ(PoSQLTimeUnit::Second, PoSQLTimeZone::utc(), &[1, 2, 3]);
1181        assert_eq!(column.column_type().byte_size(), 8);
1182        assert_eq!(column.column_type().bit_size(), 64);
1183    }
1184
1185    #[test]
1186    fn we_can_get_length_of_varbinary_column() {
1187        let raw_bytes: &[&[u8]] = &[b"foo", b"bar", b""];
1188        let scalars: Vec<TestScalar> = raw_bytes
1189            .iter()
1190            .map(|b| TestScalar::from_le_bytes_mod_order(b))
1191            .collect();
1192
1193        let column = Column::VarBinary((raw_bytes, &scalars));
1194        assert_eq!(column.len(), 3);
1195        assert!(!column.is_empty());
1196        assert_eq!(column.column_type(), ColumnType::VarBinary);
1197    }
1198
1199    #[test]
1200    fn we_can_convert_varbinary_owned_column_to_column_and_back() {
1201        use bumpalo::Bump;
1202        let alloc = Bump::new();
1203
1204        let owned_varbinary = OwnedColumn::VarBinary(vec![b"abc".to_vec(), b"xyz".to_vec()]);
1205
1206        let column = Column::<TestScalar>::from_owned_column(&owned_varbinary, &alloc);
1207        match column {
1208            Column::VarBinary((bytes, scalars)) => {
1209                assert_eq!(bytes.len(), 2);
1210                assert_eq!(scalars.len(), 2);
1211                assert_eq!(bytes[0], b"abc");
1212                assert_eq!(bytes[1], b"xyz");
1213            }
1214            _ => panic!("Expected VarBinary column"),
1215        }
1216
1217        let round_trip_owned: OwnedColumn<TestScalar> = (&column).into();
1218        assert_eq!(owned_varbinary, round_trip_owned);
1219    }
1220
1221    #[test]
1222    fn we_can_get_min_scalar() {
1223        assert_eq!(
1224            ColumnType::TinyInt.min_scalar(),
1225            Some(TestScalar::from(i8::MIN))
1226        );
1227        assert_eq!(
1228            ColumnType::SmallInt.min_scalar(),
1229            Some(TestScalar::from(i16::MIN))
1230        );
1231        assert_eq!(
1232            ColumnType::Int.min_scalar(),
1233            Some(TestScalar::from(i32::MIN))
1234        );
1235        assert_eq!(
1236            ColumnType::BigInt.min_scalar(),
1237            Some(TestScalar::from(i64::MIN))
1238        );
1239        assert_eq!(
1240            ColumnType::Int128.min_scalar(),
1241            Some(TestScalar::from(i128::MIN))
1242        );
1243        assert_eq!(ColumnType::Uint8.min_scalar::<TestScalar>(), None);
1244        assert_eq!(ColumnType::Scalar.min_scalar::<TestScalar>(), None);
1245        assert_eq!(ColumnType::Boolean.min_scalar::<TestScalar>(), None);
1246        assert_eq!(ColumnType::VarBinary.min_scalar::<TestScalar>(), None);
1247        assert_eq!(
1248            ColumnType::TimestampTZ(PoSQLTimeUnit::Second, PoSQLTimeZone::new(0))
1249                .min_scalar::<TestScalar>(),
1250            None
1251        );
1252        assert_eq!(
1253            ColumnType::Decimal75(Precision::new(1).unwrap(), 1).min_scalar::<TestScalar>(),
1254            None
1255        );
1256        assert_eq!(ColumnType::VarChar.min_scalar::<TestScalar>(), None);
1257    }
1258}