From 670dac59399ed17006c77ceb54ca5c391ab12f35 Mon Sep 17 00:00:00 2001 From: Jussi Saurio Date: Sat, 8 Feb 2025 18:04:39 +0200 Subject: [PATCH 1/8] sqlite3-parser: box the where clause in Delete --- core/translate/delete.rs | 11 ++++++++--- vendored/sqlite3-parser/src/parser/ast/mod.rs | 2 +- vendored/sqlite3-parser/src/parser/parse.y | 4 ++-- 3 files changed, 11 insertions(+), 6 deletions(-) diff --git a/core/translate/delete.rs b/core/translate/delete.rs index ffad33d73..b5ce85fdc 100644 --- a/core/translate/delete.rs +++ b/core/translate/delete.rs @@ -13,7 +13,7 @@ pub fn translate_delete( query_mode: QueryMode, schema: &Schema, tbl_name: &QualifiedName, - where_clause: Option, + where_clause: Option>, limit: Option>, syms: &SymbolTable, ) -> Result { @@ -35,7 +35,7 @@ pub fn translate_delete( pub fn prepare_delete_plan( schema: &Schema, tbl_name: &QualifiedName, - where_clause: Option, + where_clause: Option>, limit: Option>, ) -> Result { let table = match schema.get_table(tbl_name.name.0.as_str()) { @@ -53,7 +53,12 @@ pub fn prepare_delete_plan( let mut where_predicates = vec![]; // Parse the WHERE clause - parse_where(where_clause, &table_references, None, &mut where_predicates)?; + parse_where( + where_clause.map(|e| *e), + &table_references, + None, + &mut where_predicates, + )?; // Parse the LIMIT/OFFSET clause let (resolved_limit, resolved_offset) = limit.map_or(Ok((None, None)), |l| parse_limit(*l))?; diff --git a/vendored/sqlite3-parser/src/parser/ast/mod.rs b/vendored/sqlite3-parser/src/parser/ast/mod.rs index f149322b3..077f2b6ac 100644 --- a/vendored/sqlite3-parser/src/parser/ast/mod.rs +++ b/vendored/sqlite3-parser/src/parser/ast/mod.rs @@ -168,7 +168,7 @@ pub enum Stmt { /// `INDEXED` indexed: Option, /// `WHERE` clause - where_clause: Option, + where_clause: Option>, /// `RETURNING` returning: Option>, /// `ORDER BY` diff --git a/vendored/sqlite3-parser/src/parser/parse.y b/vendored/sqlite3-parser/src/parser/parse.y index 226dca5a7..76c053964 100644 --- a/vendored/sqlite3-parser/src/parser/parse.y +++ b/vendored/sqlite3-parser/src/parser/parse.y @@ -761,13 +761,13 @@ limit_opt(A) ::= LIMIT expr(X) COMMA expr(Y). cmd ::= with(C) DELETE FROM xfullname(X) indexed_opt(I) where_opt_ret(W) orderby_opt(O) limit_opt(L). { let (where_clause, returning) = W; - self.ctx.stmt = Some(Stmt::Delete{ with: C, tbl_name: X, indexed: I, where_clause, returning, + self.ctx.stmt = Some(Stmt::Delete{ with: C, tbl_name: X, indexed: I, where_clause: where_clause.map(Box::new), returning, order_by: O, limit: L }); } %else cmd ::= with(C) DELETE FROM xfullname(X) indexed_opt(I) where_opt_ret(W). { let (where_clause, returning) = W; - self.ctx.stmt = Some(Stmt::Delete{ with: C, tbl_name: X, indexed: I, where_clause, returning, + self.ctx.stmt = Some(Stmt::Delete{ with: C, tbl_name: X, indexed: I, where_clause: where_clause.map(Box::new), returning, order_by: None, limit: None }); } %endif From 0dba39b025f82905fca2d3e504f999450d2b55e8 Mon Sep 17 00:00:00 2001 From: Jussi Saurio Date: Sat, 8 Feb 2025 18:05:13 +0200 Subject: [PATCH 2/8] sqlite3-parser: box everything in Attach --- vendored/sqlite3-parser/src/parser/ast/mod.rs | 6 +++--- vendored/sqlite3-parser/src/parser/parse.y | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/vendored/sqlite3-parser/src/parser/ast/mod.rs b/vendored/sqlite3-parser/src/parser/ast/mod.rs index 077f2b6ac..a60d2a592 100644 --- a/vendored/sqlite3-parser/src/parser/ast/mod.rs +++ b/vendored/sqlite3-parser/src/parser/ast/mod.rs @@ -78,11 +78,11 @@ pub enum Stmt { Attach { /// filename // TODO distinction between ATTACH and ATTACH DATABASE - expr: Expr, + expr: Box, /// schema name - db_name: Expr, + db_name: Box, /// password - key: Option, + key: Option>, }, /// `BEGIN`: tx type, tx name Begin(Option, Option), diff --git a/vendored/sqlite3-parser/src/parser/parse.y b/vendored/sqlite3-parser/src/parser/parse.y index 76c053964..0750af969 100644 --- a/vendored/sqlite3-parser/src/parser/parse.y +++ b/vendored/sqlite3-parser/src/parser/parse.y @@ -1276,7 +1276,7 @@ cmd ::= DROP TRIGGER ifexists(NOERR) fullname(X). { //////////////////////// ATTACH DATABASE file AS name ///////////////////////// %ifndef SQLITE_OMIT_ATTACH cmd ::= ATTACH database_kw_opt expr(F) AS expr(D) key_opt(K). { - self.ctx.stmt = Some(Stmt::Attach{ expr: F, db_name: D, key: K }); + self.ctx.stmt = Some(Stmt::Attach{ expr: Box::new(F), db_name: Box::new(D), key: K.map(Box::new) }); } cmd ::= DETACH database_kw_opt expr(D). { self.ctx.stmt = Some(Stmt::Detach(D)); From f341474fee3c76869fd49e8e6f43ebf7234c0e86 Mon Sep 17 00:00:00 2001 From: Jussi Saurio Date: Sat, 8 Feb 2025 18:05:49 +0200 Subject: [PATCH 3/8] sqlite3-parser: box large members of CreateTrigger --- vendored/sqlite3-parser/src/parser/ast/mod.rs | 4 ++-- vendored/sqlite3-parser/src/parser/parse.y | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/vendored/sqlite3-parser/src/parser/ast/mod.rs b/vendored/sqlite3-parser/src/parser/ast/mod.rs index a60d2a592..91f5633e3 100644 --- a/vendored/sqlite3-parser/src/parser/ast/mod.rs +++ b/vendored/sqlite3-parser/src/parser/ast/mod.rs @@ -125,13 +125,13 @@ pub enum Stmt { /// `BEFORE`/`AFTER`/`INSTEAD OF` time: Option, /// `DELETE`/`INSERT`/`UPDATE` - event: TriggerEvent, + event: Box, /// table name tbl_name: QualifiedName, /// `FOR EACH ROW` for_each_row: bool, /// `WHEN` - when_clause: Option, + when_clause: Option>, /// statements commands: Vec, }, diff --git a/vendored/sqlite3-parser/src/parser/parse.y b/vendored/sqlite3-parser/src/parser/parse.y index 0750af969..694bb4216 100644 --- a/vendored/sqlite3-parser/src/parser/parse.y +++ b/vendored/sqlite3-parser/src/parser/parse.y @@ -1167,8 +1167,8 @@ minus_num(A) ::= MINUS number(X). {A = Expr::unary(UnaryOperator::Negative, cmd ::= createkw temp(T) TRIGGER ifnotexists(NOERR) fullname(B) trigger_time(C) trigger_event(D) ON fullname(E) foreach_clause(X) when_clause(G) BEGIN trigger_cmd_list(S) END. { self.ctx.stmt = Some(Stmt::CreateTrigger{ - temporary: T, if_not_exists: NOERR, trigger_name: B, time: C, event: D, tbl_name: E, - for_each_row: X, when_clause: G, commands: S + temporary: T, if_not_exists: NOERR, trigger_name: B, time: C, event: Box::new(D), tbl_name: E, + for_each_row: X, when_clause: G.map(Box::new), commands: S }); } From ac7f9d67b7c62d41cb43491128dffa0b8bc04ef7 Mon Sep 17 00:00:00 2001 From: Jussi Saurio Date: Sat, 8 Feb 2025 18:06:45 +0200 Subject: [PATCH 4/8] sqlite3-parser: box large members of Upsert --- vendored/sqlite3-parser/src/parser/ast/mod.rs | 4 ++-- vendored/sqlite3-parser/src/parser/parse.y | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/vendored/sqlite3-parser/src/parser/ast/mod.rs b/vendored/sqlite3-parser/src/parser/ast/mod.rs index 91f5633e3..ffeafea07 100644 --- a/vendored/sqlite3-parser/src/parser/ast/mod.rs +++ b/vendored/sqlite3-parser/src/parser/ast/mod.rs @@ -1769,9 +1769,9 @@ pub enum TransactionType { #[derive(Clone, Debug, PartialEq, Eq)] pub struct Upsert { /// conflict targets - pub index: Option, + pub index: Option>, /// `DO` clause - pub do_clause: UpsertDo, + pub do_clause: Box, /// next upsert pub next: Option>, } diff --git a/vendored/sqlite3-parser/src/parser/parse.y b/vendored/sqlite3-parser/src/parser/parse.y index 694bb4216..af16eefa2 100644 --- a/vendored/sqlite3-parser/src/parser/parse.y +++ b/vendored/sqlite3-parser/src/parser/parse.y @@ -851,16 +851,16 @@ upsert(A) ::= ON CONFLICT LP sortlist(T) RP where_opt(TW) { let index = UpsertIndex{ targets: T, where_clause: TW }; let do_clause = UpsertDo::Set{ sets: Z, where_clause: W }; let (next, returning) = N; - A = (Some(Upsert{ index: Some(index), do_clause, next: next.map(Box::new) }), returning);} + A = (Some(Upsert{ index: Some(Box::new(index)), do_clause: Box::new(do_clause), next: next.map(Box::new) }), returning);} upsert(A) ::= ON CONFLICT LP sortlist(T) RP where_opt(TW) DO NOTHING upsert(N). { let index = UpsertIndex{ targets: T, where_clause: TW }; let (next, returning) = N; - A = (Some(Upsert{ index: Some(index), do_clause: UpsertDo::Nothing, next: next.map(Box::new) }), returning); } + A = (Some(Upsert{ index: Some(Box::new(index)), do_clause: Box::new(UpsertDo::Nothing), next: next.map(Box::new) }), returning); } upsert(A) ::= ON CONFLICT DO NOTHING returning(R). - { A = (Some(Upsert{ index: None, do_clause: UpsertDo::Nothing, next: None }), R); } + { A = (Some(Upsert{ index: None, do_clause: Box::new(UpsertDo::Nothing), next: None }), R); } upsert(A) ::= ON CONFLICT DO UPDATE SET setlist(Z) where_opt(W) returning(R). { let do_clause = UpsertDo::Set{ sets: Z, where_clause: W }; - A = (Some(Upsert{ index: None, do_clause, next: None }), R);} + A = (Some(Upsert{ index: None, do_clause: Box::new(do_clause), next: None }), R);} %type returning {Option>} returning(A) ::= RETURNING selcollist(X). {A = Some(X);} From 74262042040ffef407ffe516c11d967fde89ef32 Mon Sep 17 00:00:00 2001 From: Jussi Saurio Date: Sat, 8 Feb 2025 18:07:38 +0200 Subject: [PATCH 5/8] sqlite3-parser: box Following and Preceding in FrameBound --- vendored/sqlite3-parser/src/parser/ast/mod.rs | 4 ++-- vendored/sqlite3-parser/src/parser/parse.y | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/vendored/sqlite3-parser/src/parser/ast/mod.rs b/vendored/sqlite3-parser/src/parser/ast/mod.rs index ffeafea07..f8534e9a3 100644 --- a/vendored/sqlite3-parser/src/parser/ast/mod.rs +++ b/vendored/sqlite3-parser/src/parser/ast/mod.rs @@ -1872,9 +1872,9 @@ pub enum FrameBound { /// `CURRENT ROW` CurrentRow, /// `FOLLOWING` - Following(Expr), + Following(Box), /// `PRECEDING` - Preceding(Expr), + Preceding(Box), /// `UNBOUNDED FOLLOWING` UnboundedFollowing, /// `UNBOUNDED PRECEDING` diff --git a/vendored/sqlite3-parser/src/parser/parse.y b/vendored/sqlite3-parser/src/parser/parse.y index af16eefa2..0f17415e4 100644 --- a/vendored/sqlite3-parser/src/parser/parse.y +++ b/vendored/sqlite3-parser/src/parser/parse.y @@ -1454,9 +1454,9 @@ frame_bound_s(A) ::= UNBOUNDED PRECEDING. {A = FrameBound::UnboundedPreceding;} frame_bound_e(A) ::= frame_bound(X). {A = X;} frame_bound_e(A) ::= UNBOUNDED FOLLOWING. {A = FrameBound::UnboundedFollowing;} -frame_bound(A) ::= expr(X) PRECEDING. { A = FrameBound::Preceding(X); } +frame_bound(A) ::= expr(X) PRECEDING. { A = FrameBound::Preceding(Box::new(X)); } frame_bound(A) ::= CURRENT ROW. { A = FrameBound::CurrentRow; } -frame_bound(A) ::= expr(X) FOLLOWING. { A = FrameBound::Following(X); } +frame_bound(A) ::= expr(X) FOLLOWING. { A = FrameBound::Following(Box::new(X)); } %type frame_exclude_opt {Option} frame_exclude_opt(A) ::= . {A = None;} From 2a82091cb38be49a28ccb8c4fe57df2d464d3a73 Mon Sep 17 00:00:00 2001 From: Jussi Saurio Date: Sat, 8 Feb 2025 18:08:31 +0200 Subject: [PATCH 6/8] sqlite3-parser: box the where clause in Update --- vendored/sqlite3-parser/src/parser/ast/mod.rs | 2 +- vendored/sqlite3-parser/src/parser/parse.y | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/vendored/sqlite3-parser/src/parser/ast/mod.rs b/vendored/sqlite3-parser/src/parser/ast/mod.rs index f8534e9a3..b9e662683 100644 --- a/vendored/sqlite3-parser/src/parser/ast/mod.rs +++ b/vendored/sqlite3-parser/src/parser/ast/mod.rs @@ -256,7 +256,7 @@ pub enum Stmt { /// `FROM` from: Option, /// `WHERE` clause - where_clause: Option, + where_clause: Option>, /// `RETURNING` returning: Option>, /// `ORDER BY` diff --git a/vendored/sqlite3-parser/src/parser/parse.y b/vendored/sqlite3-parser/src/parser/parse.y index 0f17415e4..7fb578158 100644 --- a/vendored/sqlite3-parser/src/parser/parse.y +++ b/vendored/sqlite3-parser/src/parser/parse.y @@ -791,14 +791,14 @@ cmd ::= with(C) UPDATE orconf(R) xfullname(X) indexed_opt(I) SET setlist(Y) from where_opt_ret(W) orderby_opt(O) limit_opt(L). { let (where_clause, returning) = W; self.ctx.stmt = Some(Stmt::Update { with: C, or_conflict: R, tbl_name: X, indexed: I, sets: Y, from: F, - where_clause, returning, order_by: O, limit: L }); + where_clause: where_clause.map(Box::new), returning, order_by: O, limit: L }); } %else cmd ::= with(C) UPDATE orconf(R) xfullname(X) indexed_opt(I) SET setlist(Y) from(F) where_opt_ret(W). { let (where_clause, returning) = W; self.ctx.stmt = Some(Stmt::Update { with: C, or_conflict: R, tbl_name: X, indexed: I, sets: Y, from: F, - where_clause, returning, order_by: None, limit: None }); + where_clause: where_clause.map(Box::new), returning, order_by: None, limit: None }); } %endif From 781aa3b5d61d919d429e877957285abc2fc08565 Mon Sep 17 00:00:00 2001 From: Jussi Saurio Date: Sat, 8 Feb 2025 18:08:54 +0200 Subject: [PATCH 7/8] sqlite3-parser: box the having clause in GroupBy --- core/translate/select.rs | 2 +- vendored/sqlite3-parser/src/parser/ast/mod.rs | 2 +- vendored/sqlite3-parser/src/parser/parse.y | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/core/translate/select.rs b/core/translate/select.rs index 2a055afd2..b5091af64 100644 --- a/core/translate/select.rs +++ b/core/translate/select.rs @@ -305,7 +305,7 @@ pub fn prepare_select_plan( exprs: group_by.exprs, having: if let Some(having) = group_by.having { let mut predicates = vec![]; - break_predicate_at_and_boundaries(having, &mut predicates); + break_predicate_at_and_boundaries(*having, &mut predicates); for expr in predicates.iter_mut() { bind_column_references( expr, diff --git a/vendored/sqlite3-parser/src/parser/ast/mod.rs b/vendored/sqlite3-parser/src/parser/ast/mod.rs index b9e662683..43f2c5dfb 100644 --- a/vendored/sqlite3-parser/src/parser/ast/mod.rs +++ b/vendored/sqlite3-parser/src/parser/ast/mod.rs @@ -1005,7 +1005,7 @@ pub struct GroupBy { /// expressions pub exprs: Vec, /// `HAVING` - pub having: Option, // HAVING clause on a non-aggregate query + pub having: Option>, // HAVING clause on a non-aggregate query } /// identifier or one of several keywords or `INDEXED` diff --git a/vendored/sqlite3-parser/src/parser/parse.y b/vendored/sqlite3-parser/src/parser/parse.y index 7fb578158..6402a6d5d 100644 --- a/vendored/sqlite3-parser/src/parser/parse.y +++ b/vendored/sqlite3-parser/src/parser/parse.y @@ -731,7 +731,7 @@ nulls(A) ::= . {A = None;} %type groupby_opt {Option} groupby_opt(A) ::= . {A = None;} -groupby_opt(A) ::= GROUP BY nexprlist(X) having_opt(Y). {A = Some(GroupBy{ exprs: X, having: Y });} +groupby_opt(A) ::= GROUP BY nexprlist(X) having_opt(Y). {A = Some(GroupBy{ exprs: X, having: Y.map(Box::new) });} %type having_opt {Option} having_opt(A) ::= . {A = None;} From 4faadd86b0af548d3d176181f7dac516ea45acde Mon Sep 17 00:00:00 2001 From: Jussi Saurio Date: Sat, 8 Feb 2025 18:09:58 +0200 Subject: [PATCH 8/8] sqlite3-parser: box the InsertBody --- .../sqlite3-parser/src/parser/ast/check.rs | 20 +++++++++---------- vendored/sqlite3-parser/src/parser/ast/mod.rs | 2 +- vendored/sqlite3-parser/src/parser/parse.y | 4 ++-- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/vendored/sqlite3-parser/src/parser/ast/check.rs b/vendored/sqlite3-parser/src/parser/ast/check.rs index e1e0eecd3..ca1e8cb55 100644 --- a/vendored/sqlite3-parser/src/parser/ast/check.rs +++ b/vendored/sqlite3-parser/src/parser/ast/check.rs @@ -160,19 +160,19 @@ impl Stmt { } => Err(custom_err!("ORDER BY without LIMIT on DELETE")), Self::Insert { columns: Some(columns), - body: InsertBody::Select(select, ..), + body, .. - } => match select.body.select.column_count() { - ColumnCount::Fixed(n) if n != columns.len() => { - Err(custom_err!("{} values for {} columns", n, columns.len())) + } => match &**body { + InsertBody::Select(select, ..) => match select.body.select.column_count() { + ColumnCount::Fixed(n) if n != columns.len() => { + Err(custom_err!("{} values for {} columns", n, columns.len())) + } + _ => Ok(()), + }, + InsertBody::DefaultValues => { + Err(custom_err!("0 values for {} columns", columns.len())) } - _ => Ok(()), }, - Self::Insert { - columns: Some(columns), - body: InsertBody::DefaultValues, - .. - } => Err(custom_err!("0 values for {} columns", columns.len())), Self::Update { order_by: Some(_), limit: None, diff --git a/vendored/sqlite3-parser/src/parser/ast/mod.rs b/vendored/sqlite3-parser/src/parser/ast/mod.rs index 43f2c5dfb..8cf4f805d 100644 --- a/vendored/sqlite3-parser/src/parser/ast/mod.rs +++ b/vendored/sqlite3-parser/src/parser/ast/mod.rs @@ -217,7 +217,7 @@ pub enum Stmt { /// `COLUMNS` columns: Option, /// `VALUES` or `SELECT` - body: InsertBody, + body: Box, /// `RETURNING` returning: Option>, }, diff --git a/vendored/sqlite3-parser/src/parser/parse.y b/vendored/sqlite3-parser/src/parser/parse.y index 6402a6d5d..bb3c80e91 100644 --- a/vendored/sqlite3-parser/src/parser/parse.y +++ b/vendored/sqlite3-parser/src/parser/parse.y @@ -828,13 +828,13 @@ cmd ::= with(W) insert_cmd(R) INTO xfullname(X) idlist_opt(F) select(S) let (upsert, returning) = U; let body = InsertBody::Select(Box::new(S), upsert); self.ctx.stmt = Some(Stmt::Insert{ with: W, or_conflict: R, tbl_name: X, columns: F, - body, returning }); + body: Box::new(body), returning }); } cmd ::= with(W) insert_cmd(R) INTO xfullname(X) idlist_opt(F) DEFAULT VALUES returning(Y). { let body = InsertBody::DefaultValues; self.ctx.stmt = Some(Stmt::Insert{ with: W, or_conflict: R, tbl_name: X, columns: F, - body, returning: Y }); + body: Box::new(body), returning: Y }); } %type upsert {(Option, Option>)}