-
Notifications
You must be signed in to change notification settings - Fork 5
remove transactions in queries #421
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -315,26 +315,17 @@ impl State { | |
sql::ast::TableReference::AliasedTable(alias) | ||
} | ||
|
||
/// Fetch the tracked native queries used in the query plan and their table alias. | ||
pub fn get_native_queries(self) -> Vec<NativeQueryInfo> { | ||
self.native_queries.native_queries | ||
} | ||
|
||
/// increment the table index and return the current one. | ||
fn next_global_table_index(&mut self) -> TableAliasIndex { | ||
let TableAliasIndex(index) = self.global_table_index; | ||
self.global_table_index = TableAliasIndex(index + 1); | ||
TableAliasIndex(index) | ||
/// Fetch the tracked native queries used in the query plan and their table alias, | ||
/// and the global table index. | ||
pub fn get_native_queries_and_global_index(self) -> (Vec<NativeQueryInfo>, TableAliasIndex) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We break down the state so we can consume the native queries when processing native queries, and use the global table alias index outside of it when inventing names for the wrapping ctes. |
||
(self.native_queries.native_queries, self.global_table_index) | ||
} | ||
|
||
// aliases | ||
|
||
/// Create table aliases using this function so they get a unique index. | ||
pub fn make_table_alias(&mut self, name: String) -> sql::ast::TableAlias { | ||
sql::ast::TableAlias { | ||
unique_index: self.next_global_table_index().0, | ||
name, | ||
} | ||
self.global_table_index.make_table_alias(name) | ||
} | ||
|
||
/// Create a table alias for left outer join lateral part. | ||
|
@@ -373,6 +364,23 @@ impl State { | |
} | ||
} | ||
|
||
impl TableAliasIndex { | ||
/// increment the table index and return the current one. | ||
fn next_global_table_index(&mut self) -> TableAliasIndex { | ||
let index = self.0; | ||
*self = TableAliasIndex(index + 1); | ||
TableAliasIndex(index) | ||
} | ||
|
||
/// Create table aliases using this function so they get a unique index. | ||
pub fn make_table_alias(&mut self, name: String) -> sql::ast::TableAlias { | ||
sql::ast::TableAlias { | ||
unique_index: self.next_global_table_index().0, | ||
name, | ||
} | ||
} | ||
} | ||
|
||
impl NativeQueries { | ||
fn new() -> NativeQueries { | ||
NativeQueries { | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -257,7 +257,8 @@ fn translate_native_query( | |
|
||
// add the procedure native query definition is a with clause. | ||
select.with = sql::ast::With { | ||
common_table_expressions: crate::translation::query::native_queries::translate(env, state)?, | ||
common_table_expressions: crate::translation::query::native_queries::translate(env, state)? | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. mutations do need to run native queries at the top-level, because they are mutations. So we don't wrap the ctes here. |
||
.0, | ||
}; | ||
|
||
// normalize ast | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -19,7 +19,6 @@ use query_engine_sql::sql; | |
/// Translate the incoming QueryRequest to an ExecutionPlan (SQL) to be run against the database. | ||
pub fn translate( | ||
metadata: &metadata::Metadata, | ||
isolation_level: sql::ast::transaction::IsolationLevel, | ||
query_request: models::QueryRequest, | ||
) -> Result<sql::execution_plan::ExecutionPlan<sql::execution_plan::Query>, Error> { | ||
let mut state = State::new(); | ||
|
@@ -66,7 +65,13 @@ pub fn translate( | |
&state.make_table_alias("universe_agg".to_string()), | ||
// native queries if there are any | ||
sql::ast::With { | ||
common_table_expressions: native_queries::translate(&env, state)?, | ||
common_table_expressions: { | ||
let (ctes, mut global_table_index) = native_queries::translate(&env, state)?; | ||
// wrap ctes in another cte to guard against mutations in queries | ||
ctes.into_iter() | ||
.map(|cte| native_queries::wrap_cte_in_cte(&mut global_table_index, cte)) | ||
.collect() | ||
}, | ||
Comment on lines
+68
to
+74
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. here we wrap. |
||
}, | ||
select_set, | ||
); | ||
|
@@ -75,7 +80,6 @@ pub fn translate( | |
let json_select = sql::rewrites::constant_folding::normalize_select(json_select); | ||
|
||
Ok(sql::execution_plan::simple_query_execution_plan( | ||
isolation_level, | ||
query_request.variables, | ||
query_request.collection, | ||
json_select, | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,15 +4,18 @@ use ndc_sdk::models; | |
|
||
use super::values; | ||
use crate::translation::error::Error; | ||
use crate::translation::helpers::{Env, State}; | ||
use crate::translation::helpers::{Env, State, TableAliasIndex}; | ||
use query_engine_metadata::metadata; | ||
use query_engine_sql::sql; | ||
|
||
/// Translate native queries collected in State by the translation proccess into CTEs. | ||
pub fn translate(env: &Env, state: State) -> Result<Vec<sql::ast::CommonTableExpression>, Error> { | ||
pub fn translate( | ||
env: &Env, | ||
state: State, | ||
) -> Result<(Vec<sql::ast::CommonTableExpression>, TableAliasIndex), Error> { | ||
let mut ctes = vec![]; | ||
let variables_table = env.get_variables_table(); | ||
let native_queries = state.get_native_queries(); | ||
let (native_queries, global_table_index) = state.get_native_queries_and_global_index(); | ||
|
||
// We need a 'State' value when translating variables in order | ||
// to be able to generate fresh names for bound relational | ||
|
@@ -72,5 +75,38 @@ pub fn translate(env: &Env, state: State) -> Result<Vec<sql::ast::CommonTableExp | |
}); | ||
} | ||
|
||
Ok(ctes) | ||
Ok((ctes, global_table_index)) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We return the global table index here as well so it can be used when wrapping ctes, but the native queries with the state is consumed. |
||
} | ||
|
||
/// Wrap a CTE in another CTE so we can guard against mutations in queries. | ||
pub fn wrap_cte_in_cte( | ||
table_alias_index: &mut TableAliasIndex, | ||
mut cte: sql::ast::CommonTableExpression, | ||
) -> sql::ast::CommonTableExpression { | ||
// This is the name the rest of the query knows, so we keep it on the outer parts. | ||
let outer_cte_alias = cte.alias; | ||
|
||
// this is going to be internal, so we replace the CTE. | ||
cte.alias = table_alias_index.make_table_alias(outer_cte_alias.name.clone()); | ||
|
||
// build the internal `WITH <CTE> SELECT * FROM CTE as <nested_cte_alias>`. | ||
let nested_cte_alias = table_alias_index.make_table_alias(outer_cte_alias.name.clone()); | ||
|
||
let nested_cte_select = sql::ast::CTExpr::Select({ | ||
let mut select = sql::helpers::star_select(sql::ast::From::Table { | ||
reference: sql::ast::TableReference::AliasedTable(cte.alias.clone()), | ||
alias: nested_cte_alias.clone(), | ||
}); | ||
select.with = sql::ast::With { | ||
common_table_expressions: vec![cte], | ||
}; | ||
select | ||
}); | ||
|
||
// wrap in another CTE. | ||
sql::ast::CommonTableExpression { | ||
alias: outer_cte_alias, | ||
column_names: None, | ||
select: nested_cte_select, | ||
} | ||
Comment on lines
+81
to
+111
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. how to wrap ctes. |
||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,9 +2,6 @@ | |
source: crates/query-engine/translation/tests/tests.rs | ||
expression: result | ||
--- | ||
BEGIN | ||
ISOLATION LEVEL READ COMMITTED READ ONLY; | ||
|
||
SELECT | ||
coalesce(json_agg("%8_universe_agg"."universe"), '[]') AS "universe" | ||
FROM | ||
|
@@ -15,16 +12,22 @@ FROM | |
jsonb_to_recordset($1) AS "%0_%variables_table"("%variable_order" int, "%variables" jsonb) | ||
CROSS JOIN LATERAL ( | ||
WITH "%2_NATIVE_QUERY_array_series" AS ( | ||
SELECT | ||
3 as three, | ||
array_agg(arr.series) AS series | ||
FROM | ||
( | ||
SELECT | ||
generate_series( | ||
cast( | ||
( | ||
("%0_%variables_table"."%variables" -> $2) #>> cast(ARRAY [] as text[])) as int4),cast((("%0_%variables_table"."%variables" -> $3) #>> cast(ARRAY [] as text[])) as int4)) AS series) AS arr | ||
WITH "%9_NATIVE_QUERY_array_series" AS ( | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. an example of a wrapping. |
||
SELECT | ||
3 as three, | ||
array_agg(arr.series) AS series | ||
FROM | ||
( | ||
SELECT | ||
generate_series( | ||
cast( | ||
( | ||
("%0_%variables_table"."%variables" -> $2) #>> cast(ARRAY [] as text[])) as int4),cast((("%0_%variables_table"."%variables" -> $3) #>> cast(ARRAY [] as text[])) as int4)) AS series) AS arr | ||
) | ||
SELECT | ||
* | ||
FROM | ||
"%9_NATIVE_QUERY_array_series" AS "%10_NATIVE_QUERY_array_series" | ||
) | ||
SELECT | ||
* | ||
|
@@ -52,8 +55,6 @@ FROM | |
( | ||
"%3_array"."element" #>> cast(ARRAY [] as text[])) as int4)) AS "element" FROM jsonb_array_elements(("%0_%variables_table"."%variables" -> $4)) AS "%3_array"("element"))) AS "%4_in_subquery"("value")))) AS "%6_rows") AS "%6_rows") AS "%5_universe" ORDER BY "%0_%variables_table"."%variable_order" ASC ) AS "%8_universe_agg"; | ||
|
||
COMMIT; | ||
|
||
{ | ||
1: Variable( | ||
"%VARIABLES_OBJECT_PLACEHOLDER", | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No more begin and commit for queries.