@@ -5175,6 +5175,8 @@ impl<'a> Parser<'a> {
51755175 self.parse_create_user(or_replace).map(Into::into)
51765176 } else if self.parse_keyword(Keyword::AGGREGATE) {
51775177 self.parse_create_aggregate(or_replace).map(Into::into)
5178+ } else if self.parse_keyword(Keyword::TRANSFORM) {
5179+ self.parse_create_transform(or_replace).map(Into::into)
51785180 } else if or_replace {
51795181 self.expected_ref(
51805182 "[EXTERNAL] TABLE or [MATERIALIZED] VIEW or FUNCTION after CREATE OR REPLACE",
@@ -5232,6 +5234,12 @@ impl<'a> Parser<'a> {
52325234 self.parse_create_publication().map(Into::into)
52335235 } else if self.parse_keyword(Keyword::SUBSCRIPTION) {
52345236 self.parse_create_subscription().map(Into::into)
5237+ } else if self.parse_keyword(Keyword::STATISTICS) {
5238+ self.parse_create_statistics().map(Into::into)
5239+ } else if self.parse_keywords(&[Keyword::ACCESS, Keyword::METHOD]) {
5240+ self.parse_create_access_method().map(Into::into)
5241+ } else if self.parse_keywords(&[Keyword::EVENT, Keyword::TRIGGER]) {
5242+ self.parse_create_event_trigger().map(Into::into)
52355243 } else {
52365244 self.expected_ref("an object type after CREATE", self.peek_token_ref())
52375245 }
@@ -20268,6 +20276,162 @@ impl<'a> Parser<'a> {
2026820276 })
2026920277 }
2027020278
20279+ /// Parse a `CREATE STATISTICS` statement.
20280+ ///
20281+ /// See <https://www.postgresql.org/docs/current/sql-createstatistics.html>
20282+ pub fn parse_create_statistics(&mut self) -> Result<CreateStatistics, ParserError> {
20283+ let if_not_exists = self.parse_keywords(&[Keyword::IF, Keyword::NOT, Keyword::EXISTS]);
20284+ let name = self.parse_object_name(false)?;
20285+
20286+ let kinds = if self.consume_token(&Token::LParen) {
20287+ let kinds = self.parse_comma_separated(|p| {
20288+ let ident = p.parse_identifier()?;
20289+ match ident.value.to_lowercase().as_str() {
20290+ "ndistinct" => Ok(StatisticsKind::NDistinct),
20291+ "dependencies" => Ok(StatisticsKind::Dependencies),
20292+ "mcv" => Ok(StatisticsKind::Mcv),
20293+ other => Err(ParserError::ParserError(format!(
20294+ "Unknown statistics kind: {other}"
20295+ ))),
20296+ }
20297+ })?;
20298+ self.expect_token(&Token::RParen)?;
20299+ kinds
20300+ } else {
20301+ vec![]
20302+ };
20303+
20304+ self.expect_keyword_is(Keyword::ON)?;
20305+ let on = self.parse_comma_separated(Parser::parse_expr)?;
20306+ self.expect_keyword_is(Keyword::FROM)?;
20307+ let from = self.parse_object_name(false)?;
20308+
20309+ Ok(CreateStatistics {
20310+ if_not_exists,
20311+ name,
20312+ kinds,
20313+ on,
20314+ from,
20315+ })
20316+ }
20317+
20318+ /// Parse a `CREATE ACCESS METHOD` statement.
20319+ ///
20320+ /// See <https://www.postgresql.org/docs/current/sql-create-access-method.html>
20321+ pub fn parse_create_access_method(&mut self) -> Result<CreateAccessMethod, ParserError> {
20322+ let name = self.parse_identifier()?;
20323+ self.expect_keyword_is(Keyword::TYPE)?;
20324+ let method_type = if self.parse_keyword(Keyword::INDEX) {
20325+ AccessMethodType::Index
20326+ } else if self.parse_keyword(Keyword::TABLE) {
20327+ AccessMethodType::Table
20328+ } else {
20329+ return self.expected_ref("INDEX or TABLE after TYPE", self.peek_token_ref());
20330+ };
20331+ self.expect_keyword_is(Keyword::HANDLER)?;
20332+ let handler = self.parse_object_name(false)?;
20333+
20334+ Ok(CreateAccessMethod {
20335+ name,
20336+ method_type,
20337+ handler,
20338+ })
20339+ }
20340+
20341+ /// Parse a `CREATE EVENT TRIGGER` statement.
20342+ ///
20343+ /// See <https://www.postgresql.org/docs/current/sql-createeventtrigger.html>
20344+ pub fn parse_create_event_trigger(&mut self) -> Result<CreateEventTrigger, ParserError> {
20345+ let name = self.parse_identifier()?;
20346+ self.expect_keyword_is(Keyword::ON)?;
20347+ let event_ident = self.parse_identifier()?;
20348+ let event = match event_ident.value.to_lowercase().as_str() {
20349+ "ddl_command_start" => EventTriggerEvent::DdlCommandStart,
20350+ "ddl_command_end" => EventTriggerEvent::DdlCommandEnd,
20351+ "table_rewrite" => EventTriggerEvent::TableRewrite,
20352+ "sql_drop" => EventTriggerEvent::SqlDrop,
20353+ other => {
20354+ return Err(ParserError::ParserError(format!(
20355+ "Unknown event trigger event: {other}"
20356+ )))
20357+ }
20358+ };
20359+
20360+ let when_tags = if self.parse_keyword(Keyword::WHEN) {
20361+ self.expect_keyword_is(Keyword::TAG)?;
20362+ self.expect_keyword_is(Keyword::IN)?;
20363+ self.expect_token(&Token::LParen)?;
20364+ let tags = self.parse_comma_separated(|p| p.parse_value().map(|v| v.value))?;
20365+ self.expect_token(&Token::RParen)?;
20366+ Some(tags)
20367+ } else {
20368+ None
20369+ };
20370+
20371+ self.expect_keyword_is(Keyword::EXECUTE)?;
20372+ let is_procedure = if self.parse_keyword(Keyword::FUNCTION) {
20373+ false
20374+ } else if self.parse_keyword(Keyword::PROCEDURE) {
20375+ true
20376+ } else {
20377+ return self.expected_ref("FUNCTION or PROCEDURE after EXECUTE", self.peek_token_ref());
20378+ };
20379+ let execute = self.parse_object_name(false)?;
20380+ self.expect_token(&Token::LParen)?;
20381+ self.expect_token(&Token::RParen)?;
20382+
20383+ Ok(CreateEventTrigger {
20384+ name,
20385+ event,
20386+ when_tags,
20387+ execute,
20388+ is_procedure,
20389+ })
20390+ }
20391+
20392+ /// Parse a `CREATE [OR REPLACE] TRANSFORM` statement.
20393+ ///
20394+ /// See <https://www.postgresql.org/docs/current/sql-createtransform.html>
20395+ pub fn parse_create_transform(&mut self, or_replace: bool) -> Result<CreateTransform, ParserError> {
20396+ self.expect_keyword_is(Keyword::FOR)?;
20397+ let type_name = self.parse_data_type()?;
20398+ self.expect_keyword_is(Keyword::LANGUAGE)?;
20399+ let language = self.parse_identifier()?;
20400+ self.expect_token(&Token::LParen)?;
20401+ let elements = self.parse_comma_separated(|p| {
20402+ let is_from = if p.parse_keyword(Keyword::FROM) {
20403+ true
20404+ } else {
20405+ p.expect_keyword_is(Keyword::TO)?;
20406+ false
20407+ };
20408+ p.expect_keyword_is(Keyword::SQL)?;
20409+ p.expect_keyword_is(Keyword::WITH)?;
20410+ p.expect_keyword_is(Keyword::FUNCTION)?;
20411+ let function = p.parse_object_name(false)?;
20412+ p.expect_token(&Token::LParen)?;
20413+ let arg_types = if p.peek_token().token == Token::RParen {
20414+ vec![]
20415+ } else {
20416+ p.parse_comma_separated(|p| p.parse_data_type())?
20417+ };
20418+ p.expect_token(&Token::RParen)?;
20419+ Ok(TransformElement {
20420+ is_from,
20421+ function,
20422+ arg_types,
20423+ })
20424+ })?;
20425+ self.expect_token(&Token::RParen)?;
20426+
20427+ Ok(CreateTransform {
20428+ or_replace,
20429+ type_name,
20430+ language,
20431+ elements,
20432+ })
20433+ }
20434+
2027120435 /// The index of the first unprocessed token.
2027220436 pub fn index(&self) -> usize {
2027320437 self.index
0 commit comments