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,17 +9045,22 @@ 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 { } else {
return self.expected( options = self.parse_options(Keyword::SET)?;
"ADD, RENAME, PARTITION, SWAP, DROP, REPLICA IDENTITY, or SET TBLPROPERTIES after ALTER TABLE", 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(), 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]