@@ -533,10 +533,11 @@ impl<'a> Parser<'a> {
533533 Keyword::EXECUTE | Keyword::EXEC => self.parse_execute(),
534534 Keyword::PREPARE => self.parse_prepare(),
535535 Keyword::MERGE => self.parse_merge(),
536- // `LISTEN` and `NOTIFY` are Postgres-specific
536+ // `LISTEN`, `UNLISTEN` and `NOTIFY` are Postgres-specific
537537 // syntaxes. They are used for Postgres statement.
538- Keyword::LISTEN if self.dialect.supports_listen() => self.parse_listen(),
539- Keyword::NOTIFY if self.dialect.supports_notify() => self.parse_notify(),
538+ Keyword::LISTEN if self.dialect.supports_listen_notify() => self.parse_listen(),
539+ Keyword::UNLISTEN if self.dialect.supports_listen_notify() => self.parse_unlisten(),
540+ Keyword::NOTIFY if self.dialect.supports_listen_notify() => self.parse_notify(),
540541 // `PRAGMA` is sqlite specific https://www.sqlite.org/pragma.html
541542 Keyword::PRAGMA => self.parse_pragma(),
542543 Keyword::UNLOAD => self.parse_unload(),
@@ -1003,6 +1004,21 @@ impl<'a> Parser<'a> {
10031004 Ok(Statement::LISTEN { channel })
10041005 }
10051006
1007+ pub fn parse_unlisten(&mut self) -> Result<Statement, ParserError> {
1008+ let channel = if self.consume_token(&Token::Mul) {
1009+ Ident::new(Expr::Wildcard(AttachedToken::empty()).to_string())
1010+ } else {
1011+ match self.parse_identifier(false) {
1012+ Ok(expr) => expr,
1013+ _ => {
1014+ self.prev_token();
1015+ return self.expected("wildcard or identifier", self.peek_token());
1016+ }
1017+ }
1018+ };
1019+ Ok(Statement::UNLISTEN { channel })
1020+ }
1021+
10061022 pub fn parse_notify(&mut self) -> Result<Statement, ParserError> {
10071023 let channel = self.parse_identifier(false)?;
10081024 let payload = if self.consume_token(&Token::Comma) {
@@ -2927,7 +2943,7 @@ impl<'a> Parser<'a> {
29272943 } else if Token::LBracket == tok {
29282944 if dialect_of!(self is PostgreSqlDialect | DuckDbDialect | GenericDialect) {
29292945 self.parse_subscript(expr)
2930- } else if dialect_of!(self is SnowflakeDialect) {
2946+ } else if dialect_of!(self is SnowflakeDialect) || self.dialect.supports_partiql() {
29312947 self.prev_token();
29322948 self.parse_json_access(expr)
29332949 } else {
@@ -3063,6 +3079,14 @@ impl<'a> Parser<'a> {
30633079 }
30643080
30653081 fn parse_json_access(&mut self, expr: Expr) -> Result<Expr, ParserError> {
3082+ let path = self.parse_json_path()?;
3083+ Ok(Expr::JsonAccess {
3084+ value: Box::new(expr),
3085+ path,
3086+ })
3087+ }
3088+
3089+ fn parse_json_path(&mut self) -> Result<JsonPath, ParserError> {
30663090 let mut path = Vec::new();
30673091 loop {
30683092 match self.next_token().token {
@@ -3086,10 +3110,7 @@ impl<'a> Parser<'a> {
30863110 }
30873111
30883112 debug_assert!(!path.is_empty());
3089- Ok(Expr::JsonAccess {
3090- value: Box::new(expr),
3091- path: JsonPath { path },
3092- })
3113+ Ok(JsonPath { path })
30933114 }
30943115
30953116 pub fn parse_map_access(&mut self, expr: Expr) -> Result<Expr, ParserError> {
@@ -3522,16 +3543,11 @@ impl<'a> Parser<'a> {
35223543 // e.g. `SELECT 1, 2, FROM t`
35233544 // https://cloud.google.com/bigquery/docs/reference/standard-sql/lexical#trailing_commas
35243545 // https://docs.snowflake.com/en/release-notes/2024/8_11#select-supports-trailing-commas
3525- //
3526- // This pattern could be captured better with RAII type semantics, but it's quite a bit of
3527- // code to add for just one case, so we'll just do it manually here.
3528- let old_value = self.options.trailing_commas;
3529- self.options.trailing_commas |= self.dialect.supports_projection_trailing_commas();
35303546
3531- let ret = self.parse_comma_separated(|p| p.parse_select_item());
3532- self.options.trailing_commas = old_value ;
3547+ let trailing_commas =
3548+ self.options.trailing_commas | self.dialect.supports_projection_trailing_commas() ;
35333549
3534- ret
3550+ self.parse_comma_separated_with_trailing_commas(|p| p.parse_select_item(), trailing_commas)
35353551 }
35363552
35373553 pub fn parse_actions_list(&mut self) -> Result<Vec<ParsedAction>, ParserError> {
@@ -3558,11 +3574,12 @@ impl<'a> Parser<'a> {
35583574 }
35593575
35603576 /// Parse the comma of a comma-separated syntax element.
3577+ /// Allows for control over trailing commas
35613578 /// Returns true if there is a next element
3562- fn is_parse_comma_separated_end (&mut self) -> bool {
3579+ fn is_parse_comma_separated_end_with_trailing_commas (&mut self, trailing_commas: bool ) -> bool {
35633580 if !self.consume_token(&Token::Comma) {
35643581 true
3565- } else if self.options. trailing_commas {
3582+ } else if trailing_commas {
35663583 let token = self.peek_token().token;
35673584 match token {
35683585 Token::Word(ref kw)
@@ -3580,15 +3597,34 @@ impl<'a> Parser<'a> {
35803597 }
35813598 }
35823599
3600+ /// Parse the comma of a comma-separated syntax element.
3601+ /// Returns true if there is a next element
3602+ fn is_parse_comma_separated_end(&mut self) -> bool {
3603+ self.is_parse_comma_separated_end_with_trailing_commas(self.options.trailing_commas)
3604+ }
3605+
35833606 /// Parse a comma-separated list of 1+ items accepted by `F`
3584- pub fn parse_comma_separated<T, F>(&mut self, mut f: F) -> Result<Vec<T>, ParserError>
3607+ pub fn parse_comma_separated<T, F>(&mut self, f: F) -> Result<Vec<T>, ParserError>
3608+ where
3609+ F: FnMut(&mut Parser<'a>) -> Result<T, ParserError>,
3610+ {
3611+ self.parse_comma_separated_with_trailing_commas(f, self.options.trailing_commas)
3612+ }
3613+
3614+ /// Parse a comma-separated list of 1+ items accepted by `F`
3615+ /// Allows for control over trailing commas
3616+ fn parse_comma_separated_with_trailing_commas<T, F>(
3617+ &mut self,
3618+ mut f: F,
3619+ trailing_commas: bool,
3620+ ) -> Result<Vec<T>, ParserError>
35853621 where
35863622 F: FnMut(&mut Parser<'a>) -> Result<T, ParserError>,
35873623 {
35883624 let mut values = vec![];
35893625 loop {
35903626 values.push(f(self)?);
3591- if self.is_parse_comma_separated_end( ) {
3627+ if self.is_parse_comma_separated_end_with_trailing_commas(trailing_commas ) {
35923628 break;
35933629 }
35943630 }
@@ -10326,6 +10362,11 @@ impl<'a> Parser<'a> {
1032610362 } else {
1032710363 let name = self.parse_object_name(true)?;
1032810364
10365+ let json_path = match self.peek_token().token {
10366+ Token::LBracket if self.dialect.supports_partiql() => Some(self.parse_json_path()?),
10367+ _ => None,
10368+ };
10369+
1032910370 let partitions: Vec<Ident> = if dialect_of!(self is MySqlDialect | GenericDialect)
1033010371 && self.parse_keyword(Keyword::PARTITION)
1033110372 {
@@ -10368,6 +10409,7 @@ impl<'a> Parser<'a> {
1036810409 version,
1036910410 partitions,
1037010411 with_ordinality,
10412+ json_path,
1037110413 };
1037210414
1037310415 while let Some(kw) = self.parse_one_of_keywords(&[Keyword::PIVOT, Keyword::UNPIVOT]) {
0 commit comments