proof_of_sql/utils/
parse.rs1use crate::base::map::IndexMap;
2use alloc::{
3 string::{String, ToString},
4 vec::Vec,
5};
6use sqlparser::{
7 ast::{DataType, ExactNumberInfo, Statement},
8 dialect::GenericDialect,
9 parser::Parser,
10};
11
12#[expect(clippy::cast_possible_truncation)]
13#[must_use]
18pub fn find_bigdecimals(queries: &str) -> IndexMap<String, Vec<(String, u8, i8)>> {
19 let dialect = GenericDialect {};
20 let ast = Parser::parse_sql(&dialect, queries).expect("Failed to parse SQL");
21 ast.iter()
23 .filter_map(|statement| match statement {
24 Statement::CreateTable { name, columns, .. } => {
25 let str_name = name.to_string();
29 let big_decimal_specs: Vec<(String, u8, i8)> = columns
30 .iter()
31 .filter_map(|column_def| match column_def.data_type {
32 DataType::Decimal(ExactNumberInfo::PrecisionAndScale(precision, scale))
33 if precision > 38 =>
34 {
35 Some((column_def.name.to_string(), precision as u8, scale as i8))
36 }
37 _ => None,
38 })
39 .collect();
40 Some((str_name, big_decimal_specs))
41 }
42 _ => None,
43 })
44 .collect::<IndexMap<String, Vec<_>>>()
45}
46
47#[cfg(test)]
48mod tests {
49 use super::*;
50
51 #[test]
52 fn test_find_bigdecimals() {
53 let sql = "CREATE TABLE IF NOT EXISTS ETHEREUM.BLOCKS(
54 BLOCK_NUMBER BIGINT NOT NULL,
55 TIME_STAMP TIMESTAMP,
56 BLOCK_HASH VARCHAR,
57 MINER VARCHAR,
58 REWARD DECIMAL(78, 0),
59 SIZE_ INT,
60 GAS_USED INT,
61 GAS_LIMIT INT,
62 BASE_FEE_PER_GAS DECIMAL(78, 0),
63 TRANSACTION_COUNT INT,
64 PARENT_HASH VARCHAR,
65 PRIMARY KEY(BLOCK_NUMBER)
66 );
67
68 CREATE TABLE IF NOT EXISTS ETHEREUM.BLOCK_DETAILS(
69 BLOCK_NUMBER BIGINT NOT NULL,
70 TIME_STAMP TIMESTAMP,
71 SHA3_UNCLES VARCHAR,
72 STATE_ROOT VARCHAR,
73 TRANSACTIONS_ROOT VARCHAR,
74 RECEIPTS_ROOT VARCHAR,
75 UNCLES_COUNT INT,
76 VERSION VARCHAR,
77 LOGS_BLOOM VARCHAR,
78 NONCE VARCHAR,
79 PRIMARY KEY(BLOCK_NUMBER)
80 );";
81 let bigdecimals = find_bigdecimals(sql);
82 assert_eq!(
83 bigdecimals.get("ETHEREUM.BLOCKS").unwrap(),
84 &[
85 ("REWARD".to_string(), 78, 0),
86 ("BASE_FEE_PER_GAS".to_string(), 78, 0)
87 ]
88 );
89 let empty_vec: Vec<(String, u8, i8)> = vec![];
90 assert_eq!(
91 bigdecimals.get("ETHEREUM.BLOCK_DETAILS").unwrap(),
92 &empty_vec
93 );
94 }
95}