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}