diff --git a/src/ast/ddl.rs b/src/ast/ddl.rs index 51e057840..92936a6f0 100644 --- a/src/ast/ddl.rs +++ b/src/ast/ddl.rs @@ -351,6 +351,16 @@ pub enum AlterTableOperation { ValidateConstraint { name: Ident, }, + /// Arbitrary parenthesized `SET` options. + /// + /// Example: + /// ```sql + /// SET (scale_factor = 0.01, threshold = 500)` + /// ``` + /// [PostgreSQL](https://www.postgresql.org/docs/current/sql-altertable.html) + SetOptionsParens { + options: Vec, + }, } /// An `ALTER Policy` (`Statement::AlterPolicy`) operation @@ -791,6 +801,9 @@ impl fmt::Display for AlterTableOperation { AlterTableOperation::ValidateConstraint { name } => { write!(f, "VALIDATE CONSTRAINT {name}") } + AlterTableOperation::SetOptionsParens { options } => { + write!(f, "SET ({})", display_comma_separated(options)) + } } } } diff --git a/src/ast/spans.rs b/src/ast/spans.rs index 3e82905e1..cb348a0e5 100644 --- a/src/ast/spans.rs +++ b/src/ast/spans.rs @@ -1201,6 +1201,9 @@ impl Spanned for AlterTableOperation { AlterTableOperation::Lock { .. } => Span::empty(), AlterTableOperation::ReplicaIdentity { .. } => Span::empty(), AlterTableOperation::ValidateConstraint { name } => name.span, + AlterTableOperation::SetOptionsParens { options } => { + union_spans(options.iter().map(|i| i.span())) + } } } } diff --git a/src/parser/mod.rs b/src/parser/mod.rs index 3bb913118..705875eaa 100644 --- a/src/parser/mod.rs +++ b/src/parser/mod.rs @@ -8938,17 +8938,22 @@ impl<'a> Parser<'a> { let name = self.parse_identifier()?; AlterTableOperation::ValidateConstraint { name } } else { - let options: Vec = + let mut options = self.parse_options_with_keywords(&[Keyword::SET, Keyword::TBLPROPERTIES])?; if !options.is_empty() { AlterTableOperation::SetTblProperties { table_properties: options, } } else { - return self.expected( - "ADD, RENAME, PARTITION, SWAP, DROP, REPLICA IDENTITY, or SET TBLPROPERTIES after ALTER TABLE", + options = self.parse_options(Keyword::SET)?; + if !options.is_empty() { + AlterTableOperation::SetOptionsParens { options } + } else { + return self.expected( + "ADD, RENAME, PARTITION, SWAP, DROP, REPLICA IDENTITY, SET, or SET TBLPROPERTIES after ALTER TABLE", self.peek_token(), - ); + ); + } } }; Ok(operation) diff --git a/tests/sqlparser_common.rs b/tests/sqlparser_common.rs index 4183c5539..b9b0d2f5e 100644 --- a/tests/sqlparser_common.rs +++ b/tests/sqlparser_common.rs @@ -4725,6 +4725,34 @@ fn parse_alter_table() { } _ => unreachable!(), } + + let set_storage_parameters = "ALTER TABLE tab SET (autovacuum_vacuum_scale_factor = 0.01, autovacuum_vacuum_threshold = 500)"; + match alter_table_op(verified_stmt(set_storage_parameters)) { + AlterTableOperation::SetOptionsParens { options } => { + assert_eq!( + options, + [ + SqlOption::KeyValue { + key: Ident { + value: "autovacuum_vacuum_scale_factor".to_string(), + quote_style: None, + span: Span::empty(), + }, + value: Expr::Value(test_utils::number("0.01").with_empty_span()), + }, + SqlOption::KeyValue { + key: Ident { + value: "autovacuum_vacuum_threshold".to_string(), + quote_style: None, + span: Span::empty(), + }, + value: Expr::Value(test_utils::number("500").with_empty_span()), + } + ], + ); + } + _ => unreachable!(), + } } #[test]