From 3834f441c4ebbc489da9bf0f515c844e08baefc1 Mon Sep 17 00:00:00 2001 From: Diego Reis Date: Wed, 30 Jul 2025 21:06:50 -0300 Subject: [PATCH] Accept parsing SET statements with repeated names, like `.. SET (a, a) = (1, 2)` --- core/translate/display.rs | 2 +- core/translate/emitter.rs | 1 - vendored/sqlite3-parser/src/parser/ast/mod.rs | 36 ++++++++++++++++++- vendored/sqlite3-parser/src/parser/parse.y | 14 +++++--- 4 files changed, 46 insertions(+), 7 deletions(-) diff --git a/core/translate/display.rs b/core/translate/display.rs index 73878f771..21344c025 100644 --- a/core/translate/display.rs +++ b/core/translate/display.rs @@ -557,7 +557,7 @@ impl ToTokens for UpdatePlan { .unwrap(); ast::Set { - col_names: ast::DistinctNames::single(ast::Name::from_str(col_name)), + col_names: ast::Names::single(ast::Name::from_str(col_name)), expr: set_expr.clone(), } }), diff --git a/core/translate/emitter.rs b/core/translate/emitter.rs index 288ab3a80..9684696d7 100644 --- a/core/translate/emitter.rs +++ b/core/translate/emitter.rs @@ -825,7 +825,6 @@ fn emit_update_insns( }); // Check if rowid was provided (through INTEGER PRIMARY KEY as a rowid alias) - let rowid_alias_index = table_ref.columns().iter().position(|c| c.is_rowid_alias); let has_user_provided_rowid = if let Some(index) = rowid_alias_index { diff --git a/vendored/sqlite3-parser/src/parser/ast/mod.rs b/vendored/sqlite3-parser/src/parser/ast/mod.rs index d1e1ce501..605840f31 100644 --- a/vendored/sqlite3-parser/src/parser/ast/mod.rs +++ b/vendored/sqlite3-parser/src/parser/ast/mod.rs @@ -1292,6 +1292,39 @@ impl QualifiedName { } } +/// Ordered set of column names +#[derive(Clone, Debug, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct Names(Vec); + +impl Names { + /// Initialize + pub fn new(name: Name) -> Self { + let mut dn = Self(Vec::new()); + dn.0.push(name); + dn + } + /// Single column name + pub fn single(name: Name) -> Self { + let mut dn = Self(Vec::with_capacity(1)); + dn.0.push(name); + dn + } + /// Push name + pub fn insert(&mut self, name: Name) -> Result<(), ParserError> { + self.0.push(name); + Ok(()) + } +} + +impl Deref for Names { + type Target = Vec; + + fn deref(&self) -> &Vec { + &self.0 + } +} + /// Ordered set of distinct column names #[derive(Clone, Debug, PartialEq, Eq)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] @@ -1319,6 +1352,7 @@ impl DistinctNames { Ok(()) } } + impl Deref for DistinctNames { type Target = IndexSet; @@ -1735,7 +1769,7 @@ pub enum InsertBody { #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct Set { /// column name(s) - pub col_names: DistinctNames, + pub col_names: Names, /// expression pub expr: Expr, } diff --git a/vendored/sqlite3-parser/src/parser/parse.y b/vendored/sqlite3-parser/src/parser/parse.y index dcc4c4d16..912c72bbb 100644 --- a/vendored/sqlite3-parser/src/parser/parse.y +++ b/vendored/sqlite3-parser/src/parser/parse.y @@ -802,22 +802,28 @@ cmd ::= with(C) UPDATE orconf(R) xfullname(X) indexed_opt(I) SET setlist(Y) from } %endif +%type reidlist {Names} +reidlist(A) ::= reidlist(A) COMMA nm(Y). + {let id = Y; A.insert(id)?;} +reidlist(A) ::= nm(Y). + { A = Names::new(Y); /*A-overwrites-Y*/} %type setlist {Vec} setlist(A) ::= setlist(A) COMMA nm(X) EQ expr(Y). { - let s = Set{ col_names: DistinctNames::single(X), expr: Y }; + let s = Set{ col_names: Names::single(X), expr: Y }; A.push(s); } -setlist(A) ::= setlist(A) COMMA LP idlist(X) RP EQ expr(Y). { +setlist(A) ::= setlist(A) COMMA LP reidlist(X) RP EQ expr(Y). { let s = Set{ col_names: X, expr: Y }; A.push(s); } setlist(A) ::= nm(X) EQ expr(Y). { - A = vec![Set{ col_names: DistinctNames::single(X), expr: Y }]; + A = vec![Set{ col_names: Names::single(X), expr: Y }]; + } -setlist(A) ::= LP idlist(X) RP EQ expr(Y). { +setlist(A) ::= LP reidlist(X) RP EQ expr(Y). { A = vec![Set{ col_names: X, expr: Y }]; }