Skip to content

Commit

Permalink
feat: timestamp inequality support (#52)
Browse files Browse the repository at this point in the history
# Rationale for this change

Quick PR to add support for inequality expressions between timestamps.
Since theyre represented internally as i64, they can be easily compared
against one another.

# What changes are included in this PR?

Adds support for statements with the following syntax:

```
SELECT * FROM table WHERE times <= timestamp '1970-01-01T00:00:00Z
SELECT * FROM table WHERE times >= timestamp '1970-01-01T00:00:00Z
SELECT * FROM table WHERE times > timestamp '1970-01-01T00:00:00Z
SELECT * FROM table WHERE times < timestamp '1970-01-01T00:00:00Z
```

# Are these changes tested?

yes
  • Loading branch information
Dustin-Ray authored Jul 18, 2024
1 parent 54584e5 commit 255ebeb
Show file tree
Hide file tree
Showing 2 changed files with 157 additions and 3 deletions.
2 changes: 1 addition & 1 deletion crates/proof-of-sql/src/sql/parse/query_context_builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -306,11 +306,11 @@ pub(crate) fn type_check_binary_operation(
return false;
}
}
// TODO: inequality support for timestamps
left_dtype.is_numeric() && right_dtype.is_numeric()
|| matches!(
(left_dtype, right_dtype),
(ColumnType::Boolean, ColumnType::Boolean)
| (ColumnType::TimestampTZ(_, _), ColumnType::TimestampTZ(_, _))
)
}
BinaryOperator::Add | BinaryOperator::Subtract => {
Expand Down
158 changes: 156 additions & 2 deletions crates/proof-of-sql/tests/timestamp_integration_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ use proof_of_sql::base::commitment::InnerProductProof;
use proof_of_sql::{
base::database::{owned_table_utility::*, OwnedTableTestAccessor, TestAccessor},
proof_primitive::dory::{
test_rng, DoryEvaluationProof, DoryProverPublicSetup, DoryVerifierPublicSetup, ProverSetup,
PublicParameters, VerifierSetup,
test_rng, DoryCommitment, DoryEvaluationProof, DoryProverPublicSetup,
DoryVerifierPublicSetup, ProverSetup, PublicParameters, VerifierSetup,
},
sql::{
parse::QueryExpr,
Expand Down Expand Up @@ -134,6 +134,86 @@ mod tests {
);
}

#[test]
fn test_basic_timestamp_inequality_query() {
let test_timestamps = vec![i64::MIN, -1, 0, 1, i64::MAX];

run_timestamp_query_test(
"SELECT * FROM table WHERE times < timestamp '1970-01-01T00:00:00Z';",
test_timestamps.clone(),
vec![i64::MIN, -1],
);

run_timestamp_query_test(
"SELECT * FROM table WHERE times > timestamp '1970-01-01T00:00:00Z';",
test_timestamps.clone(),
vec![1, i64::MAX],
);

run_timestamp_query_test(
"SELECT * FROM table WHERE times >= timestamp '1970-01-01T00:00:00Z';",
test_timestamps.clone(),
vec![0, 1, i64::MAX],
);

run_timestamp_query_test(
"SELECT * FROM table WHERE times <= timestamp '1970-01-01T00:00:00Z';",
test_timestamps.clone(),
vec![i64::MIN, -1, 0],
);
}

#[test]
fn test_timestamp_inequality_queries_with_timezone_offsets() {
// Test with a range of timestamps around the Unix epoch
// 60 * 60 = 3600 * 8 (PST offset) = 28800
let test_timestamps = vec![i64::MIN, 28800, 28799, 0, 1, i64::MAX];

// Test timezone offset -08:00 (e.g., Pacific Standard Time)
run_timestamp_query_test(
"SELECT * FROM table WHERE times > timestamp '1970-01-01T00:00:00-08:00';",
test_timestamps.clone(),
vec![i64::MAX],
);
run_timestamp_query_test(
"SELECT * FROM table WHERE times < timestamp '1970-01-01T00:00:00-08:00';",
test_timestamps.clone(),
vec![i64::MIN, 28799, 0, 1],
);
run_timestamp_query_test(
"SELECT * FROM table WHERE times >= timestamp '1970-01-01T00:00:00-08:00';",
test_timestamps.clone(),
vec![28800, i64::MAX],
);
run_timestamp_query_test(
"SELECT * FROM table WHERE times <= timestamp '1970-01-01T00:00:00-08:00';",
test_timestamps.clone(),
vec![i64::MIN, 28800, 28799, 0, 1],
);

// Test timezone offset +00:00 (e.g., UTC)
run_timestamp_query_test(
"SELECT * FROM table WHERE times > timestamp '1970-01-01T00:00:00+00:00';",
test_timestamps.clone(),
vec![28800, 28799, 1, i64::MAX],
);
run_timestamp_query_test(
"SELECT * FROM table WHERE times < timestamp '1970-01-01T00:00:00+00:00';",
test_timestamps.clone(),
vec![i64::MIN],
);
run_timestamp_query_test(
"SELECT * FROM table WHERE times >= timestamp '1970-01-01T00:00:00+00:00';",
test_timestamps.clone(),
vec![28800, 28799, 0, 1, i64::MAX],
);
run_timestamp_query_test(
"SELECT * FROM table WHERE times <= timestamp '1970-01-01T00:00:00+00:00';",
test_timestamps.clone(),
vec![i64::MIN, 0],
);
}

// This test simulates the following query:
//
// 1. Creating a table:
Expand Down Expand Up @@ -342,3 +422,77 @@ mod tests {
);
}
}

#[test]
#[cfg(feature = "blitzar")]
fn we_can_prove_timestamp_inequality_queries_with_multiple_columns() {
let public_parameters = PublicParameters::rand(4, &mut test_rng());
let prover_setup = ProverSetup::from(&public_parameters);
let verifier_setup = VerifierSetup::from(&public_parameters);
let dory_prover_setup = DoryProverPublicSetup::new(&prover_setup, 3);
let dory_verifier_setup = DoryVerifierPublicSetup::new(&verifier_setup, 3);
let mut accessor =
OwnedTableTestAccessor::<DoryEvaluationProof>::new_empty_with_setup(dory_prover_setup);
accessor.add_table(
"sxt.table".parse().unwrap(),
owned_table([
timestamptz(
"a",
PoSQLTimeUnit::Nanosecond,
PoSQLTimeZone::Utc,
[
i64::MIN,
2,
-1,
0,
1,
-2,
1231006505000000000, // bitcoin genesis block time
i64::MAX,
],
),
timestamptz(
"b",
PoSQLTimeUnit::Nanosecond,
PoSQLTimeZone::Utc,
[i64::MAX, -2, -1, -1231006505000000000, 0, 1, 2, i64::MIN],
),
]),
0,
);
let query = QueryExpr::<DoryCommitment>::try_new(
"select *, a <= b as res from TABLE where a <= b"
.parse()
.unwrap(),
"sxt".parse().unwrap(),
&accessor,
)
.unwrap();
let (proof, serialized_result) =
QueryProof::<DoryEvaluationProof>::new(query.proof_expr(), &accessor, &dory_prover_setup);
let owned_table_result = proof
.verify(
query.proof_expr(),
&accessor,
&serialized_result,
&dory_verifier_setup,
)
.unwrap()
.table;
let expected_result = owned_table([
timestamptz(
"a",
PoSQLTimeUnit::Nanosecond,
PoSQLTimeZone::Utc,
[i64::MIN, -1, -2],
),
timestamptz(
"b",
PoSQLTimeUnit::Nanosecond,
PoSQLTimeZone::Utc,
[i64::MAX, -1, 1],
),
boolean("res", [true, true, true]),
]);
assert_eq!(owned_table_result, expected_result);
}

0 comments on commit 255ebeb

Please sign in to comment.