Postgres: Support parenthesized SET options for ALTER TABLE (#1947)

Co-authored-by: Ifeanyi Ubah <ify1992@yahoo.com>
This commit is contained in:
carl 2025-07-23 11:53:17 -04:00 committed by GitHub
parent 2ed2cbe291
commit f49c30feb6
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 53 additions and 4 deletions

View file

@ -351,6 +351,16 @@ pub enum AlterTableOperation {
ValidateConstraint { ValidateConstraint {
name: Ident, 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<SqlOption>,
},
} }
/// An `ALTER Policy` (`Statement::AlterPolicy`) operation /// An `ALTER Policy` (`Statement::AlterPolicy`) operation
@ -791,6 +801,9 @@ impl fmt::Display for AlterTableOperation {
AlterTableOperation::ValidateConstraint { name } => { AlterTableOperation::ValidateConstraint { name } => {
write!(f, "VALIDATE CONSTRAINT {name}") write!(f, "VALIDATE CONSTRAINT {name}")
} }
AlterTableOperation::SetOptionsParens { options } => {
write!(f, "SET ({})", display_comma_separated(options))
}
} }
} }
} }

View file

@ -1202,6 +1202,9 @@ impl Spanned for AlterTableOperation {
AlterTableOperation::Lock { .. } => Span::empty(), AlterTableOperation::Lock { .. } => Span::empty(),
AlterTableOperation::ReplicaIdentity { .. } => Span::empty(), AlterTableOperation::ReplicaIdentity { .. } => Span::empty(),
AlterTableOperation::ValidateConstraint { name } => name.span, AlterTableOperation::ValidateConstraint { name } => name.span,
AlterTableOperation::SetOptionsParens { options } => {
union_spans(options.iter().map(|i| i.span()))
}
} }
} }
} }

View file

@ -9045,18 +9045,23 @@ impl<'a> Parser<'a> {
let name = self.parse_identifier()?; let name = self.parse_identifier()?;
AlterTableOperation::ValidateConstraint { name } AlterTableOperation::ValidateConstraint { name }
} else { } else {
let options: Vec<SqlOption> = let mut options =
self.parse_options_with_keywords(&[Keyword::SET, Keyword::TBLPROPERTIES])?; self.parse_options_with_keywords(&[Keyword::SET, Keyword::TBLPROPERTIES])?;
if !options.is_empty() { if !options.is_empty() {
AlterTableOperation::SetTblProperties { AlterTableOperation::SetTblProperties {
table_properties: options, table_properties: options,
} }
} else {
options = self.parse_options(Keyword::SET)?;
if !options.is_empty() {
AlterTableOperation::SetOptionsParens { options }
} else { } else {
return self.expected( return self.expected(
"ADD, RENAME, PARTITION, SWAP, DROP, REPLICA IDENTITY, or SET TBLPROPERTIES after ALTER TABLE", "ADD, RENAME, PARTITION, SWAP, DROP, REPLICA IDENTITY, SET, or SET TBLPROPERTIES after ALTER TABLE",
self.peek_token(), self.peek_token(),
); );
} }
}
}; };
Ok(operation) Ok(operation)
} }

View file

@ -4728,6 +4728,34 @@ fn parse_alter_table() {
} }
_ => unreachable!(), _ => 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] #[test]