Skip to content

Commit 10faec0

Browse files
PostgreSQL: Support ALTER SERVER
1 parent 654ba6f commit 10faec0

7 files changed

Lines changed: 247 additions & 37 deletions

File tree

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
ALTER SERVER s VERSION NULL OPTIONS (ADD host 'db', SET port '5432', DROP dbname);
2+
ALTER SERVER s OWNER TO postgres

‎src/ast/ddl.rs‎

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4867,6 +4867,79 @@ impl Spanned for AlterCollation {
48674867
}
48684868
}
48694869

4870+
/// `ALTER SERVER` statement.
4871+
///
4872+
/// [PostgreSQL](https://www.postgresql.org/docs/current/sql-alterserver.html)
4873+
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
4874+
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
4875+
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
4876+
pub struct AlterServer {
4877+
/// Name of the server being altered.
4878+
pub name: Ident,
4879+
/// The operation to perform on the server.
4880+
pub operation: AlterServerOperation,
4881+
}
4882+
4883+
/// Operations supported by `ALTER SERVER`.
4884+
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
4885+
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
4886+
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
4887+
pub enum AlterServerOperation {
4888+
/// Change the server version, its options, or both.
4889+
///
4890+
/// ```sql
4891+
/// ALTER SERVER name [ VERSION 'new_version' ] [ OPTIONS ( [ ADD | SET | DROP ] option ['value'] [, ...] ) ]
4892+
/// ```
4893+
Update {
4894+
/// The new version, `NULL` included.
4895+
version: Option<ValueWithSpan>,
4896+
/// The option changes, in source order.
4897+
options: Option<Vec<AlterGenericOption>>,
4898+
},
4899+
/// Change the server owner.
4900+
///
4901+
/// ```sql
4902+
/// ALTER SERVER name OWNER TO role_name
4903+
/// ```
4904+
OwnerTo(Owner),
4905+
/// Rename the server.
4906+
///
4907+
/// ```sql
4908+
/// ALTER SERVER name RENAME TO new_name
4909+
/// ```
4910+
RenameTo {
4911+
/// New server name.
4912+
new_name: Ident,
4913+
},
4914+
}
4915+
4916+
impl fmt::Display for AlterServerOperation {
4917+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
4918+
match self {
4919+
AlterServerOperation::Update { version, options } => {
4920+
if let Some(version) = version {
4921+
write!(f, "VERSION {version}")?;
4922+
if options.is_some() {
4923+
f.write_str(" ")?;
4924+
}
4925+
}
4926+
if let Some(options) = options {
4927+
write!(f, "OPTIONS ({})", display_comma_separated(options))?;
4928+
}
4929+
Ok(())
4930+
}
4931+
AlterServerOperation::OwnerTo(owner) => write!(f, "OWNER TO {owner}"),
4932+
AlterServerOperation::RenameTo { new_name } => write!(f, "RENAME TO {new_name}"),
4933+
}
4934+
}
4935+
}
4936+
4937+
impl fmt::Display for AlterServer {
4938+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
4939+
write!(f, "ALTER SERVER {} {}", self.name, self.operation)
4940+
}
4941+
}
4942+
48704943
/// Table type for ALTER TABLE statements.
48714944
/// Used to distinguish between regular tables, Iceberg tables, and Dynamic tables.
48724945
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]

‎src/ast/mod.rs‎

Lines changed: 26 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -67,20 +67,20 @@ pub use self::ddl::{
6767
AlterFunctionOperation, AlterGenericOption, AlterIndexOperation, AlterOperator,
6868
AlterOperatorClass, AlterOperatorClassOperation, AlterOperatorFamily,
6969
AlterOperatorFamilyOperation, AlterOperatorOperation, AlterPolicy, AlterPolicyOperation,
70-
AlterSchema, AlterSchemaOperation, AlterTable, AlterTableAlgorithm, AlterTableLock,
71-
AlterTableOperation, AlterTableType, AlterTextSearch, AlterTextSearchOperation,
72-
AlterTextSearchOption, AlterTrigger, AlterTriggerOperation, AlterType, AlterTypeAddValue,
73-
AlterTypeAddValuePosition, AlterTypeOperation, AlterTypeRename, AlterTypeRenameValue,
74-
ClusteredBy, ColumnDef, ColumnOption, ColumnOptionDef, ColumnOptions, ColumnPolicy,
75-
ColumnPolicyProperty, ConstraintCharacteristics, CreateAggregate, CreateAggregateArgs,
76-
CreateAggregateOption, CreateCollation, CreateCollationDefinition, CreateConnector,
77-
CreateDomain, CreateExtension, CreateForeignDataWrapper, CreateForeignTable, CreateFunction,
78-
CreateIndex, CreateOperator, CreateOperatorClass, CreateOperatorFamily, CreatePolicy,
79-
CreatePolicyCommand, CreatePolicyType, CreateRule, CreateRuleAction, CreateRuleDoKind,
80-
CreateRuleEvent, CreateTable, CreateTextSearch, CreateTrigger, CreateView, Deduplicate,
81-
DeferrableInitial, DistStyle, DropBehavior, DropExtension, DropFunction, DropOperator,
82-
DropOperatorClass, DropOperatorFamily, DropOperatorSignature, DropPolicy, DropTrigger,
83-
ForValues, ForeignDataWrapperRoutineClause, FunctionReturnType, GeneratedAs,
70+
AlterSchema, AlterSchemaOperation, AlterServer, AlterServerOperation, AlterTable,
71+
AlterTableAlgorithm, AlterTableLock, AlterTableOperation, AlterTableType, AlterTextSearch,
72+
AlterTextSearchOperation, AlterTextSearchOption, AlterTrigger, AlterTriggerOperation,
73+
AlterType, AlterTypeAddValue, AlterTypeAddValuePosition, AlterTypeOperation, AlterTypeRename,
74+
AlterTypeRenameValue, ClusteredBy, ColumnDef, ColumnOption, ColumnOptionDef, ColumnOptions,
75+
ColumnPolicy, ColumnPolicyProperty, ConstraintCharacteristics, CreateAggregate,
76+
CreateAggregateArgs, CreateAggregateOption, CreateCollation, CreateCollationDefinition,
77+
CreateConnector, CreateDomain, CreateExtension, CreateForeignDataWrapper, CreateForeignTable,
78+
CreateFunction, CreateIndex, CreateOperator, CreateOperatorClass, CreateOperatorFamily,
79+
CreatePolicy, CreatePolicyCommand, CreatePolicyType, CreateRule, CreateRuleAction,
80+
CreateRuleDoKind, CreateRuleEvent, CreateTable, CreateTextSearch, CreateTrigger, CreateView,
81+
Deduplicate, DeferrableInitial, DistStyle, DropBehavior, DropExtension, DropFunction,
82+
DropOperator, DropOperatorClass, DropOperatorFamily, DropOperatorSignature, DropPolicy,
83+
DropTrigger, ForValues, ForeignDataWrapperRoutineClause, FunctionReturnType, GeneratedAs,
8484
GeneratedExpressionMode, IdentityParameters, IdentityProperty, IdentityPropertyFormatKind,
8585
IdentityPropertyKind, IdentityPropertyOrder, IndexColumn, IndexOption, IndexType,
8686
KeyOrIndexDisplay, Msck, NullsDistinctOption, OperatorArgTypes, OperatorClassItem,
@@ -3932,6 +3932,11 @@ pub enum Statement {
39323932
/// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-altercollation.html)
39333933
AlterCollation(AlterCollation),
39343934
/// ```sql
3935+
/// ALTER SERVER
3936+
/// ```
3937+
/// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-alterserver.html)
3938+
AlterServer(AlterServer),
3939+
/// ```sql
39353940
/// ALTER OPERATOR
39363941
/// ```
39373942
/// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-alteroperator.html)
@@ -5754,6 +5759,7 @@ impl fmt::Display for Statement {
57545759
write!(f, "ALTER TYPE {name} {operation}")
57555760
}
57565761
Statement::AlterCollation(alter_collation) => write!(f, "{alter_collation}"),
5762+
Statement::AlterServer(alter_server) => write!(f, "{alter_server}"),
57575763
Statement::AlterOperator(alter_operator) => write!(f, "{alter_operator}"),
57585764
Statement::AlterOperatorFamily(alter_operator_family) => {
57595765
write!(f, "{alter_operator_family}")
@@ -12587,6 +12593,12 @@ impl From<AlterCollation> for Statement {
1258712593
}
1258812594
}
1258912595

12596+
impl From<AlterServer> for Statement {
12597+
fn from(a: AlterServer) -> Self {
12598+
Self::AlterServer(a)
12599+
}
12600+
}
12601+
1259012602
impl From<AlterOperator> for Statement {
1259112603
fn from(a: AlterOperator) -> Self {
1259212604
Self::AlterOperator(a)

‎src/ast/spans.rs‎

Lines changed: 39 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -29,27 +29,27 @@ use crate::tokenizer::Span;
2929

3030
use super::{
3131
comments, dcl::SecondaryRoles, value::ValueWithSpan, AccessExpr, AlterColumnOperation,
32-
AlterGenericOption, AlterIndexOperation, AlterTableOperation, AlterTrigger,
33-
AlterTriggerOperation, Analyze, Array, Assignment, AssignmentTarget, AttachedToken,
34-
BeginEndStatements, CaseStatement, CloseCursor, ClusteredIndex, ColumnDef, ColumnOption,
35-
ColumnOptionDef, ConditionalStatementBlock, ConditionalStatements, ConflictTarget,
36-
ConnectByKind, ConstraintCharacteristics, CopySource, CreateIndex, CreateRule,
37-
CreateRuleAction, CreateTable, CreateTableOptions, Cte, Delete, DoUpdate, ExceptSelectItem,
38-
ExcludeConstraintElement, ExcludeSelectItem, Expr, ExprWithAlias, Fetch, ForValues, FromTable,
39-
Function, FunctionArg, FunctionArgExpr, FunctionArgumentClause, FunctionArgumentList,
40-
FunctionArguments, GroupByExpr, HavingBound, IfStatement, IlikeSelectItem, InTarget,
41-
IndexColumn, Insert, Interpolate, InterpolateExpr, Join, JoinConstraint, JoinOperator,
42-
JsonPath, JsonPathElem, LateralView, LimitClause, MatchRecognizePattern, Measure, Merge,
43-
MergeAction, MergeClause, MergeInsertExpr, MergeInsertKind, MergeUpdateExpr, MergeUpdateKind,
44-
NamedParenthesizedList, NamedWindowDefinition, ObjectName, ObjectNamePart, Offset, OnConflict,
45-
OnConflictAction, OnInsert, OpenStatement, OperateFunctionArg, OrderBy, OrderByExpr,
46-
OrderByKind, OutputClause, Parens, Partition, PartitionBoundValue, PivotValueSource,
47-
ProjectionSelect, Query, RaiseStatement, RaiseStatementValue, ReferentialAction,
48-
RenameSelectItem, ReplaceSelectElement, ReplaceSelectItem, Select, SelectInto, SelectItem,
49-
SetExpr, Setting, SqlOption, Statement, Subscript, SymbolDefinition, TableAlias,
50-
TableAliasColumnDef, TableConstraint, TableFactor, TableObject, TableOptionsClustered,
51-
TableWithJoins, Update, UpdateTableFromKind, Use, Values, ViewColumnDef, WhileStatement,
52-
WildcardAdditionalOptions, With, WithFill,
32+
AlterGenericOption, AlterIndexOperation, AlterServer, AlterServerOperation,
33+
AlterTableOperation, AlterTrigger, AlterTriggerOperation, Analyze, Array, Assignment,
34+
AssignmentTarget, AttachedToken, BeginEndStatements, CaseStatement, CloseCursor,
35+
ClusteredIndex, ColumnDef, ColumnOption, ColumnOptionDef, ConditionalStatementBlock,
36+
ConditionalStatements, ConflictTarget, ConnectByKind, ConstraintCharacteristics, CopySource,
37+
CreateIndex, CreateRule, CreateRuleAction, CreateTable, CreateTableOptions, Cte, Delete,
38+
DoUpdate, ExceptSelectItem, ExcludeConstraintElement, ExcludeSelectItem, Expr, ExprWithAlias,
39+
Fetch, ForValues, FromTable, Function, FunctionArg, FunctionArgExpr, FunctionArgumentClause,
40+
FunctionArgumentList, FunctionArguments, GroupByExpr, HavingBound, IfStatement,
41+
IlikeSelectItem, InTarget, IndexColumn, Insert, Interpolate, InterpolateExpr, Join,
42+
JoinConstraint, JoinOperator, JsonPath, JsonPathElem, LateralView, LimitClause,
43+
MatchRecognizePattern, Measure, Merge, MergeAction, MergeClause, MergeInsertExpr,
44+
MergeInsertKind, MergeUpdateExpr, MergeUpdateKind, NamedParenthesizedList,
45+
NamedWindowDefinition, ObjectName, ObjectNamePart, Offset, OnConflict, OnConflictAction,
46+
OnInsert, OpenStatement, OperateFunctionArg, OrderBy, OrderByExpr, OrderByKind, OutputClause,
47+
Parens, Partition, PartitionBoundValue, PivotValueSource, ProjectionSelect, Query,
48+
RaiseStatement, RaiseStatementValue, ReferentialAction, RenameSelectItem, ReplaceSelectElement,
49+
ReplaceSelectItem, Select, SelectInto, SelectItem, SetExpr, Setting, SqlOption, Statement,
50+
Subscript, SymbolDefinition, TableAlias, TableAliasColumnDef, TableConstraint, TableFactor,
51+
TableObject, TableOptionsClustered, TableWithJoins, Update, UpdateTableFromKind, Use, Values,
52+
ViewColumnDef, WhileStatement, WildcardAdditionalOptions, With, WithFill,
5353
};
5454

5555
/// Given an iterator of spans, return the [Span::union] of all spans.
@@ -422,6 +422,7 @@ impl Spanned for Statement {
422422
Statement::AlterFunction { .. } => Span::empty(),
423423
Statement::AlterType { .. } => Span::empty(),
424424
Statement::AlterCollation { .. } => Span::empty(),
425+
Statement::AlterServer(alter_server) => alter_server.span(),
425426
Statement::AlterOperator { .. } => Span::empty(),
426427
Statement::AlterOperatorFamily { .. } => Span::empty(),
427428
Statement::AlterOperatorClass { .. } => Span::empty(),
@@ -2783,6 +2784,23 @@ impl Spanned for comments::CommentWithSpan {
27832784
}
27842785
}
27852786

2787+
impl Spanned for AlterServer {
2788+
fn span(&self) -> Span {
2789+
let operation = match &self.operation {
2790+
AlterServerOperation::Update { version, options } => Span::union_iter(
2791+
version
2792+
.iter()
2793+
.map(|version| version.span)
2794+
.chain(options.iter().flatten().map(|option| option.span())),
2795+
),
2796+
AlterServerOperation::OwnerTo(Owner::Ident(owner)) => owner.span,
2797+
AlterServerOperation::OwnerTo(_) => Span::empty(),
2798+
AlterServerOperation::RenameTo { new_name } => new_name.span,
2799+
};
2800+
self.name.span.union(&operation)
2801+
}
2802+
}
2803+
27862804
#[cfg(test)]
27872805
pub mod tests {
27882806
use crate::ast::Value;

‎src/parser/mod.rs‎

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11757,14 +11757,15 @@ impl<'a> Parser<'a> {
1175711757
Keyword::POLICY => self.parse_alter_policy().map(Into::into),
1175811758
Keyword::TRIGGER => self.parse_alter_trigger().map(Into::into),
1175911759
Keyword::CONNECTOR => self.parse_alter_connector(),
11760+
Keyword::SERVER => self.parse_alter_server().map(Into::into),
1176011761
Keyword::USER if self.dialect.supports_alter_user_as_alter_role() => {
1176111762
self.parse_alter_role()
1176211763
}
1176311764
Keyword::USER => self.parse_alter_user().map(Into::into),
1176411765
_ => {
1176511766
self.index = index;
1176611767
self.expected_ref(
11767-
"one of VIEW or TYPE or COLLATION or TABLE or INDEX or FUNCTION or AGGREGATE or ROLE or POLICY or TRIGGER or CONNECTOR or ICEBERG or FOREIGN TABLE or SCHEMA or USER or OPERATOR",
11768+
"one of VIEW or TYPE or COLLATION or TABLE or INDEX or FUNCTION or AGGREGATE or ROLE or POLICY or TRIGGER or CONNECTOR or ICEBERG or FOREIGN TABLE or SCHEMA or SERVER or USER or OPERATOR",
1176811769
self.peek_token_ref(),
1176911770
)
1177011771
}
@@ -12121,6 +12122,40 @@ impl<'a> Parser<'a> {
1212112122
Ok(AlterCollation { name, operation })
1212212123
}
1212312124

12125+
/// Parse a [Statement::AlterServer].
12126+
///
12127+
/// [PostgreSQL Documentation](https://www.postgresql.org/docs/current/sql-alterserver.html)
12128+
pub fn parse_alter_server(&mut self) -> Result<AlterServer, ParserError> {
12129+
let name = self.parse_identifier()?;
12130+
let operation = if self.parse_keywords(&[Keyword::RENAME, Keyword::TO]) {
12131+
AlterServerOperation::RenameTo {
12132+
new_name: self.parse_identifier()?,
12133+
}
12134+
} else if self.parse_keywords(&[Keyword::OWNER, Keyword::TO]) {
12135+
AlterServerOperation::OwnerTo(self.parse_owner()?)
12136+
} else {
12137+
let version = if self.parse_keyword(Keyword::VERSION) {
12138+
Some(self.parse_value()?)
12139+
} else {
12140+
None
12141+
};
12142+
let options = if self.parse_keyword(Keyword::OPTIONS) {
12143+
Some(self.parse_alter_generic_options()?)
12144+
} else {
12145+
None
12146+
};
12147+
if version.is_none() && options.is_none() {
12148+
return self.expected_ref(
12149+
"VERSION, OPTIONS, OWNER TO, or RENAME TO after ALTER SERVER",
12150+
self.peek_token_ref(),
12151+
);
12152+
}
12153+
AlterServerOperation::Update { version, options }
12154+
};
12155+
12156+
Ok(AlterServer { name, operation })
12157+
}
12158+
1212412159
/// Parse a [Statement::AlterOperator]
1212512160
///
1212612161
/// [PostgreSQL Documentation](https://www.postgresql.org/docs/current/sql-alteroperator.html)

‎tests/sqlparser_common.rs‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15856,7 +15856,7 @@ fn parse_alter_trigger_spans() {
1585615856

1585715857
#[test]
1585815858
fn parse_alter_rejects_missing_or_unknown_object_type() {
15859-
let objects = "one of VIEW or TYPE or COLLATION or TABLE or INDEX or FUNCTION or AGGREGATE or ROLE or POLICY or TRIGGER or CONNECTOR or ICEBERG or FOREIGN TABLE or SCHEMA or USER or OPERATOR";
15859+
let objects = "one of VIEW or TYPE or COLLATION or TABLE or INDEX or FUNCTION or AGGREGATE or ROLE or POLICY or TRIGGER or CONNECTOR or ICEBERG or FOREIGN TABLE or SCHEMA or SERVER or USER or OPERATOR";
1586015860
for (sql, found) in [
1586115861
("ALTER", "EOF"),
1586215862
("ALTER 1", "1"),

‎tests/sqlparser_postgres.rs‎

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11158,3 +11158,73 @@ fn parse_alter_foreign_table() {
1115811158
);
1115911159
}
1116011160
}
11161+
11162+
#[test]
11163+
fn parse_alter_server() {
11164+
let sql = "ALTER SERVER s VERSION NULL OPTIONS (ADD host 'db', SET port '5432', DROP dbname)";
11165+
let Statement::AlterServer(alter) = pg_and_generic().verified_stmt(sql) else {
11166+
unreachable!()
11167+
};
11168+
assert_eq!(alter.name, Ident::new("s"));
11169+
let AlterServerOperation::Update { version, options } = alter.operation else {
11170+
unreachable!()
11171+
};
11172+
assert_eq!(version.map(|version| version.value), Some(Value::Null));
11173+
assert_eq!(
11174+
options,
11175+
Some(vec![
11176+
AlterGenericOption::Add {
11177+
option: CreateServerOption {
11178+
key: Ident::new("host"),
11179+
value: Ident::with_quote('\'', "db"),
11180+
},
11181+
add_keyword: true,
11182+
},
11183+
AlterGenericOption::Set(CreateServerOption {
11184+
key: Ident::new("port"),
11185+
value: Ident::with_quote('\'', "5432"),
11186+
}),
11187+
AlterGenericOption::Drop(Ident::new("dbname")),
11188+
])
11189+
);
11190+
11191+
assert_eq!(
11192+
pg_and_generic().verified_stmt("ALTER SERVER s OWNER TO postgres"),
11193+
Statement::AlterServer(AlterServer {
11194+
name: Ident::new("s"),
11195+
operation: AlterServerOperation::OwnerTo(Owner::Ident(Ident::new("postgres"))),
11196+
})
11197+
);
11198+
for sql in [
11199+
"ALTER SERVER s VERSION '2.0'",
11200+
"ALTER SERVER s OPTIONS (host 'db')",
11201+
"ALTER SERVER s OWNER TO CURRENT_USER",
11202+
"ALTER SERVER s RENAME TO s2",
11203+
] {
11204+
pg_and_generic().verified_stmt(sql);
11205+
}
11206+
11207+
for (sql, expected) in [
11208+
(
11209+
"ALTER SERVER s",
11210+
"Expected: VERSION, OPTIONS, OWNER TO, or RENAME TO after ALTER SERVER, found: EOF",
11211+
),
11212+
(
11213+
"ALTER SERVER s OPTIONS (port '1') VERSION '4'",
11214+
"Expected: end of statement, found: VERSION",
11215+
),
11216+
(
11217+
"ALTER SERVER public.s OWNER TO app",
11218+
"Expected: VERSION, OPTIONS, OWNER TO, or RENAME TO after ALTER SERVER, found: .",
11219+
),
11220+
] {
11221+
assert_eq!(
11222+
pg_and_generic()
11223+
.parse_sql_statements(sql)
11224+
.unwrap_err()
11225+
.to_string(),
11226+
format!("sql parser error: {expected}"),
11227+
"{sql}"
11228+
);
11229+
}
11230+
}

0 commit comments

Comments
 (0)