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