@@ -902,6 +902,9 @@ impl<'a> Parser<'a> {
902902 let token = self.next_token();
903903
904904 let (object_type, object_name) = match token.token {
905+ Token::Word(w) if w.keyword == Keyword::COLLATION => {
906+ (CommentObject::Collation, self.parse_object_name(false)?)
907+ }
905908 Token::Word(w) if w.keyword == Keyword::COLUMN => {
906909 (CommentObject::Column, self.parse_object_name(false)?)
907910 }
@@ -5188,6 +5191,8 @@ impl<'a> Parser<'a> {
51885191 self.parse_create_role().map(Into::into)
51895192 } else if self.parse_keyword(Keyword::SEQUENCE) {
51905193 self.parse_create_sequence(temporary)
5194+ } else if self.parse_keyword(Keyword::COLLATION) {
5195+ self.parse_create_collation().map(Into::into)
51915196 } else if self.parse_keyword(Keyword::TYPE) {
51925197 self.parse_create_type()
51935198 } else if self.parse_keyword(Keyword::PROCEDURE) {
@@ -7352,6 +7357,8 @@ impl<'a> Parser<'a> {
73527357
73537358 let object_type = if self.parse_keyword(Keyword::TABLE) {
73547359 ObjectType::Table
7360+ } else if self.parse_keyword(Keyword::COLLATION) {
7361+ ObjectType::Collation
73557362 } else if self.parse_keyword(Keyword::VIEW) {
73567363 ObjectType::View
73577364 } else if self.parse_keywords(&[Keyword::MATERIALIZED, Keyword::VIEW]) {
@@ -7401,7 +7408,7 @@ impl<'a> Parser<'a> {
74017408 };
74027409 } else {
74037410 return self.expected_ref(
7404- "CONNECTOR, DATABASE, EXTENSION, FUNCTION, INDEX, OPERATOR, POLICY, PROCEDURE, ROLE, SCHEMA, SECRET, SEQUENCE, STAGE, TABLE, TRIGGER, TYPE, VIEW, MATERIALIZED VIEW or USER after DROP",
7411+ "COLLATION, CONNECTOR, DATABASE, EXTENSION, FUNCTION, INDEX, OPERATOR, POLICY, PROCEDURE, ROLE, SCHEMA, SECRET, SEQUENCE, STAGE, TABLE, TRIGGER, TYPE, VIEW, MATERIALIZED VIEW or USER after DROP",
74057412 self.peek_token_ref(),
74067413 );
74077414 };
@@ -8142,6 +8149,31 @@ impl<'a> Parser<'a> {
81428149 })
81438150 }
81448151
8152+ /// Parse a PostgreSQL-specific [Statement::CreateCollation] statement.
8153+ pub fn parse_create_collation(&mut self) -> Result<CreateCollation, ParserError> {
8154+ let if_not_exists = self.parse_keywords(&[Keyword::IF, Keyword::NOT, Keyword::EXISTS]);
8155+ let name = self.parse_object_name(false)?;
8156+
8157+ let definition = if self.parse_keyword(Keyword::FROM) {
8158+ CreateCollationDefinition::From(self.parse_object_name(false)?)
8159+ } else if self.consume_token(&Token::LParen) {
8160+ let options = self.parse_comma_separated(Parser::parse_sql_option)?;
8161+ self.expect_token(&Token::RParen)?;
8162+ CreateCollationDefinition::Options(options)
8163+ } else {
8164+ return self.expected_ref(
8165+ "FROM or parenthesized option list after CREATE COLLATION name",
8166+ self.peek_token_ref(),
8167+ );
8168+ };
8169+
8170+ Ok(CreateCollation {
8171+ if_not_exists,
8172+ name,
8173+ definition,
8174+ })
8175+ }
8176+
81458177 /// Parse a PostgreSQL-specific [Statement::DropExtension] statement.
81468178 pub fn parse_drop_extension(&mut self) -> Result<Statement, ParserError> {
81478179 let if_exists = self.parse_keywords(&[Keyword::IF, Keyword::EXISTS]);
@@ -10673,6 +10705,7 @@ impl<'a> Parser<'a> {
1067310705 let object_type = self.expect_one_of_keywords(&[
1067410706 Keyword::VIEW,
1067510707 Keyword::TYPE,
10708+ Keyword::COLLATION,
1067610709 Keyword::TABLE,
1067710710 Keyword::INDEX,
1067810711 Keyword::FUNCTION,
@@ -10693,6 +10726,7 @@ impl<'a> Parser<'a> {
1069310726 }
1069410727 Keyword::VIEW => self.parse_alter_view(),
1069510728 Keyword::TYPE => self.parse_alter_type(),
10729+ Keyword::COLLATION => self.parse_alter_collation().map(Into::into),
1069610730 Keyword::TABLE => self.parse_alter_table(false),
1069710731 Keyword::ICEBERG => {
1069810732 self.expect_keyword(Keyword::TABLE)?;
@@ -10733,7 +10767,7 @@ impl<'a> Parser<'a> {
1073310767 Keyword::USER => self.parse_alter_user().map(Into::into),
1073410768 // unreachable because expect_one_of_keywords used above
1073510769 unexpected_keyword => Err(ParserError::ParserError(
10736- format!("Internal parser error: expected any of {{VIEW, TYPE, TABLE, INDEX, FUNCTION, AGGREGATE, ROLE, POLICY, CONNECTOR, ICEBERG, SCHEMA, USER, OPERATOR}}, got {unexpected_keyword:?}"),
10770+ format!("Internal parser error: expected any of {{VIEW, TYPE, COLLATION, TABLE, INDEX, FUNCTION, AGGREGATE, ROLE, POLICY, CONNECTOR, ICEBERG, SCHEMA, USER, OPERATOR}}, got {unexpected_keyword:?}"),
1073710771 )),
1073810772 }
1073910773 }
@@ -11070,6 +11104,33 @@ impl<'a> Parser<'a> {
1107011104 }
1107111105 }
1107211106
11107+ /// Parse a [Statement::AlterCollation].
11108+ ///
11109+ /// [PostgreSQL Documentation](https://www.postgresql.org/docs/current/sql-altercollation.html)
11110+ pub fn parse_alter_collation(&mut self) -> Result<AlterCollation, ParserError> {
11111+ let name = self.parse_object_name(false)?;
11112+ let operation = if self.parse_keywords(&[Keyword::RENAME, Keyword::TO]) {
11113+ AlterCollationOperation::RenameTo {
11114+ new_name: self.parse_identifier()?,
11115+ }
11116+ } else if self.parse_keywords(&[Keyword::OWNER, Keyword::TO]) {
11117+ AlterCollationOperation::OwnerTo(self.parse_owner()?)
11118+ } else if self.parse_keywords(&[Keyword::SET, Keyword::SCHEMA]) {
11119+ AlterCollationOperation::SetSchema {
11120+ schema_name: self.parse_object_name(false)?,
11121+ }
11122+ } else if self.parse_keywords(&[Keyword::REFRESH, Keyword::VERSION]) {
11123+ AlterCollationOperation::RefreshVersion
11124+ } else {
11125+ return self.expected_ref(
11126+ "RENAME TO, OWNER TO, SET SCHEMA, or REFRESH VERSION after ALTER COLLATION",
11127+ self.peek_token_ref(),
11128+ );
11129+ };
11130+
11131+ Ok(AlterCollation { name, operation })
11132+ }
11133+
1107311134 /// Parse a [Statement::AlterOperator]
1107411135 ///
1107511136 /// [PostgreSQL Documentation](https://www.postgresql.org/docs/current/sql-alteroperator.html)
0 commit comments