From f0fb05bb975b04d2317af283625c023e255b1c07 Mon Sep 17 00:00:00 2001 From: LucaCappelletti94 Date: Sat, 14 Nov 2026 11:30:23 +0100 Subject: [PATCH] PostgreSQL: Support subscripts in assignment and insert targets --- .../postgres_subscript_assignment_target.sql | 1 + src/ast/dml.rs | 8 +- src/ast/mod.rs | 44 +++++++++- src/ast/spans.rs | 15 +++- src/parser/merge.rs | 6 +- src/parser/mod.rs | 33 ++++++- tests/sqlparser_bigquery.rs | 4 +- tests/sqlparser_common.rs | 76 ++++++++++++---- tests/sqlparser_mysql.rs | 86 +++++++++---------- tests/sqlparser_oracle.rs | 6 +- tests/sqlparser_postgres.rs | 38 ++++---- tests/sqlparser_sqlite.rs | 4 +- 12 files changed, 220 insertions(+), 101 deletions(-) create mode 100644 fuzz/fuzz_seeds/postgres_subscript_assignment_target.sql diff --git a/fuzz/fuzz_seeds/postgres_subscript_assignment_target.sql b/fuzz/fuzz_seeds/postgres_subscript_assignment_target.sql new file mode 100644 index 0000000000..cedb2e212f --- /dev/null +++ b/fuzz/fuzz_seeds/postgres_subscript_assignment_target.sql @@ -0,0 +1 @@ +UPDATE u SET arr[1] = 5 \ No newline at end of file diff --git a/src/ast/dml.rs b/src/ast/dml.rs index f394db2686..e8b0f07bfb 100644 --- a/src/ast/dml.rs +++ b/src/ast/dml.rs @@ -33,8 +33,8 @@ use super::{ display_comma_separated, helpers::attached_token::AttachedToken, query::InputFormatClause, Assignment, Expr, FromTable, Ident, InsertAliases, MysqlInsertPriority, ObjectName, OnInsert, OptimizerHint, OrderByExpr, Query, SelectInto, SelectItem, Setting, SqliteOnConflict, - TableAliasWithoutColumns, TableFactor, TableObject, TableWithJoins, UpdateTableFromKind, - Values, + TableAliasWithoutColumns, TableFactor, TableObject, TableWithJoins, TargetColumn, + UpdateTableFromKind, Values, }; /// The `OVERRIDING` clause of a PostgreSQL `INSERT`: whether values supplied for an identity @@ -84,7 +84,7 @@ pub struct Insert { /// `table_name foo` (for Oracle) pub table_alias: Option, /// COLUMNS - pub columns: Vec, + pub columns: Vec, /// `BY NAME` clause used by Databricks SQL. /// /// When present, columns from the source query are matched to columns in @@ -784,7 +784,7 @@ pub struct MergeInsertExpr { /// INSERT (product, quantity) VALUES(product, quantity) /// INSERT (product, quantity) ROW /// ``` - pub columns: Vec, + pub columns: Vec, /// The token, `[VALUES | ROW]` starting `kind`. pub kind_token: AttachedToken, /// The insert type used by the statement. diff --git a/src/ast/mod.rs b/src/ast/mod.rs index 473b11a37b..432cbb3ade 100644 --- a/src/ast/mod.rs +++ b/src/ast/mod.rs @@ -8112,9 +8112,9 @@ impl fmt::Display for Assignment { #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub enum AssignmentTarget { /// A single column - ColumnName(ObjectName), + ColumnName(TargetColumn), /// A tuple of columns - Tuple(Vec), + Tuple(Vec), } impl fmt::Display for AssignmentTarget { @@ -8126,6 +8126,46 @@ impl fmt::Display for AssignmentTarget { } } +/// A column written by an assignment or listed in an `INSERT` column list, +/// e.g. `col`, `arr[1]` or `arr[1:2]`. +/// +/// [PostgreSQL](https://www.postgresql.org/docs/current/sql-update.html) +#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] +#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] +#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] +pub struct TargetColumn { + /// The column, e.g. `arr` in `arr[1].x`. + pub name: ObjectName, + /// Subscripts and the subfields after them, e.g. `[1]` and `.x` in `arr[1].x`. + pub access_chain: Vec, +} + +impl From for TargetColumn { + fn from(name: ObjectName) -> Self { + Self { + name, + access_chain: vec![], + } + } +} + +impl From for TargetColumn { + fn from(ident: Ident) -> Self { + ObjectName::from(ident).into() + } +} + +impl fmt::Display for TargetColumn { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!( + f, + "{}{}", + self.name, + display_separated(&self.access_chain, "") + ) + } +} + #[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] diff --git a/src/ast/spans.rs b/src/ast/spans.rs index bc6d8fa0d1..61cfdbec2a 100644 --- a/src/ast/spans.rs +++ b/src/ast/spans.rs @@ -49,8 +49,9 @@ use super::{ RefreshMaterializedView, RenameSelectItem, ReplaceSelectElement, ReplaceSelectItem, Select, SelectInto, SelectItem, SetExpr, Setting, SqlOption, Statement, Subscript, SymbolDefinition, TableAlias, TableAliasColumnDef, TableConstraint, TableFactor, TableObject, - TableOptionsClustered, TableWithJoins, Update, UpdateTableFromKind, Use, UserMappingUser, - Values, ViewColumnDef, WhileStatement, WildcardAdditionalOptions, With, WithFill, + TableOptionsClustered, TableWithJoins, TargetColumn, Update, UpdateTableFromKind, Use, + UserMappingUser, Values, ViewColumnDef, WhileStatement, WildcardAdditionalOptions, With, + WithFill, }; /// Given an iterator of spans, return the [Span::union] of all spans. @@ -1620,12 +1621,20 @@ impl Spanned for Setting { impl Spanned for AssignmentTarget { fn span(&self) -> Span { match self { - AssignmentTarget::ColumnName(object_name) => object_name.span(), + AssignmentTarget::ColumnName(column) => column.span(), AssignmentTarget::Tuple(vec) => union_spans(vec.iter().map(|i| i.span())), } } } +impl Spanned for TargetColumn { + fn span(&self) -> Span { + let TargetColumn { name, access_chain } = self; + + union_spans(iter::once(name.span()).chain(access_chain.iter().map(|i| i.span()))) + } +} + /// # partial span /// /// Most expressions are missing keywords in their spans. diff --git a/src/parser/merge.rs b/src/parser/merge.rs index 79a77df9d9..e63e22f140 100644 --- a/src/parser/merge.rs +++ b/src/parser/merge.rs @@ -18,7 +18,7 @@ use alloc::{boxed::Box, format, vec, vec::Vec}; use crate::{ ast::{ Merge, MergeAction, MergeClause, MergeClauseKind, MergeInsertExpr, MergeInsertKind, - MergeUpdateExpr, MergeUpdateKind, ObjectName, OutputClause, SetExpr, + MergeUpdateExpr, MergeUpdateKind, OutputClause, SetExpr, TargetColumn, }, dialect::{BigQueryDialect, GenericDialect, MySqlDialect}, keywords::Keyword, @@ -239,8 +239,8 @@ impl Parser<'_> { fn parse_merge_clause_insert_columns( &mut self, allow_empty: bool, - ) -> Result, ParserError> { - self.parse_parenthesized_qualified_column_list(IsOptional::Optional, allow_empty) + ) -> Result, ParserError> { + self.parse_parenthesized_target_column_list(IsOptional::Optional, allow_empty) } /// Parses an `OUTPUT` clause if present (MSSQL). diff --git a/src/parser/mod.rs b/src/parser/mod.rs index 76bd114071..5547ddd314 100644 --- a/src/parser/mod.rs +++ b/src/parser/mod.rs @@ -15062,6 +15062,18 @@ impl<'a> Parser<'a> { }) } + /// Parses a parenthesized comma-separated list of target columns. + /// For example: `(tbl.col1, arr[1], "col 2")` + fn parse_parenthesized_target_column_list( + &mut self, + optional: IsOptional, + allow_empty: bool, + ) -> Result, ParserError> { + self.parse_parenthesized_column_list_inner(optional, allow_empty, |p| { + p.parse_target_column(true) + }) + } + /// Parses a parenthesized comma-separated list of columns using /// the provided function to parse each element. fn parse_parenthesized_column_list_inner( @@ -19823,7 +19835,7 @@ impl<'a> Parser<'a> { } else { let (columns, partitioned, after_columns) = if !self.peek_subquery_start() { let columns = - self.parse_parenthesized_qualified_column_list(Optional, is_mysql)?; + self.parse_parenthesized_target_column_list(Optional, is_mysql)?; let partitioned = self.parse_insert_partition()?; by_name = self.parse_keywords(&[Keyword::BY, Keyword::NAME]); @@ -20190,15 +20202,30 @@ impl<'a> Parser<'a> { /// Parse the left-hand side of an assignment, used in an UPDATE statement pub fn parse_assignment_target(&mut self) -> Result { if self.consume_token(&Token::LParen) { - let columns = self.parse_comma_separated(|p| p.parse_object_name(false))?; + let columns = self.parse_comma_separated(|p| p.parse_target_column(false))?; self.expect_token(&Token::RParen)?; Ok(AssignmentTarget::Tuple(columns)) } else { - let column = self.parse_object_name(false)?; + let column = self.parse_target_column(false)?; Ok(AssignmentTarget::ColumnName(column)) } } + /// Parse a column written by an assignment or an `INSERT`, e.g. `col` or `arr[1].x`. + fn parse_target_column(&mut self, in_table_clause: bool) -> Result { + let name = self.parse_object_name(in_table_clause)?; + let mut access_chain = vec![]; + if !self.dialect.supports_partiql() { + self.parse_multi_dim_subscript(&mut access_chain)?; + while !access_chain.is_empty() && self.consume_token(&Token::Period) { + let field = self.parse_identifier()?; + access_chain.push(AccessExpr::Dot(Expr::Identifier(field))); + self.parse_multi_dim_subscript(&mut access_chain)?; + } + } + Ok(TargetColumn { name, access_chain }) + } + /// Parse a single function argument, handling named and unnamed variants. pub fn parse_function_args(&mut self) -> Result { // Parse the argument expression once, then check for a named-arg diff --git a/tests/sqlparser_bigquery.rs b/tests/sqlparser_bigquery.rs index f26e591aac..b8177fef8d 100644 --- a/tests/sqlparser_bigquery.rs +++ b/tests/sqlparser_bigquery.rs @@ -1850,11 +1850,11 @@ fn parse_merge() { update_token: AttachedToken::empty(), kind: MergeUpdateKind::Set(vec![ Assignment { - target: AssignmentTarget::ColumnName(ObjectName::from(vec![Ident::new("a")])), + target: AssignmentTarget::ColumnName(Ident::new("a").into()), value: Expr::value(number("1")), }, Assignment { - target: AssignmentTarget::ColumnName(ObjectName::from(vec![Ident::new("b")])), + target: AssignmentTarget::ColumnName(Ident::new("b").into()), value: Expr::value(number("2")), }, ]), diff --git a/tests/sqlparser_common.rs b/tests/sqlparser_common.rs index f2f7849154..677cf00863 100644 --- a/tests/sqlparser_common.rs +++ b/tests/sqlparser_common.rs @@ -174,7 +174,7 @@ fn parse_insert_values() { for (index, column) in columns.iter().enumerate() { assert_eq!( column, - &ObjectName::from(Ident::new(expected_columns[index].clone())) + &TargetColumn::from(Ident::new(expected_columns[index].clone())) ); } match *source.body { @@ -470,15 +470,15 @@ fn parse_update() { assignments, vec![ Assignment { - target: AssignmentTarget::ColumnName(ObjectName::from(vec!["a".into()])), + target: AssignmentTarget::ColumnName(Ident::new("a").into()), value: Expr::value(number("1")), }, Assignment { - target: AssignmentTarget::ColumnName(ObjectName::from(vec!["b".into()])), + target: AssignmentTarget::ColumnName(Ident::new("b").into()), value: Expr::value(number("2")), }, Assignment { - target: AssignmentTarget::ColumnName(ObjectName::from(vec!["c".into()])), + target: AssignmentTarget::ColumnName(Ident::new("c").into()), value: Expr::value(number("3")), }, ] @@ -530,7 +530,7 @@ fn parse_update_set_from() { }, on_cluster: None, assignments: vec![Assignment { - target: AssignmentTarget::ColumnName(ObjectName::from(vec![Ident::new("name")])), + target: AssignmentTarget::ColumnName(Ident::new("name").into()), value: Expr::CompoundIdentifier(vec![Ident::new("t2"), Ident::new("name")]) }], from: Some(UpdateTableFromKind::AfterSet(vec![TableWithJoins { @@ -651,10 +651,9 @@ fn parse_update_with_table_alias() { ); assert_eq!( vec![Assignment { - target: AssignmentTarget::ColumnName(ObjectName::from(vec![ - Ident::new("u"), - Ident::new("username") - ])), + target: AssignmentTarget::ColumnName( + ObjectName::from(vec![Ident::new("u"), Ident::new("username")]).into() + ), value: Expr::Value( (Value::SingleQuotedString("new_user".to_string())).with_empty_span() ), @@ -11327,20 +11326,20 @@ fn parse_merge() { update_token: AttachedToken::empty(), kind: MergeUpdateKind::Set(vec![ Assignment { - target: AssignmentTarget::ColumnName(ObjectName::from(vec![ - Ident::new("dest"), - Ident::new("F") - ])), + target: AssignmentTarget::ColumnName( + ObjectName::from(vec![Ident::new("dest"), Ident::new("F")]) + .into() + ), value: Expr::CompoundIdentifier(vec![ Ident::new("stg"), Ident::new("F"), ]), }, Assignment { - target: AssignmentTarget::ColumnName(ObjectName::from(vec![ - Ident::new("dest"), - Ident::new("G") - ])), + target: AssignmentTarget::ColumnName( + ObjectName::from(vec![Ident::new("dest"), Ident::new("G")]) + .into() + ), value: Expr::CompoundIdentifier(vec![ Ident::new("stg"), Ident::new("G"), @@ -23516,3 +23515,46 @@ fn parse_national_character_string_types() { ParserError::ParserError("Expected: ), found: EOF".to_string()) ); } + +#[test] +fn parse_subscripted_assignment_targets() { + let dialects = all_dialects_except(|d| { + d.is::() + || d.is::() + || d.is::() + || d.is::() + }); + for sql in [ + "UPDATE u SET arr[1] = 5, arr[2:3] = '{6,7}', arr[:1] = '{1}', m[1][2] = 4", + "UPDATE u SET parr[1].x = 9, p.y = 3", + "UPDATE u SET (arr[1], p.x) = (11, 12)", + "INSERT INTO u (id, arr[1], arr[2:3], p.x, parr[1].y) VALUES (1, 10, '{20,30}', 7, 8)", + "INSERT INTO u (id) VALUES (1) ON CONFLICT(id) DO UPDATE SET arr[1] = 99", + "MERGE INTO u USING v ON u.id = v.id WHEN MATCHED THEN UPDATE SET arr[1] = 5 WHEN NOT MATCHED THEN INSERT (id, arr[2]) VALUES (v.id, 6)", + ] { + dialects.verified_stmt(sql); + } + + match dialects.verified_stmt("UPDATE u SET parr[1].x = 9") { + Statement::Update(Update { assignments, .. }) => assert_eq!( + assignments[0].target, + AssignmentTarget::ColumnName(TargetColumn { + name: ObjectName::from(vec![Ident::new("parr")]), + access_chain: vec![ + AccessExpr::Subscript(Subscript::Index { + index: Expr::value(number("1")), + }), + AccessExpr::Dot(Expr::Identifier(Ident::new("x"))), + ], + }) + ), + stmt => panic!("unexpected statement: {stmt:?}"), + } + + assert_eq!( + dialects + .parse_sql_statements("UPDATE u SET arr[1]. = 5") + .unwrap_err(), + ParserError::ParserError("Expected: identifier, found: =".to_string()) + ); +} diff --git a/tests/sqlparser_mysql.rs b/tests/sqlparser_mysql.rs index d5ba2a9056..f3f0e7279f 100644 --- a/tests/sqlparser_mysql.rs +++ b/tests/sqlparser_mysql.rs @@ -1989,8 +1989,8 @@ fn parse_simple_insert() { ); assert_eq!( vec![ - ObjectName::from(Ident::new("title")), - ObjectName::from(Ident::new("priority")) + TargetColumn::from(Ident::new("title")), + TargetColumn::from(Ident::new("priority")) ], columns ); @@ -2060,8 +2060,8 @@ fn parse_ignore_insert() { ); assert_eq!( vec![ - ObjectName::from(Ident::new("title")), - ObjectName::from(Ident::new("priority")) + TargetColumn::from(Ident::new("title")), + TargetColumn::from(Ident::new("priority")) ], columns ); @@ -2116,8 +2116,8 @@ fn parse_priority_insert() { ); assert_eq!( vec![ - ObjectName::from(Ident::new("title")), - ObjectName::from(Ident::new("priority")) + TargetColumn::from(Ident::new("title")), + TargetColumn::from(Ident::new("priority")) ], columns ); @@ -2169,8 +2169,8 @@ fn parse_priority_insert() { ); assert_eq!( vec![ - ObjectName::from(Ident::new("title")), - ObjectName::from(Ident::new("priority")) + TargetColumn::from(Ident::new("title")), + TargetColumn::from(Ident::new("priority")) ], columns ); @@ -2222,7 +2222,7 @@ fn parse_insert_as() { table_name ); assert_eq!( - vec![ObjectName::from(Ident::with_quote('`', "date"))], + vec![TargetColumn::from(Ident::with_quote('`', "date"))], columns ); let insert_alias = insert_alias.unwrap(); @@ -2278,8 +2278,8 @@ fn parse_insert_as() { ); assert_eq!( vec![ - ObjectName::from(Ident::with_quote('`', "id")), - ObjectName::from(Ident::with_quote('`', "date")) + TargetColumn::from(Ident::with_quote('`', "id")), + TargetColumn::from(Ident::with_quote('`', "date")) ], columns ); @@ -2344,8 +2344,8 @@ fn parse_replace_insert() { ); assert_eq!( vec![ - ObjectName::from(Ident::new("title")), - ObjectName::from(Ident::new("priority")) + TargetColumn::from(Ident::new("title")), + TargetColumn::from(Ident::new("priority")) ], columns ); @@ -2445,12 +2445,12 @@ fn parse_insert_with_on_duplicate_update() { ); assert_eq!( vec![ - ObjectName::from(Ident::new("name")), - ObjectName::from(Ident::new("description")), - ObjectName::from(Ident::new("perm_create")), - ObjectName::from(Ident::new("perm_read")), - ObjectName::from(Ident::new("perm_update")), - ObjectName::from(Ident::new("perm_delete")) + TargetColumn::from(Ident::new("name")), + TargetColumn::from(Ident::new("description")), + TargetColumn::from(Ident::new("perm_create")), + TargetColumn::from(Ident::new("perm_read")), + TargetColumn::from(Ident::new("perm_update")), + TargetColumn::from(Ident::new("perm_delete")) ], columns ); @@ -2491,33 +2491,33 @@ fn parse_insert_with_on_duplicate_update() { assert_eq!( Some(OnInsert::DuplicateKeyUpdate(vec![ Assignment { - target: AssignmentTarget::ColumnName(ObjectName::from(vec![Ident::new( - "description".to_string() - )])), + target: AssignmentTarget::ColumnName( + ObjectName::from(vec![Ident::new("description".to_string())]).into() + ), value: call("VALUES", [Expr::Identifier(Ident::new("description"))]), }, Assignment { - target: AssignmentTarget::ColumnName(ObjectName::from(vec![Ident::new( - "perm_create".to_string() - )])), + target: AssignmentTarget::ColumnName( + ObjectName::from(vec![Ident::new("perm_create".to_string())]).into() + ), value: call("VALUES", [Expr::Identifier(Ident::new("perm_create"))]), }, Assignment { - target: AssignmentTarget::ColumnName(ObjectName::from(vec![Ident::new( - "perm_read".to_string() - )])), + target: AssignmentTarget::ColumnName( + ObjectName::from(vec![Ident::new("perm_read".to_string())]).into() + ), value: call("VALUES", [Expr::Identifier(Ident::new("perm_read"))]), }, Assignment { - target: AssignmentTarget::ColumnName(ObjectName::from(vec![Ident::new( - "perm_update".to_string() - )])), + target: AssignmentTarget::ColumnName( + ObjectName::from(vec![Ident::new("perm_update".to_string())]).into() + ), value: call("VALUES", [Expr::Identifier(Ident::new("perm_update"))]), }, Assignment { - target: AssignmentTarget::ColumnName(ObjectName::from(vec![Ident::new( - "perm_delete".to_string() - )])), + target: AssignmentTarget::ColumnName( + ObjectName::from(vec![Ident::new("perm_delete".to_string())]).into() + ), value: call("VALUES", [Expr::Identifier(Ident::new("perm_delete"))]), }, ])), @@ -2765,7 +2765,7 @@ fn parse_insert_with_numeric_prefix_column_name() { table_name ); assert_eq!( - vec![ObjectName::from(Ident::new("123col_$@length123"))], + vec![TargetColumn::from(Ident::new("123col_$@length123"))], columns ); } @@ -2839,10 +2839,9 @@ fn parse_update_with_joins() { ); assert_eq!( vec![Assignment { - target: AssignmentTarget::ColumnName(ObjectName::from(vec![ - Ident::new("o"), - Ident::new("completed") - ])), + target: AssignmentTarget::ColumnName( + ObjectName::from(vec![Ident::new("o"), Ident::new("completed")]).into() + ), value: Expr::Value((Value::Boolean(true)).with_empty_span()) }], assignments @@ -4550,13 +4549,14 @@ fn test_variable_assignment_using_colon_equal() { assert_eq!( assignments, vec![Assignment { - target: AssignmentTarget::ColumnName(ObjectName(vec![ - ObjectNamePart::Identifier(Ident { + target: AssignmentTarget::ColumnName( + ObjectName(vec![ObjectNamePart::Identifier(Ident { value: "price".to_string(), quote_style: None, span: Span::empty(), - }) - ])), + })]) + .into() + ), value: Expr::BinaryOp { left: Box::new(Expr::Identifier(Ident { value: "@new_price".to_string(), diff --git a/tests/sqlparser_oracle.rs b/tests/sqlparser_oracle.rs index 0ed573be68..b0a3addfa0 100644 --- a/tests/sqlparser_oracle.rs +++ b/tests/sqlparser_oracle.rs @@ -23,7 +23,7 @@ use pretty_assertions::assert_eq; use sqlparser::{ ast::{ BinaryOperator, Expr, Ident, Insert, ObjectName, Query, QuoteDelimitedString, SetExpr, - Statement, TableAliasWithoutColumns, TableObject, Value, ValueWithSpan, + Statement, TableAliasWithoutColumns, TableObject, TargetColumn, Value, ValueWithSpan, }, dialect::OracleDialect, parser::ParserError, @@ -479,8 +479,8 @@ fn test_insert_with_table_alias() { if let Statement::Insert(Insert { columns, .. }) = stmt { assert_eq!( vec![ - ObjectName::from(vec![Ident::new("t"), Ident::new("id")]), - ObjectName::from(vec![Ident::new("t"), Ident::new("val")]) + TargetColumn::from(ObjectName::from(vec![Ident::new("t"), Ident::new("id")])), + TargetColumn::from(ObjectName::from(vec![Ident::new("t"), Ident::new("val")])) ], columns ); diff --git a/tests/sqlparser_postgres.rs b/tests/sqlparser_postgres.rs index 9fe435e7d5..48ec1e60ea 100644 --- a/tests/sqlparser_postgres.rs +++ b/tests/sqlparser_postgres.rs @@ -2653,9 +2653,9 @@ fn parse_pg_on_conflict() { assert_eq!( OnConflictAction::DoUpdate(DoUpdate { assignments: vec![Assignment { - target: AssignmentTarget::ColumnName(ObjectName::from( - vec!["dname".into()] - )), + target: AssignmentTarget::ColumnName( + ObjectName::from(vec!["dname".into()]).into() + ), value: Expr::CompoundIdentifier(vec!["EXCLUDED".into(), "dname".into()]) },], selection: None @@ -2690,18 +2690,18 @@ fn parse_pg_on_conflict() { OnConflictAction::DoUpdate(DoUpdate { assignments: vec![ Assignment { - target: AssignmentTarget::ColumnName(ObjectName::from(vec![ - "dname".into() - ])), + target: AssignmentTarget::ColumnName( + ObjectName::from(vec!["dname".into()]).into() + ), value: Expr::CompoundIdentifier(vec![ "EXCLUDED".into(), "dname".into() ]) }, Assignment { - target: AssignmentTarget::ColumnName(ObjectName::from(vec![ - "area".into() - ])), + target: AssignmentTarget::ColumnName( + ObjectName::from(vec!["area".into()]).into() + ), value: Expr::CompoundIdentifier(vec!["EXCLUDED".into(), "area".into()]) }, ], @@ -2755,9 +2755,9 @@ fn parse_pg_on_conflict() { assert_eq!( OnConflictAction::DoUpdate(DoUpdate { assignments: vec![Assignment { - target: AssignmentTarget::ColumnName(ObjectName::from( - vec!["dname".into()] - )), + target: AssignmentTarget::ColumnName( + ObjectName::from(vec!["dname".into()]).into() + ), value: Expr::Value( (Value::Placeholder("$1".to_string())).with_empty_span() ) @@ -2802,9 +2802,9 @@ fn parse_pg_on_conflict() { assert_eq!( OnConflictAction::DoUpdate(DoUpdate { assignments: vec![Assignment { - target: AssignmentTarget::ColumnName(ObjectName::from( - vec!["dname".into()] - )), + target: AssignmentTarget::ColumnName( + ObjectName::from(vec!["dname".into()]).into() + ), value: Expr::Value( (Value::Placeholder("$1".to_string())).with_empty_span() ) @@ -6819,12 +6819,12 @@ fn test_simple_postgres_insert_with_alias() { } }), columns: vec![ - ObjectName::from(Ident { + TargetColumn::from(Ident { value: "id".to_string(), quote_style: None, span: Span::empty(), }), - ObjectName::from(Ident { + TargetColumn::from(Ident { value: "a".to_string(), quote_style: None, span: Span::empty(), @@ -6903,12 +6903,12 @@ fn test_simple_insert_with_quoted_alias() { } }), columns: vec![ - ObjectName::from(Ident { + TargetColumn::from(Ident { value: "id".to_string(), quote_style: None, span: Span::empty(), }), - ObjectName::from(Ident { + TargetColumn::from(Ident { value: "a".to_string(), quote_style: None, span: Span::empty(), diff --git a/tests/sqlparser_sqlite.rs b/tests/sqlparser_sqlite.rs index ce5be7bf10..dedcd67d2e 100644 --- a/tests/sqlparser_sqlite.rs +++ b/tests/sqlparser_sqlite.rs @@ -516,8 +516,8 @@ fn parse_update_tuple_row_values() { or: None, assignments: vec![Assignment { target: AssignmentTarget::Tuple(vec![ - ObjectName::from(vec![Ident::new("a"),]), - ObjectName::from(vec![Ident::new("b"),]), + Ident::new("a").into(), + Ident::new("b").into(), ]), value: Expr::Tuple(vec![ Expr::Value((Value::Number("1".parse().unwrap(), false)).with_empty_span()),