Skip to content

Commit

Permalink
feat!: Add TinyInt / i8 type (#190)
Browse files Browse the repository at this point in the history
# Rationale for this change

We already have `SmallInt / i16`, `Int / i32`, and `BigInt / i64` data types supported. Adding an additional `TinyInt / i8` data type would be helpful to some users and would additionally have (minor) performance benefits with those columns.

# What changes are included in this PR?

Added a TinyInt variant to the various *Column* enum types.
Added a branch for handling TinyInt everywhere that SmallInt, Int, and BigInt are handled.


# Are these changes tested?

Added unit tests covering the additional code.
  • Loading branch information
Ashu999 authored Oct 5, 2024
1 parent 227f611 commit 48b2f0b
Show file tree
Hide file tree
Showing 29 changed files with 1,388 additions and 15 deletions.
4 changes: 3 additions & 1 deletion crates/proof-of-sql/benches/bench_append_rows.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ use proof_of_sql::{
database::{
owned_table_utility::{
bigint, boolean, decimal75, int, int128, owned_table, scalar, smallint,
timestamptz, varchar,
timestamptz, tinyint, varchar,
},
OwnedTable,
},
Expand Down Expand Up @@ -86,6 +86,7 @@ pub fn generate_random_owned_table<S: Scalar>(
"scalar",
"varchar",
"decimal75",
"tinyint",
"smallint",
"int",
"timestamptz",
Expand Down Expand Up @@ -118,6 +119,7 @@ pub fn generate_random_owned_table<S: Scalar>(
2,
vec![generate_random_u64_array(); num_rows],
)),
"tinyint" => columns.push(tinyint(identifier.deref(), vec![rng.gen::<i8>(); num_rows])),
"smallint" => columns.push(smallint(
identifier.deref(),
vec![rng.gen::<i16>(); num_rows],
Expand Down
34 changes: 34 additions & 0 deletions crates/proof-of-sql/src/base/commitment/column_bounds.rs
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,8 @@ pub struct ColumnBoundsMismatch {
pub enum ColumnBounds {
/// Column does not have order.
NoOrder,
/// The bounds of a `TinyInt` column.
TinyInt(Bounds<i8>),
/// The bounds of a `SmallInt` column.
SmallInt(Bounds<i16>),
/// The bounds of an Int column.
Expand All @@ -222,6 +224,7 @@ impl ColumnBounds {
#[must_use]
pub fn from_column(column: &CommittableColumn) -> ColumnBounds {
match column {
CommittableColumn::TinyInt(ints) => ColumnBounds::TinyInt(Bounds::from_iter(*ints)),
CommittableColumn::SmallInt(ints) => ColumnBounds::SmallInt(Bounds::from_iter(*ints)),
CommittableColumn::Int(ints) => ColumnBounds::Int(Bounds::from_iter(*ints)),
CommittableColumn::BigInt(ints) => ColumnBounds::BigInt(Bounds::from_iter(*ints)),
Expand All @@ -243,6 +246,9 @@ impl ColumnBounds {
pub fn try_union(self, other: Self) -> Result<Self, ColumnBoundsMismatch> {
match (self, other) {
(ColumnBounds::NoOrder, ColumnBounds::NoOrder) => Ok(ColumnBounds::NoOrder),
(ColumnBounds::TinyInt(bounds_a), ColumnBounds::TinyInt(bounds_b)) => {
Ok(ColumnBounds::TinyInt(bounds_a.union(bounds_b)))
}
(ColumnBounds::SmallInt(bounds_a), ColumnBounds::SmallInt(bounds_b)) => {
Ok(ColumnBounds::SmallInt(bounds_a.union(bounds_b)))
}
Expand Down Expand Up @@ -272,6 +278,9 @@ impl ColumnBounds {
pub fn try_difference(self, other: Self) -> Result<Self, ColumnBoundsMismatch> {
match (self, other) {
(ColumnBounds::NoOrder, ColumnBounds::NoOrder) => Ok(self),
(ColumnBounds::TinyInt(bounds_a), ColumnBounds::TinyInt(bounds_b)) => {
Ok(ColumnBounds::TinyInt(bounds_a.difference(bounds_b)))
}
(ColumnBounds::SmallInt(bounds_a), ColumnBounds::SmallInt(bounds_b)) => {
Ok(ColumnBounds::SmallInt(bounds_a.difference(bounds_b)))
}
Expand Down Expand Up @@ -497,6 +506,14 @@ mod tests {
let varchar_column_bounds = ColumnBounds::from_column(&committable_varchar_column);
assert_eq!(varchar_column_bounds, ColumnBounds::NoOrder);

let tinyint_column = OwnedColumn::<Curve25519Scalar>::TinyInt([1, 2, 3, 1, 0].to_vec());
let committable_tinyint_column = CommittableColumn::from(&tinyint_column);
let tinyint_column_bounds = ColumnBounds::from_column(&committable_tinyint_column);
assert_eq!(
tinyint_column_bounds,
ColumnBounds::TinyInt(Bounds::Sharp(BoundsInner { min: 0, max: 3 }))
);

let smallint_column = OwnedColumn::<Curve25519Scalar>::SmallInt([1, 2, 3, 1, 0].to_vec());
let committable_smallint_column = CommittableColumn::from(&smallint_column);
let smallint_column_bounds = ColumnBounds::from_column(&committable_smallint_column);
Expand Down Expand Up @@ -560,6 +577,13 @@ mod tests {
let no_order = ColumnBounds::NoOrder;
assert_eq!(no_order.try_union(no_order).unwrap(), no_order);

let tinyint_a = ColumnBounds::TinyInt(Bounds::Sharp(BoundsInner { min: 1, max: 3 }));
let tinyint_b = ColumnBounds::TinyInt(Bounds::Sharp(BoundsInner { min: 4, max: 6 }));
assert_eq!(
tinyint_a.try_union(tinyint_b).unwrap(),
ColumnBounds::TinyInt(Bounds::Sharp(BoundsInner { min: 1, max: 6 }))
);

let smallint_a = ColumnBounds::SmallInt(Bounds::Sharp(BoundsInner { min: 1, max: 3 }));
let smallint_b = ColumnBounds::SmallInt(Bounds::Sharp(BoundsInner { min: 4, max: 6 }));
assert_eq!(
Expand Down Expand Up @@ -607,6 +631,7 @@ mod tests {
#[test]
fn we_cannot_union_mismatched_column_bounds() {
let no_order = ColumnBounds::NoOrder;
let tinyint = ColumnBounds::TinyInt(Bounds::Sharp(BoundsInner { min: -3, max: 3 }));
let smallint = ColumnBounds::SmallInt(Bounds::Sharp(BoundsInner { min: -5, max: 5 }));
let int = ColumnBounds::Int(Bounds::Sharp(BoundsInner { min: -10, max: 10 }));
let bigint = ColumnBounds::BigInt(Bounds::Sharp(BoundsInner { min: 1, max: 3 }));
Expand All @@ -615,6 +640,7 @@ mod tests {

let bounds = [
(no_order, "NoOrder"),
(tinyint, "TinyInt"),
(smallint, "SmallInt"),
(int, "Int"),
(bigint, "BigInt"),
Expand All @@ -639,6 +665,10 @@ mod tests {
let no_order = ColumnBounds::NoOrder;
assert_eq!(no_order.try_difference(no_order).unwrap(), no_order);

let tinyint_a = ColumnBounds::TinyInt(Bounds::Sharp(BoundsInner { min: 1, max: 3 }));
let tinyint_b = ColumnBounds::TinyInt(Bounds::Empty);
assert_eq!(tinyint_a.try_difference(tinyint_b).unwrap(), tinyint_a);

let smallint_a = ColumnBounds::SmallInt(Bounds::Sharp(BoundsInner { min: 1, max: 3 }));
let smallint_b = ColumnBounds::SmallInt(Bounds::Empty);
assert_eq!(smallint_a.try_difference(smallint_b).unwrap(), smallint_a);
Expand Down Expand Up @@ -672,6 +702,7 @@ mod tests {
let bigint = ColumnBounds::BigInt(Bounds::Sharp(BoundsInner { min: 1, max: 3 }));
let int128 = ColumnBounds::Int128(Bounds::Sharp(BoundsInner { min: 4, max: 6 }));
let timestamp = ColumnBounds::TimestampTZ(Bounds::Sharp(BoundsInner { min: 4, max: 6 }));
let tinyint = ColumnBounds::TinyInt(Bounds::Sharp(BoundsInner { min: 1, max: 3 }));
let smallint = ColumnBounds::SmallInt(Bounds::Sharp(BoundsInner { min: 1, max: 3 }));

assert!(no_order.try_difference(bigint).is_err());
Expand All @@ -683,6 +714,9 @@ mod tests {
assert!(bigint.try_difference(int128).is_err());
assert!(int128.try_difference(bigint).is_err());

assert!(tinyint.try_difference(timestamp).is_err());
assert!(timestamp.try_difference(tinyint).is_err());

assert!(smallint.try_difference(timestamp).is_err());
assert!(timestamp.try_difference(smallint).is_err());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,8 @@ impl ColumnCommitmentMetadata {
bounds: ColumnBounds,
) -> Result<ColumnCommitmentMetadata, InvalidColumnCommitmentMetadata> {
match (column_type, bounds) {
(ColumnType::SmallInt, ColumnBounds::SmallInt(_))
(ColumnType::TinyInt, ColumnBounds::TinyInt(_))
| (ColumnType::SmallInt, ColumnBounds::SmallInt(_))
| (ColumnType::Int, ColumnBounds::Int(_))
| (ColumnType::BigInt, ColumnBounds::BigInt(_))
| (ColumnType::Int128, ColumnBounds::Int128(_))
Expand Down Expand Up @@ -189,6 +190,18 @@ mod tests {

#[test]
fn we_can_construct_metadata() {
assert_eq!(
ColumnCommitmentMetadata::try_new(
ColumnType::TinyInt,
ColumnBounds::TinyInt(Bounds::Empty)
)
.unwrap(),
ColumnCommitmentMetadata {
column_type: ColumnType::TinyInt,
bounds: ColumnBounds::TinyInt(Bounds::Empty)
}
);

assert_eq!(
ColumnCommitmentMetadata::try_new(
ColumnType::SmallInt,
Expand Down Expand Up @@ -436,6 +449,17 @@ mod tests {
panic!("Bounds constructed from nonempty BigInt column should be ColumnBounds::Int(Bounds::Sharp(_))");
}

let tinyint_column = OwnedColumn::<Curve25519Scalar>::TinyInt([1, 2, 3, 1, 0].to_vec());
let committable_tinyint_column = CommittableColumn::from(&tinyint_column);
let tinyint_metadata = ColumnCommitmentMetadata::from_column(&committable_tinyint_column);
assert_eq!(tinyint_metadata.column_type(), &ColumnType::TinyInt);
if let ColumnBounds::TinyInt(Bounds::Sharp(bounds)) = tinyint_metadata.bounds() {
assert_eq!(bounds.min(), &0);
assert_eq!(bounds.max(), &3);
} else {
panic!("Bounds constructed from nonempty BigInt column should be ColumnBounds::TinyInt(Bounds::Sharp(_))");
}

let smallint_column = OwnedColumn::<Curve25519Scalar>::SmallInt([1, 2, 3, 1, 0].to_vec());
let committable_smallint_column = CommittableColumn::from(&smallint_column);
let smallint_metadata = ColumnCommitmentMetadata::from_column(&committable_smallint_column);
Expand Down Expand Up @@ -504,6 +528,18 @@ mod tests {
);

// Ordered case
let ints = [1, 2, 3, 1, 0];
let tinyint_column_a = CommittableColumn::TinyInt(&ints[..2]);
let tinyint_metadata_a = ColumnCommitmentMetadata::from_column(&tinyint_column_a);
let tinyint_column_b = CommittableColumn::TinyInt(&ints[2..]);
let tinyint_metadata_b = ColumnCommitmentMetadata::from_column(&tinyint_column_b);
let tinyint_column_c = CommittableColumn::TinyInt(&ints);
let tinyint_metadata_c = ColumnCommitmentMetadata::from_column(&tinyint_column_c);
assert_eq!(
tinyint_metadata_a.try_union(tinyint_metadata_b).unwrap(),
tinyint_metadata_c
);

let ints = [1, 2, 3, 1, 0];
let smallint_column_a = CommittableColumn::SmallInt(&ints[..2]);
let smallint_metadata_a = ColumnCommitmentMetadata::from_column(&smallint_column_a);
Expand Down Expand Up @@ -650,6 +686,43 @@ mod tests {
);
}

#[test]
fn we_can_difference_tinyint_matching_metadata() {
// Ordered case
let tinyints = [1, 2, 3, 1, 0];
let tinyint_column_a = CommittableColumn::TinyInt(&tinyints[..2]);
let tinyint_metadata_a = ColumnCommitmentMetadata::from_column(&tinyint_column_a);
let tinyint_column_b = CommittableColumn::TinyInt(&tinyints);
let tinyint_metadata_b = ColumnCommitmentMetadata::from_column(&tinyint_column_b);

let b_difference_a = tinyint_metadata_b
.try_difference(tinyint_metadata_a)
.unwrap();
assert_eq!(b_difference_a.column_type, ColumnType::TinyInt);
if let ColumnBounds::TinyInt(Bounds::Bounded(bounds)) = b_difference_a.bounds() {
assert_eq!(bounds.min(), &0);
assert_eq!(bounds.max(), &3);
} else {
panic!("difference of overlapping bounds should be Bounded");
}

let tinyint_column_empty = CommittableColumn::TinyInt(&[]);
let tinyint_metadata_empty = ColumnCommitmentMetadata::from_column(&tinyint_column_empty);

assert_eq!(
tinyint_metadata_b
.try_difference(tinyint_metadata_empty)
.unwrap(),
tinyint_metadata_b
);
assert_eq!(
tinyint_metadata_empty
.try_difference(tinyint_metadata_b)
.unwrap(),
tinyint_metadata_empty
);
}

#[test]
fn we_can_difference_smallint_matching_metadata() {
// Ordered case
Expand Down Expand Up @@ -732,6 +805,10 @@ mod tests {
column_type: ColumnType::Scalar,
bounds: ColumnBounds::NoOrder,
};
let tinyint_metadata = ColumnCommitmentMetadata {
column_type: ColumnType::TinyInt,
bounds: ColumnBounds::TinyInt(Bounds::Empty),
};
let smallint_metadata = ColumnCommitmentMetadata {
column_type: ColumnType::SmallInt,
bounds: ColumnBounds::SmallInt(Bounds::Empty),
Expand All @@ -753,6 +830,18 @@ mod tests {
bounds: ColumnBounds::Int128(Bounds::Empty),
};

assert!(tinyint_metadata.try_union(scalar_metadata).is_err());
assert!(scalar_metadata.try_union(tinyint_metadata).is_err());

assert!(tinyint_metadata.try_union(decimal75_metadata).is_err());
assert!(decimal75_metadata.try_union(tinyint_metadata).is_err());

assert!(tinyint_metadata.try_union(varchar_metadata).is_err());
assert!(varchar_metadata.try_union(tinyint_metadata).is_err());

assert!(tinyint_metadata.try_union(boolean_metadata).is_err());
assert!(boolean_metadata.try_union(tinyint_metadata).is_err());

assert!(smallint_metadata.try_union(scalar_metadata).is_err());
assert!(scalar_metadata.try_union(smallint_metadata).is_err());

Expand Down
Loading

0 comments on commit 48b2f0b

Please sign in to comment.