Skip to content

Commit 3574aea

Browse files
committed
store: Rewrite table names in from clauses
1 parent 79dc39b commit 3574aea

File tree

4 files changed

+78
-206
lines changed

4 files changed

+78
-206
lines changed

store/postgres/src/sql/formatter.rs

Lines changed: 0 additions & 103 deletions
This file was deleted.

store/postgres/src/sql/mod.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
mod constants;
2-
mod formatter;
32
mod parser;
43
mod validation;
54

store/postgres/src/sql/parser.rs

Lines changed: 23 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -1,92 +1,41 @@
1-
use super::{constants::SQL_DIALECT, formatter::Formatter, validation::Validator};
2-
use crate::relational::{ColumnType, Layout};
1+
use super::{constants::SQL_DIALECT, validation::Validator};
2+
use crate::relational::Layout;
33
use anyhow::{anyhow, Ok, Result};
4-
use graph::components::store::BLOCK_NUMBER_MAX;
5-
use itertools::Itertools;
64
use std::sync::Arc;
75

8-
pub fn generate_table_prelude_from_layout(layout: &Layout) -> String {
9-
let schema = &layout.catalog.site.namespace;
10-
let ctes = layout
11-
.tables
12-
.iter()
13-
.filter(|(entity, _)| !entity.is_poi())
14-
.map(|(_, table)| {
15-
let table_name = table.name.as_str();
16-
17-
let (block_column, filter) = if !table.immutable {
18-
(
19-
"block_range",
20-
Some(format!(" WHERE \"block_range\" @> {}", BLOCK_NUMBER_MAX)),
21-
)
22-
} else {
23-
("block$", None)
24-
};
25-
26-
let columns = table
27-
.columns
28-
.iter()
29-
.map(|col| {
30-
if !col.is_list() && col.column_type == ColumnType::Bytes {
31-
format!(
32-
r#"concat('0x', encode("{}", 'hex')) AS "{}""#,
33-
col.name.as_str(),
34-
col.name.as_str()
35-
)
36-
} else {
37-
format!(r#""{}""#, col.name.as_str())
38-
}
39-
})
40-
.chain(std::iter::once(format!(r#""{}""#, block_column)))
41-
.collect::<Vec<_>>()
42-
.join(", ");
43-
format!(
44-
"\"{table_name}\" AS (SELECT {columns} FROM \"{schema}\".\"{table_name}\"{})",
45-
filter.unwrap_or_default()
46-
)
47-
})
48-
.sorted()
49-
.collect::<Vec<_>>()
50-
.join(",\n");
51-
format!("WITH {ctes}")
52-
}
53-
546
pub struct Parser {
557
layout: Arc<Layout>,
56-
prelude: String,
578
}
589

5910
impl Parser {
6011
pub fn new(layout: Arc<Layout>) -> Self {
61-
let prelude = generate_table_prelude_from_layout(&layout);
62-
Self { layout, prelude }
12+
Self { layout }
6313
}
6414

6515
pub fn parse_and_validate(&self, sql: &str) -> Result<String> {
6616
let mut statements = sqlparser::parser::Parser::parse_sql(&SQL_DIALECT, sql)?;
6717

6818
let mut validator = Validator::new(&self.layout);
69-
validator.validate_statements(&statements)?;
70-
71-
let mut formatter = Formatter::new(&self.prelude, &self.layout);
19+
validator.validate_statements(&mut statements)?;
7220

7321
let statement = statements
7422
.get_mut(0)
7523
.ok_or_else(|| anyhow!("No SQL statements found"))?;
7624

77-
let result = formatter.format(statement);
78-
79-
Ok(result)
25+
let sql = format!(
26+
"select to_jsonb(sub.*) as data from ( {} ) as sub",
27+
statement
28+
);
29+
Ok(sql)
8030
}
8131
}
8232

8333
#[cfg(test)]
8434
mod test {
8535

86-
use crate::layout_for_tests::{make_dummy_site, Catalog, Namespace};
36+
use crate::sql::test::make_layout;
8737

8838
use super::*;
89-
use graph::{data::subgraph::DeploymentHash, schema::InputSchema};
9039

9140
const TEST_GQL: &str = "
9241
type SwapMulti @entity(immutable: true) {
@@ -111,8 +60,6 @@ mod test {
11160
}
11261
";
11362

114-
const NAMESPACE: &str = "sgd0815";
115-
11663
const SQL_QUERY: &str = "
11764
with tokens as (
11865
select * from (values
@@ -145,31 +92,28 @@ mod test {
14592
14693
";
14794

148-
fn test_layout() -> Layout {
149-
let subgraph = DeploymentHash::new("subgraph").unwrap();
150-
let schema =
151-
InputSchema::parse_latest(TEST_GQL, subgraph.clone()).expect("Test schema invalid");
152-
let namespace = Namespace::new(NAMESPACE.to_owned()).unwrap();
153-
let site = Arc::new(make_dummy_site(subgraph, namespace, "anet".to_string()));
154-
let catalog =
155-
Catalog::for_tests(site.clone(), Default::default()).expect("Can not create catalog");
156-
Layout::new(site, &schema, catalog).expect("Failed to construct Layout")
95+
fn parse_and_validate(sql: &str) -> Result<String, anyhow::Error> {
96+
let parser = Parser::new(Arc::new(make_layout(TEST_GQL)));
97+
98+
parser.parse_and_validate(sql)
15799
}
158100

159101
#[test]
160102
fn parse_sql() {
161-
let parser = Parser::new(Arc::new(test_layout()));
162-
163-
let result = parser.parse_and_validate(SQL_QUERY);
164-
165-
assert!(result.is_ok());
166-
167-
let query = result.unwrap();
103+
let query = parse_and_validate(SQL_QUERY).unwrap();
168104

169105
assert_eq!(
170106
query,
171107
r#"WITH "swap_multi" AS (SELECT concat('0x', encode("id", 'hex')) AS "id", concat('0x', encode("sender", 'hex')) AS "sender", "amounts_in", "tokens_in", "amounts_out", "tokens_out", "referral_code", "block_number", "block_timestamp", concat('0x', encode("transaction_hash", 'hex')) AS "transaction_hash", "block$" FROM "sgd0815"."swap_multi"),
172108
"token" AS (SELECT "id", concat('0x', encode("address", 'hex')) AS "address", "symbol", "name", "decimals", "block_range" FROM "sgd0815"."token" WHERE "block_range" @> 2147483647) SELECT to_jsonb(sub.*) AS data FROM ( WITH tokens AS (SELECT * FROM (VALUES ('0x0000000000000000000000000000000000000000', 'ETH', 'Ethereum', 18), ('0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48', 'USDC', 'USD Coin', 6)) AS t (address, symbol, name, decimals)) SELECT date, t.symbol, SUM(amount) / pow(10, t.decimals) AS amount FROM (SELECT date(to_timestamp(block_timestamp) AT TIME ZONE 'utc') AS date, token, amount FROM "swap_multi" AS sm, UNNEST(sm.amounts_in, sm.tokens_in) AS smi (amount, token) UNION ALL SELECT date(to_timestamp(block_timestamp) AT TIME ZONE 'utc') AS date, token, amount FROM "swap_multi" AS sm, UNNEST(sm.amounts_out, sm.tokens_out) AS smo (amount, token)) AS tp JOIN tokens AS t ON t.address = '0x' || encode(tp.token, 'hex') GROUP BY tp.date, t.symbol, t.decimals ORDER BY tp.date DESC, amount DESC ) AS sub"#
173109
);
174110
}
111+
112+
#[test]
113+
fn parse_simple_sql() {
114+
let query =
115+
parse_and_validate("select symbol, address from token where decimals > 10").unwrap();
116+
117+
println!("{}", query);
118+
}
175119
}

0 commit comments

Comments
 (0)