Skip to content

Commit 37dafa8

Browse files
committed
store: Revamp query rewriting
1. Do not use CTE's to inject a view of a table at a certain block. Instead rewrite the 'from' clause 2. Do not turn bytea columns into string columns since that is hugely wasteful
1 parent 3574aea commit 37dafa8

File tree

3 files changed

+32
-8
lines changed

3 files changed

+32
-8
lines changed

store/postgres/src/query_store.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ impl QueryStore {
3030
) -> Self {
3131
let sql_parser = store
3232
.find_layout(site.clone())
33-
.map(|layout| Parser::new(layout));
33+
.map(|layout| Parser::new(layout, BLOCK_NUMBER_MAX));
3434
QueryStore {
3535
site,
3636
replica_id,

store/postgres/src/sql/parser.rs

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,23 @@
11
use super::{constants::SQL_DIALECT, validation::Validator};
22
use crate::relational::Layout;
33
use anyhow::{anyhow, Ok, Result};
4+
use graph::prelude::BlockNumber;
45
use std::sync::Arc;
56

67
pub struct Parser {
78
layout: Arc<Layout>,
9+
block: BlockNumber,
810
}
911

1012
impl Parser {
11-
pub fn new(layout: Arc<Layout>) -> Self {
12-
Self { layout }
13+
pub fn new(layout: Arc<Layout>, block: BlockNumber) -> Self {
14+
Self { layout, block }
1315
}
1416

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

18-
let mut validator = Validator::new(&self.layout);
20+
let mut validator = Validator::new(&self.layout, self.block);
1921
validator.validate_statements(&mut statements)?;
2022

2123
let statement = statements
@@ -33,6 +35,8 @@ impl Parser {
3335
#[cfg(test)]
3436
mod test {
3537

38+
use graph::prelude::BLOCK_NUMBER_MAX;
39+
3640
use crate::sql::test::make_layout;
3741

3842
use super::*;
@@ -93,7 +97,7 @@ mod test {
9397
";
9498

9599
fn parse_and_validate(sql: &str) -> Result<String, anyhow::Error> {
96-
let parser = Parser::new(Arc::new(make_layout(TEST_GQL)));
100+
let parser = Parser::new(Arc::new(make_layout(TEST_GQL)), BLOCK_NUMBER_MAX);
97101

98102
parser.parse_and_validate(sql)
99103
}
@@ -114,6 +118,10 @@ mod test {
114118
let query =
115119
parse_and_validate("select symbol, address from token where decimals > 10").unwrap();
116120

121+
assert_eq!(
122+
query,
123+
r#"select to_jsonb(sub.*) as data from ( SELECT symbol, address FROM (SELECT * FROM "sgd0815"."token" WHERE block_range @> 2147483647) AS token WHERE decimals > 10 ) as sub"#
124+
);
117125
println!("{}", query);
118126
}
119127
}

store/postgres/src/sql/validation.rs

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use graph::prelude::BlockNumber;
12
use sqlparser::ast::{
23
Expr, Ident, ObjectName, Query, SetExpr, Statement, TableAlias, TableFactor, VisitMut,
34
VisitorMut,
@@ -6,6 +7,7 @@ use sqlparser::parser::Parser;
67
use std::result::Result;
78
use std::{collections::HashSet, ops::ControlFlow};
89

10+
use crate::block_range::{BLOCK_COLUMN, BLOCK_RANGE_COLUMN};
911
use crate::relational::Layout;
1012

1113
use super::constants::{ALLOWED_FUNCTIONS, SQL_DIALECT};
@@ -25,13 +27,15 @@ pub enum Error {
2527
pub struct Validator<'a> {
2628
layout: &'a Layout,
2729
ctes: HashSet<String>,
30+
block: BlockNumber,
2831
}
2932

3033
impl<'a> Validator<'a> {
31-
pub fn new(layout: &'a Layout) -> Self {
34+
pub fn new(layout: &'a Layout, block: BlockNumber) -> Self {
3235
Self {
3336
layout,
3437
ctes: Default::default(),
38+
block,
3539
}
3640
}
3741

@@ -113,7 +117,17 @@ impl VisitorMut for Validator<'_> {
113117
};
114118

115119
// Change 'from table [as alias]' to 'from (select * from table) as alias'
116-
let query = format!("select * from {}", table.qualified_name);
120+
let query = if table.immutable {
121+
format!(
122+
"select * from {} where {} <= {}",
123+
table.qualified_name, BLOCK_COLUMN, self.block
124+
)
125+
} else {
126+
format!(
127+
"select * from {} where {} @> {}",
128+
table.qualified_name, BLOCK_RANGE_COLUMN, self.block
129+
)
130+
};
117131
let Statement::Query(subquery) = Parser::parse_sql(&SQL_DIALECT, &query)
118132
.unwrap()
119133
.pop()
@@ -147,6 +161,8 @@ impl VisitorMut for Validator<'_> {
147161

148162
#[cfg(test)]
149163
mod test {
164+
use graph::prelude::BLOCK_NUMBER_MAX;
165+
150166
use super::*;
151167
use crate::sql::{constants::SQL_DIALECT, test::make_layout};
152168

@@ -170,7 +186,7 @@ mod test {
170186

171187
let layout = make_layout(GQL);
172188

173-
let mut validator = Validator::new(&layout);
189+
let mut validator = Validator::new(&layout, BLOCK_NUMBER_MAX);
174190

175191
validator.validate_statements(&mut statements)
176192
}

0 commit comments

Comments
 (0)