proof_of_sql/base/database/
columnar_value.rs1use crate::base::{
2 database::{Column, ColumnType, LiteralValue},
3 scalar::Scalar,
4};
5use bumpalo::Bump;
6use snafu::Snafu;
7
8#[derive(Debug, Eq, PartialEq, Clone)]
12pub enum ColumnarValue<'a, S: Scalar> {
13 Column(Column<'a, S>),
15 Literal(LiteralValue),
17}
18
19#[derive(Snafu, Debug, PartialEq, Eq)]
21pub enum ColumnarValueError {
22 ColumnLengthMismatch {
24 columnar_value_length: usize,
26 attempt_to_convert_length: usize,
28 },
29}
30
31impl<'a, S: Scalar> ColumnarValue<'a, S> {
32 #[must_use]
34 pub fn column_type(&self) -> ColumnType {
35 match self {
36 Self::Column(column) => column.column_type(),
37 Self::Literal(literal) => literal.column_type(),
38 }
39 }
40
41 pub fn into_column(
43 &self,
44 num_rows: usize,
45 alloc: &'a Bump,
46 ) -> Result<Column<'a, S>, ColumnarValueError> {
47 match self {
48 Self::Column(column) => {
49 if column.len() == num_rows {
50 Ok(*column)
51 } else {
52 Err(ColumnarValueError::ColumnLengthMismatch {
53 columnar_value_length: column.len(),
54 attempt_to_convert_length: num_rows,
55 })
56 }
57 }
58 Self::Literal(literal) => {
59 Ok(Column::from_literal_with_length(literal, num_rows, alloc))
60 }
61 }
62 }
63}
64
65#[cfg(test)]
66mod tests {
67 use super::*;
68 use crate::base::scalar::test_scalar::TestScalar;
69 use core::convert::Into;
70
71 #[test]
72 fn we_can_get_column_type_of_columnar_values() {
73 let column = ColumnarValue::Column(Column::<TestScalar>::Int(&[1, 2, 3]));
74 assert_eq!(column.column_type(), ColumnType::Int);
75
76 let column = ColumnarValue::<TestScalar>::Literal(LiteralValue::Boolean(true));
77 assert_eq!(column.column_type(), ColumnType::Boolean);
78 }
79
80 #[test]
81 fn we_can_transform_columnar_values_into_columns() {
82 let bump = Bump::new();
83
84 let columnar_value = ColumnarValue::Column(Column::<TestScalar>::Int(&[1, 2, 3]));
85 let column = columnar_value.into_column(3, &bump).unwrap();
86 assert_eq!(column, Column::Int(&[1, 2, 3]));
87
88 let columnar_value = ColumnarValue::<TestScalar>::Literal(LiteralValue::Boolean(false));
89 let column = columnar_value.into_column(5, &bump).unwrap();
90 assert_eq!(column, Column::Boolean(&[false; 5]));
91
92 let columnar_value = ColumnarValue::<TestScalar>::Literal(LiteralValue::TinyInt(2));
94 let column = columnar_value.into_column(0, &bump).unwrap();
95 assert_eq!(column, Column::TinyInt(&[]));
96
97 let columnar_value = ColumnarValue::Column(Column::<TestScalar>::SmallInt(&[]));
98 let column = columnar_value.into_column(0, &bump).unwrap();
99 assert_eq!(column, Column::SmallInt(&[]));
100 }
101
102 #[test]
103 fn we_cannot_transform_columnar_values_into_columns_of_different_length() {
104 let bump = Bump::new();
105
106 let columnar_value = ColumnarValue::Column(Column::<TestScalar>::Int(&[1, 2, 3]));
107 let res = columnar_value.into_column(2, &bump);
108 assert_eq!(
109 res,
110 Err(ColumnarValueError::ColumnLengthMismatch {
111 columnar_value_length: 3,
112 attempt_to_convert_length: 2,
113 })
114 );
115
116 let strings = ["a", "b", "c"];
117 let scalars: Vec<TestScalar> = strings.iter().map(Into::into).collect();
118 let columnar_value =
119 ColumnarValue::Column(Column::<TestScalar>::VarChar((&strings, &scalars)));
120 let res = columnar_value.into_column(0, &bump);
121 assert_eq!(
122 res,
123 Err(ColumnarValueError::ColumnLengthMismatch {
124 columnar_value_length: 3,
125 attempt_to_convert_length: 0,
126 })
127 );
128
129 let columnar_value = ColumnarValue::Column(Column::<TestScalar>::Boolean(&[]));
130 let res = columnar_value.into_column(1, &bump);
131 assert_eq!(
132 res,
133 Err(ColumnarValueError::ColumnLengthMismatch {
134 columnar_value_length: 0,
135 attempt_to_convert_length: 1,
136 })
137 );
138 }
139}