Skip to content

Commit 727a6fb

Browse files
feat(parser): parse PostgreSQL collation DDL
Extend parser dispatch and handlers for PostgreSQL collation syntax.\n\n- parse CREATE COLLATION with FROM and option-list forms\n- parse ALTER COLLATION operations: RENAME TO, OWNER TO, SET SCHEMA, REFRESH VERSION\n- accept DROP COLLATION via generic DROP statement path\n- support COMMENT ON COLLATION targets
1 parent 8721780 commit 727a6fb

File tree

1 file changed

+63
-2
lines changed

1 file changed

+63
-2
lines changed

src/parser/mod.rs

Lines changed: 63 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -898,6 +898,9 @@ impl<'a> Parser<'a> {
898898
let token = self.next_token();
899899

900900
let (object_type, object_name) = match token.token {
901+
Token::Word(w) if w.keyword == Keyword::COLLATION => {
902+
(CommentObject::Collation, self.parse_object_name(false)?)
903+
}
901904
Token::Word(w) if w.keyword == Keyword::COLUMN => {
902905
(CommentObject::Column, self.parse_object_name(false)?)
903906
}
@@ -5151,6 +5154,8 @@ impl<'a> Parser<'a> {
51515154
self.parse_create_role().map(Into::into)
51525155
} else if self.parse_keyword(Keyword::SEQUENCE) {
51535156
self.parse_create_sequence(temporary)
5157+
} else if self.parse_keyword(Keyword::COLLATION) {
5158+
self.parse_create_collation().map(Into::into)
51545159
} else if self.parse_keyword(Keyword::TYPE) {
51555160
self.parse_create_type()
51565161
} else if self.parse_keyword(Keyword::PROCEDURE) {
@@ -7200,6 +7205,8 @@ impl<'a> Parser<'a> {
72007205

72017206
let object_type = if self.parse_keyword(Keyword::TABLE) {
72027207
ObjectType::Table
7208+
} else if self.parse_keyword(Keyword::COLLATION) {
7209+
ObjectType::Collation
72037210
} else if self.parse_keyword(Keyword::VIEW) {
72047211
ObjectType::View
72057212
} else if self.parse_keywords(&[Keyword::MATERIALIZED, Keyword::VIEW]) {
@@ -7249,7 +7256,7 @@ impl<'a> Parser<'a> {
72497256
};
72507257
} else {
72517258
return self.expected_ref(
7252-
"CONNECTOR, DATABASE, EXTENSION, FUNCTION, INDEX, OPERATOR, POLICY, PROCEDURE, ROLE, SCHEMA, SECRET, SEQUENCE, STAGE, TABLE, TRIGGER, TYPE, VIEW, MATERIALIZED VIEW or USER after DROP",
7259+
"COLLATION, CONNECTOR, DATABASE, EXTENSION, FUNCTION, INDEX, OPERATOR, POLICY, PROCEDURE, ROLE, SCHEMA, SECRET, SEQUENCE, STAGE, TABLE, TRIGGER, TYPE, VIEW, MATERIALIZED VIEW or USER after DROP",
72537260
self.peek_token_ref(),
72547261
);
72557262
};
@@ -7990,6 +7997,31 @@ impl<'a> Parser<'a> {
79907997
})
79917998
}
79927999

8000+
/// Parse a PostgreSQL-specific [Statement::CreateCollation] statement.
8001+
pub fn parse_create_collation(&mut self) -> Result<CreateCollation, ParserError> {
8002+
let if_not_exists = self.parse_keywords(&[Keyword::IF, Keyword::NOT, Keyword::EXISTS]);
8003+
let name = self.parse_object_name(false)?;
8004+
8005+
let definition = if self.parse_keyword(Keyword::FROM) {
8006+
CreateCollationDefinition::From(self.parse_object_name(false)?)
8007+
} else if self.consume_token(&Token::LParen) {
8008+
let options = self.parse_comma_separated(Parser::parse_sql_option)?;
8009+
self.expect_token(&Token::RParen)?;
8010+
CreateCollationDefinition::Options(options)
8011+
} else {
8012+
return self.expected_ref(
8013+
"FROM or parenthesized option list after CREATE COLLATION name",
8014+
self.peek_token_ref(),
8015+
);
8016+
};
8017+
8018+
Ok(CreateCollation {
8019+
if_not_exists,
8020+
name,
8021+
definition,
8022+
})
8023+
}
8024+
79938025
/// Parse a PostgreSQL-specific [Statement::DropExtension] statement.
79948026
pub fn parse_drop_extension(&mut self) -> Result<Statement, ParserError> {
79958027
let if_exists = self.parse_keywords(&[Keyword::IF, Keyword::EXISTS]);
@@ -10431,6 +10463,7 @@ impl<'a> Parser<'a> {
1043110463
let object_type = self.expect_one_of_keywords(&[
1043210464
Keyword::VIEW,
1043310465
Keyword::TYPE,
10466+
Keyword::COLLATION,
1043410467
Keyword::TABLE,
1043510468
Keyword::INDEX,
1043610469
Keyword::ROLE,
@@ -10449,6 +10482,7 @@ impl<'a> Parser<'a> {
1044910482
}
1045010483
Keyword::VIEW => self.parse_alter_view(),
1045110484
Keyword::TYPE => self.parse_alter_type(),
10485+
Keyword::COLLATION => self.parse_alter_collation().map(Into::into),
1045210486
Keyword::TABLE => self.parse_alter_table(false),
1045310487
Keyword::ICEBERG => {
1045410488
self.expect_keyword(Keyword::TABLE)?;
@@ -10487,7 +10521,7 @@ impl<'a> Parser<'a> {
1048710521
Keyword::USER => self.parse_alter_user().map(Into::into),
1048810522
// unreachable because expect_one_of_keywords used above
1048910523
unexpected_keyword => Err(ParserError::ParserError(
10490-
format!("Internal parser error: expected any of {{VIEW, TYPE, TABLE, INDEX, ROLE, POLICY, CONNECTOR, ICEBERG, SCHEMA, USER, OPERATOR}}, got {unexpected_keyword:?}"),
10524+
format!("Internal parser error: expected any of {{VIEW, TYPE, COLLATION, TABLE, INDEX, ROLE, POLICY, CONNECTOR, ICEBERG, SCHEMA, USER, OPERATOR}}, got {unexpected_keyword:?}"),
1049110525
)),
1049210526
}
1049310527
}
@@ -10603,6 +10637,33 @@ impl<'a> Parser<'a> {
1060310637
}
1060410638
}
1060510639

10640+
/// Parse a [Statement::AlterCollation].
10641+
///
10642+
/// [PostgreSQL Documentation](https://www.postgresql.org/docs/current/sql-altercollation.html)
10643+
pub fn parse_alter_collation(&mut self) -> Result<AlterCollation, ParserError> {
10644+
let name = self.parse_object_name(false)?;
10645+
let operation = if self.parse_keywords(&[Keyword::RENAME, Keyword::TO]) {
10646+
AlterCollationOperation::RenameTo {
10647+
new_name: self.parse_identifier()?,
10648+
}
10649+
} else if self.parse_keywords(&[Keyword::OWNER, Keyword::TO]) {
10650+
AlterCollationOperation::OwnerTo(self.parse_owner()?)
10651+
} else if self.parse_keywords(&[Keyword::SET, Keyword::SCHEMA]) {
10652+
AlterCollationOperation::SetSchema {
10653+
schema_name: self.parse_object_name(false)?,
10654+
}
10655+
} else if self.parse_keywords(&[Keyword::REFRESH, Keyword::VERSION]) {
10656+
AlterCollationOperation::RefreshVersion
10657+
} else {
10658+
return self.expected_ref(
10659+
"RENAME TO, OWNER TO, SET SCHEMA, or REFRESH VERSION after ALTER COLLATION",
10660+
self.peek_token_ref(),
10661+
);
10662+
};
10663+
10664+
Ok(AlterCollation { name, operation })
10665+
}
10666+
1060610667
/// Parse a [Statement::AlterOperator]
1060710668
///
1060810669
/// [PostgreSQL Documentation](https://www.postgresql.org/docs/current/sql-alteroperator.html)

0 commit comments

Comments
 (0)