@@ -4692,6 +4692,17 @@ impl<'a> Parser<'a> {
46924692 }
46934693 }
46944694
4695+ /// Returns `true` if the current token matches `token` and is further
4696+ /// followed by one of the specified `keywords`.
4697+ ///
4698+ /// Does not advance the current token.
4699+ #[must_use]
4700+ fn peek_token_with_one_of_keywords(&mut self, token: &Token, keywords: &[Keyword]) -> bool {
4701+ let [maybe_token, maybe_keyword] = self.peek_tokens_ref();
4702+ &maybe_token.token == token
4703+ && matches!(&maybe_keyword.token, Token::Word(w) if keywords.contains(&w.keyword))
4704+ }
4705+
46954706 /// If the current token is one of the expected keywords, consume the token
46964707 /// and return the keyword that matches. Otherwise, return an error.
46974708 pub fn expect_one_of_keywords(&mut self, keywords: &[Keyword]) -> Result<Keyword, ParserError> {
@@ -12688,7 +12699,7 @@ impl<'a> Parser<'a> {
1268812699 let fn_name = self.parse_object_name(false)?;
1268912700 self.parse_function_call(fn_name)
1269012701 .map(TableObject::TableFunction)
12691- } else if self.dialect.supports_insert_table_query() && self.peek_subquery_start(true ) {
12702+ } else if self.dialect.supports_insert_table_query() && self.peek_subquery_or_cte_start( ) {
1269212703 self.parse_parenthesized(|p| p.parse_query())
1269312704 .map(TableObject::TableQuery)
1269412705 } else {
@@ -17437,7 +17448,7 @@ impl<'a> Parser<'a> {
1743717448 {
1743817449 (vec![], None, vec![], None, None, vec![])
1743917450 } else {
17440- let (columns, partitioned, after_columns) = if !self.peek_subquery_start(false ) {
17451+ let (columns, partitioned, after_columns) = if !self.peek_subquery_start() {
1744117452 let columns =
1744217453 self.parse_parenthesized_qualified_column_list(Optional, is_mysql)?;
1744317454
@@ -17602,15 +17613,16 @@ impl<'a> Parser<'a> {
1760217613 }
1760317614
1760417615 /// Returns true if the immediate tokens look like the
17605- /// beginning of a subquery, e.g. `(SELECT ...`.
17606- ///
17607- /// If `full_query == true` attempt to detect a full query with its
17608- /// optional, leading `WITH` clause, e.g. `(WITH ...)`
17609- fn peek_subquery_start(&mut self, full_query: bool) -> bool {
17610- let [maybe_lparen, maybe_select] = self.peek_tokens();
17611- Token::LParen == maybe_lparen
17612- && matches!(maybe_select, Token::Word(w)
17613- if w.keyword == Keyword::SELECT || (full_query && w.keyword == Keyword::WITH))
17616+ /// beginning of a subquery. `(SELECT ...`
17617+ fn peek_subquery_start(&mut self) -> bool {
17618+ self.peek_token_with_one_of_keywords(&Token::LParen, &[Keyword::SELECT])
17619+ }
17620+
17621+ /// Returns true if the immediate tokens look like the
17622+ /// beginning of a subquery possibly preceded by CTEs;
17623+ /// i.e. `(WITH ...` or `(SELECT ...`.
17624+ fn peek_subquery_or_cte_start(&mut self) -> bool {
17625+ self.peek_token_with_one_of_keywords(&Token::LParen, &[Keyword::SELECT, Keyword::WITH])
1761417626 }
1761517627
1761617628 fn parse_conflict_clause(&mut self) -> Option<SqliteOnConflict> {
0 commit comments