Skip to content

Commit

Permalink
feat: add find_bigdecimals
Browse files Browse the repository at this point in the history
  • Loading branch information
iajoiner committed Oct 16, 2024
1 parent c749566 commit 086d98b
Show file tree
Hide file tree
Showing 5 changed files with 98 additions and 0 deletions.
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ rayon = { version = "1.5" }
serde = { version = "1", default-features = false }
serde_json = { version = "1", default-features = false, features = ["alloc"] }
snafu = { version = "0.8.4", default-features = false }
sqlparser = { version = "0.45.0", default-features = false }
tiny-keccak = { version = "2.0.2", features = [ "keccak" ] }
tracing = { version = "0.1.36", default-features = false }
tracing-opentelemetry = { version = "0.22.0" }
Expand Down
1 change: 1 addition & 0 deletions crates/proof-of-sql/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ rayon = { workspace = true, optional = true }
serde = { workspace = true, features = ["serde_derive"] }
serde_json = { workspace = true }
snafu = { workspace = true }
sqlparser = { workspace = true }
tiny-keccak = { workspace = true }
tracing = { workspace = true, features = ["attributes"] }
zerocopy = { workspace = true }
Expand Down
2 changes: 2 additions & 0 deletions crates/proof-of-sql/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ extern crate alloc;
pub mod base;
pub mod proof_primitive;
pub mod sql;
/// Utilities for working with the library
pub mod utils;

#[cfg(test)]
mod tests;
3 changes: 3 additions & 0 deletions crates/proof-of-sql/src/utils/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
//! This module contains utilities for working with the library
/// Parse DDLs and find bigdecimal columns
pub mod parse;
91 changes: 91 additions & 0 deletions crates/proof-of-sql/src/utils/parse.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
use crate::base::map::IndexMap;
use alloc::string::ToString;
use sqlparser::{
ast::{DataType, ExactNumberInfo, Statement},
dialect::GenericDialect,
parser::Parser,
};

/// Parse a DDL file and return a map of table names to bigdecimal columns
///
/// # Panics
/// Panics if there is an error parsing the SQL
#[must_use]
pub fn find_bigdecimals(queries: &str) -> IndexMap<String, Vec<String>> {
let dialect = GenericDialect {};
let ast = match Parser::parse_sql(&dialect, queries) {
Ok(ast) => ast,
Err(e) => panic!("Error parsing SQL: {e:?}"),
};
// Find all `CREATE TABLE` statements
ast.iter()
.filter_map(|statement| match statement {
Statement::CreateTable { name, columns, .. } => {
// Find all `DECIMAL` columns where precision > 38
// Find the table name
// Add the table name and column name to the map
let str_name = name.to_string();
let big_decimal_cols: Vec<String> = columns
.iter()
.filter_map(|column_def| match column_def.data_type {
DataType::Decimal(ExactNumberInfo::PrecisionAndScale(precision, _))
if precision > 38 =>
{
Some(column_def.name.to_string())
}
_ => None,
})
.collect();
Some((str_name, big_decimal_cols))
}
_ => None,
})
.collect::<IndexMap<String, Vec<String>>>()
}

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn test_find_bigdecimals() {
let sql = "CREATE TABLE IF NOT EXISTS ETHEREUM.BLOCKS(
BLOCK_NUMBER BIGINT NOT NULL,
TIME_STAMP TIMESTAMP,
BLOCK_HASH VARCHAR,
MINER VARCHAR,
REWARD DECIMAL(78, 0),
SIZE_ INT,
GAS_USED INT,
GAS_LIMIT INT,
BASE_FEE_PER_GAS DECIMAL(78, 0),
TRANSACTION_COUNT INT,
PARENT_HASH VARCHAR,
PRIMARY KEY(BLOCK_NUMBER)
);
CREATE TABLE IF NOT EXISTS ETHEREUM.BLOCK_DETAILS(
BLOCK_NUMBER BIGINT NOT NULL,
TIME_STAMP TIMESTAMP,
SHA3_UNCLES VARCHAR,
STATE_ROOT VARCHAR,
TRANSACTIONS_ROOT VARCHAR,
RECEIPTS_ROOT VARCHAR,
UNCLES_COUNT INT,
VERSION VARCHAR,
LOGS_BLOOM VARCHAR,
NONCE VARCHAR,
PRIMARY KEY(BLOCK_NUMBER)
);";
let bigdecimals = find_bigdecimals(sql);
assert_eq!(
bigdecimals.get("ETHEREUM.BLOCKS").unwrap(),
&["REWARD", "BASE_FEE_PER_GAS"]
);
let empty_vec: Vec<String> = vec![];
assert_eq!(
bigdecimals.get("ETHEREUM.BLOCK_DETAILS").unwrap(),
&empty_vec
);
}
}

0 comments on commit 086d98b

Please sign in to comment.