proof_of_sql/base/database/
table_utility.rs

1//! Utility functions for creating [`Table`]s and [`Column`]s.
2//! These functions are primarily intended for use in tests.
3//!
4//! # Example
5//! ```
6//! use bumpalo::Bump;
7//! use proof_of_sql::base::{database::table_utility::*, scalar::Curve25519Scalar};
8//! let alloc = Bump::new();
9//! let result = table::<Curve25519Scalar>([
10//!     borrowed_bigint("a", [1, 2, 3], &alloc),
11//!     borrowed_boolean("b", [true, false, true], &alloc),
12//!     borrowed_int128("c", [1, 2, 3], &alloc),
13//!     borrowed_scalar("d", [1, 2, 3], &alloc),
14//!     borrowed_varchar("e", ["a", "b", "c"], &alloc),
15//!     borrowed_decimal75("f", 12, 1, [1, 2, 3], &alloc),
16//! ]);
17//! ```
18use super::{Column, Table, TableOptions};
19use crate::base::scalar::Scalar;
20use alloc::{string::String, vec::Vec};
21use bumpalo::Bump;
22use proof_of_sql_parser::posql_time::{PoSQLTimeUnit, PoSQLTimeZone};
23use sqlparser::ast::Ident;
24
25/// Creates an [`Table`] from a list of `(Ident, Column)` pairs.
26/// This is a convenience wrapper around [`Table::try_from_iter`] primarily for use in tests and
27/// intended to be used along with the other methods in this module (e.g. [`borrowed_bigint`],
28/// [`borrowed_boolean`], etc).
29/// The function will panic under a variety of conditions. See [`Table::try_from_iter`] for more details.
30///
31/// # Example
32/// ```
33/// use bumpalo::Bump;
34/// use proof_of_sql::base::{database::table_utility::*, scalar::Curve25519Scalar};
35/// let alloc = Bump::new();
36/// let result = table::<Curve25519Scalar>([
37///     borrowed_bigint("a", [1, 2, 3], &alloc),
38///     borrowed_boolean("b", [true, false, true], &alloc),
39///     borrowed_int128("c", [1, 2, 3], &alloc),
40///     borrowed_scalar("d", [1, 2, 3], &alloc),
41///     borrowed_varchar("e", ["a", "b", "c"], &alloc),
42///     borrowed_decimal75("f", 12, 1, [1, 2, 3], &alloc),
43/// ]);
44/// ```
45///
46/// # Panics
47/// - Panics if converting the iterator into an `Table<'a, S>` fails.
48pub fn table<'a, S: Scalar>(
49    iter: impl IntoIterator<Item = (Ident, Column<'a, S>)>,
50) -> Table<'a, S> {
51    Table::try_from_iter(iter).unwrap()
52}
53
54/// Creates an [`Table`] from a list of `(Ident, Column)` pairs with a specified row count.
55/// The main reason for this function is to allow for creating tables that may potentially have
56/// no columns, but still have a specified row count.
57///
58/// # Panics
59/// - Panics if the given row count doesn't match the number of rows in any of the columns.
60pub fn table_with_row_count<'a, S: Scalar>(
61    iter: impl IntoIterator<Item = (Ident, Column<'a, S>)>,
62    row_count: usize,
63) -> Table<'a, S> {
64    Table::try_from_iter_with_options(iter, TableOptions::new(Some(row_count))).unwrap()
65}
66
67/// Creates a (Ident, `Column`) pair for a uint8 column.
68/// This is primarily intended for use in conjunction with [`table`].
69/// # Example
70/// ```
71/// use bumpalo::Bump;
72/// use proof_of_sql::base::{database::table_utility::*, scalar::Curve25519Scalar};
73/// let alloc = Bump::new();
74/// let result = table::<Curve25519Scalar>([
75///     borrowed_uint8("a", [1_u8, 2, 3], &alloc),
76/// ]);
77///```
78pub fn borrowed_uint8<S: Scalar>(
79    name: impl Into<Ident>,
80    data: impl IntoIterator<Item = impl Into<u8>>,
81    alloc: &Bump,
82) -> (Ident, Column<'_, S>) {
83    let transformed_data: Vec<u8> = data.into_iter().map(Into::into).collect();
84    let alloc_data = alloc.alloc_slice_copy(&transformed_data);
85    (name.into(), Column::Uint8(alloc_data))
86}
87
88/// Creates a (Ident, `Column`) pair for a tinyint column.
89/// This is primarily intended for use in conjunction with [`table`].
90/// # Example
91/// ```
92/// use bumpalo::Bump;
93/// use proof_of_sql::base::{database::table_utility::*, scalar::Curve25519Scalar};
94/// let alloc = Bump::new();
95/// let result = table::<Curve25519Scalar>([
96///     borrowed_tinyint("a", [1_i8, 2, 3], &alloc),
97/// ]);
98///```
99pub fn borrowed_tinyint<S: Scalar>(
100    name: impl Into<Ident>,
101    data: impl IntoIterator<Item = impl Into<i8>>,
102    alloc: &Bump,
103) -> (Ident, Column<'_, S>) {
104    let transformed_data: Vec<i8> = data.into_iter().map(Into::into).collect();
105    let alloc_data = alloc.alloc_slice_copy(&transformed_data);
106    (name.into(), Column::TinyInt(alloc_data))
107}
108
109/// Creates a `(Ident, Column)` pair for a smallint column.
110/// This is primarily intended for use in conjunction with [`table`].
111///
112/// # Example
113/// ```rust
114/// use bumpalo::Bump;
115/// use proof_of_sql::base::{database::table_utility::*, scalar::Curve25519Scalar};
116/// let alloc = Bump::new();
117/// let result = table::<Curve25519Scalar>([
118///     borrowed_smallint("a", [1_i16, 2, 3], &alloc),
119/// ]);
120/// ```
121///
122pub fn borrowed_smallint<S: Scalar>(
123    name: impl Into<Ident>,
124    data: impl IntoIterator<Item = impl Into<i16>>,
125    alloc: &Bump,
126) -> (Ident, Column<'_, S>) {
127    let transformed_data: Vec<i16> = data.into_iter().map(Into::into).collect();
128    let alloc_data = alloc.alloc_slice_copy(&transformed_data);
129    (name.into(), Column::SmallInt(alloc_data))
130}
131
132/// Creates a `(Ident, Column)` pair for an int column.
133/// This is primarily intended for use in conjunction with [`table`].
134///
135/// # Example
136/// ```rust
137/// use bumpalo::Bump;
138/// use proof_of_sql::base::{database::table_utility::*, scalar::Curve25519Scalar};
139/// let alloc = Bump::new();
140/// let result = table::<Curve25519Scalar>([
141///     borrowed_int("a", [1, 2, 3], &alloc),
142/// ]);
143/// ```
144///
145pub fn borrowed_int<S: Scalar>(
146    name: impl Into<Ident>,
147    data: impl IntoIterator<Item = impl Into<i32>>,
148    alloc: &Bump,
149) -> (Ident, Column<'_, S>) {
150    let transformed_data: Vec<i32> = data.into_iter().map(Into::into).collect();
151    let alloc_data = alloc.alloc_slice_copy(&transformed_data);
152    (name.into(), Column::Int(alloc_data))
153}
154
155/// Creates a `(Ident, Column)` pair for a bigint column.
156/// This is primarily intended for use in conjunction with [`table`].
157///
158/// # Example
159/// ```rust
160/// use bumpalo::Bump;
161/// use proof_of_sql::base::{database::table_utility::*, scalar::Curve25519Scalar};
162/// let alloc = Bump::new();
163/// let result = table::<Curve25519Scalar>([
164///     borrowed_bigint("a", [1, 2, 3], &alloc),
165/// ]);
166/// ```
167pub fn borrowed_bigint<S: Scalar>(
168    name: impl Into<Ident>,
169    data: impl IntoIterator<Item = impl Into<i64>>,
170    alloc: &Bump,
171) -> (Ident, Column<'_, S>) {
172    let transformed_data: Vec<i64> = data.into_iter().map(Into::into).collect();
173    let alloc_data = alloc.alloc_slice_copy(&transformed_data);
174    (name.into(), Column::BigInt(alloc_data))
175}
176
177/// Creates a `(Ident, Column)` pair for a boolean column.
178/// This is primarily intended for use in conjunction with [`table`].
179///
180/// # Example
181/// ```
182/// use bumpalo::Bump;
183/// use proof_of_sql::base::{database::table_utility::*, scalar::Curve25519Scalar};
184/// let alloc = Bump::new();
185/// let result = table::<Curve25519Scalar>([
186///     borrowed_boolean("a", [true, false, true], &alloc),
187/// ]);
188/// ```
189pub fn borrowed_boolean<S: Scalar>(
190    name: impl Into<Ident>,
191    data: impl IntoIterator<Item = impl Into<bool>>,
192    alloc: &Bump,
193) -> (Ident, Column<'_, S>) {
194    let transformed_data: Vec<bool> = data.into_iter().map(Into::into).collect();
195    let alloc_data = alloc.alloc_slice_copy(&transformed_data);
196    (name.into(), Column::Boolean(alloc_data))
197}
198
199/// Creates a `(Ident, Column)` pair for an int128 column.
200/// This is primarily intended for use in conjunction with [`table`].
201///
202/// # Example
203/// ```
204/// use bumpalo::Bump;
205/// use proof_of_sql::base::{database::table_utility::*, scalar::Curve25519Scalar};
206/// let alloc = Bump::new();
207/// let result = table::<Curve25519Scalar>([
208///     borrowed_int128("a", [1, 2, 3], &alloc),
209/// ]);
210/// ```
211pub fn borrowed_int128<S: Scalar>(
212    name: impl Into<Ident>,
213    data: impl IntoIterator<Item = impl Into<i128>>,
214    alloc: &Bump,
215) -> (Ident, Column<'_, S>) {
216    let transformed_data: Vec<i128> = data.into_iter().map(Into::into).collect();
217    let alloc_data = alloc.alloc_slice_copy(&transformed_data);
218    (name.into(), Column::Int128(alloc_data))
219}
220
221/// Creates a `(Ident, Column)` pair for a scalar column.
222/// This is primarily intended for use in conjunction with [`table`].
223///
224/// # Example
225/// ```
226/// use bumpalo::Bump;
227/// use proof_of_sql::base::{database::table_utility::*, scalar::Curve25519Scalar};
228/// let alloc = Bump::new();
229/// let result = table::<Curve25519Scalar>([
230///     borrowed_scalar("a", [1, 2, 3], &alloc),
231/// ]);
232/// ```
233pub fn borrowed_scalar<S: Scalar>(
234    name: impl Into<Ident>,
235    data: impl IntoIterator<Item = impl Into<S>>,
236    alloc: &Bump,
237) -> (Ident, Column<'_, S>) {
238    let transformed_data: Vec<S> = data.into_iter().map(Into::into).collect();
239    let alloc_data = alloc.alloc_slice_copy(&transformed_data);
240    (name.into(), Column::Scalar(alloc_data))
241}
242
243/// Creates a `(Ident, Column)` pair for a varchar column.
244/// This is primarily intended for use in conjunction with [`table`].
245/// # Example
246/// ```
247/// use bumpalo::Bump;
248/// use proof_of_sql::base::{database::table_utility::*, scalar::Curve25519Scalar};
249/// let alloc = Bump::new();
250/// let result = table::<Curve25519Scalar>([
251///     borrowed_varchar("a", ["a", "b", "c"], &alloc),
252/// ]);
253/// ```
254pub fn borrowed_varchar<'a, S: Scalar>(
255    name: impl Into<Ident>,
256    data: impl IntoIterator<Item = impl Into<String>>,
257    alloc: &'a Bump,
258) -> (Ident, Column<'a, S>) {
259    let strings: Vec<&'a str> = data
260        .into_iter()
261        .map(|item| {
262            let string = item.into();
263            alloc.alloc_str(&string) as &'a str
264        })
265        .collect();
266    let alloc_strings = alloc.alloc_slice_clone(&strings);
267    let scalars: Vec<S> = strings.iter().map(|s| (*s).into()).collect();
268    let alloc_scalars = alloc.alloc_slice_copy(&scalars);
269    (name.into(), Column::VarChar((alloc_strings, alloc_scalars)))
270}
271
272/// Creates a `(Ident, Column)` pair for a decimal75 column.
273/// This is primarily intended for use in conjunction with [`table`].
274/// # Example
275/// ```
276/// use bumpalo::Bump;
277/// use proof_of_sql::base::{database::table_utility::*, scalar::Curve25519Scalar};
278/// let alloc = Bump::new();
279/// let result = table::<Curve25519Scalar>([
280///     borrowed_decimal75("a", 12, 1, [1, 2, 3], &alloc),
281/// ]);
282/// ```
283/// # Panics
284/// - Panics if creating the `Precision` from the specified precision value fails.
285pub fn borrowed_decimal75<S: Scalar>(
286    name: impl Into<Ident>,
287    precision: u8,
288    scale: i8,
289    data: impl IntoIterator<Item = impl Into<S>>,
290    alloc: &Bump,
291) -> (Ident, Column<'_, S>) {
292    let transformed_data: Vec<S> = data.into_iter().map(Into::into).collect();
293    let alloc_data = alloc.alloc_slice_copy(&transformed_data);
294    (
295        name.into(),
296        Column::Decimal75(
297            crate::base::math::decimal::Precision::new(precision).unwrap(),
298            scale,
299            alloc_data,
300        ),
301    )
302}
303
304/// Creates a `(Ident, Column)` pair for a timestamp column.
305/// This is primarily intended for use in conjunction with [`table`].
306///
307/// # Parameters
308/// - `name`: The name of the column.
309/// - `time_unit`: The time unit of the timestamps.
310/// - `timezone`: The timezone for the timestamps.
311/// - `data`: The data for the column, provided as an iterator over `i64` values representing time since the unix epoch.
312/// - `alloc`: The bump allocator to use for allocating the column data.
313///
314/// # Example
315/// ```
316/// use bumpalo::Bump;
317/// use proof_of_sql::base::{database::table_utility::*,
318///     scalar::Curve25519Scalar,
319/// };
320/// use proof_of_sql_parser::{
321///    posql_time::{PoSQLTimeZone, PoSQLTimeUnit}};
322///
323/// let alloc = Bump::new();
324/// let result = table::<Curve25519Scalar>([
325///     borrowed_timestamptz("event_time", PoSQLTimeUnit::Second, PoSQLTimeZone::utc(), vec![1625072400, 1625076000, 1625079600], &alloc),
326/// ]);
327/// ```
328pub fn borrowed_timestamptz<S: Scalar>(
329    name: impl Into<Ident>,
330    time_unit: PoSQLTimeUnit,
331    timezone: PoSQLTimeZone,
332    data: impl IntoIterator<Item = i64>,
333    alloc: &Bump,
334) -> (Ident, Column<'_, S>) {
335    let vec_data: Vec<i64> = data.into_iter().collect();
336    let alloc_data = alloc.alloc_slice_copy(&vec_data);
337    (
338        name.into(),
339        Column::TimestampTZ(time_unit, timezone, alloc_data),
340    )
341}