// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//! SQL Parser

#[cfg(not(feature = "std"))]
use alloc::{
    boxed::Box,
    collections::{BTreeMap, BTreeSet},
    format,
    string::{String, ToString},
    vec,
    vec::Vec,
};
use core::{
    fmt::{self, Display},
    str::FromStr,
};
#[cfg(feature = "std")]
use std::collections::{BTreeMap, BTreeSet};

use helpers::attached_token::AttachedToken;

use log::debug;

use recursion::RecursionCounter;
use IsLateral::*;
use IsOptional::*;

use crate::ast::*;
use crate::ast::{
    comments,
    helpers::{
        key_value_options::{
            KeyValueOption, KeyValueOptionKind, KeyValueOptions, KeyValueOptionsDelimiter,
        },
        stmt_create_table::{CreateTableBuilder, CreateTableConfiguration},
    },
};
use crate::dialect::*;
use crate::keywords::{Keyword, ALL_KEYWORDS};
use crate::tokenizer::*;
use sqlparser::parser::ParserState::ColumnDefinition;

/// Errors produced by the SQL parser.
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum ParserError {
    /// Error originating from the tokenizer with a message.
    TokenizerError(String),
    /// Generic parser error with a message.
    ParserError(String),
    /// Raised when a recursion depth limit is exceeded.
    RecursionLimitExceeded,
}

// Use `Parser::expected` instead, if possible
macro_rules! parser_err {
    ($MSG:expr, $loc:expr) => {
        Err(ParserError::ParserError(format!("{}{}", $MSG, $loc)))
    };
}

mod alter;
mod merge;

/// Implementation of [`RecursionCounter`].
///
/// Explicitly requires only `alloc` and `core`, so recursion is limited even
/// when the "std" feature is disabled.
mod recursion {
    use alloc::rc::Rc;
    use core::cell::Cell;

    use super::ParserError;

    /// Tracks remaining recursion depth. This value is decremented on
    /// each call to [`RecursionCounter::try_decrease()`], when it reaches 0 an error will
    /// be returned.
    ///
    /// Note: Uses an [`alloc::rc::Rc`] and [`core::cell::Cell`] in order to satisfy the Rust
    /// borrow checker so the automatic [`DepthGuard`] decrement a
    /// reference to the counter.
    ///
    /// Note: when "recursive-protection" feature is enabled, this crate uses additional stack overflow protection
    /// for some of its recursive methods. See [`recursive::recursive`] for more information.
    pub(crate) struct RecursionCounter {
        remaining_depth: Rc<Cell<usize>>,
    }

    impl RecursionCounter {
        /// Creates a [`RecursionCounter`] with the specified maximum
        /// depth
        pub fn new(remaining_depth: usize) -> Self {
            Self {
                remaining_depth: Rc::new(remaining_depth.into()),
            }
        }

        /// Decreases the remaining depth by 1.
        ///
        /// Returns [`Err`] if the remaining depth falls to 0.
        ///
        /// Returns a [`DepthGuard`] which will adds 1 to the
        /// remaining depth upon drop;
        pub fn try_decrease(&self) -> Result<DepthGuard, ParserError> {
            let old_value = self.remaining_depth.get();
            // ran out of space
            if old_value == 0 {
                Err(ParserError::RecursionLimitExceeded)
            } else {
                self.remaining_depth.set(old_value - 1);
                Ok(DepthGuard::new(Rc::clone(&self.remaining_depth)))
            }
        }
    }

    /// Guard that increases the remaining depth by 1 on drop
    pub struct DepthGuard {
        remaining_depth: Rc<Cell<usize>>,
    }

    impl DepthGuard {
        fn new(remaining_depth: Rc<Cell<usize>>) -> Self {
            Self { remaining_depth }
        }
    }

    impl Drop for DepthGuard {
        fn drop(&mut self) {
            let old_value = self.remaining_depth.get();
            self.remaining_depth.set(old_value.saturating_add(1));
        }
    }
}

#[derive(PartialEq, Eq)]
/// Indicates whether a parser element is optional or mandatory.
pub enum IsOptional {
    /// The element is optional.
    Optional,
    /// The element is mandatory.
    Mandatory,
}

/// Indicates if a table expression is lateral.
pub enum IsLateral {
    /// The expression is lateral.
    Lateral,
    /// The expression is not lateral.
    NotLateral,
}

/// Represents a wildcard expression used in SELECT lists.
pub enum WildcardExpr {
    /// A specific expression used instead of a wildcard.
    Expr(Expr),
    /// A qualified wildcard like `table.*`.
    QualifiedWildcard(ObjectName),
    /// An unqualified `*` wildcard.
    Wildcard,
}

impl From<TokenizerError> for ParserError {
    fn from(e: TokenizerError) -> Self {
        ParserError::TokenizerError(e.to_string())
    }
}

impl fmt::Display for ParserError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(
            f,
            "sql parser error: {}",
            match self {
                ParserError::TokenizerError(s) => s,
                ParserError::ParserError(s) => s,
                ParserError::RecursionLimitExceeded => "recursion limit exceeded",
            }
        )
    }
}

impl core::error::Error for ParserError {}

// By default, allow expressions up to this deep before erroring
const DEFAULT_REMAINING_DEPTH: usize = 50;

// A constant EOF token that can be referenced.
const EOF_TOKEN: TokenWithSpan = TokenWithSpan {
    token: Token::EOF,
    span: Span {
        start: Location { line: 0, column: 0 },
        end: Location { line: 0, column: 0 },
    },
};

/// Composite types declarations using angle brackets syntax can be arbitrary
/// nested such that the following declaration is possible:
///      `ARRAY<ARRAY<INT>>`
/// But the tokenizer recognizes the `>>` as a ShiftRight token.
/// We work around that limitation when parsing a data type by accepting
/// either a `>` or `>>` token in such cases, remembering which variant we
/// matched.
/// In the latter case having matched a `>>`, the parent type will not look to
/// match its closing `>` as a result since that will have taken place at the
/// child type.
///
/// See [Parser::parse_data_type] for details
struct MatchedTrailingBracket(bool);

impl From<bool> for MatchedTrailingBracket {
    fn from(value: bool) -> Self {
        Self(value)
    }
}

/// Options that control how the [`Parser`] parses SQL text
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ParserOptions {
    /// Allow trailing commas in lists (e.g. `a, b,`).
    pub trailing_commas: bool,
    /// Controls how literal values are unescaped. See
    /// [`Tokenizer::with_unescape`] for more details.
    pub unescape: bool,
    /// Controls if the parser expects a semi-colon token
    /// between statements. Default is `true`.
    pub require_semicolon_stmt_delimiter: bool,
}

impl Default for ParserOptions {
    fn default() -> Self {
        Self {
            trailing_commas: false,
            unescape: true,
            require_semicolon_stmt_delimiter: true,
        }
    }
}

impl ParserOptions {
    /// Create a new [`ParserOptions`]
    pub fn new() -> Self {
        Default::default()
    }

    /// Set if trailing commas are allowed.
    ///
    /// If this option is `false` (the default), the following SQL will
    /// not parse. If the option is `true`, the SQL will parse.
    ///
    /// ```sql
    ///  SELECT
    ///   foo,
    ///   bar,
    ///  FROM baz
    /// ```
    pub fn with_trailing_commas(mut self, trailing_commas: bool) -> Self {
        self.trailing_commas = trailing_commas;
        self
    }

    /// Set if literal values are unescaped. Defaults to true. See
    /// [`Tokenizer::with_unescape`] for more details.
    pub fn with_unescape(mut self, unescape: bool) -> Self {
        self.unescape = unescape;
        self
    }
}

#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
enum ParserState {
    /// The default state of the parser.
    Normal,
    /// The state when parsing a CONNECT BY expression. This allows parsing
    /// PRIOR expressions while still allowing prior as an identifier name
    /// in other contexts.
    ConnectBy,
    /// The state when parsing column definitions.  This state prohibits
    /// NOT NULL as an alias for IS NOT NULL.  For example:
    /// ```sql
    /// CREATE TABLE foo (abc BIGINT NOT NULL);
    /// ```
    ColumnDefinition,
}

/// A SQL Parser
///
/// This struct is the main entry point for parsing SQL queries.
///
/// # Functionality:
/// * Parsing SQL: see examples on [`Parser::new`] and [`Parser::parse_sql`]
/// * Controlling recursion: See [`Parser::with_recursion_limit`]
/// * Controlling parser options: See [`Parser::with_options`]
/// * Providing your own tokens: See [`Parser::with_tokens`]
///
/// # Internals
///
/// The parser uses a [`Tokenizer`] to tokenize the input SQL string into a
/// `Vec` of [`TokenWithSpan`]s and maintains an `index` to the current token
/// being processed. The token vec may contain multiple SQL statements.
///
/// * The "current" token is the token at `index - 1`
/// * The "next" token is the token at `index`
/// * The "previous" token is the token at `index - 2`
///
/// If `index` is equal to the length of the token stream, the 'next' token is
/// [`Token::EOF`].
///
/// For example, the SQL string "SELECT * FROM foo" will be tokenized into
/// following tokens:
/// ```text
///  [
///    "SELECT", // token index 0
///    " ",      // whitespace
///    "*",
///    " ",
///    "FROM",
///    " ",
///    "foo"
///   ]
/// ```
///
///
pub struct Parser<'a> {
    /// The tokens
    tokens: Vec<TokenWithSpan>,
    /// The index of the first unprocessed token in [`Parser::tokens`].
    index: usize,
    /// The current state of the parser.
    state: ParserState,
    /// The SQL dialect to use.
    dialect: &'a dyn Dialect,
    /// Additional options that allow you to mix & match behavior
    /// otherwise constrained to certain dialects (e.g. trailing
    /// commas) and/or format of parse (e.g. unescaping).
    options: ParserOptions,
    /// Ensures the stack does not overflow by limiting recursion depth.
    recursion_counter: RecursionCounter,
    /// Cached failures from `parse_prefix` calls that returned `Err`. See
    /// [`Parser::parse_prefix`] for the 2^N patterns this guards.
    failed_prefix_positions: BTreeMap<usize, ExprPrefixError>,
    /// Cached failures from the speculative reserved-word prefix arm. See
    /// [`Parser::parse_prefix`] for the 2^N patterns this guards.
    failed_reserved_word_prefix_positions: BTreeMap<usize, ExprPrefixError>,
    /// Cached failures from the speculative derived-table arm of
    /// `parse_table_factor`. See [`Parser::parse_table_factor`] for the 2^N
    /// pattern this guards.
    failed_derived_table_factor_positions: BTreeSet<usize>,
    /// Cached failures of the speculative `POSITION(<expr> IN <expr>)` arm.
    /// See [`Parser::parse_position_expr`] for the 2^N pattern this guards.
    /// Keyed by state too, since `PRIOR` parses differently in `CONNECT BY`.
    failed_position_syntax_positions: BTreeSet<(usize, ParserState)>,
    /// Cached failures from the speculative subquery arm of [`Parser::parse_in`],
    /// which `IN` lists nested in a leading subquery would otherwise retry at
    /// every level, taking 2^N time. Maps the arm's start to where a parsed
    /// query lacked its `)`.
    failed_in_subquery_positions: BTreeMap<usize, Option<usize>>,
}

/// Copy marker for a [`ParserError`] cached by the `parse_prefix` failure
/// memoization, so the caches hold no strings.
#[derive(Debug, Clone, Copy)]
enum ExprPrefixError {
    RecursionLimitExceeded,
    Err,
}

impl From<&ParserError> for ExprPrefixError {
    fn from(e: &ParserError) -> Self {
        match e {
            ParserError::RecursionLimitExceeded => Self::RecursionLimitExceeded,
            _ => Self::Err,
        }
    }
}

impl<'a> Parser<'a> {
    /// Create a parser for a [`Dialect`]
    ///
    /// See also [`Parser::parse_sql`]
    ///
    /// Example:
    /// ```
    /// # use sqlparser::{parser::{Parser, ParserError}, dialect::GenericDialect};
    /// # fn main() -> Result<(), ParserError> {
    /// let dialect = GenericDialect{};
    /// let statements = Parser::new(&dialect)
    ///   .try_with_sql("SELECT * FROM foo")?
    ///   .parse_statements()?;
    /// # Ok(())
    /// # }
    /// ```
    pub fn new(dialect: &'a dyn Dialect) -> Self {
        Self {
            tokens: vec![],
            index: 0,
            state: ParserState::Normal,
            dialect,
            recursion_counter: RecursionCounter::new(DEFAULT_REMAINING_DEPTH),
            options: ParserOptions::new().with_trailing_commas(dialect.supports_trailing_commas()),
            failed_prefix_positions: BTreeMap::new(),
            failed_reserved_word_prefix_positions: BTreeMap::new(),
            failed_derived_table_factor_positions: BTreeSet::new(),
            failed_position_syntax_positions: BTreeSet::new(),
            failed_in_subquery_positions: BTreeMap::new(),
        }
    }

    /// Specify the maximum recursion limit while parsing.
    ///
    /// [`Parser`] prevents stack overflows by returning
    /// [`ParserError::RecursionLimitExceeded`] if the parser exceeds
    /// this depth while processing the query.
    ///
    /// Example:
    /// ```
    /// # use sqlparser::{parser::{Parser, ParserError}, dialect::GenericDialect};
    /// # fn main() -> Result<(), ParserError> {
    /// let dialect = GenericDialect{};
    /// let result = Parser::new(&dialect)
    ///   .with_recursion_limit(1)
    ///   .try_with_sql("SELECT * FROM foo WHERE (a OR (b OR (c OR d)))")?
    ///   .parse_statements();
    ///   assert_eq!(result, Err(ParserError::RecursionLimitExceeded));
    /// # Ok(())
    /// # }
    /// ```
    ///
    /// Note: Versions prior to `0.63.0` did not enforce any limit in builds
    /// without the "std" feature.
    ///
    /// Note: when "recursive-protection" feature is enabled, this crate uses
    /// additional stack overflow protection for some of its recursive methods.
    /// See [`recursive::recursive`] for more information.
    pub fn with_recursion_limit(mut self, recursion_limit: usize) -> Self {
        self.recursion_counter = RecursionCounter::new(recursion_limit);
        self
    }

    /// Specify additional parser options
    ///
    /// [`Parser`] supports additional options ([`ParserOptions`])
    /// that allow you to mix & match behavior otherwise constrained
    /// to certain dialects (e.g. trailing commas).
    ///
    /// Example:
    /// ```
    /// # use sqlparser::{parser::{Parser, ParserError, ParserOptions}, dialect::GenericDialect};
    /// # fn main() -> Result<(), ParserError> {
    /// let dialect = GenericDialect{};
    /// let options = ParserOptions::new()
    ///    .with_trailing_commas(true)
    ///    .with_unescape(false);
    /// let result = Parser::new(&dialect)
    ///   .with_options(options)
    ///   .try_with_sql("SELECT a, b, COUNT(*), FROM foo GROUP BY a, b,")?
    ///   .parse_statements();
    ///   assert!(matches!(result, Ok(_)));
    /// # Ok(())
    /// # }
    /// ```
    pub fn with_options(mut self, options: ParserOptions) -> Self {
        self.options = options;
        self
    }

    /// Reset this parser to parse the specified token stream
    pub fn with_tokens_with_locations(mut self, tokens: Vec<TokenWithSpan>) -> Self {
        self.tokens = tokens;
        self.index = 0;
        self.failed_prefix_positions.clear();
        self.failed_reserved_word_prefix_positions.clear();
        self.failed_derived_table_factor_positions.clear();
        self.failed_position_syntax_positions.clear();
        self.failed_in_subquery_positions.clear();
        self
    }

    /// Reset this parser state to parse the specified tokens
    pub fn with_tokens(self, tokens: Vec<Token>) -> Self {
        // Put in dummy locations
        let tokens_with_locations: Vec<TokenWithSpan> = tokens
            .into_iter()
            .map(|token| TokenWithSpan {
                token,
                span: Span::empty(),
            })
            .collect();
        self.with_tokens_with_locations(tokens_with_locations)
    }

    /// Tokenize the sql string and sets this [`Parser`]'s state to
    /// parse the resulting tokens
    ///
    /// Returns an error if there was an error tokenizing the SQL string.
    ///
    /// See example on [`Parser::new()`] for an example
    pub fn try_with_sql(self, sql: &str) -> Result<Self, ParserError> {
        debug!("Parsing sql '{sql}'...");
        let tokens = Tokenizer::new(self.dialect, sql)
            .with_unescape(self.options.unescape)
            .tokenize_with_location()?;
        Ok(self.with_tokens_with_locations(tokens))
    }

    /// Parse potentially multiple statements
    ///
    /// Example
    /// ```
    /// # use sqlparser::{parser::{Parser, ParserError}, dialect::GenericDialect};
    /// # fn main() -> Result<(), ParserError> {
    /// let dialect = GenericDialect{};
    /// let statements = Parser::new(&dialect)
    ///   // Parse a SQL string with 2 separate statements
    ///   .try_with_sql("SELECT * FROM foo; SELECT * FROM bar;")?
    ///   .parse_statements()?;
    /// assert_eq!(statements.len(), 2);
    /// # Ok(())
    /// # }
    /// ```
    pub fn parse_statements(&mut self) -> Result<Vec<Statement>, ParserError> {
        let mut stmts = Vec::new();
        let mut expecting_statement_delimiter = false;
        loop {
            // ignore empty statements (between successive statement delimiters)
            while self.consume_token(&Token::SemiColon) {
                expecting_statement_delimiter = false;
            }

            if !self.options.require_semicolon_stmt_delimiter {
                expecting_statement_delimiter = false;
            }

            match &self.peek_token_ref().token {
                Token::EOF => break,
                // end of statement
                Token::Word(word)
                    if expecting_statement_delimiter && word.keyword == Keyword::END =>
                {
                    break;
                }
                _ => {}
            }

            if expecting_statement_delimiter {
                return self.expected_ref("end of statement", self.peek_token_ref());
            }

            let statement = self.parse_statement()?;
            stmts.push(statement);
            expecting_statement_delimiter = true;
        }
        Ok(stmts)
    }

    /// Convenience method to parse a string with one or more SQL
    /// statements into produce an Abstract Syntax Tree (AST).
    ///
    /// Example
    /// ```
    /// # use sqlparser::{parser::{Parser, ParserError}, dialect::GenericDialect};
    /// # fn main() -> Result<(), ParserError> {
    /// let dialect = GenericDialect{};
    /// let statements = Parser::parse_sql(
    ///   &dialect, "SELECT * FROM foo"
    /// )?;
    /// assert_eq!(statements.len(), 1);
    /// # Ok(())
    /// # }
    /// ```
    pub fn parse_sql(dialect: &dyn Dialect, sql: &str) -> Result<Vec<Statement>, ParserError> {
        Parser::new(dialect).try_with_sql(sql)?.parse_statements()
    }

    /// Parses the given `sql` into an Abstract Syntax Tree (AST), returning
    /// also encountered source code comments.
    ///
    /// See [Parser::parse_sql].
    pub fn parse_sql_with_comments(
        dialect: &'a dyn Dialect,
        sql: &str,
    ) -> Result<(Vec<Statement>, comments::Comments), ParserError> {
        let mut p = Parser::new(dialect).try_with_sql(sql)?;
        p.parse_statements().map(|stmts| (stmts, p.into_comments()))
    }

    /// Consumes this parser returning comments from the parsed token stream.
    pub fn into_comments(self) -> comments::Comments {
        let mut comments = comments::Comments::default();
        for t in self.tokens.into_iter() {
            match t.token {
                Token::Whitespace(Whitespace::SingleLineComment { comment, prefix }) => {
                    comments.offer(comments::CommentWithSpan {
                        comment: comments::Comment::SingleLine {
                            content: comment,
                            prefix,
                        },
                        span: t.span,
                    });
                }
                Token::Whitespace(Whitespace::MultiLineComment(comment)) => {
                    comments.offer(comments::CommentWithSpan {
                        comment: comments::Comment::MultiLine(comment),
                        span: t.span,
                    });
                }
                _ => {}
            }
        }
        comments
    }

    /// Parse a single top-level statement (such as SELECT, INSERT, CREATE, etc.),
    /// stopping before the statement separator, if any.
    pub fn parse_statement(&mut self) -> Result<Statement, ParserError> {
        let _guard = self.recursion_counter.try_decrease()?;

        // allow the dialect to override statement parsing
        if let Some(statement) = self.dialect.parse_statement(self) {
            return statement;
        }

        let next_token = self.next_token();
        match &next_token.token {
            Token::Word(w) => match w.keyword {
                Keyword::KILL => self.parse_kill(),
                Keyword::FLUSH => self.parse_flush(),
                Keyword::DESC => self.parse_explain(DescribeAlias::Desc),
                Keyword::DESCRIBE => self.parse_explain(DescribeAlias::Describe),
                Keyword::EXPLAIN => self.parse_explain(DescribeAlias::Explain),
                Keyword::ANALYZE => self.parse_analyze().map(Into::into),
                Keyword::CASE => {
                    self.prev_token();
                    self.parse_case_stmt().map(Into::into)
                }
                Keyword::IF => {
                    self.prev_token();
                    self.parse_if_stmt().map(Into::into)
                }
                Keyword::WHILE => {
                    self.prev_token();
                    self.parse_while().map(Into::into)
                }
                Keyword::RAISE => {
                    self.prev_token();
                    self.parse_raise_stmt().map(Into::into)
                }
                Keyword::SELECT | Keyword::WITH | Keyword::VALUES | Keyword::FROM => {
                    self.prev_token();
                    self.parse_query().map(Into::into)
                }
                Keyword::TRUNCATE => self.parse_truncate().map(Into::into),
                Keyword::ATTACH => {
                    if dialect_of!(self is DuckDbDialect) {
                        self.parse_attach_duckdb_database()
                    } else {
                        self.parse_attach_database()
                    }
                }
                Keyword::DETACH if self.dialect.supports_detach() => {
                    self.parse_detach_duckdb_database()
                }
                Keyword::MSCK => self.parse_msck().map(Into::into),
                Keyword::CREATE => self.parse_create(),
                Keyword::CACHE => self.parse_cache_table(),
                Keyword::DROP => self.parse_drop(),
                Keyword::DISCARD => self.parse_discard(),
                Keyword::DECLARE => self.parse_declare(),
                Keyword::FETCH => self.parse_fetch_statement(),
                Keyword::DELETE => self.parse_delete(next_token),
                Keyword::INSERT => self.parse_insert(next_token),
                Keyword::REPLACE => self.parse_replace(next_token),
                Keyword::UNCACHE => self.parse_uncache_table(),
                Keyword::UPDATE => self.parse_update(next_token),
                Keyword::ALTER => self.parse_alter(),
                Keyword::CALL => self.parse_call(),
                Keyword::COPY => self.parse_copy(),
                Keyword::OPEN => {
                    self.prev_token();
                    self.parse_open()
                }
                Keyword::CLOSE => self.parse_close(),
                Keyword::SET => self.parse_set(),
                Keyword::SHOW => self.parse_show(),
                Keyword::USE => self.parse_use(),
                Keyword::GRANT => self.parse_grant().map(Into::into),
                Keyword::DENY => {
                    self.prev_token();
                    self.parse_deny()
                }
                Keyword::REVOKE => self.parse_revoke().map(Into::into),
                Keyword::START => self.parse_start_transaction(),
                Keyword::BEGIN => self.parse_begin(),
                Keyword::END => self.parse_end(),
                Keyword::SAVEPOINT => self.parse_savepoint(),
                Keyword::RELEASE => self.parse_release(),
                Keyword::COMMIT => self.parse_commit(),
                Keyword::RAISERROR => Ok(self.parse_raiserror()?),
                Keyword::THROW => {
                    self.prev_token();
                    self.parse_throw().map(Into::into)
                }
                Keyword::ROLLBACK => self.parse_rollback(),
                Keyword::ABORT => self.parse_abort(),
                Keyword::ASSERT => self.parse_assert(),
                // `PREPARE`, `EXECUTE` and `DEALLOCATE` are Postgres-specific
                // syntaxes. They are used for Postgres prepared statement.
                Keyword::DEALLOCATE => self.parse_deallocate(),
                Keyword::EXECUTE | Keyword::EXEC => self.parse_execute(),
                Keyword::PREPARE => self.parse_prepare(),
                Keyword::MERGE => self.parse_merge(next_token).map(Into::into),
                // `LISTEN`, `UNLISTEN` and `NOTIFY` are Postgres-specific
                // syntaxes. They are used for Postgres statement.
                Keyword::LISTEN if self.dialect.supports_listen_notify() => self.parse_listen(),
                Keyword::UNLISTEN if self.dialect.supports_listen_notify() => self.parse_unlisten(),
                Keyword::NOTIFY if self.dialect.supports_listen_notify() => self.parse_notify(),
                // `PRAGMA` is sqlite specific https://www.sqlite.org/pragma.html
                Keyword::PRAGMA => self.parse_pragma(),
                Keyword::UNLOAD => {
                    self.prev_token();
                    self.parse_unload()
                }
                Keyword::RENAME => self.parse_rename(),
                // `INSTALL` is duckdb specific https://duckdb.org/docs/extensions/overview
                Keyword::INSTALL if self.dialect.supports_install() => self.parse_install(),
                Keyword::LOAD => self.parse_load(),
                Keyword::LOCK => {
                    self.prev_token();
                    self.parse_lock_statement().map(Into::into)
                }
                Keyword::OPTIMIZE if self.dialect.supports_optimize_table() => {
                    self.parse_optimize_table()
                }
                // `COMMENT` is snowflake specific https://docs.snowflake.com/en/sql-reference/sql/comment
                Keyword::COMMENT if self.dialect.supports_comment_on() => self.parse_comment(),
                Keyword::PRINT => self.parse_print(),
                // `WAITFOR` is MSSQL specific https://learn.microsoft.com/en-us/sql/t-sql/language-elements/waitfor-transact-sql
                Keyword::WAITFOR => self.parse_waitfor(),
                Keyword::RETURN => self.parse_return(),
                Keyword::EXPORT => {
                    self.prev_token();
                    self.parse_export_data()
                }
                Keyword::VACUUM => {
                    self.prev_token();
                    self.parse_vacuum()
                }
                Keyword::RESET => self.parse_reset().map(Into::into),
                _ => self.expected("an SQL statement", next_token),
            },
            Token::LParen => {
                self.prev_token();
                self.parse_query().map(Into::into)
            }
            _ => self.expected("an SQL statement", next_token),
        }
    }

    /// Parse a `CASE` statement.
    ///
    /// See [Statement::Case]
    pub fn parse_case_stmt(&mut self) -> Result<CaseStatement, ParserError> {
        let case_token = self.expect_keyword(Keyword::CASE)?;

        let match_expr = if self.peek_keyword(Keyword::WHEN) {
            None
        } else {
            Some(self.parse_expr()?)
        };

        self.expect_keyword_is(Keyword::WHEN)?;
        let when_blocks = self.parse_keyword_separated(Keyword::WHEN, |parser| {
            parser.parse_conditional_statement_block(&[Keyword::WHEN, Keyword::ELSE, Keyword::END])
        })?;

        let else_block = if self.parse_keyword(Keyword::ELSE) {
            Some(self.parse_conditional_statement_block(&[Keyword::END])?)
        } else {
            None
        };

        let mut end_case_token = self.expect_keyword(Keyword::END)?;
        if self.peek_keyword(Keyword::CASE) {
            end_case_token = self.expect_keyword(Keyword::CASE)?;
        }

        Ok(CaseStatement {
            case_token: AttachedToken(case_token),
            match_expr,
            when_blocks,
            else_block,
            end_case_token: AttachedToken(end_case_token),
        })
    }

    /// Parse an `IF` statement.
    ///
    /// See [Statement::If]
    pub fn parse_if_stmt(&mut self) -> Result<IfStatement, ParserError> {
        self.expect_keyword_is(Keyword::IF)?;
        let if_block = self.parse_conditional_statement_block(&[
            Keyword::ELSE,
            Keyword::ELSEIF,
            Keyword::END,
        ])?;

        let elseif_blocks = if self.parse_keyword(Keyword::ELSEIF) {
            self.parse_keyword_separated(Keyword::ELSEIF, |parser| {
                parser.parse_conditional_statement_block(&[
                    Keyword::ELSEIF,
                    Keyword::ELSE,
                    Keyword::END,
                ])
            })?
        } else {
            vec![]
        };

        let else_block = if self.parse_keyword(Keyword::ELSE) {
            Some(self.parse_conditional_statement_block(&[Keyword::END])?)
        } else {
            None
        };

        self.expect_keyword_is(Keyword::END)?;
        let end_token = self.expect_keyword(Keyword::IF)?;

        Ok(IfStatement {
            if_block,
            elseif_blocks,
            else_block,
            end_token: Some(AttachedToken(end_token)),
        })
    }

    /// Parse a `WHILE` statement.
    ///
    /// See [Statement::While]
    fn parse_while(&mut self) -> Result<WhileStatement, ParserError> {
        self.expect_keyword_is(Keyword::WHILE)?;
        let while_block = self.parse_conditional_statement_block(&[Keyword::END])?;

        Ok(WhileStatement { while_block })
    }

    /// Parses an expression and associated list of statements
    /// belonging to a conditional statement like `IF` or `WHEN` or `WHILE`.
    ///
    /// Example:
    /// ```sql
    /// IF condition THEN statement1; statement2;
    /// ```
    fn parse_conditional_statement_block(
        &mut self,
        terminal_keywords: &[Keyword],
    ) -> Result<ConditionalStatementBlock, ParserError> {
        let start_token = self.get_current_token().clone(); // self.expect_keyword(keyword)?;
        let mut then_token = None;

        let condition = match &start_token.token {
            Token::Word(w) if w.keyword == Keyword::ELSE => None,
            Token::Word(w) if w.keyword == Keyword::WHILE => {
                let expr = self.parse_expr()?;
                Some(expr)
            }
            _ => {
                let expr = self.parse_expr()?;
                then_token = Some(AttachedToken(self.expect_keyword(Keyword::THEN)?));
                Some(expr)
            }
        };

        let conditional_statements = self.parse_conditional_statements(terminal_keywords)?;

        Ok(ConditionalStatementBlock {
            start_token: AttachedToken(start_token),
            condition,
            then_token,
            conditional_statements,
        })
    }

    /// Parse a BEGIN/END block or a sequence of statements
    /// This could be inside of a conditional (IF, CASE, WHILE etc.) or an object body defined optionally BEGIN/END and one or more statements.
    pub(crate) fn parse_conditional_statements(
        &mut self,
        terminal_keywords: &[Keyword],
    ) -> Result<ConditionalStatements, ParserError> {
        let conditional_statements = if self.peek_keyword(Keyword::BEGIN) {
            let begin_token = self.expect_keyword(Keyword::BEGIN)?;
            let statements = self.parse_statement_list(terminal_keywords)?;
            let end_token = self.expect_keyword(Keyword::END)?;

            ConditionalStatements::BeginEnd(BeginEndStatements {
                begin_token: AttachedToken(begin_token),
                statements,
                end_token: AttachedToken(end_token),
            })
        } else {
            ConditionalStatements::Sequence {
                statements: self.parse_statement_list(terminal_keywords)?,
            }
        };
        Ok(conditional_statements)
    }

    /// Parse a `RAISE` statement.
    ///
    /// See [Statement::Raise]
    pub fn parse_raise_stmt(&mut self) -> Result<RaiseStatement, ParserError> {
        self.expect_keyword_is(Keyword::RAISE)?;

        let value = if self.parse_keywords(&[Keyword::USING, Keyword::MESSAGE]) {
            self.expect_token(&Token::Eq)?;
            Some(RaiseStatementValue::UsingMessage(self.parse_expr()?))
        } else {
            self.maybe_parse(|parser| parser.parse_expr().map(RaiseStatementValue::Expr))?
        };

        Ok(RaiseStatement { value })
    }
    /// Parse a COMMENT statement.
    ///
    /// See [Statement::Comment]
    pub fn parse_comment(&mut self) -> Result<Statement, ParserError> {
        let if_exists = self.parse_keywords(&[Keyword::IF, Keyword::EXISTS]);

        self.expect_keyword_is(Keyword::ON)?;
        let token = self.next_token();

        let (object_type, object_name) = match token.token {
            Token::Word(w) if w.keyword == Keyword::COLLATION => {
                (CommentObject::Collation, self.parse_object_name(false)?)
            }
            Token::Word(w) if w.keyword == Keyword::COLUMN => {
                (CommentObject::Column, self.parse_object_name(false)?)
            }
            Token::Word(w) if w.keyword == Keyword::DATABASE => {
                (CommentObject::Database, self.parse_object_name(false)?)
            }
            Token::Word(w) if w.keyword == Keyword::DOMAIN => {
                (CommentObject::Domain, self.parse_object_name(false)?)
            }
            Token::Word(w) if w.keyword == Keyword::EXTENSION => {
                (CommentObject::Extension, self.parse_object_name(false)?)
            }
            Token::Word(w) if w.keyword == Keyword::FUNCTION => {
                (CommentObject::Function, self.parse_object_name(false)?)
            }
            Token::Word(w) if w.keyword == Keyword::INDEX => {
                (CommentObject::Index, self.parse_object_name(false)?)
            }
            Token::Word(w) if w.keyword == Keyword::MATERIALIZED => {
                self.expect_keyword_is(Keyword::VIEW)?;
                (
                    CommentObject::MaterializedView,
                    self.parse_object_name(false)?,
                )
            }
            Token::Word(w) if w.keyword == Keyword::PROCEDURE => {
                (CommentObject::Procedure, self.parse_object_name(false)?)
            }
            Token::Word(w) if w.keyword == Keyword::ROLE => {
                (CommentObject::Role, self.parse_object_name(false)?)
            }
            Token::Word(w) if w.keyword == Keyword::SCHEMA => {
                (CommentObject::Schema, self.parse_object_name(false)?)
            }
            Token::Word(w) if w.keyword == Keyword::SEQUENCE => {
                (CommentObject::Sequence, self.parse_object_name(false)?)
            }
            Token::Word(w) if w.keyword == Keyword::TABLE => {
                (CommentObject::Table, self.parse_object_name(false)?)
            }
            Token::Word(w) if w.keyword == Keyword::TYPE => {
                (CommentObject::Type, self.parse_object_name(false)?)
            }
            Token::Word(w) if w.keyword == Keyword::USER => {
                (CommentObject::User, self.parse_object_name(false)?)
            }
            Token::Word(w) if w.keyword == Keyword::VIEW => {
                (CommentObject::View, self.parse_object_name(false)?)
            }
            _ => self.expected("comment object_type", token)?,
        };

        self.expect_keyword_is(Keyword::IS)?;
        let comment = if self.parse_keyword(Keyword::NULL) {
            None
        } else {
            Some(self.parse_literal_string()?)
        };
        Ok(Statement::Comment {
            object_type,
            object_name,
            comment,
            if_exists,
        })
    }

    /// Parse `FLUSH` statement.
    pub fn parse_flush(&mut self) -> Result<Statement, ParserError> {
        let mut channel = None;
        let mut tables: Vec<ObjectName> = vec![];
        let mut read_lock = false;
        let mut export = false;

        if !dialect_of!(self is MySqlDialect | GenericDialect) {
            return parser_err!(
                "Unsupported statement FLUSH",
                self.peek_token_ref().span.start
            );
        }

        let location = if self.parse_keyword(Keyword::NO_WRITE_TO_BINLOG) {
            Some(FlushLocation::NoWriteToBinlog)
        } else if self.parse_keyword(Keyword::LOCAL) {
            Some(FlushLocation::Local)
        } else {
            None
        };

        let object_type = if self.parse_keywords(&[Keyword::BINARY, Keyword::LOGS]) {
            FlushType::BinaryLogs
        } else if self.parse_keywords(&[Keyword::ENGINE, Keyword::LOGS]) {
            FlushType::EngineLogs
        } else if self.parse_keywords(&[Keyword::ERROR, Keyword::LOGS]) {
            FlushType::ErrorLogs
        } else if self.parse_keywords(&[Keyword::GENERAL, Keyword::LOGS]) {
            FlushType::GeneralLogs
        } else if self.parse_keywords(&[Keyword::HOSTS]) {
            FlushType::Hosts
        } else if self.parse_keyword(Keyword::PRIVILEGES) {
            FlushType::Privileges
        } else if self.parse_keyword(Keyword::OPTIMIZER_COSTS) {
            FlushType::OptimizerCosts
        } else if self.parse_keywords(&[Keyword::RELAY, Keyword::LOGS]) {
            if self.parse_keywords(&[Keyword::FOR, Keyword::CHANNEL]) {
                channel = Some(self.parse_object_name(false)?.to_string());
            }
            FlushType::RelayLogs
        } else if self.parse_keywords(&[Keyword::SLOW, Keyword::LOGS]) {
            FlushType::SlowLogs
        } else if self.parse_keyword(Keyword::STATUS) {
            FlushType::Status
        } else if self.parse_keyword(Keyword::USER_RESOURCES) {
            FlushType::UserResources
        } else if self.parse_keywords(&[Keyword::LOGS]) {
            FlushType::Logs
        } else if self.parse_keywords(&[Keyword::TABLES]) {
            loop {
                let next_token = self.next_token();
                match &next_token.token {
                    Token::Word(w) => match w.keyword {
                        Keyword::WITH => {
                            read_lock = self.parse_keywords(&[Keyword::READ, Keyword::LOCK]);
                        }
                        Keyword::FOR => {
                            export = self.parse_keyword(Keyword::EXPORT);
                        }
                        Keyword::NoKeyword => {
                            self.prev_token();
                            tables = self.parse_comma_separated(|p| p.parse_object_name(false))?;
                        }
                        _ => {}
                    },
                    _ => {
                        break;
                    }
                }
            }

            FlushType::Tables
        } else {
            return self.expected_ref(
                "BINARY LOGS, ENGINE LOGS, ERROR LOGS, GENERAL LOGS, HOSTS, LOGS, PRIVILEGES, OPTIMIZER_COSTS,\
                 RELAY LOGS [FOR CHANNEL channel], SLOW LOGS, STATUS, USER_RESOURCES",
                self.peek_token_ref(),
            );
        };

        Ok(Statement::Flush {
            object_type,
            location,
            channel,
            read_lock,
            export,
            tables,
        })
    }

    /// Parse `MSCK` statement.
    pub fn parse_msck(&mut self) -> Result<Msck, ParserError> {
        let repair = self.parse_keyword(Keyword::REPAIR);
        self.expect_keyword_is(Keyword::TABLE)?;
        let table_name = self.parse_object_name(false)?;
        let partition_action = self
            .maybe_parse(|parser| {
                let pa = match parser.parse_one_of_keywords(&[
                    Keyword::ADD,
                    Keyword::DROP,
                    Keyword::SYNC,
                ]) {
                    Some(Keyword::ADD) => Some(AddDropSync::ADD),
                    Some(Keyword::DROP) => Some(AddDropSync::DROP),
                    Some(Keyword::SYNC) => Some(AddDropSync::SYNC),
                    _ => None,
                };
                parser.expect_keyword_is(Keyword::PARTITIONS)?;
                Ok(pa)
            })?
            .unwrap_or_default();
        Ok(Msck {
            repair,
            table_name,
            partition_action,
        })
    }

    /// Parse `TRUNCATE` statement.
    pub fn parse_truncate(&mut self) -> Result<Truncate, ParserError> {
        let table = self.parse_keyword(Keyword::TABLE);
        let if_exists = self.parse_keywords(&[Keyword::IF, Keyword::EXISTS]);

        let table_names = self.parse_comma_separated(|p| {
            let only = p.parse_keyword(Keyword::ONLY);
            let name = p.parse_object_name(false)?;
            let has_asterisk = p.consume_token(&Token::Mul);
            Ok(TruncateTableTarget {
                name,
                only,
                has_asterisk,
            })
        })?;

        let mut partitions = None;
        if self.parse_keyword(Keyword::PARTITION) {
            self.expect_token(&Token::LParen)?;
            partitions = Some(self.parse_comma_separated(Parser::parse_expr)?);
            self.expect_token(&Token::RParen)?;
        }

        let mut identity = None;
        let mut cascade = None;

        if dialect_of!(self is PostgreSqlDialect | GenericDialect) {
            identity = if self.parse_keywords(&[Keyword::RESTART, Keyword::IDENTITY]) {
                Some(TruncateIdentityOption::Restart)
            } else if self.parse_keywords(&[Keyword::CONTINUE, Keyword::IDENTITY]) {
                Some(TruncateIdentityOption::Continue)
            } else {
                None
            };

            cascade = self.parse_cascade_option();
        };

        let on_cluster = self.parse_optional_on_cluster()?;

        Ok(Truncate {
            table_names,
            partitions,
            table,
            if_exists,
            identity,
            cascade,
            on_cluster,
        })
    }

    fn parse_cascade_option(&mut self) -> Option<CascadeOption> {
        if self.parse_keyword(Keyword::CASCADE) {
            Some(CascadeOption::Cascade)
        } else if self.parse_keyword(Keyword::RESTRICT) {
            Some(CascadeOption::Restrict)
        } else {
            None
        }
    }

    /// Parse options for `ATTACH DUCKDB DATABASE` statement.
    pub fn parse_attach_duckdb_database_options(
        &mut self,
    ) -> Result<Vec<AttachDuckDBDatabaseOption>, ParserError> {
        if !self.consume_token(&Token::LParen) {
            return Ok(vec![]);
        }

        let mut options = vec![];
        loop {
            if self.parse_keyword(Keyword::READ_ONLY) {
                let boolean = if self.parse_keyword(Keyword::TRUE) {
                    Some(true)
                } else if self.parse_keyword(Keyword::FALSE) {
                    Some(false)
                } else {
                    None
                };
                options.push(AttachDuckDBDatabaseOption::ReadOnly(boolean));
            } else if self.parse_keyword(Keyword::TYPE) {
                let ident = self.parse_identifier()?;
                options.push(AttachDuckDBDatabaseOption::Type(ident));
            } else {
                return self
                    .expected_ref("expected one of: ), READ_ONLY, TYPE", self.peek_token_ref());
            };

            if self.consume_token(&Token::RParen) {
                return Ok(options);
            } else if self.consume_token(&Token::Comma) {
                continue;
            } else {
                return self.expected_ref("expected one of: ')', ','", self.peek_token_ref());
            }
        }
    }

    /// Parse `ATTACH DUCKDB DATABASE` statement.
    pub fn parse_attach_duckdb_database(&mut self) -> Result<Statement, ParserError> {
        let database = self.parse_keyword(Keyword::DATABASE);
        let if_not_exists = self.parse_keywords(&[Keyword::IF, Keyword::NOT, Keyword::EXISTS]);
        let database_path = self.parse_identifier()?;
        let database_alias = if self.parse_keyword(Keyword::AS) {
            Some(self.parse_identifier()?)
        } else {
            None
        };

        let attach_options = self.parse_attach_duckdb_database_options()?;
        Ok(Statement::AttachDuckDBDatabase {
            if_not_exists,
            database,
            database_path,
            database_alias,
            attach_options,
        })
    }

    /// Parse `DETACH DUCKDB DATABASE` statement.
    pub fn parse_detach_duckdb_database(&mut self) -> Result<Statement, ParserError> {
        let database = self.parse_keyword(Keyword::DATABASE);
        let if_exists = self.parse_keywords(&[Keyword::IF, Keyword::EXISTS]);
        let database_alias = self.parse_identifier()?;
        Ok(Statement::DetachDuckDBDatabase {
            if_exists,
            database,
            database_alias,
        })
    }

    /// Parse `ATTACH DATABASE` statement.
    pub fn parse_attach_database(&mut self) -> Result<Statement, ParserError> {
        let database = self.parse_keyword(Keyword::DATABASE);
        let database_file_name = self.parse_expr()?;
        self.expect_keyword_is(Keyword::AS)?;
        let schema_name = self.parse_identifier()?;
        Ok(Statement::AttachDatabase {
            database,
            schema_name,
            database_file_name,
        })
    }

    /// Parse `ANALYZE` statement.
    pub fn parse_analyze(&mut self) -> Result<Analyze, ParserError> {
        let has_table_keyword = self.parse_keyword(Keyword::TABLE);
        let table_name = self.maybe_parse(|parser| parser.parse_object_name(false))?;
        let mut for_columns = false;
        let mut cache_metadata = false;
        let mut noscan = false;
        let mut partitions = None;
        let mut compute_statistics = false;
        let mut columns = vec![];

        // PostgreSQL syntax: ANALYZE t (col1, col2)
        if table_name.is_some() && self.consume_token(&Token::LParen) {
            columns = self.parse_comma_separated(|p| p.parse_identifier())?;
            self.expect_token(&Token::RParen)?;
        }

        loop {
            match self.parse_one_of_keywords(&[
                Keyword::PARTITION,
                Keyword::FOR,
                Keyword::CACHE,
                Keyword::NOSCAN,
                Keyword::COMPUTE,
            ]) {
                Some(Keyword::PARTITION) => {
                    self.expect_token(&Token::LParen)?;
                    partitions = Some(self.parse_comma_separated(Parser::parse_expr)?);
                    self.expect_token(&Token::RParen)?;
                }
                Some(Keyword::NOSCAN) => noscan = true,
                Some(Keyword::FOR) => {
                    self.expect_keyword_is(Keyword::COLUMNS)?;

                    columns = self
                        .maybe_parse(|parser| {
                            parser.parse_comma_separated(|p| p.parse_identifier())
                        })?
                        .unwrap_or_default();
                    for_columns = true
                }
                Some(Keyword::CACHE) => {
                    self.expect_keyword_is(Keyword::METADATA)?;
                    cache_metadata = true
                }
                Some(Keyword::COMPUTE) => {
                    self.expect_keyword_is(Keyword::STATISTICS)?;
                    compute_statistics = true
                }
                _ => break,
            }
        }

        Ok(Analyze {
            has_table_keyword,
            table_name,
            for_columns,
            columns,
            partitions,
            cache_metadata,
            noscan,
            compute_statistics,
        })
    }

    /// Parse a new expression including wildcard & qualified wildcard.
    pub fn parse_wildcard_expr(&mut self) -> Result<Expr, ParserError> {
        let index = self.index;

        let next_token = self.next_token();
        match next_token.token {
            t @ (Token::Word(_) | Token::SingleQuotedString(_))
                if self.peek_token_ref().token == Token::Period =>
            {
                let mut id_parts: Vec<Ident> = vec![match t {
                    Token::Word(w) => w.into_ident(next_token.span),
                    Token::SingleQuotedString(s) => Ident::with_quote('\'', s),
                    _ => {
                        return Err(ParserError::ParserError(
                            "Internal parser error: unexpected token type".to_string(),
                        ))
                    }
                }];

                while self.consume_token(&Token::Period) {
                    let next_token = self.next_token();
                    match next_token.token {
                        Token::Word(w) => id_parts.push(w.into_ident(next_token.span)),
                        Token::SingleQuotedString(s) => {
                            // SQLite has single-quoted identifiers
                            id_parts.push(Ident::with_quote('\'', s))
                        }
                        Token::Placeholder(s) => {
                            // Snowflake uses $1, $2, etc. for positional column references
                            // in staged data queries like: SELECT t.$1 FROM @stage t
                            id_parts.push(Ident::new(s))
                        }
                        Token::Mul => {
                            return Ok(Expr::QualifiedWildcard(
                                ObjectName::from(id_parts),
                                AttachedToken(next_token),
                            ));
                        }
                        // A field index such as `t.1` is parsed as an expression.
                        Token::Number(..) if self.dialect.supports_tuple_element_access() => break,
                        _ => {
                            return self.expected("an identifier or a '*' after '.'", next_token);
                        }
                    }
                }
            }
            Token::Mul => {
                return Ok(Expr::Wildcard(AttachedToken(next_token)));
            }
            // Handle parenthesized wildcard: (*)
            Token::LParen => {
                let [maybe_mul, maybe_rparen] = self.peek_tokens_ref();
                if maybe_mul.token == Token::Mul && maybe_rparen.token == Token::RParen {
                    let mul_token = self.next_token(); // consume Mul
                    self.next_token(); // consume RParen
                    return Ok(Expr::Wildcard(AttachedToken(mul_token)));
                }
            }
            _ => (),
        };

        self.index = index;
        self.parse_expr()
    }

    /// Parse a new expression.
    pub fn parse_expr(&mut self) -> Result<Expr, ParserError> {
        self.parse_subexpr(self.dialect.prec_unknown())
    }

    /// Parse expression with optional alias and order by.
    pub fn parse_expr_with_alias_and_order_by(
        &mut self,
    ) -> Result<ExprWithAliasAndOrderBy, ParserError> {
        let expr = self.parse_expr()?;

        fn validator(explicit: bool, kw: &Keyword, _parser: &mut Parser) -> bool {
            explicit || !&[Keyword::ASC, Keyword::DESC, Keyword::GROUP].contains(kw)
        }
        let alias = self.parse_optional_alias_inner(None, validator)?;
        let order_by = OrderByOptions {
            sort: self.parse_optional_order_by_sort(),
            nulls_first: None,
        };
        Ok(ExprWithAliasAndOrderBy {
            expr: ExprWithAlias { expr, alias },
            order_by,
        })
    }

    /// Parse tokens until the precedence changes.
    #[cfg_attr(feature = "recursive-protection", recursive::recursive)]
    pub fn parse_subexpr(&mut self, precedence: u8) -> Result<Expr, ParserError> {
        let _guard = self.recursion_counter.try_decrease()?;
        debug!("parsing expr");
        let mut expr = self.parse_prefix()?;

        expr = self.parse_compound_expr(expr, vec![])?;

        // Parse an optional collation cast operator following `expr`.
        //
        // For example (MSSQL): t1.a COLLATE Latin1_General_CI_AS
        if !self.in_column_definition_state() && self.parse_keyword(Keyword::COLLATE) {
            expr = Expr::Collate {
                expr: Box::new(expr),
                collation: self.parse_object_name(false)?,
            };
        }

        debug!("prefix: {expr:?}");
        loop {
            let next_precedence = self.get_next_precedence()?;
            debug!("next precedence: {next_precedence:?}");

            if precedence >= next_precedence {
                break;
            }

            // The period operator is handled exclusively by the
            // compound field access parsing.
            if Token::Period == self.peek_token_ref().token {
                break;
            }

            expr = self.parse_infix(expr, next_precedence)?;
        }
        Ok(expr)
    }

    /// Parse `ASSERT` statement.
    pub fn parse_assert(&mut self) -> Result<Statement, ParserError> {
        let condition = self.parse_expr()?;
        let message = if self.parse_keyword(Keyword::AS) {
            Some(self.parse_expr()?)
        } else {
            None
        };

        Ok(Statement::Assert { condition, message })
    }

    /// Parse `SAVEPOINT` statement.
    pub fn parse_savepoint(&mut self) -> Result<Statement, ParserError> {
        let name = self.parse_identifier()?;
        Ok(Statement::Savepoint { name })
    }

    /// Parse `RELEASE` statement.
    pub fn parse_release(&mut self) -> Result<Statement, ParserError> {
        let _ = self.parse_keyword(Keyword::SAVEPOINT);
        let name = self.parse_identifier()?;

        Ok(Statement::ReleaseSavepoint { name })
    }

    /// Parse `LISTEN` statement.
    pub fn parse_listen(&mut self) -> Result<Statement, ParserError> {
        let channel = self.parse_identifier()?;
        Ok(Statement::LISTEN { channel })
    }

    /// Parse `UNLISTEN` statement.
    pub fn parse_unlisten(&mut self) -> Result<Statement, ParserError> {
        let channel = if self.consume_token(&Token::Mul) {
            Ident::new(Expr::Wildcard(AttachedToken::empty()).to_string())
        } else {
            match self.parse_identifier() {
                Ok(expr) => expr,
                _ => {
                    self.prev_token();
                    return self.expected_ref("wildcard or identifier", self.peek_token_ref());
                }
            }
        };
        Ok(Statement::UNLISTEN { channel })
    }

    /// Parse `NOTIFY` statement.
    pub fn parse_notify(&mut self) -> Result<Statement, ParserError> {
        let channel = self.parse_identifier()?;
        let payload = if self.consume_token(&Token::Comma) {
            Some(self.parse_literal_string()?)
        } else {
            None
        };
        Ok(Statement::NOTIFY { channel, payload })
    }

    /// Parses a `RENAME TABLE` statement. See [Statement::RenameTable]
    pub fn parse_rename(&mut self) -> Result<Statement, ParserError> {
        if self.peek_keyword(Keyword::TABLE) {
            self.expect_keyword(Keyword::TABLE)?;
            let rename_tables = self.parse_comma_separated(|parser| {
                let old_name = parser.parse_object_name(false)?;
                parser.expect_keyword(Keyword::TO)?;
                let new_name = parser.parse_object_name(false)?;

                Ok(RenameTable { old_name, new_name })
            })?;
            Ok(rename_tables.into())
        } else {
            self.expected_ref("KEYWORD `TABLE` after RENAME", self.peek_token_ref())
        }
    }

    /// Tries to parse an expression by matching the specified word to known keywords that have a special meaning in the dialect.
    /// Returns `None if no match is found.
    fn parse_expr_prefix_by_reserved_word(
        &mut self,
        w: &Word,
        w_span: Span,
    ) -> Result<Option<Expr>, ParserError> {
        match w.keyword {
            Keyword::TRUE | Keyword::FALSE if self.dialect.supports_boolean_literals() => {
                self.prev_token();
                Ok(Some(Expr::Value(self.parse_value()?)))
            }
            Keyword::NULL => {
                self.prev_token();
                Ok(Some(Expr::Value(self.parse_value()?)))
            }
            Keyword::CURRENT_CATALOG
            | Keyword::CURRENT_USER
            | Keyword::SESSION_USER
            | Keyword::USER
            if dialect_of!(self is PostgreSqlDialect | GenericDialect) =>
                {
                    Ok(Some(Expr::Function(Function {
                        name: ObjectName::from(vec![w.to_ident(w_span)]),
                        uses_odbc_syntax: false,
                        parameters: FunctionArguments::None,
                        args: FunctionArguments::None,
                        null_treatment: None,
                        filter: None,
                        over: None,
                        within_group: vec![],
                    })))
                }
            Keyword::CURRENT_TIMESTAMP
            | Keyword::CURRENT_TIME
            | Keyword::CURRENT_DATE
            | Keyword::LOCALTIME
            | Keyword::LOCALTIMESTAMP => {
                Ok(Some(self.parse_time_functions(ObjectName::from(vec![w.to_ident(w_span)]))?))
            }
            Keyword::CASE => Ok(Some(self.parse_case_expr()?)),
            Keyword::CONVERT => Ok(Some(self.parse_convert_expr(false)?)),
            Keyword::TRY_CONVERT if self.dialect.supports_try_convert() => Ok(Some(self.parse_convert_expr(true)?)),
            Keyword::CAST => Ok(Some(self.parse_cast_expr(CastKind::Cast)?)),
            Keyword::TRY_CAST => Ok(Some(self.parse_cast_expr(CastKind::TryCast)?)),
            Keyword::SAFE_CAST => Ok(Some(self.parse_cast_expr(CastKind::SafeCast)?)),
            Keyword::EXISTS
            // Support parsing Databricks has a function named `exists`.
            if !dialect_of!(self is DatabricksDialect)
                || matches!(
                        self.peek_nth_token_ref(1).token,
                        Token::Word(Word {
                            keyword: Keyword::SELECT | Keyword::WITH,
                            ..
                        })
                    ) =>
                {
                    Ok(Some(self.parse_exists_expr(false)?))
                }
            Keyword::EXTRACT => Ok(Some(self.parse_extract_expr()?)),
            Keyword::CEIL => Ok(Some(self.parse_ceil_floor_expr(true)?)),
            Keyword::FLOOR => Ok(Some(self.parse_ceil_floor_expr(false)?)),
            Keyword::POSITION if self.peek_token_ref().token == Token::LParen => {
                Ok(Some(self.parse_position_expr(w.to_ident(w_span))?))
            }
            Keyword::SUBSTR | Keyword::SUBSTRING => {
                self.prev_token();
                Ok(Some(self.parse_substring()?))
            }
            Keyword::OVERLAY => Ok(Some(self.parse_overlay_expr()?)),
            Keyword::TRIM => Ok(Some(self.parse_trim_expr()?)),
            Keyword::INTERVAL => Ok(Some(self.parse_interval()?)),
            // Treat ARRAY[1,2,3] as an array [1,2,3], otherwise try as subquery or a function call
            Keyword::ARRAY if *self.peek_token_ref() == Token::LBracket => {
                self.expect_token(&Token::LBracket)?;
                Ok(Some(self.parse_array_expr(true)?))
            }
            Keyword::ARRAY
            if self.peek_token_ref().token == Token::LParen
                && !dialect_of!(self is ClickHouseDialect | DatabricksDialect) =>
                {
                    self.expect_token(&Token::LParen)?;
                    let query = self.parse_query()?;
                    self.expect_token(&Token::RParen)?;
                    Ok(Some(Expr::Function(Function {
                        name: ObjectName::from(vec![w.to_ident(w_span)]),
                        uses_odbc_syntax: false,
                        parameters: FunctionArguments::None,
                        args: FunctionArguments::Subquery(query),
                        filter: None,
                        null_treatment: None,
                        over: None,
                        within_group: vec![],
                    })))
                }
            Keyword::NOT => Ok(Some(self.parse_not()?)),
            Keyword::MATCH if self.dialect.supports_match_against() => {
                Ok(Some(self.parse_match_against()?))
            }
            Keyword::STRUCT if self.dialect.supports_struct_literal() => {
                let struct_expr = self.parse_struct_literal()?;
                Ok(Some(struct_expr))
            }
            Keyword::PRIOR if matches!(self.state, ParserState::ConnectBy) => {
                let expr = self.parse_subexpr(self.dialect.prec_value(Precedence::PlusMinus))?;
                Ok(Some(Expr::Prior(Box::new(expr))))
            }
            Keyword::MAP if *self.peek_token_ref() == Token::LBrace && self.dialect.support_map_literal_syntax() => {
                Ok(Some(self.parse_duckdb_map_literal()?))
            }
            Keyword::APPROXIMATE
                if self.dialect.supports_approximate_percentile_disc()
                    && self.peek_keyword(Keyword::PERCENTILE_DISC) =>
            {
                self.maybe_parse(|parser| {
                    let function_name = parser.parse_object_name(false)?;
                    parser.parse_function(function_name).map(|function| Expr::Prefixed {
                        prefix: w.to_ident(w_span),
                        value: Box::new(function),
                    })
                })
            }
            Keyword::LAMBDA if self.dialect.supports_lambda_keyword_syntax() => {
                Ok(Some(self.parse_lambda_expr()?))
            }
            _ if self.dialect.supports_geometric_types() => match w.keyword {
                Keyword::CIRCLE => Ok(Some(self.parse_geometric_type(GeometricTypeKind::Circle)?)),
                Keyword::BOX => Ok(Some(self.parse_geometric_type(GeometricTypeKind::GeometricBox)?)),
                Keyword::PATH => Ok(Some(self.parse_geometric_type(GeometricTypeKind::GeometricPath)?)),
                Keyword::LINE => Ok(Some(self.parse_geometric_type(GeometricTypeKind::Line)?)),
                Keyword::LSEG => Ok(Some(self.parse_geometric_type(GeometricTypeKind::LineSegment)?)),
                Keyword::POINT => Ok(Some(self.parse_geometric_type(GeometricTypeKind::Point)?)),
                Keyword::POLYGON => Ok(Some(self.parse_geometric_type(GeometricTypeKind::Polygon)?)),
                _ => Ok(None),
            },
            _ => Ok(None),
        }
    }

    /// Tries to parse an expression by a word that is not known to have a special meaning in the dialect.
    fn parse_expr_prefix_by_unreserved_word(
        &mut self,
        w: &Word,
        w_span: Span,
    ) -> Result<Expr, ParserError> {
        let is_outer_join = self.peek_outer_join_operator();
        match &self.peek_token_ref().token {
            Token::LParen if !is_outer_join => {
                let id_parts = vec![w.to_ident(w_span)];
                self.parse_function(ObjectName::from(id_parts))
            }
            // string introducer https://dev.mysql.com/doc/refman/8.0/en/charset-introducer.html
            Token::SingleQuotedString(_)
            | Token::DoubleQuotedString(_)
            | Token::HexStringLiteral(_)
                if w.value.starts_with('_') =>
            {
                Ok(Expr::Prefixed {
                    prefix: w.to_ident(w_span),
                    value: self.parse_introduced_string_expr()?.into(),
                })
            }
            // string introducer https://dev.mysql.com/doc/refman/8.0/en/charset-introducer.html
            Token::SingleQuotedString(_)
            | Token::DoubleQuotedString(_)
            | Token::HexStringLiteral(_)
                if w.value.starts_with('_') =>
            {
                Ok(Expr::Prefixed {
                    prefix: w.to_ident(w_span),
                    value: self.parse_introduced_string_expr()?.into(),
                })
            }
            // An unreserved word (likely an identifier) is followed by an arrow,
            // which indicates a lambda function with a single, untyped parameter.
            // For example: `a -> a * 2`.
            Token::Arrow if self.dialect.supports_lambda_functions() => {
                self.expect_token(&Token::Arrow)?;
                Ok(Expr::Lambda(LambdaFunction {
                    params: OneOrManyWithParens::One(LambdaFunctionParameter {
                        name: w.to_ident(w_span),
                        data_type: None,
                    }),
                    body: Box::new(self.parse_expr()?),
                    syntax: LambdaSyntax::Arrow,
                }))
            }
            // An unreserved word (likely an identifier) that is followed by another word (likley a data type)
            // which is then followed by an arrow, which indicates a lambda function with a single, typed parameter.
            // For example: `a INT -> a * 2`.
            Token::Word(_)
                if self.dialect.supports_lambda_functions()
                    && self.peek_nth_token_ref(1).token == Token::Arrow =>
            {
                let data_type = self.parse_data_type()?;
                self.expect_token(&Token::Arrow)?;
                Ok(Expr::Lambda(LambdaFunction {
                    params: OneOrManyWithParens::One(LambdaFunctionParameter {
                        name: w.to_ident(w_span),
                        data_type: Some(data_type),
                    }),
                    body: Box::new(self.parse_expr()?),
                    syntax: LambdaSyntax::Arrow,
                }))
            }
            _ => Ok(Expr::Identifier(w.to_ident(w_span))),
        }
    }

    /// Returns true if the given [ObjectName] is a single unquoted
    /// identifier matching `expected` (case-insensitive).
    fn is_simple_unquoted_object_name(name: &ObjectName, expected: &str) -> bool {
        if let [ObjectNamePart::Identifier(ident)] = name.0.as_slice() {
            ident.quote_style.is_none() && ident.value.eq_ignore_ascii_case(expected)
        } else {
            false
        }
    }

    /// Parse an expression prefix.
    pub fn parse_prefix(&mut self) -> Result<Expr, ParserError> {
        // allow the dialect to override prefix parsing
        if let Some(prefix) = self.dialect.parse_prefix(self) {
            return prefix;
        }

        // Memoize parse_prefix failures to break 2^N speculation when both
        // prefix arms fail at every level (e.g. `IF(current_time(...x`).
        // The per-arm cache in `parse_prefix_inner` complements this for
        // chains where the reserved arm fails but the unreserved fallback
        // succeeds (e.g. `case-case-...c`).
        let start_index = self.index;
        if let Some(&cached) = self.failed_prefix_positions.get(&start_index) {
            return self.cached_prefix_error(cached, self.peek_token_ref());
        }
        let result = self.parse_prefix_inner();
        if let Err(ref e) = result {
            self.failed_prefix_positions.insert(start_index, e.into());
        }
        result
    }

    /// Rebuild the error for a cached prefix failure at the `found` token.
    fn cached_prefix_error<T>(
        &self,
        cached: ExprPrefixError,
        found: &TokenWithSpan,
    ) -> Result<T, ParserError> {
        match cached {
            ExprPrefixError::RecursionLimitExceeded => Err(ParserError::RecursionLimitExceeded),
            ExprPrefixError::Err => self.expected_ref("an expression", found),
        }
    }

    fn parse_prefix_inner(&mut self) -> Result<Expr, ParserError> {
        // PostgreSQL allows any string literal to be preceded by a type name, indicating that the
        // string literal represents a literal of that type. Some examples:
        //
        //      DATE '2020-05-20'
        //      TIMESTAMP WITH TIME ZONE '2020-05-20 7:43:54'
        //      BOOL 'true'
        //
        // The first two are standard SQL, while the latter is a PostgreSQL extension. Complicating
        // matters is the fact that INTERVAL string literals may optionally be followed by special
        // keywords, e.g.:
        //
        //      INTERVAL '7' DAY
        //
        // Note also that naively `SELECT date` looks like a syntax error because the `date` type
        // name is not followed by a string literal, but in fact in PostgreSQL it is a valid
        // expression that should parse as the column name "date".
        let loc = self.peek_token_ref().span.start;
        let opt_expr = self.maybe_parse(|parser| {
            match parser.parse_data_type()? {
                DataType::Interval { .. } => parser.parse_interval(),
                // PostgreSQL allows almost any identifier to be used as custom data type name,
                // and we support that in `parse_data_type()`. But unlike Postgres we don't
                // have a list of globally reserved keywords (since they vary across dialects),
                // so given `NOT 'a' LIKE 'b'`, we'd accept `NOT` as a possible custom data type
                // name, resulting in `NOT 'a'` being recognized as a `TypedString` instead of
                // an unary negation `NOT ('a' LIKE 'b')`. To solve this, we don't accept the
                // `type 'string'` syntax for the custom data types at all ...
                //
                // ... with the exception of `xml '...'` on dialects that support XML
                // expressions, which is a valid PostgreSQL typed string literal.
                DataType::Custom(ref name, ref modifiers)
                    if modifiers.is_empty()
                        && Self::is_simple_unquoted_object_name(name, "xml")
                        && parser.dialect.supports_xml_expressions() =>
                {
                    Ok(Expr::TypedString(TypedString {
                        data_type: DataType::Custom(name.clone(), modifiers.clone()),
                        value: parser.parse_value()?,
                        uses_odbc_syntax: false,
                    }))
                }
                DataType::Custom(..) => parser_err!("dummy", loc),
                // MySQL supports using the `BINARY` keyword as a cast to binary type.
                DataType::Binary(..) if self.dialect.supports_binary_kw_as_cast() => {
                    Ok(Expr::Cast {
                        kind: CastKind::Cast,
                        expr: Box::new(parser.parse_expr()?),
                        data_type: DataType::Binary(None),
                        format: None,
                    })
                }
                data_type => Ok(Expr::TypedString(TypedString {
                    data_type,
                    value: parser.parse_value()?,
                    uses_odbc_syntax: false,
                })),
            }
        })?;

        if let Some(expr) = opt_expr {
            return Ok(expr);
        }

        // Cache some dialect properties to avoid lifetime issues with the
        // next_token reference.

        let dialect = self.dialect;

        self.advance_token();
        let next_token_index = self.get_current_index();
        let next_token = self.get_current_token();
        let span = next_token.span;
        let expr = match &next_token.token {
            Token::Word(w) => {
                // The word we consumed may fall into one of two cases: it has a special meaning, or not.
                // For example, in Snowflake, the word `interval` may have two meanings depending on the context:
                // `SELECT CURRENT_DATE() + INTERVAL '1 DAY', MAX(interval) FROM tbl;`
                //                          ^^^^^^^^^^^^^^^^      ^^^^^^^^
                //                         interval expression   identifier
                //
                // We first try to parse the word and following tokens as a special expression, and if that fails,
                // we rollback and try to parse it as an identifier.
                let w = w.clone();
                // Memoize failed speculative reserved-word parses. When
                // the reserved arm (CASE, CURRENT_TIME, etc.) does
                // exponential work but the unreserved fallback ultimately
                // succeeds, the overall `parse_prefix` returns `Ok` and the
                // outer cache never fires. Chains like `case-case-...c`
                // need this per-arm cache to break the doubling.
                let try_parse_result = if let Some(&cached) = self
                    .failed_reserved_word_prefix_positions
                    .get(&next_token_index)
                {
                    self.cached_prefix_error(cached, self.get_current_token())
                } else {
                    self.try_parse(|parser| parser.parse_expr_prefix_by_reserved_word(&w, span))
                };
                match try_parse_result {
                    // This word indicated an expression prefix and parsing was successful
                    Ok(Some(expr)) => Ok(expr),

                    // No expression prefix associated with this word
                    Ok(None) => Ok(self.parse_expr_prefix_by_unreserved_word(&w, span)?),

                    // If parsing of the word as a special expression failed, we are facing two options:
                    // 1. The statement is malformed, e.g. `SELECT INTERVAL '1 DAI` (`DAI` instead of `DAY`)
                    // 2. The word is used as an identifier, e.g. `SELECT MAX(interval) FROM tbl`
                    // We first try to parse the word as an identifier and if that fails
                    // we rollback and return the parsing error we got from trying to parse a
                    // special expression (to maintain backwards compatibility of parsing errors).
                    Err(e) => {
                        self.failed_reserved_word_prefix_positions
                            .insert(next_token_index, (&e).into());
                        if !self.dialect.is_reserved_for_identifier(w.keyword) {
                            if let Ok(Some(expr)) = self.maybe_parse(|parser| {
                                parser.parse_expr_prefix_by_unreserved_word(&w, span)
                            }) {
                                return Ok(expr);
                            }
                        }
                        return Err(e);
                    }
                }
            } // End of Token::Word
            // array `[1, 2, 3]`
            Token::LBracket => self.parse_array_expr(false),
            tok @ Token::Minus | tok @ Token::Plus => {
                let op = if *tok == Token::Plus {
                    UnaryOperator::Plus
                } else {
                    UnaryOperator::Minus
                };
                Ok(Expr::UnaryOp {
                    op,
                    expr: Box::new(
                        self.parse_subexpr(self.dialect.prec_value(Precedence::MulDivModOp))?,
                    ),
                })
            }
            Token::ExclamationMark if dialect.supports_bang_not_operator() => Ok(Expr::UnaryOp {
                op: UnaryOperator::BangNot,
                expr: Box::new(self.parse_subexpr(self.dialect.prec_value(Precedence::UnaryNot))?),
            }),
            tok @ Token::DoubleExclamationMark
            | tok @ Token::PGSquareRoot
            | tok @ Token::PGCubeRoot
            | tok @ Token::AtSign
                if dialect_is!(dialect is PostgreSqlDialect) =>
            {
                let op = match tok {
                    Token::DoubleExclamationMark => UnaryOperator::PGPrefixFactorial,
                    Token::PGSquareRoot => UnaryOperator::PGSquareRoot,
                    Token::PGCubeRoot => UnaryOperator::PGCubeRoot,
                    Token::AtSign => UnaryOperator::PGAbs,
                    _ => {
                        return Err(ParserError::ParserError(
                            "Internal parser error: unexpected unary operator token".to_string(),
                        ))
                    }
                };
                Ok(Expr::UnaryOp {
                    op,
                    expr: Box::new(
                        self.parse_subexpr(self.dialect.prec_value(Precedence::PlusMinus))?,
                    ),
                })
            }
            Token::Tilde => Ok(Expr::UnaryOp {
                op: UnaryOperator::BitwiseNot,
                expr: Box::new(self.parse_subexpr(self.dialect.prec_value(Precedence::PlusMinus))?),
            }),
            tok @ Token::Sharp
            | tok @ Token::AtDashAt
            | tok @ Token::AtAt
            | tok @ Token::QuestionMarkDash
            | tok @ Token::QuestionPipe
                if self.dialect.supports_geometric_types() =>
            {
                let op = match tok {
                    Token::Sharp => UnaryOperator::Hash,
                    Token::AtDashAt => UnaryOperator::AtDashAt,
                    Token::AtAt => UnaryOperator::DoubleAt,
                    Token::QuestionMarkDash => UnaryOperator::QuestionDash,
                    Token::QuestionPipe => UnaryOperator::QuestionPipe,
                    _ => {
                        return Err(ParserError::ParserError(format!(
                            "Unexpected token in unary operator parsing: {tok:?}"
                        )))
                    }
                };
                Ok(Expr::UnaryOp {
                    op,
                    expr: Box::new(
                        self.parse_subexpr(self.dialect.prec_value(Precedence::PlusMinus))?,
                    ),
                })
            }
            Token::EscapedStringLiteral(_) if dialect_is!(dialect is PostgreSqlDialect | GenericDialect) =>
            {
                self.prev_token();
                Ok(Expr::Value(self.parse_value()?))
            }
            Token::UnicodeStringLiteral(_) => {
                self.prev_token();
                Ok(Expr::Value(self.parse_value()?))
            }
            Token::Number(_, _)
            | Token::SingleQuotedString(_)
            | Token::DoubleQuotedString(_)
            | Token::TripleSingleQuotedString(_)
            | Token::TripleDoubleQuotedString(_)
            | Token::DollarQuotedString(_)
            | Token::SingleQuotedByteStringLiteral(_)
            | Token::DoubleQuotedByteStringLiteral(_)
            | Token::TripleSingleQuotedByteStringLiteral(_)
            | Token::TripleDoubleQuotedByteStringLiteral(_)
            | Token::SingleQuotedRawStringLiteral(_)
            | Token::DoubleQuotedRawStringLiteral(_)
            | Token::TripleSingleQuotedRawStringLiteral(_)
            | Token::TripleDoubleQuotedRawStringLiteral(_)
            | Token::NationalStringLiteral(_)
            | Token::QuoteDelimitedStringLiteral(_)
            | Token::NationalQuoteDelimitedStringLiteral(_)
            | Token::HexStringLiteral(_) => {
                self.prev_token();
                Ok(Expr::Value(self.parse_value()?))
            }
            Token::LParen => {
                let expr =
                    if let Some(expr) = self.try_parse_expr_sub_query()? {
                        expr
                    } else if let Some(lambda) = self.try_parse_lambda()? {
                        return Ok(lambda);
                    } else {
                        // Parentheses in expressions switch to "normal" parsing state.
                        // This matters for dialects (SQLite, DuckDB) where `NOT NULL` can
                        // be an alias for `IS NOT NULL`. In column definitions like:
                        //
                        //   CREATE TABLE t (c INT DEFAULT (42 NOT NULL) NOT NULL)
                        //
                        // The `(42 NOT NULL)` is an expression with parens, so it parses
                        // as `IsNotNull(42)`. The trailing `NOT NULL` is outside those
                        // expression parens (the outer parens are CREATE TABLE syntax),
                        // so it remains a column constraint.
                        let exprs = self.with_state(ParserState::Normal, |p| {
                            p.parse_comma_separated(Parser::parse_expr)
                        })?;
                        match exprs.len() {
                            0 => return Err(ParserError::ParserError(
                                "Internal parser error: parse_comma_separated returned empty list"
                                    .to_string(),
                            )),
                            1 => Expr::Nested(Box::new(exprs.into_iter().next().unwrap())),
                            _ => Expr::Tuple(exprs),
                        }
                    };
                self.expect_token(&Token::RParen)?;
                Ok(expr)
            }
            Token::Placeholder(_) | Token::Colon | Token::AtSign => {
                self.prev_token();
                Ok(Expr::Value(self.parse_value()?))
            }
            Token::LBrace => {
                self.prev_token();
                self.parse_lbrace_expr()
            }
            _ => self.expected_at("an expression", next_token_index),
        }?;

        Ok(expr)
    }

    fn parse_geometric_type(&mut self, kind: GeometricTypeKind) -> Result<Expr, ParserError> {
        Ok(Expr::TypedString(TypedString {
            data_type: DataType::GeometricType(kind),
            value: self.parse_value()?,
            uses_odbc_syntax: false,
        }))
    }

    /// Try to parse an [Expr::CompoundFieldAccess] like `a.b.c` or `a.b[1].c`.
    /// If all the fields are `Expr::Identifier`s, return an [Expr::CompoundIdentifier] instead.
    /// If only the root exists, return the root.
    /// Parses compound expressions which may be delimited by period
    /// or bracket notation.
    /// For example: `a.b.c`, `a.b[1]`.
    pub fn parse_compound_expr(
        &mut self,
        root: Expr,
        mut chain: Vec<AccessExpr>,
    ) -> Result<Expr, ParserError> {
        let mut ending_wildcard: Option<TokenWithSpan> = None;
        loop {
            if self.consume_token(&Token::Period) {
                let next_token = self.peek_token_ref();
                match &next_token.token {
                    Token::Mul => {
                        // Postgres explicitly allows funcnm(tablenm.*) and the
                        // function array_agg traverses this control flow
                        if dialect_of!(self is PostgreSqlDialect) {
                            ending_wildcard = Some(self.next_token());
                        } else {
                            // Put back the consumed `.` tokens before exiting.
                            // If this expression is being parsed in the
                            // context of a projection, then the `.*` could imply
                            // a wildcard expansion. For example:
                            // `SELECT STRUCT('foo').* FROM T`
                            self.prev_token(); // .
                        }

                        break;
                    }
                    Token::SingleQuotedString(s) => {
                        let expr =
                            Expr::Identifier(Ident::with_quote_and_span('\'', next_token.span, s));
                        chain.push(AccessExpr::Dot(expr));
                        self.advance_token(); // The consumed string
                    }
                    Token::Placeholder(s) => {
                        // Snowflake uses $1, $2, etc. for positional column references
                        // in staged data queries like: SELECT t.$1 FROM @stage t
                        let expr = Expr::Identifier(Ident::with_span(next_token.span, s));
                        chain.push(AccessExpr::Dot(expr));
                        self.advance_token(); // The consumed placeholder
                    }
                    // Parse a single field component, restricted to expression types valid
                    // after `.` (so e.g. `T.interval` is a compound identifier, not an
                    // interval expression). Using `parse_prefix` here rather than
                    // `parse_subexpr` avoids 2^N work on inputs like `IF a.b.c...x.#`:
                    // the outer loop already consumes successive `.field` segments, so a
                    // recursive `parse_subexpr` would re-walk the rest of the chain at
                    // every dot.
                    _ => {
                        // For a plain `Word` field (not followed by `(`), skip the
                        // speculative `parse_prefix`. The only result the validator
                        // below would accept is `Identifier`, which `parse_identifier`
                        // in the None branch produces directly. This avoids 2^N work
                        // on chains like `.not-b.not-b...` where `parse_prefix` would
                        // descend into `parse_not` and re-walk the remaining chain at
                        // every segment.
                        let word_field_no_lparen =
                            matches!(self.peek_token_ref().token, Token::Word(_))
                                && self.peek_nth_token_ref(1).token != Token::LParen;

                        let expr = if word_field_no_lparen {
                            None
                        } else {
                            self.maybe_parse(|parser| {
                                let expr = parser.parse_prefix()?;
                                match &expr {
                                    Expr::CompoundFieldAccess { .. }
                                    | Expr::CompoundIdentifier(_)
                                    | Expr::Identifier(_)
                                    | Expr::Value(_)
                                    | Expr::Function(_) => Ok(expr),
                                    _ => parser.expected_ref(
                                        "an identifier or value",
                                        parser.peek_token_ref(),
                                    ),
                                }
                            })?
                        };

                        match expr {
                            // If we get back a compound field access or identifier,
                            // we flatten the nested expression.
                            // For example if the current root is `foo`
                            // and we get back a compound identifier expression `bar.baz`
                            // The full expression should be `foo.bar.baz` (i.e.
                            // a root with an access chain with 2 entries) and not
                            // `foo.(bar.baz)` (i.e. a root with an access chain with
                            // 1 entry`).
                            Some(Expr::CompoundFieldAccess { root, access_chain }) => {
                                chain.push(AccessExpr::Dot(*root));
                                chain.extend(access_chain);
                            }
                            Some(Expr::CompoundIdentifier(parts)) => chain.extend(
                                parts.into_iter().map(Expr::Identifier).map(AccessExpr::Dot),
                            ),
                            Some(expr) => {
                                chain.push(AccessExpr::Dot(expr));
                            }
                            // If the expression is not a valid suffix, fall back to
                            // parsing as an identifier. This handles cases like `T.interval`
                            // where `interval` is a keyword but should be treated as an identifier.
                            None => {
                                chain.push(AccessExpr::Dot(Expr::Identifier(
                                    self.parse_identifier()?,
                                )));
                            }
                        }
                    }
                }
            } else if !self.dialect.supports_partiql()
                && self.peek_token_ref().token == Token::LBracket
            {
                self.parse_multi_dim_subscript(&mut chain)?;
            } else {
                break;
            }
        }

        let tok_index = self.get_current_index();
        if let Some(wildcard_token) = ending_wildcard {
            if !Self::is_all_ident(&root, &chain) {
                return self
                    .expected_ref("an identifier or a '*' after '.'", self.peek_token_ref());
            };
            Ok(Expr::QualifiedWildcard(
                ObjectName::from(Self::exprs_to_idents(root, chain)?),
                AttachedToken(wildcard_token),
            ))
        } else if self.maybe_parse_outer_join_operator() {
            if !Self::is_all_ident(&root, &chain) {
                return self.expected_at("column identifier before (+)", tok_index);
            };
            let expr = if chain.is_empty() {
                root
            } else {
                Expr::CompoundIdentifier(Self::exprs_to_idents(root, chain)?)
            };
            Ok(Expr::OuterJoin(expr.into()))
        } else {
            Self::build_compound_expr(root, chain)
        }
    }

    /// Combines a root expression and access chain to form
    /// a compound expression. Which may be a [Expr::CompoundFieldAccess]
    /// or other special cased expressions like [Expr::CompoundIdentifier],
    /// [Expr::OuterJoin].
    fn build_compound_expr(
        root: Expr,
        mut access_chain: Vec<AccessExpr>,
    ) -> Result<Expr, ParserError> {
        if access_chain.is_empty() {
            return Ok(root);
        }

        if Self::is_all_ident(&root, &access_chain) {
            return Ok(Expr::CompoundIdentifier(Self::exprs_to_idents(
                root,
                access_chain,
            )?));
        }

        // Flatten qualified function calls.
        // For example, the expression `a.b.c.foo(1,2,3)` should
        // represent a function called `a.b.c.foo`, rather than
        // a composite expression.
        if matches!(root, Expr::Identifier(_))
            && matches!(
                access_chain.last(),
                Some(AccessExpr::Dot(Expr::Function(_)))
            )
            && access_chain
                .iter()
                .rev()
                .skip(1) // All except the Function
                .all(|access| matches!(access, AccessExpr::Dot(Expr::Identifier(_))))
        {
            let Some(AccessExpr::Dot(Expr::Function(mut func))) = access_chain.pop() else {
                return parser_err!("expected function expression", root.span().start);
            };

            let compound_func_name = [root]
                .into_iter()
                .chain(access_chain.into_iter().flat_map(|access| match access {
                    AccessExpr::Dot(expr) => Some(expr),
                    _ => None,
                }))
                .flat_map(|expr| match expr {
                    Expr::Identifier(ident) => Some(ident),
                    _ => None,
                })
                .map(ObjectNamePart::Identifier)
                .chain(func.name.0)
                .collect::<Vec<_>>();
            func.name = ObjectName(compound_func_name);

            return Ok(Expr::Function(func));
        }

        // Flatten qualified outer join expressions.
        // For example, the expression `T.foo(+)` should
        // represent an outer join on the column name `T.foo`
        // rather than a composite expression.
        if access_chain.len() == 1
            && matches!(
                access_chain.last(),
                Some(AccessExpr::Dot(Expr::OuterJoin(_)))
            )
        {
            let Some(AccessExpr::Dot(Expr::OuterJoin(inner_expr))) = access_chain.pop() else {
                return parser_err!("expected (+) expression", root.span().start);
            };

            if !Self::is_all_ident(&root, &[]) {
                return parser_err!("column identifier before (+)", root.span().start);
            };

            let token_start = root.span().start;
            let mut idents = Self::exprs_to_idents(root, vec![])?;
            match *inner_expr {
                Expr::CompoundIdentifier(suffix) => idents.extend(suffix),
                Expr::Identifier(suffix) => idents.push(suffix),
                _ => {
                    return parser_err!("column identifier before (+)", token_start);
                }
            }

            return Ok(Expr::OuterJoin(Expr::CompoundIdentifier(idents).into()));
        }

        Ok(Expr::CompoundFieldAccess {
            root: Box::new(root),
            access_chain,
        })
    }

    fn keyword_to_modifier(k: Keyword) -> Option<ContextModifier> {
        match k {
            Keyword::LOCAL => Some(ContextModifier::Local),
            Keyword::GLOBAL => Some(ContextModifier::Global),
            Keyword::SESSION => Some(ContextModifier::Session),
            _ => None,
        }
    }

    /// Check if the root is an identifier and all fields are identifiers.
    fn is_all_ident(root: &Expr, fields: &[AccessExpr]) -> bool {
        if !matches!(root, Expr::Identifier(_)) {
            return false;
        }
        fields
            .iter()
            .all(|x| matches!(x, AccessExpr::Dot(Expr::Identifier(_))))
    }

    /// Convert a root and a list of fields to a list of identifiers.
    fn exprs_to_idents(root: Expr, fields: Vec<AccessExpr>) -> Result<Vec<Ident>, ParserError> {
        let mut idents = vec![];
        if let Expr::Identifier(root) = root {
            idents.push(root);
            for x in fields {
                if let AccessExpr::Dot(Expr::Identifier(ident)) = x {
                    idents.push(ident);
                } else {
                    return parser_err!(
                        format!("Expected identifier, found: {}", x),
                        x.span().start
                    );
                }
            }
            Ok(idents)
        } else {
            parser_err!(
                format!("Expected identifier, found: {}", root),
                root.span().start
            )
        }
    }

    /// Returns true if the next tokens indicate the outer join operator `(+)`.
    fn peek_outer_join_operator(&mut self) -> bool {
        if !self.dialect.supports_outer_join_operator() {
            return false;
        }

        let [maybe_lparen, maybe_plus, maybe_rparen] = self.peek_tokens_ref();
        Token::LParen == maybe_lparen.token
            && Token::Plus == maybe_plus.token
            && Token::RParen == maybe_rparen.token
    }

    /// If the next tokens indicates the outer join operator `(+)`, consume
    /// the tokens and return true.
    fn maybe_parse_outer_join_operator(&mut self) -> bool {
        self.dialect.supports_outer_join_operator()
            && self.consume_tokens(&[Token::LParen, Token::Plus, Token::RParen])
    }

    /// Parse utility options in the form of `(option1, option2 arg2, option3 arg3, ...)`
    pub fn parse_utility_options(&mut self) -> Result<Vec<UtilityOption>, ParserError> {
        self.expect_token(&Token::LParen)?;
        let options = self.parse_comma_separated(Self::parse_utility_option)?;
        self.expect_token(&Token::RParen)?;

        Ok(options)
    }

    fn parse_utility_option(&mut self) -> Result<UtilityOption, ParserError> {
        let name = self.parse_identifier()?;

        let next_token = self.peek_token_ref();
        if next_token == &Token::Comma || next_token == &Token::RParen {
            return Ok(UtilityOption { name, arg: None });
        }
        let arg = self.parse_expr()?;

        Ok(UtilityOption {
            name,
            arg: Some(arg),
        })
    }

    fn try_parse_expr_sub_query(&mut self) -> Result<Option<Expr>, ParserError> {
        if !self.peek_sub_query() {
            return Ok(None);
        }

        Ok(Some(Expr::Subquery(self.parse_query()?)))
    }

    fn try_parse_lambda(&mut self) -> Result<Option<Expr>, ParserError> {
        if !self.dialect.supports_lambda_functions() {
            return Ok(None);
        }
        self.maybe_parse(|p| {
            let params = p.parse_comma_separated(|p| p.parse_lambda_function_parameter())?;
            p.expect_token(&Token::RParen)?;
            p.expect_token(&Token::Arrow)?;
            let expr = p.parse_expr()?;
            Ok(Expr::Lambda(LambdaFunction {
                params: OneOrManyWithParens::Many(params),
                body: Box::new(expr),
                syntax: LambdaSyntax::Arrow,
            }))
        })
    }

    /// Parses a lambda expression following the `LAMBDA` keyword syntax.
    ///
    /// Syntax: `LAMBDA <params> : <expr>`
    ///
    /// Examples:
    /// - `LAMBDA x : x + 1`
    /// - `LAMBDA x, i : x > i`
    ///
    /// See <https://duckdb.org/docs/stable/sql/functions/lambda>
    fn parse_lambda_expr(&mut self) -> Result<Expr, ParserError> {
        // Parse the parameters: either a single identifier or comma-separated identifiers
        let params = self.parse_lambda_function_parameters()?;
        // Expect the colon separator
        self.expect_token(&Token::Colon)?;
        // Parse the body expression
        let body = self.parse_expr()?;
        Ok(Expr::Lambda(LambdaFunction {
            params,
            body: Box::new(body),
            syntax: LambdaSyntax::LambdaKeyword,
        }))
    }

    /// Parses the parameters of a lambda function with optional typing.
    fn parse_lambda_function_parameters(
        &mut self,
    ) -> Result<OneOrManyWithParens<LambdaFunctionParameter>, ParserError> {
        // Parse the parameters: either a single identifier or comma-separated identifiers
        let params = if self.consume_token(&Token::LParen) {
            // Parenthesized parameters: (x, y)
            let params = self.parse_comma_separated(|p| p.parse_lambda_function_parameter())?;
            self.expect_token(&Token::RParen)?;
            OneOrManyWithParens::Many(params)
        } else {
            // Unparenthesized parameters: x or x, y
            let params = self.parse_comma_separated(|p| p.parse_lambda_function_parameter())?;
            if params.len() == 1 {
                OneOrManyWithParens::One(params.into_iter().next().unwrap())
            } else {
                OneOrManyWithParens::Many(params)
            }
        };
        Ok(params)
    }

    /// Parses a single parameter of a lambda function, with optional typing.
    fn parse_lambda_function_parameter(&mut self) -> Result<LambdaFunctionParameter, ParserError> {
        let name = self.parse_identifier()?;
        let data_type = match &self.peek_token_ref().token {
            Token::Word(_) => self.maybe_parse(|p| p.parse_data_type())?,
            _ => None,
        };
        Ok(LambdaFunctionParameter { name, data_type })
    }

    /// Tries to parse the body of an [ODBC escaping sequence]
    /// i.e. without the enclosing braces
    /// Currently implemented:
    /// Scalar Function Calls
    /// Date, Time, and Timestamp Literals
    /// See <https://learn.microsoft.com/en-us/sql/odbc/reference/develop-app/escape-sequences-in-odbc?view=sql-server-2017>
    fn maybe_parse_odbc_body(&mut self) -> Result<Option<Expr>, ParserError> {
        // Attempt 1: Try to parse it as a function.
        if let Some(expr) = self.maybe_parse_odbc_fn_body()? {
            return Ok(Some(expr));
        }
        // Attempt 2: Try to parse it as a Date, Time or Timestamp Literal
        self.maybe_parse_odbc_body_datetime()
    }

    /// Tries to parse the body of an [ODBC Date, Time, and Timestamp Literals] call.
    ///
    /// ```sql
    /// {d '2025-07-17'}
    /// {t '14:12:01'}
    /// {ts '2025-07-17 14:12:01'}
    /// ```
    ///
    /// [ODBC Date, Time, and Timestamp Literals]:
    /// https://learn.microsoft.com/en-us/sql/odbc/reference/develop-app/date-time-and-timestamp-literals?view=sql-server-2017
    fn maybe_parse_odbc_body_datetime(&mut self) -> Result<Option<Expr>, ParserError> {
        self.maybe_parse(|p| {
            let token = p.next_token().clone();
            let word_string = token.token.to_string();
            let data_type = match word_string.as_str() {
                "t" => DataType::Time(None, TimezoneInfo::None),
                "d" => DataType::Date,
                "ts" => DataType::Timestamp(None, TimezoneInfo::None),
                _ => return p.expected("ODBC datetime keyword (t, d, or ts)", token),
            };
            let value = p.parse_value()?;
            Ok(Expr::TypedString(TypedString {
                data_type,
                value,
                uses_odbc_syntax: true,
            }))
        })
    }

    /// Tries to parse the body of an [ODBC function] call.
    /// i.e. without the enclosing braces
    ///
    /// ```sql
    /// fn myfunc(1,2,3)
    /// ```
    ///
    /// [ODBC function]: https://learn.microsoft.com/en-us/sql/odbc/reference/develop-app/scalar-function-calls?view=sql-server-2017
    fn maybe_parse_odbc_fn_body(&mut self) -> Result<Option<Expr>, ParserError> {
        self.maybe_parse(|p| {
            p.expect_keyword(Keyword::FN)?;
            let fn_name = p.parse_object_name(false)?;
            let mut fn_call = p.parse_function_call(fn_name)?;
            fn_call.uses_odbc_syntax = true;
            Ok(Expr::Function(fn_call))
        })
    }

    /// Parse the argument list of `XMLPARSE({ DOCUMENT | CONTENT } value)`,
    /// including the closing parenthesis. The mode word becomes the name of the
    /// single argument, with no operator between it and the value.
    fn parse_xmlparse_argument_list(&mut self) -> Result<FunctionArgumentList, ParserError> {
        let arg = FunctionArg::Named {
            name: self.parse_identifier()?,
            arg: FunctionArgExpr::Expr(self.parse_expr()?),
            operator: FunctionArgOperator::Space,
        };
        self.expect_token(&Token::RParen)?;
        Ok(FunctionArgumentList {
            duplicate_treatment: None,
            args: vec![arg],
            clauses: vec![],
        })
    }

    /// Parse a function call expression named by `name` and return it as an `Expr`.
    pub fn parse_function(&mut self, name: ObjectName) -> Result<Expr, ParserError> {
        self.parse_function_call(name).map(Expr::Function)
    }

    fn parse_function_call(&mut self, name: ObjectName) -> Result<Function, ParserError> {
        self.expect_token(&Token::LParen)?;

        // Snowflake permits a subquery to be passed as an argument without
        // an enclosing set of parens if it's the only argument.
        if self.dialect.supports_subquery_as_function_arg() && self.peek_sub_query() {
            let subquery = self.parse_query()?;
            self.expect_token(&Token::RParen)?;
            return Ok(Function {
                name,
                uses_odbc_syntax: false,
                parameters: FunctionArguments::None,
                args: FunctionArguments::Subquery(subquery),
                filter: None,
                null_treatment: None,
                over: None,
                within_group: vec![],
            });
        }

        let mut args = if self.dialect.supports_xml_expressions()
            && Self::is_simple_unquoted_object_name(&name, "xmlparse")
        {
            self.parse_xmlparse_argument_list()?
        } else {
            self.parse_function_argument_list()?
        };
        let mut parameters = FunctionArguments::None;
        // ClickHouse aggregations support parametric functions like `HISTOGRAM(0.5, 0.6)(x, y)`
        // which (0.5, 0.6) is a parameter to the function.
        if dialect_of!(self is ClickHouseDialect | GenericDialect)
            && self.consume_token(&Token::LParen)
        {
            parameters = FunctionArguments::List(args);
            args = self.parse_function_argument_list()?;
        }

        let within_group = if self.parse_keywords(&[Keyword::WITHIN, Keyword::GROUP]) {
            self.expect_token(&Token::LParen)?;
            self.expect_keywords(&[Keyword::ORDER, Keyword::BY])?;
            let order_by = self.parse_comma_separated(Parser::parse_order_by_expr)?;
            self.expect_token(&Token::RParen)?;
            order_by
        } else {
            vec![]
        };

        let filter = if self.dialect.supports_filter_during_aggregation()
            && self.parse_keyword(Keyword::FILTER)
            && self.consume_token(&Token::LParen)
            && self.parse_keyword(Keyword::WHERE)
        {
            let filter = Some(Box::new(self.parse_expr()?));
            self.expect_token(&Token::RParen)?;
            filter
        } else {
            None
        };

        // Syntax for null treatment shows up either in the args list
        // or after the function call, but not both.
        let null_treatment = if args
            .clauses
            .iter()
            .all(|clause| !matches!(clause, FunctionArgumentClause::IgnoreOrRespectNulls(_)))
        {
            self.parse_null_treatment()?
        } else {
            None
        };

        let over = if self.parse_keyword(Keyword::OVER) {
            if self.consume_token(&Token::LParen) {
                let window_spec = self.parse_window_spec()?;
                Some(WindowType::WindowSpec(window_spec))
            } else {
                Some(WindowType::NamedWindow(self.parse_identifier()?))
            }
        } else {
            None
        };

        Ok(Function {
            name,
            uses_odbc_syntax: false,
            parameters,
            args: FunctionArguments::List(args),
            null_treatment,
            filter,
            over,
            within_group,
        })
    }

    /// Optionally parses a null treatment clause.
    fn parse_null_treatment(&mut self) -> Result<Option<NullTreatment>, ParserError> {
        match self.parse_one_of_keywords(&[Keyword::RESPECT, Keyword::IGNORE]) {
            Some(keyword) => {
                self.expect_keyword_is(Keyword::NULLS)?;

                Ok(match keyword {
                    Keyword::RESPECT => Some(NullTreatment::RespectNulls),
                    Keyword::IGNORE => Some(NullTreatment::IgnoreNulls),
                    _ => None,
                })
            }
            None => Ok(None),
        }
    }

    /// Parse time-related function `name` possibly followed by `(...)` arguments.
    pub fn parse_time_functions(&mut self, name: ObjectName) -> Result<Expr, ParserError> {
        let args = if self.consume_token(&Token::LParen) {
            FunctionArguments::List(self.parse_function_argument_list()?)
        } else {
            FunctionArguments::None
        };
        Ok(Expr::Function(Function {
            name,
            uses_odbc_syntax: false,
            parameters: FunctionArguments::None,
            args,
            filter: None,
            over: None,
            null_treatment: None,
            within_group: vec![],
        }))
    }

    /// Parse window frame `UNITS` clause: `ROWS`, `RANGE`, or `GROUPS`.
    pub fn parse_window_frame_units(&mut self) -> Result<WindowFrameUnits, ParserError> {
        let next_token = self.next_token();
        match &next_token.token {
            Token::Word(w) => match w.keyword {
                Keyword::ROWS => Ok(WindowFrameUnits::Rows),
                Keyword::RANGE => Ok(WindowFrameUnits::Range),
                Keyword::GROUPS => Ok(WindowFrameUnits::Groups),
                _ => self.expected("ROWS, RANGE, GROUPS", next_token)?,
            },
            _ => self.expected("ROWS, RANGE, GROUPS", next_token),
        }
    }

    /// Parse a `WINDOW` frame definition (units and bounds).
    pub fn parse_window_frame(&mut self) -> Result<WindowFrame, ParserError> {
        let units = self.parse_window_frame_units()?;
        let (start_bound, end_bound) = if self.parse_keyword(Keyword::BETWEEN) {
            let start_bound = self.parse_window_frame_bound()?;
            self.expect_keyword_is(Keyword::AND)?;
            let end_bound = Some(self.parse_window_frame_bound()?);
            (start_bound, end_bound)
        } else {
            (self.parse_window_frame_bound()?, None)
        };
        Ok(WindowFrame {
            units,
            start_bound,
            end_bound,
        })
    }

    /// Parse a window frame bound: `CURRENT ROW` or `<n> PRECEDING|FOLLOWING`.
    pub fn parse_window_frame_bound(&mut self) -> Result<WindowFrameBound, ParserError> {
        if self.parse_keywords(&[Keyword::CURRENT, Keyword::ROW]) {
            Ok(WindowFrameBound::CurrentRow)
        } else {
            let rows = if self.parse_keyword(Keyword::UNBOUNDED) {
                None
            } else {
                Some(Box::new(match &self.peek_token_ref().token {
                    Token::SingleQuotedString(_) => self.parse_interval()?,
                    _ => self.parse_expr()?,
                }))
            };
            if self.parse_keyword(Keyword::PRECEDING) {
                Ok(WindowFrameBound::Preceding(rows))
            } else if self.parse_keyword(Keyword::FOLLOWING) {
                Ok(WindowFrameBound::Following(rows))
            } else {
                self.expected_ref("PRECEDING or FOLLOWING", self.peek_token_ref())
            }
        }
    }

    /// Parse a group by expr. Group by expr can be one of group sets, roll up, cube, or simple expr.
    fn parse_group_by_expr(&mut self) -> Result<Expr, ParserError> {
        if self.dialect.supports_group_by_expr() {
            if self.parse_keywords(&[Keyword::GROUPING, Keyword::SETS]) {
                self.expect_token(&Token::LParen)?;
                let result = self.parse_comma_separated(|p| p.parse_tuple(true, true))?;
                self.expect_token(&Token::RParen)?;
                Ok(Expr::GroupingSets(result))
            } else if self.parse_keyword(Keyword::CUBE) {
                self.expect_token(&Token::LParen)?;
                let result = self.parse_comma_separated(|p| p.parse_tuple(true, true))?;
                self.expect_token(&Token::RParen)?;
                Ok(Expr::Cube(result))
            } else if self.parse_keyword(Keyword::ROLLUP) {
                self.expect_token(&Token::LParen)?;
                let result = self.parse_comma_separated(|p| p.parse_tuple(true, true))?;
                self.expect_token(&Token::RParen)?;
                Ok(Expr::Rollup(result))
            } else if self.consume_tokens(&[Token::LParen, Token::RParen]) {
                // PostgreSQL allow to use empty tuple as a group by expression,
                // e.g. `GROUP BY (), name`. Please refer to GROUP BY Clause section in
                // [PostgreSQL](https://www.postgresql.org/docs/16/sql-select.html)
                Ok(Expr::Tuple(vec![]))
            } else {
                self.parse_expr()
            }
        } else {
            // TODO parse rollup for other dialects
            self.parse_expr()
        }
    }

    /// Parse a tuple with `(` and `)`.
    /// If `lift_singleton` is true, then a singleton tuple is lifted to a tuple of length 1, otherwise it will fail.
    /// If `allow_empty` is true, then an empty tuple is allowed.
    fn parse_tuple(
        &mut self,
        lift_singleton: bool,
        allow_empty: bool,
    ) -> Result<Vec<Expr>, ParserError> {
        if lift_singleton {
            if self.consume_token(&Token::LParen) {
                let result = if allow_empty && self.consume_token(&Token::RParen) {
                    vec![]
                } else {
                    let result = self.parse_comma_separated(Parser::parse_expr)?;
                    self.expect_token(&Token::RParen)?;
                    result
                };
                Ok(result)
            } else {
                Ok(vec![self.parse_expr()?])
            }
        } else {
            self.expect_token(&Token::LParen)?;
            let result = if allow_empty && self.consume_token(&Token::RParen) {
                vec![]
            } else {
                let result = self.parse_comma_separated(Parser::parse_expr)?;
                self.expect_token(&Token::RParen)?;
                result
            };
            Ok(result)
        }
    }

    /// Parse a `CASE` expression and return an [`Expr::Case`].
    pub fn parse_case_expr(&mut self) -> Result<Expr, ParserError> {
        let case_token = AttachedToken(self.get_current_token().clone());
        let mut operand = None;
        if !self.parse_keyword(Keyword::WHEN) {
            operand = Some(Box::new(self.parse_expr()?));
            self.expect_keyword_is(Keyword::WHEN)?;
        }
        let mut conditions = vec![];
        loop {
            let condition = self.parse_expr()?;
            self.expect_keyword_is(Keyword::THEN)?;
            let result = self.parse_expr()?;
            conditions.push(CaseWhen { condition, result });
            if !self.parse_keyword(Keyword::WHEN) {
                break;
            }
        }
        let else_result = if self.parse_keyword(Keyword::ELSE) {
            Some(Box::new(self.parse_expr()?))
        } else {
            None
        };
        let end_token = AttachedToken(self.expect_keyword(Keyword::END)?);
        Ok(Expr::Case {
            case_token,
            end_token,
            operand,
            conditions,
            else_result,
        })
    }

    /// Parse an optional `FORMAT` clause for `CAST` expressions.
    pub fn parse_optional_cast_format(&mut self) -> Result<Option<CastFormat>, ParserError> {
        if self.parse_keyword(Keyword::FORMAT) {
            let value = self.parse_value()?;
            match self.parse_optional_time_zone()? {
                Some(tz) => Ok(Some(CastFormat::ValueAtTimeZone(value, tz))),
                None => Ok(Some(CastFormat::Value(value))),
            }
        } else {
            Ok(None)
        }
    }

    /// Parse an optional `AT TIME ZONE` clause.
    pub fn parse_optional_time_zone(&mut self) -> Result<Option<ValueWithSpan>, ParserError> {
        if self.parse_keywords(&[Keyword::AT, Keyword::TIME, Keyword::ZONE]) {
            self.parse_value().map(Some)
        } else {
            Ok(None)
        }
    }

    /// mssql-like convert function
    fn parse_mssql_convert(&mut self, is_try: bool) -> Result<Expr, ParserError> {
        self.expect_token(&Token::LParen)?;
        let data_type = self.parse_data_type()?;
        self.expect_token(&Token::Comma)?;
        let expr = self.parse_expr()?;
        let styles = if self.consume_token(&Token::Comma) {
            self.parse_comma_separated(Parser::parse_expr)?
        } else {
            Default::default()
        };
        self.expect_token(&Token::RParen)?;
        Ok(Expr::Convert {
            is_try,
            expr: Box::new(expr),
            data_type: Some(data_type),
            charset: None,
            target_before_value: true,
            styles,
        })
    }

    /// Parse a SQL CONVERT function:
    ///  - `CONVERT('héhé' USING utf8mb4)` (MySQL)
    ///  - `CONVERT('héhé', CHAR CHARACTER SET utf8mb4)` (MySQL)
    ///  - `CONVERT(DECIMAL(10, 5), 42)` (MSSQL) - the type comes first
    pub fn parse_convert_expr(&mut self, is_try: bool) -> Result<Expr, ParserError> {
        if self.dialect.convert_type_before_value() {
            return self.parse_mssql_convert(is_try);
        }
        self.expect_token(&Token::LParen)?;
        let expr = self.parse_expr()?;
        if self.parse_keyword(Keyword::USING) {
            let charset = self.parse_object_name(false)?;
            self.expect_token(&Token::RParen)?;
            return Ok(Expr::Convert {
                is_try,
                expr: Box::new(expr),
                data_type: None,
                charset: Some(charset),
                target_before_value: false,
                styles: vec![],
            });
        }
        self.expect_token(&Token::Comma)?;
        let data_type = self.parse_data_type()?;
        let charset = if self.parse_keywords(&[Keyword::CHARACTER, Keyword::SET]) {
            Some(self.parse_object_name(false)?)
        } else {
            None
        };
        self.expect_token(&Token::RParen)?;
        Ok(Expr::Convert {
            is_try,
            expr: Box::new(expr),
            data_type: Some(data_type),
            charset,
            target_before_value: false,
            styles: vec![],
        })
    }

    /// Parse a SQL CAST function e.g. `CAST(expr AS FLOAT)`
    pub fn parse_cast_expr(&mut self, kind: CastKind) -> Result<Expr, ParserError> {
        self.expect_token(&Token::LParen)?;
        let expr = self.parse_expr()?;
        self.expect_keyword_is(Keyword::AS)?;
        let data_type = if self.dialect.supports_cast_empty_data_type_to_unspecified()
            && self.peek_token_ref().token == Token::RParen
        {
            DataType::Unspecified
        } else {
            self.parse_data_type()?
        };
        let format = self.parse_optional_cast_format()?;
        self.expect_token(&Token::RParen)?;
        Ok(Expr::Cast {
            kind,
            expr: Box::new(expr),
            data_type,
            format,
        })
    }

    /// Parse a SQL EXISTS expression e.g. `WHERE EXISTS(SELECT ...)`.
    pub fn parse_exists_expr(&mut self, negated: bool) -> Result<Expr, ParserError> {
        self.expect_token(&Token::LParen)?;
        let exists_node = Expr::Exists {
            negated,
            subquery: self.parse_query()?,
        };
        self.expect_token(&Token::RParen)?;
        Ok(exists_node)
    }

    /// Parse a SQL `EXTRACT` expression e.g. `EXTRACT(YEAR FROM date)`.
    pub fn parse_extract_expr(&mut self) -> Result<Expr, ParserError> {
        self.expect_token(&Token::LParen)?;
        let field = self.parse_date_time_field()?;

        let syntax = if self.parse_keyword(Keyword::FROM) {
            ExtractSyntax::From
        } else if self.dialect.supports_extract_comma_syntax() && self.consume_token(&Token::Comma)
        {
            ExtractSyntax::Comma
        } else {
            return Err(ParserError::ParserError(
                "Expected 'FROM' or ','".to_string(),
            ));
        };

        let expr = self.parse_expr()?;
        self.expect_token(&Token::RParen)?;
        Ok(Expr::Extract {
            field,
            expr: Box::new(expr),
            syntax,
        })
    }

    /// Parse a `CEIL` or `FLOOR` expression.
    pub fn parse_ceil_floor_expr(&mut self, is_ceil: bool) -> Result<Expr, ParserError> {
        self.expect_token(&Token::LParen)?;
        let expr = self.parse_expr()?;
        // Parse `CEIL/FLOOR(expr)`
        let field = if self.parse_keyword(Keyword::TO) {
            // Parse `CEIL/FLOOR(expr TO DateTimeField)`
            CeilFloorKind::DateTimeField(self.parse_date_time_field()?)
        } else if self.consume_token(&Token::Comma) {
            // Parse `CEIL/FLOOR(expr, scale)`
            let v = self.parse_value()?;
            if matches!(v.value, Value::Number(_, _)) {
                CeilFloorKind::Scale(v)
            } else {
                return Err(ParserError::ParserError(
                    "Scale field can only be of number type".to_string(),
                ));
            }
        } else {
            CeilFloorKind::DateTimeField(DateTimeField::NoDateTime)
        };
        self.expect_token(&Token::RParen)?;
        if is_ceil {
            Ok(Expr::Ceil {
                expr: Box::new(expr),
                field,
            })
        } else {
            Ok(Expr::Floor {
                expr: Box::new(expr),
                field,
            })
        }
    }

    /// Parse a `POSITION` expression.
    pub fn parse_position_expr(&mut self, ident: Ident) -> Result<Expr, ParserError> {
        let between_prec = self.dialect.prec_value(Precedence::Between);
        // Memoize a failed `IN` form: the function-call fallback re-parses the
        // same argument, so nested `POSITION(POSITION(...))` would take 2^N.
        let memo_key = (self.index, self.state);
        if self.failed_position_syntax_positions.contains(&memo_key) {
            return self.parse_function(ObjectName::from(vec![ident]));
        }
        let position_expr = self.maybe_parse(|p| {
            // PARSE SELECT POSITION('@' in field)
            p.expect_token(&Token::LParen)?;

            // Parse the subexpr till the IN keyword
            let expr = p.parse_subexpr(between_prec)?;
            p.expect_keyword_is(Keyword::IN)?;
            let from = p.parse_expr()?;
            p.expect_token(&Token::RParen)?;
            Ok(Expr::Position {
                expr: Box::new(expr),
                r#in: Box::new(from),
            })
        })?;
        match position_expr {
            Some(expr) => Ok(expr),
            // Snowflake supports `position` as an ordinary function call
            // without the special `IN` syntax.
            None => {
                self.failed_position_syntax_positions.insert(memo_key);
                self.parse_function(ObjectName::from(vec![ident]))
            }
        }
    }

    /// Parse `SUBSTRING`/`SUBSTR` expressions: `SUBSTRING(expr FROM start FOR length)` or `SUBSTR(expr, start, length)`.
    pub fn parse_substring(&mut self) -> Result<Expr, ParserError> {
        let shorthand = match self.expect_one_of_keywords(&[Keyword::SUBSTR, Keyword::SUBSTRING])? {
            Keyword::SUBSTR => true,
            Keyword::SUBSTRING => false,
            _ => {
                self.prev_token();
                return self.expected_ref("SUBSTR or SUBSTRING", self.peek_token_ref());
            }
        };
        self.expect_token(&Token::LParen)?;
        let expr = self.parse_expr()?;
        let mut from_expr = None;
        let special = self.consume_token(&Token::Comma);
        if special || self.parse_keyword(Keyword::FROM) {
            from_expr = Some(self.parse_expr()?);
        }

        let mut to_expr = None;
        if self.parse_keyword(Keyword::FOR) || self.consume_token(&Token::Comma) {
            to_expr = Some(self.parse_expr()?);
        }
        self.expect_token(&Token::RParen)?;

        Ok(Expr::Substring {
            expr: Box::new(expr),
            substring_from: from_expr.map(Box::new),
            substring_for: to_expr.map(Box::new),
            special,
            shorthand,
        })
    }

    /// Parse an OVERLAY expression.
    ///
    /// See [Expr::Overlay]
    pub fn parse_overlay_expr(&mut self) -> Result<Expr, ParserError> {
        // PARSE OVERLAY (EXPR PLACING EXPR FROM 1 [FOR 3])
        self.expect_token(&Token::LParen)?;
        let expr = self.parse_expr()?;
        self.expect_keyword_is(Keyword::PLACING)?;
        let what_expr = self.parse_expr()?;
        self.expect_keyword_is(Keyword::FROM)?;
        let from_expr = self.parse_expr()?;
        let mut for_expr = None;
        if self.parse_keyword(Keyword::FOR) {
            for_expr = Some(self.parse_expr()?);
        }
        self.expect_token(&Token::RParen)?;

        Ok(Expr::Overlay {
            expr: Box::new(expr),
            overlay_what: Box::new(what_expr),
            overlay_from: Box::new(from_expr),
            overlay_for: for_expr.map(Box::new),
        })
    }

    /// ```sql
    /// TRIM ([WHERE] ['text' FROM] 'text')
    /// TRIM ('text')
    /// TRIM(<expr>, [, characters]) -- PostgreSQL, DuckDB, Snowflake, BigQuery, Generic
    /// ```
    pub fn parse_trim_expr(&mut self) -> Result<Expr, ParserError> {
        self.expect_token(&Token::LParen)?;
        let mut trim_where = None;
        if let Token::Word(word) = &self.peek_token_ref().token {
            if [Keyword::BOTH, Keyword::LEADING, Keyword::TRAILING].contains(&word.keyword) {
                trim_where = Some(self.parse_trim_where()?);
            }
        }
        if self.dialect.supports_comma_separated_trim() && self.parse_keyword(Keyword::FROM) {
            let expr = self.parse_expr()?;
            let trim_characters = if self.consume_token(&Token::Comma) {
                Some(self.parse_comma_separated(Parser::parse_expr)?)
            } else {
                None
            };
            self.expect_token(&Token::RParen)?;
            return Ok(Expr::Trim {
                expr: Box::new(expr),
                trim_where,
                trim_what: None,
                trim_characters,
            });
        }
        let expr = self.parse_expr()?;
        if self.parse_keyword(Keyword::FROM) {
            let trim_what = Box::new(expr);
            let expr = self.parse_expr()?;
            self.expect_token(&Token::RParen)?;
            Ok(Expr::Trim {
                expr: Box::new(expr),
                trim_where,
                trim_what: Some(trim_what),
                trim_characters: None,
            })
        } else if self.dialect.supports_comma_separated_trim() && self.consume_token(&Token::Comma)
        {
            let characters = self.parse_comma_separated(Parser::parse_expr)?;
            self.expect_token(&Token::RParen)?;
            Ok(Expr::Trim {
                expr: Box::new(expr),
                trim_where,
                trim_what: None,
                trim_characters: Some(characters),
            })
        } else {
            self.expect_token(&Token::RParen)?;
            Ok(Expr::Trim {
                expr: Box::new(expr),
                trim_where,
                trim_what: None,
                trim_characters: None,
            })
        }
    }

    /// Parse the `WHERE` field for a `TRIM` expression.
    ///
    /// See [TrimWhereField]
    pub fn parse_trim_where(&mut self) -> Result<TrimWhereField, ParserError> {
        let next_token = self.next_token();
        match &next_token.token {
            Token::Word(w) => match w.keyword {
                Keyword::BOTH => Ok(TrimWhereField::Both),
                Keyword::LEADING => Ok(TrimWhereField::Leading),
                Keyword::TRAILING => Ok(TrimWhereField::Trailing),
                _ => self.expected("trim_where field", next_token)?,
            },
            _ => self.expected("trim_where field", next_token),
        }
    }

    /// Parses an array expression `[ex1, ex2, ..]`
    /// if `named` is `true`, came from an expression like  `ARRAY[ex1, ex2]`
    pub fn parse_array_expr(&mut self, named: bool) -> Result<Expr, ParserError> {
        let exprs = self.parse_comma_separated0(Parser::parse_expr, Token::RBracket)?;
        self.expect_token(&Token::RBracket)?;
        Ok(Expr::Array(Array { elem: exprs, named }))
    }

    /// Parse the `ON OVERFLOW` clause for `LISTAGG`.
    ///
    /// See [`ListAggOnOverflow`]
    pub fn parse_listagg_on_overflow(&mut self) -> Result<Option<ListAggOnOverflow>, ParserError> {
        if self.parse_keywords(&[Keyword::ON, Keyword::OVERFLOW]) {
            if self.parse_keyword(Keyword::ERROR) {
                Ok(Some(ListAggOnOverflow::Error))
            } else {
                self.expect_keyword_is(Keyword::TRUNCATE)?;
                let filler = match &self.peek_token_ref().token {
                    Token::Word(w)
                        if w.keyword == Keyword::WITH || w.keyword == Keyword::WITHOUT =>
                    {
                        None
                    }
                    Token::SingleQuotedString(_)
                    | Token::EscapedStringLiteral(_)
                    | Token::UnicodeStringLiteral(_)
                    | Token::NationalStringLiteral(_)
                    | Token::QuoteDelimitedStringLiteral(_)
                    | Token::NationalQuoteDelimitedStringLiteral(_)
                    | Token::HexStringLiteral(_) => Some(Box::new(self.parse_expr()?)),
                    _ => self.expected_ref(
                        "either filler, WITH, or WITHOUT in LISTAGG",
                        self.peek_token_ref(),
                    )?,
                };
                let with_count = self.parse_keyword(Keyword::WITH);
                if !with_count && !self.parse_keyword(Keyword::WITHOUT) {
                    self.expected_ref("either WITH or WITHOUT in LISTAGG", self.peek_token_ref())?;
                }
                self.expect_keyword_is(Keyword::COUNT)?;
                Ok(Some(ListAggOnOverflow::Truncate { filler, with_count }))
            }
        } else {
            Ok(None)
        }
    }

    /// Parse a date/time field for `EXTRACT`, interval qualifiers, and ceil/floor operations.
    ///
    /// `EXTRACT` supports a wider set of date/time fields than interval qualifiers,
    /// so this function may need to be split in two.
    ///
    /// See [`DateTimeField`]
    pub fn parse_date_time_field(&mut self) -> Result<DateTimeField, ParserError> {
        let next_token = self.next_token();
        match &next_token.token {
            Token::Word(w) => match w.keyword {
                Keyword::YEAR => Ok(DateTimeField::Year),
                Keyword::YEARS => Ok(DateTimeField::Years),
                Keyword::MONTH => Ok(DateTimeField::Month),
                Keyword::MONTHS => Ok(DateTimeField::Months),
                Keyword::WEEK => {
                    let week_day = if dialect_of!(self is BigQueryDialect | GenericDialect)
                        && self.consume_token(&Token::LParen)
                    {
                        let week_day = self.parse_identifier()?;
                        self.expect_token(&Token::RParen)?;
                        Some(week_day)
                    } else {
                        None
                    };
                    Ok(DateTimeField::Week(week_day))
                }
                Keyword::WEEKS => Ok(DateTimeField::Weeks),
                Keyword::DAY => Ok(DateTimeField::Day),
                Keyword::DAYOFWEEK => Ok(DateTimeField::DayOfWeek),
                Keyword::DAYOFYEAR => Ok(DateTimeField::DayOfYear),
                Keyword::DAYS => Ok(DateTimeField::Days),
                Keyword::DATE => Ok(DateTimeField::Date),
                Keyword::DATETIME => Ok(DateTimeField::Datetime),
                Keyword::HOUR => Ok(DateTimeField::Hour),
                Keyword::HOURS => Ok(DateTimeField::Hours),
                Keyword::MINUTE => Ok(DateTimeField::Minute),
                Keyword::MINUTES => Ok(DateTimeField::Minutes),
                Keyword::SECOND => Ok(DateTimeField::Second),
                Keyword::SECONDS => Ok(DateTimeField::Seconds),
                Keyword::CENTURY => Ok(DateTimeField::Century),
                Keyword::DECADE => Ok(DateTimeField::Decade),
                Keyword::DOY => Ok(DateTimeField::Doy),
                Keyword::DOW => Ok(DateTimeField::Dow),
                Keyword::EPOCH => Ok(DateTimeField::Epoch),
                Keyword::ISODOW => Ok(DateTimeField::Isodow),
                Keyword::ISOYEAR => Ok(DateTimeField::Isoyear),
                Keyword::ISOWEEK => Ok(DateTimeField::IsoWeek),
                Keyword::JULIAN => Ok(DateTimeField::Julian),
                Keyword::MICROSECOND => Ok(DateTimeField::Microsecond),
                Keyword::MICROSECONDS => Ok(DateTimeField::Microseconds),
                Keyword::MILLENIUM => Ok(DateTimeField::Millenium),
                Keyword::MILLENNIUM => Ok(DateTimeField::Millennium),
                Keyword::MILLISECOND => Ok(DateTimeField::Millisecond),
                Keyword::MILLISECONDS => Ok(DateTimeField::Milliseconds),
                Keyword::NANOSECOND => Ok(DateTimeField::Nanosecond),
                Keyword::NANOSECONDS => Ok(DateTimeField::Nanoseconds),
                Keyword::QUARTER => Ok(DateTimeField::Quarter),
                Keyword::TIME => Ok(DateTimeField::Time),
                Keyword::TIMEZONE => Ok(DateTimeField::Timezone),
                Keyword::TIMEZONE_ABBR => Ok(DateTimeField::TimezoneAbbr),
                Keyword::TIMEZONE_HOUR => Ok(DateTimeField::TimezoneHour),
                Keyword::TIMEZONE_MINUTE => Ok(DateTimeField::TimezoneMinute),
                Keyword::TIMEZONE_REGION => Ok(DateTimeField::TimezoneRegion),
                _ if self.dialect.allow_extract_custom() => {
                    self.prev_token();
                    let custom = self.parse_identifier()?;
                    Ok(DateTimeField::Custom(custom))
                }
                _ => self.expected("date/time field", next_token),
            },
            Token::SingleQuotedString(_) if self.dialect.allow_extract_single_quotes() => {
                self.prev_token();
                let custom = self.parse_identifier()?;
                Ok(DateTimeField::Custom(custom))
            }
            _ => self.expected("date/time field", next_token),
        }
    }

    /// Parse a `NOT` expression.
    ///
    /// Represented in the AST as `Expr::UnaryOp` with `UnaryOperator::Not`.
    pub fn parse_not(&mut self) -> Result<Expr, ParserError> {
        match &self.peek_token_ref().token {
            Token::Word(w) => match w.keyword {
                Keyword::EXISTS => {
                    let negated = true;
                    let _ = self.parse_keyword(Keyword::EXISTS);
                    self.parse_exists_expr(negated)
                }
                _ => Ok(Expr::UnaryOp {
                    op: UnaryOperator::Not,
                    expr: Box::new(
                        self.parse_subexpr(self.dialect.prec_value(Precedence::UnaryNot))?,
                    ),
                }),
            },
            _ => Ok(Expr::UnaryOp {
                op: UnaryOperator::Not,
                expr: Box::new(self.parse_subexpr(self.dialect.prec_value(Precedence::UnaryNot))?),
            }),
        }
    }

    /// Parse expression types that start with a left brace '{'.
    /// Examples:
    /// ```sql
    /// -- Dictionary expr.
    /// {'key1': 'value1', 'key2': 'value2'}
    ///
    /// -- Function call using the ODBC syntax.
    /// { fn CONCAT('foo', 'bar') }
    /// ```
    fn parse_lbrace_expr(&mut self) -> Result<Expr, ParserError> {
        let token = self.expect_token(&Token::LBrace)?;

        if let Some(fn_expr) = self.maybe_parse_odbc_body()? {
            self.expect_token(&Token::RBrace)?;
            return Ok(fn_expr);
        }

        if self.dialect.supports_dictionary_syntax() {
            self.prev_token(); // Put back the '{'
            return self.parse_dictionary();
        }

        self.expected("an expression", token)
    }

    /// Parses fulltext expressions [`sqlparser::ast::Expr::MatchAgainst`]
    ///
    /// # Errors
    /// This method will raise an error if the column list is empty or with invalid identifiers,
    /// the match expression is not a literal string, or if the search modifier is not valid.
    pub fn parse_match_against(&mut self) -> Result<Expr, ParserError> {
        let columns = self.parse_parenthesized_qualified_column_list(Mandatory, false)?;

        self.expect_keyword_is(Keyword::AGAINST)?;

        self.expect_token(&Token::LParen)?;

        // MySQL is too permissive about the value, IMO we can't validate it perfectly on syntax level.
        let match_value = self.parse_value()?;

        let in_natural_language_mode_keywords = &[
            Keyword::IN,
            Keyword::NATURAL,
            Keyword::LANGUAGE,
            Keyword::MODE,
        ];

        let with_query_expansion_keywords = &[Keyword::WITH, Keyword::QUERY, Keyword::EXPANSION];

        let in_boolean_mode_keywords = &[Keyword::IN, Keyword::BOOLEAN, Keyword::MODE];

        let opt_search_modifier = if self.parse_keywords(in_natural_language_mode_keywords) {
            if self.parse_keywords(with_query_expansion_keywords) {
                Some(SearchModifier::InNaturalLanguageModeWithQueryExpansion)
            } else {
                Some(SearchModifier::InNaturalLanguageMode)
            }
        } else if self.parse_keywords(in_boolean_mode_keywords) {
            Some(SearchModifier::InBooleanMode)
        } else if self.parse_keywords(with_query_expansion_keywords) {
            Some(SearchModifier::WithQueryExpansion)
        } else {
            None
        };

        self.expect_token(&Token::RParen)?;

        Ok(Expr::MatchAgainst {
            columns,
            match_value,
            opt_search_modifier,
        })
    }

    /// Parse an `INTERVAL` expression.
    ///
    /// Some syntactically valid intervals:
    ///
    /// ```sql
    ///   1. INTERVAL '1' DAY
    ///   2. INTERVAL '1-1' YEAR TO MONTH
    ///   3. INTERVAL '1' SECOND
    ///   4. INTERVAL '1:1:1.1' HOUR (5) TO SECOND (5)
    ///   5. INTERVAL '1.1' SECOND (2, 2)
    ///   6. INTERVAL '1:1' HOUR (5) TO MINUTE (5)
    ///   7. (MySql & BigQuery only): INTERVAL 1 DAY
    /// ```
    ///
    /// Note that we do not currently attempt to parse the quoted value.
    #[cfg_attr(feature = "recursive-protection", recursive::recursive)]
    pub fn parse_interval(&mut self) -> Result<Expr, ParserError> {
        let _guard = self.recursion_counter.try_decrease()?;

        // The SQL standard allows an optional sign before the value string, but
        // it is not clear if any implementations support that syntax, so we
        // don't currently try to parse it. (The sign can instead be included
        // inside the value string.)

        // to match the different flavours of INTERVAL syntax, we only allow expressions
        // if the dialect requires an interval qualifier,
        // see https://github.com/sqlparser-rs/sqlparser-rs/pull/1398 for more details
        let value = if self.dialect.require_interval_qualifier() {
            // parse a whole expression so `INTERVAL 1 + 1 DAY` is valid
            self.parse_expr()?
        } else {
            // parse a prefix expression so `INTERVAL 1 DAY` is valid, but `INTERVAL 1 + 1 DAY` is not
            // this also means that `INTERVAL '5 days' > INTERVAL '1 day'` treated properly
            self.parse_prefix()?
        };

        // Following the string literal is a qualifier which indicates the units
        // of the duration specified in the string literal.
        //
        // Note that PostgreSQL allows omitting the qualifier, so we provide
        // this more general implementation.
        let leading_field = if self.next_token_is_temporal_unit() {
            Some(self.parse_date_time_field()?)
        } else if self.dialect.require_interval_qualifier() {
            return parser_err!(
                "INTERVAL requires a unit after the literal value",
                self.peek_token_ref().span.start
            );
        } else {
            None
        };

        let (leading_precision, last_field, fsec_precision) =
            if leading_field == Some(DateTimeField::Second) {
                // SQL mandates special syntax for `SECOND TO SECOND` literals.
                // Instead of
                //     `SECOND [(<leading precision>)] TO SECOND[(<fractional seconds precision>)]`
                // one must use the special format:
                //     `SECOND [( <leading precision> [ , <fractional seconds precision>] )]`
                let last_field = None;
                let (leading_precision, fsec_precision) = self.parse_optional_precision_scale()?;
                (leading_precision, last_field, fsec_precision)
            } else {
                let leading_precision = self.parse_optional_precision()?;
                if self.parse_keyword(Keyword::TO) {
                    let last_field = Some(self.parse_date_time_field()?);
                    let fsec_precision = if last_field == Some(DateTimeField::Second) {
                        self.parse_optional_precision()?
                    } else {
                        None
                    };
                    (leading_precision, last_field, fsec_precision)
                } else {
                    (leading_precision, None, None)
                }
            };

        Ok(Expr::Interval(Interval {
            value: Box::new(value),
            leading_field,
            leading_precision,
            last_field,
            fractional_seconds_precision: fsec_precision,
        }))
    }

    /// Peek at the next token and determine if it is a temporal unit
    /// like `second`.
    pub fn next_token_is_temporal_unit(&mut self) -> bool {
        if let Token::Word(word) = &self.peek_token_ref().token {
            matches!(
                word.keyword,
                Keyword::YEAR
                    | Keyword::YEARS
                    | Keyword::MONTH
                    | Keyword::MONTHS
                    | Keyword::WEEK
                    | Keyword::WEEKS
                    | Keyword::DAY
                    | Keyword::DAYS
                    | Keyword::HOUR
                    | Keyword::HOURS
                    | Keyword::MINUTE
                    | Keyword::MINUTES
                    | Keyword::SECOND
                    | Keyword::SECONDS
                    | Keyword::CENTURY
                    | Keyword::DECADE
                    | Keyword::DOW
                    | Keyword::DOY
                    | Keyword::EPOCH
                    | Keyword::ISODOW
                    | Keyword::ISOYEAR
                    | Keyword::JULIAN
                    | Keyword::MICROSECOND
                    | Keyword::MICROSECONDS
                    | Keyword::MILLENIUM
                    | Keyword::MILLENNIUM
                    | Keyword::MILLISECOND
                    | Keyword::MILLISECONDS
                    | Keyword::NANOSECOND
                    | Keyword::NANOSECONDS
                    | Keyword::QUARTER
                    | Keyword::TIMEZONE
                    | Keyword::TIMEZONE_HOUR
                    | Keyword::TIMEZONE_MINUTE
            )
        } else {
            false
        }
    }

    /// Syntax
    /// ```sql
    /// -- typed
    /// STRUCT<[field_name] field_type, ...>( expr1 [, ... ])
    /// -- typeless
    /// STRUCT( expr1 [AS field_name] [, ... ])
    /// ```
    fn parse_struct_literal(&mut self) -> Result<Expr, ParserError> {
        // Parse the fields definition if exist `<[field_name] field_type, ...>`
        self.prev_token();
        let (fields, trailing_bracket) =
            self.parse_struct_type_def(Self::parse_struct_field_def)?;
        if trailing_bracket.0 {
            return parser_err!(
                "unmatched > in STRUCT literal",
                self.peek_token_ref().span.start
            );
        }

        // Parse the struct values `(expr1 [, ... ])`
        self.expect_token(&Token::LParen)?;
        let values = self
            .parse_comma_separated(|parser| parser.parse_struct_field_expr(!fields.is_empty()))?;
        self.expect_token(&Token::RParen)?;

        Ok(Expr::Struct { values, fields })
    }

    /// Parse an expression value for a struct literal
    /// Syntax
    /// ```sql
    /// expr [AS name]
    /// ```
    ///
    /// For biquery [1], Parameter typed_syntax is set to true if the expression
    /// is to be parsed as a field expression declared using typed
    /// struct syntax [2], and false if using typeless struct syntax [3].
    ///
    /// [1]: https://cloud.google.com/bigquery/docs/reference/standard-sql/data-types#constructing_a_struct
    /// [2]: https://cloud.google.com/bigquery/docs/reference/standard-sql/data-types#typed_struct_syntax
    /// [3]: https://cloud.google.com/bigquery/docs/reference/standard-sql/data-types#typeless_struct_syntax
    fn parse_struct_field_expr(&mut self, typed_syntax: bool) -> Result<Expr, ParserError> {
        let expr = self.parse_expr()?;
        if self.parse_keyword(Keyword::AS) {
            if typed_syntax {
                return parser_err!("Typed syntax does not allow AS", {
                    self.prev_token();
                    self.peek_token_ref().span.start
                });
            }
            let field_name = self.parse_identifier()?;
            Ok(Expr::Named {
                expr: expr.into(),
                name: field_name,
            })
        } else {
            Ok(expr)
        }
    }

    /// Parse a Struct type definition as a sequence of field-value pairs.
    /// The syntax of the Struct elem differs by dialect so it is customised
    /// by the `elem_parser` argument.
    ///
    /// Syntax
    /// ```sql
    /// Hive:
    /// STRUCT<field_name: field_type>
    ///
    /// BigQuery:
    /// STRUCT<[field_name] field_type>
    /// ```
    fn parse_struct_type_def<F>(
        &mut self,
        mut elem_parser: F,
    ) -> Result<(Vec<StructField>, MatchedTrailingBracket), ParserError>
    where
        F: FnMut(&mut Parser<'a>) -> Result<(StructField, MatchedTrailingBracket), ParserError>,
    {
        self.expect_keyword_is(Keyword::STRUCT)?;

        // Nothing to do if we have no type information.
        if self.peek_token_ref().token != Token::Lt {
            return Ok((Default::default(), false.into()));
        }
        self.next_token();

        let mut field_defs = vec![];
        let trailing_bracket = loop {
            let (def, trailing_bracket) = elem_parser(self)?;
            field_defs.push(def);
            // The struct field definition is finished if it occurs `>>` or comma.
            if trailing_bracket.0 || !self.consume_token(&Token::Comma) {
                break trailing_bracket;
            }
        };

        Ok((
            field_defs,
            self.expect_closing_angle_bracket(trailing_bracket)?,
        ))
    }

    /// Duckdb Struct Data Type <https://duckdb.org/docs/sql/data_types/struct.html#retrieving-from-structs>
    fn parse_duckdb_struct_type_def(&mut self) -> Result<Vec<StructField>, ParserError> {
        self.expect_keyword_is(Keyword::STRUCT)?;
        self.expect_token(&Token::LParen)?;
        let struct_body = self.parse_comma_separated(|parser| {
            let field_name = parser.parse_identifier()?;
            let field_type = parser.parse_data_type()?;

            Ok(StructField {
                field_name: Some(field_name),
                field_type,
                options: None,
            })
        });
        self.expect_token(&Token::RParen)?;
        struct_body
    }

    /// Parse a field definition in a [struct] or [tuple].
    /// Syntax:
    ///
    /// ```sql
    /// [field_name] field_type
    /// field_name: field_type
    /// ```
    ///
    /// [struct]: https://cloud.google.com/bigquery/docs/reference/standard-sql/data-types#declaring_a_struct_type
    /// [tuple]: https://clickhouse.com/docs/en/sql-reference/data-types/tuple
    /// [databricks]: https://docs.databricks.com/en/sql/language-manual/data-types/struct-type.html
    fn parse_struct_field_def(
        &mut self,
    ) -> Result<(StructField, MatchedTrailingBracket), ParserError> {
        // Look beyond the next item to infer whether both field name
        // and type are specified.
        let is_named_field = matches!(
            (self.peek_nth_token(0).token, self.peek_nth_token(1).token),
            (Token::Word(_), Token::Word(_)) | (Token::Word(_), Token::Colon)
        );

        let field_name = if is_named_field {
            let name = self.parse_identifier()?;
            let _ = self.consume_token(&Token::Colon);
            Some(name)
        } else {
            None
        };

        let (field_type, trailing_bracket) = self.parse_data_type_with_optional_collation()?;

        let options = self.maybe_parse_options(Keyword::OPTIONS)?;
        Ok((
            StructField {
                field_name,
                field_type,
                options,
            },
            trailing_bracket,
        ))
    }

    /// DuckDB specific: Parse a Union type definition as a sequence of field-value pairs.
    ///
    /// Syntax:
    ///
    /// ```sql
    /// UNION(field_name field_type[,...])
    /// ```
    ///
    /// [1]: https://duckdb.org/docs/sql/data_types/union.html
    fn parse_union_type_def(&mut self) -> Result<Vec<UnionField>, ParserError> {
        self.expect_keyword_is(Keyword::UNION)?;

        self.expect_token(&Token::LParen)?;

        let fields = self.parse_comma_separated(|p| {
            Ok(UnionField {
                field_name: p.parse_identifier()?,
                field_type: p.parse_data_type()?,
            })
        })?;

        self.expect_token(&Token::RParen)?;

        Ok(fields)
    }

    /// DuckDB and ClickHouse specific: Parse a duckdb [dictionary] or a clickhouse [map] setting
    ///
    /// Syntax:
    ///
    /// ```sql
    /// {'field_name': expr1[, ... ]}
    /// ```
    ///
    /// [dictionary]: https://duckdb.org/docs/sql/data_types/struct#creating-structs
    /// [map]: https://clickhouse.com/docs/operations/settings/settings#additional_table_filters
    fn parse_dictionary(&mut self) -> Result<Expr, ParserError> {
        self.expect_token(&Token::LBrace)?;

        let fields = self.parse_comma_separated0(Self::parse_dictionary_field, Token::RBrace)?;

        self.expect_token(&Token::RBrace)?;

        Ok(Expr::Dictionary(fields))
    }

    /// Parse a field for a duckdb [dictionary] or a clickhouse [map] setting
    ///
    /// Syntax
    ///
    /// ```sql
    /// 'name': expr
    /// ```
    ///
    /// [dictionary]: https://duckdb.org/docs/sql/data_types/struct#creating-structs
    /// [map]: https://clickhouse.com/docs/operations/settings/settings#additional_table_filters
    fn parse_dictionary_field(&mut self) -> Result<DictionaryField, ParserError> {
        let key = self.parse_identifier()?;

        self.expect_token(&Token::Colon)?;

        let expr = self.parse_expr()?;

        Ok(DictionaryField {
            key,
            value: Box::new(expr),
        })
    }

    /// DuckDB specific: Parse a duckdb [map]
    ///
    /// Syntax:
    ///
    /// ```sql
    /// Map {key1: value1[, ... ]}
    /// ```
    ///
    /// [map]: https://duckdb.org/docs/sql/data_types/map.html#creating-maps
    fn parse_duckdb_map_literal(&mut self) -> Result<Expr, ParserError> {
        self.expect_token(&Token::LBrace)?;
        let fields = self.parse_comma_separated0(Self::parse_duckdb_map_field, Token::RBrace)?;
        self.expect_token(&Token::RBrace)?;
        Ok(Expr::Map(Map { entries: fields }))
    }

    /// Parse a field for a duckdb [map]
    ///
    /// Syntax
    ///
    /// ```sql
    /// key: value
    /// ```
    ///
    /// [map]: https://duckdb.org/docs/sql/data_types/map.html#creating-maps
    fn parse_duckdb_map_field(&mut self) -> Result<MapEntry, ParserError> {
        // Stop before `:` so it can act as a key/value separator
        let key = self.parse_subexpr(self.dialect.prec_value(Precedence::Colon))?;

        self.expect_token(&Token::Colon)?;

        let value = self.parse_expr()?;

        Ok(MapEntry {
            key: Box::new(key),
            value: Box::new(value),
        })
    }

    /// Parse a parenthesized MAP type (ClickHouse or Snowflake).
    ///
    /// Syntax
    ///
    /// ```sql
    /// Map(key_data_type, value_data_type)
    /// ```
    ///
    /// [map]: https://clickhouse.com/docs/en/sql-reference/data-types/map
    fn parse_parenthesized_map_type_def(
        &mut self,
    ) -> Result<(DataType, DataType, bool), ParserError> {
        self.expect_keyword_is(Keyword::MAP)?;
        self.expect_token(&Token::LParen)?;
        let key_data_type = self.parse_data_type()?;
        self.expect_token(&Token::Comma)?;
        let value_data_type = self.parse_data_type()?;
        let value_not_null = self.dialect.supports_map_value_not_null()
            && self.parse_keywords(&[Keyword::NOT, Keyword::NULL]);
        self.expect_token(&Token::RParen)?;

        Ok((key_data_type, value_data_type, value_not_null))
    }

    /// Parse clickhouse [tuple]
    ///
    /// Syntax
    ///
    /// ```sql
    /// Tuple([field_name] field_type, ...)
    /// ```
    ///
    /// [tuple]: https://clickhouse.com/docs/en/sql-reference/data-types/tuple
    fn parse_click_house_tuple_def(&mut self) -> Result<Vec<StructField>, ParserError> {
        self.expect_keyword_is(Keyword::TUPLE)?;
        self.expect_token(&Token::LParen)?;
        let mut field_defs = vec![];
        loop {
            let (def, _) = self.parse_struct_field_def()?;
            field_defs.push(def);
            if !self.consume_token(&Token::Comma) {
                break;
            }
        }
        self.expect_token(&Token::RParen)?;

        Ok(field_defs)
    }

    /// For nested types that use the angle bracket syntax, this matches either
    /// `>`, `>>` or nothing depending on which variant is expected (specified by the previously
    /// matched `trailing_bracket` argument). It returns whether there is a trailing
    /// left to be matched - (i.e. if '>>' was matched).
    fn expect_closing_angle_bracket(
        &mut self,
        trailing_bracket: MatchedTrailingBracket,
    ) -> Result<MatchedTrailingBracket, ParserError> {
        let trailing_bracket = if !trailing_bracket.0 {
            match &self.peek_token_ref().token {
                Token::Gt => {
                    self.next_token();
                    false.into()
                }
                Token::ShiftRight => {
                    self.next_token();
                    true.into()
                }
                _ => return self.expected_ref(">", self.peek_token_ref()),
            }
        } else {
            false.into()
        };

        Ok(trailing_bracket)
    }

    /// Parse an operator following an expression
    pub fn parse_infix(&mut self, expr: Expr, precedence: u8) -> Result<Expr, ParserError> {
        // allow the dialect to override infix parsing
        if let Some(infix) = self.dialect.parse_infix(self, &expr, precedence) {
            return infix;
        }

        let dialect = self.dialect;

        self.advance_token();
        let tok = self.get_current_token();
        debug!("infix: {tok:?}");
        let tok_index = self.get_current_index();
        let span = tok.span;
        let regular_binary_operator = match &tok.token {
            Token::Spaceship => Some(BinaryOperator::Spaceship),
            Token::DoubleEq => Some(BinaryOperator::Eq),
            Token::Assignment => Some(BinaryOperator::Assignment),
            Token::Eq => Some(BinaryOperator::Eq),
            Token::Neq => Some(BinaryOperator::NotEq),
            Token::Gt => Some(BinaryOperator::Gt),
            Token::GtEq => Some(BinaryOperator::GtEq),
            Token::Lt => Some(BinaryOperator::Lt),
            Token::LtEq => Some(BinaryOperator::LtEq),
            Token::Plus => Some(BinaryOperator::Plus),
            Token::Minus => Some(BinaryOperator::Minus),
            Token::Mul => Some(BinaryOperator::Multiply),
            Token::Mod => Some(BinaryOperator::Modulo),
            Token::StringConcat => Some(BinaryOperator::StringConcat),
            Token::Pipe => Some(BinaryOperator::BitwiseOr),
            Token::Caret => {
                // In PostgreSQL, ^ stands for the exponentiation operation,
                // and # stands for XOR. See https://www.postgresql.org/docs/current/functions-math.html
                if dialect_is!(dialect is PostgreSqlDialect) {
                    Some(BinaryOperator::PGExp)
                } else {
                    Some(BinaryOperator::BitwiseXor)
                }
            }
            Token::Ampersand => Some(BinaryOperator::BitwiseAnd),
            Token::Div => Some(BinaryOperator::Divide),
            Token::DuckIntDiv if dialect_is!(dialect is DuckDbDialect | GenericDialect) => {
                Some(BinaryOperator::DuckIntegerDivide)
            }
            Token::ShiftLeft if dialect.supports_bitwise_shift_operators() => {
                Some(BinaryOperator::PGBitwiseShiftLeft)
            }
            Token::ShiftRight if dialect.supports_bitwise_shift_operators() => {
                Some(BinaryOperator::PGBitwiseShiftRight)
            }
            Token::Sharp if dialect_is!(dialect is PostgreSqlDialect | RedshiftSqlDialect) => {
                Some(BinaryOperator::PGBitwiseXor)
            }
            Token::Overlap if dialect_is!(dialect is PostgreSqlDialect | RedshiftSqlDialect) => {
                Some(BinaryOperator::PGOverlap)
            }
            Token::Overlap if dialect_is!(dialect is PostgreSqlDialect | GenericDialect) => {
                Some(BinaryOperator::PGOverlap)
            }
            Token::Overlap if dialect.supports_double_ampersand_operator() => {
                Some(BinaryOperator::And)
            }
            Token::CaretAt if dialect_is!(dialect is PostgreSqlDialect | GenericDialect) => {
                Some(BinaryOperator::PGStartsWith)
            }
            Token::Tilde => Some(BinaryOperator::PGRegexMatch),
            Token::TildeAsterisk => Some(BinaryOperator::PGRegexIMatch),
            Token::ExclamationMarkTilde => Some(BinaryOperator::PGRegexNotMatch),
            Token::ExclamationMarkTildeAsterisk => Some(BinaryOperator::PGRegexNotIMatch),
            Token::DoubleTilde => Some(BinaryOperator::PGLikeMatch),
            Token::DoubleTildeAsterisk => Some(BinaryOperator::PGILikeMatch),
            Token::ExclamationMarkDoubleTilde => Some(BinaryOperator::PGNotLikeMatch),
            Token::ExclamationMarkDoubleTildeAsterisk => Some(BinaryOperator::PGNotILikeMatch),
            Token::Arrow => Some(BinaryOperator::Arrow),
            Token::LongArrow => Some(BinaryOperator::LongArrow),
            Token::HashArrow => Some(BinaryOperator::HashArrow),
            Token::HashLongArrow => Some(BinaryOperator::HashLongArrow),
            Token::AtArrow => Some(BinaryOperator::AtArrow),
            Token::ArrowAt => Some(BinaryOperator::ArrowAt),
            Token::HashMinus => Some(BinaryOperator::HashMinus),
            Token::AtQuestion => Some(BinaryOperator::AtQuestion),
            Token::AtAt => Some(BinaryOperator::AtAt),
            Token::Question => Some(BinaryOperator::Question),
            Token::QuestionAnd => Some(BinaryOperator::QuestionAnd),
            Token::QuestionPipe => Some(BinaryOperator::QuestionPipe),
            Token::CustomBinaryOperator(s) => Some(BinaryOperator::Custom(s.clone())),
            Token::DoubleSharp if self.dialect.supports_geometric_types() => {
                Some(BinaryOperator::DoubleHash)
            }

            Token::AmpersandLeftAngleBracket if self.dialect.supports_geometric_types() => {
                Some(BinaryOperator::AndLt)
            }
            Token::AmpersandRightAngleBracket if self.dialect.supports_geometric_types() => {
                Some(BinaryOperator::AndGt)
            }
            Token::QuestionMarkDash if self.dialect.supports_geometric_types() => {
                Some(BinaryOperator::QuestionDash)
            }
            Token::AmpersandLeftAngleBracketVerticalBar
                if self.dialect.supports_geometric_types() =>
            {
                Some(BinaryOperator::AndLtPipe)
            }
            Token::VerticalBarAmpersandRightAngleBracket
                if self.dialect.supports_geometric_types() =>
            {
                Some(BinaryOperator::PipeAndGt)
            }
            Token::TwoWayArrow if self.dialect.supports_geometric_types() => {
                Some(BinaryOperator::LtDashGt)
            }
            Token::LeftAngleBracketCaret if self.dialect.supports_geometric_types() => {
                Some(BinaryOperator::LtCaret)
            }
            Token::RightAngleBracketCaret if self.dialect.supports_geometric_types() => {
                Some(BinaryOperator::GtCaret)
            }
            Token::QuestionMarkSharp if self.dialect.supports_geometric_types() => {
                Some(BinaryOperator::QuestionHash)
            }
            Token::QuestionMarkDoubleVerticalBar if self.dialect.supports_geometric_types() => {
                Some(BinaryOperator::QuestionDoublePipe)
            }
            Token::QuestionMarkDashVerticalBar if self.dialect.supports_geometric_types() => {
                Some(BinaryOperator::QuestionDashPipe)
            }
            Token::TildeEqual if self.dialect.supports_geometric_types() => {
                Some(BinaryOperator::TildeEq)
            }
            Token::ShiftLeftVerticalBar if self.dialect.supports_geometric_types() => {
                Some(BinaryOperator::LtLtPipe)
            }
            Token::VerticalBarShiftRight if self.dialect.supports_geometric_types() => {
                Some(BinaryOperator::PipeGtGt)
            }
            Token::AtSign if self.dialect.supports_geometric_types() => Some(BinaryOperator::At),

            Token::Word(w) => match w.keyword {
                Keyword::AND => Some(BinaryOperator::And),
                Keyword::OR => Some(BinaryOperator::Or),
                Keyword::XOR => Some(BinaryOperator::Xor),
                Keyword::OVERLAPS => Some(BinaryOperator::Overlaps),
                Keyword::OPERATOR if dialect_is!(dialect is PostgreSqlDialect | GenericDialect) => {
                    // there are special rules for operator names in
                    // postgres so we can not use 'parse_object'
                    // or similar.
                    // See https://www.postgresql.org/docs/current/sql-createoperator.html
                    Some(BinaryOperator::PGCustomBinaryOperator(
                        self.parse_pg_operator_ident_parts()?,
                    ))
                }
                _ => None,
            },
            _ => None,
        };

        let tok = self.token_at(tok_index);
        if let Some(op) = regular_binary_operator {
            if let Some(keyword) =
                self.parse_one_of_keywords(&[Keyword::ANY, Keyword::ALL, Keyword::SOME])
            {
                self.expect_token(&Token::LParen)?;
                let right = if self.peek_sub_query() {
                    // We have a subquery ahead (SELECT\WITH ...) need to rewind and
                    // use the parenthesis for parsing the subquery as an expression.
                    self.prev_token(); // LParen
                    self.parse_subexpr(precedence)?
                } else {
                    // Non-subquery expression
                    let right = self.parse_subexpr(precedence)?;
                    self.expect_token(&Token::RParen)?;
                    right
                };

                if !matches!(
                    op,
                    BinaryOperator::Gt
                        | BinaryOperator::Lt
                        | BinaryOperator::GtEq
                        | BinaryOperator::LtEq
                        | BinaryOperator::Eq
                        | BinaryOperator::NotEq
                        | BinaryOperator::PGRegexMatch
                        | BinaryOperator::PGRegexIMatch
                        | BinaryOperator::PGRegexNotMatch
                        | BinaryOperator::PGRegexNotIMatch
                        | BinaryOperator::PGLikeMatch
                        | BinaryOperator::PGILikeMatch
                        | BinaryOperator::PGNotLikeMatch
                        | BinaryOperator::PGNotILikeMatch
                ) {
                    return parser_err!(
                        format!(
                        "Expected one of [=, >, <, =>, =<, !=, ~, ~*, !~, !~*, ~~, ~~*, !~~, !~~*] as comparison operator, found: {op}"
                    ),
                        span.start
                    );
                };

                Ok(match keyword {
                    Keyword::ALL => Expr::AllOp {
                        left: Box::new(expr),
                        compare_op: op,
                        right: Box::new(right),
                    },
                    Keyword::ANY | Keyword::SOME => Expr::AnyOp {
                        left: Box::new(expr),
                        compare_op: op,
                        right: Box::new(right),
                        is_some: keyword == Keyword::SOME,
                    },
                    unexpected_keyword => return Err(ParserError::ParserError(
                        format!("Internal parser error: expected any of {{ALL, ANY, SOME}}, got {unexpected_keyword:?}"),
                    )),
                })
            } else {
                Ok(Expr::BinaryOp {
                    left: Box::new(expr),
                    op,
                    right: Box::new(self.parse_subexpr(precedence)?),
                })
            }
        } else if let Token::Word(w) = &tok.token {
            match w.keyword {
                Keyword::IS => {
                    if self.parse_keyword(Keyword::NULL) {
                        Ok(Expr::IsNull(Box::new(expr)))
                    } else if self.parse_keywords(&[Keyword::NOT, Keyword::NULL]) {
                        Ok(Expr::IsNotNull(Box::new(expr)))
                    } else if self.parse_keywords(&[Keyword::TRUE]) {
                        Ok(Expr::IsTrue(Box::new(expr)))
                    } else if self.parse_keywords(&[Keyword::NOT, Keyword::TRUE]) {
                        Ok(Expr::IsNotTrue(Box::new(expr)))
                    } else if self.parse_keywords(&[Keyword::FALSE]) {
                        Ok(Expr::IsFalse(Box::new(expr)))
                    } else if self.parse_keywords(&[Keyword::NOT, Keyword::FALSE]) {
                        Ok(Expr::IsNotFalse(Box::new(expr)))
                    } else if self.parse_keywords(&[Keyword::UNKNOWN]) {
                        Ok(Expr::IsUnknown(Box::new(expr)))
                    } else if self.parse_keywords(&[Keyword::NOT, Keyword::UNKNOWN]) {
                        Ok(Expr::IsNotUnknown(Box::new(expr)))
                    } else if self.parse_keywords(&[Keyword::DISTINCT, Keyword::FROM]) {
                        // The right operand binds no more loosely than `IS`
                        // itself, so that e.g. `a IS DISTINCT FROM b AND c`
                        // parses as `(a IS DISTINCT FROM b) AND c`.
                        let expr2 = self.parse_subexpr(precedence)?;
                        Ok(Expr::IsDistinctFrom(Box::new(expr), Box::new(expr2)))
                    } else if self.parse_keywords(&[Keyword::NOT, Keyword::DISTINCT, Keyword::FROM])
                    {
                        let expr2 = self.parse_subexpr(precedence)?;
                        Ok(Expr::IsNotDistinctFrom(Box::new(expr), Box::new(expr2)))
                    } else if self.parse_keyword(Keyword::JSON) {
                        self.parse_is_json_predicate(expr, false)
                    } else if self.parse_keywords(&[Keyword::NOT, Keyword::JSON]) {
                        self.parse_is_json_predicate(expr, true)
                    } else if let Ok(is_normalized) = self.parse_unicode_is_normalized(expr) {
                        Ok(is_normalized)
                    } else {
                        self.expected_ref(
                            "[NOT] NULL | TRUE | FALSE | DISTINCT | [NOT] JSON [VALUE | SCALAR | ARRAY | OBJECT] [WITH | WITHOUT UNIQUE [KEYS]] | [form] NORMALIZED FROM after IS",
                            self.peek_token_ref(),
                        )
                    }
                }
                Keyword::AT => {
                    self.expect_keywords(&[Keyword::TIME, Keyword::ZONE])?;
                    Ok(Expr::AtTimeZone {
                        timestamp: Box::new(expr),
                        time_zone: Box::new(self.parse_subexpr(precedence)?),
                    })
                }
                Keyword::GLOBAL if self.dialect.supports_global_in() => {
                    let negated = self.parse_keyword(Keyword::NOT);
                    self.expect_keyword_is(Keyword::IN)?;
                    self.parse_in(expr, negated, true)
                }
                Keyword::NOT
                | Keyword::IN
                | Keyword::BETWEEN
                | Keyword::LIKE
                | Keyword::ILIKE
                | Keyword::SIMILAR
                | Keyword::REGEXP
                | Keyword::RLIKE => {
                    self.prev_token();
                    let negated = self.parse_keyword(Keyword::NOT);
                    let regexp = self.parse_keyword(Keyword::REGEXP);
                    let rlike = self.parse_keyword(Keyword::RLIKE);
                    let null = if !self.in_column_definition_state() {
                        self.parse_keyword(Keyword::NULL)
                    } else {
                        false
                    };
                    if regexp || rlike {
                        Ok(Expr::RLike {
                            negated,
                            expr: Box::new(expr),
                            pattern: Box::new(
                                self.parse_subexpr(self.dialect.prec_value(Precedence::Like))?,
                            ),
                            regexp,
                        })
                    } else if negated && null {
                        Ok(Expr::IsNotNull(Box::new(expr)))
                    } else if self.parse_keyword(Keyword::IN) {
                        self.parse_in(expr, negated, false)
                    } else if self.parse_keyword(Keyword::BETWEEN) {
                        self.parse_between(expr, negated)
                    } else if self.parse_keyword(Keyword::LIKE) {
                        Ok(Expr::Like {
                            negated,
                            any: self.parse_keyword(Keyword::ANY),
                            expr: Box::new(expr),
                            pattern: Box::new(
                                self.parse_subexpr(self.dialect.prec_value(Precedence::Like))?,
                            ),
                            escape_char: self.parse_escape_char()?,
                        })
                    } else if self.parse_keyword(Keyword::ILIKE) {
                        Ok(Expr::ILike {
                            negated,
                            any: self.parse_keyword(Keyword::ANY),
                            expr: Box::new(expr),
                            pattern: Box::new(
                                self.parse_subexpr(self.dialect.prec_value(Precedence::Like))?,
                            ),
                            escape_char: self.parse_escape_char()?,
                        })
                    } else if self.parse_keywords(&[Keyword::SIMILAR, Keyword::TO]) {
                        Ok(Expr::SimilarTo {
                            negated,
                            expr: Box::new(expr),
                            pattern: Box::new(
                                self.parse_subexpr(self.dialect.prec_value(Precedence::Like))?,
                            ),
                            escape_char: self.parse_escape_char()?,
                        })
                    } else {
                        self.expected_ref("IN or BETWEEN after NOT", self.peek_token_ref())
                    }
                }
                Keyword::NOTNULL if dialect.supports_notnull_operator() => {
                    Ok(Expr::IsNotNull(Box::new(expr)))
                }
                Keyword::MEMBER => {
                    if self.parse_keyword(Keyword::OF) {
                        self.expect_token(&Token::LParen)?;
                        let array = self.parse_expr()?;
                        self.expect_token(&Token::RParen)?;
                        Ok(Expr::MemberOf(MemberOf {
                            value: Box::new(expr),
                            array: Box::new(array),
                        }))
                    } else {
                        self.expected_ref("OF after MEMBER", self.peek_token_ref())
                    }
                }
                // Reached when the dialect assigns `COLLATE` a lower precedence than `::`, e.g.
                // Postgres's `expr::type COLLATE collation`.
                // See <https://www.postgresql.org/docs/current/sql-syntax-lexical.html#SQL-PRECEDENCE>
                Keyword::COLLATE => Ok(Expr::Collate {
                    expr: Box::new(expr),
                    collation: self.parse_object_name(false)?,
                }),
                // Can only happen if `get_next_precedence` got out of sync with this function
                _ => parser_err!(
                    format!("No infix parser for token {:?}", tok.token),
                    tok.span.start
                ),
            }
        } else if Token::DoubleColon == *tok {
            Ok(Expr::Cast {
                kind: CastKind::DoubleColon,
                expr: Box::new(expr),
                data_type: self.parse_data_type()?,
                format: None,
            })
        } else if Token::ExclamationMark == *tok && self.dialect.supports_factorial_operator() {
            Ok(Expr::UnaryOp {
                op: UnaryOperator::PGPostfixFactorial,
                expr: Box::new(expr),
            })
        } else if Token::LBracket == *tok && self.dialect.supports_partiql()
            || (Token::Colon == *tok)
        {
            self.prev_token();
            self.parse_json_access(expr)
        } else {
            // Can only happen if `get_next_precedence` got out of sync with this function
            parser_err!(
                format!("No infix parser for token {:?}", tok.token),
                tok.span.start
            )
        }
    }

    /// Parse the `ESCAPE CHAR` portion of `LIKE`, `ILIKE`, and `SIMILAR TO`
    pub fn parse_escape_char(&mut self) -> Result<Option<Box<Expr>>, ParserError> {
        if self.parse_keyword(Keyword::ESCAPE) {
            Ok(Some(Box::new(self.parse_subexpr(
                self.dialect.prec_value(Precedence::Like),
            )?)))
        } else {
            Ok(None)
        }
    }

    /// Parses an array subscript like
    /// * `[:]`
    /// * `[l]`
    /// * `[l:]`
    /// * `[:u]`
    /// * `[l:u]`
    /// * `[l:u:s]`
    ///
    /// Parser is right after `[`
    fn parse_subscript_inner(&mut self) -> Result<Subscript, ParserError> {
        // at either `<lower>:(rest)` or `:(rest)]`
        let lower_bound = if self.consume_token(&Token::Colon) {
            None
        } else {
            // parse expr until we hit a colon (or any token with lower precedence)
            Some(self.parse_subexpr(self.dialect.prec_value(Precedence::Colon))?)
        };

        // check for end
        if self.consume_token(&Token::RBracket) {
            if let Some(lower_bound) = lower_bound {
                return Ok(Subscript::Index { index: lower_bound });
            };
            return Ok(Subscript::Slice {
                lower_bound,
                upper_bound: None,
                stride: None,
            });
        }

        // consume the `:`
        if lower_bound.is_some() {
            self.expect_token(&Token::Colon)?;
        }

        // we are now at either `]`, `<upper>(rest)]`
        let upper_bound = if self.consume_token(&Token::RBracket) {
            return Ok(Subscript::Slice {
                lower_bound,
                upper_bound: None,
                stride: None,
            });
        } else {
            // parse expr until we hit a colon (or any token with lower precedence)
            Some(self.parse_subexpr(self.dialect.prec_value(Precedence::Colon))?)
        };

        // check for end
        if self.consume_token(&Token::RBracket) {
            return Ok(Subscript::Slice {
                lower_bound,
                upper_bound,
                stride: None,
            });
        }

        // we are now at `:]` or `:stride]`
        self.expect_token(&Token::Colon)?;
        let stride = if self.consume_token(&Token::RBracket) {
            None
        } else {
            Some(self.parse_expr()?)
        };

        if stride.is_some() {
            self.expect_token(&Token::RBracket)?;
        }

        Ok(Subscript::Slice {
            lower_bound,
            upper_bound,
            stride,
        })
    }

    /// Parse a multi-dimension array accessing like `[1:3][1][1]`
    pub fn parse_multi_dim_subscript(
        &mut self,
        chain: &mut Vec<AccessExpr>,
    ) -> Result<(), ParserError> {
        while self.consume_token(&Token::LBracket) {
            self.parse_subscript(chain)?;
        }
        Ok(())
    }

    /// Parses an array subscript like `[1:3]`
    ///
    /// Parser is right after `[`
    fn parse_subscript(&mut self, chain: &mut Vec<AccessExpr>) -> Result<(), ParserError> {
        let subscript = self.parse_subscript_inner()?;
        chain.push(AccessExpr::Subscript(subscript));
        Ok(())
    }

    fn parse_json_path_object_key(&mut self) -> Result<JsonPathElem, ParserError> {
        let token = self.next_token();
        match token.token {
            Token::Word(Word {
                value,
                // path segments in SF dot notation can be unquoted or double-quoted;
                // Databricks also supports backtick-quoted identifiers
                quote_style: quote_style @ (Some('"') | Some('`') | None),
                // some experimentation suggests that snowflake permits
                // any keyword here unquoted.
                keyword: _,
            }) => Ok(JsonPathElem::Dot {
                key: value,
                quoted: quote_style.is_some(),
            }),

            // This token should never be generated on snowflake or generic
            // dialects, but we handle it just in case this is used on future
            // dialects.
            Token::DoubleQuotedString(key) => Ok(JsonPathElem::Dot { key, quoted: true }),

            _ => self.expected("variant object key name", token),
        }
    }

    fn parse_json_access(&mut self, expr: Expr) -> Result<Expr, ParserError> {
        let path = self.parse_json_path()?;
        Ok(Expr::JsonAccess {
            value: Box::new(expr),
            path,
        })
    }

    fn parse_json_path(&mut self) -> Result<JsonPath, ParserError> {
        let mut path = Vec::new();
        loop {
            match self.next_token().token {
                Token::Colon if path.is_empty() && self.peek_token_ref() == &Token::LBracket => {
                    self.next_token();
                    let key = self.parse_wildcard_expr()?;
                    self.expect_token(&Token::RBracket)?;
                    path.push(JsonPathElem::ColonBracket { key });
                }
                Token::Colon if path.is_empty() => {
                    path.push(self.parse_json_path_object_key()?);
                }
                Token::Period if !path.is_empty() => {
                    path.push(self.parse_json_path_object_key()?);
                }
                Token::LBracket => {
                    let key = self.parse_wildcard_expr()?;
                    self.expect_token(&Token::RBracket)?;

                    path.push(JsonPathElem::Bracket { key });
                }
                _ => {
                    self.prev_token();
                    break;
                }
            };
        }

        debug_assert!(!path.is_empty());
        Ok(JsonPath { path })
    }

    /// Parses the parens following the `[ GLOBAL ] [ NOT ] IN` operator.
    pub fn parse_in(
        &mut self,
        expr: Expr,
        negated: bool,
        global: bool,
    ) -> Result<Expr, ParserError> {
        // BigQuery allows `IN UNNEST(array_expression)`
        // https://cloud.google.com/bigquery/docs/reference/standard-sql/operators#in_operators
        let target = if !global && self.parse_keyword(Keyword::UNNEST) {
            self.expect_token(&Token::LParen)?;
            let array_expr = self.parse_expr()?;
            self.expect_token(&Token::RParen)?;
            InTarget::Unnest(Box::new(array_expr))
        } else if self.dialect.supports_in_unparenthesized_expr()
            && self.peek_token_ref().token != Token::LParen
        {
            InTarget::List(vec![
                self.parse_subexpr(self.dialect.prec_value(Precedence::Eq))?
            ])
        } else {
            self.parse_in_parenthesized_target()?
        };
        Ok(Expr::In {
            expr: Box::new(expr),
            target,
            negated,
            global,
        })
    }

    /// Parses the parenthesized subquery or value list of an `IN` predicate.
    fn parse_in_parenthesized_target(&mut self) -> Result<InTarget, ParserError> {
        self.expect_token(&Token::LParen)?;
        // A leading query is the whole subquery only when `)` follows it,
        // otherwise it is the first item of a list, as in `IN ((SELECT 1), 2)`.
        let start = self.index;
        // Where a parsed query lacked its `)`. Reported if the list fails no
        // further in, since that error would sit inside the query.
        let missing_rparen = match self.failed_in_subquery_positions.get(&start) {
            Some(&cached) => cached,
            None => {
                let mut missing_rparen = None;
                if let Some(subquery) = self.maybe_parse(|p| p.parse_query())? {
                    if self.consume_token(&Token::RParen) {
                        return Ok(InTarget::Subquery(subquery));
                    }
                    missing_rparen = Some(self.index);
                    self.index = start;
                }
                self.failed_in_subquery_positions
                    .insert(start, missing_rparen);
                missing_rparen
            }
        };
        let list = if self.dialect.supports_in_empty_list() {
            self.parse_comma_separated0(Parser::parse_expr, Token::RParen)
        } else {
            self.parse_comma_separated(Parser::parse_expr)
        };
        match list.and_then(|list| self.expect_token(&Token::RParen).map(|_| list)) {
            Ok(list) => Ok(InTarget::List(list)),
            Err(ParserError::RecursionLimitExceeded) => Err(ParserError::RecursionLimitExceeded),
            Err(e) => match missing_rparen {
                Some(index) if self.index <= index => {
                    self.index = index;
                    self.expected_ref(")", self.peek_token_ref())
                }
                _ => Err(e),
            },
        }
    }

    /// Parses `BETWEEN <low> AND <high>`, assuming the `BETWEEN` keyword was already consumed.
    pub fn parse_between(&mut self, expr: Expr, negated: bool) -> Result<Expr, ParserError> {
        // Stop parsing subexpressions for <low> and <high> on tokens with
        // precedence lower than that of `BETWEEN`, such as `AND`, `IS`, etc.
        let low = self.parse_subexpr(self.dialect.prec_value(Precedence::Between))?;
        self.expect_keyword_is(Keyword::AND)?;
        let high = self.parse_subexpr(self.dialect.prec_value(Precedence::Between))?;
        Ok(Expr::Between {
            expr: Box::new(expr),
            negated,
            low: Box::new(low),
            high: Box::new(high),
        })
    }

    /// Parse a PostgreSQL casting style which is in the form of `expr::datatype`.
    pub fn parse_pg_cast(&mut self, expr: Expr) -> Result<Expr, ParserError> {
        Ok(Expr::Cast {
            kind: CastKind::DoubleColon,
            expr: Box::new(expr),
            data_type: self.parse_data_type()?,
            format: None,
        })
    }

    /// Get the precedence of the next token
    pub fn get_next_precedence(&self) -> Result<u8, ParserError> {
        self.dialect.get_next_precedence_default(self)
    }

    /// Return the token at the given location, or EOF if the index is beyond
    /// the length of the current set of tokens.
    pub fn token_at(&self, index: usize) -> &TokenWithSpan {
        self.tokens.get(index).unwrap_or(&EOF_TOKEN)
    }

    /// Return the first non-whitespace token that has not yet been processed
    /// or Token::EOF
    ///
    /// See [`Self::peek_token_ref`] to avoid the copy.
    pub fn peek_token(&self) -> TokenWithSpan {
        self.peek_nth_token(0)
    }

    /// Return a reference to the first non-whitespace token that has not yet
    /// been processed or Token::EOF
    pub fn peek_token_ref(&self) -> &TokenWithSpan {
        self.peek_nth_token_ref(0)
    }

    /// Returns the `N` next non-whitespace tokens that have not yet been
    /// processed.
    ///
    /// Example:
    /// ```rust
    /// # use sqlparser::dialect::GenericDialect;
    /// # use sqlparser::parser::Parser;
    /// # use sqlparser::keywords::Keyword;
    /// # use sqlparser::tokenizer::{Token, Word};
    /// let dialect = GenericDialect {};
    /// let mut parser = Parser::new(&dialect).try_with_sql("ORDER BY foo, bar").unwrap();
    ///
    /// // Note that Rust infers the number of tokens to peek based on the
    /// // length of the slice pattern!
    /// assert!(matches!(
    ///     parser.peek_tokens(),
    ///     [
    ///         Token::Word(Word { keyword: Keyword::ORDER, .. }),
    ///         Token::Word(Word { keyword: Keyword::BY, .. }),
    ///     ]
    /// ));
    /// ```
    pub fn peek_tokens<const N: usize>(&self) -> [Token; N] {
        self.peek_tokens_with_location()
            .map(|with_loc| with_loc.token)
    }

    /// Returns the `N` next non-whitespace tokens with locations that have not
    /// yet been processed.
    ///
    /// See [`Self::peek_token`] for an example.
    pub fn peek_tokens_with_location<const N: usize>(&self) -> [TokenWithSpan; N] {
        let mut index = self.index;
        core::array::from_fn(|_| loop {
            let token = self.tokens.get(index);
            index += 1;
            if let Some(TokenWithSpan {
                token: Token::Whitespace(_),
                span: _,
            }) = token
            {
                continue;
            }
            break token.cloned().unwrap_or(TokenWithSpan {
                token: Token::EOF,
                span: Span::empty(),
            });
        })
    }

    /// Returns references to the `N` next non-whitespace tokens
    /// that have not yet been processed.
    ///
    /// See [`Self::peek_tokens`] for an example.
    pub fn peek_tokens_ref<const N: usize>(&self) -> [&TokenWithSpan; N] {
        let mut index = self.index;
        core::array::from_fn(|_| loop {
            let token = self.tokens.get(index);
            index += 1;
            if let Some(TokenWithSpan {
                token: Token::Whitespace(_),
                span: _,
            }) = token
            {
                continue;
            }
            break token.unwrap_or(&EOF_TOKEN);
        })
    }

    /// Return nth non-whitespace token that has not yet been processed
    pub fn peek_nth_token(&self, n: usize) -> TokenWithSpan {
        self.peek_nth_token_ref(n).clone()
    }

    /// Return nth non-whitespace token that has not yet been processed
    pub fn peek_nth_token_ref(&self, mut n: usize) -> &TokenWithSpan {
        let mut index = self.index;
        loop {
            index += 1;
            match self.tokens.get(index - 1) {
                Some(TokenWithSpan {
                    token: Token::Whitespace(_),
                    span: _,
                }) => continue,
                non_whitespace => {
                    if n == 0 {
                        return non_whitespace.unwrap_or(&EOF_TOKEN);
                    }
                    n -= 1;
                }
            }
        }
    }

    /// Return the first token, possibly whitespace, that has not yet been processed
    /// (or None if reached end-of-file).
    pub fn peek_token_no_skip(&self) -> TokenWithSpan {
        self.peek_nth_token_no_skip(0)
    }

    /// Return nth token, possibly whitespace, that has not yet been processed.
    pub fn peek_nth_token_no_skip(&self, n: usize) -> TokenWithSpan {
        self.tokens
            .get(self.index + n)
            .cloned()
            .unwrap_or(TokenWithSpan {
                token: Token::EOF,
                span: Span::empty(),
            })
    }

    /// Return nth token, possibly whitespace, that has not yet been processed.
    fn peek_nth_token_no_skip_ref(&self, n: usize) -> &TokenWithSpan {
        self.tokens.get(self.index + n).unwrap_or(&EOF_TOKEN)
    }

    /// Return true if the next tokens exactly `expected`
    ///
    /// Does not advance the current token.
    fn peek_keywords(&mut self, expected: &[Keyword]) -> bool {
        let index = self.index;
        let matched = self.parse_keywords(expected);
        self.index = index;
        matched
    }

    /// Advances to the next non-whitespace token and returns a copy.
    ///
    /// Please use [`Self::advance_token`] and [`Self::get_current_token`] to
    /// avoid the copy.
    pub fn next_token(&mut self) -> TokenWithSpan {
        self.advance_token();
        self.get_current_token().clone()
    }

    /// Returns the index of the current token
    ///
    /// This can be used with APIs that expect an index, such as
    /// [`Self::token_at`]
    pub fn get_current_index(&self) -> usize {
        self.index.saturating_sub(1)
    }

    /// Return the next unprocessed token, possibly whitespace.
    pub fn next_token_no_skip(&mut self) -> Option<&TokenWithSpan> {
        self.index += 1;
        self.tokens.get(self.index - 1)
    }

    /// Advances the current token to the next non-whitespace token
    ///
    /// See [`Self::get_current_token`] to get the current token after advancing
    pub fn advance_token(&mut self) {
        loop {
            self.index += 1;
            match self.tokens.get(self.index - 1) {
                Some(TokenWithSpan {
                    token: Token::Whitespace(_),
                    span: _,
                }) => continue,
                _ => break,
            }
        }
    }

    /// Returns a reference to the current token
    ///
    /// Does not advance the current token.
    pub fn get_current_token(&self) -> &TokenWithSpan {
        self.token_at(self.index.saturating_sub(1))
    }

    /// Returns a reference to the previous token
    ///
    /// Does not advance the current token.
    pub fn get_previous_token(&self) -> &TokenWithSpan {
        self.token_at(self.index.saturating_sub(2))
    }

    /// Returns a reference to the next token
    ///
    /// Does not advance the current token.
    pub fn get_next_token(&self) -> &TokenWithSpan {
        self.token_at(self.index)
    }

    /// Seek back the last one non-whitespace token.
    ///
    /// Must be called after `next_token()`, otherwise might panic. OK to call
    /// after `next_token()` indicates an EOF.
    ///
    // TODO rename to backup_token and deprecate prev_token?
    pub fn prev_token(&mut self) {
        loop {
            assert!(self.index > 0);
            self.index -= 1;
            if let Some(TokenWithSpan {
                token: Token::Whitespace(_),
                span: _,
            }) = self.tokens.get(self.index)
            {
                continue;
            }
            return;
        }
    }

    /// Report `found` was encountered instead of `expected`
    pub fn expected<T>(&self, expected: &str, found: TokenWithSpan) -> Result<T, ParserError> {
        parser_err!(
            format!("Expected: {expected}, found: {found}"),
            found.span.start
        )
    }

    /// report `found` was encountered instead of `expected`
    pub fn expected_ref<T>(&self, expected: &str, found: &TokenWithSpan) -> Result<T, ParserError> {
        parser_err!(
            format!("Expected: {expected}, found: {found}"),
            found.span.start
        )
    }

    /// Report that the token at `index` was found instead of `expected`.
    pub fn expected_at<T>(&self, expected: &str, index: usize) -> Result<T, ParserError> {
        let found = self.tokens.get(index).unwrap_or(&EOF_TOKEN);
        parser_err!(
            format!("Expected: {expected}, found: {found}"),
            found.span.start
        )
    }

    /// If the current token is the `expected` keyword, consume it and returns
    /// true. Otherwise, no tokens are consumed and returns false.
    #[must_use]
    pub fn parse_keyword(&mut self, expected: Keyword) -> bool {
        if self.peek_keyword(expected) {
            self.advance_token();
            true
        } else {
            false
        }
    }

    #[must_use]
    /// Check if the current token is the expected keyword without consuming it.
    ///
    /// Returns true if the current token matches the expected keyword.
    pub fn peek_keyword(&self, expected: Keyword) -> bool {
        matches!(&self.peek_token_ref().token, Token::Word(w) if expected == w.keyword)
    }

    /// If the current token is the `expected` keyword followed by
    /// specified tokens, consume them and returns true.
    /// Otherwise, no tokens are consumed and returns false.
    ///
    /// Note that if the length of `tokens` is too long, this function will
    /// not be efficient as it does a loop on the tokens with `peek_nth_token`
    /// each time.
    pub fn parse_keyword_with_tokens(&mut self, expected: Keyword, tokens: &[Token]) -> bool {
        self.keyword_with_tokens(expected, tokens, true)
    }

    /// Peeks to see if the current token is the `expected` keyword followed by specified tokens
    /// without consuming them.
    ///
    /// See [Self::parse_keyword_with_tokens] for details.
    pub(crate) fn peek_keyword_with_tokens(&mut self, expected: Keyword, tokens: &[Token]) -> bool {
        self.keyword_with_tokens(expected, tokens, false)
    }

    fn keyword_with_tokens(&mut self, expected: Keyword, tokens: &[Token], consume: bool) -> bool {
        match &self.peek_token_ref().token {
            Token::Word(w) if expected == w.keyword => {
                for (idx, token) in tokens.iter().enumerate() {
                    if self.peek_nth_token_ref(idx + 1).token != *token {
                        return false;
                    }
                }

                if consume {
                    for _ in 0..(tokens.len() + 1) {
                        self.advance_token();
                    }
                }

                true
            }
            _ => false,
        }
    }

    /// If the current and subsequent tokens exactly match the `keywords`
    /// sequence, consume them and returns true. Otherwise, no tokens are
    /// consumed and returns false
    #[must_use]
    pub fn parse_keywords(&mut self, keywords: &[Keyword]) -> bool {
        self.parse_keywords_indexed(keywords).is_some()
    }

    /// Just like [Self::parse_keywords], but - upon success - returns the
    /// token index of the first keyword.
    #[must_use]
    fn parse_keywords_indexed(&mut self, keywords: &[Keyword]) -> Option<usize> {
        let start_index = self.index;
        let mut first_keyword_index = None;
        for &keyword in keywords {
            if !self.parse_keyword(keyword) {
                self.index = start_index;
                return None;
            }
            if first_keyword_index.is_none() {
                first_keyword_index = Some(self.index.saturating_sub(1));
            }
        }
        first_keyword_index
    }

    /// If the current token is one of the given `keywords`, returns the keyword
    /// that matches, without consuming the token. Otherwise, returns [`None`].
    #[must_use]
    pub fn peek_one_of_keywords(&self, keywords: &[Keyword]) -> Option<Keyword> {
        for keyword in keywords {
            if self.peek_keyword(*keyword) {
                return Some(*keyword);
            }
        }
        None
    }

    /// If the current token is one of the given `keywords`, consume the token
    /// and return the keyword that matches. Otherwise, no tokens are consumed
    /// and returns [`None`].
    #[must_use]
    pub fn parse_one_of_keywords(&mut self, keywords: &[Keyword]) -> Option<Keyword> {
        match &self.peek_token_ref().token {
            Token::Word(w) => {
                keywords
                    .iter()
                    .find(|keyword| **keyword == w.keyword)
                    .map(|keyword| {
                        self.advance_token();
                        *keyword
                    })
            }
            _ => None,
        }
    }

    /// If the current token is one of the expected keywords, consume the token
    /// and return the keyword that matches. Otherwise, return an error.
    pub fn expect_one_of_keywords(&mut self, keywords: &[Keyword]) -> Result<Keyword, ParserError> {
        if let Some(keyword) = self.parse_one_of_keywords(keywords) {
            Ok(keyword)
        } else {
            let keywords: Vec<String> = keywords.iter().map(|x| format!("{x:?}")).collect();
            self.expected_ref(
                &format!("one of {}", keywords.join(" or ")),
                self.peek_token_ref(),
            )
        }
    }

    /// If the current token is the `expected` keyword, consume the token.
    /// Otherwise, return an error.
    ///
    // todo deprecate in favor of expected_keyword_is
    pub fn expect_keyword(&mut self, expected: Keyword) -> Result<TokenWithSpan, ParserError> {
        if self.parse_keyword(expected) {
            Ok(self.get_current_token().clone())
        } else {
            self.expected_ref(format!("{:?}", expected).as_str(), self.peek_token_ref())
        }
    }

    /// If the current token is the `expected` keyword, consume the token.
    /// Otherwise, return an error.
    ///
    /// This differs from expect_keyword only in that the matched keyword
    /// token is not returned.
    pub fn expect_keyword_is(&mut self, expected: Keyword) -> Result<(), ParserError> {
        if self.parse_keyword(expected) {
            Ok(())
        } else {
            self.expected_ref(format!("{:?}", expected).as_str(), self.peek_token_ref())
        }
    }

    /// If the current and subsequent tokens exactly match the `keywords`
    /// sequence, consume them and returns Ok. Otherwise, return an Error.
    pub fn expect_keywords(&mut self, expected: &[Keyword]) -> Result<(), ParserError> {
        for &kw in expected {
            self.expect_keyword_is(kw)?;
        }
        Ok(())
    }

    /// Consume the next token if it matches the expected token, otherwise return false
    ///
    /// See [Self::advance_token] to consume the token unconditionally
    #[must_use]
    pub fn consume_token(&mut self, expected: &Token) -> bool {
        if self.peek_token_ref() == expected {
            self.advance_token();
            true
        } else {
            false
        }
    }

    /// If the current and subsequent tokens exactly match the `tokens`
    /// sequence, consume them and returns true. Otherwise, no tokens are
    /// consumed and returns false
    #[must_use]
    pub fn consume_tokens(&mut self, tokens: &[Token]) -> bool {
        let index = self.index;
        for token in tokens {
            if !self.consume_token(token) {
                self.index = index;
                return false;
            }
        }
        true
    }

    /// Bail out if the current token is not an expected keyword, or consume it if it is
    pub fn expect_token(&mut self, expected: &Token) -> Result<TokenWithSpan, ParserError> {
        if self.peek_token_ref() == expected {
            Ok(self.next_token())
        } else {
            self.expected_ref(&expected.to_string(), self.peek_token_ref())
        }
    }

    fn parse<T: FromStr>(s: String, loc: Location) -> Result<T, ParserError>
    where
        <T as FromStr>::Err: Display,
    {
        s.parse::<T>().map_err(|e| {
            ParserError::ParserError(format!(
                "Could not parse '{s}' as {}: {e}{loc}",
                core::any::type_name::<T>()
            ))
        })
    }

    /// Parse a comma-separated list of 1+ SelectItem
    pub fn parse_projection(&mut self) -> Result<Vec<SelectItem>, ParserError> {
        // BigQuery and Snowflake allow trailing commas, but only in project lists
        // e.g. `SELECT 1, 2, FROM t`
        // https://cloud.google.com/bigquery/docs/reference/standard-sql/lexical#trailing_commas
        // https://docs.snowflake.com/en/release-notes/2024/8_11#select-supports-trailing-commas

        let trailing_commas =
            self.options.trailing_commas | self.dialect.supports_projection_trailing_commas();

        self.parse_comma_separated_with_trailing_commas(
            |p| p.parse_select_item(),
            trailing_commas,
            Self::is_reserved_for_column_alias,
        )
    }

    /// Parse a list of actions for `GRANT` statements.
    pub fn parse_actions_list(&mut self) -> Result<Vec<Action>, ParserError> {
        let mut values = vec![];
        loop {
            values.push(self.parse_grant_permission()?);
            if !self.consume_token(&Token::Comma) {
                break;
            } else if self.options.trailing_commas {
                match &self.peek_token_ref().token {
                    Token::Word(kw) if kw.keyword == Keyword::ON => {
                        break;
                    }
                    Token::RParen
                    | Token::SemiColon
                    | Token::EOF
                    | Token::RBracket
                    | Token::RBrace => break,
                    _ => continue,
                }
            }
        }
        Ok(values)
    }

    /// Parse a list of [TableWithJoins]
    fn parse_table_with_joins(&mut self) -> Result<Vec<TableWithJoins>, ParserError> {
        let trailing_commas = self.dialect.supports_from_trailing_commas();

        self.parse_comma_separated_with_trailing_commas(
            Parser::parse_table_and_joins,
            trailing_commas,
            |kw, parser| !self.dialect.is_table_factor(kw, parser),
        )
    }

    /// Parse the comma of a comma-separated syntax element.
    /// `R` is a predicate that should return true if the next
    /// keyword is a reserved keyword.
    /// Allows for control over trailing commas
    ///
    /// Returns true if there is a next element
    fn is_parse_comma_separated_end_with_trailing_commas<R>(
        &mut self,
        trailing_commas: bool,
        is_reserved_keyword: &R,
    ) -> bool
    where
        R: Fn(&Keyword, &mut Parser) -> bool,
    {
        if !self.consume_token(&Token::Comma) {
            true
        } else if trailing_commas {
            let token = self.next_token().token;
            let is_end = match token {
                Token::Word(ref kw) if is_reserved_keyword(&kw.keyword, self) => true,
                Token::RParen | Token::SemiColon | Token::EOF | Token::RBracket | Token::RBrace => {
                    true
                }
                _ => false,
            };
            self.prev_token();

            is_end
        } else {
            false
        }
    }

    /// Parse the comma of a comma-separated syntax element.
    /// Returns true if there is a next element
    fn is_parse_comma_separated_end(&mut self) -> bool {
        self.is_parse_comma_separated_end_with_trailing_commas(
            self.options.trailing_commas,
            &Self::is_reserved_for_column_alias,
        )
    }

    /// Parse a comma-separated list of 1+ items accepted by `F`
    pub fn parse_comma_separated<T, F>(&mut self, f: F) -> Result<Vec<T>, ParserError>
    where
        F: FnMut(&mut Parser<'a>) -> Result<T, ParserError>,
    {
        self.parse_comma_separated_with_trailing_commas(
            f,
            self.options.trailing_commas,
            Self::is_reserved_for_column_alias,
        )
    }

    /// Parse a comma-separated list of 1+ items accepted by `F`.
    /// `R` is a predicate that should return true if the next
    /// keyword is a reserved keyword.
    /// Allows for control over trailing commas.
    fn parse_comma_separated_with_trailing_commas<T, F, R>(
        &mut self,
        mut f: F,
        trailing_commas: bool,
        is_reserved_keyword: R,
    ) -> Result<Vec<T>, ParserError>
    where
        F: FnMut(&mut Parser<'a>) -> Result<T, ParserError>,
        R: Fn(&Keyword, &mut Parser) -> bool,
    {
        let mut values = vec![];
        loop {
            values.push(f(self)?);
            if self.is_parse_comma_separated_end_with_trailing_commas(
                trailing_commas,
                &is_reserved_keyword,
            ) {
                break;
            }
        }
        Ok(values)
    }

    /// Parse a period-separated list of 1+ items accepted by `F`
    fn parse_period_separated<T, F>(&mut self, mut f: F) -> Result<Vec<T>, ParserError>
    where
        F: FnMut(&mut Parser<'a>) -> Result<T, ParserError>,
    {
        let mut values = vec![];
        loop {
            values.push(f(self)?);
            if !self.consume_token(&Token::Period) {
                break;
            }
        }
        Ok(values)
    }

    /// Parse a keyword-separated list of 1+ items accepted by `F`
    pub fn parse_keyword_separated<T, F>(
        &mut self,
        keyword: Keyword,
        mut f: F,
    ) -> Result<Vec<T>, ParserError>
    where
        F: FnMut(&mut Parser<'a>) -> Result<T, ParserError>,
    {
        let mut values = vec![];
        loop {
            values.push(f(self)?);
            if !self.parse_keyword(keyword) {
                break;
            }
        }
        Ok(values)
    }

    /// Parse an expression enclosed in parentheses.
    pub fn parse_parenthesized<T, F>(&mut self, mut f: F) -> Result<T, ParserError>
    where
        F: FnMut(&mut Parser<'a>) -> Result<T, ParserError>,
    {
        self.expect_token(&Token::LParen)?;
        let res = f(self)?;
        self.expect_token(&Token::RParen)?;
        Ok(res)
    }

    /// Parse a comma-separated list of 0+ items accepted by `F`
    /// * `end_token` - expected end token for the closure (e.g. [Token::RParen], [Token::RBrace] ...)
    pub fn parse_comma_separated0<T, F>(
        &mut self,
        f: F,
        end_token: Token,
    ) -> Result<Vec<T>, ParserError>
    where
        F: FnMut(&mut Parser<'a>) -> Result<T, ParserError>,
    {
        if self.peek_token_ref().token == end_token {
            return Ok(vec![]);
        }

        if self.options.trailing_commas && self.peek_tokens() == [Token::Comma, end_token] {
            let _ = self.consume_token(&Token::Comma);
            return Ok(vec![]);
        }

        self.parse_comma_separated(f)
    }

    /// Parses 0 or more statements, each followed by a semicolon.
    /// If the next token is any of `terminal_keywords` then no more
    /// statements will be parsed.
    pub(crate) fn parse_statement_list(
        &mut self,
        terminal_keywords: &[Keyword],
    ) -> Result<Vec<Statement>, ParserError> {
        let mut values = vec![];
        loop {
            match &self.peek_nth_token_ref(0).token {
                Token::EOF => break,
                Token::Word(w)
                    if w.quote_style.is_none() && terminal_keywords.contains(&w.keyword) =>
                {
                    break;
                }
                _ => {}
            }

            values.push(self.parse_statement()?);
            self.expect_token(&Token::SemiColon)?;
        }
        Ok(values)
    }

    /// Default implementation of a predicate that returns true if
    /// the specified keyword is reserved for column alias.
    /// See [Dialect::is_column_alias]
    fn is_reserved_for_column_alias(kw: &Keyword, parser: &mut Parser) -> bool {
        !parser.dialect.is_column_alias(kw, parser)
    }

    /// Run a parser method `f`, reverting back to the current position if unsuccessful.
    /// Returns `ParserError::RecursionLimitExceeded` if `f` returns a `RecursionLimitExceeded`.
    /// Returns `Ok(None)` if `f` returns any other error.
    pub fn maybe_parse<T, F>(&mut self, f: F) -> Result<Option<T>, ParserError>
    where
        F: FnMut(&mut Parser) -> Result<T, ParserError>,
    {
        match self.try_parse(f) {
            Ok(t) => Ok(Some(t)),
            Err(ParserError::RecursionLimitExceeded) => Err(ParserError::RecursionLimitExceeded),
            _ => Ok(None),
        }
    }

    /// Run a parser method `f`, reverting back to the current position if unsuccessful.
    pub fn try_parse<T, F>(&mut self, mut f: F) -> Result<T, ParserError>
    where
        F: FnMut(&mut Parser) -> Result<T, ParserError>,
    {
        let index = self.index;
        match f(self) {
            Ok(t) => Ok(t),
            Err(e) => {
                // Unwind stack if limit exceeded
                self.index = index;
                Err(e)
            }
        }
    }

    /// Parse either `ALL`, `DISTINCT` or `DISTINCT ON (...)`. Returns [`None`] if `ALL` is parsed
    /// and results in a [`ParserError`] if both `ALL` and `DISTINCT` are found.
    pub fn parse_all_or_distinct(&mut self) -> Result<Option<Distinct>, ParserError> {
        let loc = self.peek_token_ref().span.start;
        let distinct = match self.parse_one_of_keywords(&[Keyword::ALL, Keyword::DISTINCT]) {
            Some(Keyword::ALL) => {
                if self.peek_keyword(Keyword::DISTINCT) {
                    return parser_err!("Cannot specify ALL then DISTINCT".to_string(), loc);
                }
                Some(Distinct::All)
            }
            Some(Keyword::DISTINCT) => {
                if self.peek_keyword(Keyword::ALL) {
                    return parser_err!("Cannot specify DISTINCT then ALL".to_string(), loc);
                }
                Some(Distinct::Distinct)
            }
            None => return Ok(None),
            _ => return parser_err!("ALL or DISTINCT", loc),
        };

        let Some(Distinct::Distinct) = distinct else {
            return Ok(distinct);
        };
        if !self.parse_keyword(Keyword::ON) {
            return Ok(Some(Distinct::Distinct));
        }

        self.expect_token(&Token::LParen)?;
        let col_names = if self.consume_token(&Token::RParen) {
            self.prev_token();
            Vec::new()
        } else {
            self.parse_comma_separated(Parser::parse_expr)?
        };
        self.expect_token(&Token::RParen)?;
        Ok(Some(Distinct::On(col_names)))
    }

    /// Parse a SQL CREATE statement
    pub fn parse_create(&mut self) -> Result<Statement, ParserError> {
        let modifier_loc = self.peek_token_ref().span.start;
        let or_replace = self.parse_keywords(&[Keyword::OR, Keyword::REPLACE]);
        let or_alter = self.parse_keywords(&[Keyword::OR, Keyword::ALTER]);
        let multiset = self.maybe_parse_multiset();
        let local = self.parse_one_of_keywords(&[Keyword::LOCAL]).is_some();
        let global = self.parse_one_of_keywords(&[Keyword::GLOBAL]).is_some();
        let transient = self.parse_one_of_keywords(&[Keyword::TRANSIENT]).is_some();
        let global: Option<bool> = if global {
            Some(true)
        } else if local {
            Some(false)
        } else {
            None
        };
        let temporary = self
            .parse_one_of_keywords(&[Keyword::TEMP, Keyword::TEMPORARY])
            .is_some();
        let volatile = self.parse_keyword(Keyword::VOLATILE);
        let unlogged = self.peek_keywords(&[Keyword::UNLOGGED, Keyword::TABLE]);
        if unlogged {
            self.expect_keyword(Keyword::UNLOGGED)?;
        }
        let persistent = dialect_of!(self is DuckDbDialect)
            && self.parse_one_of_keywords(&[Keyword::PERSISTENT]).is_some();
        let create_view_params = self.parse_create_view_params()?;
        if self.peek_keywords(&[Keyword::SNAPSHOT, Keyword::TABLE]) {
            self.parse_create_snapshot_table().map(Into::into)
        } else if self.peek_keywords(&[Keyword::TEXT, Keyword::SEARCH]) {
            self.parse_create_text_search().map(Into::into)
        } else if self.parse_keyword(Keyword::TABLE) {
            self.parse_create_table(
                or_replace, temporary, unlogged, global, transient, volatile, multiset,
            )
            .map(Into::into)
        } else if self.peek_keyword(Keyword::MATERIALIZED)
            || self.peek_keyword(Keyword::VIEW)
            || self.peek_keywords(&[Keyword::SECURE, Keyword::MATERIALIZED, Keyword::VIEW])
            || self.peek_keywords(&[Keyword::SECURE, Keyword::VIEW])
        {
            self.parse_create_view(or_alter, or_replace, temporary, create_view_params)
                .map(Into::into)
        } else if self.parse_keyword(Keyword::POLICY) {
            self.parse_create_policy().map(Into::into)
        } else if self.parse_keyword(Keyword::EXTERNAL) {
            self.parse_create_external_table(or_replace).map(Into::into)
        } else if self.parse_keyword(Keyword::FUNCTION) {
            self.parse_create_function(or_alter, or_replace, temporary)
        } else if self.parse_keyword(Keyword::DOMAIN) {
            self.parse_create_domain().map(Into::into)
        } else if self.parse_keyword(Keyword::TRIGGER) {
            self.parse_create_trigger(temporary, or_alter, or_replace, false)
                .map(Into::into)
        } else if self.parse_keywords(&[Keyword::CONSTRAINT, Keyword::TRIGGER]) {
            self.parse_create_trigger(temporary, or_alter, or_replace, true)
                .map(Into::into)
        } else if self.parse_keyword(Keyword::MACRO) {
            self.parse_create_macro(or_replace, temporary)
        } else if self.parse_keyword(Keyword::SECRET) {
            self.parse_create_secret(or_replace, temporary, persistent)
        } else if self.parse_keyword(Keyword::USER) {
            self.parse_create_user(or_replace).map(Into::into)
        } else if self.parse_keyword(Keyword::SCHEMA) {
            self.parse_create_schema(or_replace)
        } else if self.parse_keyword(Keyword::WAREHOUSE) {
            self.parse_create_warehouse(or_replace).map(Into::into)
        } else if or_replace {
            self.expected_ref(
                "[EXTERNAL] TABLE or [MATERIALIZED] VIEW or FUNCTION or SCHEMA or WAREHOUSE after CREATE OR REPLACE",
                self.peek_token_ref(),
            )
        } else if self.parse_keyword(Keyword::EXTENSION) {
            self.parse_create_extension().map(Into::into)
        } else if self.parse_keyword(Keyword::INDEX) {
            self.parse_create_index(false).map(Into::into)
        } else if self.parse_keywords(&[Keyword::UNIQUE, Keyword::INDEX]) {
            self.parse_create_index(true).map(Into::into)
        } else if self.parse_keyword(Keyword::VIRTUAL) {
            self.parse_create_virtual_table()
        } else if self.parse_keyword(Keyword::DATABASE) {
            self.parse_create_database()
        } else if self.parse_keyword(Keyword::ROLE) {
            self.parse_create_role().map(Into::into)
        } else if self.parse_keyword(Keyword::SEQUENCE) {
            self.parse_create_sequence(temporary)
        } else if self.parse_keyword(Keyword::COLLATION) {
            self.parse_create_collation().map(Into::into)
        } else if self.parse_keyword(Keyword::TYPE) {
            self.parse_create_type()
        } else if self.parse_keyword(Keyword::PROCEDURE)
            || self.dialect.supports_create_proc_syntax() && self.parse_keyword(Keyword::PROC)
        {
            self.parse_create_procedure(or_alter)
        } else if self.parse_keyword(Keyword::CONNECTOR) {
            self.parse_create_connector().map(Into::into)
        } else if self.parse_keyword(Keyword::OPERATOR) {
            // Check if this is CREATE OPERATOR FAMILY or CREATE OPERATOR CLASS
            if self.parse_keyword(Keyword::FAMILY) {
                self.parse_create_operator_family().map(Into::into)
            } else if self.parse_keyword(Keyword::CLASS) {
                self.parse_create_operator_class().map(Into::into)
            } else {
                self.parse_create_operator().map(Into::into)
            }
        } else if self.parse_keyword(Keyword::SERVER) {
            self.parse_pg_create_server()
        } else if self.parse_keywords(&[Keyword::FOREIGN, Keyword::TABLE]) {
            // `or_replace` cannot reach here today, since the arm above catches it.
            // It stays so that reordering the arms cannot make it fall through.
            if or_replace
                || or_alter
                || temporary
                || global.is_some()
                || transient
                || volatile
                || multiset.is_some()
                || persistent
                || create_view_params.is_some()
            {
                return parser_err!(
                    "CREATE FOREIGN TABLE does not accept this modifier",
                    modifier_loc
                );
            }
            self.parse_create_foreign_table().map(Into::into)
        } else {
            self.expected_ref("an object type after CREATE", self.peek_token_ref())
        }
    }

    fn parse_text_search_object_type(&mut self) -> Result<TextSearchObjectType, ParserError> {
        match self.expect_one_of_keywords(&[
            Keyword::DICTIONARY,
            Keyword::CONFIGURATION,
            Keyword::TEMPLATE,
            Keyword::PARSER,
        ])? {
            Keyword::DICTIONARY => Ok(TextSearchObjectType::Dictionary),
            Keyword::CONFIGURATION => Ok(TextSearchObjectType::Configuration),
            Keyword::TEMPLATE => Ok(TextSearchObjectType::Template),
            Keyword::PARSER => Ok(TextSearchObjectType::Parser),
            unexpected_keyword => Err(ParserError::ParserError(format!(
                "Internal parser error: expected any of {{DICTIONARY, CONFIGURATION, TEMPLATE, PARSER}}, got {unexpected_keyword:?}"
            ))),
        }
    }

    /// Parse a `CREATE TEXT SEARCH ...` statement.
    pub fn parse_create_text_search(&mut self) -> Result<CreateTextSearch, ParserError> {
        self.expect_keywords(&[Keyword::TEXT, Keyword::SEARCH])?;
        let object_type = self.parse_text_search_object_type()?;
        let name = self.parse_object_name(false)?;
        self.expect_token(&Token::LParen)?;
        let options = self.parse_comma_separated(Parser::parse_sql_option)?;
        self.expect_token(&Token::RParen)?;
        Ok(CreateTextSearch {
            object_type,
            name,
            options,
        })
    }

    fn parse_alter_text_search_option(&mut self) -> Result<AlterTextSearchOption, ParserError> {
        let key = self.parse_identifier()?;
        let value = if self.consume_token(&Token::Eq) {
            Some(self.parse_expr()?)
        } else {
            None
        };
        Ok(AlterTextSearchOption { key, value })
    }

    /// Parse an `ALTER TEXT SEARCH ...` statement.
    pub fn parse_alter_text_search(&mut self) -> Result<AlterTextSearch, ParserError> {
        self.expect_keywords(&[Keyword::TEXT, Keyword::SEARCH])?;
        let object_type = self.parse_text_search_object_type()?;
        let name = self.parse_object_name(false)?;

        let operation = if self.parse_keywords(&[Keyword::RENAME, Keyword::TO]) {
            AlterTextSearchOperation::RenameTo {
                new_name: self.parse_identifier()?,
            }
        } else if self.parse_keywords(&[Keyword::OWNER, Keyword::TO]) {
            AlterTextSearchOperation::OwnerTo(self.parse_owner()?)
        } else if self.parse_keywords(&[Keyword::SET, Keyword::SCHEMA]) {
            AlterTextSearchOperation::SetSchema {
                schema_name: self.parse_object_name(false)?,
            }
        } else if self.consume_token(&Token::LParen) {
            let options = self.parse_comma_separated(Parser::parse_alter_text_search_option)?;
            self.expect_token(&Token::RParen)?;
            AlterTextSearchOperation::SetOptions { options }
        } else {
            let expected = "RENAME TO, OWNER TO, SET SCHEMA, or (...) after ALTER TEXT SEARCH";
            return self.expected_ref(expected, self.peek_token_ref());
        };

        Ok(AlterTextSearch {
            object_type,
            name,
            operation,
        })
    }

    fn parse_create_user(&mut self, or_replace: bool) -> Result<CreateUser, ParserError> {
        let if_not_exists = self.parse_keywords(&[Keyword::IF, Keyword::NOT, Keyword::EXISTS]);
        let name = self.parse_identifier()?;
        let options = self
            .parse_key_value_options(false, &[Keyword::WITH, Keyword::TAG])?
            .options;
        let with_tags = self.parse_keyword(Keyword::WITH);
        let tags = if self.parse_keyword(Keyword::TAG) {
            self.parse_key_value_options(true, &[])?.options
        } else {
            vec![]
        };
        Ok(CreateUser {
            or_replace,
            if_not_exists,
            name,
            options: KeyValueOptions {
                options,
                delimiter: KeyValueOptionsDelimiter::Space,
            },
            with_tags,
            tags: KeyValueOptions {
                options: tags,
                delimiter: KeyValueOptionsDelimiter::Comma,
            },
        })
    }

    /// Parse a `CREATE WAREHOUSE` statement.
    ///
    /// See <https://docs.snowflake.com/en/sql-reference/sql/create-warehouse>
    fn parse_create_warehouse(&mut self, or_replace: bool) -> Result<CreateWarehouse, ParserError> {
        let if_not_exists = self.parse_keywords(&[Keyword::IF, Keyword::NOT, Keyword::EXISTS]);
        let name = self.parse_object_name(false)?;
        let _ = self.parse_keyword(Keyword::WITH);
        let options = self.parse_key_value_options(false, &[])?;
        Ok(CreateWarehouse {
            or_replace,
            if_not_exists,
            name,
            options,
        })
    }

    /// See [DuckDB Docs](https://duckdb.org/docs/sql/statements/create_secret.html) for more details.
    pub fn parse_create_secret(
        &mut self,
        or_replace: bool,
        temporary: bool,
        persistent: bool,
    ) -> Result<Statement, ParserError> {
        let if_not_exists = self.parse_keywords(&[Keyword::IF, Keyword::NOT, Keyword::EXISTS]);

        let mut storage_specifier = None;
        let mut name = None;
        if self.peek_token_ref().token != Token::LParen {
            if self.parse_keyword(Keyword::IN) {
                storage_specifier = self.parse_identifier().ok()
            } else {
                name = self.parse_identifier().ok();
            }

            // Storage specifier may follow the name
            if storage_specifier.is_none()
                && self.peek_token_ref().token != Token::LParen
                && self.parse_keyword(Keyword::IN)
            {
                storage_specifier = self.parse_identifier().ok();
            }
        }

        self.expect_token(&Token::LParen)?;
        self.expect_keyword_is(Keyword::TYPE)?;
        let secret_type = self.parse_identifier()?;

        let mut options = Vec::new();
        if self.consume_token(&Token::Comma) {
            options.append(&mut self.parse_comma_separated(|p| {
                let key = p.parse_identifier()?;
                let value = p.parse_identifier()?;
                Ok(SecretOption { key, value })
            })?);
        }
        self.expect_token(&Token::RParen)?;

        let temp = match (temporary, persistent) {
            (true, false) => Some(true),
            (false, true) => Some(false),
            (false, false) => None,
            _ => self.expected_ref("TEMPORARY or PERSISTENT", self.peek_token_ref())?,
        };

        Ok(Statement::CreateSecret {
            or_replace,
            temporary: temp,
            if_not_exists,
            name,
            storage_specifier,
            secret_type,
            options,
        })
    }

    /// Parse a CACHE TABLE statement
    pub fn parse_cache_table(&mut self) -> Result<Statement, ParserError> {
        let (mut table_flag, mut options, mut has_as, mut query) = (None, vec![], false, None);
        if self.parse_keyword(Keyword::TABLE) {
            let table_name = self.parse_object_name(false)?;
            if self.peek_token_ref().token != Token::EOF {
                if let Token::Word(word) = &self.peek_token_ref().token {
                    if word.keyword == Keyword::OPTIONS {
                        options = self.parse_options(Keyword::OPTIONS)?
                    }
                };

                if self.peek_token_ref().token != Token::EOF {
                    let (a, q) = self.parse_as_query()?;
                    has_as = a;
                    query = Some(q);
                }

                Ok(Statement::Cache {
                    table_flag,
                    table_name,
                    has_as,
                    options,
                    query,
                })
            } else {
                Ok(Statement::Cache {
                    table_flag,
                    table_name,
                    has_as,
                    options,
                    query,
                })
            }
        } else {
            table_flag = Some(self.parse_object_name(false)?);
            if self.parse_keyword(Keyword::TABLE) {
                let table_name = self.parse_object_name(false)?;
                if self.peek_token_ref().token != Token::EOF {
                    if let Token::Word(word) = &self.peek_token_ref().token {
                        if word.keyword == Keyword::OPTIONS {
                            options = self.parse_options(Keyword::OPTIONS)?
                        }
                    };

                    if self.peek_token_ref().token != Token::EOF {
                        let (a, q) = self.parse_as_query()?;
                        has_as = a;
                        query = Some(q);
                    }

                    Ok(Statement::Cache {
                        table_flag,
                        table_name,
                        has_as,
                        options,
                        query,
                    })
                } else {
                    Ok(Statement::Cache {
                        table_flag,
                        table_name,
                        has_as,
                        options,
                        query,
                    })
                }
            } else {
                if self.peek_token_ref().token == Token::EOF {
                    self.prev_token();
                }
                self.expected_ref("a `TABLE` keyword", self.peek_token_ref())
            }
        }
    }

    /// Parse 'AS' before as query,such as `WITH XXX AS SELECT XXX` oer `CACHE TABLE AS SELECT XXX`
    pub fn parse_as_query(&mut self) -> Result<(bool, Box<Query>), ParserError> {
        match &self.peek_token_ref().token {
            Token::Word(word) => match word.keyword {
                Keyword::AS => {
                    self.next_token();
                    Ok((true, self.parse_query()?))
                }
                _ => Ok((false, self.parse_query()?)),
            },
            _ => self.expected_ref("a QUERY statement", self.peek_token_ref()),
        }
    }

    /// Parse a UNCACHE TABLE statement
    pub fn parse_uncache_table(&mut self) -> Result<Statement, ParserError> {
        self.expect_keyword_is(Keyword::TABLE)?;
        let if_exists = self.parse_keywords(&[Keyword::IF, Keyword::EXISTS]);
        let table_name = self.parse_object_name(false)?;
        Ok(Statement::UNCache {
            table_name,
            if_exists,
        })
    }

    /// SQLite-specific `CREATE VIRTUAL TABLE`
    pub fn parse_create_virtual_table(&mut self) -> Result<Statement, ParserError> {
        self.expect_keyword_is(Keyword::TABLE)?;
        let if_not_exists = self.parse_keywords(&[Keyword::IF, Keyword::NOT, Keyword::EXISTS]);
        let table_name = self.parse_object_name(false)?;
        self.expect_keyword_is(Keyword::USING)?;
        let module_name = self.parse_identifier()?;
        // SQLite docs note that module "arguments syntax is sufficiently
        // general that the arguments can be made to appear as column
        // definitions in a traditional CREATE TABLE statement", but
        // we don't implement that.
        let module_args = self.parse_parenthesized_column_list(Optional, false)?;
        Ok(Statement::CreateVirtualTable {
            name: table_name,
            if_not_exists,
            module_name,
            module_args,
        })
    }

    /// Parse a `CREATE SCHEMA` statement.
    pub fn parse_create_schema(&mut self, or_replace: bool) -> Result<Statement, ParserError> {
        let if_not_exists = self.parse_keywords(&[Keyword::IF, Keyword::NOT, Keyword::EXISTS]);

        let schema_name = self.parse_schema_name()?;

        let default_collate_spec = if self.parse_keywords(&[Keyword::DEFAULT, Keyword::COLLATE]) {
            Some(self.parse_expr()?)
        } else {
            None
        };

        let with = if self.peek_keyword(Keyword::WITH) {
            Some(self.parse_options(Keyword::WITH)?)
        } else {
            None
        };

        let options = if self.peek_keyword(Keyword::OPTIONS) {
            Some(self.parse_options(Keyword::OPTIONS)?)
        } else {
            None
        };

        let clone = if self.parse_keyword(Keyword::CLONE) {
            Some(self.parse_object_name(false)?)
        } else {
            None
        };

        Ok(Statement::CreateSchema {
            schema_name,
            or_replace,
            if_not_exists,
            with,
            options,
            default_collate_spec,
            clone,
        })
    }

    fn parse_schema_name(&mut self) -> Result<SchemaName, ParserError> {
        if self.parse_keyword(Keyword::AUTHORIZATION) {
            Ok(SchemaName::UnnamedAuthorization(self.parse_identifier()?))
        } else {
            let name = self.parse_object_name(false)?;

            if self.parse_keyword(Keyword::AUTHORIZATION) {
                Ok(SchemaName::NamedAuthorization(
                    name,
                    self.parse_identifier()?,
                ))
            } else {
                Ok(SchemaName::Simple(name))
            }
        }
    }

    /// Parse a `CREATE DATABASE` statement.
    pub fn parse_create_database(&mut self) -> Result<Statement, ParserError> {
        let ine = self.parse_keywords(&[Keyword::IF, Keyword::NOT, Keyword::EXISTS]);
        let db_name = self.parse_object_name(false)?;
        let mut location = None;
        let mut managed_location = None;
        loop {
            match self.parse_one_of_keywords(&[Keyword::LOCATION, Keyword::MANAGEDLOCATION]) {
                Some(Keyword::LOCATION) => location = Some(self.parse_literal_string()?),
                Some(Keyword::MANAGEDLOCATION) => {
                    managed_location = Some(self.parse_literal_string()?)
                }
                _ => break,
            }
        }
        let clone = if self.parse_keyword(Keyword::CLONE) {
            Some(self.parse_object_name(false)?)
        } else {
            None
        };

        // Parse MySQL-style [DEFAULT] CHARACTER SET and [DEFAULT] COLLATE options
        //
        // Note: The docs only mention `CHARACTER SET`, but `CHARSET` is also supported.
        // Furthermore, MySQL will only accept one character set, raising an error if there is more
        // than one, but will accept multiple collations and use the last one.
        //
        // <https://dev.mysql.com/doc/refman/8.4/en/create-database.html>
        let mut default_charset = None;
        let mut default_collation = None;
        loop {
            let has_default = self.parse_keyword(Keyword::DEFAULT);
            if default_charset.is_none() && self.parse_keywords(&[Keyword::CHARACTER, Keyword::SET])
                || self.parse_keyword(Keyword::CHARSET)
            {
                let _ = self.consume_token(&Token::Eq);
                default_charset = Some(self.parse_identifier()?.value);
            } else if self.parse_keyword(Keyword::COLLATE) {
                let _ = self.consume_token(&Token::Eq);
                default_collation = Some(self.parse_identifier()?.value);
            } else if has_default {
                // DEFAULT keyword not followed by CHARACTER SET, CHARSET, or COLLATE
                self.prev_token();
                break;
            } else {
                break;
            }
        }

        Ok(Statement::CreateDatabase {
            db_name,
            if_not_exists: ine,
            location,
            managed_location,
            or_replace: false,
            transient: false,
            clone,
            data_retention_time_in_days: None,
            max_data_extension_time_in_days: None,
            external_volume: None,
            catalog: None,
            replace_invalid_characters: None,
            default_ddl_collation: None,
            storage_serialization_policy: None,
            comment: None,
            default_charset,
            default_collation,
            catalog_sync: None,
            catalog_sync_namespace_mode: None,
            catalog_sync_namespace_flatten_delimiter: None,
            with_tags: None,
            with_contacts: None,
        })
    }

    /// Parse an optional `USING` clause for `CREATE FUNCTION`.
    pub fn parse_optional_create_function_using(
        &mut self,
    ) -> Result<Option<CreateFunctionUsing>, ParserError> {
        if !self.parse_keyword(Keyword::USING) {
            return Ok(None);
        };
        let keyword =
            self.expect_one_of_keywords(&[Keyword::JAR, Keyword::FILE, Keyword::ARCHIVE])?;

        let uri = self.parse_literal_string()?;

        match keyword {
            Keyword::JAR => Ok(Some(CreateFunctionUsing::Jar(uri))),
            Keyword::FILE => Ok(Some(CreateFunctionUsing::File(uri))),
            Keyword::ARCHIVE => Ok(Some(CreateFunctionUsing::Archive(uri))),
            _ => self.expected(
                "JAR, FILE or ARCHIVE, got {:?}",
                TokenWithSpan::wrap(Token::make_keyword(format!("{keyword:?}").as_str())),
            ),
        }
    }

    /// Parse a `CREATE FUNCTION` statement.
    pub fn parse_create_function(
        &mut self,
        or_alter: bool,
        or_replace: bool,
        temporary: bool,
    ) -> Result<Statement, ParserError> {
        if dialect_of!(self is HiveDialect) {
            self.parse_hive_create_function(or_replace, temporary)
                .map(Into::into)
        } else if dialect_of!(self is PostgreSqlDialect | GenericDialect) {
            self.parse_postgres_create_function(or_replace, temporary)
                .map(Into::into)
        } else if dialect_of!(self is DuckDbDialect) {
            self.parse_create_macro(or_replace, temporary)
        } else if dialect_of!(self is BigQueryDialect) {
            self.parse_bigquery_create_function(or_replace, temporary)
                .map(Into::into)
        } else if dialect_of!(self is MsSqlDialect) {
            self.parse_mssql_create_function(or_alter, or_replace, temporary)
                .map(Into::into)
        } else {
            self.prev_token();
            self.expected_ref("an object type after CREATE", self.peek_token_ref())
        }
    }

    /// Parse `CREATE FUNCTION` for [PostgreSQL]
    ///
    /// [PostgreSQL]: https://www.postgresql.org/docs/15/sql-createfunction.html
    fn parse_postgres_create_function(
        &mut self,
        or_replace: bool,
        temporary: bool,
    ) -> Result<CreateFunction, ParserError> {
        let name = self.parse_object_name(false)?;

        self.expect_token(&Token::LParen)?;
        let args = if Token::RParen != self.peek_token_ref().token {
            self.parse_comma_separated(Parser::parse_function_arg)?
        } else {
            vec![]
        };
        self.expect_token(&Token::RParen)?;

        let return_type = if self.parse_keyword(Keyword::RETURNS) {
            Some(self.parse_function_return_type()?)
        } else {
            None
        };

        #[derive(Default)]
        struct Body {
            language: Option<Ident>,
            behavior: Option<FunctionBehavior>,
            function_body: Option<CreateFunctionBody>,
            called_on_null: Option<FunctionCalledOnNull>,
            parallel: Option<FunctionParallel>,
            security: Option<FunctionSecurity>,
        }
        let mut body = Body::default();
        let mut set_params: Vec<FunctionDefinitionSetParam> = Vec::new();
        loop {
            fn ensure_not_set<T>(field: &Option<T>, name: &str) -> Result<(), ParserError> {
                if field.is_some() {
                    return Err(ParserError::ParserError(format!(
                        "{name} specified more than once",
                    )));
                }
                Ok(())
            }
            if self.parse_keyword(Keyword::AS) {
                ensure_not_set(&body.function_body, "AS")?;
                body.function_body = Some(self.parse_create_function_body_string()?);
            } else if self.parse_keyword(Keyword::LANGUAGE) {
                ensure_not_set(&body.language, "LANGUAGE")?;
                body.language = Some(self.parse_identifier()?);
            } else if self.parse_keyword(Keyword::IMMUTABLE) {
                ensure_not_set(&body.behavior, "IMMUTABLE | STABLE | VOLATILE")?;
                body.behavior = Some(FunctionBehavior::Immutable);
            } else if self.parse_keyword(Keyword::STABLE) {
                ensure_not_set(&body.behavior, "IMMUTABLE | STABLE | VOLATILE")?;
                body.behavior = Some(FunctionBehavior::Stable);
            } else if self.parse_keyword(Keyword::VOLATILE) {
                ensure_not_set(&body.behavior, "IMMUTABLE | STABLE | VOLATILE")?;
                body.behavior = Some(FunctionBehavior::Volatile);
            } else if self.parse_keywords(&[
                Keyword::CALLED,
                Keyword::ON,
                Keyword::NULL,
                Keyword::INPUT,
            ]) {
                ensure_not_set(
                    &body.called_on_null,
                    "CALLED ON NULL INPUT | RETURNS NULL ON NULL INPUT | STRICT",
                )?;
                body.called_on_null = Some(FunctionCalledOnNull::CalledOnNullInput);
            } else if self.parse_keywords(&[
                Keyword::RETURNS,
                Keyword::NULL,
                Keyword::ON,
                Keyword::NULL,
                Keyword::INPUT,
            ]) {
                ensure_not_set(
                    &body.called_on_null,
                    "CALLED ON NULL INPUT | RETURNS NULL ON NULL INPUT | STRICT",
                )?;
                body.called_on_null = Some(FunctionCalledOnNull::ReturnsNullOnNullInput);
            } else if self.parse_keyword(Keyword::STRICT) {
                ensure_not_set(
                    &body.called_on_null,
                    "CALLED ON NULL INPUT | RETURNS NULL ON NULL INPUT | STRICT",
                )?;
                body.called_on_null = Some(FunctionCalledOnNull::Strict);
            } else if self.parse_keyword(Keyword::PARALLEL) {
                ensure_not_set(&body.parallel, "PARALLEL { UNSAFE | RESTRICTED | SAFE }")?;
                if self.parse_keyword(Keyword::UNSAFE) {
                    body.parallel = Some(FunctionParallel::Unsafe);
                } else if self.parse_keyword(Keyword::RESTRICTED) {
                    body.parallel = Some(FunctionParallel::Restricted);
                } else if self.parse_keyword(Keyword::SAFE) {
                    body.parallel = Some(FunctionParallel::Safe);
                } else {
                    return self
                        .expected_ref("one of UNSAFE | RESTRICTED | SAFE", self.peek_token_ref());
                }
            } else if self.parse_keyword(Keyword::SECURITY) {
                ensure_not_set(&body.security, "SECURITY { DEFINER | INVOKER }")?;
                if self.parse_keyword(Keyword::DEFINER) {
                    body.security = Some(FunctionSecurity::Definer);
                } else if self.parse_keyword(Keyword::INVOKER) {
                    body.security = Some(FunctionSecurity::Invoker);
                } else {
                    return self.expected_ref("DEFINER or INVOKER", self.peek_token_ref());
                }
            } else if self.parse_keyword(Keyword::SET) {
                let name = self.parse_object_name(false)?;
                let value = if self.parse_keywords(&[Keyword::FROM, Keyword::CURRENT]) {
                    FunctionSetValue::FromCurrent
                } else {
                    if !self.consume_token(&Token::Eq) && !self.parse_keyword(Keyword::TO) {
                        return self.expected_ref("= or TO", self.peek_token_ref());
                    }
                    if self.parse_keyword(Keyword::DEFAULT) {
                        FunctionSetValue::Default
                    } else {
                        let values = self.parse_comma_separated(Parser::parse_expr)?;
                        FunctionSetValue::Values(values)
                    }
                };
                set_params.push(FunctionDefinitionSetParam { name, value });
            } else if self.parse_keyword(Keyword::RETURN) {
                ensure_not_set(&body.function_body, "RETURN")?;
                body.function_body = Some(CreateFunctionBody::Return(self.parse_expr()?));
            } else {
                break;
            }
        }

        Ok(CreateFunction {
            or_alter: false,
            or_replace,
            temporary,
            name,
            args: Some(args),
            return_type,
            behavior: body.behavior,
            called_on_null: body.called_on_null,
            parallel: body.parallel,
            security: body.security,
            set_params,
            language: body.language,
            function_body: body.function_body,
            if_not_exists: false,
            using: None,
            determinism_specifier: None,
            options: None,
            remote_connection: None,
        })
    }

    /// Parse `CREATE FUNCTION` for [Hive]
    ///
    /// [Hive]: https://cwiki.apache.org/confluence/display/hive/languagemanual+ddl#LanguageManualDDL-Create/Drop/ReloadFunction
    fn parse_hive_create_function(
        &mut self,
        or_replace: bool,
        temporary: bool,
    ) -> Result<CreateFunction, ParserError> {
        let name = self.parse_object_name(false)?;
        self.expect_keyword_is(Keyword::AS)?;

        let body = self.parse_create_function_body_string()?;
        let using = self.parse_optional_create_function_using()?;

        Ok(CreateFunction {
            or_alter: false,
            or_replace,
            temporary,
            name,
            function_body: Some(body),
            using,
            if_not_exists: false,
            args: None,
            return_type: None,
            behavior: None,
            called_on_null: None,
            parallel: None,
            security: None,
            set_params: vec![],
            language: None,
            determinism_specifier: None,
            options: None,
            remote_connection: None,
        })
    }

    /// Parse `CREATE FUNCTION` for [BigQuery]
    ///
    /// [BigQuery]: https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#create_function_statement
    fn parse_bigquery_create_function(
        &mut self,
        or_replace: bool,
        temporary: bool,
    ) -> Result<CreateFunction, ParserError> {
        let if_not_exists = self.parse_keywords(&[Keyword::IF, Keyword::NOT, Keyword::EXISTS]);
        let (name, args) = self.parse_create_function_name_and_params()?;

        let return_type = if self.parse_keyword(Keyword::RETURNS) {
            Some(self.parse_function_return_type()?)
        } else {
            None
        };

        let determinism_specifier = if self.parse_keyword(Keyword::DETERMINISTIC) {
            Some(FunctionDeterminismSpecifier::Deterministic)
        } else if self.parse_keywords(&[Keyword::NOT, Keyword::DETERMINISTIC]) {
            Some(FunctionDeterminismSpecifier::NotDeterministic)
        } else {
            None
        };

        let language = if self.parse_keyword(Keyword::LANGUAGE) {
            Some(self.parse_identifier()?)
        } else {
            None
        };

        let remote_connection =
            if self.parse_keywords(&[Keyword::REMOTE, Keyword::WITH, Keyword::CONNECTION]) {
                Some(self.parse_object_name(false)?)
            } else {
                None
            };

        // `OPTIONS` may come before of after the function body but
        // may be specified at most once.
        let mut options = self.maybe_parse_options(Keyword::OPTIONS)?;

        let function_body = if remote_connection.is_none() {
            self.expect_keyword_is(Keyword::AS)?;
            let expr = self.parse_expr()?;
            if options.is_none() {
                options = self.maybe_parse_options(Keyword::OPTIONS)?;
                Some(CreateFunctionBody::AsBeforeOptions {
                    body: expr,
                    link_symbol: None,
                })
            } else {
                Some(CreateFunctionBody::AsAfterOptions(expr))
            }
        } else {
            None
        };

        Ok(CreateFunction {
            or_alter: false,
            or_replace,
            temporary,
            if_not_exists,
            name,
            args: Some(args),
            return_type,
            function_body,
            language,
            determinism_specifier,
            options,
            remote_connection,
            using: None,
            behavior: None,
            called_on_null: None,
            parallel: None,
            security: None,
            set_params: vec![],
        })
    }

    /// Parse `CREATE FUNCTION` for [MsSql]
    ///
    /// [MsSql]: https://learn.microsoft.com/en-us/sql/t-sql/statements/create-function-transact-sql
    fn parse_mssql_create_function(
        &mut self,
        or_alter: bool,
        or_replace: bool,
        temporary: bool,
    ) -> Result<CreateFunction, ParserError> {
        let (name, args) = self.parse_create_function_name_and_params()?;

        self.expect_keyword(Keyword::RETURNS)?;

        let return_table = self.maybe_parse(|p| {
            let return_table_name = p.parse_identifier()?;

            p.expect_keyword_is(Keyword::TABLE)?;
            p.prev_token();

            let table_column_defs = match p.parse_data_type()? {
                DataType::Table(Some(table_column_defs)) if !table_column_defs.is_empty() => {
                    table_column_defs
                }
                _ => parser_err!(
                    "Expected table column definitions after TABLE keyword",
                    p.peek_token_ref().span.start
                )?,
            };

            Ok(DataType::NamedTable {
                name: ObjectName(vec![ObjectNamePart::Identifier(return_table_name)]),
                columns: table_column_defs,
            })
        })?;

        let data_type = match return_table {
            Some(table_type) => table_type,
            None => self.parse_data_type()?,
        };
        let return_type = Some(FunctionReturnType::DataType(data_type));

        let _ = self.parse_keyword(Keyword::AS);

        let function_body = if self.peek_keyword(Keyword::BEGIN) {
            let begin_token = self.expect_keyword(Keyword::BEGIN)?;
            let statements = self.parse_statement_list(&[Keyword::END])?;
            let end_token = self.expect_keyword(Keyword::END)?;

            Some(CreateFunctionBody::AsBeginEnd(BeginEndStatements {
                begin_token: AttachedToken(begin_token),
                statements,
                end_token: AttachedToken(end_token),
            }))
        } else if self.parse_keyword(Keyword::RETURN) {
            if self.peek_token_ref().token == Token::LParen {
                Some(CreateFunctionBody::AsReturnExpr(self.parse_expr()?))
            } else if self.peek_keyword(Keyword::SELECT) {
                let select = self.parse_select()?;
                Some(CreateFunctionBody::AsReturnSelect(select))
            } else {
                parser_err!(
                    "Expected a subquery (or bare SELECT statement) after RETURN",
                    self.peek_token_ref().span.start
                )?
            }
        } else {
            parser_err!("Unparsable function body", self.peek_token_ref().span.start)?
        };

        Ok(CreateFunction {
            or_alter,
            or_replace,
            temporary,
            if_not_exists: false,
            name,
            args: Some(args),
            return_type,
            function_body,
            language: None,
            determinism_specifier: None,
            options: None,
            remote_connection: None,
            using: None,
            behavior: None,
            called_on_null: None,
            parallel: None,
            security: None,
            set_params: vec![],
        })
    }

    fn parse_function_return_type(&mut self) -> Result<FunctionReturnType, ParserError> {
        if self.parse_keyword(Keyword::SETOF) {
            Ok(FunctionReturnType::SetOf(self.parse_data_type()?))
        } else {
            Ok(FunctionReturnType::DataType(self.parse_data_type()?))
        }
    }

    fn parse_create_function_name_and_params(
        &mut self,
    ) -> Result<(ObjectName, Vec<OperateFunctionArg>), ParserError> {
        let name = self.parse_object_name(false)?;
        let parse_function_param =
            |parser: &mut Parser| -> Result<OperateFunctionArg, ParserError> {
                let name = parser.parse_identifier()?;
                let data_type = parser.parse_data_type()?;
                let default_expr = if parser.consume_token(&Token::Eq) {
                    Some(parser.parse_expr()?)
                } else {
                    None
                };

                Ok(OperateFunctionArg {
                    mode: None,
                    name: Some(name),
                    data_type,
                    default_expr,
                })
            };
        self.expect_token(&Token::LParen)?;
        let args = self.parse_comma_separated0(parse_function_param, Token::RParen)?;
        self.expect_token(&Token::RParen)?;
        Ok((name, args))
    }

    fn parse_function_arg(&mut self) -> Result<OperateFunctionArg, ParserError> {
        let mode = if self.parse_keyword(Keyword::IN) {
            Some(ArgMode::In)
        } else if self.parse_keyword(Keyword::OUT) {
            Some(ArgMode::Out)
        } else if self.parse_keyword(Keyword::INOUT) {
            Some(ArgMode::InOut)
        } else if self.parse_keyword(Keyword::VARIADIC) {
            Some(ArgMode::Variadic)
        } else {
            None
        };

        // parse: [ argname ] argtype
        let mut name = None;
        let mut data_type = self.parse_data_type()?;

        // To check whether the first token is a name or a type, we need to
        // peek the next token, which if it is another type keyword, then the
        // first token is a name and not a type in itself.
        let data_type_idx = self.get_current_index();

        // DEFAULT will be parsed as `DataType::Custom`, which is undesirable in this context
        fn parse_data_type_no_default(parser: &mut Parser) -> Result<DataType, ParserError> {
            if parser.peek_keyword(Keyword::DEFAULT) {
                // This dummy error is ignored in `maybe_parse`
                parser_err!(
                    "The DEFAULT keyword is not a type",
                    parser.peek_token_ref().span.start
                )
            } else {
                parser.parse_data_type()
            }
        }

        if let Some(next_data_type) = self.maybe_parse(parse_data_type_no_default)? {
            let token = self.token_at(data_type_idx).clone();

            // We ensure that the token is a `Word` token, and not other special tokens.
            match token.token {
                Token::Word(word) => name = Some(word.into_ident(token.span)),
                _ => return self.expected("a name or type", token),
            }

            data_type = next_data_type;
        }

        let default_expr = if self.parse_keyword(Keyword::DEFAULT) || self.consume_token(&Token::Eq)
        {
            Some(self.parse_expr()?)
        } else {
            None
        };
        Ok(OperateFunctionArg {
            mode,
            name,
            data_type,
            default_expr,
        })
    }

    fn parse_aggregate_function_arg(&mut self) -> Result<OperateFunctionArg, ParserError> {
        let mode = if self.parse_keyword(Keyword::IN) {
            Some(ArgMode::In)
        } else {
            if self
                .peek_one_of_keywords(&[Keyword::OUT, Keyword::INOUT, Keyword::VARIADIC])
                .is_some()
            {
                return self.expected_ref(
                    "IN or argument type in aggregate signature",
                    self.peek_token_ref(),
                );
            }
            None
        };

        // Parse: [ argname ] argtype, but do not consume ORDER from
        // `... argtype ORDER BY ...` as a type-name disambiguator.
        let mut name = None;
        let mut data_type = self.parse_data_type()?;
        let data_type_idx = self.get_current_index();

        fn parse_data_type_for_aggregate_arg(parser: &mut Parser) -> Result<DataType, ParserError> {
            if parser.peek_keyword(Keyword::DEFAULT)
                || parser.peek_keyword(Keyword::ORDER)
                || parser.peek_token_ref().token == Token::Comma
                || parser.peek_token_ref().token == Token::RParen
            {
                // Dummy error ignored by maybe_parse
                parser_err!(
                    "The current token cannot start an aggregate argument type",
                    parser.peek_token_ref().span.start
                )
            } else {
                parser.parse_data_type()
            }
        }

        if let Some(next_data_type) = self.maybe_parse(parse_data_type_for_aggregate_arg)? {
            let token = self.token_at(data_type_idx).clone();
            match token.token {
                Token::Word(word) => name = Some(word.into_ident(token.span)),
                _ => return self.expected("a name or type", token),
            }

            data_type = next_data_type;
        }

        if self.peek_keyword(Keyword::DEFAULT) || self.peek_token_ref().token == Token::Eq {
            return self.expected_ref(
                "',' or ')' or ORDER BY after aggregate argument type",
                self.peek_token_ref(),
            );
        }

        Ok(OperateFunctionArg {
            mode,
            name,
            data_type,
            default_expr: None,
        })
    }

    /// Parse statements of the DropTrigger type such as:
    ///
    /// ```sql
    /// DROP TRIGGER [ IF EXISTS ] name ON table_name [ CASCADE | RESTRICT ]
    /// ```
    pub fn parse_drop_trigger(&mut self) -> Result<DropTrigger, ParserError> {
        if !dialect_of!(self is PostgreSqlDialect | SQLiteDialect | GenericDialect | MySqlDialect | MsSqlDialect)
        {
            self.prev_token();
            return self.expected_ref("an object type after DROP", self.peek_token_ref());
        }
        let if_exists = self.parse_keywords(&[Keyword::IF, Keyword::EXISTS]);
        let trigger_name = self.parse_object_name(false)?;
        let table_name = if self.parse_keyword(Keyword::ON) {
            Some(self.parse_object_name(false)?)
        } else {
            None
        };
        let option = match self.parse_one_of_keywords(&[Keyword::CASCADE, Keyword::RESTRICT]) {
            Some(Keyword::CASCADE) => Some(ReferentialAction::Cascade),
            Some(Keyword::RESTRICT) => Some(ReferentialAction::Restrict),
            Some(unexpected_keyword) => return Err(ParserError::ParserError(
                format!("Internal parser error: expected any of {{CASCADE, RESTRICT}}, got {unexpected_keyword:?}"),
            )),
            None => None,
        };
        Ok(DropTrigger {
            if_exists,
            trigger_name,
            table_name,
            option,
        })
    }

    /// Parse a `CREATE TRIGGER` statement.
    pub fn parse_create_trigger(
        &mut self,
        temporary: bool,
        or_alter: bool,
        or_replace: bool,
        is_constraint: bool,
    ) -> Result<CreateTrigger, ParserError> {
        if !dialect_of!(self is PostgreSqlDialect | SQLiteDialect | GenericDialect | MySqlDialect | MsSqlDialect)
        {
            self.prev_token();
            return self.expected_ref("an object type after CREATE", self.peek_token_ref());
        }

        let name = self.parse_object_name(false)?;
        let period = self.maybe_parse(|parser| parser.parse_trigger_period())?;

        let events = self.parse_keyword_separated(Keyword::OR, Parser::parse_trigger_event)?;
        self.expect_keyword_is(Keyword::ON)?;
        let table_name = self.parse_object_name(false)?;

        let referenced_table_name = if self.parse_keyword(Keyword::FROM) {
            self.parse_object_name(true).ok()
        } else {
            None
        };

        let characteristics = self.parse_constraint_characteristics()?;

        let mut referencing = vec![];
        if self.parse_keyword(Keyword::REFERENCING) {
            while let Some(refer) = self.parse_trigger_referencing()? {
                referencing.push(refer);
            }
        }

        let trigger_object = if self.parse_keyword(Keyword::FOR) {
            let include_each = self.parse_keyword(Keyword::EACH);
            let trigger_object =
                match self.expect_one_of_keywords(&[Keyword::ROW, Keyword::STATEMENT])? {
                    Keyword::ROW => TriggerObject::Row,
                    Keyword::STATEMENT => TriggerObject::Statement,
                    unexpected_keyword => return Err(ParserError::ParserError(
                        format!("Internal parser error: unexpected keyword `{unexpected_keyword}` in ROW/STATEMENT"),
                    )),
                };

            Some(if include_each {
                TriggerObjectKind::ForEach(trigger_object)
            } else {
                TriggerObjectKind::For(trigger_object)
            })
        } else {
            let _ = self.parse_keyword(Keyword::FOR);

            None
        };

        let condition = self
            .parse_keyword(Keyword::WHEN)
            .then(|| self.parse_expr())
            .transpose()?;

        let mut exec_body = None;
        let mut statements = None;
        if self.parse_keyword(Keyword::EXECUTE) {
            exec_body = Some(self.parse_trigger_exec_body()?);
        } else {
            statements = Some(self.parse_conditional_statements(&[Keyword::END])?);
        }

        Ok(CreateTrigger {
            or_alter,
            temporary,
            or_replace,
            is_constraint,
            name,
            period,
            period_before_table: true,
            events,
            table_name,
            referenced_table_name,
            referencing,
            trigger_object,
            condition,
            exec_body,
            statements_as: false,
            statements,
            characteristics,
        })
    }

    /// Parse the period part of a trigger (`BEFORE`, `AFTER`, etc.).
    pub fn parse_trigger_period(&mut self) -> Result<TriggerPeriod, ParserError> {
        Ok(
            match self.expect_one_of_keywords(&[
                Keyword::FOR,
                Keyword::BEFORE,
                Keyword::AFTER,
                Keyword::INSTEAD,
            ])? {
                Keyword::FOR => TriggerPeriod::For,
                Keyword::BEFORE => TriggerPeriod::Before,
                Keyword::AFTER => TriggerPeriod::After,
                Keyword::INSTEAD => self
                    .expect_keyword_is(Keyword::OF)
                    .map(|_| TriggerPeriod::InsteadOf)?,
                unexpected_keyword => return Err(ParserError::ParserError(
                    format!("Internal parser error: unexpected keyword `{unexpected_keyword}` in trigger period"),
                )),
            },
        )
    }

    /// Parse the event part of a trigger (`INSERT`, `UPDATE`, etc.).
    pub fn parse_trigger_event(&mut self) -> Result<TriggerEvent, ParserError> {
        Ok(
            match self.expect_one_of_keywords(&[
                Keyword::INSERT,
                Keyword::UPDATE,
                Keyword::DELETE,
                Keyword::TRUNCATE,
            ])? {
                Keyword::INSERT => TriggerEvent::Insert,
                Keyword::UPDATE => {
                    if self.parse_keyword(Keyword::OF) {
                        let cols = self.parse_comma_separated(Parser::parse_identifier)?;
                        TriggerEvent::Update(cols)
                    } else {
                        TriggerEvent::Update(vec![])
                    }
                }
                Keyword::DELETE => TriggerEvent::Delete,
                Keyword::TRUNCATE => TriggerEvent::Truncate,
                unexpected_keyword => return Err(ParserError::ParserError(
                    format!("Internal parser error: unexpected keyword `{unexpected_keyword}` in trigger event"),
                )),
            },
        )
    }

    /// Parse the `REFERENCING` clause of a trigger.
    pub fn parse_trigger_referencing(&mut self) -> Result<Option<TriggerReferencing>, ParserError> {
        let refer_type = match self.parse_one_of_keywords(&[Keyword::OLD, Keyword::NEW]) {
            Some(Keyword::OLD) if self.parse_keyword(Keyword::TABLE) => {
                TriggerReferencingType::OldTable
            }
            Some(Keyword::NEW) if self.parse_keyword(Keyword::TABLE) => {
                TriggerReferencingType::NewTable
            }
            _ => {
                return Ok(None);
            }
        };

        let is_as = self.parse_keyword(Keyword::AS);
        let transition_relation_name = self.parse_object_name(false)?;
        Ok(Some(TriggerReferencing {
            refer_type,
            is_as,
            transition_relation_name,
        }))
    }

    /// Parse the execution body of a trigger (`FUNCTION` or `PROCEDURE`).
    pub fn parse_trigger_exec_body(&mut self) -> Result<TriggerExecBody, ParserError> {
        Ok(TriggerExecBody {
            exec_type: match self
                .expect_one_of_keywords(&[Keyword::FUNCTION, Keyword::PROCEDURE])?
            {
                Keyword::FUNCTION => TriggerExecBodyType::Function,
                Keyword::PROCEDURE => TriggerExecBodyType::Procedure,
                unexpected_keyword => return Err(ParserError::ParserError(
                    format!("Internal parser error: unexpected keyword `{unexpected_keyword}` in trigger exec body"),
                )),
            },
            func_desc: self.parse_function_desc()?,
        })
    }

    /// Parse a `CREATE MACRO` statement.
    pub fn parse_create_macro(
        &mut self,
        or_replace: bool,
        temporary: bool,
    ) -> Result<Statement, ParserError> {
        if dialect_of!(self is DuckDbDialect |  GenericDialect) {
            let name = self.parse_object_name(false)?;
            self.expect_token(&Token::LParen)?;
            let args = if self.consume_token(&Token::RParen) {
                self.prev_token();
                None
            } else {
                Some(self.parse_comma_separated(Parser::parse_macro_arg)?)
            };

            self.expect_token(&Token::RParen)?;
            self.expect_keyword_is(Keyword::AS)?;

            Ok(Statement::CreateMacro {
                or_replace,
                temporary,
                name,
                args,
                definition: if self.parse_keyword(Keyword::TABLE) {
                    MacroDefinition::Table(self.parse_query()?)
                } else {
                    MacroDefinition::Expr(self.parse_expr()?)
                },
            })
        } else {
            self.prev_token();
            self.expected_ref("an object type after CREATE", self.peek_token_ref())
        }
    }

    fn parse_macro_arg(&mut self) -> Result<MacroArg, ParserError> {
        let name = self.parse_identifier()?;

        let default_expr =
            if self.consume_token(&Token::Assignment) || self.consume_token(&Token::RArrow) {
                Some(self.parse_expr()?)
            } else {
                None
            };
        Ok(MacroArg { name, default_expr })
    }

    /// Parse a `CREATE EXTERNAL TABLE` statement.
    pub fn parse_create_external_table(
        &mut self,
        or_replace: bool,
    ) -> Result<CreateTable, ParserError> {
        self.expect_keyword_is(Keyword::TABLE)?;
        let if_not_exists = self.parse_keywords(&[Keyword::IF, Keyword::NOT, Keyword::EXISTS]);
        let table_name = self.parse_object_name(false)?;
        let (columns, constraints) = self.parse_columns()?;

        let hive_distribution = self.parse_hive_distribution()?;
        let hive_formats = self.parse_hive_formats()?;

        let file_format = if let Some(ref hf) = hive_formats {
            if let Some(ref ff) = hf.storage {
                match ff {
                    HiveIOFormat::FileFormat { format } => Some(*format),
                    _ => None,
                }
            } else {
                None
            }
        } else {
            None
        };
        let location = hive_formats.as_ref().and_then(|hf| hf.location.clone());

        let with_connection = if self.parse_keywords(&[Keyword::WITH, Keyword::CONNECTION]) {
            Some(self.parse_object_name(false)?)
        } else {
            None
        };
        let table_properties = self.parse_options(Keyword::TBLPROPERTIES)?;
        let table_options = if !table_properties.is_empty() {
            CreateTableOptions::TableProperties(table_properties)
        } else if let Some(options) = self.maybe_parse_options(Keyword::OPTIONS)? {
            CreateTableOptions::Options(options)
        } else {
            CreateTableOptions::None
        };
        Ok(CreateTableBuilder::new(table_name)
            .columns(columns)
            .constraints(constraints)
            .hive_distribution(hive_distribution)
            .hive_formats(hive_formats)
            .table_options(table_options)
            .with_connection(with_connection)
            .or_replace(or_replace)
            .if_not_exists(if_not_exists)
            .external(true)
            .file_format(file_format)
            .location(location)
            .build())
    }

    /// Parse `CREATE SNAPSHOT TABLE` statement.
    ///
    /// <https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#create_snapshot_table_statement>
    pub fn parse_create_snapshot_table(&mut self) -> Result<CreateTable, ParserError> {
        self.expect_keywords(&[Keyword::SNAPSHOT, Keyword::TABLE])?;
        let if_not_exists = self.parse_keywords(&[Keyword::IF, Keyword::NOT, Keyword::EXISTS]);
        let table_name = self.parse_object_name(true)?;

        self.expect_keyword_is(Keyword::CLONE)?;
        let clone = Some(self.parse_object_name(true)?);

        let version =
            if self.parse_keywords(&[Keyword::FOR, Keyword::SYSTEM_TIME, Keyword::AS, Keyword::OF])
            {
                Some(TableVersion::ForSystemTimeAsOf(self.parse_expr()?))
            } else {
                None
            };

        let table_options = if let Some(options) = self.maybe_parse_options(Keyword::OPTIONS)? {
            CreateTableOptions::Options(options)
        } else {
            CreateTableOptions::None
        };

        Ok(CreateTableBuilder::new(table_name)
            .snapshot(true)
            .if_not_exists(if_not_exists)
            .clone_clause(clone)
            .version(version)
            .table_options(table_options)
            .build())
    }

    /// Parse a file format for external tables.
    pub fn parse_file_format(&mut self) -> Result<FileFormat, ParserError> {
        let next_token = self.next_token();
        match &next_token.token {
            Token::Word(w) => match w.keyword {
                Keyword::AVRO => Ok(FileFormat::AVRO),
                Keyword::JSONFILE => Ok(FileFormat::JSONFILE),
                Keyword::ORC => Ok(FileFormat::ORC),
                Keyword::PARQUET => Ok(FileFormat::PARQUET),
                Keyword::RCFILE => Ok(FileFormat::RCFILE),
                Keyword::SEQUENCEFILE => Ok(FileFormat::SEQUENCEFILE),
                Keyword::TEXTFILE => Ok(FileFormat::TEXTFILE),
                _ => self.expected("fileformat", next_token),
            },
            _ => self.expected("fileformat", next_token),
        }
    }

    fn parse_analyze_format_kind(&mut self) -> Result<AnalyzeFormatKind, ParserError> {
        if self.consume_token(&Token::Eq) {
            Ok(AnalyzeFormatKind::Assignment(self.parse_analyze_format()?))
        } else {
            Ok(AnalyzeFormatKind::Keyword(self.parse_analyze_format()?))
        }
    }

    /// Parse an `ANALYZE FORMAT`.
    pub fn parse_analyze_format(&mut self) -> Result<AnalyzeFormat, ParserError> {
        let next_token = self.next_token();
        match &next_token.token {
            Token::Word(w) => match w.keyword {
                Keyword::TEXT => Ok(AnalyzeFormat::TEXT),
                Keyword::GRAPHVIZ => Ok(AnalyzeFormat::GRAPHVIZ),
                Keyword::JSON => Ok(AnalyzeFormat::JSON),
                Keyword::TREE => Ok(AnalyzeFormat::TREE),
                _ => self.expected("fileformat", next_token),
            },
            _ => self.expected("fileformat", next_token),
        }
    }

    /// Parse a `CREATE VIEW` statement.
    pub fn parse_create_view(
        &mut self,
        or_alter: bool,
        or_replace: bool,
        temporary: bool,
        create_view_params: Option<CreateViewParams>,
    ) -> Result<CreateView, ParserError> {
        let secure = self.parse_keyword(Keyword::SECURE);
        let materialized = self.parse_keyword(Keyword::MATERIALIZED);
        self.expect_keyword_is(Keyword::VIEW)?;
        let allow_unquoted_hyphen = dialect_of!(self is BigQueryDialect);
        // Tries to parse IF NOT EXISTS either before name or after name
        // Name before IF NOT EXISTS is supported by snowflake but undocumented
        let if_not_exists_first =
            self.parse_keywords(&[Keyword::IF, Keyword::NOT, Keyword::EXISTS]);
        let name = self.parse_object_name(allow_unquoted_hyphen)?;
        let name_before_not_exists = !if_not_exists_first
            && self.parse_keywords(&[Keyword::IF, Keyword::NOT, Keyword::EXISTS]);
        let if_not_exists = if_not_exists_first || name_before_not_exists;
        let mut copy_grants = self.parse_keywords(&[Keyword::COPY, Keyword::GRANTS]);
        // Many dialects support `OR ALTER` right after `CREATE`, but we don't (yet).
        // ANSI SQL and Postgres support RECURSIVE here, but we don't support it either.
        let columns = self.parse_view_columns()?;
        // Snowflake also documents `COPY GRANTS` *after* the column list; accept
        // either position, but not both.
        // <https://docs.snowflake.com/en/sql-reference/sql/create-view#syntax>
        if !copy_grants {
            copy_grants = self.parse_keywords(&[Keyword::COPY, Keyword::GRANTS]);
        }
        let mut options = CreateTableOptions::None;
        let with_options = self.parse_options(Keyword::WITH)?;
        if !with_options.is_empty() {
            options = CreateTableOptions::With(with_options);
        }

        let cluster_by = if self.parse_keyword(Keyword::CLUSTER) {
            self.expect_keyword_is(Keyword::BY)?;
            self.parse_parenthesized_column_list(Optional, false)?
        } else {
            vec![]
        };

        if dialect_of!(self is BigQueryDialect | GenericDialect) {
            if let Some(opts) = self.maybe_parse_options(Keyword::OPTIONS)? {
                if !opts.is_empty() {
                    options = CreateTableOptions::Options(opts);
                }
            };
        }

        let to = if dialect_of!(self is ClickHouseDialect | GenericDialect)
            && self.parse_keyword(Keyword::TO)
        {
            Some(self.parse_object_name(false)?)
        } else {
            None
        };

        let comment = if self.dialect.supports_create_view_comment_syntax()
            && self.parse_keyword(Keyword::COMMENT)
        {
            self.expect_token(&Token::Eq)?;
            Some(self.parse_comment_value()?)
        } else {
            None
        };

        self.expect_keyword_is(Keyword::AS)?;
        let query = self.parse_query()?;
        // Optional `WITH [ CASCADED | LOCAL ] CHECK OPTION` is widely supported here.

        let with_no_schema_binding = dialect_of!(self is RedshiftSqlDialect | GenericDialect)
            && self.parse_keywords(&[
                Keyword::WITH,
                Keyword::NO,
                Keyword::SCHEMA,
                Keyword::BINDING,
            ]);

        Ok(CreateView {
            or_alter,
            name,
            columns,
            query,
            materialized,
            secure,
            or_replace,
            options,
            cluster_by,
            comment,
            with_no_schema_binding,
            if_not_exists,
            temporary,
            copy_grants,
            to,
            params: create_view_params,
            name_before_not_exists,
        })
    }

    /// Parse optional parameters for the `CREATE VIEW` statement supported by [MySQL].
    ///
    /// [MySQL]: https://dev.mysql.com/doc/refman/9.1/en/create-view.html
    fn parse_create_view_params(&mut self) -> Result<Option<CreateViewParams>, ParserError> {
        let algorithm = if self.parse_keyword(Keyword::ALGORITHM) {
            self.expect_token(&Token::Eq)?;
            Some(
                match self.expect_one_of_keywords(&[
                    Keyword::UNDEFINED,
                    Keyword::MERGE,
                    Keyword::TEMPTABLE,
                ])? {
                    Keyword::UNDEFINED => CreateViewAlgorithm::Undefined,
                    Keyword::MERGE => CreateViewAlgorithm::Merge,
                    Keyword::TEMPTABLE => CreateViewAlgorithm::TempTable,
                    _ => {
                        self.prev_token();
                        let found = self.next_token();
                        return self
                            .expected("UNDEFINED or MERGE or TEMPTABLE after ALGORITHM =", found);
                    }
                },
            )
        } else {
            None
        };
        let definer = if self.parse_keyword(Keyword::DEFINER) {
            self.expect_token(&Token::Eq)?;
            Some(self.parse_grantee_name()?)
        } else {
            None
        };
        let security = if self.parse_keywords(&[Keyword::SQL, Keyword::SECURITY]) {
            Some(
                match self.expect_one_of_keywords(&[Keyword::DEFINER, Keyword::INVOKER])? {
                    Keyword::DEFINER => CreateViewSecurity::Definer,
                    Keyword::INVOKER => CreateViewSecurity::Invoker,
                    _ => {
                        self.prev_token();
                        let found = self.next_token();
                        return self.expected("DEFINER or INVOKER after SQL SECURITY", found);
                    }
                },
            )
        } else {
            None
        };
        if algorithm.is_some() || definer.is_some() || security.is_some() {
            Ok(Some(CreateViewParams {
                algorithm,
                definer,
                security,
            }))
        } else {
            Ok(None)
        }
    }

    /// Parse a `CREATE ROLE` statement.
    pub fn parse_create_role(&mut self) -> Result<CreateRole, ParserError> {
        let if_not_exists = self.parse_keywords(&[Keyword::IF, Keyword::NOT, Keyword::EXISTS]);
        let names = self.parse_comma_separated(|p| p.parse_object_name(false))?;

        let _ = self.parse_keyword(Keyword::WITH); // [ WITH ]

        let optional_keywords = if dialect_of!(self is MsSqlDialect) {
            vec![Keyword::AUTHORIZATION]
        } else if dialect_of!(self is PostgreSqlDialect) {
            vec![
                Keyword::LOGIN,
                Keyword::NOLOGIN,
                Keyword::INHERIT,
                Keyword::NOINHERIT,
                Keyword::BYPASSRLS,
                Keyword::NOBYPASSRLS,
                Keyword::PASSWORD,
                Keyword::CREATEDB,
                Keyword::NOCREATEDB,
                Keyword::CREATEROLE,
                Keyword::NOCREATEROLE,
                Keyword::SUPERUSER,
                Keyword::NOSUPERUSER,
                Keyword::REPLICATION,
                Keyword::NOREPLICATION,
                Keyword::CONNECTION,
                Keyword::VALID,
                Keyword::IN,
                Keyword::ROLE,
                Keyword::ADMIN,
                Keyword::USER,
            ]
        } else {
            vec![]
        };

        // MSSQL
        let mut authorization_owner = None;
        // Postgres
        let mut login = None;
        let mut inherit = None;
        let mut bypassrls = None;
        let mut password = None;
        let mut create_db = None;
        let mut create_role = None;
        let mut superuser = None;
        let mut replication = None;
        let mut connection_limit = None;
        let mut valid_until = None;
        let mut in_role = vec![];
        let mut in_group = vec![];
        let mut role = vec![];
        let mut user = vec![];
        let mut admin = vec![];

        while let Some(keyword) = self.parse_one_of_keywords(&optional_keywords) {
            let loc = self
                .tokens
                .get(self.index - 1)
                .map_or(Location { line: 0, column: 0 }, |t| t.span.start);
            match keyword {
                Keyword::AUTHORIZATION => {
                    if authorization_owner.is_some() {
                        parser_err!("Found multiple AUTHORIZATION", loc)
                    } else {
                        authorization_owner = Some(self.parse_object_name(false)?);
                        Ok(())
                    }
                }
                Keyword::LOGIN | Keyword::NOLOGIN => {
                    if login.is_some() {
                        parser_err!("Found multiple LOGIN or NOLOGIN", loc)
                    } else {
                        login = Some(keyword == Keyword::LOGIN);
                        Ok(())
                    }
                }
                Keyword::INHERIT | Keyword::NOINHERIT => {
                    if inherit.is_some() {
                        parser_err!("Found multiple INHERIT or NOINHERIT", loc)
                    } else {
                        inherit = Some(keyword == Keyword::INHERIT);
                        Ok(())
                    }
                }
                Keyword::BYPASSRLS | Keyword::NOBYPASSRLS => {
                    if bypassrls.is_some() {
                        parser_err!("Found multiple BYPASSRLS or NOBYPASSRLS", loc)
                    } else {
                        bypassrls = Some(keyword == Keyword::BYPASSRLS);
                        Ok(())
                    }
                }
                Keyword::CREATEDB | Keyword::NOCREATEDB => {
                    if create_db.is_some() {
                        parser_err!("Found multiple CREATEDB or NOCREATEDB", loc)
                    } else {
                        create_db = Some(keyword == Keyword::CREATEDB);
                        Ok(())
                    }
                }
                Keyword::CREATEROLE | Keyword::NOCREATEROLE => {
                    if create_role.is_some() {
                        parser_err!("Found multiple CREATEROLE or NOCREATEROLE", loc)
                    } else {
                        create_role = Some(keyword == Keyword::CREATEROLE);
                        Ok(())
                    }
                }
                Keyword::SUPERUSER | Keyword::NOSUPERUSER => {
                    if superuser.is_some() {
                        parser_err!("Found multiple SUPERUSER or NOSUPERUSER", loc)
                    } else {
                        superuser = Some(keyword == Keyword::SUPERUSER);
                        Ok(())
                    }
                }
                Keyword::REPLICATION | Keyword::NOREPLICATION => {
                    if replication.is_some() {
                        parser_err!("Found multiple REPLICATION or NOREPLICATION", loc)
                    } else {
                        replication = Some(keyword == Keyword::REPLICATION);
                        Ok(())
                    }
                }
                Keyword::PASSWORD => {
                    if password.is_some() {
                        parser_err!("Found multiple PASSWORD", loc)
                    } else {
                        password = if self.parse_keyword(Keyword::NULL) {
                            Some(Password::NullPassword)
                        } else {
                            Some(Password::Password(Expr::Value(self.parse_value()?)))
                        };
                        Ok(())
                    }
                }
                Keyword::CONNECTION => {
                    self.expect_keyword_is(Keyword::LIMIT)?;
                    if connection_limit.is_some() {
                        parser_err!("Found multiple CONNECTION LIMIT", loc)
                    } else {
                        connection_limit = Some(Expr::Value(self.parse_number_value()?));
                        Ok(())
                    }
                }
                Keyword::VALID => {
                    self.expect_keyword_is(Keyword::UNTIL)?;
                    if valid_until.is_some() {
                        parser_err!("Found multiple VALID UNTIL", loc)
                    } else {
                        valid_until = Some(Expr::Value(self.parse_value()?));
                        Ok(())
                    }
                }
                Keyword::IN => {
                    if self.parse_keyword(Keyword::ROLE) {
                        if !in_role.is_empty() {
                            parser_err!("Found multiple IN ROLE", loc)
                        } else {
                            in_role = self.parse_comma_separated(|p| p.parse_identifier())?;
                            Ok(())
                        }
                    } else if self.parse_keyword(Keyword::GROUP) {
                        if !in_group.is_empty() {
                            parser_err!("Found multiple IN GROUP", loc)
                        } else {
                            in_group = self.parse_comma_separated(|p| p.parse_identifier())?;
                            Ok(())
                        }
                    } else {
                        self.expected_ref("ROLE or GROUP after IN", self.peek_token_ref())
                    }
                }
                Keyword::ROLE => {
                    if !role.is_empty() {
                        parser_err!("Found multiple ROLE", loc)
                    } else {
                        role = self.parse_comma_separated(|p| p.parse_identifier())?;
                        Ok(())
                    }
                }
                Keyword::USER => {
                    if !user.is_empty() {
                        parser_err!("Found multiple USER", loc)
                    } else {
                        user = self.parse_comma_separated(|p| p.parse_identifier())?;
                        Ok(())
                    }
                }
                Keyword::ADMIN => {
                    if !admin.is_empty() {
                        parser_err!("Found multiple ADMIN", loc)
                    } else {
                        admin = self.parse_comma_separated(|p| p.parse_identifier())?;
                        Ok(())
                    }
                }
                _ => break,
            }?
        }

        Ok(CreateRole {
            names,
            if_not_exists,
            login,
            inherit,
            bypassrls,
            password,
            create_db,
            create_role,
            replication,
            superuser,
            connection_limit,
            valid_until,
            in_role,
            in_group,
            role,
            user,
            admin,
            authorization_owner,
        })
    }

    /// Parse an `OWNER` clause.
    pub fn parse_owner(&mut self) -> Result<Owner, ParserError> {
        let owner = match self.parse_one_of_keywords(&[Keyword::CURRENT_USER, Keyword::CURRENT_ROLE, Keyword::SESSION_USER]) {
            Some(Keyword::CURRENT_USER) => Owner::CurrentUser,
            Some(Keyword::CURRENT_ROLE) => Owner::CurrentRole,
            Some(Keyword::SESSION_USER) => Owner::SessionUser,
            Some(unexpected_keyword) => return Err(ParserError::ParserError(
                format!("Internal parser error: unexpected keyword `{unexpected_keyword}` in owner"),
            )),
            None => {
                match self.parse_identifier() {
                    Ok(ident) => Owner::Ident(ident),
                    Err(e) => {
                        return Err(ParserError::ParserError(format!("Expected: CURRENT_USER, CURRENT_ROLE, SESSION_USER or identifier after OWNER TO. {e}")))
                    }
                }
            }
        };
        Ok(owner)
    }

    /// Parses a [Statement::CreateDomain] statement.
    fn parse_create_domain(&mut self) -> Result<CreateDomain, ParserError> {
        let name = self.parse_object_name(false)?;
        self.expect_keyword_is(Keyword::AS)?;
        let data_type = self.parse_data_type()?;
        let collation = if self.parse_keyword(Keyword::COLLATE) {
            Some(self.parse_identifier()?)
        } else {
            None
        };
        let default = if self.parse_keyword(Keyword::DEFAULT) {
            Some(self.parse_expr()?)
        } else {
            None
        };
        let mut constraints = Vec::new();
        while let Some(constraint) = self.parse_optional_table_constraint()? {
            constraints.push(constraint);
        }

        Ok(CreateDomain {
            name,
            data_type,
            collation,
            default,
            constraints,
        })
    }

    /// ```sql
    ///     CREATE POLICY name ON table_name [ AS { PERMISSIVE | RESTRICTIVE } ]
    ///     [ FOR { ALL | SELECT | INSERT | UPDATE | DELETE } ]
    ///     [ TO { role_name | PUBLIC | CURRENT_USER | CURRENT_ROLE | SESSION_USER } [, ...] ]
    ///     [ USING ( using_expression ) ]
    ///     [ WITH CHECK ( with_check_expression ) ]
    /// ```
    ///
    /// [PostgreSQL Documentation](https://www.postgresql.org/docs/current/sql-createpolicy.html)
    pub fn parse_create_policy(&mut self) -> Result<CreatePolicy, ParserError> {
        let name = self.parse_identifier()?;
        self.expect_keyword_is(Keyword::ON)?;
        let table_name = self.parse_object_name(false)?;

        let policy_type = if self.parse_keyword(Keyword::AS) {
            let keyword =
                self.expect_one_of_keywords(&[Keyword::PERMISSIVE, Keyword::RESTRICTIVE])?;
            Some(match keyword {
                Keyword::PERMISSIVE => CreatePolicyType::Permissive,
                Keyword::RESTRICTIVE => CreatePolicyType::Restrictive,
                unexpected_keyword => return Err(ParserError::ParserError(
                    format!("Internal parser error: unexpected keyword `{unexpected_keyword}` in policy type"),
                )),
            })
        } else {
            None
        };

        let command = if self.parse_keyword(Keyword::FOR) {
            let keyword = self.expect_one_of_keywords(&[
                Keyword::ALL,
                Keyword::SELECT,
                Keyword::INSERT,
                Keyword::UPDATE,
                Keyword::DELETE,
            ])?;
            Some(match keyword {
                Keyword::ALL => CreatePolicyCommand::All,
                Keyword::SELECT => CreatePolicyCommand::Select,
                Keyword::INSERT => CreatePolicyCommand::Insert,
                Keyword::UPDATE => CreatePolicyCommand::Update,
                Keyword::DELETE => CreatePolicyCommand::Delete,
                unexpected_keyword => return Err(ParserError::ParserError(
                    format!("Internal parser error: unexpected keyword `{unexpected_keyword}` in policy command"),
                )),
            })
        } else {
            None
        };

        let to = if self.parse_keyword(Keyword::TO) {
            Some(self.parse_comma_separated(|p| p.parse_owner())?)
        } else {
            None
        };

        let using = if self.parse_keyword(Keyword::USING) {
            self.expect_token(&Token::LParen)?;
            let expr = self.parse_expr()?;
            self.expect_token(&Token::RParen)?;
            Some(expr)
        } else {
            None
        };

        let with_check = if self.parse_keywords(&[Keyword::WITH, Keyword::CHECK]) {
            self.expect_token(&Token::LParen)?;
            let expr = self.parse_expr()?;
            self.expect_token(&Token::RParen)?;
            Some(expr)
        } else {
            None
        };

        Ok(CreatePolicy {
            name,
            table_name,
            policy_type,
            command,
            to,
            using,
            with_check,
        })
    }

    /// ```sql
    /// CREATE CONNECTOR [IF NOT EXISTS] connector_name
    /// [TYPE datasource_type]
    /// [URL datasource_url]
    /// [COMMENT connector_comment]
    /// [WITH DCPROPERTIES(property_name=property_value, ...)]
    /// ```
    ///
    /// [Hive Documentation](https://cwiki.apache.org/confluence/pages/viewpage.action?pageId=27362034#LanguageManualDDL-CreateDataConnectorCreateConnector)
    pub fn parse_create_connector(&mut self) -> Result<CreateConnector, ParserError> {
        let if_not_exists = self.parse_keywords(&[Keyword::IF, Keyword::NOT, Keyword::EXISTS]);
        let name = self.parse_identifier()?;

        let connector_type = if self.parse_keyword(Keyword::TYPE) {
            Some(self.parse_literal_string()?)
        } else {
            None
        };

        let url = if self.parse_keyword(Keyword::URL) {
            Some(self.parse_literal_string()?)
        } else {
            None
        };

        let comment = self.parse_optional_inline_comment()?;

        let with_dcproperties =
            match self.parse_options_with_keywords(&[Keyword::WITH, Keyword::DCPROPERTIES])? {
                properties if !properties.is_empty() => Some(properties),
                _ => None,
            };

        Ok(CreateConnector {
            name,
            if_not_exists,
            connector_type,
            url,
            comment,
            with_dcproperties,
        })
    }

    /// Parse an operator name, which can contain special characters like +, -, <, >, =
    /// that are tokenized as operator tokens rather than identifiers.
    /// This is used for PostgreSQL CREATE OPERATOR statements.
    ///
    /// Examples: `+`, `myschema.+`, `pg_catalog.<=`
    fn parse_operator_name(&mut self) -> Result<ObjectName, ParserError> {
        let mut parts = vec![];
        loop {
            parts.push(ObjectNamePart::Identifier(Ident::new(
                self.next_token().to_string(),
            )));
            if !self.consume_token(&Token::Period) {
                break;
            }
        }
        Ok(ObjectName(parts))
    }

    /// Parse a [Statement::CreateOperator]
    ///
    /// [PostgreSQL Documentation](https://www.postgresql.org/docs/current/sql-createoperator.html)
    pub fn parse_create_operator(&mut self) -> Result<CreateOperator, ParserError> {
        let name = self.parse_operator_name()?;
        self.expect_token(&Token::LParen)?;

        let mut function: Option<ObjectName> = None;
        let mut is_procedure = false;
        let mut left_arg: Option<DataType> = None;
        let mut right_arg: Option<DataType> = None;
        let mut options: Vec<OperatorOption> = Vec::new();

        loop {
            let keyword = self.expect_one_of_keywords(&[
                Keyword::FUNCTION,
                Keyword::PROCEDURE,
                Keyword::LEFTARG,
                Keyword::RIGHTARG,
                Keyword::COMMUTATOR,
                Keyword::NEGATOR,
                Keyword::RESTRICT,
                Keyword::JOIN,
                Keyword::HASHES,
                Keyword::MERGES,
            ])?;

            match keyword {
                Keyword::HASHES if !options.iter().any(|o| matches!(o, OperatorOption::Hashes)) => {
                    options.push(OperatorOption::Hashes);
                }
                Keyword::MERGES if !options.iter().any(|o| matches!(o, OperatorOption::Merges)) => {
                    options.push(OperatorOption::Merges);
                }
                Keyword::FUNCTION | Keyword::PROCEDURE if function.is_none() => {
                    self.expect_token(&Token::Eq)?;
                    function = Some(self.parse_object_name(false)?);
                    is_procedure = keyword == Keyword::PROCEDURE;
                }
                Keyword::LEFTARG if left_arg.is_none() => {
                    self.expect_token(&Token::Eq)?;
                    left_arg = Some(self.parse_data_type()?);
                }
                Keyword::RIGHTARG if right_arg.is_none() => {
                    self.expect_token(&Token::Eq)?;
                    right_arg = Some(self.parse_data_type()?);
                }
                Keyword::COMMUTATOR
                    if !options
                        .iter()
                        .any(|o| matches!(o, OperatorOption::Commutator(_))) =>
                {
                    self.expect_token(&Token::Eq)?;
                    if self.parse_keyword(Keyword::OPERATOR) {
                        self.expect_token(&Token::LParen)?;
                        let op = self.parse_operator_name()?;
                        self.expect_token(&Token::RParen)?;
                        options.push(OperatorOption::Commutator(op));
                    } else {
                        options.push(OperatorOption::Commutator(self.parse_operator_name()?));
                    }
                }
                Keyword::NEGATOR
                    if !options
                        .iter()
                        .any(|o| matches!(o, OperatorOption::Negator(_))) =>
                {
                    self.expect_token(&Token::Eq)?;
                    if self.parse_keyword(Keyword::OPERATOR) {
                        self.expect_token(&Token::LParen)?;
                        let op = self.parse_operator_name()?;
                        self.expect_token(&Token::RParen)?;
                        options.push(OperatorOption::Negator(op));
                    } else {
                        options.push(OperatorOption::Negator(self.parse_operator_name()?));
                    }
                }
                Keyword::RESTRICT
                    if !options
                        .iter()
                        .any(|o| matches!(o, OperatorOption::Restrict(_))) =>
                {
                    self.expect_token(&Token::Eq)?;
                    options.push(OperatorOption::Restrict(Some(
                        self.parse_object_name(false)?,
                    )));
                }
                Keyword::JOIN if !options.iter().any(|o| matches!(o, OperatorOption::Join(_))) => {
                    self.expect_token(&Token::Eq)?;
                    options.push(OperatorOption::Join(Some(self.parse_object_name(false)?)));
                }
                _ => {
                    return Err(ParserError::ParserError(format!(
                        "Duplicate or unexpected keyword {:?} in CREATE OPERATOR",
                        keyword
                    )))
                }
            }

            if !self.consume_token(&Token::Comma) {
                break;
            }
        }

        // Expect closing parenthesis
        self.expect_token(&Token::RParen)?;

        // FUNCTION is required
        let function = function.ok_or_else(|| {
            ParserError::ParserError("CREATE OPERATOR requires FUNCTION parameter".to_string())
        })?;

        Ok(CreateOperator {
            name,
            function,
            is_procedure,
            left_arg,
            right_arg,
            options,
        })
    }

    /// Parse a [Statement::CreateOperatorFamily]
    ///
    /// [PostgreSQL Documentation](https://www.postgresql.org/docs/current/sql-createopfamily.html)
    pub fn parse_create_operator_family(&mut self) -> Result<CreateOperatorFamily, ParserError> {
        let name = self.parse_object_name(false)?;
        self.expect_keyword(Keyword::USING)?;
        let using = self.parse_identifier()?;

        Ok(CreateOperatorFamily { name, using })
    }

    /// Parse a [Statement::CreateOperatorClass]
    ///
    /// [PostgreSQL Documentation](https://www.postgresql.org/docs/current/sql-createopclass.html)
    pub fn parse_create_operator_class(&mut self) -> Result<CreateOperatorClass, ParserError> {
        let name = self.parse_object_name(false)?;
        let default = self.parse_keyword(Keyword::DEFAULT);
        self.expect_keywords(&[Keyword::FOR, Keyword::TYPE])?;
        let for_type = self.parse_data_type()?;
        self.expect_keyword(Keyword::USING)?;
        let using = self.parse_identifier()?;

        let family = if self.parse_keyword(Keyword::FAMILY) {
            Some(self.parse_object_name(false)?)
        } else {
            None
        };

        self.expect_keyword(Keyword::AS)?;

        let mut items = vec![];
        loop {
            if self.parse_keyword(Keyword::OPERATOR) {
                let strategy_number = self.parse_literal_uint()?;
                let operator_name = self.parse_operator_name()?;

                // Optional operator argument types
                let op_types = if self.consume_token(&Token::LParen) {
                    let left = self.parse_data_type()?;
                    self.expect_token(&Token::Comma)?;
                    let right = self.parse_data_type()?;
                    self.expect_token(&Token::RParen)?;
                    Some(OperatorArgTypes { left, right })
                } else {
                    None
                };

                // Optional purpose
                let purpose = if self.parse_keyword(Keyword::FOR) {
                    if self.parse_keyword(Keyword::SEARCH) {
                        Some(OperatorPurpose::ForSearch)
                    } else if self.parse_keywords(&[Keyword::ORDER, Keyword::BY]) {
                        let sort_family = self.parse_object_name(false)?;
                        Some(OperatorPurpose::ForOrderBy { sort_family })
                    } else {
                        return self
                            .expected_ref("SEARCH or ORDER BY after FOR", self.peek_token_ref());
                    }
                } else {
                    None
                };

                items.push(OperatorClassItem::Operator {
                    strategy_number,
                    operator_name,
                    op_types,
                    purpose,
                });
            } else if self.parse_keyword(Keyword::FUNCTION) {
                let support_number = self.parse_literal_uint()?;

                // Optional operator types
                let op_types = if self.consume_token(&Token::LParen)
                    && self.peek_token_ref().token != Token::RParen
                {
                    let mut types = vec![];
                    loop {
                        types.push(self.parse_data_type()?);
                        if !self.consume_token(&Token::Comma) {
                            break;
                        }
                    }
                    self.expect_token(&Token::RParen)?;
                    Some(types)
                } else {
                    None
                };

                let function_name = self.parse_object_name(false)?;

                // Function argument types
                let argument_types = if self.consume_token(&Token::LParen) {
                    let mut types = vec![];
                    loop {
                        if self.peek_token_ref().token == Token::RParen {
                            break;
                        }
                        types.push(self.parse_data_type()?);
                        if !self.consume_token(&Token::Comma) {
                            break;
                        }
                    }
                    self.expect_token(&Token::RParen)?;
                    types
                } else {
                    vec![]
                };

                items.push(OperatorClassItem::Function {
                    support_number,
                    op_types,
                    function_name,
                    argument_types,
                });
            } else if self.parse_keyword(Keyword::STORAGE) {
                let storage_type = self.parse_data_type()?;
                items.push(OperatorClassItem::Storage { storage_type });
            } else {
                break;
            }

            // Check for comma separator
            if !self.consume_token(&Token::Comma) {
                break;
            }
        }

        Ok(CreateOperatorClass {
            name,
            default,
            for_type,
            using,
            family,
            items,
        })
    }

    /// Parse a `DROP` statement.
    pub fn parse_drop(&mut self) -> Result<Statement, ParserError> {
        // MySQL dialect supports `TEMPORARY`
        let temporary = dialect_of!(self is MySqlDialect | GenericDialect | DuckDbDialect)
            && self.parse_keyword(Keyword::TEMPORARY);
        let persistent = dialect_of!(self is DuckDbDialect)
            && self.parse_one_of_keywords(&[Keyword::PERSISTENT]).is_some();

        let object_type = if self.parse_keyword(Keyword::TABLE) {
            ObjectType::Table
        } else if self.parse_keyword(Keyword::COLLATION) {
            ObjectType::Collation
        } else if self.parse_keyword(Keyword::VIEW) {
            ObjectType::View
        } else if self.parse_keywords(&[Keyword::MATERIALIZED, Keyword::VIEW]) {
            ObjectType::MaterializedView
        } else if self.parse_keyword(Keyword::INDEX) {
            ObjectType::Index
        } else if self.parse_keyword(Keyword::ROLE) {
            ObjectType::Role
        } else if self.parse_keyword(Keyword::SCHEMA) {
            ObjectType::Schema
        } else if self.parse_keyword(Keyword::DATABASE) {
            ObjectType::Database
        } else if self.parse_keyword(Keyword::SEQUENCE) {
            ObjectType::Sequence
        } else if self.parse_keyword(Keyword::STAGE) {
            ObjectType::Stage
        } else if self.parse_keyword(Keyword::TYPE) {
            ObjectType::Type
        } else if self.parse_keyword(Keyword::USER) {
            ObjectType::User
        } else if self.parse_keyword(Keyword::STREAM) {
            ObjectType::Stream
        } else if self.parse_keyword(Keyword::WAREHOUSE) {
            ObjectType::Warehouse
        } else if self.parse_keyword(Keyword::FUNCTION) {
            return self.parse_drop_function().map(Into::into);
        } else if self.parse_keyword(Keyword::POLICY) {
            return self.parse_drop_policy().map(Into::into);
        } else if self.parse_keyword(Keyword::CONNECTOR) {
            return self.parse_drop_connector();
        } else if self.parse_keyword(Keyword::DOMAIN) {
            return self.parse_drop_domain().map(Into::into);
        } else if self.parse_keyword(Keyword::PROCEDURE) {
            return self.parse_drop_procedure();
        } else if self.parse_keyword(Keyword::SECRET) {
            return self.parse_drop_secret(temporary, persistent);
        } else if self.parse_keyword(Keyword::TRIGGER) {
            return self.parse_drop_trigger().map(Into::into);
        } else if self.parse_keyword(Keyword::EXTENSION) {
            return self.parse_drop_extension();
        } else if self.parse_keyword(Keyword::OPERATOR) {
            // Check if this is DROP OPERATOR FAMILY or DROP OPERATOR CLASS
            return if self.parse_keyword(Keyword::FAMILY) {
                self.parse_drop_operator_family()
            } else if self.parse_keyword(Keyword::CLASS) {
                self.parse_drop_operator_class()
            } else {
                self.parse_drop_operator()
            };
        } else {
            return self.expected_ref(
                "COLLATION, CONNECTOR, DATABASE, EXTENSION, FUNCTION, INDEX, OPERATOR, POLICY, PROCEDURE, ROLE, SCHEMA, SECRET, SEQUENCE, STAGE, TABLE, TRIGGER, TYPE, VIEW, MATERIALIZED VIEW, USER or WAREHOUSE after DROP",
                self.peek_token_ref(),
            );
        };
        // Many dialects support the non-standard `IF EXISTS` clause and allow
        // specifying multiple objects to delete in a single statement
        let if_exists = self.parse_keywords(&[Keyword::IF, Keyword::EXISTS]);
        let names = self.parse_comma_separated(|p| p.parse_object_name(false))?;

        let loc = self.peek_token_ref().span.start;
        let cascade = self.parse_keyword(Keyword::CASCADE);
        let restrict = self.parse_keyword(Keyword::RESTRICT);
        let purge = self.parse_keyword(Keyword::PURGE);
        if cascade && restrict {
            return parser_err!("Cannot specify both CASCADE and RESTRICT in DROP", loc);
        }
        if object_type == ObjectType::Role && (cascade || restrict || purge) {
            return parser_err!(
                "Cannot specify CASCADE, RESTRICT, or PURGE in DROP ROLE",
                loc
            );
        }
        let table = if self.parse_keyword(Keyword::ON) {
            Some(self.parse_object_name(false)?)
        } else {
            None
        };
        Ok(Statement::Drop {
            object_type,
            if_exists,
            names,
            cascade,
            restrict,
            purge,
            temporary,
            table,
        })
    }

    fn parse_optional_drop_behavior(&mut self) -> Option<DropBehavior> {
        match self.parse_one_of_keywords(&[Keyword::CASCADE, Keyword::RESTRICT]) {
            Some(Keyword::CASCADE) => Some(DropBehavior::Cascade),
            Some(Keyword::RESTRICT) => Some(DropBehavior::Restrict),
            _ => None,
        }
    }

    /// ```sql
    /// DROP FUNCTION [ IF EXISTS ] name [ ( [ [ argmode ] [ argname ] argtype [, ...] ] ) ] [, ...]
    /// [ CASCADE | RESTRICT ]
    /// ```
    fn parse_drop_function(&mut self) -> Result<DropFunction, ParserError> {
        let if_exists = self.parse_keywords(&[Keyword::IF, Keyword::EXISTS]);
        let func_desc = self.parse_comma_separated(Parser::parse_function_desc)?;
        let drop_behavior = self.parse_optional_drop_behavior();
        Ok(DropFunction {
            if_exists,
            func_desc,
            drop_behavior,
        })
    }

    /// ```sql
    /// DROP POLICY [ IF EXISTS ] name ON table_name [ CASCADE | RESTRICT ]
    /// ```
    ///
    /// [PostgreSQL Documentation](https://www.postgresql.org/docs/current/sql-droppolicy.html)
    fn parse_drop_policy(&mut self) -> Result<DropPolicy, ParserError> {
        let if_exists = self.parse_keywords(&[Keyword::IF, Keyword::EXISTS]);
        let name = self.parse_identifier()?;
        self.expect_keyword_is(Keyword::ON)?;
        let table_name = self.parse_object_name(false)?;
        let drop_behavior = self.parse_optional_drop_behavior();
        Ok(DropPolicy {
            if_exists,
            name,
            table_name,
            drop_behavior,
        })
    }
    /// ```sql
    /// DROP CONNECTOR [IF EXISTS] name
    /// ```
    ///
    /// See [Hive](https://cwiki.apache.org/confluence/pages/viewpage.action?pageId=27362034#LanguageManualDDL-DropConnector)
    fn parse_drop_connector(&mut self) -> Result<Statement, ParserError> {
        let if_exists = self.parse_keywords(&[Keyword::IF, Keyword::EXISTS]);
        let name = self.parse_identifier()?;
        Ok(Statement::DropConnector { if_exists, name })
    }

    /// ```sql
    /// DROP DOMAIN [ IF EXISTS ] name [ CASCADE | RESTRICT ]
    /// ```
    fn parse_drop_domain(&mut self) -> Result<DropDomain, ParserError> {
        let if_exists = self.parse_keywords(&[Keyword::IF, Keyword::EXISTS]);
        let name = self.parse_object_name(false)?;
        let drop_behavior = self.parse_optional_drop_behavior();
        Ok(DropDomain {
            if_exists,
            name,
            drop_behavior,
        })
    }

    /// ```sql
    /// DROP PROCEDURE [ IF EXISTS ] name [ ( [ [ argmode ] [ argname ] argtype [, ...] ] ) ] [, ...]
    /// [ CASCADE | RESTRICT ]
    /// ```
    fn parse_drop_procedure(&mut self) -> Result<Statement, ParserError> {
        let if_exists = self.parse_keywords(&[Keyword::IF, Keyword::EXISTS]);
        let proc_desc = self.parse_comma_separated(Parser::parse_function_desc)?;
        let drop_behavior = self.parse_optional_drop_behavior();
        Ok(Statement::DropProcedure {
            if_exists,
            proc_desc,
            drop_behavior,
        })
    }

    fn parse_function_desc(&mut self) -> Result<FunctionDesc, ParserError> {
        let name = self.parse_object_name(false)?;

        let args = if self.consume_token(&Token::LParen) {
            if self.consume_token(&Token::RParen) {
                Some(vec![])
            } else {
                let args = self.parse_comma_separated(Parser::parse_function_arg)?;
                self.expect_token(&Token::RParen)?;
                Some(args)
            }
        } else {
            None
        };

        Ok(FunctionDesc { name, args })
    }

    /// See [DuckDB Docs](https://duckdb.org/docs/sql/statements/create_secret.html) for more details.
    fn parse_drop_secret(
        &mut self,
        temporary: bool,
        persistent: bool,
    ) -> Result<Statement, ParserError> {
        let if_exists = self.parse_keywords(&[Keyword::IF, Keyword::EXISTS]);
        let name = self.parse_identifier()?;
        let storage_specifier = if self.parse_keyword(Keyword::FROM) {
            self.parse_identifier().ok()
        } else {
            None
        };
        let temp = match (temporary, persistent) {
            (true, false) => Some(true),
            (false, true) => Some(false),
            (false, false) => None,
            _ => self.expected_ref("TEMPORARY or PERSISTENT", self.peek_token_ref())?,
        };

        Ok(Statement::DropSecret {
            if_exists,
            temporary: temp,
            name,
            storage_specifier,
        })
    }

    /// Parse a `DECLARE` statement.
    ///
    /// ```sql
    /// DECLARE name [ BINARY ] [ ASENSITIVE | INSENSITIVE ] [ [ NO ] SCROLL ]
    ///     CURSOR [ { WITH | WITHOUT } HOLD ] FOR query
    /// ```
    ///
    /// The syntax can vary significantly between warehouses. See the grammar
    /// on the warehouse specific function in such cases.
    pub fn parse_declare(&mut self) -> Result<Statement, ParserError> {
        if dialect_of!(self is BigQueryDialect) {
            return self.parse_big_query_declare();
        }
        if dialect_of!(self is SnowflakeDialect) {
            return self.parse_snowflake_declare();
        }
        if dialect_of!(self is MsSqlDialect) {
            return self.parse_mssql_declare();
        }

        let name = self.parse_identifier()?;

        let binary = Some(self.parse_keyword(Keyword::BINARY));
        let sensitive = if self.parse_keyword(Keyword::INSENSITIVE) {
            Some(true)
        } else if self.parse_keyword(Keyword::ASENSITIVE) {
            Some(false)
        } else {
            None
        };
        let scroll = if self.parse_keyword(Keyword::SCROLL) {
            Some(true)
        } else if self.parse_keywords(&[Keyword::NO, Keyword::SCROLL]) {
            Some(false)
        } else {
            None
        };

        self.expect_keyword_is(Keyword::CURSOR)?;
        let declare_type = Some(DeclareType::Cursor);

        let hold = match self.parse_one_of_keywords(&[Keyword::WITH, Keyword::WITHOUT]) {
            Some(keyword) => {
                self.expect_keyword_is(Keyword::HOLD)?;

                match keyword {
                    Keyword::WITH => Some(true),
                    Keyword::WITHOUT => Some(false),
                    unexpected_keyword => return Err(ParserError::ParserError(
                        format!("Internal parser error: unexpected keyword `{unexpected_keyword}` in cursor hold"),
                    )),
                }
            }
            None => None,
        };

        self.expect_keyword_is(Keyword::FOR)?;

        let query = Some(self.parse_query()?);

        Ok(Statement::Declare {
            stmts: vec![Declare {
                names: vec![name],
                data_type: None,
                assignment: None,
                declare_type,
                binary,
                sensitive,
                scroll,
                hold,
                for_query: query,
            }],
        })
    }

    /// Parse a [BigQuery] `DECLARE` statement.
    ///
    /// Syntax:
    /// ```text
    /// DECLARE variable_name[, ...] [{ <variable_type> | <DEFAULT expression> }];
    /// ```
    /// [BigQuery]: https://cloud.google.com/bigquery/docs/reference/standard-sql/procedural-language#declare
    pub fn parse_big_query_declare(&mut self) -> Result<Statement, ParserError> {
        let names = self.parse_comma_separated(Parser::parse_identifier)?;

        let data_type = match &self.peek_token_ref().token {
            Token::Word(w) if w.keyword == Keyword::DEFAULT => None,
            _ => Some(self.parse_data_type()?),
        };

        let expr = if data_type.is_some() {
            if self.parse_keyword(Keyword::DEFAULT) {
                Some(self.parse_expr()?)
            } else {
                None
            }
        } else {
            // If no variable type - default expression must be specified, per BQ docs.
            // i.e `DECLARE foo;` is invalid.
            self.expect_keyword_is(Keyword::DEFAULT)?;
            Some(self.parse_expr()?)
        };

        Ok(Statement::Declare {
            stmts: vec![Declare {
                names,
                data_type,
                assignment: expr.map(|expr| DeclareAssignment::Default(Box::new(expr))),
                declare_type: None,
                binary: None,
                sensitive: None,
                scroll: None,
                hold: None,
                for_query: None,
            }],
        })
    }

    /// Parse a [Snowflake] `DECLARE` statement.
    ///
    /// Syntax:
    /// ```text
    /// DECLARE
    ///   [{ <variable_declaration>
    ///      | <cursor_declaration>
    ///      | <resultset_declaration>
    ///      | <exception_declaration> }; ... ]
    ///
    /// <variable_declaration>
    /// <variable_name> [<type>] [ { DEFAULT | := } <expression>]
    ///
    /// <cursor_declaration>
    /// <cursor_name> CURSOR FOR <query>
    ///
    /// <resultset_declaration>
    /// <resultset_name> RESULTSET [ { DEFAULT | := } ( <query> ) ] ;
    ///
    /// <exception_declaration>
    /// <exception_name> EXCEPTION [ ( <exception_number> , '<exception_message>' ) ] ;
    /// ```
    ///
    /// [Snowflake]: https://docs.snowflake.com/en/sql-reference/snowflake-scripting/declare
    pub fn parse_snowflake_declare(&mut self) -> Result<Statement, ParserError> {
        let mut stmts = vec![];
        loop {
            let name = self.parse_identifier()?;
            let (declare_type, for_query, assigned_expr, data_type) =
                if self.parse_keyword(Keyword::CURSOR) {
                    self.expect_keyword_is(Keyword::FOR)?;
                    match &self.peek_token_ref().token {
                        Token::Word(w) if w.keyword == Keyword::SELECT => (
                            Some(DeclareType::Cursor),
                            Some(self.parse_query()?),
                            None,
                            None,
                        ),
                        _ => (
                            Some(DeclareType::Cursor),
                            None,
                            Some(DeclareAssignment::For(Box::new(self.parse_expr()?))),
                            None,
                        ),
                    }
                } else if self.parse_keyword(Keyword::RESULTSET) {
                    let assigned_expr = if self.peek_token_ref().token != Token::SemiColon {
                        self.parse_snowflake_variable_declaration_expression()?
                    } else {
                        // Nothing more to do. The statement has no further parameters.
                        None
                    };

                    (Some(DeclareType::ResultSet), None, assigned_expr, None)
                } else if self.parse_keyword(Keyword::EXCEPTION) {
                    let assigned_expr = if self.peek_token_ref().token == Token::LParen {
                        Some(DeclareAssignment::Expr(Box::new(self.parse_expr()?)))
                    } else {
                        // Nothing more to do. The statement has no further parameters.
                        None
                    };

                    (Some(DeclareType::Exception), None, assigned_expr, None)
                } else {
                    // Without an explicit keyword, the only valid option is variable declaration.
                    let (assigned_expr, data_type) = if let Some(assigned_expr) =
                        self.parse_snowflake_variable_declaration_expression()?
                    {
                        (Some(assigned_expr), None)
                    } else if let Token::Word(_) = &self.peek_token_ref().token {
                        let data_type = self.parse_data_type()?;
                        (
                            self.parse_snowflake_variable_declaration_expression()?,
                            Some(data_type),
                        )
                    } else {
                        (None, None)
                    };
                    (None, None, assigned_expr, data_type)
                };
            let stmt = Declare {
                names: vec![name],
                data_type,
                assignment: assigned_expr,
                declare_type,
                binary: None,
                sensitive: None,
                scroll: None,
                hold: None,
                for_query,
            };

            stmts.push(stmt);
            if self.consume_token(&Token::SemiColon) {
                match &self.peek_token_ref().token {
                    Token::Word(w)
                        if ALL_KEYWORDS
                            .binary_search(&w.value.to_uppercase().as_str())
                            .is_err() =>
                    {
                        // Not a keyword - start of a new declaration.
                        continue;
                    }
                    _ => {
                        // Put back the semicolon, this is the end of the DECLARE statement.
                        self.prev_token();
                    }
                }
            }

            break;
        }

        Ok(Statement::Declare { stmts })
    }

    /// Parse a [MsSql] `DECLARE` statement.
    ///
    /// Syntax:
    /// ```text
    /// DECLARE
    // {
    //   { @local_variable [AS] data_type [ = value ] }
    //   | { @cursor_variable_name CURSOR [ FOR ] }
    // } [ ,...n ]
    /// ```
    /// [MsSql]: https://learn.microsoft.com/en-us/sql/t-sql/language-elements/declare-local-variable-transact-sql?view=sql-server-ver16
    pub fn parse_mssql_declare(&mut self) -> Result<Statement, ParserError> {
        let stmts = self.parse_comma_separated(Parser::parse_mssql_declare_stmt)?;

        Ok(Statement::Declare { stmts })
    }

    /// Parse the body of a [MsSql] `DECLARE`statement.
    ///
    /// Syntax:
    /// ```text
    // {
    //   { @local_variable [AS] data_type [ = value ] }
    //   | { @cursor_variable_name CURSOR [ FOR ]}
    // } [ ,...n ]
    /// ```
    /// [MsSql]: https://learn.microsoft.com/en-us/sql/t-sql/language-elements/declare-local-variable-transact-sql?view=sql-server-ver16
    pub fn parse_mssql_declare_stmt(&mut self) -> Result<Declare, ParserError> {
        let name = {
            let ident = self.parse_identifier()?;
            if !ident.value.starts_with('@')
                && !matches!(
                    &self.peek_token_ref().token,
                    Token::Word(w) if w.keyword == Keyword::CURSOR
                )
            {
                Err(ParserError::TokenizerError(
                    "Invalid MsSql variable declaration.".to_string(),
                ))
            } else {
                Ok(ident)
            }
        }?;

        let (declare_type, data_type) = match &self.peek_token_ref().token {
            Token::Word(w) => match w.keyword {
                Keyword::CURSOR => {
                    self.next_token();
                    (Some(DeclareType::Cursor), None)
                }
                Keyword::AS => {
                    self.next_token();
                    (None, Some(self.parse_data_type()?))
                }
                _ => (None, Some(self.parse_data_type()?)),
            },
            _ => (None, Some(self.parse_data_type()?)),
        };

        let (for_query, assignment) = if self.peek_keyword(Keyword::FOR) {
            self.next_token();
            let query = Some(self.parse_query()?);
            (query, None)
        } else {
            let assignment = self.parse_mssql_variable_declaration_expression()?;
            (None, assignment)
        };

        Ok(Declare {
            names: vec![name],
            data_type,
            assignment,
            declare_type,
            binary: None,
            sensitive: None,
            scroll: None,
            hold: None,
            for_query,
        })
    }

    /// Parses the assigned expression in a variable declaration.
    ///
    /// Syntax:
    /// ```text
    /// [ { DEFAULT | := } <expression>]
    /// ```
    /// <https://docs.snowflake.com/en/sql-reference/snowflake-scripting/declare#variable-declaration-syntax>
    pub fn parse_snowflake_variable_declaration_expression(
        &mut self,
    ) -> Result<Option<DeclareAssignment>, ParserError> {
        Ok(match &self.peek_token_ref().token {
            Token::Word(w) if w.keyword == Keyword::DEFAULT => {
                self.next_token(); // Skip `DEFAULT`
                Some(DeclareAssignment::Default(Box::new(self.parse_expr()?)))
            }
            Token::Assignment => {
                self.next_token(); // Skip `:=`
                Some(DeclareAssignment::DuckAssignment(Box::new(
                    self.parse_expr()?,
                )))
            }
            _ => None,
        })
    }

    /// Parses the assigned expression in a variable declaration.
    ///
    /// Syntax:
    /// ```text
    /// [ = <expression>]
    /// ```
    pub fn parse_mssql_variable_declaration_expression(
        &mut self,
    ) -> Result<Option<DeclareAssignment>, ParserError> {
        Ok(match &self.peek_token_ref().token {
            Token::Eq => {
                self.next_token(); // Skip `=`
                Some(DeclareAssignment::MsSqlAssignment(Box::new(
                    self.parse_expr()?,
                )))
            }
            _ => None,
        })
    }

    /// Parse `FETCH [direction] { FROM | IN } cursor INTO target;` statement.
    pub fn parse_fetch_statement(&mut self) -> Result<Statement, ParserError> {
        let direction = if self.parse_keyword(Keyword::NEXT) {
            FetchDirection::Next
        } else if self.parse_keyword(Keyword::PRIOR) {
            FetchDirection::Prior
        } else if self.parse_keyword(Keyword::FIRST) {
            FetchDirection::First
        } else if self.parse_keyword(Keyword::LAST) {
            FetchDirection::Last
        } else if self.parse_keyword(Keyword::ABSOLUTE) {
            FetchDirection::Absolute {
                limit: self.parse_number_value()?,
            }
        } else if self.parse_keyword(Keyword::RELATIVE) {
            FetchDirection::Relative {
                limit: self.parse_number_value()?,
            }
        } else if self.parse_keyword(Keyword::FORWARD) {
            if self.parse_keyword(Keyword::ALL) {
                FetchDirection::ForwardAll
            } else {
                FetchDirection::Forward {
                    // TODO: Support optional
                    limit: Some(self.parse_number_value()?),
                }
            }
        } else if self.parse_keyword(Keyword::BACKWARD) {
            if self.parse_keyword(Keyword::ALL) {
                FetchDirection::BackwardAll
            } else {
                FetchDirection::Backward {
                    // TODO: Support optional
                    limit: Some(self.parse_number_value()?),
                }
            }
        } else if self.parse_keyword(Keyword::ALL) {
            FetchDirection::All
        } else {
            FetchDirection::Count {
                limit: self.parse_number_value()?,
            }
        };

        let position = if self.peek_keyword(Keyword::FROM) {
            self.expect_keyword(Keyword::FROM)?;
            FetchPosition::From
        } else if self.peek_keyword(Keyword::IN) {
            self.expect_keyword(Keyword::IN)?;
            FetchPosition::In
        } else {
            return parser_err!("Expected FROM or IN", self.peek_token_ref().span.start);
        };

        let name = self.parse_identifier()?;

        let into = if self.parse_keyword(Keyword::INTO) {
            Some(self.parse_object_name(false)?)
        } else {
            None
        };

        Ok(Statement::Fetch {
            name,
            direction,
            position,
            into,
        })
    }

    /// Parse a `DISCARD` statement.
    pub fn parse_discard(&mut self) -> Result<Statement, ParserError> {
        let object_type = if self.parse_keyword(Keyword::ALL) {
            DiscardObject::ALL
        } else if self.parse_keyword(Keyword::PLANS) {
            DiscardObject::PLANS
        } else if self.parse_keyword(Keyword::SEQUENCES) {
            DiscardObject::SEQUENCES
        } else if self.parse_keyword(Keyword::TEMP) || self.parse_keyword(Keyword::TEMPORARY) {
            DiscardObject::TEMP
        } else {
            return self.expected_ref(
                "ALL, PLANS, SEQUENCES, TEMP or TEMPORARY after DISCARD",
                self.peek_token_ref(),
            );
        };
        Ok(Statement::Discard { object_type })
    }

    /// Parse a `CREATE INDEX` statement.
    pub fn parse_create_index(&mut self, unique: bool) -> Result<CreateIndex, ParserError> {
        let concurrently = self.parse_keyword(Keyword::CONCURRENTLY);
        let r#async = self.parse_keyword(Keyword::ASYNC);
        let if_not_exists = self.parse_keywords(&[Keyword::IF, Keyword::NOT, Keyword::EXISTS]);

        let mut using = None;

        let index_name = if if_not_exists || !self.parse_keyword(Keyword::ON) {
            let index_name = self.parse_object_name(false)?;
            // MySQL allows `USING index_type` either before or after `ON table_name`
            using = self.parse_optional_using_then_index_type()?;
            self.expect_keyword_is(Keyword::ON)?;
            Some(index_name)
        } else {
            None
        };

        let table_name = self.parse_object_name(false)?;

        // MySQL allows having two `USING` clauses.
        // In that case, the second clause overwrites the first.
        using = self.parse_optional_using_then_index_type()?.or(using);

        let columns = self.parse_parenthesized_index_column_list()?;

        let include = if self.parse_keyword(Keyword::INCLUDE) {
            self.expect_token(&Token::LParen)?;
            let columns = self.parse_comma_separated(|p| p.parse_identifier())?;
            self.expect_token(&Token::RParen)?;
            columns
        } else {
            vec![]
        };

        let nulls_distinct = if self.parse_keyword(Keyword::NULLS) {
            let not = self.parse_keyword(Keyword::NOT);
            self.expect_keyword_is(Keyword::DISTINCT)?;
            Some(!not)
        } else {
            None
        };

        let with = if self.dialect.supports_create_index_with_clause()
            && self.parse_keyword(Keyword::WITH)
        {
            self.expect_token(&Token::LParen)?;
            let with_params = self.parse_comma_separated(Parser::parse_expr)?;
            self.expect_token(&Token::RParen)?;
            with_params
        } else {
            Vec::new()
        };

        let predicate = if self.parse_keyword(Keyword::WHERE) {
            Some(self.parse_expr()?)
        } else {
            None
        };

        // MySQL options (including the modern style of `USING` after the column list instead of
        // before, which is deprecated) shouldn't conflict with other preceding options (e.g. `WITH
        // PARSER` won't be caught by the above `WITH` clause parsing because MySQL doesn't set that
        // support flag). This is probably invalid syntax for other dialects, but it is simpler to
        // parse it anyway (as we do inside `ALTER TABLE` and `CREATE TABLE` parsing).
        let index_options = self.parse_index_options()?;

        // MySQL allows `ALGORITHM` and `LOCK` options. Unlike in `ALTER TABLE`, they need not be comma separated.
        let mut alter_options = Vec::new();
        while self
            .peek_one_of_keywords(&[Keyword::ALGORITHM, Keyword::LOCK])
            .is_some()
        {
            alter_options.push(self.parse_alter_table_operation()?)
        }

        Ok(CreateIndex {
            name: index_name,
            table_name,
            using,
            columns,
            unique,
            concurrently,
            r#async,
            if_not_exists,
            include,
            nulls_distinct,
            with,
            predicate,
            index_options,
            alter_options,
        })
    }

    /// Parse a `CREATE EXTENSION` statement.
    pub fn parse_create_extension(&mut self) -> Result<CreateExtension, ParserError> {
        let if_not_exists = self.parse_keywords(&[Keyword::IF, Keyword::NOT, Keyword::EXISTS]);
        let name = self.parse_identifier()?;

        let (schema, version, cascade) = if self.parse_keyword(Keyword::WITH) {
            let schema = if self.parse_keyword(Keyword::SCHEMA) {
                Some(self.parse_identifier()?)
            } else {
                None
            };

            let version = if self.parse_keyword(Keyword::VERSION) {
                Some(self.parse_identifier()?)
            } else {
                None
            };

            let cascade = self.parse_keyword(Keyword::CASCADE);

            (schema, version, cascade)
        } else {
            (None, None, false)
        };

        Ok(CreateExtension {
            name,
            if_not_exists,
            schema,
            version,
            cascade,
        })
    }

    /// Parse a PostgreSQL-specific [Statement::CreateCollation] statement.
    pub fn parse_create_collation(&mut self) -> Result<CreateCollation, ParserError> {
        let if_not_exists = self.parse_keywords(&[Keyword::IF, Keyword::NOT, Keyword::EXISTS]);
        let name = self.parse_object_name(false)?;

        let definition = if self.parse_keyword(Keyword::FROM) {
            CreateCollationDefinition::From(self.parse_object_name(false)?)
        } else if self.consume_token(&Token::LParen) {
            let options = self.parse_comma_separated(Parser::parse_sql_option)?;
            self.expect_token(&Token::RParen)?;
            CreateCollationDefinition::Options(options)
        } else {
            return self.expected_ref(
                "FROM or parenthesized option list after CREATE COLLATION name",
                self.peek_token_ref(),
            );
        };

        Ok(CreateCollation {
            if_not_exists,
            name,
            definition,
        })
    }

    /// Parse a PostgreSQL-specific [Statement::DropExtension] statement.
    pub fn parse_drop_extension(&mut self) -> Result<Statement, ParserError> {
        let if_exists = self.parse_keywords(&[Keyword::IF, Keyword::EXISTS]);
        let names = self.parse_comma_separated(|p| p.parse_identifier())?;
        let cascade_or_restrict =
            self.parse_one_of_keywords(&[Keyword::CASCADE, Keyword::RESTRICT]);
        Ok(Statement::DropExtension(DropExtension {
            names,
            if_exists,
            cascade_or_restrict: cascade_or_restrict
                .map(|k| match k {
                    Keyword::CASCADE => Ok(ReferentialAction::Cascade),
                    Keyword::RESTRICT => Ok(ReferentialAction::Restrict),
                    _ => self.expected_ref("CASCADE or RESTRICT", self.peek_token_ref()),
                })
                .transpose()?,
        }))
    }

    /// Parse a[Statement::DropOperator] statement.
    ///
    pub fn parse_drop_operator(&mut self) -> Result<Statement, ParserError> {
        let if_exists = self.parse_keywords(&[Keyword::IF, Keyword::EXISTS]);
        let operators = self.parse_comma_separated(|p| p.parse_drop_operator_signature())?;
        let drop_behavior = self.parse_optional_drop_behavior();
        Ok(Statement::DropOperator(DropOperator {
            if_exists,
            operators,
            drop_behavior,
        }))
    }

    /// Parse an operator signature for a [Statement::DropOperator]
    /// Format: `name ( { left_type | NONE } , right_type )`
    fn parse_drop_operator_signature(&mut self) -> Result<DropOperatorSignature, ParserError> {
        let name = self.parse_operator_name()?;
        self.expect_token(&Token::LParen)?;

        // Parse left operand type (or NONE for prefix operators)
        let left_type = if self.parse_keyword(Keyword::NONE) {
            None
        } else {
            Some(self.parse_data_type()?)
        };

        self.expect_token(&Token::Comma)?;

        // Parse right operand type (always required)
        let right_type = self.parse_data_type()?;

        self.expect_token(&Token::RParen)?;

        Ok(DropOperatorSignature {
            name,
            left_type,
            right_type,
        })
    }

    /// Parse a [Statement::DropOperatorFamily]
    ///
    /// [PostgreSQL Documentation](https://www.postgresql.org/docs/current/sql-dropopfamily.html)
    pub fn parse_drop_operator_family(&mut self) -> Result<Statement, ParserError> {
        let if_exists = self.parse_keywords(&[Keyword::IF, Keyword::EXISTS]);
        let names = self.parse_comma_separated(|p| p.parse_object_name(false))?;
        self.expect_keyword(Keyword::USING)?;
        let using = self.parse_identifier()?;
        let drop_behavior = self.parse_optional_drop_behavior();
        Ok(Statement::DropOperatorFamily(DropOperatorFamily {
            if_exists,
            names,
            using,
            drop_behavior,
        }))
    }

    /// Parse a [Statement::DropOperatorClass]
    ///
    /// [PostgreSQL Documentation](https://www.postgresql.org/docs/current/sql-dropopclass.html)
    pub fn parse_drop_operator_class(&mut self) -> Result<Statement, ParserError> {
        let if_exists = self.parse_keywords(&[Keyword::IF, Keyword::EXISTS]);
        let names = self.parse_comma_separated(|p| p.parse_object_name(false))?;
        self.expect_keyword(Keyword::USING)?;
        let using = self.parse_identifier()?;
        let drop_behavior = self.parse_optional_drop_behavior();
        Ok(Statement::DropOperatorClass(DropOperatorClass {
            if_exists,
            names,
            using,
            drop_behavior,
        }))
    }

    /// Parse Hive distribution style.
    ///
    /// TODO: Support parsing for `SKEWED` distribution style.
    pub fn parse_hive_distribution(&mut self) -> Result<HiveDistributionStyle, ParserError> {
        if self.parse_keywords(&[Keyword::PARTITIONED, Keyword::BY]) {
            self.expect_token(&Token::LParen)?;
            let columns =
                self.parse_comma_separated(|parser| parser.parse_column_def_inner(true))?;
            self.expect_token(&Token::RParen)?;
            Ok(HiveDistributionStyle::PARTITIONED { columns })
        } else {
            Ok(HiveDistributionStyle::NONE)
        }
    }

    /// Parse Redshift `DISTSTYLE { AUTO | EVEN | KEY | ALL }`.
    ///
    /// See <https://docs.aws.amazon.com/redshift/latest/dg/r_CREATE_TABLE_NEW.html>
    fn parse_dist_style(&mut self) -> Result<DistStyle, ParserError> {
        let token = self.next_token();
        match &token.token {
            Token::Word(w) => match w.keyword {
                Keyword::AUTO => Ok(DistStyle::Auto),
                Keyword::EVEN => Ok(DistStyle::Even),
                Keyword::KEY => Ok(DistStyle::Key),
                Keyword::ALL => Ok(DistStyle::All),
                _ => self.expected("AUTO, EVEN, KEY, or ALL", token),
            },
            _ => self.expected("AUTO, EVEN, KEY, or ALL", token),
        }
    }

    /// Parse Hive formats.
    pub fn parse_hive_formats(&mut self) -> Result<Option<HiveFormat>, ParserError> {
        let mut hive_format: Option<HiveFormat> = None;
        loop {
            match self.parse_one_of_keywords(&[
                Keyword::ROW,
                Keyword::STORED,
                Keyword::LOCATION,
                Keyword::WITH,
                Keyword::USING,
            ]) {
                Some(Keyword::ROW) => {
                    hive_format
                        .get_or_insert_with(HiveFormat::default)
                        .row_format = Some(self.parse_row_format()?);
                }
                Some(Keyword::STORED) => {
                    self.expect_keyword_is(Keyword::AS)?;
                    if self.parse_keyword(Keyword::INPUTFORMAT) {
                        let input_format = self.parse_expr()?;
                        self.expect_keyword_is(Keyword::OUTPUTFORMAT)?;
                        let output_format = self.parse_expr()?;
                        hive_format.get_or_insert_with(HiveFormat::default).storage =
                            Some(HiveIOFormat::IOF {
                                input_format,
                                output_format,
                            });
                    } else {
                        let format = self.parse_file_format()?;
                        hive_format.get_or_insert_with(HiveFormat::default).storage =
                            Some(HiveIOFormat::FileFormat { format });
                    }
                }
                Some(Keyword::LOCATION) => {
                    hive_format.get_or_insert_with(HiveFormat::default).location =
                        Some(self.parse_literal_string()?);
                }
                Some(Keyword::WITH) => {
                    self.prev_token();
                    let properties = self
                        .parse_options_with_keywords(&[Keyword::WITH, Keyword::SERDEPROPERTIES])?;
                    if !properties.is_empty() {
                        hive_format
                            .get_or_insert_with(HiveFormat::default)
                            .serde_properties = Some(properties);
                    } else {
                        break;
                    }
                }
                Some(Keyword::USING) if self.dialect.supports_create_table_using() => {
                    let format = self.parse_identifier()?;
                    hive_format.get_or_insert_with(HiveFormat::default).storage =
                        Some(HiveIOFormat::Using { format });
                }
                Some(Keyword::USING) => {
                    // USING is not a table format keyword in this dialect; put it back
                    self.prev_token();
                    break;
                }
                None => break,
                _ => break,
            }
        }

        Ok(hive_format)
    }

    /// Parse Hive row format.
    pub fn parse_row_format(&mut self) -> Result<HiveRowFormat, ParserError> {
        self.expect_keyword_is(Keyword::FORMAT)?;
        match self.parse_one_of_keywords(&[Keyword::SERDE, Keyword::DELIMITED]) {
            Some(Keyword::SERDE) => {
                let class = self.parse_literal_string()?;
                Ok(HiveRowFormat::SERDE { class })
            }
            _ => {
                let mut row_delimiters = vec![];

                loop {
                    match self.parse_one_of_keywords(&[
                        Keyword::FIELDS,
                        Keyword::COLLECTION,
                        Keyword::MAP,
                        Keyword::LINES,
                        Keyword::NULL,
                    ]) {
                        Some(Keyword::FIELDS)
                            if self.parse_keywords(&[Keyword::TERMINATED, Keyword::BY]) =>
                        {
                            row_delimiters.push(HiveRowDelimiter {
                                delimiter: HiveDelimiter::FieldsTerminatedBy,
                                char: self.parse_identifier()?,
                            });

                            if self.parse_keywords(&[Keyword::ESCAPED, Keyword::BY]) {
                                row_delimiters.push(HiveRowDelimiter {
                                    delimiter: HiveDelimiter::FieldsEscapedBy,
                                    char: self.parse_identifier()?,
                                });
                            }
                        }
                        Some(Keyword::COLLECTION)
                            if self.parse_keywords(&[
                                Keyword::ITEMS,
                                Keyword::TERMINATED,
                                Keyword::BY,
                            ]) =>
                        {
                            row_delimiters.push(HiveRowDelimiter {
                                delimiter: HiveDelimiter::CollectionItemsTerminatedBy,
                                char: self.parse_identifier()?,
                            });
                        }
                        Some(Keyword::MAP)
                            if self.parse_keywords(&[
                                Keyword::KEYS,
                                Keyword::TERMINATED,
                                Keyword::BY,
                            ]) =>
                        {
                            row_delimiters.push(HiveRowDelimiter {
                                delimiter: HiveDelimiter::MapKeysTerminatedBy,
                                char: self.parse_identifier()?,
                            });
                        }
                        Some(Keyword::LINES)
                            if self.parse_keywords(&[Keyword::TERMINATED, Keyword::BY]) =>
                        {
                            row_delimiters.push(HiveRowDelimiter {
                                delimiter: HiveDelimiter::LinesTerminatedBy,
                                char: self.parse_identifier()?,
                            });
                        }
                        Some(Keyword::NULL)
                            if self.parse_keywords(&[Keyword::DEFINED, Keyword::AS]) =>
                        {
                            row_delimiters.push(HiveRowDelimiter {
                                delimiter: HiveDelimiter::NullDefinedAs,
                                char: self.parse_identifier()?,
                            });
                        }
                        Some(Keyword::NULL) => break,
                        _ => {
                            break;
                        }
                    }
                }

                Ok(HiveRowFormat::DELIMITED {
                    delimiters: row_delimiters,
                })
            }
        }
    }

    fn parse_optional_on_cluster(&mut self) -> Result<Option<Ident>, ParserError> {
        if self.parse_keywords(&[Keyword::ON, Keyword::CLUSTER]) {
            Ok(Some(self.parse_identifier()?))
        } else {
            Ok(None)
        }
    }

    /// Parse `CREATE TABLE` statement.
    #[expect(
        clippy::too_many_arguments,
        reason = "each flag is a `CREATE` modifier the caller parsed before `TABLE`"
    )]
    pub fn parse_create_table(
        &mut self,
        or_replace: bool,
        temporary: bool,
        unlogged: bool,
        global: Option<bool>,
        transient: bool,
        volatile: bool,
        multiset: Option<bool>,
    ) -> Result<CreateTable, ParserError> {
        let allow_unquoted_hyphen = dialect_of!(self is BigQueryDialect);
        let if_not_exists = self.parse_keywords(&[Keyword::IF, Keyword::NOT, Keyword::EXISTS]);
        let table_name = self.parse_object_name(allow_unquoted_hyphen)?;

        let fallback = if self.dialect.supports_leading_comma_before_table_options()
            && self.consume_token(&Token::Comma)
        {
            let fallback = self.maybe_parse_fallback()?;
            if fallback.is_none() {
                self.prev_token(); // Put back comma.
            }
            fallback
        } else {
            None
        };

        // PostgreSQL PARTITION OF for child partition tables
        // Note: This is a PostgreSQL-specific feature, but the dialect check was intentionally
        // removed to allow GenericDialect and other dialects to parse this syntax. This enables
        // multi-dialect SQL tools to work with PostgreSQL-specific DDL statements.
        //
        // PARTITION OF can be combined with other table definition clauses in the AST,
        // though PostgreSQL itself prohibits PARTITION OF with AS SELECT or LIKE clauses.
        // The parser accepts these combinations for flexibility; semantic validation
        // is left to downstream tools.
        // Child partitions can have their own constraints and indexes.
        let partition_of = if self.parse_keywords(&[Keyword::PARTITION, Keyword::OF]) {
            Some(self.parse_object_name(allow_unquoted_hyphen)?)
        } else {
            None
        };

        // Clickhouse has `ON CLUSTER 'cluster'` syntax for DDLs
        let on_cluster = self.parse_optional_on_cluster()?;

        let like = self.maybe_parse_create_table_like(allow_unquoted_hyphen)?;

        let clone = if self.parse_keyword(Keyword::CLONE) {
            self.parse_object_name(allow_unquoted_hyphen).ok()
        } else {
            None
        };

        // parse optional column list (schema)
        let (columns, constraints) = self.parse_columns()?;
        let comment_after_column_def =
            if dialect_of!(self is HiveDialect) && self.parse_keyword(Keyword::COMMENT) {
                let next_token = self.next_token();
                match next_token.token {
                    Token::SingleQuotedString(str) => Some(CommentDef::WithoutEq(str)),
                    _ => self.expected("comment", next_token)?,
                }
            } else {
                None
            };

        // PostgreSQL PARTITION OF: partition bound specification
        let for_values = if partition_of.is_some() {
            if self.peek_keyword(Keyword::FOR) || self.peek_keyword(Keyword::DEFAULT) {
                Some(self.parse_partition_for_values()?)
            } else {
                return self.expected_ref(
                    "FOR VALUES or DEFAULT after PARTITION OF",
                    self.peek_token_ref(),
                );
            }
        } else {
            None
        };

        let sqlite_table_options = self.parse_sqlite_table_options()?;

        let hive_distribution = self.parse_hive_distribution()?;
        let clustered_by = self.parse_optional_clustered_by()?;
        let hive_formats = self.parse_hive_formats()?;

        let create_table_config = self.parse_optional_create_table_config()?;

        // ClickHouse supports `PRIMARY KEY`, before `ORDER BY`
        // https://clickhouse.com/docs/en/sql-reference/statements/create/table#primary-key
        let primary_key = if dialect_of!(self is ClickHouseDialect | GenericDialect)
            && self.parse_keywords(&[Keyword::PRIMARY, Keyword::KEY])
        {
            Some(Box::new(self.parse_expr()?))
        } else {
            None
        };

        let order_by = if self.parse_keywords(&[Keyword::ORDER, Keyword::BY]) {
            Some(self.parse_sorting_key()?)
        } else {
            None
        };

        // ClickHouse allows PARTITION BY after ORDER BY
        // https://clickhouse.com/docs/en/sql-reference/statements/create/table#partition-by
        let partition_by = if create_table_config.partition_by.is_none()
            && self.dialect.supports_partition_by_after_order_by()
            && self.parse_keywords(&[Keyword::PARTITION, Keyword::BY])
        {
            Some(Box::new(self.parse_expr()?))
        } else {
            create_table_config.partition_by
        };

        let on_commit = if self.parse_keywords(&[Keyword::ON, Keyword::COMMIT]) {
            Some(self.parse_create_table_on_commit()?)
        } else {
            None
        };

        // Redshift: BACKUP YES|NO
        let backup = if self.parse_keyword(Keyword::BACKUP) {
            let keyword = self.expect_one_of_keywords(&[Keyword::YES, Keyword::NO])?;
            Some(keyword == Keyword::YES)
        } else {
            None
        };

        // Redshift: DISTSTYLE, DISTKEY, SORTKEY
        let diststyle = if self.parse_keyword(Keyword::DISTSTYLE) {
            Some(self.parse_dist_style()?)
        } else {
            None
        };
        let distkey = if self.parse_keyword(Keyword::DISTKEY) {
            self.expect_token(&Token::LParen)?;
            let expr = self.parse_expr()?;
            self.expect_token(&Token::RParen)?;
            Some(expr)
        } else {
            None
        };
        let sortkey = if self.parse_keyword(Keyword::SORTKEY) {
            self.expect_token(&Token::LParen)?;
            let columns = self.parse_comma_separated(|p| p.parse_expr())?;
            self.expect_token(&Token::RParen)?;
            Some(columns)
        } else {
            None
        };

        // Parse optional `AS ( query )`
        let query = if self.parse_keyword(Keyword::AS) {
            Some(self.parse_query()?)
        } else if self.dialect.supports_create_table_select() && self.parse_keyword(Keyword::SELECT)
        {
            // rewind the SELECT keyword
            self.prev_token();
            Some(self.parse_query()?)
        } else {
            None
        };

        // `WITH DATA` clause only applies if there is a query body.
        let with_data = if query.is_some() {
            self.maybe_parse_with_data()?
        } else {
            None
        };

        Ok(CreateTableBuilder::new(table_name)
            .temporary(temporary)
            .unlogged(unlogged)
            .columns(columns)
            .constraints(constraints)
            .or_replace(or_replace)
            .if_not_exists(if_not_exists)
            .transient(transient)
            .volatile(volatile)
            .multiset(multiset)
            .fallback(fallback)
            .hive_distribution(hive_distribution)
            .hive_formats(hive_formats)
            .global(global)
            .query(query)
            .sqlite_table_options(sqlite_table_options)
            .like(like)
            .clone_clause(clone)
            .comment_after_column_def(comment_after_column_def)
            .order_by(order_by)
            .on_commit(on_commit)
            .on_cluster(on_cluster)
            .clustered_by(clustered_by)
            .partition_by(partition_by)
            .cluster_by(create_table_config.cluster_by)
            .inherits(create_table_config.inherits)
            .partition_of(partition_of)
            .for_values(for_values)
            .table_options(create_table_config.table_options)
            .primary_key(primary_key)
            .with_data(with_data)
            .backup(backup)
            .diststyle(diststyle)
            .distkey(distkey)
            .sortkey(sortkey)
            .build())
    }

    /// Parse SQLite's `table-options` list, empty when absent, and the
    /// optional comma before it.
    ///
    /// See <https://www.sqlite.org/lang_createtable.html>.
    fn parse_sqlite_table_options(&mut self) -> Result<SqliteTableOptions, ParserError> {
        let leading_comma = self.consume_token(&Token::Comma);
        let Some(first) = self.maybe_parse_sqlite_table_option()? else {
            if leading_comma {
                self.prev_token();
            }
            return Ok(SqliteTableOptions::default());
        };
        let mut options = Vec::with_capacity(2);
        options.push(first);
        while self.consume_token(&Token::Comma) {
            match self.maybe_parse_sqlite_table_option()? {
                Some(option) => options.push(option),
                None => return self.expected_ref("WITHOUT ROWID or STRICT", self.peek_token_ref()),
            }
        }
        Ok(SqliteTableOptions {
            leading_comma,
            options,
        })
    }

    fn maybe_parse_sqlite_table_option(
        &mut self,
    ) -> Result<Option<SqliteTableOption>, ParserError> {
        if self.parse_keyword(Keyword::WITHOUT) {
            self.expect_keyword_is(Keyword::ROWID)?;
            Ok(Some(SqliteTableOption::WithoutRowid))
        } else if self.parse_keyword(Keyword::STRICT) {
            Ok(Some(SqliteTableOption::Strict))
        } else {
            Ok(None)
        }
    }

    /// Parse `MULTISET` table-kind prefix on `CREATE TABLE`.
    fn maybe_parse_multiset(&mut self) -> Option<bool> {
        match self.parse_one_of_keywords(&[Keyword::SET, Keyword::MULTISET]) {
            Some(Keyword::MULTISET) => Some(true),
            Some(Keyword::SET) => Some(false),
            _ => None,
        }
    }

    /// Parse `FALLBACK` option on a `CREATE TABLE` statement,
    fn maybe_parse_fallback(&mut self) -> Result<Option<bool>, ParserError> {
        if self.parse_keywords(&[Keyword::NO, Keyword::FALLBACK]) {
            Ok(Some(false))
        } else if self.parse_keyword(Keyword::FALLBACK) {
            Ok(Some(true))
        } else {
            Ok(None)
        }
    }

    /// Parse [`WithData`] clause on `CREATE TABLE ... AS` statement.
    fn maybe_parse_with_data(&mut self) -> Result<Option<WithData>, ParserError> {
        let data = if self.parse_keywords(&[Keyword::WITH, Keyword::DATA]) {
            true
        } else if self.parse_keywords(&[Keyword::WITH, Keyword::NO, Keyword::DATA]) {
            false
        } else {
            return Ok(None);
        };

        let statistics = if self.parse_keywords(&[Keyword::AND, Keyword::STATISTICS]) {
            Some(true)
        } else if self.parse_keywords(&[Keyword::AND, Keyword::NO, Keyword::STATISTICS]) {
            Some(false)
        } else {
            None
        };

        Ok(Some(WithData { data, statistics }))
    }

    fn maybe_parse_create_table_like(
        &mut self,
        allow_unquoted_hyphen: bool,
    ) -> Result<Option<CreateTableLikeKind>, ParserError> {
        let like = if self.dialect.supports_create_table_like_parenthesized()
            && self.consume_token(&Token::LParen)
        {
            if self.parse_keyword(Keyword::LIKE) {
                let name = self.parse_object_name(allow_unquoted_hyphen)?;
                let defaults = if self.parse_keywords(&[Keyword::INCLUDING, Keyword::DEFAULTS]) {
                    Some(CreateTableLikeDefaults::Including)
                } else if self.parse_keywords(&[Keyword::EXCLUDING, Keyword::DEFAULTS]) {
                    Some(CreateTableLikeDefaults::Excluding)
                } else {
                    None
                };
                self.expect_token(&Token::RParen)?;
                Some(CreateTableLikeKind::Parenthesized(CreateTableLike {
                    name,
                    defaults,
                }))
            } else {
                // Rollback the '(' it's probably the columns list
                self.prev_token();
                None
            }
        } else if self.parse_keyword(Keyword::LIKE) || self.parse_keyword(Keyword::ILIKE) {
            let name = self.parse_object_name(allow_unquoted_hyphen)?;
            Some(CreateTableLikeKind::Plain(CreateTableLike {
                name,
                defaults: None,
            }))
        } else {
            None
        };
        Ok(like)
    }

    pub(crate) fn parse_create_table_on_commit(&mut self) -> Result<OnCommit, ParserError> {
        if self.parse_keywords(&[Keyword::DELETE, Keyword::ROWS]) {
            Ok(OnCommit::DeleteRows)
        } else if self.parse_keywords(&[Keyword::PRESERVE, Keyword::ROWS]) {
            Ok(OnCommit::PreserveRows)
        } else if self.parse_keywords(&[Keyword::DROP]) {
            Ok(OnCommit::Drop)
        } else {
            parser_err!(
                "Expecting DELETE ROWS, PRESERVE ROWS or DROP",
                self.peek_token_ref()
            )
        }
    }

    /// Parse [ForValues] of a `PARTITION OF` clause.
    ///
    /// Parses: `FOR VALUES partition_bound_spec | DEFAULT`
    ///
    /// [PostgreSQL](https://www.postgresql.org/docs/current/sql-createtable.html)
    fn parse_partition_for_values(&mut self) -> Result<ForValues, ParserError> {
        if self.parse_keyword(Keyword::DEFAULT) {
            return Ok(ForValues::Default);
        }

        self.expect_keywords(&[Keyword::FOR, Keyword::VALUES])?;

        if self.parse_keyword(Keyword::IN) {
            // FOR VALUES IN (expr, ...)
            self.expect_token(&Token::LParen)?;
            if self.peek_token_ref().token == Token::RParen {
                return self.expected_ref("at least one value", self.peek_token_ref());
            }
            let values = self.parse_comma_separated(Parser::parse_expr)?;
            self.expect_token(&Token::RParen)?;
            Ok(ForValues::In(values))
        } else if self.parse_keyword(Keyword::FROM) {
            // FOR VALUES FROM (...) TO (...)
            self.expect_token(&Token::LParen)?;
            if self.peek_token_ref().token == Token::RParen {
                return self.expected_ref("at least one value", self.peek_token_ref());
            }
            let from = self.parse_comma_separated(Parser::parse_partition_bound_value)?;
            self.expect_token(&Token::RParen)?;
            self.expect_keyword(Keyword::TO)?;
            self.expect_token(&Token::LParen)?;
            if self.peek_token_ref().token == Token::RParen {
                return self.expected_ref("at least one value", self.peek_token_ref());
            }
            let to = self.parse_comma_separated(Parser::parse_partition_bound_value)?;
            self.expect_token(&Token::RParen)?;
            Ok(ForValues::From { from, to })
        } else if self.parse_keyword(Keyword::WITH) {
            // FOR VALUES WITH (MODULUS n, REMAINDER r)
            self.expect_token(&Token::LParen)?;
            self.expect_keyword(Keyword::MODULUS)?;
            let modulus = self.parse_literal_uint()?;
            self.expect_token(&Token::Comma)?;
            self.expect_keyword(Keyword::REMAINDER)?;
            let remainder = self.parse_literal_uint()?;
            self.expect_token(&Token::RParen)?;
            Ok(ForValues::With { modulus, remainder })
        } else {
            self.expected_ref("IN, FROM, or WITH after FOR VALUES", self.peek_token_ref())
        }
    }

    /// Parse a single partition bound value (MINVALUE, MAXVALUE, or expression).
    fn parse_partition_bound_value(&mut self) -> Result<PartitionBoundValue, ParserError> {
        if self.parse_keyword(Keyword::MINVALUE) {
            Ok(PartitionBoundValue::MinValue)
        } else if self.parse_keyword(Keyword::MAXVALUE) {
            Ok(PartitionBoundValue::MaxValue)
        } else {
            Ok(PartitionBoundValue::Expr(self.parse_expr()?))
        }
    }

    /// Parse configuration like inheritance, partitioning, clustering information during the table creation.
    ///
    /// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#syntax_2)
    /// [PostgreSQL](https://www.postgresql.org/docs/current/ddl-partitioning.html)
    /// [MySql](https://dev.mysql.com/doc/refman/8.4/en/create-table.html)
    fn parse_optional_create_table_config(
        &mut self,
    ) -> Result<CreateTableConfiguration, ParserError> {
        let mut table_options = CreateTableOptions::None;

        let inherits = if self.parse_keyword(Keyword::INHERITS) {
            Some(self.parse_parenthesized_qualified_column_list(IsOptional::Mandatory, false)?)
        } else {
            None
        };

        // PostgreSQL supports `WITH ( options )`, before `AS`
        let with_options = self.parse_options(Keyword::WITH)?;
        if !with_options.is_empty() {
            table_options = CreateTableOptions::With(with_options)
        }

        let table_properties = self.parse_options(Keyword::TBLPROPERTIES)?;
        if !table_properties.is_empty() {
            table_options = CreateTableOptions::TableProperties(table_properties);
        }
        let partition_by = if dialect_of!(self is BigQueryDialect | PostgreSqlDialect | GenericDialect)
            && self.parse_keywords(&[Keyword::PARTITION, Keyword::BY])
        {
            Some(Box::new(self.parse_expr()?))
        } else {
            None
        };

        let mut cluster_by = None;
        if dialect_of!(self is BigQueryDialect | GenericDialect) {
            if self.parse_keywords(&[Keyword::CLUSTER, Keyword::BY]) {
                cluster_by = Some(WrappedCollection::NoWrapping(
                    self.parse_comma_separated(|p| p.parse_expr())?,
                ));
            };

            if let Token::Word(word) = &self.peek_token_ref().token {
                if word.keyword == Keyword::OPTIONS {
                    table_options =
                        CreateTableOptions::Options(self.parse_options(Keyword::OPTIONS)?)
                }
            };
        }

        if !dialect_of!(self is HiveDialect) && table_options == CreateTableOptions::None {
            let plain_options = self.parse_plain_options()?;
            if !plain_options.is_empty() {
                table_options = CreateTableOptions::Plain(plain_options)
            }
        };

        Ok(CreateTableConfiguration {
            partition_by,
            cluster_by,
            inherits,
            table_options,
        })
    }

    fn parse_plain_option(&mut self) -> Result<Option<SqlOption>, ParserError> {
        // Single parameter option
        // <https://dev.mysql.com/doc/refman/8.4/en/create-table.html>
        if self.parse_keywords(&[Keyword::START, Keyword::TRANSACTION]) {
            return Ok(Some(SqlOption::Ident(Ident::new("START TRANSACTION"))));
        }

        // Custom option
        // <https://dev.mysql.com/doc/refman/8.4/en/create-table.html>
        if self.parse_keywords(&[Keyword::COMMENT]) {
            let has_eq = self.consume_token(&Token::Eq);
            let value = self.next_token();

            let comment = match (has_eq, value.token) {
                (true, Token::SingleQuotedString(s)) => {
                    Ok(Some(SqlOption::Comment(CommentDef::WithEq(s))))
                }
                (false, Token::SingleQuotedString(s)) => {
                    Ok(Some(SqlOption::Comment(CommentDef::WithoutEq(s))))
                }
                (_, token) => {
                    self.expected("Token::SingleQuotedString", TokenWithSpan::wrap(token))
                }
            };
            return comment;
        }

        // <https://dev.mysql.com/doc/refman/8.4/en/create-table.html>
        // <https://clickhouse.com/docs/sql-reference/statements/create/table>
        if self.parse_keywords(&[Keyword::ENGINE]) {
            let _ = self.consume_token(&Token::Eq);
            let value = self.next_token();

            let engine = match value.token {
                Token::Word(w) => {
                    let parameters = if self.peek_token_ref().token == Token::LParen {
                        self.parse_parenthesized_identifiers()?
                    } else {
                        vec![]
                    };

                    Ok(Some(SqlOption::NamedParenthesizedList(
                        NamedParenthesizedList {
                            key: Ident::new("ENGINE"),
                            name: Some(w.into_ident(value.span)),
                            values: parameters,
                        },
                    )))
                }
                _ => {
                    return self.expected("Token::Word", value)?;
                }
            };

            return engine;
        }

        // <https://dev.mysql.com/doc/refman/8.4/en/create-table.html>
        if self.parse_keywords(&[Keyword::TABLESPACE]) {
            let _ = self.consume_token(&Token::Eq);
            let value = self.next_token();

            let tablespace = match value.token {
                Token::Word(Word { value: name, .. }) | Token::SingleQuotedString(name) => {
                    let storage = match self.parse_keyword(Keyword::STORAGE) {
                        true => {
                            let _ = self.consume_token(&Token::Eq);
                            let storage_token = self.next_token();
                            match &storage_token.token {
                                Token::Word(w) => match w.value.to_uppercase().as_str() {
                                    "DISK" => Some(StorageType::Disk),
                                    "MEMORY" => Some(StorageType::Memory),
                                    _ => self
                                        .expected("Storage type (DISK or MEMORY)", storage_token)?,
                                },
                                _ => self.expected("Token::Word", storage_token)?,
                            }
                        }
                        false => None,
                    };

                    Ok(Some(SqlOption::TableSpace(TablespaceOption {
                        name,
                        storage,
                    })))
                }
                _ => {
                    return self.expected("Token::Word", value)?;
                }
            };

            return tablespace;
        }

        // <https://dev.mysql.com/doc/refman/8.4/en/create-table.html>
        if self.parse_keyword(Keyword::UNION) {
            let _ = self.consume_token(&Token::Eq);
            let value = self.next_token();

            match value.token {
                Token::LParen => {
                    let tables: Vec<Ident> =
                        self.parse_comma_separated0(Parser::parse_identifier, Token::RParen)?;
                    self.expect_token(&Token::RParen)?;

                    return Ok(Some(SqlOption::NamedParenthesizedList(
                        NamedParenthesizedList {
                            key: Ident::new("UNION"),
                            name: None,
                            values: tables,
                        },
                    )));
                }
                _ => {
                    return self.expected("Token::LParen", value)?;
                }
            }
        }

        // Key/Value parameter option
        let key = if self.parse_keywords(&[Keyword::DEFAULT, Keyword::CHARSET]) {
            Ident::new("DEFAULT CHARSET")
        } else if self.parse_keyword(Keyword::CHARSET) {
            Ident::new("CHARSET")
        } else if self.parse_keywords(&[Keyword::DEFAULT, Keyword::CHARACTER, Keyword::SET]) {
            Ident::new("DEFAULT CHARACTER SET")
        } else if self.parse_keywords(&[Keyword::CHARACTER, Keyword::SET]) {
            Ident::new("CHARACTER SET")
        } else if self.parse_keywords(&[Keyword::DEFAULT, Keyword::COLLATE]) {
            Ident::new("DEFAULT COLLATE")
        } else if self.parse_keyword(Keyword::COLLATE) {
            Ident::new("COLLATE")
        } else if self.parse_keywords(&[Keyword::DATA, Keyword::DIRECTORY]) {
            Ident::new("DATA DIRECTORY")
        } else if self.parse_keywords(&[Keyword::INDEX, Keyword::DIRECTORY]) {
            Ident::new("INDEX DIRECTORY")
        } else if self.parse_keyword(Keyword::KEY_BLOCK_SIZE) {
            Ident::new("KEY_BLOCK_SIZE")
        } else if self.parse_keyword(Keyword::ROW_FORMAT) {
            Ident::new("ROW_FORMAT")
        } else if self.parse_keyword(Keyword::PACK_KEYS) {
            Ident::new("PACK_KEYS")
        } else if self.parse_keyword(Keyword::STATS_AUTO_RECALC) {
            Ident::new("STATS_AUTO_RECALC")
        } else if self.parse_keyword(Keyword::STATS_PERSISTENT) {
            Ident::new("STATS_PERSISTENT")
        } else if self.parse_keyword(Keyword::STATS_SAMPLE_PAGES) {
            Ident::new("STATS_SAMPLE_PAGES")
        } else if self.parse_keyword(Keyword::DELAY_KEY_WRITE) {
            Ident::new("DELAY_KEY_WRITE")
        } else if self.parse_keyword(Keyword::COMPRESSION) {
            Ident::new("COMPRESSION")
        } else if self.parse_keyword(Keyword::ENCRYPTION) {
            Ident::new("ENCRYPTION")
        } else if self.parse_keyword(Keyword::MAX_ROWS) {
            Ident::new("MAX_ROWS")
        } else if self.parse_keyword(Keyword::MIN_ROWS) {
            Ident::new("MIN_ROWS")
        } else if self.parse_keyword(Keyword::AUTOEXTEND_SIZE) {
            Ident::new("AUTOEXTEND_SIZE")
        } else if self.parse_keyword(Keyword::AVG_ROW_LENGTH) {
            Ident::new("AVG_ROW_LENGTH")
        } else if self.parse_keyword(Keyword::CHECKSUM) {
            Ident::new("CHECKSUM")
        } else if self.parse_keyword(Keyword::CONNECTION) {
            Ident::new("CONNECTION")
        } else if self.parse_keyword(Keyword::ENGINE_ATTRIBUTE) {
            Ident::new("ENGINE_ATTRIBUTE")
        } else if self.parse_keyword(Keyword::PASSWORD) {
            Ident::new("PASSWORD")
        } else if self.parse_keyword(Keyword::SECONDARY_ENGINE_ATTRIBUTE) {
            Ident::new("SECONDARY_ENGINE_ATTRIBUTE")
        } else if self.parse_keyword(Keyword::INSERT_METHOD) {
            Ident::new("INSERT_METHOD")
        } else if self.parse_keyword(Keyword::AUTO_INCREMENT) {
            Ident::new("AUTO_INCREMENT")
        } else {
            return Ok(None);
        };

        let _ = self.consume_token(&Token::Eq);

        let value = match self
            .maybe_parse(|parser| parser.parse_value())?
            .map(Expr::Value)
        {
            Some(expr) => expr,
            None => Expr::Identifier(self.parse_identifier()?),
        };

        Ok(Some(SqlOption::KeyValue { key, value }))
    }

    /// Parse plain options.
    pub fn parse_plain_options(&mut self) -> Result<Vec<SqlOption>, ParserError> {
        let mut options = Vec::new();

        while let Some(option) = self.parse_plain_option()? {
            options.push(option);
            // Some dialects support comma-separated options; it shouldn't introduce ambiguity to
            // consume it for all dialects.
            let _ = self.consume_token(&Token::Comma);
        }

        Ok(options)
    }

    /// Parse optional inline comment.
    pub fn parse_optional_inline_comment(&mut self) -> Result<Option<CommentDef>, ParserError> {
        let comment = if self.parse_keyword(Keyword::COMMENT) {
            let has_eq = self.consume_token(&Token::Eq);
            let comment = self.parse_comment_value()?;
            Some(if has_eq {
                CommentDef::WithEq(comment)
            } else {
                CommentDef::WithoutEq(comment)
            })
        } else {
            None
        };
        Ok(comment)
    }

    /// Parse comment value.
    pub fn parse_comment_value(&mut self) -> Result<String, ParserError> {
        let next_token = self.next_token();
        let value = match next_token.token {
            Token::SingleQuotedString(str) => str,
            Token::DollarQuotedString(str) => str.value,
            _ => self.expected("string literal", next_token)?,
        };
        Ok(value)
    }

    /// Parse optional procedure parameters.
    pub fn parse_optional_procedure_parameters(
        &mut self,
    ) -> Result<Option<Vec<ProcedureParam>>, ParserError> {
        let mut params = vec![];
        if !self.consume_token(&Token::LParen) || self.consume_token(&Token::RParen) {
            return Ok(Some(params));
        }
        loop {
            if let Token::Word(_) = &self.peek_token_ref().token {
                params.push(self.parse_procedure_param()?)
            }
            let comma = self.consume_token(&Token::Comma);
            if self.consume_token(&Token::RParen) {
                // allow a trailing comma, even though it's not in standard
                break;
            } else if !comma {
                return self.expected_ref(
                    "',' or ')' after parameter definition",
                    self.peek_token_ref(),
                );
            }
        }
        Ok(Some(params))
    }

    /// Parse columns and constraints.
    pub fn parse_columns(&mut self) -> Result<(Vec<ColumnDef>, Vec<TableConstraint>), ParserError> {
        let mut columns = vec![];
        let mut constraints = vec![];
        if !self.consume_token(&Token::LParen) || self.consume_token(&Token::RParen) {
            return Ok((columns, constraints));
        }

        loop {
            if let Some(constraint) = self.parse_optional_table_constraint()? {
                constraints.push(constraint);
            } else if let Token::Word(_) = &self.peek_token_ref().token {
                columns.push(self.parse_column_def()?);
            } else if matches!(&self.peek_token_ref().token, Token::SingleQuotedString(_))
                && self.dialect.supports_string_literal_column_names()
            {
                columns.push(self.parse_column_def()?);
            } else {
                return self.expected_ref(
                    "column name or constraint definition",
                    self.peek_token_ref(),
                );
            }

            let comma = self.consume_token(&Token::Comma);
            let rparen = self.peek_token_ref().token == Token::RParen;

            if !comma && !rparen {
                return self
                    .expected_ref("',' or ')' after column definition", self.peek_token_ref());
            };

            if rparen
                && (!comma
                    || self.dialect.supports_column_definition_trailing_commas()
                    || self.options.trailing_commas)
            {
                let _ = self.consume_token(&Token::RParen);
                break;
            }
        }

        Ok((columns, constraints))
    }

    /// Parse procedure parameter.
    pub fn parse_procedure_param(&mut self) -> Result<ProcedureParam, ParserError> {
        let mode = if self.parse_keyword(Keyword::IN) {
            Some(ArgMode::In)
        } else if self.parse_keyword(Keyword::OUT) {
            Some(ArgMode::Out)
        } else if self.parse_keyword(Keyword::INOUT) {
            Some(ArgMode::InOut)
        } else {
            None
        };
        let name = self.parse_identifier()?;
        let data_type = self.parse_data_type()?;
        let default = if self.consume_token(&Token::Eq) {
            Some(self.parse_expr()?)
        } else {
            None
        };

        Ok(ProcedureParam {
            name,
            data_type,
            mode,
            default,
        })
    }

    /// Parse column definition.
    pub fn parse_column_def(&mut self) -> Result<ColumnDef, ParserError> {
        self.parse_column_def_inner(false)
    }

    fn parse_column_def_inner(
        &mut self,
        optional_data_type: bool,
    ) -> Result<ColumnDef, ParserError> {
        let col_name = self.parse_identifier()?;
        let data_type = if self.is_column_type_sqlite_unspecified() {
            DataType::Unspecified
        } else if optional_data_type {
            self.maybe_parse(|parser| parser.parse_data_type())?
                .unwrap_or(DataType::Unspecified)
        } else {
            self.parse_data_type()?
        };
        let mut options = vec![];
        loop {
            if self.parse_keyword(Keyword::CONSTRAINT) {
                let name = Some(self.parse_identifier()?);
                if let Some(option) = self.parse_optional_column_option()? {
                    options.push(ColumnOptionDef { name, option });
                } else {
                    return self.expected_ref(
                        "constraint details after CONSTRAINT <name>",
                        self.peek_token_ref(),
                    );
                }
            } else if let Some(option) = self.parse_optional_column_option()? {
                options.push(ColumnOptionDef { name: None, option });
            } else {
                break;
            };
        }
        Ok(ColumnDef {
            name: col_name,
            data_type,
            options,
        })
    }

    fn is_column_type_sqlite_unspecified(&mut self) -> bool {
        if dialect_of!(self is SQLiteDialect) {
            match &self.peek_token_ref().token {
                Token::Word(word) => matches!(
                    word.keyword,
                    Keyword::CONSTRAINT
                        | Keyword::PRIMARY
                        | Keyword::NOT
                        | Keyword::UNIQUE
                        | Keyword::CHECK
                        | Keyword::DEFAULT
                        | Keyword::COLLATE
                        | Keyword::REFERENCES
                        | Keyword::GENERATED
                        | Keyword::AS
                ),
                _ => true, // e.g. comma immediately after column name
            }
        } else {
            false
        }
    }

    /// Parse optional column option.
    pub fn parse_optional_column_option(&mut self) -> Result<Option<ColumnOption>, ParserError> {
        if let Some(option) = self.dialect.parse_column_option(self)? {
            return option;
        }

        self.with_state(
            ColumnDefinition,
            |parser| -> Result<Option<ColumnOption>, ParserError> {
                parser.parse_optional_column_option_inner()
            },
        )
    }

    fn parse_optional_column_option_inner(&mut self) -> Result<Option<ColumnOption>, ParserError> {
        if self.parse_keywords(&[Keyword::CHARACTER, Keyword::SET]) {
            Ok(Some(ColumnOption::CharacterSet(
                self.parse_object_name(false)?,
            )))
        } else if self.parse_keywords(&[Keyword::COLLATE]) {
            Ok(Some(ColumnOption::Collation(
                self.parse_object_name(false)?,
            )))
        } else if self.parse_keywords(&[Keyword::NOT, Keyword::NULL]) {
            Ok(Some(ColumnOption::NotNull))
        } else if self.parse_keywords(&[Keyword::COMMENT]) {
            Ok(Some(ColumnOption::Comment(self.parse_comment_value()?)))
        } else if self.parse_keyword(Keyword::NULL) {
            Ok(Some(ColumnOption::Null))
        } else if self.parse_keyword(Keyword::DEFAULT) {
            Ok(Some(ColumnOption::Default(self.parse_expr()?)))
        } else if dialect_of!(self is ClickHouseDialect| GenericDialect)
            && self.parse_keyword(Keyword::MATERIALIZED)
        {
            Ok(Some(ColumnOption::Materialized(self.parse_expr()?)))
        } else if dialect_of!(self is ClickHouseDialect| GenericDialect)
            && self.parse_keyword(Keyword::ALIAS)
        {
            Ok(Some(ColumnOption::Alias(self.parse_expr()?)))
        } else if dialect_of!(self is ClickHouseDialect| GenericDialect)
            && self.parse_keyword(Keyword::EPHEMERAL)
        {
            // The expression is optional for the EPHEMERAL syntax, so we need to check
            // if the column definition has remaining tokens before parsing the expression.
            if matches!(self.peek_token_ref().token, Token::Comma | Token::RParen) {
                Ok(Some(ColumnOption::Ephemeral(None)))
            } else {
                Ok(Some(ColumnOption::Ephemeral(Some(self.parse_expr()?))))
            }
        } else if self.parse_keywords(&[Keyword::PRIMARY, Keyword::KEY]) {
            let characteristics = self.parse_constraint_characteristics()?;
            Ok(Some(
                PrimaryKeyConstraint {
                    name: None,
                    index_name: None,
                    index_type: None,
                    columns: vec![],
                    include: vec![],
                    index_options: vec![],
                    characteristics,
                }
                .into(),
            ))
        } else if self.parse_keyword(Keyword::UNIQUE) {
            let index_type_display =
                if self.dialect.supports_key_column_option() && self.parse_keyword(Keyword::KEY) {
                    KeyOrIndexDisplay::Key
                } else {
                    KeyOrIndexDisplay::None
                };
            let characteristics = self.parse_constraint_characteristics()?;
            Ok(Some(
                UniqueConstraint {
                    name: None,
                    index_name: None,
                    index_type_display,
                    index_type: None,
                    columns: vec![],
                    include: vec![],
                    index_options: vec![],
                    characteristics,
                    nulls_distinct: NullsDistinctOption::None,
                }
                .into(),
            ))
        } else if self.dialect.supports_key_column_option() && self.parse_keyword(Keyword::KEY) {
            // In MySQL, `KEY` in a column definition is shorthand for `PRIMARY KEY`.
            // See: https://dev.mysql.com/doc/refman/8.4/en/create-table.html
            let characteristics = self.parse_constraint_characteristics()?;
            Ok(Some(
                PrimaryKeyConstraint {
                    name: None,
                    index_name: None,
                    index_type: None,
                    columns: vec![],
                    include: vec![],
                    index_options: vec![],
                    characteristics,
                }
                .into(),
            ))
        } else if self.parse_keyword(Keyword::REFERENCES) {
            let foreign_table = self.parse_object_name(false)?;
            // PostgreSQL allows omitting the column list and
            // uses the primary key column of the foreign table by default
            let referred_columns = self.parse_parenthesized_column_list(Optional, false)?;
            let mut match_kind = None;
            let mut on_delete = None;
            let mut on_update = None;
            loop {
                if match_kind.is_none() && self.parse_keyword(Keyword::MATCH) {
                    match_kind = Some(self.parse_match_kind()?);
                } else if on_delete.is_none()
                    && self.parse_keywords(&[Keyword::ON, Keyword::DELETE])
                {
                    on_delete = Some(self.parse_referential_action()?);
                } else if on_update.is_none()
                    && self.parse_keywords(&[Keyword::ON, Keyword::UPDATE])
                {
                    on_update = Some(self.parse_referential_action()?);
                } else {
                    break;
                }
            }
            let characteristics = self.parse_constraint_characteristics()?;

            Ok(Some(
                ForeignKeyConstraint {
                    name: None,       // Column-level constraints don't have names
                    index_name: None, // Not applicable for column-level constraints
                    columns: vec![],  // Not applicable for column-level constraints
                    foreign_table,
                    referred_columns,
                    on_delete,
                    on_update,
                    match_kind,
                    characteristics,
                }
                .into(),
            ))
        } else if self.parse_keyword(Keyword::CHECK) {
            self.expect_token(&Token::LParen)?;
            // since `CHECK` requires parentheses, we can parse the inner expression in ParserState::Normal
            let expr: Expr = self.with_state(ParserState::Normal, |p| p.parse_expr())?;
            self.expect_token(&Token::RParen)?;
            let no_inherit = self.parse_keywords(&[Keyword::NO, Keyword::INHERIT]);

            let enforced = if self.parse_keyword(Keyword::ENFORCED) {
                Some(true)
            } else if self.parse_keywords(&[Keyword::NOT, Keyword::ENFORCED]) {
                Some(false)
            } else {
                None
            };

            Ok(Some(
                CheckConstraint {
                    name: None, // Column-level check constraints don't have names
                    expr: Box::new(expr),
                    no_inherit,
                    enforced,
                }
                .into(),
            ))
        } else if self.parse_keyword(Keyword::AUTO_INCREMENT)
            && dialect_of!(self is MySqlDialect | GenericDialect)
        {
            // Support AUTO_INCREMENT for MySQL
            Ok(Some(ColumnOption::DialectSpecific(vec![
                Token::make_keyword("AUTO_INCREMENT"),
            ])))
        } else if self.parse_keyword(Keyword::AUTOINCREMENT)
            && dialect_of!(self is SQLiteDialect |  GenericDialect)
        {
            // Support AUTOINCREMENT for SQLite
            Ok(Some(ColumnOption::DialectSpecific(vec![
                Token::make_keyword("AUTOINCREMENT"),
            ])))
        } else if self.parse_keyword(Keyword::ASC)
            && self.dialect.supports_asc_desc_in_column_definition()
        {
            // Support ASC for SQLite
            Ok(Some(ColumnOption::DialectSpecific(vec![
                Token::make_keyword("ASC"),
            ])))
        } else if self.parse_keyword(Keyword::DESC)
            && self.dialect.supports_asc_desc_in_column_definition()
        {
            // Support DESC for SQLite
            Ok(Some(ColumnOption::DialectSpecific(vec![
                Token::make_keyword("DESC"),
            ])))
        } else if self.parse_keywords(&[Keyword::ON, Keyword::UPDATE])
            && dialect_of!(self is MySqlDialect | GenericDialect)
        {
            let expr = self.parse_expr()?;
            Ok(Some(ColumnOption::OnUpdate(expr)))
        } else if self.parse_keyword(Keyword::GENERATED) {
            self.parse_optional_column_option_generated()
        } else if dialect_of!(self is BigQueryDialect | GenericDialect)
            && self.parse_keyword(Keyword::OPTIONS)
        {
            self.prev_token();
            Ok(Some(ColumnOption::Options(
                self.parse_options(Keyword::OPTIONS)?,
            )))
        } else if self.parse_keyword(Keyword::AS)
            && dialect_of!(self is MySqlDialect | SQLiteDialect | DuckDbDialect | GenericDialect)
        {
            self.parse_optional_column_option_as()
        } else if self.parse_keyword(Keyword::SRID)
            && dialect_of!(self is MySqlDialect | GenericDialect)
        {
            Ok(Some(ColumnOption::Srid(Box::new(self.parse_expr()?))))
        } else if self.parse_keyword(Keyword::IDENTITY)
            && dialect_of!(self is MsSqlDialect | GenericDialect)
        {
            let parameters = if self.consume_token(&Token::LParen) {
                let seed = self.parse_number()?;
                self.expect_token(&Token::Comma)?;
                let increment = self.parse_number()?;
                self.expect_token(&Token::RParen)?;

                Some(IdentityPropertyFormatKind::FunctionCall(
                    IdentityParameters { seed, increment },
                ))
            } else {
                None
            };
            Ok(Some(ColumnOption::Identity(
                IdentityPropertyKind::Identity(IdentityProperty {
                    parameters,
                    order: None,
                }),
            )))
        } else if dialect_of!(self is SQLiteDialect | GenericDialect)
            && self.parse_keywords(&[Keyword::ON, Keyword::CONFLICT])
        {
            // Support ON CONFLICT for SQLite
            Ok(Some(ColumnOption::OnConflict(
                self.expect_one_of_keywords(&[
                    Keyword::ROLLBACK,
                    Keyword::ABORT,
                    Keyword::FAIL,
                    Keyword::IGNORE,
                    Keyword::REPLACE,
                ])?,
            )))
        } else if self.parse_keyword(Keyword::INVISIBLE) {
            Ok(Some(ColumnOption::Invisible))
        } else {
            Ok(None)
        }
    }

    pub(crate) fn parse_tag(&mut self) -> Result<Tag, ParserError> {
        let name = self.parse_object_name(false)?;
        self.expect_token(&Token::Eq)?;
        let value = self.parse_literal_string()?;

        Ok(Tag::new(name, value))
    }

    fn parse_optional_column_option_generated(
        &mut self,
    ) -> Result<Option<ColumnOption>, ParserError> {
        if self.parse_keywords(&[Keyword::ALWAYS, Keyword::AS, Keyword::IDENTITY]) {
            let mut sequence_options = vec![];
            if self.expect_token(&Token::LParen).is_ok() {
                sequence_options = self.parse_create_sequence_options()?;
                self.expect_token(&Token::RParen)?;
            }
            Ok(Some(ColumnOption::Generated {
                generated_as: GeneratedAs::Always,
                sequence_options: Some(sequence_options),
                generation_expr: None,
                generation_expr_mode: None,
                generated_keyword: true,
            }))
        } else if self.parse_keywords(&[
            Keyword::BY,
            Keyword::DEFAULT,
            Keyword::AS,
            Keyword::IDENTITY,
        ]) {
            let mut sequence_options = vec![];
            if self.expect_token(&Token::LParen).is_ok() {
                sequence_options = self.parse_create_sequence_options()?;
                self.expect_token(&Token::RParen)?;
            }
            Ok(Some(ColumnOption::Generated {
                generated_as: GeneratedAs::ByDefault,
                sequence_options: Some(sequence_options),
                generation_expr: None,
                generation_expr_mode: None,
                generated_keyword: true,
            }))
        } else if self.parse_keywords(&[Keyword::ALWAYS, Keyword::AS]) {
            if self.expect_token(&Token::LParen).is_ok() {
                let expr: Expr = self.with_state(ParserState::Normal, |p| p.parse_expr())?;
                self.expect_token(&Token::RParen)?;
                let (gen_as, expr_mode) = if self.parse_keywords(&[Keyword::STORED]) {
                    Ok((
                        GeneratedAs::ExpStored,
                        Some(GeneratedExpressionMode::Stored),
                    ))
                } else if dialect_of!(self is PostgreSqlDialect) {
                    // Postgres' AS IDENTITY branches are above, this one needs STORED
                    self.expected_ref("STORED", self.peek_token_ref())
                } else if self.parse_keywords(&[Keyword::VIRTUAL]) {
                    Ok((GeneratedAs::Always, Some(GeneratedExpressionMode::Virtual)))
                } else {
                    Ok((GeneratedAs::Always, None))
                }?;

                Ok(Some(ColumnOption::Generated {
                    generated_as: gen_as,
                    sequence_options: None,
                    generation_expr: Some(expr),
                    generation_expr_mode: expr_mode,
                    generated_keyword: true,
                }))
            } else {
                Ok(None)
            }
        } else {
            Ok(None)
        }
    }

    fn parse_optional_column_option_as(&mut self) -> Result<Option<ColumnOption>, ParserError> {
        // Some DBs allow 'AS (expr)', shorthand for GENERATED ALWAYS AS
        self.expect_token(&Token::LParen)?;
        let expr = self.parse_expr()?;
        self.expect_token(&Token::RParen)?;

        let (gen_as, expr_mode) = if self.parse_keywords(&[Keyword::STORED]) {
            (
                GeneratedAs::ExpStored,
                Some(GeneratedExpressionMode::Stored),
            )
        } else if self.parse_keywords(&[Keyword::VIRTUAL]) {
            (GeneratedAs::Always, Some(GeneratedExpressionMode::Virtual))
        } else {
            (GeneratedAs::Always, None)
        };

        Ok(Some(ColumnOption::Generated {
            generated_as: gen_as,
            sequence_options: None,
            generation_expr: Some(expr),
            generation_expr_mode: expr_mode,
            generated_keyword: false,
        }))
    }

    /// Parse optional `CLUSTERED BY` clause for Hive/Generic dialects.
    pub fn parse_optional_clustered_by(&mut self) -> Result<Option<ClusteredBy>, ParserError> {
        let clustered_by = if dialect_of!(self is HiveDialect|GenericDialect)
            && self.parse_keywords(&[Keyword::CLUSTERED, Keyword::BY])
        {
            let columns = self.parse_parenthesized_column_list(Mandatory, false)?;

            let sorted_by = if self.parse_keywords(&[Keyword::SORTED, Keyword::BY]) {
                self.expect_token(&Token::LParen)?;
                let sorted_by_columns = self.parse_comma_separated(|p| p.parse_order_by_expr())?;
                self.expect_token(&Token::RParen)?;
                Some(sorted_by_columns)
            } else {
                None
            };

            self.expect_keyword_is(Keyword::INTO)?;
            let num_buckets = self.parse_number_value()?.value;
            self.expect_keyword_is(Keyword::BUCKETS)?;
            Some(ClusteredBy {
                columns,
                sorted_by,
                num_buckets,
            })
        } else {
            None
        };
        Ok(clustered_by)
    }

    /// Parse a referential action used in foreign key clauses.
    ///
    /// Recognized forms: `RESTRICT`, `CASCADE`, `SET NULL`, `NO ACTION`, `SET DEFAULT`.
    pub fn parse_referential_action(&mut self) -> Result<ReferentialAction, ParserError> {
        if self.parse_keyword(Keyword::RESTRICT) {
            Ok(ReferentialAction::Restrict)
        } else if self.parse_keyword(Keyword::CASCADE) {
            Ok(ReferentialAction::Cascade)
        } else if self.parse_keywords(&[Keyword::SET, Keyword::NULL]) {
            Ok(ReferentialAction::SetNull)
        } else if self.parse_keywords(&[Keyword::NO, Keyword::ACTION]) {
            Ok(ReferentialAction::NoAction)
        } else if self.parse_keywords(&[Keyword::SET, Keyword::DEFAULT]) {
            Ok(ReferentialAction::SetDefault)
        } else {
            self.expected_ref(
                "one of RESTRICT, CASCADE, SET NULL, NO ACTION or SET DEFAULT",
                self.peek_token_ref(),
            )
        }
    }

    /// Parse a `MATCH` kind for constraint references: `FULL`, `PARTIAL`, or `SIMPLE`.
    pub fn parse_match_kind(&mut self) -> Result<ConstraintReferenceMatchKind, ParserError> {
        if self.parse_keyword(Keyword::FULL) {
            Ok(ConstraintReferenceMatchKind::Full)
        } else if self.parse_keyword(Keyword::PARTIAL) {
            Ok(ConstraintReferenceMatchKind::Partial)
        } else if self.parse_keyword(Keyword::SIMPLE) {
            Ok(ConstraintReferenceMatchKind::Simple)
        } else {
            self.expected_ref("one of FULL, PARTIAL or SIMPLE", self.peek_token_ref())
        }
    }

    /// Parse `index_name [ DEFERRABLE | NOT DEFERRABLE ] [ INITIALLY DEFERRED | INITIALLY IMMEDIATE ]`
    /// after `{ PRIMARY KEY | UNIQUE } USING INDEX`.
    fn parse_constraint_using_index(
        &mut self,
        name: Option<Ident>,
    ) -> Result<ConstraintUsingIndex, ParserError> {
        let index_name = self.parse_identifier()?;
        let characteristics = self.parse_constraint_characteristics()?;
        Ok(ConstraintUsingIndex {
            name,
            index_name,
            characteristics,
        })
    }

    /// Parse optional constraint characteristics such as `DEFERRABLE`, `INITIALLY` and `ENFORCED`.
    pub fn parse_constraint_characteristics(
        &mut self,
    ) -> Result<Option<ConstraintCharacteristics>, ParserError> {
        let mut cc = ConstraintCharacteristics::default();

        loop {
            if cc.deferrable.is_none() && self.parse_keywords(&[Keyword::NOT, Keyword::DEFERRABLE])
            {
                cc.deferrable = Some(false);
            } else if cc.deferrable.is_none() && self.parse_keyword(Keyword::DEFERRABLE) {
                cc.deferrable = Some(true);
            } else if cc.initially.is_none() && self.parse_keyword(Keyword::INITIALLY) {
                if self.parse_keyword(Keyword::DEFERRED) {
                    cc.initially = Some(DeferrableInitial::Deferred);
                } else if self.parse_keyword(Keyword::IMMEDIATE) {
                    cc.initially = Some(DeferrableInitial::Immediate);
                } else {
                    self.expected_ref("one of DEFERRED or IMMEDIATE", self.peek_token_ref())?;
                }
            } else if cc.enforced.is_none() && self.parse_keyword(Keyword::ENFORCED) {
                cc.enforced = Some(true);
            } else if cc.enforced.is_none()
                && self.parse_keywords(&[Keyword::NOT, Keyword::ENFORCED])
            {
                cc.enforced = Some(false);
            } else {
                break;
            }
        }

        if cc.deferrable.is_some() || cc.initially.is_some() || cc.enforced.is_some() {
            Ok(Some(cc))
        } else {
            Ok(None)
        }
    }

    /// Parse an optional table constraint (e.g. `PRIMARY KEY`, `UNIQUE`, `FOREIGN KEY`, `CHECK`).
    pub fn parse_optional_table_constraint(
        &mut self,
    ) -> Result<Option<TableConstraint>, ParserError> {
        let name = if self.parse_keyword(Keyword::CONSTRAINT) {
            if self.dialect.supports_constraint_keyword_without_name()
                && self
                    .peek_one_of_keywords(&[
                        Keyword::CHECK,
                        Keyword::PRIMARY,
                        Keyword::UNIQUE,
                        Keyword::FOREIGN,
                    ])
                    .is_some()
            {
                None
            } else {
                Some(self.parse_identifier()?)
            }
        } else {
            None
        };

        let next_token = self.next_token();
        match next_token.token {
            Token::Word(w) if w.keyword == Keyword::UNIQUE => {
                // PostgreSQL: UNIQUE USING INDEX index_name
                // https://www.postgresql.org/docs/current/sql-altertable.html
                if self.parse_keywords(&[Keyword::USING, Keyword::INDEX]) {
                    return Ok(Some(TableConstraint::UniqueUsingIndex(
                        self.parse_constraint_using_index(name)?,
                    )));
                }

                let index_type_display = self.parse_index_type_display();
                if !dialect_of!(self is GenericDialect | MySqlDialect)
                    && !index_type_display.is_none()
                {
                    return self.expected_ref(
                        "`index_name` or `(column_name [, ...])`",
                        self.peek_token_ref(),
                    );
                }

                let nulls_distinct = self.parse_optional_nulls_distinct()?;

                // optional index name
                let index_name = self.parse_optional_ident()?;
                let index_type = self.parse_optional_using_then_index_type()?;

                let columns = self.parse_parenthesized_index_column_list()?;
                let include = self.parse_optional_include_columns()?;
                let index_options = self.parse_index_options()?;
                let characteristics = self.parse_constraint_characteristics()?;
                Ok(Some(
                    UniqueConstraint {
                        name,
                        index_name,
                        index_type_display,
                        index_type,
                        columns,
                        include,
                        index_options,
                        characteristics,
                        nulls_distinct,
                    }
                    .into(),
                ))
            }
            Token::Word(w) if w.keyword == Keyword::PRIMARY => {
                // after `PRIMARY` always stay `KEY`
                self.expect_keyword_is(Keyword::KEY)?;

                // PostgreSQL: PRIMARY KEY USING INDEX index_name
                // https://www.postgresql.org/docs/current/sql-altertable.html
                if self.parse_keywords(&[Keyword::USING, Keyword::INDEX]) {
                    return Ok(Some(TableConstraint::PrimaryKeyUsingIndex(
                        self.parse_constraint_using_index(name)?,
                    )));
                }

                // optional index name
                let index_name = self.parse_optional_ident()?;
                let index_type = self.parse_optional_using_then_index_type()?;

                let columns = self.parse_parenthesized_index_column_list()?;
                let include = self.parse_optional_include_columns()?;
                let index_options = self.parse_index_options()?;
                let characteristics = self.parse_constraint_characteristics()?;
                Ok(Some(
                    PrimaryKeyConstraint {
                        name,
                        index_name,
                        index_type,
                        columns,
                        include,
                        index_options,
                        characteristics,
                    }
                    .into(),
                ))
            }
            Token::Word(w) if w.keyword == Keyword::FOREIGN => {
                self.expect_keyword_is(Keyword::KEY)?;
                let index_name = self.parse_optional_ident()?;
                let columns = self.parse_parenthesized_column_list(Mandatory, false)?;
                self.expect_keyword_is(Keyword::REFERENCES)?;
                let foreign_table = self.parse_object_name(false)?;
                let referred_columns = self.parse_parenthesized_column_list(Optional, false)?;
                let mut match_kind = None;
                let mut on_delete = None;
                let mut on_update = None;
                loop {
                    if match_kind.is_none() && self.parse_keyword(Keyword::MATCH) {
                        match_kind = Some(self.parse_match_kind()?);
                    } else if on_delete.is_none()
                        && self.parse_keywords(&[Keyword::ON, Keyword::DELETE])
                    {
                        on_delete = Some(self.parse_referential_action()?);
                    } else if on_update.is_none()
                        && self.parse_keywords(&[Keyword::ON, Keyword::UPDATE])
                    {
                        on_update = Some(self.parse_referential_action()?);
                    } else {
                        break;
                    }
                }

                let characteristics = self.parse_constraint_characteristics()?;

                Ok(Some(
                    ForeignKeyConstraint {
                        name,
                        index_name,
                        columns,
                        foreign_table,
                        referred_columns,
                        on_delete,
                        on_update,
                        match_kind,
                        characteristics,
                    }
                    .into(),
                ))
            }
            Token::Word(w) if w.keyword == Keyword::CHECK => {
                self.expect_token(&Token::LParen)?;
                let expr = Box::new(self.parse_expr()?);
                self.expect_token(&Token::RParen)?;
                let no_inherit = self.parse_keywords(&[Keyword::NO, Keyword::INHERIT]);

                let enforced = if self.parse_keyword(Keyword::ENFORCED) {
                    Some(true)
                } else if self.parse_keywords(&[Keyword::NOT, Keyword::ENFORCED]) {
                    Some(false)
                } else {
                    None
                };

                Ok(Some(
                    CheckConstraint {
                        name,
                        expr,
                        no_inherit,
                        enforced,
                    }
                    .into(),
                ))
            }
            Token::Word(w)
                if (w.keyword == Keyword::INDEX || w.keyword == Keyword::KEY)
                    && dialect_of!(self is GenericDialect | MySqlDialect)
                    && name.is_none() =>
            {
                let display_as_key = w.keyword == Keyword::KEY;

                let name = match &self.peek_token_ref().token {
                    Token::Word(word) if word.keyword == Keyword::USING => None,
                    _ => self.parse_optional_ident()?,
                };

                let index_type = self.parse_optional_using_then_index_type()?;
                let columns = self.parse_parenthesized_index_column_list()?;
                let index_options = self.parse_index_options()?;

                Ok(Some(
                    IndexConstraint {
                        display_as_key,
                        name,
                        index_type,
                        columns,
                        index_options,
                    }
                    .into(),
                ))
            }
            Token::Word(w)
                if (w.keyword == Keyword::FULLTEXT || w.keyword == Keyword::SPATIAL)
                    && dialect_of!(self is GenericDialect | MySqlDialect) =>
            {
                if let Some(name) = name {
                    return self.expected(
                        "FULLTEXT or SPATIAL option without constraint name",
                        TokenWithSpan {
                            token: Token::make_keyword(&name.to_string()),
                            span: next_token.span,
                        },
                    );
                }

                let fulltext = w.keyword == Keyword::FULLTEXT;

                let index_type_display = self.parse_index_type_display();

                let opt_index_name = self.parse_optional_ident()?;

                let columns = self.parse_parenthesized_index_column_list()?;

                Ok(Some(
                    FullTextOrSpatialConstraint {
                        fulltext,
                        index_type_display,
                        opt_index_name,
                        columns,
                    }
                    .into(),
                ))
            }
            Token::Word(w)
                if w.keyword == Keyword::EXCLUDE && self.dialect.supports_exclude_constraint() =>
            {
                // `EXCLUDE` is a non-reserved keyword in PostgreSQL, so it is a
                // valid column name. Only treat it as an exclusion constraint
                // when it begins one (named, or followed by `USING` / `(`);
                // otherwise backtrack and let it parse as a column.
                if name.is_some()
                    || self.peek_keyword(Keyword::USING)
                    || self.peek_token_ref().token == Token::LParen
                {
                    Ok(Some(self.parse_exclude_constraint(name)?.into()))
                } else {
                    self.prev_token();
                    Ok(None)
                }
            }
            _ => {
                if name.is_some() {
                    self.expected("PRIMARY, UNIQUE, FOREIGN, CHECK, or EXCLUDE", next_token)
                } else {
                    self.prev_token();
                    Ok(None)
                }
            }
        }
    }

    // The leading `EXCLUDE` keyword is already consumed by the caller.
    fn parse_exclude_constraint(
        &mut self,
        name: Option<Ident>,
    ) -> Result<ExcludeConstraint, ParserError> {
        let index_method = if self.parse_keyword(Keyword::USING) {
            Some(self.parse_identifier()?)
        } else {
            None
        };

        self.expect_token(&Token::LParen)?;
        let elements = self.parse_comma_separated(|p| p.parse_exclude_constraint_element())?;
        self.expect_token(&Token::RParen)?;

        let include = if self.parse_keyword(Keyword::INCLUDE) {
            self.expect_token(&Token::LParen)?;
            let cols = self.parse_comma_separated(|p| p.parse_identifier())?;
            self.expect_token(&Token::RParen)?;
            cols
        } else {
            vec![]
        };

        let where_clause = if self.parse_keyword(Keyword::WHERE) {
            self.expect_token(&Token::LParen)?;
            let predicate = self.parse_expr()?;
            self.expect_token(&Token::RParen)?;
            Some(Box::new(predicate))
        } else {
            None
        };

        let characteristics = self.parse_constraint_characteristics()?;

        Ok(ExcludeConstraint {
            name,
            index_method,
            elements,
            include,
            where_clause,
            characteristics,
        })
    }

    fn parse_exclude_constraint_element(
        &mut self,
    ) -> Result<ExcludeConstraintElement, ParserError> {
        let column = self.parse_create_index_expr()?;
        self.expect_keyword_is(Keyword::WITH)?;
        let operator = self.parse_exclude_constraint_operator()?;
        Ok(ExcludeConstraintElement { column, operator })
    }

    /// Parse the operator that follows `WITH` in an `EXCLUDE` element.
    fn parse_exclude_constraint_operator(
        &mut self,
    ) -> Result<ExcludeConstraintOperator, ParserError> {
        if self.parse_keyword(Keyword::OPERATOR) {
            return Ok(ExcludeConstraintOperator::PGOperator(
                self.parse_pg_operator_ident_parts()?,
            ));
        }

        let operator_token = self.next_token();
        Ok(ExcludeConstraintOperator::Token(
            operator_token.token.to_string(),
        ))
    }

    /// Parse the body of a Postgres `OPERATOR(schema.op)` form: the
    /// parenthesized `.`-separated path of name parts after the `OPERATOR`
    /// keyword. Shared between binary expression parsing and exclusion
    /// constraint parsing.
    fn parse_pg_operator_ident_parts(&mut self) -> Result<Vec<String>, ParserError> {
        self.expect_token(&Token::LParen)?;
        if self.peek_token_ref().token == Token::RParen {
            let token = self.next_token();
            return self.expected("operator name", token);
        }
        let mut idents = vec![];
        loop {
            self.advance_token();
            idents.push(self.get_current_token().to_string());
            if !self.consume_token(&Token::Period) {
                break;
            }
        }
        self.expect_token(&Token::RParen)?;
        Ok(idents)
    }

    fn parse_optional_nulls_distinct(&mut self) -> Result<NullsDistinctOption, ParserError> {
        Ok(if self.parse_keyword(Keyword::NULLS) {
            let not = self.parse_keyword(Keyword::NOT);
            self.expect_keyword_is(Keyword::DISTINCT)?;
            if not {
                NullsDistinctOption::NotDistinct
            } else {
                NullsDistinctOption::Distinct
            }
        } else {
            NullsDistinctOption::None
        })
    }

    /// Optionally parse a parenthesized list of `SqlOption`s introduced by `keyword`.
    pub fn maybe_parse_options(
        &mut self,
        keyword: Keyword,
    ) -> Result<Option<Vec<SqlOption>>, ParserError> {
        if let Token::Word(word) = &self.peek_token_ref().token {
            if word.keyword == keyword {
                return Ok(Some(self.parse_options(keyword)?));
            }
        };
        Ok(None)
    }

    /// Parse a parenthesized list of `SqlOption`s following `keyword`, or return an empty vec.
    pub fn parse_options(&mut self, keyword: Keyword) -> Result<Vec<SqlOption>, ParserError> {
        if self.parse_keyword(keyword) {
            self.expect_token(&Token::LParen)?;
            let options = self.parse_comma_separated0(Parser::parse_sql_option, Token::RParen)?;
            self.expect_token(&Token::RParen)?;
            Ok(options)
        } else {
            Ok(vec![])
        }
    }

    /// Parse options introduced by one of `keywords` followed by a parenthesized list.
    pub fn parse_options_with_keywords(
        &mut self,
        keywords: &[Keyword],
    ) -> Result<Vec<SqlOption>, ParserError> {
        if self.parse_keywords(keywords) {
            self.expect_token(&Token::LParen)?;
            let options = self.parse_comma_separated(Parser::parse_sql_option)?;
            self.expect_token(&Token::RParen)?;
            Ok(options)
        } else {
            Ok(vec![])
        }
    }

    /// Parse an index type token (e.g. `BTREE`, `HASH`, or a custom identifier).
    pub fn parse_index_type(&mut self) -> Result<IndexType, ParserError> {
        Ok(if self.parse_keyword(Keyword::BTREE) {
            IndexType::BTree
        } else if self.parse_keyword(Keyword::HASH) {
            IndexType::Hash
        } else if self.parse_keyword(Keyword::GIN) {
            IndexType::GIN
        } else if self.parse_keyword(Keyword::GIST) {
            IndexType::GiST
        } else if self.parse_keyword(Keyword::SPGIST) {
            IndexType::SPGiST
        } else if self.parse_keyword(Keyword::BRIN) {
            IndexType::BRIN
        } else if self.parse_keyword(Keyword::BLOOM) {
            IndexType::Bloom
        } else {
            IndexType::Custom(self.parse_identifier()?)
        })
    }

    /// Optionally parse the `USING` keyword, followed by an [IndexType]
    /// Example:
    /// ```sql
    //// USING BTREE (name, age DESC)
    /// ```
    /// Optionally parse `USING <index_type>` and return the parsed `IndexType` if present.
    pub fn parse_optional_using_then_index_type(
        &mut self,
    ) -> Result<Option<IndexType>, ParserError> {
        if self.parse_keyword(Keyword::USING) {
            Ok(Some(self.parse_index_type()?))
        } else {
            Ok(None)
        }
    }

    /// Parse `[ident]`, mostly `ident` is name, like:
    /// `window_name`, `index_name`, ...
    /// Parse an optional identifier, returning `Some(Ident)` if present.
    pub fn parse_optional_ident(&mut self) -> Result<Option<Ident>, ParserError> {
        self.maybe_parse(|parser| parser.parse_identifier())
    }

    #[must_use]
    /// Parse optional `KEY` or `INDEX` display tokens used in index/constraint declarations.
    pub fn parse_index_type_display(&mut self) -> KeyOrIndexDisplay {
        if self.parse_keyword(Keyword::KEY) {
            KeyOrIndexDisplay::Key
        } else if self.parse_keyword(Keyword::INDEX) {
            KeyOrIndexDisplay::Index
        } else {
            KeyOrIndexDisplay::None
        }
    }

    /// Parse an optional index option such as `USING <type>` or `COMMENT <string>`.
    pub fn parse_optional_index_option(&mut self) -> Result<Option<IndexOption>, ParserError> {
        if let Some(index_type) = self.parse_optional_using_then_index_type()? {
            Ok(Some(IndexOption::Using(index_type)))
        } else if self.parse_keyword(Keyword::COMMENT) {
            let s = self.parse_literal_string()?;
            Ok(Some(IndexOption::Comment(s)))
        } else {
            Ok(None)
        }
    }

    /// Parse zero or more index options and return them as a vector.
    pub fn parse_index_options(&mut self) -> Result<Vec<IndexOption>, ParserError> {
        let mut options = Vec::new();

        loop {
            match self.parse_optional_index_option()? {
                Some(index_option) => options.push(index_option),
                None => return Ok(options),
            }
        }
    }

    /// Parse an optional `INCLUDE (col, ...)` clause on a table constraint.
    pub fn parse_optional_include_columns(&mut self) -> Result<Vec<Ident>, ParserError> {
        if self.parse_keyword(Keyword::INCLUDE) {
            self.expect_token(&Token::LParen)?;
            let columns = self.parse_comma_separated(|p| p.parse_identifier())?;
            self.expect_token(&Token::RParen)?;
            Ok(columns)
        } else {
            Ok(vec![])
        }
    }

    /// Parse a single `SqlOption` used by various dialect-specific DDL statements.
    pub fn parse_sql_option(&mut self) -> Result<SqlOption, ParserError> {
        let is_mssql = dialect_of!(self is MsSqlDialect|GenericDialect);

        match &self.peek_token_ref().token {
            Token::Word(w) if w.keyword == Keyword::HEAP && is_mssql => {
                Ok(SqlOption::Ident(self.parse_identifier()?))
            }
            Token::Word(w) if w.keyword == Keyword::PARTITION && is_mssql => {
                self.parse_option_partition()
            }
            Token::Word(w) if w.keyword == Keyword::CLUSTERED && is_mssql => {
                self.parse_option_clustered()
            }
            _ => {
                let name = self.parse_identifier()?;
                self.expect_token(&Token::Eq)?;
                let value = self.parse_expr()?;

                Ok(SqlOption::KeyValue { key: name, value })
            }
        }
    }

    /// Parse a `CLUSTERED` table option (MSSQL-specific syntaxes supported).
    pub fn parse_option_clustered(&mut self) -> Result<SqlOption, ParserError> {
        if self.parse_keywords(&[
            Keyword::CLUSTERED,
            Keyword::COLUMNSTORE,
            Keyword::INDEX,
            Keyword::ORDER,
        ]) {
            Ok(SqlOption::Clustered(
                TableOptionsClustered::ColumnstoreIndexOrder(
                    self.parse_parenthesized_column_list(IsOptional::Mandatory, false)?,
                ),
            ))
        } else if self.parse_keywords(&[Keyword::CLUSTERED, Keyword::COLUMNSTORE, Keyword::INDEX]) {
            Ok(SqlOption::Clustered(
                TableOptionsClustered::ColumnstoreIndex,
            ))
        } else if self.parse_keywords(&[Keyword::CLUSTERED, Keyword::INDEX]) {
            self.expect_token(&Token::LParen)?;

            let columns = self.parse_comma_separated(|p| {
                let name = p.parse_identifier()?;
                let asc = p.parse_asc_desc();

                Ok(ClusteredIndex { name, asc })
            })?;

            self.expect_token(&Token::RParen)?;

            Ok(SqlOption::Clustered(TableOptionsClustered::Index(columns)))
        } else {
            Err(ParserError::ParserError(
                "invalid CLUSTERED sequence".to_string(),
            ))
        }
    }

    /// Parse a `PARTITION(...) FOR VALUES(...)` table option.
    pub fn parse_option_partition(&mut self) -> Result<SqlOption, ParserError> {
        self.expect_keyword_is(Keyword::PARTITION)?;
        self.expect_token(&Token::LParen)?;
        let column_name = self.parse_identifier()?;

        self.expect_keyword_is(Keyword::RANGE)?;
        let range_direction = if self.parse_keyword(Keyword::LEFT) {
            Some(PartitionRangeDirection::Left)
        } else if self.parse_keyword(Keyword::RIGHT) {
            Some(PartitionRangeDirection::Right)
        } else {
            None
        };

        self.expect_keywords(&[Keyword::FOR, Keyword::VALUES])?;
        self.expect_token(&Token::LParen)?;

        let for_values = self.parse_comma_separated(Parser::parse_expr)?;

        self.expect_token(&Token::RParen)?;
        self.expect_token(&Token::RParen)?;

        Ok(SqlOption::Partition {
            column_name,
            range_direction,
            for_values,
        })
    }

    /// Parse a parenthesized list of partition expressions and return a `Partition` value.
    pub fn parse_partition(&mut self) -> Result<Partition, ParserError> {
        self.expect_token(&Token::LParen)?;
        let partitions = self.parse_comma_separated(Parser::parse_expr)?;
        self.expect_token(&Token::RParen)?;
        Ok(Partition::Partitions(partitions))
    }

    /// Parse a parenthesized `SELECT` projection used for projection-based operations.
    pub fn parse_projection_select(&mut self) -> Result<ProjectionSelect, ParserError> {
        self.expect_token(&Token::LParen)?;
        self.expect_keyword_is(Keyword::SELECT)?;
        let projection = self.parse_projection()?;
        let group_by = self.parse_optional_group_by()?;
        let order_by = self.parse_optional_order_by()?;
        self.expect_token(&Token::RParen)?;
        Ok(ProjectionSelect {
            projection,
            group_by,
            order_by,
        })
    }
    /// Parse `ALTER TABLE ... ADD PROJECTION ...` operation.
    pub fn parse_alter_table_add_projection(&mut self) -> Result<AlterTableOperation, ParserError> {
        let if_not_exists = self.parse_keywords(&[Keyword::IF, Keyword::NOT, Keyword::EXISTS]);
        let name = self.parse_identifier()?;
        let query = self.parse_projection_select()?;
        Ok(AlterTableOperation::AddProjection {
            if_not_exists,
            name,
            select: query,
        })
    }

    /// Parse Redshift `ALTER SORTKEY (column_list)`.
    ///
    /// See <https://docs.aws.amazon.com/redshift/latest/dg/r_ALTER_TABLE.html>
    fn parse_alter_sort_key(&mut self) -> Result<AlterTableOperation, ParserError> {
        self.expect_keyword_is(Keyword::ALTER)?;
        self.expect_keyword_is(Keyword::SORTKEY)?;
        self.expect_token(&Token::LParen)?;
        let columns = self.parse_comma_separated(|p| p.parse_expr())?;
        self.expect_token(&Token::RParen)?;
        Ok(AlterTableOperation::AlterSortKey { columns })
    }

    /// Parse the expression(s) following ClickHouse `ORDER BY`: either a single
    /// expression or a possibly empty parenthesized list.
    fn parse_sorting_key(&mut self) -> Result<OneOrManyWithParens<Expr>, ParserError> {
        if self.consume_token(&Token::LParen) {
            let columns = if self.peek_token_ref().token != Token::RParen {
                self.parse_comma_separated(|p| p.parse_expr())?
            } else {
                vec![]
            };
            self.expect_token(&Token::RParen)?;
            Ok(OneOrManyWithParens::Many(columns))
        } else {
            Ok(OneOrManyWithParens::One(self.parse_expr()?))
        }
    }

    /// Parse a single `ALTER TABLE` operation and return an `AlterTableOperation`.
    pub fn parse_alter_table_operation(&mut self) -> Result<AlterTableOperation, ParserError> {
        let operation = if self.parse_keyword(Keyword::ADD) {
            if let Some(constraint) = self.parse_optional_table_constraint()? {
                let not_valid = self.parse_keywords(&[Keyword::NOT, Keyword::VALID]);
                AlterTableOperation::AddConstraint {
                    constraint,
                    not_valid,
                }
            } else if dialect_of!(self is ClickHouseDialect|GenericDialect)
                && self.parse_keyword(Keyword::PROJECTION)
            {
                return self.parse_alter_table_add_projection();
            } else {
                let if_not_exists =
                    self.parse_keywords(&[Keyword::IF, Keyword::NOT, Keyword::EXISTS]);
                let mut new_partitions = vec![];
                loop {
                    if self.parse_keyword(Keyword::PARTITION) {
                        new_partitions.push(self.parse_partition()?);
                    } else {
                        break;
                    }
                }
                if !new_partitions.is_empty() {
                    AlterTableOperation::AddPartitions {
                        if_not_exists,
                        new_partitions,
                    }
                } else {
                    let column_keyword = self.parse_keyword(Keyword::COLUMN);

                    let if_not_exists = if dialect_of!(self is PostgreSqlDialect | BigQueryDialect | DuckDbDialect | GenericDialect)
                    {
                        self.parse_keywords(&[Keyword::IF, Keyword::NOT, Keyword::EXISTS])
                            || if_not_exists
                    } else {
                        false
                    };

                    let column_def = self.parse_column_def()?;

                    let column_position = self.parse_column_position()?;

                    AlterTableOperation::AddColumn {
                        column_keyword,
                        if_not_exists,
                        column_def,
                        column_position,
                    }
                }
            }
        } else if self.parse_keyword(Keyword::RENAME) {
            if dialect_of!(self is PostgreSqlDialect) && self.parse_keyword(Keyword::CONSTRAINT) {
                let old_name = self.parse_identifier()?;
                self.expect_keyword_is(Keyword::TO)?;
                let new_name = self.parse_identifier()?;
                AlterTableOperation::RenameConstraint { old_name, new_name }
            } else if self.parse_keyword(Keyword::TO) {
                let table_name = self.parse_object_name(false)?;
                AlterTableOperation::RenameTable {
                    table_name: RenameTableNameKind::To(table_name),
                }
            } else if self.parse_keyword(Keyword::AS) {
                let table_name = self.parse_object_name(false)?;
                AlterTableOperation::RenameTable {
                    table_name: RenameTableNameKind::As(table_name),
                }
            } else {
                let _ = self.parse_keyword(Keyword::COLUMN); // [ COLUMN ]
                let old_column_name = self.parse_identifier()?;
                self.expect_keyword_is(Keyword::TO)?;
                let new_column_name = self.parse_identifier()?;
                AlterTableOperation::RenameColumn {
                    old_column_name,
                    new_column_name,
                }
            }
        } else if self.parse_keyword(Keyword::DISABLE) {
            if self.parse_keywords(&[Keyword::ROW, Keyword::LEVEL, Keyword::SECURITY]) {
                AlterTableOperation::DisableRowLevelSecurity {}
            } else if self.parse_keyword(Keyword::RULE) {
                let name = self.parse_identifier()?;
                AlterTableOperation::DisableRule { name }
            } else if self.parse_keyword(Keyword::TRIGGER) {
                let name = self.parse_identifier()?;
                AlterTableOperation::DisableTrigger { name }
            } else {
                return self.expected_ref(
                    "ROW LEVEL SECURITY, RULE, or TRIGGER after DISABLE",
                    self.peek_token_ref(),
                );
            }
        } else if self.parse_keyword(Keyword::ENABLE) {
            if self.parse_keywords(&[Keyword::ALWAYS, Keyword::RULE]) {
                let name = self.parse_identifier()?;
                AlterTableOperation::EnableAlwaysRule { name }
            } else if self.parse_keywords(&[Keyword::ALWAYS, Keyword::TRIGGER]) {
                let name = self.parse_identifier()?;
                AlterTableOperation::EnableAlwaysTrigger { name }
            } else if self.parse_keywords(&[Keyword::ROW, Keyword::LEVEL, Keyword::SECURITY]) {
                AlterTableOperation::EnableRowLevelSecurity {}
            } else if self.parse_keywords(&[Keyword::REPLICA, Keyword::RULE]) {
                let name = self.parse_identifier()?;
                AlterTableOperation::EnableReplicaRule { name }
            } else if self.parse_keywords(&[Keyword::REPLICA, Keyword::TRIGGER]) {
                let name = self.parse_identifier()?;
                AlterTableOperation::EnableReplicaTrigger { name }
            } else if self.parse_keyword(Keyword::RULE) {
                let name = self.parse_identifier()?;
                AlterTableOperation::EnableRule { name }
            } else if self.parse_keyword(Keyword::TRIGGER) {
                let name = self.parse_identifier()?;
                AlterTableOperation::EnableTrigger { name }
            } else {
                return self.expected_ref(
                    "ALWAYS, REPLICA, ROW LEVEL SECURITY, RULE, or TRIGGER after ENABLE",
                    self.peek_token_ref(),
                );
            }
        } else if self.parse_keywords(&[
            Keyword::FORCE,
            Keyword::ROW,
            Keyword::LEVEL,
            Keyword::SECURITY,
        ]) {
            AlterTableOperation::ForceRowLevelSecurity
        } else if self.parse_keywords(&[
            Keyword::NO,
            Keyword::FORCE,
            Keyword::ROW,
            Keyword::LEVEL,
            Keyword::SECURITY,
        ]) {
            AlterTableOperation::NoForceRowLevelSecurity
        } else if self.parse_keywords(&[Keyword::CLEAR, Keyword::PROJECTION])
            && dialect_of!(self is ClickHouseDialect|GenericDialect)
        {
            let if_exists = self.parse_keywords(&[Keyword::IF, Keyword::EXISTS]);
            let name = self.parse_identifier()?;
            let partition = if self.parse_keywords(&[Keyword::IN, Keyword::PARTITION]) {
                Some(self.parse_identifier()?)
            } else {
                None
            };
            AlterTableOperation::ClearProjection {
                if_exists,
                name,
                partition,
            }
        } else if self.parse_keywords(&[Keyword::MATERIALIZE, Keyword::PROJECTION])
            && dialect_of!(self is ClickHouseDialect|GenericDialect)
        {
            let if_exists = self.parse_keywords(&[Keyword::IF, Keyword::EXISTS]);
            let name = self.parse_identifier()?;
            let partition = if self.parse_keywords(&[Keyword::IN, Keyword::PARTITION]) {
                Some(self.parse_identifier()?)
            } else {
                None
            };
            AlterTableOperation::MaterializeProjection {
                if_exists,
                name,
                partition,
            }
        } else if self.parse_keyword(Keyword::DROP) {
            if self.parse_keywords(&[Keyword::IF, Keyword::EXISTS, Keyword::PARTITION]) {
                self.expect_token(&Token::LParen)?;
                let partitions = self.parse_comma_separated(Parser::parse_expr)?;
                self.expect_token(&Token::RParen)?;
                AlterTableOperation::DropPartitions {
                    partitions,
                    if_exists: true,
                }
            } else if self.parse_keyword(Keyword::PARTITION) {
                self.expect_token(&Token::LParen)?;
                let partitions = self.parse_comma_separated(Parser::parse_expr)?;
                self.expect_token(&Token::RParen)?;
                AlterTableOperation::DropPartitions {
                    partitions,
                    if_exists: false,
                }
            } else if self.parse_keyword(Keyword::CONSTRAINT) {
                let if_exists = self.parse_keywords(&[Keyword::IF, Keyword::EXISTS]);
                let name = self.parse_identifier()?;
                let drop_behavior = self.parse_optional_drop_behavior();
                AlterTableOperation::DropConstraint {
                    if_exists,
                    name,
                    drop_behavior,
                }
            } else if self.parse_keywords(&[Keyword::PRIMARY, Keyword::KEY]) {
                let drop_behavior = self.parse_optional_drop_behavior();
                AlterTableOperation::DropPrimaryKey { drop_behavior }
            } else if self.parse_keywords(&[Keyword::FOREIGN, Keyword::KEY]) {
                let name = self.parse_identifier()?;
                let drop_behavior = self.parse_optional_drop_behavior();
                AlterTableOperation::DropForeignKey {
                    name,
                    drop_behavior,
                }
            } else if self.parse_keyword(Keyword::INDEX) {
                let name = self.parse_identifier()?;
                AlterTableOperation::DropIndex { name }
            } else if self.parse_keyword(Keyword::PROJECTION)
                && dialect_of!(self is ClickHouseDialect|GenericDialect)
            {
                let if_exists = self.parse_keywords(&[Keyword::IF, Keyword::EXISTS]);
                let name = self.parse_identifier()?;
                AlterTableOperation::DropProjection { if_exists, name }
            } else if self.parse_keywords(&[Keyword::CLUSTERING, Keyword::KEY]) {
                AlterTableOperation::DropClusteringKey
            } else {
                let has_column_keyword = self.parse_keyword(Keyword::COLUMN); // [ COLUMN ]
                let if_exists = self.parse_keywords(&[Keyword::IF, Keyword::EXISTS]);
                let column_names = if self.dialect.supports_comma_separated_drop_column_list() {
                    self.parse_comma_separated(Parser::parse_identifier)?
                } else {
                    vec![self.parse_identifier()?]
                };
                let drop_behavior = self.parse_optional_drop_behavior();
                AlterTableOperation::DropColumn {
                    has_column_keyword,
                    column_names,
                    if_exists,
                    drop_behavior,
                }
            }
        } else if self.parse_keyword(Keyword::PARTITION) {
            self.expect_token(&Token::LParen)?;
            let before = self.parse_comma_separated(Parser::parse_expr)?;
            self.expect_token(&Token::RParen)?;
            self.expect_keyword_is(Keyword::RENAME)?;
            self.expect_keywords(&[Keyword::TO, Keyword::PARTITION])?;
            self.expect_token(&Token::LParen)?;
            let renames = self.parse_comma_separated(Parser::parse_expr)?;
            self.expect_token(&Token::RParen)?;
            AlterTableOperation::RenamePartitions {
                old_partitions: before,
                new_partitions: renames,
            }
        } else if self.parse_keyword(Keyword::CHANGE) {
            let _ = self.parse_keyword(Keyword::COLUMN); // [ COLUMN ]
            let old_name = self.parse_identifier()?;
            let new_name = self.parse_identifier()?;
            let data_type = self.parse_data_type()?;
            let mut options = vec![];
            while let Some(option) = self.parse_optional_column_option()? {
                options.push(option);
            }

            let column_position = self.parse_column_position()?;

            AlterTableOperation::ChangeColumn {
                old_name,
                new_name,
                data_type,
                options,
                column_position,
            }
        } else if self.parse_keywords(&[Keyword::MODIFY, Keyword::ORDER, Keyword::BY]) {
            AlterTableOperation::ModifyOrderBy {
                order_by: self.parse_sorting_key()?,
            }
        } else if self.parse_keyword(Keyword::MODIFY) {
            let _ = self.parse_keyword(Keyword::COLUMN); // [ COLUMN ]
            let col_name = self.parse_identifier()?;
            let data_type = self.parse_data_type()?;
            let mut options = vec![];
            while let Some(option) = self.parse_optional_column_option()? {
                options.push(option);
            }

            let column_position = self.parse_column_position()?;

            AlterTableOperation::ModifyColumn {
                col_name,
                data_type,
                options,
                column_position,
            }
        } else if self.parse_keyword(Keyword::ALTER) {
            if self.peek_keyword(Keyword::SORTKEY) {
                self.prev_token();
                return self.parse_alter_sort_key();
            }

            let _ = self.parse_keyword(Keyword::COLUMN); // [ COLUMN ]
            let column_name = self.parse_identifier()?;
            let is_postgresql = dialect_of!(self is PostgreSqlDialect);

            let op: AlterColumnOperation = if self.parse_keywords(&[
                Keyword::SET,
                Keyword::NOT,
                Keyword::NULL,
            ]) {
                AlterColumnOperation::SetNotNull {}
            } else if self.parse_keywords(&[Keyword::DROP, Keyword::NOT, Keyword::NULL]) {
                AlterColumnOperation::DropNotNull {}
            } else if self.parse_keywords(&[Keyword::SET, Keyword::DEFAULT]) {
                AlterColumnOperation::SetDefault {
                    value: self.parse_expr()?,
                }
            } else if self.parse_keywords(&[Keyword::DROP, Keyword::DEFAULT]) {
                AlterColumnOperation::DropDefault {}
            } else if self.parse_keywords(&[Keyword::SET, Keyword::DATA, Keyword::TYPE]) {
                self.parse_set_data_type(true)?
            } else if self.parse_keyword(Keyword::TYPE) {
                self.parse_set_data_type(false)?
            } else if self.parse_keywords(&[Keyword::ADD, Keyword::GENERATED]) {
                let generated_as = if self.parse_keyword(Keyword::ALWAYS) {
                    Some(GeneratedAs::Always)
                } else if self.parse_keywords(&[Keyword::BY, Keyword::DEFAULT]) {
                    Some(GeneratedAs::ByDefault)
                } else {
                    None
                };

                self.expect_keywords(&[Keyword::AS, Keyword::IDENTITY])?;

                let mut sequence_options: Option<Vec<SequenceOptions>> = None;

                if self.peek_token_ref().token == Token::LParen {
                    self.expect_token(&Token::LParen)?;
                    sequence_options = Some(self.parse_create_sequence_options()?);
                    self.expect_token(&Token::RParen)?;
                }

                AlterColumnOperation::AddGenerated {
                    generated_as,
                    sequence_options,
                }
            } else {
                let message = if is_postgresql {
                    "SET/DROP NOT NULL, SET DEFAULT, SET DATA TYPE, or ADD GENERATED after ALTER COLUMN"
                } else {
                    "SET/DROP NOT NULL, SET DEFAULT, or SET DATA TYPE after ALTER COLUMN"
                };

                return self.expected_ref(message, self.peek_token_ref());
            };
            AlterTableOperation::AlterColumn { column_name, op }
        } else if self.parse_keyword(Keyword::SWAP) {
            self.expect_keyword_is(Keyword::WITH)?;
            let table_name = self.parse_object_name(false)?;
            AlterTableOperation::SwapWith { table_name }
        } else if dialect_of!(self is PostgreSqlDialect | GenericDialect)
            && self.parse_keywords(&[Keyword::OWNER, Keyword::TO])
        {
            let new_owner = self.parse_owner()?;
            AlterTableOperation::OwnerTo { new_owner }
        } else if dialect_of!(self is ClickHouseDialect|GenericDialect)
            && self.parse_keyword(Keyword::ATTACH)
        {
            AlterTableOperation::AttachPartition {
                partition: self.parse_part_or_partition()?,
            }
        } else if dialect_of!(self is ClickHouseDialect|GenericDialect)
            && self.parse_keyword(Keyword::DETACH)
        {
            AlterTableOperation::DetachPartition {
                partition: self.parse_part_or_partition()?,
            }
        } else if dialect_of!(self is ClickHouseDialect|GenericDialect)
            && self.parse_keyword(Keyword::FREEZE)
        {
            let partition = self.parse_part_or_partition()?;
            let with_name = if self.parse_keyword(Keyword::WITH) {
                self.expect_keyword_is(Keyword::NAME)?;
                Some(self.parse_identifier()?)
            } else {
                None
            };
            AlterTableOperation::FreezePartition {
                partition,
                with_name,
            }
        } else if dialect_of!(self is ClickHouseDialect|GenericDialect)
            && self.parse_keyword(Keyword::UNFREEZE)
        {
            let partition = self.parse_part_or_partition()?;
            let with_name = if self.parse_keyword(Keyword::WITH) {
                self.expect_keyword_is(Keyword::NAME)?;
                Some(self.parse_identifier()?)
            } else {
                None
            };
            AlterTableOperation::UnfreezePartition {
                partition,
                with_name,
            }
        } else if self.parse_keywords(&[Keyword::CLUSTER, Keyword::BY]) {
            self.expect_token(&Token::LParen)?;
            let exprs = self.parse_comma_separated(|parser| parser.parse_expr())?;
            self.expect_token(&Token::RParen)?;
            AlterTableOperation::ClusterBy { exprs }
        } else if self.parse_keywords(&[Keyword::SUSPEND, Keyword::RECLUSTER]) {
            AlterTableOperation::SuspendRecluster
        } else if self.parse_keywords(&[Keyword::RESUME, Keyword::RECLUSTER]) {
            AlterTableOperation::ResumeRecluster
        } else if self.parse_keyword(Keyword::LOCK) {
            let equals = self.consume_token(&Token::Eq);
            let lock = match self.parse_one_of_keywords(&[
                Keyword::DEFAULT,
                Keyword::EXCLUSIVE,
                Keyword::NONE,
                Keyword::SHARED,
            ]) {
                Some(Keyword::DEFAULT) => AlterTableLock::Default,
                Some(Keyword::EXCLUSIVE) => AlterTableLock::Exclusive,
                Some(Keyword::NONE) => AlterTableLock::None,
                Some(Keyword::SHARED) => AlterTableLock::Shared,
                _ => self.expected_ref(
                    "DEFAULT, EXCLUSIVE, NONE or SHARED after LOCK [=]",
                    self.peek_token_ref(),
                )?,
            };
            AlterTableOperation::Lock { equals, lock }
        } else if self.parse_keyword(Keyword::ALGORITHM) {
            let equals = self.consume_token(&Token::Eq);
            let algorithm = match self.parse_one_of_keywords(&[
                Keyword::DEFAULT,
                Keyword::INSTANT,
                Keyword::INPLACE,
                Keyword::COPY,
            ]) {
                Some(Keyword::DEFAULT) => AlterTableAlgorithm::Default,
                Some(Keyword::INSTANT) => AlterTableAlgorithm::Instant,
                Some(Keyword::INPLACE) => AlterTableAlgorithm::Inplace,
                Some(Keyword::COPY) => AlterTableAlgorithm::Copy,
                _ => self.expected_ref(
                    "DEFAULT, INSTANT, INPLACE, or COPY after ALGORITHM [=]",
                    self.peek_token_ref(),
                )?,
            };
            AlterTableOperation::Algorithm { equals, algorithm }
        } else if self.parse_keyword(Keyword::AUTO_INCREMENT) {
            let equals = self.consume_token(&Token::Eq);
            let value = self.parse_number_value()?;
            AlterTableOperation::AutoIncrement { equals, value }
        } else if self.parse_keywords(&[Keyword::REPLICA, Keyword::IDENTITY]) {
            let identity = if self.parse_keyword(Keyword::NOTHING) {
                ReplicaIdentity::Nothing
            } else if self.parse_keyword(Keyword::FULL) {
                ReplicaIdentity::Full
            } else if self.parse_keyword(Keyword::DEFAULT) {
                ReplicaIdentity::Default
            } else if self.parse_keywords(&[Keyword::USING, Keyword::INDEX]) {
                ReplicaIdentity::Index(self.parse_identifier()?)
            } else {
                return self.expected_ref(
                    "NOTHING, FULL, DEFAULT, or USING INDEX index_name after REPLICA IDENTITY",
                    self.peek_token_ref(),
                );
            };

            AlterTableOperation::ReplicaIdentity { identity }
        } else if self.parse_keywords(&[Keyword::VALIDATE, Keyword::CONSTRAINT]) {
            let name = self.parse_identifier()?;
            AlterTableOperation::ValidateConstraint { name }
        } else if self.parse_keywords(&[Keyword::SET, Keyword::LOGGED]) {
            AlterTableOperation::SetLogged
        } else if self.parse_keywords(&[Keyword::SET, Keyword::UNLOGGED]) {
            AlterTableOperation::SetUnlogged
        } else {
            let mut options =
                self.parse_options_with_keywords(&[Keyword::SET, Keyword::TBLPROPERTIES])?;
            if !options.is_empty() {
                AlterTableOperation::SetTblProperties {
                    table_properties: options,
                }
            } else {
                options = self.parse_options(Keyword::SET)?;
                if !options.is_empty() {
                    AlterTableOperation::SetOptionsParens { options }
                } else {
                    return self.expected_ref(
                    "ADD, RENAME, PARTITION, SWAP, DROP, REPLICA IDENTITY, SET, or SET TBLPROPERTIES after ALTER TABLE",
                    self.peek_token_ref(),
                  );
                }
            }
        };
        Ok(operation)
    }

    fn parse_set_data_type(&mut self, had_set: bool) -> Result<AlterColumnOperation, ParserError> {
        let data_type = self.parse_data_type()?;
        let using = if self.dialect.supports_alter_column_type_using()
            && self.parse_keyword(Keyword::USING)
        {
            Some(self.parse_expr()?)
        } else {
            None
        };
        Ok(AlterColumnOperation::SetDataType {
            data_type,
            using,
            had_set,
        })
    }

    fn parse_part_or_partition(&mut self) -> Result<Partition, ParserError> {
        let keyword = self.expect_one_of_keywords(&[Keyword::PART, Keyword::PARTITION])?;
        match keyword {
            Keyword::PART => Ok(Partition::Part(self.parse_expr()?)),
            Keyword::PARTITION => Ok(Partition::Expr(self.parse_expr()?)),
            // unreachable because expect_one_of_keywords used above
            unexpected_keyword => Err(ParserError::ParserError(
                format!("Internal parser error: expected any of {{PART, PARTITION}}, got {unexpected_keyword:?}"),
            )),
        }
    }

    /// Parse an `ALTER <object>` statement and dispatch to the appropriate alter handler.
    pub fn parse_alter(&mut self) -> Result<Statement, ParserError> {
        if self.peek_keywords(&[Keyword::TEXT, Keyword::SEARCH]) {
            return self.parse_alter_text_search().map(Into::into);
        }

        let object_type = self.expect_one_of_keywords(&[
            Keyword::VIEW,
            Keyword::TYPE,
            Keyword::COLLATION,
            Keyword::TABLE,
            Keyword::INDEX,
            Keyword::FUNCTION,
            Keyword::AGGREGATE,
            Keyword::ROLE,
            Keyword::POLICY,
            Keyword::CONNECTOR,
            Keyword::ICEBERG,
            Keyword::SCHEMA,
            Keyword::USER,
            Keyword::OPERATOR,
        ])?;
        match object_type {
            Keyword::SCHEMA => {
                self.prev_token();
                self.prev_token();
                self.parse_alter_schema()
            }
            Keyword::VIEW => self.parse_alter_view(),
            Keyword::TYPE => self.parse_alter_type(),
            Keyword::COLLATION => self.parse_alter_collation().map(Into::into),
            Keyword::TABLE => self.parse_alter_table(false),
            Keyword::ICEBERG => {
                self.expect_keyword(Keyword::TABLE)?;
                self.parse_alter_table(true)
            }
            Keyword::INDEX => {
                let index_name = self.parse_object_name(false)?;
                let operation = if self.parse_keyword(Keyword::RENAME) {
                    if self.parse_keyword(Keyword::TO) {
                        let index_name = self.parse_object_name(false)?;
                        AlterIndexOperation::RenameIndex { index_name }
                    } else {
                        return self.expected_ref("TO after RENAME", self.peek_token_ref());
                    }
                } else {
                    return self.expected_ref("RENAME after ALTER INDEX", self.peek_token_ref());
                };

                Ok(Statement::AlterIndex {
                    name: index_name,
                    operation,
                })
            }
            Keyword::FUNCTION => self.parse_alter_function(AlterFunctionKind::Function),
            Keyword::AGGREGATE => self.parse_alter_function(AlterFunctionKind::Aggregate),
            Keyword::OPERATOR => {
                if self.parse_keyword(Keyword::FAMILY) {
                    self.parse_alter_operator_family().map(Into::into)
                } else if self.parse_keyword(Keyword::CLASS) {
                    self.parse_alter_operator_class().map(Into::into)
                } else {
                    self.parse_alter_operator().map(Into::into)
                }
            }
            Keyword::ROLE => self.parse_alter_role(),
            Keyword::POLICY => self.parse_alter_policy().map(Into::into),
            Keyword::CONNECTOR => self.parse_alter_connector(),
            Keyword::USER if self.dialect.supports_alter_user_as_alter_role() => {
                self.parse_alter_role()
            }
            Keyword::USER => self.parse_alter_user().map(Into::into),
            // unreachable because expect_one_of_keywords used above
            unexpected_keyword => Err(ParserError::ParserError(
                format!("Internal parser error: expected any of {{TEXT SEARCH, VIEW, TYPE, COLLATION, TABLE, INDEX, FUNCTION, AGGREGATE, ROLE, POLICY, CONNECTOR, ICEBERG, SCHEMA, USER, OPERATOR}}, got {unexpected_keyword:?}"),
            )),
        }
    }

    fn parse_alter_aggregate_signature(
        &mut self,
    ) -> Result<(FunctionDesc, bool, Option<Vec<OperateFunctionArg>>), ParserError> {
        let name = self.parse_object_name(false)?;
        self.expect_token(&Token::LParen)?;

        if self.consume_token(&Token::Mul) {
            self.expect_token(&Token::RParen)?;
            return Ok((
                FunctionDesc {
                    name,
                    args: Some(vec![]),
                },
                true,
                None,
            ));
        }

        let args =
            if self.peek_keyword(Keyword::ORDER) || self.peek_token_ref().token == Token::RParen {
                vec![]
            } else {
                self.parse_comma_separated(Parser::parse_aggregate_function_arg)?
            };

        let aggregate_order_by = if self.parse_keywords(&[Keyword::ORDER, Keyword::BY]) {
            Some(self.parse_comma_separated(Parser::parse_aggregate_function_arg)?)
        } else {
            None
        };

        self.expect_token(&Token::RParen)?;
        Ok((
            FunctionDesc {
                name,
                args: Some(args),
            },
            false,
            aggregate_order_by,
        ))
    }

    fn parse_alter_function_action(&mut self) -> Result<Option<AlterFunctionAction>, ParserError> {
        let action = if self.parse_keywords(&[
            Keyword::CALLED,
            Keyword::ON,
            Keyword::NULL,
            Keyword::INPUT,
        ]) {
            Some(AlterFunctionAction::CalledOnNull(
                FunctionCalledOnNull::CalledOnNullInput,
            ))
        } else if self.parse_keywords(&[
            Keyword::RETURNS,
            Keyword::NULL,
            Keyword::ON,
            Keyword::NULL,
            Keyword::INPUT,
        ]) {
            Some(AlterFunctionAction::CalledOnNull(
                FunctionCalledOnNull::ReturnsNullOnNullInput,
            ))
        } else if self.parse_keyword(Keyword::STRICT) {
            Some(AlterFunctionAction::CalledOnNull(
                FunctionCalledOnNull::Strict,
            ))
        } else if self.parse_keyword(Keyword::IMMUTABLE) {
            Some(AlterFunctionAction::Behavior(FunctionBehavior::Immutable))
        } else if self.parse_keyword(Keyword::STABLE) {
            Some(AlterFunctionAction::Behavior(FunctionBehavior::Stable))
        } else if self.parse_keyword(Keyword::VOLATILE) {
            Some(AlterFunctionAction::Behavior(FunctionBehavior::Volatile))
        } else if self.parse_keyword(Keyword::NOT) {
            self.expect_keyword(Keyword::LEAKPROOF)?;
            Some(AlterFunctionAction::Leakproof(false))
        } else if self.parse_keyword(Keyword::LEAKPROOF) {
            Some(AlterFunctionAction::Leakproof(true))
        } else if self.parse_keyword(Keyword::EXTERNAL) {
            self.expect_keyword(Keyword::SECURITY)?;
            let security = if self.parse_keyword(Keyword::DEFINER) {
                FunctionSecurity::Definer
            } else if self.parse_keyword(Keyword::INVOKER) {
                FunctionSecurity::Invoker
            } else {
                return self.expected_ref("DEFINER or INVOKER", self.peek_token_ref());
            };
            Some(AlterFunctionAction::Security {
                external: true,
                security,
            })
        } else if self.parse_keyword(Keyword::SECURITY) {
            let security = if self.parse_keyword(Keyword::DEFINER) {
                FunctionSecurity::Definer
            } else if self.parse_keyword(Keyword::INVOKER) {
                FunctionSecurity::Invoker
            } else {
                return self.expected_ref("DEFINER or INVOKER", self.peek_token_ref());
            };
            Some(AlterFunctionAction::Security {
                external: false,
                security,
            })
        } else if self.parse_keyword(Keyword::PARALLEL) {
            let parallel = if self.parse_keyword(Keyword::UNSAFE) {
                FunctionParallel::Unsafe
            } else if self.parse_keyword(Keyword::RESTRICTED) {
                FunctionParallel::Restricted
            } else if self.parse_keyword(Keyword::SAFE) {
                FunctionParallel::Safe
            } else {
                return self
                    .expected_ref("one of UNSAFE | RESTRICTED | SAFE", self.peek_token_ref());
            };
            Some(AlterFunctionAction::Parallel(parallel))
        } else if self.parse_keyword(Keyword::COST) {
            Some(AlterFunctionAction::Cost(self.parse_number()?))
        } else if self.parse_keyword(Keyword::ROWS) {
            Some(AlterFunctionAction::Rows(self.parse_number()?))
        } else if self.parse_keyword(Keyword::SUPPORT) {
            Some(AlterFunctionAction::Support(self.parse_object_name(false)?))
        } else if self.parse_keyword(Keyword::SET) {
            let name = self.parse_object_name(false)?;
            let value = if self.parse_keywords(&[Keyword::FROM, Keyword::CURRENT]) {
                FunctionSetValue::FromCurrent
            } else {
                if !self.consume_token(&Token::Eq) && !self.parse_keyword(Keyword::TO) {
                    return self.expected_ref("= or TO", self.peek_token_ref());
                }
                if self.parse_keyword(Keyword::DEFAULT) {
                    FunctionSetValue::Default
                } else {
                    FunctionSetValue::Values(self.parse_comma_separated(Parser::parse_expr)?)
                }
            };
            Some(AlterFunctionAction::Set(FunctionDefinitionSetParam {
                name,
                value,
            }))
        } else if self.parse_keyword(Keyword::RESET) {
            let reset_config = if self.parse_keyword(Keyword::ALL) {
                ResetConfig::ALL
            } else {
                ResetConfig::ConfigName(self.parse_object_name(false)?)
            };
            Some(AlterFunctionAction::Reset(reset_config))
        } else {
            None
        };

        Ok(action)
    }

    fn parse_alter_function_actions(
        &mut self,
    ) -> Result<(Vec<AlterFunctionAction>, bool), ParserError> {
        let mut actions = vec![];
        while let Some(action) = self.parse_alter_function_action()? {
            actions.push(action);
        }
        if actions.is_empty() {
            return self.expected_ref("at least one ALTER FUNCTION action", self.peek_token_ref());
        }
        let restrict = self.parse_keyword(Keyword::RESTRICT);
        Ok((actions, restrict))
    }

    /// Parse an `ALTER FUNCTION` or `ALTER AGGREGATE` statement.
    pub fn parse_alter_function(
        &mut self,
        kind: AlterFunctionKind,
    ) -> Result<Statement, ParserError> {
        let (function, aggregate_star, aggregate_order_by) = match kind {
            AlterFunctionKind::Function => (self.parse_function_desc()?, false, None),
            AlterFunctionKind::Aggregate => self.parse_alter_aggregate_signature()?,
        };

        let operation = if self.parse_keywords(&[Keyword::RENAME, Keyword::TO]) {
            let new_name = self.parse_identifier()?;
            AlterFunctionOperation::RenameTo { new_name }
        } else if self.parse_keywords(&[Keyword::OWNER, Keyword::TO]) {
            AlterFunctionOperation::OwnerTo(self.parse_owner()?)
        } else if self.parse_keywords(&[Keyword::SET, Keyword::SCHEMA]) {
            AlterFunctionOperation::SetSchema {
                schema_name: self.parse_object_name(false)?,
            }
        } else if matches!(kind, AlterFunctionKind::Function) && self.parse_keyword(Keyword::NO) {
            if !self.parse_keyword(Keyword::DEPENDS) {
                return self.expected_ref("DEPENDS after NO", self.peek_token_ref());
            }
            self.expect_keywords(&[Keyword::ON, Keyword::EXTENSION])?;
            AlterFunctionOperation::DependsOnExtension {
                no: true,
                extension_name: self.parse_object_name(false)?,
            }
        } else if matches!(kind, AlterFunctionKind::Function)
            && self.parse_keyword(Keyword::DEPENDS)
        {
            self.expect_keywords(&[Keyword::ON, Keyword::EXTENSION])?;
            AlterFunctionOperation::DependsOnExtension {
                no: false,
                extension_name: self.parse_object_name(false)?,
            }
        } else if matches!(kind, AlterFunctionKind::Function) {
            let (actions, restrict) = self.parse_alter_function_actions()?;
            AlterFunctionOperation::Actions { actions, restrict }
        } else {
            return self.expected_ref(
                "RENAME TO, OWNER TO, or SET SCHEMA after ALTER AGGREGATE",
                self.peek_token_ref(),
            );
        };

        Ok(Statement::AlterFunction(AlterFunction {
            kind,
            function,
            aggregate_order_by,
            aggregate_star,
            operation,
        }))
    }

    /// Parse a [Statement::AlterTable]
    pub fn parse_alter_table(&mut self, iceberg: bool) -> Result<Statement, ParserError> {
        let if_exists = self.parse_keywords(&[Keyword::IF, Keyword::EXISTS]);
        let only = self.parse_keyword(Keyword::ONLY); // [ ONLY ]
        let table_name = self.parse_object_name(false)?;
        let on_cluster = self.parse_optional_on_cluster()?;
        let operations = self.parse_comma_separated(Parser::parse_alter_table_operation)?;

        let mut location = None;
        if self.parse_keyword(Keyword::LOCATION) {
            location = Some(HiveSetLocation {
                has_set: false,
                location: self.parse_identifier()?,
            });
        } else if self.parse_keywords(&[Keyword::SET, Keyword::LOCATION]) {
            location = Some(HiveSetLocation {
                has_set: true,
                location: self.parse_identifier()?,
            });
        }

        let end_token = if self.peek_token_ref().token == Token::SemiColon {
            self.peek_token_ref().clone()
        } else {
            self.get_current_token().clone()
        };

        Ok(AlterTable {
            name: table_name,
            if_exists,
            only,
            operations,
            location,
            on_cluster,
            table_type: if iceberg {
                Some(AlterTableType::Iceberg)
            } else {
                None
            },
            end_token: AttachedToken(end_token),
        }
        .into())
    }

    /// Parse an `ALTER VIEW` statement.
    pub fn parse_alter_view(&mut self) -> Result<Statement, ParserError> {
        let name = self.parse_object_name(false)?;
        let columns = self.parse_parenthesized_column_list(Optional, false)?;

        let with_options = self.parse_options(Keyword::WITH)?;

        self.expect_keyword_is(Keyword::AS)?;
        let query = self.parse_query()?;

        Ok(Statement::AlterView {
            name,
            columns,
            query,
            with_options,
        })
    }

    /// Parse a [Statement::AlterType]
    pub fn parse_alter_type(&mut self) -> Result<Statement, ParserError> {
        let name = self.parse_object_name(false)?;

        if self.parse_keywords(&[Keyword::RENAME, Keyword::TO]) {
            let new_name = self.parse_identifier()?;
            Ok(Statement::AlterType(AlterType {
                name,
                operation: AlterTypeOperation::Rename(AlterTypeRename { new_name }),
            }))
        } else if self.parse_keywords(&[Keyword::ADD, Keyword::VALUE]) {
            let if_not_exists = self.parse_keywords(&[Keyword::IF, Keyword::NOT, Keyword::EXISTS]);
            let new_enum_value = self.parse_identifier()?;
            let position = if self.parse_keyword(Keyword::BEFORE) {
                Some(AlterTypeAddValuePosition::Before(self.parse_identifier()?))
            } else if self.parse_keyword(Keyword::AFTER) {
                Some(AlterTypeAddValuePosition::After(self.parse_identifier()?))
            } else {
                None
            };

            Ok(Statement::AlterType(AlterType {
                name,
                operation: AlterTypeOperation::AddValue(AlterTypeAddValue {
                    if_not_exists,
                    value: new_enum_value,
                    position,
                }),
            }))
        } else if self.parse_keywords(&[Keyword::RENAME, Keyword::VALUE]) {
            let existing_enum_value = self.parse_identifier()?;
            self.expect_keyword(Keyword::TO)?;
            let new_enum_value = self.parse_identifier()?;

            Ok(Statement::AlterType(AlterType {
                name,
                operation: AlterTypeOperation::RenameValue(AlterTypeRenameValue {
                    from: existing_enum_value,
                    to: new_enum_value,
                }),
            }))
        } else {
            self.expected_ref(
                "{RENAME TO | { RENAME | ADD } VALUE}",
                self.peek_token_ref(),
            )
        }
    }

    /// Parse a [Statement::AlterCollation].
    ///
    /// [PostgreSQL Documentation](https://www.postgresql.org/docs/current/sql-altercollation.html)
    pub fn parse_alter_collation(&mut self) -> Result<AlterCollation, ParserError> {
        let name = self.parse_object_name(false)?;
        let operation = if self.parse_keywords(&[Keyword::RENAME, Keyword::TO]) {
            AlterCollationOperation::RenameTo {
                new_name: self.parse_identifier()?,
            }
        } else if self.parse_keywords(&[Keyword::OWNER, Keyword::TO]) {
            AlterCollationOperation::OwnerTo(self.parse_owner()?)
        } else if self.parse_keywords(&[Keyword::SET, Keyword::SCHEMA]) {
            AlterCollationOperation::SetSchema {
                schema_name: self.parse_object_name(false)?,
            }
        } else if self.parse_keywords(&[Keyword::REFRESH, Keyword::VERSION]) {
            AlterCollationOperation::RefreshVersion
        } else {
            return self.expected_ref(
                "RENAME TO, OWNER TO, SET SCHEMA, or REFRESH VERSION after ALTER COLLATION",
                self.peek_token_ref(),
            );
        };

        Ok(AlterCollation { name, operation })
    }

    /// Parse a [Statement::AlterOperator]
    ///
    /// [PostgreSQL Documentation](https://www.postgresql.org/docs/current/sql-alteroperator.html)
    pub fn parse_alter_operator(&mut self) -> Result<AlterOperator, ParserError> {
        let name = self.parse_operator_name()?;

        // Parse (left_type, right_type)
        self.expect_token(&Token::LParen)?;

        let left_type = if self.parse_keyword(Keyword::NONE) {
            None
        } else {
            Some(self.parse_data_type()?)
        };

        self.expect_token(&Token::Comma)?;
        let right_type = self.parse_data_type()?;
        self.expect_token(&Token::RParen)?;

        // Parse the operation
        let operation = if self.parse_keywords(&[Keyword::OWNER, Keyword::TO]) {
            let owner = if self.parse_keyword(Keyword::CURRENT_ROLE) {
                Owner::CurrentRole
            } else if self.parse_keyword(Keyword::CURRENT_USER) {
                Owner::CurrentUser
            } else if self.parse_keyword(Keyword::SESSION_USER) {
                Owner::SessionUser
            } else {
                Owner::Ident(self.parse_identifier()?)
            };
            AlterOperatorOperation::OwnerTo(owner)
        } else if self.parse_keywords(&[Keyword::SET, Keyword::SCHEMA]) {
            let schema_name = self.parse_object_name(false)?;
            AlterOperatorOperation::SetSchema { schema_name }
        } else if self.parse_keyword(Keyword::SET) {
            self.expect_token(&Token::LParen)?;

            let mut options = Vec::new();
            loop {
                let keyword = self.expect_one_of_keywords(&[
                    Keyword::RESTRICT,
                    Keyword::JOIN,
                    Keyword::COMMUTATOR,
                    Keyword::NEGATOR,
                    Keyword::HASHES,
                    Keyword::MERGES,
                ])?;

                match keyword {
                    Keyword::RESTRICT => {
                        self.expect_token(&Token::Eq)?;
                        let proc_name = if self.parse_keyword(Keyword::NONE) {
                            None
                        } else {
                            Some(self.parse_object_name(false)?)
                        };
                        options.push(OperatorOption::Restrict(proc_name));
                    }
                    Keyword::JOIN => {
                        self.expect_token(&Token::Eq)?;
                        let proc_name = if self.parse_keyword(Keyword::NONE) {
                            None
                        } else {
                            Some(self.parse_object_name(false)?)
                        };
                        options.push(OperatorOption::Join(proc_name));
                    }
                    Keyword::COMMUTATOR => {
                        self.expect_token(&Token::Eq)?;
                        let op_name = self.parse_operator_name()?;
                        options.push(OperatorOption::Commutator(op_name));
                    }
                    Keyword::NEGATOR => {
                        self.expect_token(&Token::Eq)?;
                        let op_name = self.parse_operator_name()?;
                        options.push(OperatorOption::Negator(op_name));
                    }
                    Keyword::HASHES => {
                        options.push(OperatorOption::Hashes);
                    }
                    Keyword::MERGES => {
                        options.push(OperatorOption::Merges);
                    }
                    unexpected_keyword => return Err(ParserError::ParserError(
                        format!("Internal parser error: unexpected keyword `{unexpected_keyword}` in operator option"),
                    )),
                }

                if !self.consume_token(&Token::Comma) {
                    break;
                }
            }

            self.expect_token(&Token::RParen)?;
            AlterOperatorOperation::Set { options }
        } else {
            return self.expected_ref(
                "OWNER TO, SET SCHEMA, or SET after ALTER OPERATOR",
                self.peek_token_ref(),
            );
        };

        Ok(AlterOperator {
            name,
            left_type,
            right_type,
            operation,
        })
    }

    /// Parse an operator item for ALTER OPERATOR FAMILY ADD operations
    fn parse_operator_family_add_operator(&mut self) -> Result<OperatorFamilyItem, ParserError> {
        let strategy_number = self.parse_literal_uint()?;
        let operator_name = self.parse_operator_name()?;

        // Operator argument types (required for ALTER OPERATOR FAMILY)
        self.expect_token(&Token::LParen)?;
        let op_types = self.parse_comma_separated(Parser::parse_data_type)?;
        self.expect_token(&Token::RParen)?;

        // Optional purpose
        let purpose = if self.parse_keyword(Keyword::FOR) {
            if self.parse_keyword(Keyword::SEARCH) {
                Some(OperatorPurpose::ForSearch)
            } else if self.parse_keywords(&[Keyword::ORDER, Keyword::BY]) {
                let sort_family = self.parse_object_name(false)?;
                Some(OperatorPurpose::ForOrderBy { sort_family })
            } else {
                return self.expected_ref("SEARCH or ORDER BY after FOR", self.peek_token_ref());
            }
        } else {
            None
        };

        Ok(OperatorFamilyItem::Operator {
            strategy_number,
            operator_name,
            op_types,
            purpose,
        })
    }

    /// Parse a function item for ALTER OPERATOR FAMILY ADD operations
    fn parse_operator_family_add_function(&mut self) -> Result<OperatorFamilyItem, ParserError> {
        let support_number = self.parse_literal_uint()?;

        // Optional operator types
        let op_types =
            if self.consume_token(&Token::LParen) && self.peek_token_ref().token != Token::RParen {
                let types = self.parse_comma_separated(Parser::parse_data_type)?;
                self.expect_token(&Token::RParen)?;
                Some(types)
            } else {
                None
            };

        let function_name = self.parse_object_name(false)?;

        // Function argument types
        let argument_types = if self.consume_token(&Token::LParen) {
            if self.peek_token_ref().token == Token::RParen {
                self.expect_token(&Token::RParen)?;
                vec![]
            } else {
                let types = self.parse_comma_separated(Parser::parse_data_type)?;
                self.expect_token(&Token::RParen)?;
                types
            }
        } else {
            vec![]
        };

        Ok(OperatorFamilyItem::Function {
            support_number,
            op_types,
            function_name,
            argument_types,
        })
    }

    /// Parse an operator item for ALTER OPERATOR FAMILY DROP operations
    fn parse_operator_family_drop_operator(
        &mut self,
    ) -> Result<OperatorFamilyDropItem, ParserError> {
        let strategy_number = self.parse_literal_uint()?;

        // Operator argument types (required for DROP)
        self.expect_token(&Token::LParen)?;
        let op_types = self.parse_comma_separated(Parser::parse_data_type)?;
        self.expect_token(&Token::RParen)?;

        Ok(OperatorFamilyDropItem::Operator {
            strategy_number,
            op_types,
        })
    }

    /// Parse a function item for ALTER OPERATOR FAMILY DROP operations
    fn parse_operator_family_drop_function(
        &mut self,
    ) -> Result<OperatorFamilyDropItem, ParserError> {
        let support_number = self.parse_literal_uint()?;

        // Operator types (required for DROP)
        self.expect_token(&Token::LParen)?;
        let op_types = self.parse_comma_separated(Parser::parse_data_type)?;
        self.expect_token(&Token::RParen)?;

        Ok(OperatorFamilyDropItem::Function {
            support_number,
            op_types,
        })
    }

    /// Parse an operator family item for ADD operations (dispatches to operator or function parsing)
    fn parse_operator_family_add_item(&mut self) -> Result<OperatorFamilyItem, ParserError> {
        if self.parse_keyword(Keyword::OPERATOR) {
            self.parse_operator_family_add_operator()
        } else if self.parse_keyword(Keyword::FUNCTION) {
            self.parse_operator_family_add_function()
        } else {
            self.expected_ref("OPERATOR or FUNCTION", self.peek_token_ref())
        }
    }

    /// Parse an operator family item for DROP operations (dispatches to operator or function parsing)
    fn parse_operator_family_drop_item(&mut self) -> Result<OperatorFamilyDropItem, ParserError> {
        if self.parse_keyword(Keyword::OPERATOR) {
            self.parse_operator_family_drop_operator()
        } else if self.parse_keyword(Keyword::FUNCTION) {
            self.parse_operator_family_drop_function()
        } else {
            self.expected_ref("OPERATOR or FUNCTION", self.peek_token_ref())
        }
    }

    /// Parse a [Statement::AlterOperatorFamily]
    /// See <https://www.postgresql.org/docs/current/sql-alteropfamily.html>
    pub fn parse_alter_operator_family(&mut self) -> Result<AlterOperatorFamily, ParserError> {
        let name = self.parse_object_name(false)?;
        self.expect_keyword(Keyword::USING)?;
        let using = self.parse_identifier()?;

        let operation = if self.parse_keyword(Keyword::ADD) {
            let items = self.parse_comma_separated(Parser::parse_operator_family_add_item)?;
            AlterOperatorFamilyOperation::Add { items }
        } else if self.parse_keyword(Keyword::DROP) {
            let items = self.parse_comma_separated(Parser::parse_operator_family_drop_item)?;
            AlterOperatorFamilyOperation::Drop { items }
        } else if self.parse_keywords(&[Keyword::RENAME, Keyword::TO]) {
            let new_name = self.parse_object_name(false)?;
            AlterOperatorFamilyOperation::RenameTo { new_name }
        } else if self.parse_keywords(&[Keyword::OWNER, Keyword::TO]) {
            let owner = self.parse_owner()?;
            AlterOperatorFamilyOperation::OwnerTo(owner)
        } else if self.parse_keywords(&[Keyword::SET, Keyword::SCHEMA]) {
            let schema_name = self.parse_object_name(false)?;
            AlterOperatorFamilyOperation::SetSchema { schema_name }
        } else {
            return self.expected_ref(
                "ADD, DROP, RENAME TO, OWNER TO, or SET SCHEMA after ALTER OPERATOR FAMILY",
                self.peek_token_ref(),
            );
        };

        Ok(AlterOperatorFamily {
            name,
            using,
            operation,
        })
    }

    /// Parse an `ALTER OPERATOR CLASS` statement.
    ///
    /// Handles operations like `RENAME TO`, `OWNER TO`, and `SET SCHEMA`.
    pub fn parse_alter_operator_class(&mut self) -> Result<AlterOperatorClass, ParserError> {
        let name = self.parse_object_name(false)?;
        self.expect_keyword(Keyword::USING)?;
        let using = self.parse_identifier()?;

        let operation = if self.parse_keywords(&[Keyword::RENAME, Keyword::TO]) {
            let new_name = self.parse_object_name(false)?;
            AlterOperatorClassOperation::RenameTo { new_name }
        } else if self.parse_keywords(&[Keyword::OWNER, Keyword::TO]) {
            let owner = self.parse_owner()?;
            AlterOperatorClassOperation::OwnerTo(owner)
        } else if self.parse_keywords(&[Keyword::SET, Keyword::SCHEMA]) {
            let schema_name = self.parse_object_name(false)?;
            AlterOperatorClassOperation::SetSchema { schema_name }
        } else {
            return self.expected_ref(
                "RENAME TO, OWNER TO, or SET SCHEMA after ALTER OPERATOR CLASS",
                self.peek_token_ref(),
            );
        };

        Ok(AlterOperatorClass {
            name,
            using,
            operation,
        })
    }

    /// Parse an `ALTER SCHEMA` statement.
    ///
    /// Supports operations such as setting options, renaming, adding/dropping replicas, and changing owner.
    pub fn parse_alter_schema(&mut self) -> Result<Statement, ParserError> {
        self.expect_keywords(&[Keyword::ALTER, Keyword::SCHEMA])?;
        let if_exists = self.parse_keywords(&[Keyword::IF, Keyword::EXISTS]);
        let name = self.parse_object_name(false)?;
        let operation = if self.parse_keywords(&[Keyword::SET, Keyword::OPTIONS]) {
            self.prev_token();
            let options = self.parse_options(Keyword::OPTIONS)?;
            AlterSchemaOperation::SetOptionsParens { options }
        } else if self.parse_keywords(&[Keyword::SET, Keyword::DEFAULT, Keyword::COLLATE]) {
            let collate = self.parse_expr()?;
            AlterSchemaOperation::SetDefaultCollate { collate }
        } else if self.parse_keywords(&[Keyword::ADD, Keyword::REPLICA]) {
            let replica = self.parse_identifier()?;
            let options = if self.peek_keyword(Keyword::OPTIONS) {
                Some(self.parse_options(Keyword::OPTIONS)?)
            } else {
                None
            };
            AlterSchemaOperation::AddReplica { replica, options }
        } else if self.parse_keywords(&[Keyword::DROP, Keyword::REPLICA]) {
            let replica = self.parse_identifier()?;
            AlterSchemaOperation::DropReplica { replica }
        } else if self.parse_keywords(&[Keyword::RENAME, Keyword::TO]) {
            let new_name = self.parse_object_name(false)?;
            AlterSchemaOperation::Rename { name: new_name }
        } else if self.parse_keywords(&[Keyword::OWNER, Keyword::TO]) {
            let owner = self.parse_owner()?;
            AlterSchemaOperation::OwnerTo { owner }
        } else {
            return self.expected_ref("ALTER SCHEMA operation", self.peek_token_ref());
        };
        Ok(Statement::AlterSchema(AlterSchema {
            name,
            if_exists,
            operations: vec![operation],
        }))
    }

    /// Parse a `CALL procedure_name(arg1, arg2, ...)`
    /// or `CALL procedure_name` statement
    pub fn parse_call(&mut self) -> Result<Statement, ParserError> {
        let object_name = self.parse_object_name(false)?;
        if self.peek_token_ref().token == Token::LParen {
            match self.parse_function(object_name)? {
                Expr::Function(f) => Ok(Statement::Call(f)),
                other => parser_err!(
                    format!("Expected a simple procedure call but found: {other}"),
                    self.peek_token_ref().span.start
                ),
            }
        } else {
            Ok(Statement::Call(Function {
                name: object_name,
                uses_odbc_syntax: false,
                parameters: FunctionArguments::None,
                args: FunctionArguments::None,
                over: None,
                filter: None,
                null_treatment: None,
                within_group: vec![],
            }))
        }
    }

    /// Parse a copy statement
    pub fn parse_copy(&mut self) -> Result<Statement, ParserError> {
        let source;
        if self.consume_token(&Token::LParen) {
            source = CopySource::Query(self.parse_query()?);
            self.expect_token(&Token::RParen)?;
        } else {
            let table_name = self.parse_object_name(false)?;
            let columns = self.parse_parenthesized_column_list(Optional, false)?;
            source = CopySource::Table {
                table_name,
                columns,
            };
        }
        let to = match self.parse_one_of_keywords(&[Keyword::FROM, Keyword::TO]) {
            Some(Keyword::FROM) => false,
            Some(Keyword::TO) => true,
            _ => self.expected_ref("FROM or TO", self.peek_token_ref())?,
        };
        if !to {
            // Use a separate if statement to prevent Rust compiler from complaining about
            // "if statement in this position is unstable: https://github.com/rust-lang/rust/issues/53667"
            if let CopySource::Query(_) = source {
                return Err(ParserError::ParserError(
                    "COPY ... FROM does not support query as a source".to_string(),
                ));
            }
        }
        let target = if self.parse_keyword(Keyword::STDIN) {
            CopyTarget::Stdin
        } else if self.parse_keyword(Keyword::STDOUT) {
            CopyTarget::Stdout
        } else if self.parse_keyword(Keyword::PROGRAM) {
            CopyTarget::Program {
                command: self.parse_literal_string()?,
            }
        } else {
            CopyTarget::File {
                filename: self.parse_literal_string()?,
            }
        };
        let _ = self.parse_keyword(Keyword::WITH); // [ WITH ]
        let mut options = vec![];
        if self.consume_token(&Token::LParen) {
            options = self.parse_comma_separated(Parser::parse_copy_option)?;
            self.expect_token(&Token::RParen)?;
        }
        let mut legacy_options = vec![];
        while let Some(opt) = self.maybe_parse(|parser| parser.parse_copy_legacy_option())? {
            legacy_options.push(opt);
        }
        let values =
            if matches!(target, CopyTarget::Stdin) && self.peek_token_ref().token != Token::EOF {
                self.expect_token(&Token::SemiColon)?;
                self.parse_tsv()
            } else {
                vec![]
            };
        Ok(Statement::Copy {
            source,
            to,
            target,
            options,
            legacy_options,
            values,
        })
    }

    /// Parse [Statement::Open]
    fn parse_open(&mut self) -> Result<Statement, ParserError> {
        self.expect_keyword(Keyword::OPEN)?;
        Ok(Statement::Open(OpenStatement {
            cursor_name: self.parse_identifier()?,
        }))
    }

    /// Parse a `CLOSE` cursor statement.
    pub fn parse_close(&mut self) -> Result<Statement, ParserError> {
        let cursor = if self.parse_keyword(Keyword::ALL) {
            CloseCursor::All
        } else {
            let name = self.parse_identifier()?;

            CloseCursor::Specific { name }
        };

        Ok(Statement::Close { cursor })
    }

    fn parse_copy_option(&mut self) -> Result<CopyOption, ParserError> {
        let ret = match self.parse_one_of_keywords(&[
            Keyword::FORMAT,
            Keyword::FREEZE,
            Keyword::DELIMITER,
            Keyword::NULL,
            Keyword::HEADER,
            Keyword::QUOTE,
            Keyword::ESCAPE,
            Keyword::FORCE_QUOTE,
            Keyword::FORCE_NOT_NULL,
            Keyword::FORCE_NULL,
            Keyword::ENCODING,
        ]) {
            Some(Keyword::FORMAT) => CopyOption::Format(self.parse_identifier()?),
            Some(Keyword::FREEZE) => CopyOption::Freeze(!matches!(
                self.parse_one_of_keywords(&[Keyword::TRUE, Keyword::FALSE]),
                Some(Keyword::FALSE)
            )),
            Some(Keyword::DELIMITER) => CopyOption::Delimiter(self.parse_literal_char()?),
            Some(Keyword::NULL) => CopyOption::Null(self.parse_literal_string()?),
            Some(Keyword::HEADER) => CopyOption::Header(!matches!(
                self.parse_one_of_keywords(&[Keyword::TRUE, Keyword::FALSE]),
                Some(Keyword::FALSE)
            )),
            Some(Keyword::QUOTE) => CopyOption::Quote(self.parse_literal_char()?),
            Some(Keyword::ESCAPE) => CopyOption::Escape(self.parse_literal_char()?),
            Some(Keyword::FORCE_QUOTE) => {
                CopyOption::ForceQuote(self.parse_parenthesized_column_list(Mandatory, false)?)
            }
            Some(Keyword::FORCE_NOT_NULL) => {
                CopyOption::ForceNotNull(self.parse_parenthesized_column_list(Mandatory, false)?)
            }
            Some(Keyword::FORCE_NULL) => {
                CopyOption::ForceNull(self.parse_parenthesized_column_list(Mandatory, false)?)
            }
            Some(Keyword::ENCODING) => CopyOption::Encoding(self.parse_literal_string()?),
            _ => self.expected_ref("option", self.peek_token_ref())?,
        };
        Ok(ret)
    }

    fn parse_copy_legacy_option(&mut self) -> Result<CopyLegacyOption, ParserError> {
        // FORMAT \[ AS \] is optional
        if self.parse_keyword(Keyword::FORMAT) {
            let _ = self.parse_keyword(Keyword::AS);
        }

        let ret = match self.parse_one_of_keywords(&[
            Keyword::ACCEPTANYDATE,
            Keyword::ACCEPTINVCHARS,
            Keyword::ADDQUOTES,
            Keyword::ALLOWOVERWRITE,
            Keyword::BINARY,
            Keyword::BLANKSASNULL,
            Keyword::BZIP2,
            Keyword::CLEANPATH,
            Keyword::COMPUPDATE,
            Keyword::CREDENTIALS,
            Keyword::CSV,
            Keyword::DATEFORMAT,
            Keyword::DELIMITER,
            Keyword::EMPTYASNULL,
            Keyword::ENCRYPTED,
            Keyword::ESCAPE,
            Keyword::EXTENSION,
            Keyword::FIXEDWIDTH,
            Keyword::GZIP,
            Keyword::HEADER,
            Keyword::IAM_ROLE,
            Keyword::IGNOREHEADER,
            Keyword::JSON,
            Keyword::MANIFEST,
            Keyword::MAXFILESIZE,
            Keyword::NULL,
            Keyword::PARALLEL,
            Keyword::PARQUET,
            Keyword::PARTITION,
            Keyword::REGION,
            Keyword::REMOVEQUOTES,
            Keyword::ROWGROUPSIZE,
            Keyword::STATUPDATE,
            Keyword::TIMEFORMAT,
            Keyword::TRUNCATECOLUMNS,
            Keyword::ZSTD,
        ]) {
            Some(Keyword::ACCEPTANYDATE) => CopyLegacyOption::AcceptAnyDate,
            Some(Keyword::ACCEPTINVCHARS) => {
                let _ = self.parse_keyword(Keyword::AS); // [ AS ]
                let ch = if matches!(self.peek_token_ref().token, Token::SingleQuotedString(_)) {
                    Some(self.parse_literal_string()?)
                } else {
                    None
                };
                CopyLegacyOption::AcceptInvChars(ch)
            }
            Some(Keyword::ADDQUOTES) => CopyLegacyOption::AddQuotes,
            Some(Keyword::ALLOWOVERWRITE) => CopyLegacyOption::AllowOverwrite,
            Some(Keyword::BINARY) => CopyLegacyOption::Binary,
            Some(Keyword::BLANKSASNULL) => CopyLegacyOption::BlankAsNull,
            Some(Keyword::BZIP2) => CopyLegacyOption::Bzip2,
            Some(Keyword::CLEANPATH) => CopyLegacyOption::CleanPath,
            Some(Keyword::COMPUPDATE) => {
                let preset = self.parse_keyword(Keyword::PRESET);
                let enabled = match self.parse_one_of_keywords(&[
                    Keyword::TRUE,
                    Keyword::FALSE,
                    Keyword::ON,
                    Keyword::OFF,
                ]) {
                    Some(Keyword::TRUE) | Some(Keyword::ON) => Some(true),
                    Some(Keyword::FALSE) | Some(Keyword::OFF) => Some(false),
                    _ => None,
                };
                CopyLegacyOption::CompUpdate { preset, enabled }
            }
            Some(Keyword::CREDENTIALS) => {
                CopyLegacyOption::Credentials(self.parse_literal_string()?)
            }
            Some(Keyword::CSV) => CopyLegacyOption::Csv({
                let mut opts = vec![];
                while let Some(opt) =
                    self.maybe_parse(|parser| parser.parse_copy_legacy_csv_option())?
                {
                    opts.push(opt);
                }
                opts
            }),
            Some(Keyword::DATEFORMAT) => {
                let _ = self.parse_keyword(Keyword::AS);
                let fmt = if matches!(self.peek_token_ref().token, Token::SingleQuotedString(_)) {
                    Some(self.parse_literal_string()?)
                } else {
                    None
                };
                CopyLegacyOption::DateFormat(fmt)
            }
            Some(Keyword::DELIMITER) => {
                let _ = self.parse_keyword(Keyword::AS);
                CopyLegacyOption::Delimiter(self.parse_literal_char()?)
            }
            Some(Keyword::EMPTYASNULL) => CopyLegacyOption::EmptyAsNull,
            Some(Keyword::ENCRYPTED) => {
                let auto = self.parse_keyword(Keyword::AUTO);
                CopyLegacyOption::Encrypted { auto }
            }
            Some(Keyword::ESCAPE) => CopyLegacyOption::Escape,
            Some(Keyword::EXTENSION) => {
                let ext = self.parse_literal_string()?;
                CopyLegacyOption::Extension(ext)
            }
            Some(Keyword::FIXEDWIDTH) => {
                let spec = self.parse_literal_string()?;
                CopyLegacyOption::FixedWidth(spec)
            }
            Some(Keyword::GZIP) => CopyLegacyOption::Gzip,
            Some(Keyword::HEADER) => CopyLegacyOption::Header,
            Some(Keyword::IAM_ROLE) => CopyLegacyOption::IamRole(self.parse_iam_role_kind()?),
            Some(Keyword::IGNOREHEADER) => {
                let _ = self.parse_keyword(Keyword::AS);
                let num_rows = self.parse_literal_uint()?;
                CopyLegacyOption::IgnoreHeader(num_rows)
            }
            Some(Keyword::JSON) => {
                let _ = self.parse_keyword(Keyword::AS);
                let fmt = if matches!(self.peek_token_ref().token, Token::SingleQuotedString(_)) {
                    Some(self.parse_literal_string()?)
                } else {
                    None
                };
                CopyLegacyOption::Json(fmt)
            }
            Some(Keyword::MANIFEST) => {
                let verbose = self.parse_keyword(Keyword::VERBOSE);
                CopyLegacyOption::Manifest { verbose }
            }
            Some(Keyword::MAXFILESIZE) => {
                let _ = self.parse_keyword(Keyword::AS);
                let size = self.parse_number_value()?;
                let unit = match self.parse_one_of_keywords(&[Keyword::MB, Keyword::GB]) {
                    Some(Keyword::MB) => Some(FileSizeUnit::MB),
                    Some(Keyword::GB) => Some(FileSizeUnit::GB),
                    _ => None,
                };
                CopyLegacyOption::MaxFileSize(FileSize { size, unit })
            }
            Some(Keyword::NULL) => {
                let _ = self.parse_keyword(Keyword::AS);
                CopyLegacyOption::Null(self.parse_literal_string()?)
            }
            Some(Keyword::PARALLEL) => {
                let enabled = match self.parse_one_of_keywords(&[
                    Keyword::TRUE,
                    Keyword::FALSE,
                    Keyword::ON,
                    Keyword::OFF,
                ]) {
                    Some(Keyword::TRUE) | Some(Keyword::ON) => Some(true),
                    Some(Keyword::FALSE) | Some(Keyword::OFF) => Some(false),
                    _ => None,
                };
                CopyLegacyOption::Parallel(enabled)
            }
            Some(Keyword::PARQUET) => CopyLegacyOption::Parquet,
            Some(Keyword::PARTITION) => {
                self.expect_keyword(Keyword::BY)?;
                let columns = self.parse_parenthesized_column_list(IsOptional::Mandatory, false)?;
                let include = self.parse_keyword(Keyword::INCLUDE);
                CopyLegacyOption::PartitionBy(UnloadPartitionBy { columns, include })
            }
            Some(Keyword::REGION) => {
                let _ = self.parse_keyword(Keyword::AS);
                let region = self.parse_literal_string()?;
                CopyLegacyOption::Region(region)
            }
            Some(Keyword::REMOVEQUOTES) => CopyLegacyOption::RemoveQuotes,
            Some(Keyword::ROWGROUPSIZE) => {
                let _ = self.parse_keyword(Keyword::AS);
                let file_size = self.parse_file_size()?;
                CopyLegacyOption::RowGroupSize(file_size)
            }
            Some(Keyword::STATUPDATE) => {
                let enabled = match self.parse_one_of_keywords(&[
                    Keyword::TRUE,
                    Keyword::FALSE,
                    Keyword::ON,
                    Keyword::OFF,
                ]) {
                    Some(Keyword::TRUE) | Some(Keyword::ON) => Some(true),
                    Some(Keyword::FALSE) | Some(Keyword::OFF) => Some(false),
                    _ => None,
                };
                CopyLegacyOption::StatUpdate(enabled)
            }
            Some(Keyword::TIMEFORMAT) => {
                let _ = self.parse_keyword(Keyword::AS);
                let fmt = if matches!(self.peek_token_ref().token, Token::SingleQuotedString(_)) {
                    Some(self.parse_literal_string()?)
                } else {
                    None
                };
                CopyLegacyOption::TimeFormat(fmt)
            }
            Some(Keyword::TRUNCATECOLUMNS) => CopyLegacyOption::TruncateColumns,
            Some(Keyword::ZSTD) => CopyLegacyOption::Zstd,
            _ => self.expected_ref("option", self.peek_token_ref())?,
        };
        Ok(ret)
    }

    fn parse_file_size(&mut self) -> Result<FileSize, ParserError> {
        let size = self.parse_number_value()?;
        let unit = self.maybe_parse_file_size_unit();
        Ok(FileSize { size, unit })
    }

    fn maybe_parse_file_size_unit(&mut self) -> Option<FileSizeUnit> {
        match self.parse_one_of_keywords(&[Keyword::MB, Keyword::GB]) {
            Some(Keyword::MB) => Some(FileSizeUnit::MB),
            Some(Keyword::GB) => Some(FileSizeUnit::GB),
            _ => None,
        }
    }

    fn parse_iam_role_kind(&mut self) -> Result<IamRoleKind, ParserError> {
        if self.parse_keyword(Keyword::DEFAULT) {
            Ok(IamRoleKind::Default)
        } else {
            let arn = self.parse_literal_string()?;
            Ok(IamRoleKind::Arn(arn))
        }
    }

    fn parse_copy_legacy_csv_option(&mut self) -> Result<CopyLegacyCsvOption, ParserError> {
        let ret = match self.parse_one_of_keywords(&[
            Keyword::HEADER,
            Keyword::QUOTE,
            Keyword::ESCAPE,
            Keyword::FORCE,
        ]) {
            Some(Keyword::HEADER) => CopyLegacyCsvOption::Header,
            Some(Keyword::QUOTE) => {
                let _ = self.parse_keyword(Keyword::AS); // [ AS ]
                CopyLegacyCsvOption::Quote(self.parse_literal_char()?)
            }
            Some(Keyword::ESCAPE) => {
                let _ = self.parse_keyword(Keyword::AS); // [ AS ]
                CopyLegacyCsvOption::Escape(self.parse_literal_char()?)
            }
            Some(Keyword::FORCE) if self.parse_keywords(&[Keyword::NOT, Keyword::NULL]) => {
                CopyLegacyCsvOption::ForceNotNull(
                    self.parse_comma_separated(|p| p.parse_identifier())?,
                )
            }
            Some(Keyword::FORCE) if self.parse_keywords(&[Keyword::QUOTE]) => {
                CopyLegacyCsvOption::ForceQuote(
                    self.parse_comma_separated(|p| p.parse_identifier())?,
                )
            }
            _ => self.expected_ref("csv option", self.peek_token_ref())?,
        };
        Ok(ret)
    }

    fn parse_literal_char(&mut self) -> Result<char, ParserError> {
        let s = self.parse_literal_string()?;
        if s.len() != 1 {
            let loc = self
                .tokens
                .get(self.index - 1)
                .map_or(Location { line: 0, column: 0 }, |t| t.span.start);
            return parser_err!(format!("Expect a char, found {s:?}"), loc);
        }
        Ok(s.chars().next().unwrap())
    }

    /// Parse a tab separated values in
    /// COPY payload
    pub fn parse_tsv(&mut self) -> Vec<Option<String>> {
        self.parse_tab_value()
    }

    /// Parse a single tab-separated value row used by `COPY` payload parsing.
    pub fn parse_tab_value(&mut self) -> Vec<Option<String>> {
        let mut values = vec![];
        let mut content = String::new();
        while let Some(t) = self.next_token_no_skip().map(|t| &t.token) {
            match t {
                Token::Whitespace(Whitespace::Tab) => {
                    values.push(Some(core::mem::take(&mut content)));
                }
                Token::Whitespace(Whitespace::Newline) => {
                    values.push(Some(core::mem::take(&mut content)));
                }
                Token::Backslash => {
                    if self.consume_token(&Token::Period) {
                        return values;
                    }
                    if let Token::Word(w) = self.next_token().token {
                        if w.value == "N" {
                            values.push(None);
                        }
                    }
                }
                _ => {
                    content.push_str(&t.to_string());
                }
            }
        }
        values
    }

    /// Parse a literal value (numbers, strings, date/time, booleans)
    pub fn parse_value(&mut self) -> Result<ValueWithSpan, ParserError> {
        let next_token = self.next_token();
        let span = next_token.span;
        let ok_value = |value: Value| Ok(value.with_span(span));
        match next_token.token {
            Token::Word(w) => match w.keyword {
                Keyword::TRUE if self.dialect.supports_boolean_literals() => {
                    ok_value(Value::Boolean(true))
                }
                Keyword::FALSE if self.dialect.supports_boolean_literals() => {
                    ok_value(Value::Boolean(false))
                }
                Keyword::NULL => ok_value(Value::Null),
                Keyword::NoKeyword if w.quote_style.is_some() => match w.quote_style {
                    Some('"') => ok_value(Value::DoubleQuotedString(w.value)),
                    Some('\'') => ok_value(Value::SingleQuotedString(w.value)),
                    _ => self.expected(
                        "A value?",
                        TokenWithSpan {
                            token: Token::Word(w),
                            span,
                        },
                    )?,
                },
                _ => self.expected(
                    "a concrete value",
                    TokenWithSpan {
                        token: Token::Word(w),
                        span,
                    },
                ),
            },
            // The call to n.parse() returns a bigdecimal when the
            // bigdecimal feature is enabled, and is otherwise a no-op
            // (i.e., it returns the input string).
            Token::Number(n, l) => ok_value(Value::Number(Self::parse(n, span.start)?, l)),
            Token::SingleQuotedString(ref s) => ok_value(Value::SingleQuotedString(
                self.maybe_concat_string_literal(s.to_string()),
            )),
            Token::DoubleQuotedString(ref s) => ok_value(Value::DoubleQuotedString(
                self.maybe_concat_string_literal(s.to_string()),
            )),
            Token::TripleSingleQuotedString(ref s) => {
                ok_value(Value::TripleSingleQuotedString(s.to_string()))
            }
            Token::TripleDoubleQuotedString(ref s) => {
                ok_value(Value::TripleDoubleQuotedString(s.to_string()))
            }
            Token::DollarQuotedString(ref s) => ok_value(Value::DollarQuotedString(s.clone())),
            Token::SingleQuotedByteStringLiteral(ref s) => {
                ok_value(Value::SingleQuotedByteStringLiteral(s.clone()))
            }
            Token::DoubleQuotedByteStringLiteral(ref s) => {
                ok_value(Value::DoubleQuotedByteStringLiteral(s.clone()))
            }
            Token::TripleSingleQuotedByteStringLiteral(ref s) => {
                ok_value(Value::TripleSingleQuotedByteStringLiteral(s.clone()))
            }
            Token::TripleDoubleQuotedByteStringLiteral(ref s) => {
                ok_value(Value::TripleDoubleQuotedByteStringLiteral(s.clone()))
            }
            Token::SingleQuotedRawStringLiteral(ref s) => {
                ok_value(Value::SingleQuotedRawStringLiteral(s.clone()))
            }
            Token::DoubleQuotedRawStringLiteral(ref s) => {
                ok_value(Value::DoubleQuotedRawStringLiteral(s.clone()))
            }
            Token::TripleSingleQuotedRawStringLiteral(ref s) => {
                ok_value(Value::TripleSingleQuotedRawStringLiteral(s.clone()))
            }
            Token::TripleDoubleQuotedRawStringLiteral(ref s) => {
                ok_value(Value::TripleDoubleQuotedRawStringLiteral(s.clone()))
            }
            Token::NationalStringLiteral(ref s) => {
                ok_value(Value::NationalStringLiteral(s.to_string()))
            }
            Token::QuoteDelimitedStringLiteral(v) => {
                ok_value(Value::QuoteDelimitedStringLiteral(v))
            }
            Token::NationalQuoteDelimitedStringLiteral(v) => {
                ok_value(Value::NationalQuoteDelimitedStringLiteral(v))
            }
            Token::EscapedStringLiteral(ref s) => {
                ok_value(Value::EscapedStringLiteral(s.to_string()))
            }
            Token::UnicodeStringLiteral(ref s) => {
                ok_value(Value::UnicodeStringLiteral(s.to_string()))
            }
            Token::HexStringLiteral(ref s) => ok_value(Value::HexStringLiteral(s.to_string())),
            Token::Placeholder(ref s) => ok_value(Value::Placeholder(s.to_string())),
            tok @ Token::Colon | tok @ Token::AtSign => {
                // 1. Not calling self.parse_identifier(false)?
                //    because only in placeholder we want to check
                //    numbers as idfentifies.  This because snowflake
                //    allows numbers as placeholders
                // 2. Not calling self.next_token() to enforce `tok`
                //    be followed immediately by a word/number, ie.
                //    without any whitespace in between
                let next_token = self.next_token_no_skip().unwrap_or(&EOF_TOKEN).clone();
                let ident = match next_token.token {
                    Token::Word(w) if w.quote_style.is_none() => Ok(w.into_ident(next_token.span)),
                    Token::Number(w, false) => Ok(Ident::with_span(next_token.span, w)),
                    _ => self.expected("placeholder", next_token),
                }?;
                Ok(Value::Placeholder(format!("{tok}{}", ident.value))
                    .with_span(Span::new(span.start, ident.span.end)))
            }
            unexpected => self.expected(
                "a value",
                TokenWithSpan {
                    token: unexpected,
                    span,
                },
            ),
        }
    }

    fn maybe_concat_string_literal(&mut self, mut str: String) -> String {
        if self.dialect.supports_string_literal_concatenation() {
            while let Token::SingleQuotedString(ref s) | Token::DoubleQuotedString(ref s) =
                self.peek_token_ref().token
            {
                str.push_str(s);
                self.advance_token();
            }
        } else if self
            .dialect
            .supports_string_literal_concatenation_with_newline()
        {
            // We are iterating over tokens including whitespaces, to identify
            // string literals separated by newlines so we can concatenate them.
            let mut after_newline = false;
            loop {
                match self.peek_token_no_skip().token {
                    Token::Whitespace(Whitespace::Newline) => {
                        after_newline = true;
                        self.next_token_no_skip();
                    }
                    Token::Whitespace(_) => {
                        self.next_token_no_skip();
                    }
                    Token::SingleQuotedString(ref s) | Token::DoubleQuotedString(ref s)
                        if after_newline =>
                    {
                        str.push_str(s.clone().as_str());
                        self.next_token_no_skip();
                        after_newline = false;
                    }
                    _ => break,
                }
            }
        }

        str
    }

    /// Parse an unsigned numeric literal
    pub fn parse_number_value(&mut self) -> Result<ValueWithSpan, ParserError> {
        let value_wrapper = self.parse_value()?;
        match &value_wrapper.value {
            Value::Number(_, _) => Ok(value_wrapper),
            Value::Placeholder(_) => Ok(value_wrapper),
            _ => {
                self.prev_token();
                self.expected_ref("literal number", self.peek_token_ref())
            }
        }
    }

    /// Parse a numeric literal as an expression. Returns a [`Expr::UnaryOp`] if the number is signed,
    /// otherwise returns a [`Expr::Value`]
    pub fn parse_number(&mut self) -> Result<Expr, ParserError> {
        let next_token = self.next_token();
        match next_token.token {
            Token::Plus => Ok(Expr::UnaryOp {
                op: UnaryOperator::Plus,
                expr: Box::new(Expr::Value(self.parse_number_value()?)),
            }),
            Token::Minus => Ok(Expr::UnaryOp {
                op: UnaryOperator::Minus,
                expr: Box::new(Expr::Value(self.parse_number_value()?)),
            }),
            _ => {
                self.prev_token();
                Ok(Expr::Value(self.parse_number_value()?))
            }
        }
    }

    fn parse_introduced_string_expr(&mut self) -> Result<Expr, ParserError> {
        let next_token = self.next_token();
        let span = next_token.span;
        match next_token.token {
            Token::SingleQuotedString(ref s) => Ok(Expr::Value(
                Value::SingleQuotedString(s.to_string()).with_span(span),
            )),
            Token::DoubleQuotedString(ref s) => Ok(Expr::Value(
                Value::DoubleQuotedString(s.to_string()).with_span(span),
            )),
            Token::HexStringLiteral(ref s) => Ok(Expr::Value(
                Value::HexStringLiteral(s.to_string()).with_span(span),
            )),
            unexpected => self.expected(
                "a string value",
                TokenWithSpan {
                    token: unexpected,
                    span,
                },
            ),
        }
    }

    /// Parse an unsigned literal integer/long
    pub fn parse_literal_uint(&mut self) -> Result<u64, ParserError> {
        let next_token = self.next_token();
        match next_token.token {
            Token::Number(s, _) => Self::parse::<u64>(s, next_token.span.start),
            _ => self.expected("literal int", next_token),
        }
    }

    /// Parse the body of a `CREATE FUNCTION` specified as a string.
    /// e.g. `CREATE FUNCTION ... AS $$ body $$`.
    fn parse_create_function_body_string(&mut self) -> Result<CreateFunctionBody, ParserError> {
        let parse_string_expr = |parser: &mut Parser| -> Result<Expr, ParserError> {
            let peek_token = parser.peek_token();
            let span = peek_token.span;
            match peek_token.token {
                Token::DollarQuotedString(s) if dialect_of!(parser is PostgreSqlDialect | GenericDialect) =>
                {
                    parser.next_token();
                    Ok(Expr::Value(Value::DollarQuotedString(s).with_span(span)))
                }
                _ => Ok(Expr::Value(
                    Value::SingleQuotedString(parser.parse_literal_string()?).with_span(span),
                )),
            }
        };

        Ok(CreateFunctionBody::AsBeforeOptions {
            body: parse_string_expr(self)?,
            link_symbol: if self.consume_token(&Token::Comma) {
                Some(parse_string_expr(self)?)
            } else {
                None
            },
        })
    }

    /// Parse a literal string
    pub fn parse_literal_string(&mut self) -> Result<String, ParserError> {
        let next_token = self.next_token();
        match next_token.token {
            Token::Word(Word {
                value,
                keyword: Keyword::NoKeyword,
                ..
            }) => Ok(value),
            Token::SingleQuotedString(s) => Ok(s),
            Token::DoubleQuotedString(s) => Ok(s),
            Token::EscapedStringLiteral(s) if dialect_of!(self is PostgreSqlDialect | GenericDialect) => {
                Ok(s)
            }
            Token::UnicodeStringLiteral(s) => Ok(s),
            _ => self.expected("literal string", next_token),
        }
    }

    /// Parse a boolean string
    pub(crate) fn parse_boolean_string(&mut self) -> Result<bool, ParserError> {
        match self.parse_one_of_keywords(&[Keyword::TRUE, Keyword::FALSE]) {
            Some(Keyword::TRUE) => Ok(true),
            Some(Keyword::FALSE) => Ok(false),
            _ => self.expected_ref("TRUE or FALSE", self.peek_token_ref()),
        }
    }

    /// Parse the `IS [NOT] JSON` predicate after `JSON` (and optional `NOT`) was consumed.
    fn parse_is_json_predicate(&mut self, expr: Expr, negated: bool) -> Result<Expr, ParserError> {
        let kind = match self.parse_one_of_keywords(&[
            Keyword::VALUE,
            Keyword::SCALAR,
            Keyword::ARRAY,
            Keyword::OBJECT,
        ]) {
            Some(Keyword::VALUE) => Some(JsonPredicateType::Value),
            Some(Keyword::SCALAR) => Some(JsonPredicateType::Scalar),
            Some(Keyword::ARRAY) => Some(JsonPredicateType::Array),
            Some(Keyword::OBJECT) => Some(JsonPredicateType::Object),
            _ => None,
        };

        let unique_keys = match self.parse_one_of_keywords(&[Keyword::WITH, Keyword::WITHOUT]) {
            Some(Keyword::WITH) => {
                self.expect_keyword_is(Keyword::UNIQUE)?;
                let _ = self.parse_keyword(Keyword::KEYS);
                Some(JsonKeyUniqueness::WithUniqueKeys)
            }
            Some(Keyword::WITHOUT) => {
                self.expect_keyword_is(Keyword::UNIQUE)?;
                let _ = self.parse_keyword(Keyword::KEYS);
                Some(JsonKeyUniqueness::WithoutUniqueKeys)
            }
            _ => None,
        };

        Ok(Expr::IsJson {
            expr: Box::new(expr),
            kind,
            unique_keys,
            negated,
        })
    }

    /// Parse a literal unicode normalization clause
    pub fn parse_unicode_is_normalized(&mut self, expr: Expr) -> Result<Expr, ParserError> {
        let neg = self.parse_keyword(Keyword::NOT);
        let normalized_form = self.maybe_parse(|parser| {
            match parser.parse_one_of_keywords(&[
                Keyword::NFC,
                Keyword::NFD,
                Keyword::NFKC,
                Keyword::NFKD,
            ]) {
                Some(Keyword::NFC) => Ok(NormalizationForm::NFC),
                Some(Keyword::NFD) => Ok(NormalizationForm::NFD),
                Some(Keyword::NFKC) => Ok(NormalizationForm::NFKC),
                Some(Keyword::NFKD) => Ok(NormalizationForm::NFKD),
                _ => parser.expected_ref("unicode normalization form", parser.peek_token_ref()),
            }
        })?;
        if self.parse_keyword(Keyword::NORMALIZED) {
            return Ok(Expr::IsNormalized {
                expr: Box::new(expr),
                form: normalized_form,
                negated: neg,
            });
        }
        self.expected_ref("unicode normalization form", self.peek_token_ref())
    }

    /// Parse parenthesized enum members, used with `ENUM(...)` type definitions.
    pub fn parse_enum_values(&mut self) -> Result<Vec<EnumMember>, ParserError> {
        self.expect_token(&Token::LParen)?;
        let values = self.parse_comma_separated(|parser| {
            let name = parser.parse_literal_string()?;
            let e = if parser.consume_token(&Token::Eq) {
                let value = parser.parse_number()?;
                EnumMember::NamedValue(name, value)
            } else {
                EnumMember::Name(name)
            };
            Ok(e)
        })?;
        self.expect_token(&Token::RParen)?;

        Ok(values)
    }

    /// Parse a SQL datatype (in the context of a CREATE TABLE statement for example)
    pub fn parse_data_type(&mut self) -> Result<DataType, ParserError> {
        let (ty, trailing_bracket) = self.parse_data_type_helper()?;
        if trailing_bracket.0 {
            return parser_err!(
                format!("unmatched > after parsing data type {ty}"),
                self.peek_token_ref()
            );
        }

        Ok(ty)
    }

    #[cfg_attr(feature = "recursive-protection", recursive::recursive)]
    fn parse_data_type_helper(
        &mut self,
    ) -> Result<(DataType, MatchedTrailingBracket), ParserError> {
        let _guard = self.recursion_counter.try_decrease()?;

        let dialect = self.dialect;
        self.advance_token();
        let next_token = self.get_current_token();
        let next_token_index = self.get_current_index();

        let mut trailing_bracket: MatchedTrailingBracket = false.into();
        let mut data = match &next_token.token {
            Token::Word(w) => match w.keyword {
                Keyword::BOOLEAN => Ok(DataType::Boolean),
                Keyword::BOOL => Ok(DataType::Bool),
                Keyword::FLOAT => {
                    let precision = self.parse_exact_number_optional_precision_scale()?;

                    if self.parse_keyword(Keyword::UNSIGNED) {
                        Ok(DataType::FloatUnsigned(precision))
                    } else {
                        Ok(DataType::Float(precision))
                    }
                }
                Keyword::REAL => {
                    if self.parse_keyword(Keyword::UNSIGNED) {
                        Ok(DataType::RealUnsigned)
                    } else {
                        Ok(DataType::Real)
                    }
                }
                Keyword::FLOAT4 => Ok(DataType::Float4),
                Keyword::FLOAT32 => Ok(DataType::Float32),
                Keyword::FLOAT64 => Ok(DataType::Float64),
                Keyword::FLOAT8 => Ok(DataType::Float8),
                Keyword::DOUBLE => {
                    if self.parse_keyword(Keyword::PRECISION) {
                        if self.parse_keyword(Keyword::UNSIGNED) {
                            Ok(DataType::DoublePrecisionUnsigned)
                        } else {
                            Ok(DataType::DoublePrecision)
                        }
                    } else {
                        let precision = self.parse_exact_number_optional_precision_scale()?;

                        if self.parse_keyword(Keyword::UNSIGNED) {
                            Ok(DataType::DoubleUnsigned(precision))
                        } else {
                            Ok(DataType::Double(precision))
                        }
                    }
                }
                Keyword::TINYINT => {
                    let optional_precision = self.parse_optional_precision();
                    if self.parse_keyword(Keyword::UNSIGNED) {
                        Ok(DataType::TinyIntUnsigned(optional_precision?))
                    } else {
                        if dialect.supports_data_type_signed_suffix() {
                            let _ = self.parse_keyword(Keyword::SIGNED);
                        }
                        Ok(DataType::TinyInt(optional_precision?))
                    }
                }
                Keyword::INT2 => {
                    let optional_precision = self.parse_optional_precision();
                    if self.parse_keyword(Keyword::UNSIGNED) {
                        Ok(DataType::Int2Unsigned(optional_precision?))
                    } else {
                        Ok(DataType::Int2(optional_precision?))
                    }
                }
                Keyword::SMALLINT => {
                    let optional_precision = self.parse_optional_precision();
                    if self.parse_keyword(Keyword::UNSIGNED) {
                        Ok(DataType::SmallIntUnsigned(optional_precision?))
                    } else {
                        if dialect.supports_data_type_signed_suffix() {
                            let _ = self.parse_keyword(Keyword::SIGNED);
                        }
                        Ok(DataType::SmallInt(optional_precision?))
                    }
                }
                Keyword::MEDIUMINT => {
                    let optional_precision = self.parse_optional_precision();
                    if self.parse_keyword(Keyword::UNSIGNED) {
                        Ok(DataType::MediumIntUnsigned(optional_precision?))
                    } else {
                        if dialect.supports_data_type_signed_suffix() {
                            let _ = self.parse_keyword(Keyword::SIGNED);
                        }
                        Ok(DataType::MediumInt(optional_precision?))
                    }
                }
                Keyword::INT => {
                    let optional_precision = self.parse_optional_precision();
                    if self.parse_keyword(Keyword::UNSIGNED) {
                        Ok(DataType::IntUnsigned(optional_precision?))
                    } else {
                        if dialect.supports_data_type_signed_suffix() {
                            let _ = self.parse_keyword(Keyword::SIGNED);
                        }
                        Ok(DataType::Int(optional_precision?))
                    }
                }
                Keyword::INT4 => {
                    let optional_precision = self.parse_optional_precision();
                    if self.parse_keyword(Keyword::UNSIGNED) {
                        Ok(DataType::Int4Unsigned(optional_precision?))
                    } else {
                        Ok(DataType::Int4(optional_precision?))
                    }
                }
                Keyword::INT8 => {
                    let optional_precision = self.parse_optional_precision();
                    if self.parse_keyword(Keyword::UNSIGNED) {
                        Ok(DataType::Int8Unsigned(optional_precision?))
                    } else {
                        Ok(DataType::Int8(optional_precision?))
                    }
                }
                Keyword::INT16 => Ok(DataType::Int16),
                Keyword::INT32 => Ok(DataType::Int32),
                Keyword::INT64 => Ok(DataType::Int64),
                Keyword::INT128 => Ok(DataType::Int128),
                Keyword::INT256 => Ok(DataType::Int256),
                Keyword::INTEGER => {
                    let optional_precision = self.parse_optional_precision();
                    if self.parse_keyword(Keyword::UNSIGNED) {
                        Ok(DataType::IntegerUnsigned(optional_precision?))
                    } else {
                        if dialect.supports_data_type_signed_suffix() {
                            let _ = self.parse_keyword(Keyword::SIGNED);
                        }
                        Ok(DataType::Integer(optional_precision?))
                    }
                }
                Keyword::BIGINT => {
                    let optional_precision = self.parse_optional_precision();
                    if self.parse_keyword(Keyword::UNSIGNED) {
                        Ok(DataType::BigIntUnsigned(optional_precision?))
                    } else {
                        if dialect.supports_data_type_signed_suffix() {
                            let _ = self.parse_keyword(Keyword::SIGNED);
                        }
                        Ok(DataType::BigInt(optional_precision?))
                    }
                }
                Keyword::HUGEINT => Ok(DataType::HugeInt),
                Keyword::UBIGINT => Ok(DataType::UBigInt),
                Keyword::UHUGEINT => Ok(DataType::UHugeInt),
                Keyword::USMALLINT => Ok(DataType::USmallInt),
                Keyword::UTINYINT => Ok(DataType::UTinyInt),
                Keyword::UINT8 => Ok(DataType::UInt8),
                Keyword::UINT16 => Ok(DataType::UInt16),
                Keyword::UINT32 => Ok(DataType::UInt32),
                Keyword::UINT64 => Ok(DataType::UInt64),
                Keyword::UINT128 => Ok(DataType::UInt128),
                Keyword::UINT256 => Ok(DataType::UInt256),
                Keyword::VARCHAR => Ok(DataType::Varchar(self.parse_optional_character_length()?)),
                Keyword::NVARCHAR => {
                    Ok(DataType::Nvarchar(self.parse_optional_character_length()?))
                }
                Keyword::CHARACTER => {
                    if self.parse_keyword(Keyword::VARYING) {
                        Ok(DataType::CharacterVarying(
                            self.parse_optional_character_length()?,
                        ))
                    } else if self.parse_keywords(&[Keyword::LARGE, Keyword::OBJECT]) {
                        Ok(DataType::CharacterLargeObject(
                            self.parse_optional_precision()?,
                        ))
                    } else {
                        Ok(DataType::Character(self.parse_optional_character_length()?))
                    }
                }
                Keyword::CHAR => {
                    if self.parse_keyword(Keyword::VARYING) {
                        Ok(DataType::CharVarying(
                            self.parse_optional_character_length()?,
                        ))
                    } else if self.parse_keywords(&[Keyword::LARGE, Keyword::OBJECT]) {
                        Ok(DataType::CharLargeObject(self.parse_optional_precision()?))
                    } else {
                        Ok(DataType::Char(self.parse_optional_character_length()?))
                    }
                }
                Keyword::CLOB => Ok(DataType::Clob(self.parse_optional_precision()?)),
                Keyword::BINARY => Ok(DataType::Binary(self.parse_optional_precision()?)),
                Keyword::VARBINARY => Ok(DataType::Varbinary(self.parse_optional_binary_length()?)),
                Keyword::BLOB => Ok(DataType::Blob(self.parse_optional_precision()?)),
                Keyword::TINYBLOB => Ok(DataType::TinyBlob),
                Keyword::MEDIUMBLOB => Ok(DataType::MediumBlob),
                Keyword::LONGBLOB => Ok(DataType::LongBlob),
                Keyword::LONG if self.dialect.supports_long_type_as_bigint() => {
                    Ok(DataType::BigInt(None))
                }
                Keyword::BYTES => Ok(DataType::Bytes(self.parse_optional_precision()?)),
                Keyword::BIT => {
                    if self.parse_keyword(Keyword::VARYING) {
                        Ok(DataType::BitVarying(self.parse_optional_precision()?))
                    } else {
                        Ok(DataType::Bit(self.parse_optional_precision()?))
                    }
                }
                Keyword::VARBIT => Ok(DataType::VarBit(self.parse_optional_precision()?)),
                Keyword::UUID => Ok(DataType::Uuid),
                Keyword::DATE => Ok(DataType::Date),
                Keyword::DATE32 => Ok(DataType::Date32),
                Keyword::DATETIME => Ok(DataType::Datetime(self.parse_optional_precision()?)),
                Keyword::DATETIME64 => {
                    self.prev_token();
                    let (precision, time_zone) = self.parse_datetime_64()?;
                    Ok(DataType::Datetime64(precision, time_zone))
                }
                Keyword::TIMESTAMP => {
                    let precision = self.parse_optional_precision()?;
                    let tz = if self.parse_keyword(Keyword::WITH) {
                        self.expect_keywords(&[Keyword::TIME, Keyword::ZONE])?;
                        TimezoneInfo::WithTimeZone
                    } else if self.parse_keyword(Keyword::WITHOUT) {
                        self.expect_keywords(&[Keyword::TIME, Keyword::ZONE])?;
                        TimezoneInfo::WithoutTimeZone
                    } else {
                        TimezoneInfo::None
                    };
                    Ok(DataType::Timestamp(precision, tz))
                }
                Keyword::TIMESTAMPTZ => Ok(DataType::Timestamp(
                    self.parse_optional_precision()?,
                    TimezoneInfo::Tz,
                )),
                Keyword::TIMESTAMP_NTZ => {
                    Ok(DataType::TimestampNtz(self.parse_optional_precision()?))
                }
                Keyword::TIME => {
                    let precision = self.parse_optional_precision()?;
                    let tz = if self.parse_keyword(Keyword::WITH) {
                        self.expect_keywords(&[Keyword::TIME, Keyword::ZONE])?;
                        TimezoneInfo::WithTimeZone
                    } else if self.parse_keyword(Keyword::WITHOUT) {
                        self.expect_keywords(&[Keyword::TIME, Keyword::ZONE])?;
                        TimezoneInfo::WithoutTimeZone
                    } else {
                        TimezoneInfo::None
                    };
                    Ok(DataType::Time(precision, tz))
                }
                Keyword::TIMETZ => Ok(DataType::Time(
                    self.parse_optional_precision()?,
                    TimezoneInfo::Tz,
                )),
                Keyword::INTERVAL => {
                    if self.dialect.supports_interval_options() {
                        let fields = self.maybe_parse_optional_interval_fields()?;
                        let precision = self.parse_optional_precision()?;
                        Ok(DataType::Interval { fields, precision })
                    } else {
                        Ok(DataType::Interval {
                            fields: None,
                            precision: None,
                        })
                    }
                }
                Keyword::JSON => Ok(DataType::JSON),
                Keyword::JSONB => Ok(DataType::JSONB),
                Keyword::REGCLASS => Ok(DataType::Regclass),
                Keyword::STRING => Ok(DataType::String(self.parse_optional_precision()?)),
                Keyword::FIXEDSTRING => {
                    self.expect_token(&Token::LParen)?;
                    let character_length = self.parse_literal_uint()?;
                    self.expect_token(&Token::RParen)?;
                    Ok(DataType::FixedString(character_length))
                }
                Keyword::TEXT => {
                    if let Some(modifiers) = self.parse_optional_type_modifiers()? {
                        Ok(DataType::Custom(
                            ObjectName::from(vec![Ident::new("TEXT")]),
                            modifiers,
                        ))
                    } else {
                        Ok(DataType::Text)
                    }
                }
                Keyword::TINYTEXT => Ok(DataType::TinyText),
                Keyword::MEDIUMTEXT => Ok(DataType::MediumText),
                Keyword::LONGTEXT => Ok(DataType::LongText),
                Keyword::BYTEA => Ok(DataType::Bytea),
                Keyword::NUMERIC => Ok(DataType::Numeric(
                    self.parse_exact_number_optional_precision_scale()?,
                )),
                Keyword::DECIMAL => {
                    let precision = self.parse_exact_number_optional_precision_scale()?;

                    if self.parse_keyword(Keyword::UNSIGNED) {
                        Ok(DataType::DecimalUnsigned(precision))
                    } else {
                        Ok(DataType::Decimal(precision))
                    }
                }
                Keyword::DEC => {
                    let precision = self.parse_exact_number_optional_precision_scale()?;

                    if self.parse_keyword(Keyword::UNSIGNED) {
                        Ok(DataType::DecUnsigned(precision))
                    } else {
                        Ok(DataType::Dec(precision))
                    }
                }
                Keyword::BIGNUMERIC => Ok(DataType::BigNumeric(
                    self.parse_exact_number_optional_precision_scale()?,
                )),
                Keyword::BIGDECIMAL => Ok(DataType::BigDecimal(
                    self.parse_exact_number_optional_precision_scale()?,
                )),
                Keyword::ENUM => Ok(DataType::Enum(self.parse_enum_values()?, None)),
                Keyword::ENUM8 => Ok(DataType::Enum(self.parse_enum_values()?, Some(8))),
                Keyword::ENUM16 => Ok(DataType::Enum(self.parse_enum_values()?, Some(16))),
                Keyword::SET => Ok(DataType::Set(self.parse_string_values()?)),
                Keyword::ARRAY => {
                    if self.dialect.supports_array_typedef_with_parentheses() {
                        if self.peek_token_ref().token == Token::LParen {
                            self.expect_token(&Token::LParen)?;
                            let internal_type = self.parse_data_type()?;
                            let not_null = self.dialect.supports_array_element_not_null()
                                && self.parse_keywords(&[Keyword::NOT, Keyword::NULL]);
                            self.expect_token(&Token::RParen)?;

                            if not_null {
                                Ok(DataType::Array(ArrayElemTypeDef::ParenthesisNotNull(
                                    Box::new(internal_type),
                                )))
                            } else {
                                Ok(DataType::Array(ArrayElemTypeDef::Parenthesis(Box::new(
                                    internal_type,
                                ))))
                            }
                        } else if self.dialect.supports_array_typedef_without_element_type() {
                            Ok(DataType::Array(ArrayElemTypeDef::None))
                        } else {
                            self.expected("(", self.peek_token())
                        }
                    } else if self.dialect.supports_array_typedef_without_element_type() {
                        Ok(DataType::Array(ArrayElemTypeDef::None))
                    } else {
                        self.expect_token(&Token::Lt)?;
                        let (inside_type, _trailing_bracket) =
                            self.parse_data_type_with_optional_collation()?;
                        trailing_bracket = self.expect_closing_angle_bracket(_trailing_bracket)?;
                        Ok(DataType::Array(ArrayElemTypeDef::AngleBracket(Box::new(
                            inside_type,
                        ))))
                    }
                }
                Keyword::OBJECT if self.peek_token_ref().token == Token::LParen => {
                    if let Some(fields) =
                        self.maybe_parse(|parser| parser.parse_structured_object_type_def())?
                    {
                        Ok(DataType::Object(fields))
                    } else {
                        self.prev_token();
                        let type_name = self.parse_object_name(false)?;
                        let modifiers = self.parse_optional_type_modifiers()?.unwrap_or_default();
                        Ok(DataType::Custom(type_name, modifiers))
                    }
                }
                Keyword::STRUCT if dialect_is!(dialect is DuckDbDialect) => {
                    self.prev_token();
                    let field_defs = self.parse_duckdb_struct_type_def()?;
                    Ok(DataType::Struct(field_defs, StructBracketKind::Parentheses))
                }
                Keyword::STRUCT if self.dialect.supports_struct_literal() => {
                    self.prev_token();
                    let (field_defs, _trailing_bracket) =
                        self.parse_struct_type_def(Self::parse_struct_field_def)?;
                    trailing_bracket = _trailing_bracket;
                    Ok(DataType::Struct(
                        field_defs,
                        StructBracketKind::AngleBrackets,
                    ))
                }
                Keyword::UNION if dialect_is!(dialect is DuckDbDialect | GenericDialect) => {
                    self.prev_token();
                    let fields = self.parse_union_type_def()?;
                    Ok(DataType::Union(fields))
                }
                Keyword::NULLABLE if dialect_is!(dialect is ClickHouseDialect | GenericDialect) => {
                    Ok(self.parse_sub_type(DataType::Nullable)?)
                }
                Keyword::LOWCARDINALITY if dialect_is!(dialect is ClickHouseDialect | GenericDialect) => {
                    Ok(self.parse_sub_type(DataType::LowCardinality)?)
                }
                Keyword::MAP if self.dialect.supports_map_literal_with_angle_brackets() => {
                    self.expect_token(&Token::Lt)?;
                    let (key_data_type, key_trailing_bracket) =
                        self.parse_data_type_with_optional_collation()?;
                    if key_trailing_bracket.0 {
                        return parser_err!(
                            format!("unmatched > after parsing data type {key_data_type}"),
                            self.peek_token_ref()
                        );
                    }
                    self.expect_token(&Token::Comma)?;
                    let (value_data_type, _trailing_bracket) =
                        self.parse_data_type_with_optional_collation()?;
                    trailing_bracket = self.expect_closing_angle_bracket(_trailing_bracket)?;
                    Ok(DataType::Map(
                        Box::new(key_data_type),
                        Box::new(value_data_type),
                        MapBracketKind::AngleBrackets,
                    ))
                }
                Keyword::MAP if self.dialect.supports_map_typedef_with_parentheses() => {
                    self.prev_token();
                    let (key_data_type, value_data_type, value_not_null) =
                        self.parse_parenthesized_map_type_def()?;
                    let bracket = if value_not_null {
                        MapBracketKind::ParenthesesNotNull
                    } else {
                        MapBracketKind::Parentheses
                    };
                    Ok(DataType::Map(
                        Box::new(key_data_type),
                        Box::new(value_data_type),
                        bracket,
                    ))
                }
                Keyword::NESTED if dialect_is!(dialect is ClickHouseDialect | GenericDialect) => {
                    self.expect_token(&Token::LParen)?;
                    let field_defs = self.parse_comma_separated(Parser::parse_column_def)?;
                    self.expect_token(&Token::RParen)?;
                    Ok(DataType::Nested(field_defs))
                }
                Keyword::TUPLE if dialect_is!(dialect is ClickHouseDialect | GenericDialect) => {
                    self.prev_token();
                    let field_defs = self.parse_click_house_tuple_def()?;
                    Ok(DataType::Tuple(field_defs))
                }
                Keyword::TRIGGER => Ok(DataType::Trigger),
                Keyword::ANY if self.peek_keyword(Keyword::TYPE) => {
                    let _ = self.parse_keyword(Keyword::TYPE);
                    Ok(DataType::AnyType)
                }
                Keyword::TABLE => {
                    // an LParen after the TABLE keyword indicates that table columns are being defined
                    // whereas no LParen indicates an anonymous table expression will be returned
                    if self.peek_token_ref().token == Token::LParen {
                        let columns = self.parse_returns_table_columns()?;
                        Ok(DataType::Table(Some(columns)))
                    } else {
                        Ok(DataType::Table(None))
                    }
                }
                Keyword::SIGNED => {
                    if self.parse_keyword(Keyword::INTEGER) {
                        Ok(DataType::SignedInteger)
                    } else {
                        Ok(DataType::Signed)
                    }
                }
                Keyword::UNSIGNED => {
                    if self.parse_keyword(Keyword::INTEGER) {
                        Ok(DataType::UnsignedInteger)
                    } else {
                        Ok(DataType::Unsigned)
                    }
                }
                Keyword::TSVECTOR if dialect_is!(dialect is PostgreSqlDialect | GenericDialect) => {
                    Ok(DataType::TsVector)
                }
                Keyword::TSQUERY if dialect_is!(dialect is PostgreSqlDialect | GenericDialect) => {
                    Ok(DataType::TsQuery)
                }
                _ => {
                    self.prev_token();
                    let type_name = self.parse_object_name(false)?;
                    if let Some(modifiers) = self.parse_optional_type_modifiers()? {
                        Ok(DataType::Custom(type_name, modifiers))
                    } else {
                        Ok(DataType::Custom(type_name, vec![]))
                    }
                }
            },
            _ => self.expected_at("a data type name", next_token_index),
        }?;

        // The `>>` that closed this type also closed the enclosing one, so any suffix belongs to that.
        if trailing_bracket.0 {
            return Ok((data, trailing_bracket));
        }

        if self.is_zerofill_allowed(next_token_index) && self.parse_keyword(Keyword::ZEROFILL) {
            data = DataType::Zerofill(Box::new(data));
        }

        if self.dialect.supports_array_typedef_with_brackets() {
            while self.consume_token(&Token::LBracket) {
                // Parse optional array data type size
                let size = self.maybe_parse(|p| p.parse_literal_uint())?;
                self.expect_token(&Token::RBracket)?;
                data = DataType::Array(ArrayElemTypeDef::SquareBracket(Box::new(data), size))
            }
        }

        // Type-qualified array, e.g. `INT ARRAY` or `INT ARRAY[3]`. One-dimensional
        // with a single optional size. The `ARRAY` keyword is unambiguous everywhere.
        if self.parse_keyword(Keyword::ARRAY) {
            let size = if self.consume_token(&Token::LBracket) {
                let size = self.maybe_parse(|p| p.parse_literal_uint())?;
                self.expect_token(&Token::RBracket)?;
                size
            } else {
                None
            };
            data = DataType::Array(ArrayElemTypeDef::Qualified(Box::new(data), size));
        }

        Ok((data, trailing_bracket))
    }

    fn parse_data_type_with_optional_collation(
        &mut self,
    ) -> Result<(DataType, MatchedTrailingBracket), ParserError> {
        let (mut data_type, trailing_bracket) = self.parse_data_type_helper()?;
        if !trailing_bracket.0
            && self.dialect.supports_data_type_collation()
            && self.parse_keyword(Keyword::COLLATE)
        {
            data_type = DataType::Collate(Box::new(data_type), self.parse_object_name(false)?);
        }
        Ok((data_type, trailing_bracket))
    }

    fn is_zerofill_allowed(&self, token_index: usize) -> bool {
        if !self.dialect.supports_data_type_zerofill_suffix() {
            return false;
        }
        match &self.token_at(token_index).token {
            Token::Word(w) => matches!(
                w.keyword,
                Keyword::TINYINT
                    | Keyword::SMALLINT
                    | Keyword::MEDIUMINT
                    | Keyword::INT
                    | Keyword::INTEGER
                    | Keyword::BIGINT
                    | Keyword::INT2
                    | Keyword::INT4
                    | Keyword::INT8
                    | Keyword::DECIMAL
                    | Keyword::DEC
                    | Keyword::NUMERIC
                    | Keyword::FLOAT
                    | Keyword::FLOAT4
                    | Keyword::FLOAT8
                    | Keyword::DOUBLE
                    | Keyword::REAL
            ),
            _ => false,
        }
    }

    fn parse_returns_table_column(&mut self) -> Result<ColumnDef, ParserError> {
        self.parse_column_def()
    }

    fn parse_returns_table_columns(&mut self) -> Result<Vec<ColumnDef>, ParserError> {
        self.expect_token(&Token::LParen)?;
        let columns = self.parse_comma_separated(Parser::parse_returns_table_column)?;
        self.expect_token(&Token::RParen)?;
        Ok(columns)
    }

    /// Parse a parenthesized, comma-separated list of single-quoted strings.
    pub fn parse_string_values(&mut self) -> Result<Vec<String>, ParserError> {
        self.expect_token(&Token::LParen)?;
        let mut values = Vec::new();
        loop {
            let next_token = self.next_token();
            match next_token.token {
                Token::SingleQuotedString(value) => values.push(value),
                _ => self.expected("a string", next_token)?,
            }
            let next_token = self.next_token();
            match next_token.token {
                Token::Comma => (),
                Token::RParen => break,
                _ => self.expected(", or }", next_token)?,
            }
        }
        Ok(values)
    }

    /// Strictly parse `identifier AS identifier`
    pub fn parse_identifier_with_alias(&mut self) -> Result<IdentWithAlias, ParserError> {
        let ident = self.parse_identifier()?;
        self.expect_keyword_is(Keyword::AS)?;
        let alias = self.parse_identifier()?;
        Ok(IdentWithAlias { ident, alias })
    }

    /// Parse `identifier [AS] identifier` where the AS keyword is optional
    fn parse_identifier_with_optional_alias(&mut self) -> Result<IdentWithAlias, ParserError> {
        let ident = self.parse_identifier()?;
        let _after_as = self.parse_keyword(Keyword::AS);
        let alias = self.parse_identifier()?;
        Ok(IdentWithAlias { ident, alias })
    }

    /// Parse comma-separated list of parenthesized queries for pipe operators
    fn parse_pipe_operator_queries(&mut self) -> Result<Vec<Query>, ParserError> {
        self.parse_comma_separated(|parser| {
            parser.expect_token(&Token::LParen)?;
            let query = parser.parse_query()?;
            parser.expect_token(&Token::RParen)?;
            Ok(*query)
        })
    }

    /// Parse set quantifier for pipe operators that require DISTINCT. E.g. INTERSECT and EXCEPT
    fn parse_distinct_required_set_quantifier(
        &mut self,
        operator_name: &str,
    ) -> Result<SetQuantifier, ParserError> {
        let quantifier = self.parse_set_quantifier(&Some(SetOperator::Intersect));
        match quantifier {
            SetQuantifier::Distinct | SetQuantifier::DistinctByName => Ok(quantifier),
            _ => Err(ParserError::ParserError(format!(
                "{operator_name} pipe operator requires DISTINCT modifier",
            ))),
        }
    }

    /// Parse optional identifier alias (with or without AS keyword)
    fn parse_identifier_optional_alias(&mut self) -> Result<Option<Ident>, ParserError> {
        if self.parse_keyword(Keyword::AS) {
            Ok(Some(self.parse_identifier()?))
        } else {
            // Check if the next token is an identifier (implicit alias)
            self.maybe_parse(|parser| parser.parse_identifier())
        }
    }

    /// Optionally parses an alias for a select list item
    fn maybe_parse_select_item_alias(&mut self) -> Result<Option<Ident>, ParserError> {
        fn validator(explicit: bool, kw: &Keyword, parser: &mut Parser) -> bool {
            parser.dialect.is_select_item_alias(explicit, kw, parser)
        }
        self.parse_optional_alias_inner(None, validator)
    }

    /// Optionally parses an alias for a table like in `... FROM generate_series(1, 10) AS t (col)`.
    /// In this case, the alias is allowed to optionally name the columns in the table, in
    /// addition to the table itself.
    pub fn maybe_parse_table_alias(&mut self) -> Result<Option<TableAlias>, ParserError> {
        fn validator(explicit: bool, kw: &Keyword, parser: &mut Parser) -> bool {
            parser.dialect.is_table_factor_alias(explicit, kw, parser)
        }
        let explicit = self.peek_keyword(Keyword::AS);
        match self.parse_optional_alias_inner(None, validator)? {
            Some(name) => {
                let columns = self.parse_table_alias_column_defs()?;
                let at = if self.dialect.supports_partiql() && self.parse_keyword(Keyword::AT) {
                    Some(self.parse_identifier()?)
                } else {
                    None
                };
                Ok(Some(TableAlias {
                    explicit,
                    name,
                    columns,
                    at,
                }))
            }
            None => Ok(None),
        }
    }

    fn parse_table_index_hints(&mut self) -> Result<Vec<TableIndexHints>, ParserError> {
        let mut hints = vec![];
        while let Some(hint_type) =
            self.parse_one_of_keywords(&[Keyword::USE, Keyword::IGNORE, Keyword::FORCE])
        {
            let hint_type = match hint_type {
                Keyword::USE => TableIndexHintType::Use,
                Keyword::IGNORE => TableIndexHintType::Ignore,
                Keyword::FORCE => TableIndexHintType::Force,
                _ => {
                    return self.expected_ref(
                        "expected to match USE/IGNORE/FORCE keyword",
                        self.peek_token_ref(),
                    )
                }
            };
            let index_type = match self.parse_one_of_keywords(&[Keyword::INDEX, Keyword::KEY]) {
                Some(Keyword::INDEX) => TableIndexType::Index,
                Some(Keyword::KEY) => TableIndexType::Key,
                _ => {
                    return self
                        .expected_ref("expected to match INDEX/KEY keyword", self.peek_token_ref())
                }
            };
            let for_clause = if self.parse_keyword(Keyword::FOR) {
                let clause = if self.parse_keyword(Keyword::JOIN) {
                    TableIndexHintForClause::Join
                } else if self.parse_keywords(&[Keyword::ORDER, Keyword::BY]) {
                    TableIndexHintForClause::OrderBy
                } else if self.parse_keywords(&[Keyword::GROUP, Keyword::BY]) {
                    TableIndexHintForClause::GroupBy
                } else {
                    return self.expected_ref(
                        "expected to match FOR/ORDER BY/GROUP BY table hint in for clause",
                        self.peek_token_ref(),
                    );
                };
                Some(clause)
            } else {
                None
            };

            self.expect_token(&Token::LParen)?;
            let index_names = if self.peek_token_ref().token != Token::RParen {
                self.parse_comma_separated(Parser::parse_identifier)?
            } else {
                vec![]
            };
            self.expect_token(&Token::RParen)?;
            hints.push(TableIndexHints {
                hint_type,
                index_type,
                for_clause,
                index_names,
            });
        }
        Ok(hints)
    }

    /// Wrapper for parse_optional_alias_inner, left for backwards-compatibility
    /// but new flows should use the context-specific methods such as `maybe_parse_select_item_alias`
    /// and `maybe_parse_table_alias`.
    pub fn parse_optional_alias(
        &mut self,
        reserved_kwds: &[Keyword],
    ) -> Result<Option<Ident>, ParserError> {
        fn validator(_explicit: bool, _kw: &Keyword, _parser: &mut Parser) -> bool {
            false
        }
        self.parse_optional_alias_inner(Some(reserved_kwds), validator)
    }

    /// Parses an optional alias after a SQL element such as a select list item
    /// or a table name.
    ///
    /// This method accepts an optional list of reserved keywords or a function
    /// to call to validate if a keyword should be parsed as an alias, to allow
    /// callers to customize the parsing logic based on their context.
    fn parse_optional_alias_inner<F>(
        &mut self,
        reserved_kwds: Option<&[Keyword]>,
        validator: F,
    ) -> Result<Option<Ident>, ParserError>
    where
        F: Fn(bool, &Keyword, &mut Parser) -> bool,
    {
        let after_as = self.parse_keyword(Keyword::AS);

        let next_token = self.next_token();
        match next_token.token {
            // Accepts a keyword as an alias if the AS keyword explicitly indicate an alias or if the
            // caller provided a list of reserved keywords and the keyword is not on that list.
            Token::Word(w)
                if reserved_kwds.is_some()
                    && (after_as || reserved_kwds.is_some_and(|x| !x.contains(&w.keyword))) =>
            {
                Ok(Some(w.into_ident(next_token.span)))
            }
            // Accepts a keyword as alias based on the caller's context, such as to what SQL element
            // this word is a potential alias of using the validator call-back. This allows for
            // dialect-specific logic.
            Token::Word(w) if validator(after_as, &w.keyword, self) => {
                Ok(Some(w.into_ident(next_token.span)))
            }
            Token::SingleQuotedString(s) if self.dialect.supports_string_literal_alias() => {
                Ok(Some(Ident::with_quote('\'', s)))
            }
            Token::DoubleQuotedString(s) => Ok(Some(Ident::with_quote('\"', s))),
            _ => {
                if after_as {
                    return self.expected("an identifier after AS", next_token);
                }
                self.prev_token();
                Ok(None) // no alias found
            }
        }
    }

    /// Parse an optional `GROUP BY` clause, returning `Some(GroupByExpr)` when present.
    pub fn parse_optional_group_by(&mut self) -> Result<Option<GroupByExpr>, ParserError> {
        if self.parse_keywords(&[Keyword::GROUP, Keyword::BY]) {
            let expressions = if self.parse_keyword(Keyword::ALL) {
                None
            } else {
                Some(self.parse_comma_separated(Parser::parse_group_by_expr)?)
            };

            let mut modifiers = vec![];
            if self.dialect.supports_group_by_with_modifier() {
                loop {
                    if !self.parse_keyword(Keyword::WITH) {
                        break;
                    }
                    let keyword = self.expect_one_of_keywords(&[
                        Keyword::ROLLUP,
                        Keyword::CUBE,
                        Keyword::TOTALS,
                    ])?;
                    modifiers.push(match keyword {
                        Keyword::ROLLUP => GroupByWithModifier::Rollup,
                        Keyword::CUBE => GroupByWithModifier::Cube,
                        Keyword::TOTALS => GroupByWithModifier::Totals,
                        _ => {
                            return parser_err!(
                                "BUG: expected to match GroupBy modifier keyword",
                                self.peek_token_ref().span.start
                            )
                        }
                    });
                }
            }
            if self.parse_keywords(&[Keyword::GROUPING, Keyword::SETS]) {
                self.expect_token(&Token::LParen)?;
                let result = self.parse_comma_separated(|p| {
                    if p.peek_token_ref().token == Token::LParen {
                        p.parse_tuple(true, true)
                    } else {
                        Ok(vec![p.parse_expr()?])
                    }
                })?;
                self.expect_token(&Token::RParen)?;
                modifiers.push(GroupByWithModifier::GroupingSets(Expr::GroupingSets(
                    result,
                )));
            };
            let group_by = match expressions {
                None => GroupByExpr::All(modifiers),
                Some(exprs) => GroupByExpr::Expressions(exprs, modifiers),
            };
            Ok(Some(group_by))
        } else {
            Ok(None)
        }
    }

    /// Parse an optional `ORDER BY` clause, returning `Some(OrderBy)` when present.
    pub fn parse_optional_order_by(&mut self) -> Result<Option<OrderBy>, ParserError> {
        if self.parse_keywords(&[Keyword::ORDER, Keyword::BY]) {
            let order_by =
                if self.dialect.supports_order_by_all() && self.parse_keyword(Keyword::ALL) {
                    let order_by_options = self.parse_order_by_options()?;
                    OrderBy {
                        kind: OrderByKind::All(order_by_options),
                        interpolate: None,
                    }
                } else {
                    let exprs = self.parse_comma_separated(Parser::parse_order_by_expr)?;
                    let interpolate = if self.dialect.supports_interpolate() {
                        self.parse_interpolations()?
                    } else {
                        None
                    };
                    OrderBy {
                        kind: OrderByKind::Expressions(exprs),
                        interpolate,
                    }
                };
            Ok(Some(order_by))
        } else {
            Ok(None)
        }
    }

    fn parse_optional_limit_clause(&mut self) -> Result<Option<LimitClause>, ParserError> {
        let mut offset = if self.parse_keyword(Keyword::OFFSET) {
            Some(self.parse_offset()?)
        } else {
            None
        };

        let (limit, limit_by) = if self.parse_keyword(Keyword::LIMIT) {
            let expr = self.parse_limit()?;

            if self.dialect.supports_limit_comma()
                && offset.is_none()
                && expr.is_some() // ALL not supported with comma
                && self.consume_token(&Token::Comma)
            {
                let offset = expr.ok_or_else(|| {
                    ParserError::ParserError(
                        "Missing offset for LIMIT <offset>, <limit>".to_string(),
                    )
                })?;
                return Ok(Some(LimitClause::OffsetCommaLimit {
                    offset,
                    limit: self.parse_expr()?,
                }));
            }

            let limit_by = if self.dialect.supports_limit_by() && self.parse_keyword(Keyword::BY) {
                Some(self.parse_comma_separated(Parser::parse_expr)?)
            } else {
                None
            };

            (Some(expr), limit_by)
        } else {
            (None, None)
        };

        if offset.is_none() && limit.is_some() && self.parse_keyword(Keyword::OFFSET) {
            offset = Some(self.parse_offset()?);
        }

        if offset.is_some() || (limit.is_some() && limit != Some(None)) || limit_by.is_some() {
            Ok(Some(LimitClause::LimitOffset {
                limit: limit.unwrap_or_default(),
                offset,
                limit_by: limit_by.unwrap_or_default(),
            }))
        } else {
            Ok(None)
        }
    }

    /// Parse a table object for insertion
    /// e.g. `some_database.some_table` or `FUNCTION some_table_func(...)`
    pub fn parse_table_object(&mut self) -> Result<TableObject, ParserError> {
        if self.dialect.supports_insert_table_function() && self.parse_keyword(Keyword::FUNCTION) {
            let fn_name = self.parse_object_name(false)?;
            self.parse_function_call(fn_name)
                .map(TableObject::TableFunction)
        } else if self.dialect.supports_insert_table_query() && self.peek_subquery_or_cte_start() {
            self.parse_parenthesized(|p| p.parse_query())
                .map(TableObject::TableQuery)
        } else {
            self.parse_object_name(false).map(TableObject::TableName)
        }
    }

    /// Parse a possibly qualified, possibly quoted identifier, e.g.
    /// `foo` or `myschema."table"
    ///
    /// The `in_table_clause` parameter indicates whether the object name is a table in a FROM, JOIN,
    /// or similar table clause. Currently, this is used only to support unquoted hyphenated identifiers
    /// in this context on BigQuery.
    pub fn parse_object_name(&mut self, in_table_clause: bool) -> Result<ObjectName, ParserError> {
        self.parse_object_name_inner(in_table_clause, false)
    }

    /// Parse a possibly qualified, possibly quoted identifier, e.g.
    /// `foo` or `myschema."table"
    ///
    /// The `in_table_clause` parameter indicates whether the object name is a table in a FROM, JOIN,
    /// or similar table clause. Currently, this is used only to support unquoted hyphenated identifiers
    /// in this context on BigQuery.
    ///
    /// The `allow_wildcards` parameter indicates whether to allow for wildcards in the object name
    /// e.g. *, *.*, `foo`.*, or "foo"."bar"
    fn parse_object_name_inner(
        &mut self,
        in_table_clause: bool,
        allow_wildcards: bool,
    ) -> Result<ObjectName, ParserError> {
        let mut parts = vec![];
        if dialect_of!(self is BigQueryDialect) && in_table_clause {
            loop {
                let (ident, end_with_period) = self.parse_unquoted_hyphenated_identifier()?;
                parts.push(ObjectNamePart::Identifier(ident));
                if !self.consume_token(&Token::Period) && !end_with_period {
                    break;
                }
            }
        } else {
            loop {
                if allow_wildcards && self.peek_token_ref().token == Token::Mul {
                    let span = self.next_token().span;
                    parts.push(ObjectNamePart::Identifier(Ident {
                        value: Token::Mul.to_string(),
                        quote_style: None,
                        span,
                    }));
                } else if dialect_of!(self is BigQueryDialect) && in_table_clause {
                    let (ident, end_with_period) = self.parse_unquoted_hyphenated_identifier()?;
                    parts.push(ObjectNamePart::Identifier(ident));
                    if !self.consume_token(&Token::Period) && !end_with_period {
                        break;
                    }
                } else if self.dialect.supports_object_name_double_dot_notation()
                    && parts.len() == 1
                    && matches!(self.peek_token_ref().token, Token::Period)
                {
                    // Empty string here means default schema
                    parts.push(ObjectNamePart::Identifier(Ident::new("")));
                } else {
                    let ident = self.parse_identifier()?;
                    let part = if self
                        .dialect
                        .is_identifier_generating_function_name(&ident, &parts)
                    {
                        self.expect_token(&Token::LParen)?;
                        let args: Vec<FunctionArg> =
                            self.parse_comma_separated0(Self::parse_function_args, Token::RParen)?;
                        self.expect_token(&Token::RParen)?;
                        ObjectNamePart::Function(ObjectNamePartFunction { name: ident, args })
                    } else {
                        ObjectNamePart::Identifier(ident)
                    };
                    parts.push(part);
                }

                if !self.consume_token(&Token::Period) {
                    break;
                }
            }
        }

        // BigQuery accepts any number of quoted identifiers of a table name.
        // https://cloud.google.com/bigquery/docs/reference/standard-sql/lexical#quoted_identifiers
        if dialect_of!(self is BigQueryDialect)
            && parts.iter().any(|part| {
                part.as_ident()
                    .is_some_and(|ident| ident.value.contains('.'))
            })
        {
            parts = parts
                .into_iter()
                .flat_map(|part| match part.as_ident() {
                    Some(ident) => ident
                        .value
                        .split('.')
                        .map(|value| {
                            ObjectNamePart::Identifier(Ident {
                                value: value.into(),
                                quote_style: ident.quote_style,
                                span: ident.span,
                            })
                        })
                        .collect::<Vec<_>>(),
                    None => vec![part],
                })
                .collect()
        }

        Ok(ObjectName(parts))
    }

    /// Parse identifiers
    pub fn parse_identifiers(&mut self) -> Result<Vec<Ident>, ParserError> {
        let mut idents = vec![];
        loop {
            let token = self.peek_token_ref();
            match &token.token {
                Token::Word(w) => {
                    idents.push(w.to_ident(token.span));
                }
                Token::EOF | Token::Eq | Token::SemiColon | Token::VerticalBarRightAngleBracket => {
                    break
                }
                _ => {}
            }
            self.advance_token();
        }
        Ok(idents)
    }

    /// Parse identifiers of form ident1[.identN]*
    ///
    /// Similar in functionality to [parse_identifiers], with difference
    /// being this function is much more strict about parsing a valid multipart identifier, not
    /// allowing extraneous tokens to be parsed, otherwise it fails.
    ///
    /// For example:
    ///
    /// ```rust
    /// use sqlparser::ast::Ident;
    /// use sqlparser::dialect::GenericDialect;
    /// use sqlparser::parser::Parser;
    ///
    /// let dialect = GenericDialect {};
    /// let expected = vec![Ident::new("one"), Ident::new("two")];
    ///
    /// // expected usage
    /// let sql = "one.two";
    /// let mut parser = Parser::new(&dialect).try_with_sql(sql).unwrap();
    /// let actual = parser.parse_multipart_identifier().unwrap();
    /// assert_eq!(&actual, &expected);
    ///
    /// // parse_identifiers is more loose on what it allows, parsing successfully
    /// let sql = "one + two";
    /// let mut parser = Parser::new(&dialect).try_with_sql(sql).unwrap();
    /// let actual = parser.parse_identifiers().unwrap();
    /// assert_eq!(&actual, &expected);
    ///
    /// // expected to strictly fail due to + separator
    /// let sql = "one + two";
    /// let mut parser = Parser::new(&dialect).try_with_sql(sql).unwrap();
    /// let actual = parser.parse_multipart_identifier().unwrap_err();
    /// assert_eq!(
    ///     actual.to_string(),
    ///     "sql parser error: Unexpected token in identifier: +"
    /// );
    /// ```
    ///
    /// [parse_identifiers]: Parser::parse_identifiers
    pub fn parse_multipart_identifier(&mut self) -> Result<Vec<Ident>, ParserError> {
        let mut idents = vec![];

        // expecting at least one word for identifier
        let next_token = self.next_token();
        match next_token.token {
            Token::Word(w) => idents.push(w.into_ident(next_token.span)),
            Token::EOF => {
                return Err(ParserError::ParserError(
                    "Empty input when parsing identifier".to_string(),
                ))?
            }
            token => {
                return Err(ParserError::ParserError(format!(
                    "Unexpected token in identifier: {token}"
                )))?
            }
        };

        // parse optional next parts if exist
        loop {
            match self.next_token().token {
                // ensure that optional period is succeeded by another identifier
                Token::Period => {
                    let next_token = self.next_token();
                    match next_token.token {
                        Token::Word(w) => idents.push(w.into_ident(next_token.span)),
                        Token::EOF => {
                            return Err(ParserError::ParserError(
                                "Trailing period in identifier".to_string(),
                            ))?
                        }
                        token => {
                            return Err(ParserError::ParserError(format!(
                                "Unexpected token following period in identifier: {token}"
                            )))?
                        }
                    }
                }
                Token::EOF => break,
                token => {
                    Err(ParserError::ParserError(format!(
                        "Unexpected token in identifier: {token}"
                    )))?;
                }
            }
        }

        Ok(idents)
    }

    /// Parse a simple one-word identifier (possibly quoted, possibly a keyword)
    pub fn parse_identifier(&mut self) -> Result<Ident, ParserError> {
        let next_token = self.next_token();
        match next_token.token {
            Token::Word(w) => Ok(w.into_ident(next_token.span)),
            Token::SingleQuotedString(s) => {
                Ok(Ident::with_quote_and_span('\'', next_token.span, s))
            }
            Token::DoubleQuotedString(s) => {
                Ok(Ident::with_quote_and_span('\"', next_token.span, s))
            }
            _ => self.expected("identifier", next_token),
        }
    }

    /// On BigQuery, hyphens are permitted in unquoted identifiers inside of a FROM or
    /// TABLE clause.
    ///
    /// The first segment must be an ordinary unquoted identifier, e.g. it must not start
    /// with a digit. Subsequent segments are either must either be valid identifiers or
    /// integers, e.g. foo-123 is allowed, but foo-123a is not.
    ///
    /// [BigQuery-lexical](https://cloud.google.com/bigquery/docs/reference/standard-sql/lexical)
    ///
    /// Return a tuple of the identifier and a boolean indicating it ends with a period.
    fn parse_unquoted_hyphenated_identifier(&mut self) -> Result<(Ident, bool), ParserError> {
        match self.peek_token().token {
            Token::Word(w) => {
                let quote_style_is_none = w.quote_style.is_none();
                let mut requires_whitespace = false;
                let mut ident = w.into_ident(self.next_token().span);
                if quote_style_is_none {
                    while matches!(self.peek_token_no_skip().token, Token::Minus) {
                        self.next_token();
                        ident.value.push('-');

                        let token = self
                            .next_token_no_skip()
                            .cloned()
                            .unwrap_or(TokenWithSpan::wrap(Token::EOF));
                        requires_whitespace = match token.token {
                            Token::Word(next_word) if next_word.quote_style.is_none() => {
                                ident.value.push_str(&next_word.value);
                                false
                            }
                            Token::Number(s, false) => {
                                // A number token can represent a decimal value ending with a period, e.g., `Number('123.')`.
                                // However, for an [ObjectName], it is part of a hyphenated identifier, e.g., `foo-123.bar`.
                                //
                                // If a number token is followed by a period, it is part of an [ObjectName].
                                // Return the identifier with `true` if the number token is followed by a period, indicating that
                                // parsing should continue for the next part of the hyphenated identifier.
                                if s.ends_with('.') {
                                    let Some(s) = s.split('.').next().filter(|s| {
                                        !s.is_empty() && s.chars().all(|c| c.is_ascii_digit())
                                    }) else {
                                        return self.expected(
                                            "continuation of hyphenated identifier",
                                            TokenWithSpan::new(Token::Number(s, false), token.span),
                                        );
                                    };
                                    ident.value.push_str(s);
                                    return Ok((ident, true));
                                } else {
                                    ident.value.push_str(&s);
                                }
                                // If next token is period, then it is part of an ObjectName and we don't expect whitespace
                                // after the number.
                                !matches!(self.peek_token_ref().token, Token::Period)
                            }
                            _ => {
                                return self
                                    .expected("continuation of hyphenated identifier", token);
                            }
                        }
                    }

                    // If the last segment was a number, we must check that it's followed by whitespace,
                    // otherwise foo-123a will be parsed as `foo-123` with the alias `a`.
                    if requires_whitespace {
                        let token = self.next_token();
                        if !matches!(token.token, Token::EOF | Token::Whitespace(_)) {
                            return self
                                .expected("whitespace following hyphenated identifier", token);
                        }
                    }
                }
                Ok((ident, false))
            }
            _ => Ok((self.parse_identifier()?, false)),
        }
    }

    /// Parses a parenthesized, comma-separated list of column definitions within a view.
    fn parse_view_columns(&mut self) -> Result<Vec<ViewColumnDef>, ParserError> {
        if self.consume_token(&Token::LParen) {
            if self.peek_token_ref().token == Token::RParen {
                self.next_token();
                Ok(vec![])
            } else {
                let cols = self.parse_comma_separated_with_trailing_commas(
                    Parser::parse_view_column,
                    self.dialect.supports_column_definition_trailing_commas(),
                    Self::is_reserved_for_column_alias,
                )?;
                self.expect_token(&Token::RParen)?;
                Ok(cols)
            }
        } else {
            Ok(vec![])
        }
    }

    /// Parses a column definition within a view.
    fn parse_view_column(&mut self) -> Result<ViewColumnDef, ParserError> {
        let name = self.parse_identifier()?;
        let options = self.parse_view_column_options()?;
        let data_type = if dialect_of!(self is ClickHouseDialect) {
            Some(self.parse_data_type()?)
        } else {
            None
        };
        Ok(ViewColumnDef {
            name,
            data_type,
            options,
        })
    }

    fn parse_view_column_options(&mut self) -> Result<Option<ColumnOptions>, ParserError> {
        let mut options = Vec::new();
        loop {
            let option = self.parse_optional_column_option()?;
            if let Some(option) = option {
                options.push(option);
            } else {
                break;
            }
        }
        if options.is_empty() {
            Ok(None)
        } else if self.dialect.supports_space_separated_column_options() {
            Ok(Some(ColumnOptions::SpaceSeparated(options)))
        } else {
            Ok(Some(ColumnOptions::CommaSeparated(options)))
        }
    }

    /// Parses a parenthesized comma-separated list of unqualified, possibly quoted identifiers.
    /// For example: `(col1, "col 2", ...)`
    pub fn parse_parenthesized_column_list(
        &mut self,
        optional: IsOptional,
        allow_empty: bool,
    ) -> Result<Vec<Ident>, ParserError> {
        self.parse_parenthesized_column_list_inner(optional, allow_empty, |p| p.parse_identifier())
    }

    /// Parse a parenthesized list of compound identifiers as expressions.
    pub fn parse_parenthesized_compound_identifier_list(
        &mut self,
        optional: IsOptional,
        allow_empty: bool,
    ) -> Result<Vec<Expr>, ParserError> {
        self.parse_parenthesized_column_list_inner(optional, allow_empty, |p| {
            Ok(Expr::CompoundIdentifier(
                p.parse_period_separated(|p| p.parse_identifier())?,
            ))
        })
    }

    /// Parses a parenthesized comma-separated list of index columns, which can be arbitrary
    /// expressions with ordering information (and an opclass in some dialects).
    fn parse_parenthesized_index_column_list(&mut self) -> Result<Vec<IndexColumn>, ParserError> {
        self.parse_parenthesized_column_list_inner(Mandatory, false, |p| {
            p.parse_create_index_expr()
        })
    }

    /// Parses a parenthesized comma-separated list of qualified, possibly quoted identifiers.
    /// For example: `(db1.sc1.tbl1.col1, db1.sc1.tbl1."col 2", ...)`
    pub fn parse_parenthesized_qualified_column_list(
        &mut self,
        optional: IsOptional,
        allow_empty: bool,
    ) -> Result<Vec<ObjectName>, ParserError> {
        self.parse_parenthesized_column_list_inner(optional, allow_empty, |p| {
            p.parse_object_name(true)
        })
    }

    /// Parses a parenthesized comma-separated list of columns using
    /// the provided function to parse each element.
    fn parse_parenthesized_column_list_inner<F, T>(
        &mut self,
        optional: IsOptional,
        allow_empty: bool,
        mut f: F,
    ) -> Result<Vec<T>, ParserError>
    where
        F: FnMut(&mut Parser) -> Result<T, ParserError>,
    {
        if self.consume_token(&Token::LParen) {
            if allow_empty && self.peek_token_ref().token == Token::RParen {
                self.next_token();
                Ok(vec![])
            } else {
                let cols = self.parse_comma_separated(|p| f(p))?;
                self.expect_token(&Token::RParen)?;
                Ok(cols)
            }
        } else if optional == Optional {
            Ok(vec![])
        } else {
            self.expected_ref("a list of columns in parentheses", self.peek_token_ref())
        }
    }

    /// Parses a parenthesized comma-separated list of table alias column definitions.
    fn parse_table_alias_column_defs(&mut self) -> Result<Vec<TableAliasColumnDef>, ParserError> {
        if self.consume_token(&Token::LParen) {
            let cols = self.parse_comma_separated(|p| {
                let name = p.parse_identifier()?;
                let data_type = p.maybe_parse(|p| p.parse_data_type())?;
                Ok(TableAliasColumnDef { name, data_type })
            })?;
            self.expect_token(&Token::RParen)?;
            Ok(cols)
        } else {
            Ok(vec![])
        }
    }

    /// Parse an unsigned precision value enclosed in parentheses, e.g. `(10)`.
    pub fn parse_precision(&mut self) -> Result<u64, ParserError> {
        self.expect_token(&Token::LParen)?;
        let n = self.parse_literal_uint()?;
        self.expect_token(&Token::RParen)?;
        Ok(n)
    }

    /// Parse an optional precision `(n)` and return it as `Some(n)` when present.
    pub fn parse_optional_precision(&mut self) -> Result<Option<u64>, ParserError> {
        if self.consume_token(&Token::LParen) {
            let n = self.parse_literal_uint()?;
            self.expect_token(&Token::RParen)?;
            Ok(Some(n))
        } else {
            Ok(None)
        }
    }

    fn maybe_parse_optional_interval_fields(
        &mut self,
    ) -> Result<Option<IntervalFields>, ParserError> {
        match self.parse_one_of_keywords(&[
            // Can be followed by `TO` option
            Keyword::YEAR,
            Keyword::DAY,
            Keyword::HOUR,
            Keyword::MINUTE,
            // No `TO` option
            Keyword::MONTH,
            Keyword::SECOND,
        ]) {
            Some(Keyword::YEAR) => {
                if self.peek_keyword(Keyword::TO) {
                    self.expect_keyword(Keyword::TO)?;
                    self.expect_keyword(Keyword::MONTH)?;
                    Ok(Some(IntervalFields::YearToMonth))
                } else {
                    Ok(Some(IntervalFields::Year))
                }
            }
            Some(Keyword::DAY) => {
                if self.peek_keyword(Keyword::TO) {
                    self.expect_keyword(Keyword::TO)?;
                    match self.expect_one_of_keywords(&[
                        Keyword::HOUR,
                        Keyword::MINUTE,
                        Keyword::SECOND,
                    ])? {
                        Keyword::HOUR => Ok(Some(IntervalFields::DayToHour)),
                        Keyword::MINUTE => Ok(Some(IntervalFields::DayToMinute)),
                        Keyword::SECOND => Ok(Some(IntervalFields::DayToSecond)),
                        _ => {
                            self.prev_token();
                            self.expected_ref("HOUR, MINUTE, or SECOND", self.peek_token_ref())
                        }
                    }
                } else {
                    Ok(Some(IntervalFields::Day))
                }
            }
            Some(Keyword::HOUR) => {
                if self.peek_keyword(Keyword::TO) {
                    self.expect_keyword(Keyword::TO)?;
                    match self.expect_one_of_keywords(&[Keyword::MINUTE, Keyword::SECOND])? {
                        Keyword::MINUTE => Ok(Some(IntervalFields::HourToMinute)),
                        Keyword::SECOND => Ok(Some(IntervalFields::HourToSecond)),
                        _ => {
                            self.prev_token();
                            self.expected_ref("MINUTE or SECOND", self.peek_token_ref())
                        }
                    }
                } else {
                    Ok(Some(IntervalFields::Hour))
                }
            }
            Some(Keyword::MINUTE) => {
                if self.peek_keyword(Keyword::TO) {
                    self.expect_keyword(Keyword::TO)?;
                    self.expect_keyword(Keyword::SECOND)?;
                    Ok(Some(IntervalFields::MinuteToSecond))
                } else {
                    Ok(Some(IntervalFields::Minute))
                }
            }
            Some(Keyword::MONTH) => Ok(Some(IntervalFields::Month)),
            Some(Keyword::SECOND) => Ok(Some(IntervalFields::Second)),
            Some(_) => {
                self.prev_token();
                self.expected_ref(
                    "YEAR, MONTH, DAY, HOUR, MINUTE, or SECOND",
                    self.peek_token_ref(),
                )
            }
            None => Ok(None),
        }
    }

    /// Parse datetime64 [1]
    /// Syntax
    /// ```sql
    /// DateTime64(precision[, timezone])
    /// ```
    ///
    /// [1]: https://clickhouse.com/docs/en/sql-reference/data-types/datetime64
    pub fn parse_datetime_64(&mut self) -> Result<(u64, Option<String>), ParserError> {
        self.expect_keyword_is(Keyword::DATETIME64)?;
        self.expect_token(&Token::LParen)?;
        let precision = self.parse_literal_uint()?;
        let time_zone = if self.consume_token(&Token::Comma) {
            Some(self.parse_literal_string()?)
        } else {
            None
        };
        self.expect_token(&Token::RParen)?;
        Ok((precision, time_zone))
    }

    /// Parse an optional character length specification `(n | MAX [CHARACTERS|OCTETS])`.
    pub fn parse_optional_character_length(
        &mut self,
    ) -> Result<Option<CharacterLength>, ParserError> {
        if self.consume_token(&Token::LParen) {
            let character_length = self.parse_character_length()?;
            self.expect_token(&Token::RParen)?;
            Ok(Some(character_length))
        } else {
            Ok(None)
        }
    }

    /// Parse an optional binary length specification like `(n)`.
    pub fn parse_optional_binary_length(&mut self) -> Result<Option<BinaryLength>, ParserError> {
        if self.consume_token(&Token::LParen) {
            let binary_length = self.parse_binary_length()?;
            self.expect_token(&Token::RParen)?;
            Ok(Some(binary_length))
        } else {
            Ok(None)
        }
    }

    /// Parse a character length, handling `MAX` or integer lengths with optional units.
    pub fn parse_character_length(&mut self) -> Result<CharacterLength, ParserError> {
        if self.parse_keyword(Keyword::MAX) {
            return Ok(CharacterLength::Max);
        }
        let length = self.parse_literal_uint()?;
        let unit = if self.parse_keyword(Keyword::CHARACTERS) {
            Some(CharLengthUnits::Characters)
        } else if self.parse_keyword(Keyword::OCTETS) {
            Some(CharLengthUnits::Octets)
        } else {
            None
        };
        Ok(CharacterLength::IntegerLength { length, unit })
    }

    /// Parse a binary length specification, returning `BinaryLength`.
    pub fn parse_binary_length(&mut self) -> Result<BinaryLength, ParserError> {
        if self.parse_keyword(Keyword::MAX) {
            return Ok(BinaryLength::Max);
        }
        let length = self.parse_literal_uint()?;
        Ok(BinaryLength::IntegerLength { length })
    }

    /// Parse an optional `(precision[, scale])` and return `(Option<precision>, Option<scale>)`.
    pub fn parse_optional_precision_scale(
        &mut self,
    ) -> Result<(Option<u64>, Option<u64>), ParserError> {
        if self.consume_token(&Token::LParen) {
            let n = self.parse_literal_uint()?;
            let scale = if self.consume_token(&Token::Comma) {
                Some(self.parse_literal_uint()?)
            } else {
                None
            };
            self.expect_token(&Token::RParen)?;
            Ok((Some(n), scale))
        } else {
            Ok((None, None))
        }
    }

    /// Parse exact-number precision/scale info like `(precision[, scale])` for decimal types.
    pub fn parse_exact_number_optional_precision_scale(
        &mut self,
    ) -> Result<ExactNumberInfo, ParserError> {
        if self.consume_token(&Token::LParen) {
            let precision = self.parse_literal_uint()?;
            let scale = if self.consume_token(&Token::Comma) {
                Some(self.parse_signed_integer()?)
            } else {
                None
            };

            self.expect_token(&Token::RParen)?;

            match scale {
                None => Ok(ExactNumberInfo::Precision(precision)),
                Some(scale) => Ok(ExactNumberInfo::PrecisionAndScale(precision, scale)),
            }
        } else {
            Ok(ExactNumberInfo::None)
        }
    }

    /// Parse an optionally signed integer literal.
    fn parse_signed_integer(&mut self) -> Result<i64, ParserError> {
        let is_negative = self.consume_token(&Token::Minus);

        if !is_negative {
            let _ = self.consume_token(&Token::Plus);
        }

        let current_token = self.peek_token_ref();
        match &current_token.token {
            Token::Number(s, _) => {
                let s = s.clone();
                let span_start = current_token.span.start;
                self.advance_token();
                let value = Self::parse::<i64>(s, span_start)?;
                Ok(if is_negative { -value } else { value })
            }
            _ => self.expected_ref("number", current_token),
        }
    }

    /// Parse optional type modifiers appearing in parentheses e.g. `(UNSIGNED, ZEROFILL)`.
    pub fn parse_optional_type_modifiers(&mut self) -> Result<Option<Vec<String>>, ParserError> {
        if self.consume_token(&Token::LParen) {
            let mut modifiers = Vec::new();
            loop {
                let next_token = self.next_token();
                match next_token.token {
                    Token::Word(w) => modifiers.push(w.to_string()),
                    Token::Number(n, _) => modifiers.push(n),
                    Token::SingleQuotedString(s) => modifiers.push(s),

                    Token::Comma => {
                        continue;
                    }
                    Token::RParen => {
                        break;
                    }
                    _ => self.expected("type modifiers", next_token)?,
                }
            }

            Ok(Some(modifiers))
        } else {
            Ok(None)
        }
    }

    fn parse_structured_object_type_def(&mut self) -> Result<Vec<ColumnDef>, ParserError> {
        self.expect_token(&Token::LParen)?;
        if self.consume_token(&Token::RParen) {
            return Ok(vec![]);
        }
        let fields = self.parse_comma_separated(|parser| {
            if matches!(parser.peek_token_ref().token, Token::SingleQuotedString(_)) {
                return parser.expected("an object field identifier", parser.peek_token());
            }
            let name = parser.parse_identifier()?;
            let data_type = parser.parse_data_type()?;
            let options = if parser.parse_keywords(&[Keyword::NOT, Keyword::NULL]) {
                vec![ColumnOptionDef {
                    name: None,
                    option: ColumnOption::NotNull,
                }]
            } else {
                vec![]
            };
            Ok(ColumnDef {
                name,
                data_type,
                options,
            })
        })?;
        self.expect_token(&Token::RParen)?;
        Ok(fields)
    }

    /// Parse a parenthesized sub data type
    fn parse_sub_type<F>(&mut self, parent_type: F) -> Result<DataType, ParserError>
    where
        F: FnOnce(Box<DataType>) -> DataType,
    {
        self.expect_token(&Token::LParen)?;
        let inside_type = self.parse_data_type()?;
        self.expect_token(&Token::RParen)?;
        Ok(parent_type(inside_type.into()))
    }

    /// Parse a DELETE statement, returning a `Box`ed SetExpr
    ///
    /// This is used to reduce the size of the stack frames in debug builds
    fn parse_delete_setexpr_boxed(
        &mut self,
        delete_token: TokenWithSpan,
    ) -> Result<Box<SetExpr>, ParserError> {
        Ok(Box::new(SetExpr::Delete(self.parse_delete(delete_token)?)))
    }

    /// Parse a `DELETE` statement and return `Statement::Delete`.
    pub fn parse_delete(&mut self, delete_token: TokenWithSpan) -> Result<Statement, ParserError> {
        let optimizer_hints = self.maybe_parse_optimizer_hints()?;
        let (tables, with_from_keyword) = if !self.parse_keyword(Keyword::FROM) {
            // `FROM` keyword is optional in BigQuery SQL.
            // https://cloud.google.com/bigquery/docs/reference/standard-sql/dml-syntax#delete_statement
            if dialect_of!(self is BigQueryDialect | OracleDialect | GenericDialect) {
                (vec![], false)
            } else {
                let tables = self.parse_comma_separated(|p| p.parse_object_name(false))?;
                self.expect_keyword_is(Keyword::FROM)?;
                (tables, true)
            }
        } else {
            (vec![], true)
        };

        let from = self.parse_comma_separated(Parser::parse_table_and_joins)?;
        let on_cluster = self.parse_optional_on_cluster()?;

        let output = self.maybe_parse_output_clause()?;

        let using = if self.parse_keyword(Keyword::USING) {
            Some(self.parse_comma_separated(Parser::parse_table_and_joins)?)
        } else {
            None
        };
        let selection = if self.parse_keyword(Keyword::WHERE) {
            Some(self.parse_expr()?)
        } else {
            None
        };
        let returning = if self.parse_keyword(Keyword::RETURNING) {
            Some(self.parse_comma_separated(Parser::parse_select_item)?)
        } else {
            None
        };
        let order_by = if self.parse_keywords(&[Keyword::ORDER, Keyword::BY]) {
            self.parse_comma_separated(Parser::parse_order_by_expr)?
        } else {
            vec![]
        };
        let limit = if self.parse_keyword(Keyword::LIMIT) {
            self.parse_limit()?
        } else {
            None
        };
        let settings = self.parse_settings()?;

        Ok(Statement::Delete(Delete {
            delete_token: delete_token.into(),
            optimizer_hints,
            tables,
            from: if with_from_keyword {
                FromTable::WithFromKeyword(from)
            } else {
                FromTable::WithoutKeyword(from)
            },
            on_cluster,
            using,
            selection,
            returning,
            output,
            order_by,
            limit,
            settings,
        }))
    }

    /// Parse a `KILL` statement, optionally specifying `CONNECTION`, `QUERY`, or `MUTATION`.
    /// KILL [CONNECTION | QUERY | MUTATION] processlist_id
    pub fn parse_kill(&mut self) -> Result<Statement, ParserError> {
        let modifier_keyword =
            self.parse_one_of_keywords(&[Keyword::CONNECTION, Keyword::QUERY, Keyword::MUTATION]);

        let id = self.parse_literal_uint()?;

        let modifier = match modifier_keyword {
            Some(Keyword::CONNECTION) => Some(KillType::Connection),
            Some(Keyword::QUERY) => Some(KillType::Query),
            Some(Keyword::MUTATION) => {
                if dialect_of!(self is ClickHouseDialect | GenericDialect) {
                    Some(KillType::Mutation)
                } else {
                    self.expected_ref(
                        "Unsupported type for KILL, allowed: CONNECTION | QUERY",
                        self.peek_token_ref(),
                    )?
                }
            }
            _ => None,
        };

        Ok(Statement::Kill { modifier, id })
    }

    /// Parse an `EXPLAIN` statement, handling dialect-specific options and modifiers.
    pub fn parse_explain(
        &mut self,
        describe_alias: DescribeAlias,
    ) -> Result<Statement, ParserError> {
        let mut analyze = false;
        let mut verbose = false;
        let mut query_plan = false;
        let mut estimate = false;
        let mut format = None;
        let mut options = None;

        // Note: DuckDB is compatible with PostgreSQL syntax for this statement,
        // although not all features may be implemented.
        if describe_alias == DescribeAlias::Explain
            && self.dialect.supports_explain_with_utility_options()
            && self.peek_token_ref().token == Token::LParen
        {
            options = Some(self.parse_utility_options()?)
        } else if self.parse_keywords(&[Keyword::QUERY, Keyword::PLAN]) {
            query_plan = true;
        } else if self.parse_keyword(Keyword::ESTIMATE) {
            estimate = true;
        } else {
            analyze = self.parse_keyword(Keyword::ANALYZE);
            verbose = self.parse_keyword(Keyword::VERBOSE);
            if self.parse_keyword(Keyword::FORMAT) {
                format = Some(self.parse_analyze_format_kind()?);
            }
        }

        match self.maybe_parse(|parser| parser.parse_statement())? {
            Some(Statement::Explain { .. }) | Some(Statement::ExplainTable { .. }) => Err(
                ParserError::ParserError("Explain must be root of the plan".to_string()),
            ),
            Some(statement) => Ok(Statement::Explain {
                describe_alias,
                analyze,
                verbose,
                query_plan,
                estimate,
                statement: Box::new(statement),
                format,
                options,
            }),
            _ => {
                let hive_format =
                    match self.parse_one_of_keywords(&[Keyword::EXTENDED, Keyword::FORMATTED]) {
                        Some(Keyword::EXTENDED) => Some(HiveDescribeFormat::Extended),
                        Some(Keyword::FORMATTED) => Some(HiveDescribeFormat::Formatted),
                        _ => None,
                    };

                let has_table_keyword = if self.dialect.describe_requires_table_keyword() {
                    // only allow to use TABLE keyword for DESC|DESCRIBE statement
                    self.parse_keyword(Keyword::TABLE)
                } else {
                    false
                };

                let table_name = self.parse_object_name(false)?;
                Ok(Statement::ExplainTable {
                    describe_alias,
                    hive_format,
                    has_table_keyword,
                    table_name,
                })
            }
        }
    }

    /// Parse a query expression, i.e. a `SELECT` statement optionally
    /// preceded with some `WITH` CTE declarations and optionally followed
    /// by `ORDER BY`. Unlike some other parse_... methods, this one doesn't
    /// expect the initial keyword to be already consumed
    #[cfg_attr(feature = "recursive-protection", recursive::recursive)]
    pub fn parse_query(&mut self) -> Result<Box<Query>, ParserError> {
        let _guard = self.recursion_counter.try_decrease()?;
        let with = if self.parse_keyword(Keyword::WITH) {
            let with_token = self.get_current_token();
            Some(With {
                with_token: with_token.clone().into(),
                recursive: self.parse_keyword(Keyword::RECURSIVE),
                cte_tables: self.parse_comma_separated(Parser::parse_cte)?,
            })
        } else {
            None
        };
        if self.parse_keyword(Keyword::INSERT) {
            Ok(Query {
                with,
                body: self.parse_insert_setexpr_boxed(self.get_current_token().clone())?,
                order_by: None,
                limit_clause: None,
                fetch: None,
                locks: vec![],
                for_clause: None,
                settings: None,
                format_clause: None,
                pipe_operators: vec![],
            }
            .into())
        } else if self.parse_keyword(Keyword::UPDATE) {
            Ok(Query {
                with,
                body: self.parse_update_setexpr_boxed(self.get_current_token().clone())?,
                order_by: None,
                limit_clause: None,
                fetch: None,
                locks: vec![],
                for_clause: None,
                settings: None,
                format_clause: None,
                pipe_operators: vec![],
            }
            .into())
        } else if self.parse_keyword(Keyword::DELETE) {
            Ok(Query {
                with,
                body: self.parse_delete_setexpr_boxed(self.get_current_token().clone())?,
                limit_clause: None,
                order_by: None,
                fetch: None,
                locks: vec![],
                for_clause: None,
                settings: None,
                format_clause: None,
                pipe_operators: vec![],
            }
            .into())
        } else if self.parse_keyword(Keyword::MERGE) {
            Ok(Query {
                with,
                body: self.parse_merge_setexpr_boxed(self.get_current_token().clone())?,
                limit_clause: None,
                order_by: None,
                fetch: None,
                locks: vec![],
                for_clause: None,
                settings: None,
                format_clause: None,
                pipe_operators: vec![],
            }
            .into())
        } else {
            let body = self.parse_query_body(self.dialect.prec_unknown())?;

            let order_by = self.parse_optional_order_by()?;

            let mut limit_clause = self.parse_optional_limit_clause()?;

            let settings = self.parse_settings()?;

            let fetch = if self.parse_keyword(Keyword::FETCH) {
                Some(self.parse_fetch()?)
            } else {
                None
            };

            let mut for_clause = None;
            let mut locks = Vec::new();
            while self.parse_keyword(Keyword::FOR) {
                if let Some(parsed_for_clause) = self.parse_for_clause()? {
                    for_clause = Some(parsed_for_clause);
                    break;
                } else {
                    locks.push(self.parse_lock()?);
                }
            }

            // Some databases (e.g. PostgreSQL) accept `LIMIT`/`OFFSET` after the
            // row-locking clause (`... FOR UPDATE SKIP LOCKED LIMIT 5`) as well
            // as before it. The locking clause above is parsed for every
            // dialect, so accept a trailing limit here too rather than gating it
            // behind a dialect flag.
            if limit_clause.is_none() {
                limit_clause = self.parse_optional_limit_clause()?;
            }

            let format_clause =
                if self.dialect.supports_select_format() && self.parse_keyword(Keyword::FORMAT) {
                    if self.parse_keyword(Keyword::NULL) {
                        Some(FormatClause::Null)
                    } else {
                        let ident = self.parse_identifier()?;
                        Some(FormatClause::Identifier(ident))
                    }
                } else {
                    None
                };

            let pipe_operators = if self.dialect.supports_pipe_operator() {
                self.parse_pipe_operators()?
            } else {
                Vec::new()
            };

            Ok(Query {
                with,
                body,
                order_by,
                limit_clause,
                fetch,
                locks,
                for_clause,
                settings,
                format_clause,
                pipe_operators,
            }
            .into())
        }
    }

    fn parse_pipe_operators(&mut self) -> Result<Vec<PipeOperator>, ParserError> {
        let mut pipe_operators = Vec::new();

        while self.consume_token(&Token::VerticalBarRightAngleBracket) {
            let kw = self.expect_one_of_keywords(&[
                Keyword::SELECT,
                Keyword::EXTEND,
                Keyword::SET,
                Keyword::DROP,
                Keyword::AS,
                Keyword::WHERE,
                Keyword::LIMIT,
                Keyword::AGGREGATE,
                Keyword::ORDER,
                Keyword::TABLESAMPLE,
                Keyword::RENAME,
                Keyword::UNION,
                Keyword::INTERSECT,
                Keyword::EXCEPT,
                Keyword::CALL,
                Keyword::PIVOT,
                Keyword::UNPIVOT,
                Keyword::JOIN,
                Keyword::INNER,
                Keyword::LEFT,
                Keyword::RIGHT,
                Keyword::FULL,
                Keyword::CROSS,
            ])?;
            match kw {
                Keyword::SELECT => {
                    let exprs = self.parse_comma_separated(Parser::parse_select_item)?;
                    pipe_operators.push(PipeOperator::Select { exprs })
                }
                Keyword::EXTEND => {
                    let exprs = self.parse_comma_separated(Parser::parse_select_item)?;
                    pipe_operators.push(PipeOperator::Extend { exprs })
                }
                Keyword::SET => {
                    let assignments = self.parse_comma_separated(Parser::parse_assignment)?;
                    pipe_operators.push(PipeOperator::Set { assignments })
                }
                Keyword::DROP => {
                    let columns = self.parse_identifiers()?;
                    pipe_operators.push(PipeOperator::Drop { columns })
                }
                Keyword::AS => {
                    let alias = self.parse_identifier()?;
                    pipe_operators.push(PipeOperator::As { alias })
                }
                Keyword::WHERE => {
                    let expr = self.parse_expr()?;
                    pipe_operators.push(PipeOperator::Where { expr })
                }
                Keyword::LIMIT => {
                    let expr = self.parse_expr()?;
                    let offset = if self.parse_keyword(Keyword::OFFSET) {
                        Some(self.parse_expr()?)
                    } else {
                        None
                    };
                    pipe_operators.push(PipeOperator::Limit { expr, offset })
                }
                Keyword::AGGREGATE => {
                    let full_table_exprs = if self.peek_keyword(Keyword::GROUP) {
                        vec![]
                    } else {
                        self.parse_comma_separated(|parser| {
                            parser.parse_expr_with_alias_and_order_by()
                        })?
                    };

                    let group_by_expr = if self.parse_keywords(&[Keyword::GROUP, Keyword::BY]) {
                        self.parse_comma_separated(|parser| {
                            parser.parse_expr_with_alias_and_order_by()
                        })?
                    } else {
                        vec![]
                    };

                    pipe_operators.push(PipeOperator::Aggregate {
                        full_table_exprs,
                        group_by_expr,
                    })
                }
                Keyword::ORDER => {
                    self.expect_one_of_keywords(&[Keyword::BY])?;
                    let exprs = self.parse_comma_separated(Parser::parse_order_by_expr)?;
                    pipe_operators.push(PipeOperator::OrderBy { exprs })
                }
                Keyword::TABLESAMPLE => {
                    let sample = self.parse_table_sample(TableSampleModifier::TableSample)?;
                    pipe_operators.push(PipeOperator::TableSample { sample });
                }
                Keyword::RENAME => {
                    let mappings =
                        self.parse_comma_separated(Parser::parse_identifier_with_optional_alias)?;
                    pipe_operators.push(PipeOperator::Rename { mappings });
                }
                Keyword::UNION => {
                    let set_quantifier = self.parse_set_quantifier(&Some(SetOperator::Union));
                    let queries = self.parse_pipe_operator_queries()?;
                    pipe_operators.push(PipeOperator::Union {
                        set_quantifier,
                        queries,
                    });
                }
                Keyword::INTERSECT => {
                    let set_quantifier =
                        self.parse_distinct_required_set_quantifier("INTERSECT")?;
                    let queries = self.parse_pipe_operator_queries()?;
                    pipe_operators.push(PipeOperator::Intersect {
                        set_quantifier,
                        queries,
                    });
                }
                Keyword::EXCEPT => {
                    let set_quantifier = self.parse_distinct_required_set_quantifier("EXCEPT")?;
                    let queries = self.parse_pipe_operator_queries()?;
                    pipe_operators.push(PipeOperator::Except {
                        set_quantifier,
                        queries,
                    });
                }
                Keyword::CALL => {
                    let function_name = self.parse_object_name(false)?;
                    let function_expr = self.parse_function(function_name)?;
                    if let Expr::Function(function) = function_expr {
                        let alias = self.parse_identifier_optional_alias()?;
                        pipe_operators.push(PipeOperator::Call { function, alias });
                    } else {
                        return Err(ParserError::ParserError(
                            "Expected function call after CALL".to_string(),
                        ));
                    }
                }
                Keyword::PIVOT => {
                    self.expect_token(&Token::LParen)?;
                    let aggregate_functions =
                        self.parse_comma_separated(Self::parse_pivot_aggregate_function)?;
                    self.expect_keyword_is(Keyword::FOR)?;
                    let value_column = self.parse_period_separated(|p| p.parse_identifier())?;
                    self.expect_keyword_is(Keyword::IN)?;

                    self.expect_token(&Token::LParen)?;
                    let value_source = if self.parse_keyword(Keyword::ANY) {
                        let order_by = if self.parse_keywords(&[Keyword::ORDER, Keyword::BY]) {
                            self.parse_comma_separated(Parser::parse_order_by_expr)?
                        } else {
                            vec![]
                        };
                        PivotValueSource::Any(order_by)
                    } else if self.peek_sub_query() {
                        PivotValueSource::Subquery(self.parse_query()?)
                    } else {
                        PivotValueSource::List(
                            self.parse_comma_separated(Self::parse_expr_with_alias)?,
                        )
                    };
                    self.expect_token(&Token::RParen)?;
                    self.expect_token(&Token::RParen)?;

                    let alias = self.parse_identifier_optional_alias()?;

                    pipe_operators.push(PipeOperator::Pivot {
                        aggregate_functions,
                        value_column,
                        value_source,
                        alias,
                    });
                }
                Keyword::UNPIVOT => {
                    self.expect_token(&Token::LParen)?;
                    let value_column = self.parse_identifier()?;
                    self.expect_keyword(Keyword::FOR)?;
                    let name_column = self.parse_identifier()?;
                    self.expect_keyword(Keyword::IN)?;

                    self.expect_token(&Token::LParen)?;
                    let unpivot_columns = self.parse_comma_separated(Parser::parse_identifier)?;
                    self.expect_token(&Token::RParen)?;

                    self.expect_token(&Token::RParen)?;

                    let alias = self.parse_identifier_optional_alias()?;

                    pipe_operators.push(PipeOperator::Unpivot {
                        value_column,
                        name_column,
                        unpivot_columns,
                        alias,
                    });
                }
                Keyword::JOIN
                | Keyword::INNER
                | Keyword::LEFT
                | Keyword::RIGHT
                | Keyword::FULL
                | Keyword::CROSS => {
                    self.prev_token();
                    let mut joins = self.parse_joins()?;
                    if joins.len() != 1 {
                        return Err(ParserError::ParserError(
                            "Join pipe operator must have a single join".to_string(),
                        ));
                    }
                    let join = joins.swap_remove(0);
                    pipe_operators.push(PipeOperator::Join(join))
                }
                unhandled => {
                    return Err(ParserError::ParserError(format!(
                    "`expect_one_of_keywords` further up allowed unhandled keyword: {unhandled:?}"
                )))
                }
            }
        }
        Ok(pipe_operators)
    }

    fn parse_settings(&mut self) -> Result<Option<Vec<Setting>>, ParserError> {
        let settings = if self.dialect.supports_settings() && self.parse_keyword(Keyword::SETTINGS)
        {
            let key_values = self.parse_comma_separated(|p| {
                let key = p.parse_identifier()?;
                p.expect_token(&Token::Eq)?;
                let value = p.parse_expr()?;
                Ok(Setting { key, value })
            })?;
            Some(key_values)
        } else {
            None
        };
        Ok(settings)
    }

    /// Parse a mssql `FOR [XML | JSON | BROWSE]` clause
    pub fn parse_for_clause(&mut self) -> Result<Option<ForClause>, ParserError> {
        if self.parse_keyword(Keyword::XML) {
            Ok(Some(self.parse_for_xml()?))
        } else if self.parse_keyword(Keyword::JSON) {
            Ok(Some(self.parse_for_json()?))
        } else if self.parse_keyword(Keyword::BROWSE) {
            Ok(Some(ForClause::Browse))
        } else {
            Ok(None)
        }
    }

    /// Parse a mssql `FOR XML` clause
    pub fn parse_for_xml(&mut self) -> Result<ForClause, ParserError> {
        let for_xml = if self.parse_keyword(Keyword::RAW) {
            let mut element_name = None;
            if self.peek_token_ref().token == Token::LParen {
                self.expect_token(&Token::LParen)?;
                element_name = Some(self.parse_literal_string()?);
                self.expect_token(&Token::RParen)?;
            }
            ForXml::Raw(element_name)
        } else if self.parse_keyword(Keyword::AUTO) {
            ForXml::Auto
        } else if self.parse_keyword(Keyword::EXPLICIT) {
            ForXml::Explicit
        } else if self.parse_keyword(Keyword::PATH) {
            let mut element_name = None;
            if self.peek_token_ref().token == Token::LParen {
                self.expect_token(&Token::LParen)?;
                element_name = Some(self.parse_literal_string()?);
                self.expect_token(&Token::RParen)?;
            }
            ForXml::Path(element_name)
        } else {
            return Err(ParserError::ParserError(
                "Expected FOR XML [RAW | AUTO | EXPLICIT | PATH ]".to_string(),
            ));
        };
        let mut elements = false;
        let mut binary_base64 = false;
        let mut root = None;
        let mut r#type = false;
        while self.peek_token_ref().token == Token::Comma {
            self.next_token();
            if self.parse_keyword(Keyword::ELEMENTS) {
                elements = true;
            } else if self.parse_keyword(Keyword::BINARY) {
                self.expect_keyword_is(Keyword::BASE64)?;
                binary_base64 = true;
            } else if self.parse_keyword(Keyword::ROOT) {
                self.expect_token(&Token::LParen)?;
                root = Some(self.parse_literal_string()?);
                self.expect_token(&Token::RParen)?;
            } else if self.parse_keyword(Keyword::TYPE) {
                r#type = true;
            }
        }
        Ok(ForClause::Xml {
            for_xml,
            elements,
            binary_base64,
            root,
            r#type,
        })
    }

    /// Parse a mssql `FOR JSON` clause
    pub fn parse_for_json(&mut self) -> Result<ForClause, ParserError> {
        let for_json = if self.parse_keyword(Keyword::AUTO) {
            ForJson::Auto
        } else if self.parse_keyword(Keyword::PATH) {
            ForJson::Path
        } else {
            return Err(ParserError::ParserError(
                "Expected FOR JSON [AUTO | PATH ]".to_string(),
            ));
        };
        let mut root = None;
        let mut include_null_values = false;
        let mut without_array_wrapper = false;
        while self.peek_token_ref().token == Token::Comma {
            self.next_token();
            if self.parse_keyword(Keyword::ROOT) {
                self.expect_token(&Token::LParen)?;
                root = Some(self.parse_literal_string()?);
                self.expect_token(&Token::RParen)?;
            } else if self.parse_keyword(Keyword::INCLUDE_NULL_VALUES) {
                include_null_values = true;
            } else if self.parse_keyword(Keyword::WITHOUT_ARRAY_WRAPPER) {
                without_array_wrapper = true;
            }
        }
        Ok(ForClause::Json {
            for_json,
            root,
            include_null_values,
            without_array_wrapper,
        })
    }

    /// Parse a CTE (`alias [( col1, col2, ... )] [AS] (subquery)`)
    pub fn parse_cte(&mut self) -> Result<Cte, ParserError> {
        let name = self.parse_identifier()?;

        let as_optional = self.dialect.supports_cte_without_as();

        // If AS is optional, first try to parse `name (query)` directly
        if as_optional && !self.peek_keyword(Keyword::AS) {
            if let Some((query, closing_paren_token)) = self.maybe_parse(|p| {
                p.expect_token(&Token::LParen)?;
                let query = p.parse_query()?;
                let closing_paren_token = p.expect_token(&Token::RParen)?;
                Ok((query, closing_paren_token))
            })? {
                let mut cte = Cte {
                    alias: TableAlias {
                        explicit: false,
                        name,
                        columns: vec![],
                        at: None,
                    },
                    query,
                    from: None,
                    materialized: None,
                    closing_paren_token: closing_paren_token.into(),
                };
                if self.parse_keyword(Keyword::FROM) {
                    cte.from = Some(self.parse_identifier()?);
                }
                return Ok(cte);
            }
        }

        // Determine column definitions and consume AS
        let columns = if self.parse_keyword(Keyword::AS) {
            vec![]
        } else {
            let columns = self.parse_table_alias_column_defs()?;
            if as_optional {
                let _ = self.parse_keyword(Keyword::AS);
            } else {
                self.expect_keyword_is(Keyword::AS)?;
            }
            columns
        };

        let mut is_materialized = None;
        if self.dialect.supports_cte_materialization() {
            if self.parse_keyword(Keyword::MATERIALIZED) {
                is_materialized = Some(CteAsMaterialized::Materialized);
            } else if self.parse_keywords(&[Keyword::NOT, Keyword::MATERIALIZED]) {
                is_materialized = Some(CteAsMaterialized::NotMaterialized);
            }
        }

        self.expect_token(&Token::LParen)?;
        let query = self.parse_query()?;
        let closing_paren_token = self.expect_token(&Token::RParen)?;

        let mut cte = Cte {
            alias: TableAlias {
                explicit: false,
                name,
                columns,
                at: None,
            },
            query,
            from: None,
            materialized: is_materialized,
            closing_paren_token: closing_paren_token.into(),
        };
        if self.dialect.supports_from_first_insert() && self.parse_keyword(Keyword::FROM) {
            cte.from = Some(self.parse_identifier()?);
        }
        Ok(cte)
    }

    /// Parse a "query body", which is an expression with roughly the
    /// following grammar:
    /// ```sql
    ///   query_body ::= restricted_select | '(' subquery ')' | set_operation
    ///   restricted_select ::= 'SELECT' [expr_list] [ from ] [ where ] [ groupby_having ]
    ///   subquery ::= query_body [ order_by_limit ]
    ///   set_operation ::= query_body { 'UNION' | 'EXCEPT' | 'INTERSECT' } [ 'ALL' ] query_body
    /// ```
    pub fn parse_query_body(&mut self, precedence: u8) -> Result<Box<SetExpr>, ParserError> {
        // We parse the expression using a Pratt parser, as in `parse_expr()`.
        // Start by parsing a restricted SELECT or a `(subquery)`:
        let expr = if self.peek_keyword(Keyword::SELECT)
            || (self.peek_keyword(Keyword::FROM) && self.dialect.supports_from_first_select())
        {
            SetExpr::Select(self.parse_select().map(Box::new)?)
        } else if self.consume_token(&Token::LParen) {
            // CTEs are not allowed here, but the parser currently accepts them
            let subquery = self.parse_query()?;
            self.expect_token(&Token::RParen)?;
            SetExpr::Query(subquery)
        } else if self.parse_keyword(Keyword::VALUES) {
            let is_mysql = dialect_of!(self is MySqlDialect);
            SetExpr::Values(self.parse_values(is_mysql, false)?)
        } else if self.parse_keyword(Keyword::VALUE) {
            let is_mysql = dialect_of!(self is MySqlDialect);
            SetExpr::Values(self.parse_values(is_mysql, true)?)
        } else if self.parse_keyword(Keyword::TABLE) {
            SetExpr::Table(Box::new(self.parse_as_table()?))
        } else {
            return self.expected_ref(
                "SELECT, VALUES, or a subquery in the query body",
                self.peek_token_ref(),
            );
        };

        self.parse_remaining_set_exprs(expr, precedence)
    }

    /// Parse any extra set expressions that may be present in a query body
    ///
    /// (this is its own function to reduce required stack size in debug builds)
    fn parse_remaining_set_exprs(
        &mut self,
        mut expr: SetExpr,
        precedence: u8,
    ) -> Result<Box<SetExpr>, ParserError> {
        loop {
            // The query can be optionally followed by a set operator:
            let op = self.parse_set_operator(&self.peek_token().token);
            let next_precedence = match op {
                // UNION and EXCEPT have the same binding power and evaluate left-to-right
                Some(SetOperator::Union) | Some(SetOperator::Except) | Some(SetOperator::Minus) => {
                    10
                }
                // INTERSECT has higher precedence than UNION/EXCEPT
                Some(SetOperator::Intersect) => 20,
                // Unexpected token or EOF => stop parsing the query body
                None => break,
            };
            if precedence >= next_precedence {
                break;
            }
            self.next_token(); // skip past the set operator
            let set_quantifier = self.parse_set_quantifier(&op);
            expr = SetExpr::SetOperation {
                left: Box::new(expr),
                op: op.unwrap(),
                set_quantifier,
                right: self.parse_query_body(next_precedence)?,
            };
        }

        Ok(expr.into())
    }

    /// Parse a set operator token into its `SetOperator` variant.
    pub fn parse_set_operator(&mut self, token: &Token) -> Option<SetOperator> {
        match token {
            Token::Word(w) if w.keyword == Keyword::UNION => Some(SetOperator::Union),
            Token::Word(w) if w.keyword == Keyword::EXCEPT => Some(SetOperator::Except),
            Token::Word(w) if w.keyword == Keyword::INTERSECT => Some(SetOperator::Intersect),
            Token::Word(w) if w.keyword == Keyword::MINUS => Some(SetOperator::Minus),
            _ => None,
        }
    }

    /// Parse a set quantifier (e.g., `ALL`, `DISTINCT BY NAME`) for the given set operator.
    pub fn parse_set_quantifier(&mut self, op: &Option<SetOperator>) -> SetQuantifier {
        match op {
            Some(
                SetOperator::Except
                | SetOperator::Intersect
                | SetOperator::Union
                | SetOperator::Minus,
            ) => {
                if self.parse_keywords(&[Keyword::DISTINCT, Keyword::BY, Keyword::NAME]) {
                    SetQuantifier::DistinctByName
                } else if self.parse_keywords(&[Keyword::BY, Keyword::NAME]) {
                    SetQuantifier::ByName
                } else if self.parse_keyword(Keyword::ALL) {
                    if self.parse_keywords(&[Keyword::BY, Keyword::NAME]) {
                        SetQuantifier::AllByName
                    } else {
                        SetQuantifier::All
                    }
                } else if self.parse_keyword(Keyword::DISTINCT) {
                    SetQuantifier::Distinct
                } else {
                    SetQuantifier::None
                }
            }
            _ => SetQuantifier::None,
        }
    }

    /// Parse a restricted `SELECT` statement (no CTEs / `UNION` / `ORDER BY`)
    pub fn parse_select(&mut self) -> Result<Select, ParserError> {
        let mut from_first = None;

        if self.dialect.supports_from_first_select() && self.peek_keyword(Keyword::FROM) {
            let from_token = self.expect_keyword(Keyword::FROM)?;
            let from = self.parse_table_with_joins()?;
            if !self.peek_keyword(Keyword::SELECT) {
                return Ok(Select {
                    select_token: AttachedToken(from_token),
                    optimizer_hints: vec![],
                    distinct: None,
                    select_modifiers: None,
                    top: None,
                    top_before_distinct: false,
                    projection: vec![],
                    exclude: None,
                    into: None,
                    from,
                    lateral_views: vec![],
                    prewhere: None,
                    selection: None,
                    group_by: GroupByExpr::Expressions(vec![], vec![]),
                    cluster_by: vec![],
                    distribute_by: vec![],
                    sort_by: vec![],
                    having: None,
                    named_window: vec![],
                    window_before_qualify: false,
                    qualify: None,
                    value_table_mode: None,
                    connect_by: vec![],
                    flavor: SelectFlavor::FromFirstNoSelect,
                });
            }
            from_first = Some(from);
        }

        let select_token = self.expect_keyword(Keyword::SELECT)?;
        let optimizer_hints = self.maybe_parse_optimizer_hints()?;
        let value_table_mode = self.parse_value_table_mode()?;

        let (select_modifiers, distinct_select_modifier) =
            if self.dialect.supports_select_modifiers() {
                self.parse_select_modifiers()?
            } else {
                (None, None)
            };

        let mut top_before_distinct = false;
        let mut top = None;
        if self.dialect.supports_top_before_distinct() && self.parse_keyword(Keyword::TOP) {
            top = Some(self.parse_top()?);
            top_before_distinct = true;
        }

        let distinct = if distinct_select_modifier.is_some() {
            distinct_select_modifier
        } else {
            self.parse_all_or_distinct()?
        };

        if !self.dialect.supports_top_before_distinct() && self.parse_keyword(Keyword::TOP) {
            top = Some(self.parse_top()?);
        }

        let projection =
            if self.dialect.supports_empty_projections() && self.peek_keyword(Keyword::FROM) {
                vec![]
            } else {
                self.parse_projection()?
            };

        let exclude = if self.dialect.supports_select_exclude() {
            self.parse_optional_select_item_exclude()?
        } else {
            None
        };

        let into = if self.parse_keyword(Keyword::INTO) {
            Some(self.parse_select_into()?)
        } else {
            None
        };

        // Note that for keywords to be properly handled here, they need to be
        // added to `RESERVED_FOR_COLUMN_ALIAS` / `RESERVED_FOR_TABLE_ALIAS`,
        // otherwise they may be parsed as an alias as part of the `projection`
        // or `from`.

        let (from, from_first) = if let Some(from) = from_first.take() {
            (from, true)
        } else if self.parse_keyword(Keyword::FROM) {
            (self.parse_table_with_joins()?, false)
        } else {
            (vec![], false)
        };

        let mut lateral_views = vec![];
        loop {
            if self.parse_keywords(&[Keyword::LATERAL, Keyword::VIEW]) {
                let outer = self.parse_keyword(Keyword::OUTER);
                let lateral_view = self.parse_expr()?;
                let lateral_view_name = self.parse_object_name(false)?;
                let lateral_col_alias = self
                    .parse_comma_separated(|parser| {
                        parser.parse_optional_alias(&[
                            Keyword::WHERE,
                            Keyword::GROUP,
                            Keyword::CLUSTER,
                            Keyword::HAVING,
                            Keyword::LATERAL,
                        ]) // This couldn't possibly be a bad idea
                    })?
                    .into_iter()
                    .flatten()
                    .collect();

                lateral_views.push(LateralView {
                    lateral_view,
                    lateral_view_name,
                    lateral_col_alias,
                    outer,
                });
            } else {
                break;
            }
        }

        let prewhere = if self.dialect.supports_prewhere() && self.parse_keyword(Keyword::PREWHERE)
        {
            Some(self.parse_expr()?)
        } else {
            None
        };

        let selection = if self.parse_keyword(Keyword::WHERE) {
            Some(self.parse_expr()?)
        } else {
            None
        };

        let connect_by = self.maybe_parse_connect_by()?;

        let group_by = self
            .parse_optional_group_by()?
            .unwrap_or_else(|| GroupByExpr::Expressions(vec![], vec![]));

        let cluster_by = if self.parse_keywords(&[Keyword::CLUSTER, Keyword::BY]) {
            self.parse_comma_separated(Parser::parse_expr)?
        } else {
            vec![]
        };

        let distribute_by = if self.parse_keywords(&[Keyword::DISTRIBUTE, Keyword::BY]) {
            self.parse_comma_separated(Parser::parse_expr)?
        } else {
            vec![]
        };

        let sort_by = if self.parse_keywords(&[Keyword::SORT, Keyword::BY]) {
            self.parse_comma_separated(Parser::parse_order_by_expr)?
        } else {
            vec![]
        };

        let having = if self.parse_keyword(Keyword::HAVING) {
            Some(self.parse_expr()?)
        } else {
            None
        };

        // Accept QUALIFY and WINDOW in any order and flag accordingly.
        let (named_windows, qualify, window_before_qualify) = if self.parse_keyword(Keyword::WINDOW)
        {
            let named_windows = self.parse_comma_separated(Parser::parse_named_window)?;
            if self.parse_keyword(Keyword::QUALIFY) {
                (named_windows, Some(self.parse_expr()?), true)
            } else {
                (named_windows, None, true)
            }
        } else if self.parse_keyword(Keyword::QUALIFY) {
            let qualify = Some(self.parse_expr()?);
            if self.parse_keyword(Keyword::WINDOW) {
                (
                    self.parse_comma_separated(Parser::parse_named_window)?,
                    qualify,
                    false,
                )
            } else {
                (Default::default(), qualify, false)
            }
        } else {
            Default::default()
        };

        Ok(Select {
            select_token: AttachedToken(select_token),
            optimizer_hints,
            distinct,
            select_modifiers,
            top,
            top_before_distinct,
            projection,
            exclude,
            into,
            from,
            lateral_views,
            prewhere,
            selection,
            group_by,
            cluster_by,
            distribute_by,
            sort_by,
            having,
            named_window: named_windows,
            window_before_qualify,
            qualify,
            value_table_mode,
            connect_by,
            flavor: if from_first {
                SelectFlavor::FromFirst
            } else {
                SelectFlavor::Standard
            },
        })
    }

    /// Parses optimizer hints at the current token position.
    ///
    /// Collects all `/*prefix+...*/` and `--prefix+...` patterns.
    /// The `prefix` is any run of ASCII alphanumeric characters between the
    /// comment marker and `+` (e.g. `""` for `/*+...*/`, `"abc"` for `/*abc+...*/`).
    ///
    /// [MySQL](https://dev.mysql.com/doc/refman/8.4/en/optimizer-hints.html#optimizer-hints-overview)
    /// [Oracle](https://docs.oracle.com/en/database/oracle/oracle-database/21/sqlrf/Comments.html#GUID-D316D545-89E2-4D54-977F-FC97815CD62E)
    fn maybe_parse_optimizer_hints(&mut self) -> Result<Vec<OptimizerHint>, ParserError> {
        let supports_hints = self.dialect.supports_comment_optimizer_hint();
        if !supports_hints {
            return Ok(vec![]);
        }
        let mut hints = vec![];
        loop {
            let t = self.peek_nth_token_no_skip_ref(0);
            let Token::Whitespace(ws) = &t.token else {
                break;
            };
            match ws {
                Whitespace::SingleLineComment { comment, prefix } => {
                    if let Some((hint_prefix, text)) = Self::extract_hint_prefix_and_text(comment) {
                        hints.push(OptimizerHint {
                            prefix: hint_prefix,
                            text,
                            style: OptimizerHintStyle::SingleLine {
                                prefix: prefix.clone(),
                            },
                        });
                    }
                    self.next_token_no_skip();
                }
                Whitespace::MultiLineComment(comment) => {
                    if let Some((hint_prefix, text)) = Self::extract_hint_prefix_and_text(comment) {
                        hints.push(OptimizerHint {
                            prefix: hint_prefix,
                            text,
                            style: OptimizerHintStyle::MultiLine,
                        });
                    }
                    self.next_token_no_skip();
                }
                Whitespace::Space | Whitespace::Tab | Whitespace::Newline => {
                    self.next_token_no_skip();
                }
            }
        }
        Ok(hints)
    }

    /// Checks if a comment's content starts with `[ASCII-alphanumeric]*+`
    /// and returns `(prefix, text_after_plus)` if so.
    fn extract_hint_prefix_and_text(comment: &str) -> Option<(String, String)> {
        let (before_plus, text) = comment.split_once('+')?;
        if before_plus.chars().all(|c| c.is_ascii_alphanumeric()) {
            Some((before_plus.to_string(), text.to_string()))
        } else {
            None
        }
    }

    /// Parses MySQL SELECT modifiers and DISTINCT/ALL in any order.
    ///
    /// Manual testing shows odifiers can appear in any order, and modifiers other than DISTINCT/ALL
    /// can be repeated.
    ///
    /// <https://dev.mysql.com/doc/refman/8.4/en/select.html>
    fn parse_select_modifiers(
        &mut self,
    ) -> Result<(Option<SelectModifiers>, Option<Distinct>), ParserError> {
        let mut modifiers = SelectModifiers::default();
        let mut distinct = None;

        let keywords = &[
            Keyword::ALL,
            Keyword::DISTINCT,
            Keyword::DISTINCTROW,
            Keyword::HIGH_PRIORITY,
            Keyword::STRAIGHT_JOIN,
            Keyword::SQL_SMALL_RESULT,
            Keyword::SQL_BIG_RESULT,
            Keyword::SQL_BUFFER_RESULT,
            Keyword::SQL_NO_CACHE,
            Keyword::SQL_CALC_FOUND_ROWS,
        ];

        while let Some(keyword) = self.parse_one_of_keywords(keywords) {
            match keyword {
                Keyword::ALL | Keyword::DISTINCT if distinct.is_none() => {
                    self.prev_token();
                    distinct = self.parse_all_or_distinct()?;
                }
                // DISTINCTROW is a MySQL-specific legacy (but not deprecated) alias for DISTINCT
                Keyword::DISTINCTROW if distinct.is_none() => {
                    distinct = Some(Distinct::Distinct);
                }
                Keyword::HIGH_PRIORITY => modifiers.high_priority = true,
                Keyword::STRAIGHT_JOIN => modifiers.straight_join = true,
                Keyword::SQL_SMALL_RESULT => modifiers.sql_small_result = true,
                Keyword::SQL_BIG_RESULT => modifiers.sql_big_result = true,
                Keyword::SQL_BUFFER_RESULT => modifiers.sql_buffer_result = true,
                Keyword::SQL_NO_CACHE => modifiers.sql_no_cache = true,
                Keyword::SQL_CALC_FOUND_ROWS => modifiers.sql_calc_found_rows = true,
                _ => {
                    self.prev_token();
                    return self.expected_ref(
                        "HIGH_PRIORITY, STRAIGHT_JOIN, or other MySQL select modifier",
                        self.peek_token_ref(),
                    );
                }
            }
        }

        // Avoid polluting the AST with `Some(SelectModifiers::default())` empty value unless there
        // actually were some modifiers set.
        let select_modifiers = if modifiers.is_any_set() {
            Some(modifiers)
        } else {
            None
        };
        Ok((select_modifiers, distinct))
    }

    fn parse_value_table_mode(&mut self) -> Result<Option<ValueTableMode>, ParserError> {
        if !dialect_of!(self is BigQueryDialect) {
            return Ok(None);
        }

        let mode = if self.parse_keywords(&[Keyword::DISTINCT, Keyword::AS, Keyword::VALUE]) {
            Some(ValueTableMode::DistinctAsValue)
        } else if self.parse_keywords(&[Keyword::DISTINCT, Keyword::AS, Keyword::STRUCT]) {
            Some(ValueTableMode::DistinctAsStruct)
        } else if self.parse_keywords(&[Keyword::AS, Keyword::VALUE])
            || self.parse_keywords(&[Keyword::ALL, Keyword::AS, Keyword::VALUE])
        {
            Some(ValueTableMode::AsValue)
        } else if self.parse_keywords(&[Keyword::AS, Keyword::STRUCT])
            || self.parse_keywords(&[Keyword::ALL, Keyword::AS, Keyword::STRUCT])
        {
            Some(ValueTableMode::AsStruct)
        } else if self.parse_keyword(Keyword::AS) {
            self.expected_ref("VALUE or STRUCT", self.peek_token_ref())?
        } else {
            None
        };

        Ok(mode)
    }

    /// Invoke `f` after first setting the parser's `ParserState` to `state`.
    ///
    /// Upon return, restores the parser's state to what it started at.
    fn with_state<T, F>(&mut self, state: ParserState, mut f: F) -> Result<T, ParserError>
    where
        F: FnMut(&mut Parser) -> Result<T, ParserError>,
    {
        let current_state = self.state;
        self.state = state;
        let res = f(self);
        self.state = current_state;
        res
    }

    /// Parse a `CONNECT BY` clause (Oracle-style hierarchical query support).
    pub fn maybe_parse_connect_by(&mut self) -> Result<Vec<ConnectByKind>, ParserError> {
        let mut clauses = Vec::with_capacity(2);
        loop {
            if let Some(idx) = self.parse_keywords_indexed(&[Keyword::START, Keyword::WITH]) {
                clauses.push(ConnectByKind::StartWith {
                    start_token: self.token_at(idx).clone().into(),
                    condition: self.parse_expr()?.into(),
                });
            } else if let Some(idx) = self.parse_keywords_indexed(&[Keyword::CONNECT, Keyword::BY])
            {
                clauses.push(ConnectByKind::ConnectBy {
                    connect_token: self.token_at(idx).clone().into(),
                    nocycle: self.parse_keyword(Keyword::NOCYCLE),
                    relationships: self.with_state(ParserState::ConnectBy, |parser| {
                        parser.parse_comma_separated(Parser::parse_expr)
                    })?,
                });
            } else {
                break;
            }
        }
        Ok(clauses)
    }

    /// Parse `CREATE TABLE x AS TABLE y`
    pub fn parse_as_table(&mut self) -> Result<Table, ParserError> {
        let first_name = self.parse_identifier()?;
        if self.consume_token(&Token::Period) {
            let second_name = self.parse_identifier()?;
            Ok(Table {
                table_name: Some(second_name),
                schema_name: Some(first_name),
            })
        } else {
            Ok(Table {
                table_name: Some(first_name),
                schema_name: None,
            })
        }
    }

    /// Parse a `SET ROLE` statement. Expects SET to be consumed already.
    fn parse_set_role(
        &mut self,
        modifier: Option<ContextModifier>,
    ) -> Result<Statement, ParserError> {
        self.expect_keyword_is(Keyword::ROLE)?;

        let role_name = if self.parse_keyword(Keyword::NONE) {
            None
        } else {
            Some(self.parse_identifier()?)
        };
        Ok(Statement::Set(Set::SetRole {
            context_modifier: modifier,
            role_name,
        }))
    }

    fn parse_set_values(
        &mut self,
        parenthesized_assignment: bool,
    ) -> Result<Vec<Expr>, ParserError> {
        let mut values = vec![];

        if parenthesized_assignment {
            self.expect_token(&Token::LParen)?;
        }

        loop {
            let value = if let Some(expr) = self.try_parse_expr_sub_query()? {
                expr
            } else if let Ok(expr) = self.parse_expr() {
                expr
            } else {
                self.expected_ref("variable value", self.peek_token_ref())?
            };

            values.push(value);
            if self.consume_token(&Token::Comma) {
                continue;
            }

            if parenthesized_assignment {
                self.expect_token(&Token::RParen)?;
            }
            return Ok(values);
        }
    }

    fn parse_context_modifier(&mut self) -> Option<ContextModifier> {
        let modifier =
            self.parse_one_of_keywords(&[Keyword::SESSION, Keyword::LOCAL, Keyword::GLOBAL])?;

        Self::keyword_to_modifier(modifier)
    }

    /// Parse a single SET statement assignment `var = expr`.
    fn parse_set_assignment(&mut self) -> Result<SetAssignment, ParserError> {
        let scope = self.parse_context_modifier();

        let name = if self.dialect.supports_parenthesized_set_variables()
            && self.consume_token(&Token::LParen)
        {
            // Parenthesized assignments are handled in the `parse_set` function after
            // trying to parse list of assignments using this function.
            // If a dialect supports both, and we find a LParen, we early exit from this function.
            self.expected_ref("Unparenthesized assignment", self.peek_token_ref())?
        } else {
            self.parse_object_name(false)?
        };

        if !(self.consume_token(&Token::Eq) || self.parse_keyword(Keyword::TO)) {
            return self.expected_ref("assignment operator", self.peek_token_ref());
        }

        let value = self.parse_expr()?;

        Ok(SetAssignment { scope, name, value })
    }

    fn parse_set(&mut self) -> Result<Statement, ParserError> {
        let hivevar = self.parse_keyword(Keyword::HIVEVAR);

        // Modifier is either HIVEVAR: or a ContextModifier (LOCAL, SESSION, etc), not both
        let scope = if !hivevar {
            self.parse_context_modifier()
        } else {
            None
        };

        if hivevar {
            self.expect_token(&Token::Colon)?;
        }

        if let Some(set_role_stmt) = self.maybe_parse(|parser| parser.parse_set_role(scope))? {
            return Ok(set_role_stmt);
        }

        // Handle special cases first
        if self.parse_keywords(&[Keyword::TIME, Keyword::ZONE])
            || self.parse_keyword(Keyword::TIMEZONE)
        {
            if self.consume_token(&Token::Eq) || self.parse_keyword(Keyword::TO) {
                return Ok(Set::SingleAssignment {
                    scope,
                    hivevar,
                    variable: ObjectName::from(vec!["TIMEZONE".into()]),
                    values: self.parse_set_values(false)?,
                }
                .into());
            } else {
                // A shorthand alias for SET TIME ZONE that doesn't require
                // the assignment operator. It's originally PostgreSQL specific,
                // but we allow it for all the dialects
                return Ok(Set::SetTimeZone {
                    local: scope == Some(ContextModifier::Local),
                    value: self.parse_expr()?,
                }
                .into());
            }
        } else if self.dialect.supports_set_names() && self.parse_keyword(Keyword::NAMES) {
            if self.parse_keyword(Keyword::DEFAULT) {
                return Ok(Set::SetNamesDefault {}.into());
            }
            let charset_name = self.parse_identifier()?;
            let collation_name = if self.parse_one_of_keywords(&[Keyword::COLLATE]).is_some() {
                Some(self.parse_literal_string()?)
            } else {
                None
            };

            return Ok(Set::SetNames {
                charset_name,
                collation_name,
            }
            .into());
        } else if self.parse_keyword(Keyword::CHARACTERISTICS) {
            self.expect_keywords(&[Keyword::AS, Keyword::TRANSACTION])?;
            return Ok(Set::SetTransaction {
                modes: self.parse_transaction_modes()?,
                snapshot: None,
                session: true,
            }
            .into());
        } else if self.parse_keyword(Keyword::TRANSACTION) {
            if self.parse_keyword(Keyword::SNAPSHOT) {
                let snapshot_id = self.parse_value()?;
                return Ok(Set::SetTransaction {
                    modes: vec![],
                    snapshot: Some(snapshot_id),
                    session: false,
                }
                .into());
            }
            return Ok(Set::SetTransaction {
                modes: self.parse_transaction_modes()?,
                snapshot: None,
                session: false,
            }
            .into());
        } else if self.parse_keyword(Keyword::AUTHORIZATION) {
            let scope = match scope {
                Some(s) => s,
                None => {
                    return self.expected_at(
                        "SESSION, LOCAL, or other scope modifier before AUTHORIZATION",
                        self.get_current_index(),
                    )
                }
            };
            let auth_value = if self.parse_keyword(Keyword::DEFAULT) {
                SetSessionAuthorizationParamKind::Default
            } else {
                let value = self.parse_identifier()?;
                SetSessionAuthorizationParamKind::User(value)
            };
            return Ok(Set::SetSessionAuthorization(SetSessionAuthorizationParam {
                scope,
                kind: auth_value,
            })
            .into());
        }

        if self.dialect.supports_comma_separated_set_assignments() {
            if scope.is_some() {
                self.prev_token();
            }

            if let Some(assignments) = self
                .maybe_parse(|parser| parser.parse_comma_separated(Parser::parse_set_assignment))?
            {
                return if assignments.len() > 1 {
                    Ok(Set::MultipleAssignments { assignments }.into())
                } else {
                    let SetAssignment { scope, name, value } =
                        assignments.into_iter().next().ok_or_else(|| {
                            ParserError::ParserError("Expected at least one assignment".to_string())
                        })?;

                    Ok(Set::SingleAssignment {
                        scope,
                        hivevar,
                        variable: name,
                        values: vec![value],
                    }
                    .into())
                };
            }
        }

        let variables = if self.dialect.supports_parenthesized_set_variables()
            && self.consume_token(&Token::LParen)
        {
            let vars = OneOrManyWithParens::Many(
                self.parse_comma_separated(|parser: &mut Parser<'a>| parser.parse_identifier())?
                    .into_iter()
                    .map(|ident| ObjectName::from(vec![ident]))
                    .collect(),
            );
            self.expect_token(&Token::RParen)?;
            vars
        } else {
            OneOrManyWithParens::One(self.parse_object_name(false)?)
        };

        if self.consume_token(&Token::Eq) || self.parse_keyword(Keyword::TO) {
            let stmt = match variables {
                OneOrManyWithParens::One(var) => Set::SingleAssignment {
                    scope,
                    hivevar,
                    variable: var,
                    values: self.parse_set_values(false)?,
                },
                OneOrManyWithParens::Many(vars) => Set::ParenthesizedAssignments {
                    variables: vars,
                    values: self.parse_set_values(true)?,
                },
            };

            return Ok(stmt.into());
        }

        if self.dialect.supports_set_stmt_without_operator() {
            self.prev_token();
            return self.parse_set_session_params();
        };

        self.expected_ref("equals sign or TO", self.peek_token_ref())
    }

    /// Parse session parameter assignments after `SET` when no `=` or `TO` is present.
    pub fn parse_set_session_params(&mut self) -> Result<Statement, ParserError> {
        if self.parse_keyword(Keyword::STATISTICS) {
            let topic = match self.parse_one_of_keywords(&[
                Keyword::IO,
                Keyword::PROFILE,
                Keyword::TIME,
                Keyword::XML,
            ]) {
                Some(Keyword::IO) => SessionParamStatsTopic::IO,
                Some(Keyword::PROFILE) => SessionParamStatsTopic::Profile,
                Some(Keyword::TIME) => SessionParamStatsTopic::Time,
                Some(Keyword::XML) => SessionParamStatsTopic::Xml,
                _ => return self.expected_ref("IO, PROFILE, TIME or XML", self.peek_token_ref()),
            };
            let value = self.parse_session_param_value()?;
            Ok(
                Set::SetSessionParam(SetSessionParamKind::Statistics(SetSessionParamStatistics {
                    topic,
                    value,
                }))
                .into(),
            )
        } else if self.parse_keyword(Keyword::IDENTITY_INSERT) {
            let obj = self.parse_object_name(false)?;
            let value = self.parse_session_param_value()?;
            Ok(Set::SetSessionParam(SetSessionParamKind::IdentityInsert(
                SetSessionParamIdentityInsert { obj, value },
            ))
            .into())
        } else if self.parse_keyword(Keyword::OFFSETS) {
            let keywords = self.parse_comma_separated(|parser| {
                let next_token = parser.next_token();
                match &next_token.token {
                    Token::Word(w) => Ok(w.to_string()),
                    _ => parser.expected("SQL keyword", next_token),
                }
            })?;
            let value = self.parse_session_param_value()?;
            Ok(
                Set::SetSessionParam(SetSessionParamKind::Offsets(SetSessionParamOffsets {
                    keywords,
                    value,
                }))
                .into(),
            )
        } else {
            let names = self.parse_comma_separated(|parser| {
                let next_token = parser.next_token();
                match next_token.token {
                    Token::Word(w) => Ok(w.to_string()),
                    _ => parser.expected("Session param name", next_token),
                }
            })?;
            let value = self.parse_expr()?.to_string();
            Ok(
                Set::SetSessionParam(SetSessionParamKind::Generic(SetSessionParamGeneric {
                    names,
                    value,
                }))
                .into(),
            )
        }
    }

    fn parse_session_param_value(&mut self) -> Result<SessionParamValue, ParserError> {
        if self.parse_keyword(Keyword::ON) {
            Ok(SessionParamValue::On)
        } else if self.parse_keyword(Keyword::OFF) {
            Ok(SessionParamValue::Off)
        } else {
            self.expected_ref("ON or OFF", self.peek_token_ref())
        }
    }

    /// Parse a `SHOW` statement and dispatch to specific SHOW handlers.
    pub fn parse_show(&mut self) -> Result<Statement, ParserError> {
        let terse = self.parse_keyword(Keyword::TERSE);
        let extended = self.parse_keyword(Keyword::EXTENDED);
        let full = self.parse_keyword(Keyword::FULL);
        let session = self.parse_keyword(Keyword::SESSION);
        let global = self.parse_keyword(Keyword::GLOBAL);
        let external = self.parse_keyword(Keyword::EXTERNAL);
        if self
            .parse_one_of_keywords(&[Keyword::COLUMNS, Keyword::FIELDS])
            .is_some()
        {
            Ok(self.parse_show_columns(extended, full)?)
        } else if self.parse_keyword(Keyword::TABLES) {
            Ok(self.parse_show_tables(terse, extended, full, external)?)
        } else if self.parse_keywords(&[Keyword::MATERIALIZED, Keyword::VIEWS]) {
            Ok(self.parse_show_views(terse, true)?)
        } else if self.parse_keyword(Keyword::VIEWS) {
            Ok(self.parse_show_views(terse, false)?)
        } else if self.parse_keyword(Keyword::FUNCTIONS) {
            Ok(self.parse_show_functions()?)
        } else if self.parse_keyword(Keyword::PROCESSLIST) {
            Ok(Statement::ShowProcessList { full })
        } else if extended || full {
            Err(ParserError::ParserError(
                "EXTENDED/FULL are not supported with this type of SHOW query".to_string(),
            ))
        } else if self.parse_one_of_keywords(&[Keyword::CREATE]).is_some() {
            Ok(self.parse_show_create()?)
        } else if self.parse_keyword(Keyword::COLLATION) {
            Ok(self.parse_show_collation()?)
        } else if self.parse_keyword(Keyword::VARIABLES)
            && dialect_of!(self is MySqlDialect | GenericDialect)
        {
            Ok(Statement::ShowVariables {
                filter: self.parse_show_statement_filter()?,
                session,
                global,
            })
        } else if self.parse_keyword(Keyword::STATUS)
            && dialect_of!(self is MySqlDialect | GenericDialect)
        {
            Ok(Statement::ShowStatus {
                filter: self.parse_show_statement_filter()?,
                session,
                global,
            })
        } else if self.parse_keyword(Keyword::CATALOGS) {
            self.parse_show_catalogs(terse)
        } else if self.parse_keyword(Keyword::DATABASES) {
            self.parse_show_databases(terse)
        } else if self.parse_keyword(Keyword::SCHEMAS) {
            self.parse_show_schemas(terse)
        } else if self.parse_keywords(&[Keyword::CHARACTER, Keyword::SET]) {
            self.parse_show_charset(false)
        } else if self.parse_keyword(Keyword::CHARSET) {
            self.parse_show_charset(true)
        } else {
            Ok(Statement::ShowVariable {
                variable: self.parse_identifiers()?,
            })
        }
    }

    fn parse_show_charset(&mut self, is_shorthand: bool) -> Result<Statement, ParserError> {
        // parse one of keywords
        Ok(Statement::ShowCharset(ShowCharset {
            is_shorthand,
            filter: self.parse_show_statement_filter()?,
        }))
    }

    fn parse_show_catalogs(&mut self, terse: bool) -> Result<Statement, ParserError> {
        let history = self.parse_keyword(Keyword::HISTORY);
        let show_options = self.parse_show_stmt_options()?;
        Ok(Statement::ShowCatalogs {
            terse,
            history,
            show_options,
        })
    }

    fn parse_show_databases(&mut self, terse: bool) -> Result<Statement, ParserError> {
        let history = self.parse_keyword(Keyword::HISTORY);
        let show_options = self.parse_show_stmt_options()?;
        Ok(Statement::ShowDatabases {
            terse,
            history,
            show_options,
        })
    }

    fn parse_show_schemas(&mut self, terse: bool) -> Result<Statement, ParserError> {
        let history = self.parse_keyword(Keyword::HISTORY);
        let show_options = self.parse_show_stmt_options()?;
        Ok(Statement::ShowSchemas {
            terse,
            history,
            show_options,
        })
    }

    /// Parse `SHOW CREATE <object>` returning the corresponding `ShowCreate` statement.
    pub fn parse_show_create(&mut self) -> Result<Statement, ParserError> {
        let obj_type = match self.expect_one_of_keywords(&[
            Keyword::TABLE,
            Keyword::TRIGGER,
            Keyword::FUNCTION,
            Keyword::PROCEDURE,
            Keyword::EVENT,
            Keyword::VIEW,
        ])? {
            Keyword::TABLE => Ok(ShowCreateObject::Table),
            Keyword::TRIGGER => Ok(ShowCreateObject::Trigger),
            Keyword::FUNCTION => Ok(ShowCreateObject::Function),
            Keyword::PROCEDURE => Ok(ShowCreateObject::Procedure),
            Keyword::EVENT => Ok(ShowCreateObject::Event),
            Keyword::VIEW => Ok(ShowCreateObject::View),
            keyword => Err(ParserError::ParserError(format!(
                "Unable to map keyword to ShowCreateObject: {keyword:?}"
            ))),
        }?;

        let obj_name = self.parse_object_name(false)?;

        Ok(Statement::ShowCreate { obj_type, obj_name })
    }

    /// Parse `SHOW COLUMNS`/`SHOW FIELDS` and return a `ShowColumns` statement.
    pub fn parse_show_columns(
        &mut self,
        extended: bool,
        full: bool,
    ) -> Result<Statement, ParserError> {
        let show_options = self.parse_show_stmt_options()?;
        Ok(Statement::ShowColumns {
            extended,
            full,
            show_options,
        })
    }

    fn parse_show_tables(
        &mut self,
        terse: bool,
        extended: bool,
        full: bool,
        external: bool,
    ) -> Result<Statement, ParserError> {
        let history = !external && self.parse_keyword(Keyword::HISTORY);
        let show_options = self.parse_show_stmt_options()?;
        Ok(Statement::ShowTables {
            terse,
            history,
            extended,
            full,
            external,
            show_options,
        })
    }

    fn parse_show_views(
        &mut self,
        terse: bool,
        materialized: bool,
    ) -> Result<Statement, ParserError> {
        let show_options = self.parse_show_stmt_options()?;
        Ok(Statement::ShowViews {
            materialized,
            terse,
            show_options,
        })
    }

    /// Parse `SHOW FUNCTIONS` and optional filter.
    pub fn parse_show_functions(&mut self) -> Result<Statement, ParserError> {
        let filter = self.parse_show_statement_filter()?;
        Ok(Statement::ShowFunctions { filter })
    }

    /// Parse `SHOW COLLATION` and optional filter.
    pub fn parse_show_collation(&mut self) -> Result<Statement, ParserError> {
        let filter = self.parse_show_statement_filter()?;
        Ok(Statement::ShowCollation { filter })
    }

    /// Parse an optional filter used by `SHOW` statements (LIKE, ILIKE, WHERE, or literal).
    pub fn parse_show_statement_filter(
        &mut self,
    ) -> Result<Option<ShowStatementFilter>, ParserError> {
        if self.parse_keyword(Keyword::LIKE) {
            Ok(Some(ShowStatementFilter::Like(
                self.parse_literal_string()?,
            )))
        } else if self.parse_keyword(Keyword::ILIKE) {
            Ok(Some(ShowStatementFilter::ILike(
                self.parse_literal_string()?,
            )))
        } else if self.parse_keyword(Keyword::WHERE) {
            Ok(Some(ShowStatementFilter::Where(self.parse_expr()?)))
        } else {
            self.maybe_parse(|parser| -> Result<String, ParserError> {
                parser.parse_literal_string()
            })?
            .map_or(Ok(None), |filter| {
                Ok(Some(ShowStatementFilter::NoKeyword(filter)))
            })
        }
    }

    /// Parse a `USE` statement (database/catalog/schema/warehouse/role selection).
    pub fn parse_use(&mut self) -> Result<Statement, ParserError> {
        // Determine which keywords are recognized by the current dialect
        let parsed_keyword = if dialect_of!(self is HiveDialect) {
            // HiveDialect accepts USE DEFAULT; statement without any db specified
            if self.parse_keyword(Keyword::DEFAULT) {
                return Ok(Statement::Use(Use::Default));
            }
            None // HiveDialect doesn't expect any other specific keyword after `USE`
        } else if dialect_of!(self is DatabricksDialect) {
            self.parse_one_of_keywords(&[Keyword::CATALOG, Keyword::DATABASE, Keyword::SCHEMA])
        } else if dialect_of!(self is SnowflakeDialect) {
            self.parse_one_of_keywords(&[
                Keyword::DATABASE,
                Keyword::SCHEMA,
                Keyword::WAREHOUSE,
                Keyword::ROLE,
                Keyword::SECONDARY,
            ])
        } else {
            None // No specific keywords for other dialects, including GenericDialect
        };

        let result = if matches!(parsed_keyword, Some(Keyword::SECONDARY)) {
            self.parse_secondary_roles()?
        } else {
            let obj_name = self.parse_object_name(false)?;
            match parsed_keyword {
                Some(Keyword::CATALOG) => Use::Catalog(obj_name),
                Some(Keyword::DATABASE) => Use::Database(obj_name),
                Some(Keyword::SCHEMA) => Use::Schema(obj_name),
                Some(Keyword::WAREHOUSE) => Use::Warehouse(obj_name),
                Some(Keyword::ROLE) => Use::Role(obj_name),
                _ => Use::Object(obj_name),
            }
        };

        Ok(Statement::Use(result))
    }

    fn parse_secondary_roles(&mut self) -> Result<Use, ParserError> {
        self.expect_one_of_keywords(&[Keyword::ROLES, Keyword::ROLE])?;
        if self.parse_keyword(Keyword::NONE) {
            Ok(Use::SecondaryRoles(SecondaryRoles::None))
        } else if self.parse_keyword(Keyword::ALL) {
            Ok(Use::SecondaryRoles(SecondaryRoles::All))
        } else {
            let roles = self.parse_comma_separated(|parser| parser.parse_identifier())?;
            Ok(Use::SecondaryRoles(SecondaryRoles::List(roles)))
        }
    }

    /// Parse a table factor followed by any join clauses, returning `TableWithJoins`.
    pub fn parse_table_and_joins(&mut self) -> Result<TableWithJoins, ParserError> {
        let relation = self.parse_table_factor()?;
        // Note that for keywords to be properly handled here, they need to be
        // added to `RESERVED_FOR_TABLE_ALIAS`, otherwise they may be parsed as
        // a table alias.
        let joins = self.parse_joins()?;
        Ok(TableWithJoins { relation, joins })
    }

    fn parse_joins(&mut self) -> Result<Vec<Join>, ParserError> {
        let mut joins = vec![];
        loop {
            let global = self.parse_keyword(Keyword::GLOBAL);
            let join = if self.parse_keyword(Keyword::CROSS) {
                let join_operator = if self.parse_keyword(Keyword::JOIN) {
                    JoinOperator::CrossJoin(JoinConstraint::None)
                } else if self.parse_keyword(Keyword::APPLY) {
                    // MSSQL extension, similar to CROSS JOIN LATERAL
                    JoinOperator::CrossApply
                } else {
                    return self.expected_ref("JOIN or APPLY after CROSS", self.peek_token_ref());
                };
                let relation = self.parse_table_factor()?;
                let join_operator = if matches!(join_operator, JoinOperator::CrossJoin(_))
                    && self.dialect.supports_cross_join_constraint()
                {
                    let constraint = self.parse_join_constraint(false)?;
                    JoinOperator::CrossJoin(constraint)
                } else {
                    join_operator
                };
                Join {
                    relation,
                    global,
                    join_operator,
                }
            } else if self.parse_keyword(Keyword::OUTER) {
                // MSSQL extension, similar to LEFT JOIN LATERAL .. ON 1=1
                self.expect_keyword_is(Keyword::APPLY)?;
                Join {
                    relation: self.parse_table_factor()?,
                    global,
                    join_operator: JoinOperator::OuterApply,
                }
            } else if self.parse_keyword(Keyword::ASOF) {
                self.expect_keyword_is(Keyword::JOIN)?;
                let relation = self.parse_table_factor()?;
                self.expect_keyword_is(Keyword::MATCH_CONDITION)?;
                let match_condition = self.parse_parenthesized(Self::parse_expr)?;
                Join {
                    relation,
                    global,
                    join_operator: JoinOperator::AsOf {
                        match_condition,
                        constraint: self.parse_join_constraint(false)?,
                    },
                }
            } else if self.dialect.supports_array_join_syntax()
                && self.parse_keywords(&[Keyword::INNER, Keyword::ARRAY, Keyword::JOIN])
            {
                // ClickHouse: INNER ARRAY JOIN
                Join {
                    relation: self.parse_table_factor()?,
                    global,
                    join_operator: JoinOperator::InnerArrayJoin,
                }
            } else if self.dialect.supports_array_join_syntax()
                && self.parse_keywords(&[Keyword::LEFT, Keyword::ARRAY, Keyword::JOIN])
            {
                // ClickHouse: LEFT ARRAY JOIN
                Join {
                    relation: self.parse_table_factor()?,
                    global,
                    join_operator: JoinOperator::LeftArrayJoin,
                }
            } else if self.dialect.supports_array_join_syntax()
                && self.parse_keywords(&[Keyword::ARRAY, Keyword::JOIN])
            {
                // ClickHouse: ARRAY JOIN
                Join {
                    relation: self.parse_table_factor()?,
                    global,
                    join_operator: JoinOperator::ArrayJoin,
                }
            } else {
                let natural = self.parse_keyword(Keyword::NATURAL);
                let peek_keyword = if let Token::Word(w) = &self.peek_token_ref().token {
                    w.keyword
                } else {
                    Keyword::NoKeyword
                };

                let join_operator_type = match peek_keyword {
                    Keyword::INNER | Keyword::JOIN => {
                        let inner = self.parse_keyword(Keyword::INNER); // [ INNER ]
                        self.expect_keyword_is(Keyword::JOIN)?;
                        if inner {
                            JoinOperator::Inner
                        } else {
                            JoinOperator::Join
                        }
                    }
                    kw @ Keyword::LEFT | kw @ Keyword::RIGHT => {
                        let _ = self.next_token(); // consume LEFT/RIGHT
                        let is_left = kw == Keyword::LEFT;
                        let join_type = self.parse_one_of_keywords(&[
                            Keyword::OUTER,
                            Keyword::SEMI,
                            Keyword::ANTI,
                            Keyword::JOIN,
                        ]);
                        match join_type {
                            Some(Keyword::OUTER) => {
                                self.expect_keyword_is(Keyword::JOIN)?;
                                if is_left {
                                    JoinOperator::LeftOuter
                                } else {
                                    JoinOperator::RightOuter
                                }
                            }
                            Some(Keyword::SEMI) => {
                                self.expect_keyword_is(Keyword::JOIN)?;
                                if is_left {
                                    JoinOperator::LeftSemi
                                } else {
                                    JoinOperator::RightSemi
                                }
                            }
                            Some(Keyword::ANTI) => {
                                self.expect_keyword_is(Keyword::JOIN)?;
                                if is_left {
                                    JoinOperator::LeftAnti
                                } else {
                                    JoinOperator::RightAnti
                                }
                            }
                            Some(Keyword::JOIN) => {
                                if is_left {
                                    JoinOperator::Left
                                } else {
                                    JoinOperator::Right
                                }
                            }
                            _ => {
                                return Err(ParserError::ParserError(format!(
                                    "expected OUTER, SEMI, ANTI or JOIN after {kw:?}"
                                )))
                            }
                        }
                    }
                    Keyword::ANTI => {
                        let _ = self.next_token(); // consume ANTI
                        self.expect_keyword_is(Keyword::JOIN)?;
                        JoinOperator::Anti
                    }
                    Keyword::SEMI => {
                        let _ = self.next_token(); // consume SEMI
                        self.expect_keyword_is(Keyword::JOIN)?;
                        JoinOperator::Semi
                    }
                    Keyword::FULL => {
                        let _ = self.next_token(); // consume FULL
                        let _ = self.parse_keyword(Keyword::OUTER); // [ OUTER ]
                        self.expect_keyword_is(Keyword::JOIN)?;
                        JoinOperator::FullOuter
                    }
                    Keyword::OUTER => {
                        return self.expected_ref("LEFT, RIGHT, or FULL", self.peek_token_ref());
                    }
                    Keyword::STRAIGHT_JOIN => {
                        let _ = self.next_token(); // consume STRAIGHT_JOIN
                        JoinOperator::StraightJoin
                    }
                    _ if natural => {
                        return self
                            .expected_ref("a join type after NATURAL", self.peek_token_ref());
                    }
                    _ => break,
                };
                let mut relation = self.parse_table_factor()?;

                if !self
                    .dialect
                    .supports_left_associative_joins_without_parens()
                    && !natural
                    && self.peek_parens_less_nested_join()
                {
                    let joins = self.parse_joins()?;
                    relation = TableFactor::NestedJoin {
                        table_with_joins: Box::new(TableWithJoins { relation, joins }),
                        alias: None,
                    };
                }

                let join_constraint = self.parse_join_constraint(natural)?;
                Join {
                    relation,
                    global,
                    join_operator: join_operator_type(join_constraint),
                }
            };
            joins.push(join);
        }
        Ok(joins)
    }

    fn peek_parens_less_nested_join(&self) -> bool {
        matches!(
            self.peek_token_ref().token,
            Token::Word(Word {
                keyword: Keyword::JOIN
                    | Keyword::INNER
                    | Keyword::LEFT
                    | Keyword::RIGHT
                    | Keyword::FULL,
                ..
            })
        )
    }

    /// A table name or a parenthesized subquery, followed by optional `[AS] alias`
    #[cfg_attr(feature = "recursive-protection", recursive::recursive)]
    pub fn parse_table_factor(&mut self) -> Result<TableFactor, ParserError> {
        let _guard = self.recursion_counter.try_decrease()?;
        if self.parse_keyword(Keyword::LATERAL) {
            // LATERAL must always be followed by a subquery or table function.
            if self.consume_token(&Token::LParen) {
                self.parse_derived_table_factor(Lateral)
            } else {
                let name = self.parse_object_name(false)?;
                self.expect_token(&Token::LParen)?;
                let args = self.parse_optional_args()?;
                let with_ordinality = self.parse_keywords(&[Keyword::WITH, Keyword::ORDINALITY]);
                let alias = self.maybe_parse_table_alias()?;
                Ok(TableFactor::Function {
                    lateral: true,
                    name,
                    args,
                    with_ordinality,
                    alias,
                })
            }
        } else if self.parse_keyword(Keyword::TABLE) {
            // parse table function (SELECT * FROM TABLE (<expr>) [ AS <alias> ])
            self.expect_token(&Token::LParen)?;
            let expr = self.parse_expr()?;
            self.expect_token(&Token::RParen)?;
            let alias = self.maybe_parse_table_alias()?;
            Ok(TableFactor::TableFunction { expr, alias })
        } else if self.consume_token(&Token::LParen) {
            // A left paren introduces either a derived table (i.e., a subquery)
            // or a nested join. It's nearly impossible to determine ahead of
            // time which it is... so we just try to parse both.
            //
            // Here's an example that demonstrates the complexity:
            //                     /-------------------------------------------------------\
            //                     | /-----------------------------------\                 |
            //     SELECT * FROM ( ( ( (SELECT 1) UNION (SELECT 2) ) AS t1 NATURAL JOIN t2 ) )
            //                   ^ ^ ^ ^
            //                   | | | |
            //                   | | | |
            //                   | | | (4) belongs to a SetExpr::Query inside the subquery
            //                   | | (3) starts a derived table (subquery)
            //                   | (2) starts a nested join
            //                   (1) an additional set of parens around a nested join
            //

            // If the recently consumed '(' starts a derived table, the call to
            // `parse_derived_table_factor` below will return success after parsing the
            // subquery, followed by the closing ')', and the alias of the derived table.
            // In the example above this is case (3).
            //
            // Memoize failures to break the 2^N work on inputs like
            // `FROM ((((...`, where the nested-join fallback recurses back into
            // `parse_table_factor` and re-attempts the same speculative parse.
            let derived_pos = self.index;
            let derived = if self
                .failed_derived_table_factor_positions
                .contains(&derived_pos)
            {
                None
            } else {
                match self.maybe_parse(|parser| parser.parse_derived_table_factor(NotLateral))? {
                    Some(t) => Some(t),
                    None => {
                        self.failed_derived_table_factor_positions
                            .insert(derived_pos);
                        None
                    }
                }
            };
            if let Some(mut table) = derived {
                while let Some(kw) = self.parse_one_of_keywords(&[Keyword::PIVOT, Keyword::UNPIVOT])
                {
                    table = match kw {
                        Keyword::PIVOT => self.parse_pivot_table_factor(table)?,
                        Keyword::UNPIVOT => self.parse_unpivot_table_factor(table)?,
                        unexpected_keyword => return Err(ParserError::ParserError(
                            format!("Internal parser error: unexpected keyword `{unexpected_keyword}` in pivot/unpivot"),
                        )),
                    }
                }
                return Ok(table);
            }

            // A parsing error from `parse_derived_table_factor` indicates that the '(' we've
            // recently consumed does not start a derived table (cases 1, 2, or 4).
            // `maybe_parse` will ignore such an error and rewind to be after the opening '('.

            // Inside the parentheses we expect to find an (A) table factor
            // followed by some joins or (B) another level of nesting.
            let mut table_and_joins = self.parse_table_and_joins()?;

            if !table_and_joins.joins.is_empty() {
                self.expect_token(&Token::RParen)?;
                let alias = self.maybe_parse_table_alias()?;
                Ok(TableFactor::NestedJoin {
                    table_with_joins: Box::new(table_and_joins),
                    alias,
                }) // (A)
            } else if let TableFactor::NestedJoin {
                table_with_joins: _,
                alias: _,
            } = &table_and_joins.relation
            {
                // (B): `table_and_joins` (what we found inside the parentheses)
                // is a nested join `(foo JOIN bar)`, not followed by other joins.
                self.expect_token(&Token::RParen)?;
                let alias = self.maybe_parse_table_alias()?;
                Ok(TableFactor::NestedJoin {
                    table_with_joins: Box::new(table_and_joins),
                    alias,
                })
            } else if self.dialect.supports_parens_around_table_factor() {
                // Dialect-specific behavior: Snowflake diverges from the
                // standard and from most of the other implementations by
                // allowing extra parentheses not only around a join (B), but
                // around lone table names (e.g. `FROM (mytable [AS alias])`)
                // and around derived tables (e.g. `FROM ((SELECT ...)
                // [AS alias])`) as well.
                self.expect_token(&Token::RParen)?;

                if let Some(outer_alias) = self.maybe_parse_table_alias()? {
                    // Snowflake also allows specifying an alias *after* parens
                    // e.g. `FROM (mytable) AS alias`
                    match &mut table_and_joins.relation {
                        TableFactor::Derived { alias, .. }
                        | TableFactor::Table { alias, .. }
                        | TableFactor::Function { alias, .. }
                        | TableFactor::UNNEST { alias, .. }
                        | TableFactor::JsonTable { alias, .. }
                        | TableFactor::XmlTable { alias, .. }
                        | TableFactor::OpenJsonTable { alias, .. }
                        | TableFactor::TableFunction { alias, .. }
                        | TableFactor::Pivot { alias, .. }
                        | TableFactor::Unpivot { alias, .. }
                        | TableFactor::MatchRecognize { alias, .. }
                        | TableFactor::SemanticView { alias, .. }
                        | TableFactor::NestedJoin { alias, .. } => {
                            // but not `FROM (mytable AS alias1) AS alias2`.
                            if let Some(inner_alias) = alias {
                                return Err(ParserError::ParserError(format!(
                                    "duplicate alias {inner_alias}"
                                )));
                            }
                            // Act as if the alias was specified normally next
                            // to the table name: `(mytable) AS alias` ->
                            // `(mytable AS alias)`
                            alias.replace(outer_alias);
                        }
                        TableFactor::UnpivotExpr { .. } => {
                            return Err(ParserError::ParserError(
                                "alias after parenthesized UNPIVOT expression is not supported"
                                    .to_string(),
                            ))
                        }
                    };
                }
                // Do not store the extra set of parens in the AST
                Ok(table_and_joins.relation)
            } else {
                // The SQL spec prohibits derived tables and bare tables from
                // appearing alone in parentheses (e.g. `FROM (mytable)`)
                self.expected_ref("joined table", self.peek_token_ref())
            }
        } else if self.dialect.supports_values_as_table_factor()
            && matches!(
                self.peek_tokens(),
                [
                    Token::Word(Word {
                        keyword: Keyword::VALUES,
                        ..
                    }),
                    Token::LParen
                ]
            )
        {
            self.expect_keyword_is(Keyword::VALUES)?;

            // Snowflake and Databricks allow syntax like below:
            // SELECT * FROM VALUES (1, 'a'), (2, 'b') AS t (col1, col2)
            // where there are no parentheses around the VALUES clause.
            let values = SetExpr::Values(self.parse_values(false, false)?);
            let alias = self.maybe_parse_table_alias()?;
            Ok(TableFactor::Derived {
                lateral: false,
                subquery: Box::new(Query {
                    with: None,
                    body: Box::new(values),
                    order_by: None,
                    limit_clause: None,
                    fetch: None,
                    locks: vec![],
                    for_clause: None,
                    settings: None,
                    format_clause: None,
                    pipe_operators: vec![],
                }),
                alias,
                sample: None,
            })
        } else if dialect_of!(self is BigQueryDialect | PostgreSqlDialect | GenericDialect)
            && self.parse_keyword(Keyword::UNNEST)
        {
            self.expect_token(&Token::LParen)?;
            let array_exprs = self.parse_comma_separated(Parser::parse_expr)?;
            self.expect_token(&Token::RParen)?;

            let with_ordinality = self.parse_keywords(&[Keyword::WITH, Keyword::ORDINALITY]);
            let alias = match self.maybe_parse_table_alias() {
                Ok(Some(alias)) => Some(alias),
                Ok(None) => None,
                Err(e) => return Err(e),
            };

            let with_offset = match self.expect_keywords(&[Keyword::WITH, Keyword::OFFSET]) {
                Ok(()) => true,
                Err(_) => false,
            };

            let with_offset_alias = if with_offset {
                match self.parse_optional_alias(keywords::RESERVED_FOR_COLUMN_ALIAS) {
                    Ok(Some(alias)) => Some(alias),
                    Ok(None) => None,
                    Err(e) => return Err(e),
                }
            } else {
                None
            };

            Ok(TableFactor::UNNEST {
                alias,
                array_exprs,
                with_offset,
                with_offset_alias,
                with_ordinality,
            })
        } else if self.dialect.supports_unpivot_expr() && self.peek_keyword(Keyword::UNPIVOT) {
            self.parse_unpivot_expr_table_factor()
        } else if self.parse_keyword_with_tokens(Keyword::JSON_TABLE, &[Token::LParen]) {
            let json_expr = self.parse_expr()?;
            self.expect_token(&Token::Comma)?;
            let json_path = self.parse_value()?;
            self.expect_keyword_is(Keyword::COLUMNS)?;
            self.expect_token(&Token::LParen)?;
            let columns = self.parse_comma_separated(Parser::parse_json_table_column_def)?;
            self.expect_token(&Token::RParen)?;
            self.expect_token(&Token::RParen)?;
            let alias = self.maybe_parse_table_alias()?;
            Ok(TableFactor::JsonTable {
                json_expr,
                json_path,
                columns,
                alias,
            })
        } else if self.parse_keyword_with_tokens(Keyword::OPENJSON, &[Token::LParen]) {
            self.prev_token();
            self.parse_open_json_table_factor()
        } else if self.parse_keyword_with_tokens(Keyword::XMLTABLE, &[Token::LParen]) {
            self.prev_token();
            self.parse_xml_table_factor()
        } else if self.dialect.supports_semantic_view_table_factor()
            && self.peek_keyword_with_tokens(Keyword::SEMANTIC_VIEW, &[Token::LParen])
        {
            self.parse_semantic_view_table_factor()
        } else if self.dialect.supports_stages() && self.peek_token_ref().token == Token::AtSign {
            // Stage reference: @mystage or @namespace.stage (e.g. Snowflake)
            self.parse_snowflake_stage_table_factor()
        } else {
            let name = self.parse_object_name(true)?;

            let json_path = match &self.peek_token_ref().token {
                Token::LBracket if self.dialect.supports_partiql() => Some(self.parse_json_path()?),
                _ => None,
            };

            let partitions: Vec<Ident> = if self.dialect.supports_table_partitions()
                && self.parse_keyword(Keyword::PARTITION)
            {
                self.parse_parenthesized_identifiers()?
            } else {
                vec![]
            };

            // Parse potential version qualifier
            let version = self.maybe_parse_table_version()?;

            // Postgres, MSSQL, ClickHouse: table-valued functions:
            let args = if self.consume_token(&Token::LParen) {
                Some(self.parse_table_function_args()?)
            } else {
                None
            };

            let with_ordinality = self.parse_keywords(&[Keyword::WITH, Keyword::ORDINALITY]);

            let mut sample = None;
            if self.dialect.supports_table_sample_before_alias() {
                if let Some(parsed_sample) = self.maybe_parse_table_sample()? {
                    sample = Some(TableSampleKind::BeforeTableAlias(parsed_sample));
                }
            }

            let alias = self.maybe_parse_table_alias()?;

            // MYSQL-specific table hints:
            let index_hints = if self.dialect.supports_table_hints() {
                self.maybe_parse(|p| p.parse_table_index_hints())?
                    .unwrap_or(vec![])
            } else {
                vec![]
            };

            // MSSQL-specific table hints:
            let mut with_hints = vec![];
            if self.parse_keyword(Keyword::WITH) {
                if self.consume_token(&Token::LParen) {
                    with_hints = self.parse_comma_separated(Parser::parse_expr)?;
                    self.expect_token(&Token::RParen)?;
                } else {
                    // rewind, as WITH may belong to the next statement's CTE
                    self.prev_token();
                }
            };

            if !self.dialect.supports_table_sample_before_alias() {
                if let Some(parsed_sample) = self.maybe_parse_table_sample()? {
                    sample = Some(TableSampleKind::AfterTableAlias(parsed_sample));
                }
            }

            let mut table = TableFactor::Table {
                name,
                alias,
                args,
                with_hints,
                version,
                partitions,
                with_ordinality,
                json_path,
                sample,
                index_hints,
            };

            while let Some(kw) = self.parse_one_of_keywords(&[Keyword::PIVOT, Keyword::UNPIVOT]) {
                table = match kw {
                    Keyword::PIVOT => self.parse_pivot_table_factor(table)?,
                    Keyword::UNPIVOT => self.parse_unpivot_table_factor(table)?,
                    unexpected_keyword => return Err(ParserError::ParserError(
                        format!("Internal parser error: unexpected keyword `{unexpected_keyword}` in pivot/unpivot"),
                    )),
                }
            }

            if self.dialect.supports_match_recognize()
                && self.parse_keyword(Keyword::MATCH_RECOGNIZE)
            {
                table = self.parse_match_recognize(table)?;
            }

            Ok(table)
        }
    }

    /// Parse a Snowflake stage reference as a table factor.
    /// Handles syntax like: `@mystage1 (file_format => 'myformat', pattern => '...')`
    ///
    /// See: <https://docs.snowflake.com/en/user-guide/querying-stage>
    fn parse_snowflake_stage_table_factor(&mut self) -> Result<TableFactor, ParserError> {
        // Parse the stage name starting with @
        let name = crate::dialect::parse_snowflake_stage_name(self)?;

        // Parse optional stage options like (file_format => 'myformat', pattern => '...')
        let args = if self.consume_token(&Token::LParen) {
            Some(self.parse_table_function_args()?)
        } else {
            None
        };

        let alias = self.maybe_parse_table_alias()?;

        Ok(TableFactor::Table {
            name,
            alias,
            args,
            with_hints: vec![],
            version: None,
            partitions: vec![],
            with_ordinality: false,
            json_path: None,
            sample: None,
            index_hints: vec![],
        })
    }

    fn maybe_parse_table_sample(&mut self) -> Result<Option<Box<TableSample>>, ParserError> {
        let modifier = if self.parse_keyword(Keyword::TABLESAMPLE) {
            TableSampleModifier::TableSample
        } else if self.parse_keyword(Keyword::SAMPLE) {
            TableSampleModifier::Sample
        } else {
            return Ok(None);
        };
        self.parse_table_sample(modifier).map(Some)
    }

    fn parse_table_sample(
        &mut self,
        modifier: TableSampleModifier,
    ) -> Result<Box<TableSample>, ParserError> {
        let name = match self.parse_one_of_keywords(&[
            Keyword::BERNOULLI,
            Keyword::ROW,
            Keyword::SYSTEM,
            Keyword::BLOCK,
        ]) {
            Some(Keyword::BERNOULLI) => Some(TableSampleMethod::Bernoulli),
            Some(Keyword::ROW) => Some(TableSampleMethod::Row),
            Some(Keyword::SYSTEM) => Some(TableSampleMethod::System),
            Some(Keyword::BLOCK) => Some(TableSampleMethod::Block),
            _ => None,
        };

        let parenthesized = self.consume_token(&Token::LParen);

        let (quantity, bucket) = if parenthesized && self.parse_keyword(Keyword::BUCKET) {
            let selected_bucket = self.parse_number_value()?;
            self.expect_keywords(&[Keyword::OUT, Keyword::OF])?;
            let total = self.parse_number_value()?;
            let on = if self.parse_keyword(Keyword::ON) {
                Some(self.parse_expr()?)
            } else {
                None
            };
            (
                None,
                Some(TableSampleBucket {
                    bucket: selected_bucket,
                    total,
                    on,
                }),
            )
        } else {
            let value = match self.maybe_parse(|p| p.parse_expr())? {
                Some(num) => num,
                None => {
                    let next_token = self.next_token();
                    if let Token::Word(w) = next_token.token {
                        Expr::Value(Value::Placeholder(w.value).with_span(next_token.span))
                    } else {
                        return parser_err!(
                            "Expecting number or byte length e.g. 100M",
                            self.peek_token_ref().span.start
                        );
                    }
                }
            };
            let unit = if self.parse_keyword(Keyword::ROWS) {
                Some(TableSampleUnit::Rows)
            } else if self.parse_keyword(Keyword::PERCENT) {
                Some(TableSampleUnit::Percent)
            } else {
                None
            };
            (
                Some(TableSampleQuantity {
                    parenthesized,
                    value,
                    unit,
                }),
                None,
            )
        };
        if parenthesized {
            self.expect_token(&Token::RParen)?;
        }

        let seed = if self.parse_keyword(Keyword::REPEATABLE) {
            Some(self.parse_table_sample_seed(TableSampleSeedModifier::Repeatable)?)
        } else if self.parse_keyword(Keyword::SEED) {
            Some(self.parse_table_sample_seed(TableSampleSeedModifier::Seed)?)
        } else {
            None
        };

        let offset = if self.parse_keyword(Keyword::OFFSET) {
            Some(self.parse_expr()?)
        } else {
            None
        };

        Ok(Box::new(TableSample {
            modifier,
            name,
            quantity,
            seed,
            bucket,
            offset,
        }))
    }

    fn parse_table_sample_seed(
        &mut self,
        modifier: TableSampleSeedModifier,
    ) -> Result<TableSampleSeed, ParserError> {
        self.expect_token(&Token::LParen)?;
        let value = self.parse_number_value()?;
        self.expect_token(&Token::RParen)?;
        Ok(TableSampleSeed { modifier, value })
    }

    /// Parses `OPENJSON( jsonExpression [ , path ] )  [ <with_clause> ]` clause,
    /// assuming the `OPENJSON` keyword was already consumed.
    fn parse_open_json_table_factor(&mut self) -> Result<TableFactor, ParserError> {
        self.expect_token(&Token::LParen)?;
        let json_expr = self.parse_expr()?;
        let json_path = if self.consume_token(&Token::Comma) {
            Some(self.parse_value()?)
        } else {
            None
        };
        self.expect_token(&Token::RParen)?;
        let columns = if self.parse_keyword(Keyword::WITH) {
            self.expect_token(&Token::LParen)?;
            let columns = self.parse_comma_separated(Parser::parse_openjson_table_column_def)?;
            self.expect_token(&Token::RParen)?;
            columns
        } else {
            Vec::new()
        };
        let alias = self.maybe_parse_table_alias()?;
        Ok(TableFactor::OpenJsonTable {
            json_expr,
            json_path,
            columns,
            alias,
        })
    }

    fn parse_xml_table_factor(&mut self) -> Result<TableFactor, ParserError> {
        self.expect_token(&Token::LParen)?;
        let namespaces = if self.parse_keyword(Keyword::XMLNAMESPACES) {
            self.expect_token(&Token::LParen)?;
            let namespaces = self.parse_comma_separated(Parser::parse_xml_namespace_definition)?;
            self.expect_token(&Token::RParen)?;
            self.expect_token(&Token::Comma)?;
            namespaces
        } else {
            vec![]
        };
        let row_expression = self.parse_expr()?;
        let passing = self.parse_xml_passing_clause()?;
        self.expect_keyword_is(Keyword::COLUMNS)?;
        let columns = self.parse_comma_separated(Parser::parse_xml_table_column)?;
        self.expect_token(&Token::RParen)?;
        let alias = self.maybe_parse_table_alias()?;
        Ok(TableFactor::XmlTable {
            namespaces,
            row_expression,
            passing,
            columns,
            alias,
        })
    }

    fn parse_xml_namespace_definition(&mut self) -> Result<XmlNamespaceDefinition, ParserError> {
        let uri = self.parse_expr()?;
        self.expect_keyword_is(Keyword::AS)?;
        let name = self.parse_identifier()?;
        Ok(XmlNamespaceDefinition { uri, name })
    }

    fn parse_xml_table_column(&mut self) -> Result<XmlTableColumn, ParserError> {
        let name = self.parse_identifier()?;

        let option = if self.parse_keyword(Keyword::FOR) {
            self.expect_keyword(Keyword::ORDINALITY)?;
            XmlTableColumnOption::ForOrdinality
        } else {
            let r#type = self.parse_data_type()?;
            let mut path = None;
            let mut default = None;

            if self.parse_keyword(Keyword::PATH) {
                path = Some(self.parse_expr()?);
            }

            if self.parse_keyword(Keyword::DEFAULT) {
                default = Some(self.parse_expr()?);
            }

            let not_null = self.parse_keywords(&[Keyword::NOT, Keyword::NULL]);
            if !not_null {
                // NULL is the default but can be specified explicitly
                let _ = self.parse_keyword(Keyword::NULL);
            }

            XmlTableColumnOption::NamedInfo {
                r#type,
                path,
                default,
                nullable: !not_null,
            }
        };
        Ok(XmlTableColumn { name, option })
    }

    fn parse_xml_passing_clause(&mut self) -> Result<XmlPassingClause, ParserError> {
        let mut arguments = vec![];
        if self.parse_keyword(Keyword::PASSING) {
            loop {
                let by_value =
                    self.parse_keyword(Keyword::BY) && self.expect_keyword(Keyword::VALUE).is_ok();
                let expr = self.parse_expr()?;
                let alias = if self.parse_keyword(Keyword::AS) {
                    Some(self.parse_identifier()?)
                } else {
                    None
                };
                arguments.push(XmlPassingArgument {
                    expr,
                    alias,
                    by_value,
                });
                if !self.consume_token(&Token::Comma) {
                    break;
                }
            }
        }
        Ok(XmlPassingClause { arguments })
    }

    /// Parse a [TableFactor::SemanticView]
    fn parse_semantic_view_table_factor(&mut self) -> Result<TableFactor, ParserError> {
        self.expect_keyword(Keyword::SEMANTIC_VIEW)?;
        self.expect_token(&Token::LParen)?;

        let name = self.parse_object_name(true)?;

        // Parse DIMENSIONS, METRICS, FACTS and WHERE clauses in flexible order
        let mut dimensions = Vec::new();
        let mut metrics = Vec::new();
        let mut facts = Vec::new();
        let mut where_clause = None;

        while self.peek_token_ref().token != Token::RParen {
            if self.parse_keyword(Keyword::DIMENSIONS) {
                if !dimensions.is_empty() {
                    return Err(ParserError::ParserError(
                        "DIMENSIONS clause can only be specified once".to_string(),
                    ));
                }
                dimensions = self.parse_comma_separated(Parser::parse_wildcard_expr)?;
            } else if self.parse_keyword(Keyword::METRICS) {
                if !metrics.is_empty() {
                    return Err(ParserError::ParserError(
                        "METRICS clause can only be specified once".to_string(),
                    ));
                }
                metrics = self.parse_comma_separated(Parser::parse_wildcard_expr)?;
            } else if self.parse_keyword(Keyword::FACTS) {
                if !facts.is_empty() {
                    return Err(ParserError::ParserError(
                        "FACTS clause can only be specified once".to_string(),
                    ));
                }
                facts = self.parse_comma_separated(Parser::parse_wildcard_expr)?;
            } else if self.parse_keyword(Keyword::WHERE) {
                if where_clause.is_some() {
                    return Err(ParserError::ParserError(
                        "WHERE clause can only be specified once".to_string(),
                    ));
                }
                where_clause = Some(self.parse_expr()?);
            } else {
                let tok = self.peek_token_ref();
                parser_err!(
                    format!(
                        "Expected one of DIMENSIONS, METRICS, FACTS or WHERE, got {}",
                        tok.token
                    ),
                    tok.span.start
                )?;
            }
        }

        self.expect_token(&Token::RParen)?;

        let alias = self.maybe_parse_table_alias()?;

        Ok(TableFactor::SemanticView {
            name,
            dimensions,
            metrics,
            facts,
            where_clause,
            alias,
        })
    }

    fn parse_match_recognize(&mut self, table: TableFactor) -> Result<TableFactor, ParserError> {
        self.expect_token(&Token::LParen)?;

        let partition_by = if self.parse_keywords(&[Keyword::PARTITION, Keyword::BY]) {
            self.parse_comma_separated(Parser::parse_expr)?
        } else {
            vec![]
        };

        let order_by = if self.parse_keywords(&[Keyword::ORDER, Keyword::BY]) {
            self.parse_comma_separated(Parser::parse_order_by_expr)?
        } else {
            vec![]
        };

        let measures = if self.parse_keyword(Keyword::MEASURES) {
            self.parse_comma_separated(|p| {
                let expr = p.parse_expr()?;
                let _ = p.parse_keyword(Keyword::AS);
                let alias = p.parse_identifier()?;
                Ok(Measure { expr, alias })
            })?
        } else {
            vec![]
        };

        let rows_per_match =
            if self.parse_keywords(&[Keyword::ONE, Keyword::ROW, Keyword::PER, Keyword::MATCH]) {
                Some(RowsPerMatch::OneRow)
            } else if self.parse_keywords(&[
                Keyword::ALL,
                Keyword::ROWS,
                Keyword::PER,
                Keyword::MATCH,
            ]) {
                Some(RowsPerMatch::AllRows(
                    if self.parse_keywords(&[Keyword::SHOW, Keyword::EMPTY, Keyword::MATCHES]) {
                        Some(EmptyMatchesMode::Show)
                    } else if self.parse_keywords(&[
                        Keyword::OMIT,
                        Keyword::EMPTY,
                        Keyword::MATCHES,
                    ]) {
                        Some(EmptyMatchesMode::Omit)
                    } else if self.parse_keywords(&[
                        Keyword::WITH,
                        Keyword::UNMATCHED,
                        Keyword::ROWS,
                    ]) {
                        Some(EmptyMatchesMode::WithUnmatched)
                    } else {
                        None
                    },
                ))
            } else {
                None
            };

        let after_match_skip =
            if self.parse_keywords(&[Keyword::AFTER, Keyword::MATCH, Keyword::SKIP]) {
                if self.parse_keywords(&[Keyword::PAST, Keyword::LAST, Keyword::ROW]) {
                    Some(AfterMatchSkip::PastLastRow)
                } else if self.parse_keywords(&[Keyword::TO, Keyword::NEXT, Keyword::ROW]) {
                    Some(AfterMatchSkip::ToNextRow)
                } else if self.parse_keywords(&[Keyword::TO, Keyword::FIRST]) {
                    Some(AfterMatchSkip::ToFirst(self.parse_identifier()?))
                } else if self.parse_keywords(&[Keyword::TO, Keyword::LAST]) {
                    Some(AfterMatchSkip::ToLast(self.parse_identifier()?))
                } else {
                    let found = self.next_token();
                    return self.expected("after match skip option", found);
                }
            } else {
                None
            };

        self.expect_keyword_is(Keyword::PATTERN)?;
        let pattern = self.parse_parenthesized(Self::parse_pattern)?;

        self.expect_keyword_is(Keyword::DEFINE)?;

        let symbols = self.parse_comma_separated(|p| {
            let symbol = p.parse_identifier()?;
            p.expect_keyword_is(Keyword::AS)?;
            let definition = p.parse_expr()?;
            Ok(SymbolDefinition { symbol, definition })
        })?;

        self.expect_token(&Token::RParen)?;

        let alias = self.maybe_parse_table_alias()?;

        Ok(TableFactor::MatchRecognize {
            table: Box::new(table),
            partition_by,
            order_by,
            measures,
            rows_per_match,
            after_match_skip,
            pattern,
            symbols,
            alias,
        })
    }

    fn parse_base_pattern(&mut self) -> Result<MatchRecognizePattern, ParserError> {
        match self.next_token().token {
            Token::Caret => Ok(MatchRecognizePattern::Symbol(MatchRecognizeSymbol::Start)),
            Token::Placeholder(s) if s == "$" => {
                Ok(MatchRecognizePattern::Symbol(MatchRecognizeSymbol::End))
            }
            Token::LBrace => {
                self.expect_token(&Token::Minus)?;
                let symbol = self.parse_identifier().map(MatchRecognizeSymbol::Named)?;
                self.expect_token(&Token::Minus)?;
                self.expect_token(&Token::RBrace)?;
                Ok(MatchRecognizePattern::Exclude(symbol))
            }
            Token::Word(Word {
                value,
                quote_style: None,
                ..
            }) if value == "PERMUTE" => {
                self.expect_token(&Token::LParen)?;
                let symbols = self.parse_comma_separated(|p| {
                    p.parse_identifier().map(MatchRecognizeSymbol::Named)
                })?;
                self.expect_token(&Token::RParen)?;
                Ok(MatchRecognizePattern::Permute(symbols))
            }
            Token::LParen => {
                let pattern = self.parse_pattern()?;
                self.expect_token(&Token::RParen)?;
                Ok(MatchRecognizePattern::Group(Box::new(pattern)))
            }
            _ => {
                self.prev_token();
                self.parse_identifier()
                    .map(MatchRecognizeSymbol::Named)
                    .map(MatchRecognizePattern::Symbol)
            }
        }
    }

    fn parse_repetition_pattern(&mut self) -> Result<MatchRecognizePattern, ParserError> {
        let pattern = self.parse_base_pattern()?;
        let token = self.next_token();
        let quantifier = match token.token {
            Token::Mul => RepetitionQuantifier::ZeroOrMore,
            Token::Plus => RepetitionQuantifier::OneOrMore,
            Token::Placeholder(s) if s == "?" => RepetitionQuantifier::AtMostOne,
            Token::LBrace => {
                // quantifier is a range like {n} or {n,} or {,m} or {n,m}
                let token = self.next_token();
                match token.token {
                    Token::Comma => {
                        let next_token = self.next_token();
                        let Token::Number(n, _) = next_token.token else {
                            return self.expected("literal number", next_token);
                        };
                        self.expect_token(&Token::RBrace)?;
                        RepetitionQuantifier::AtMost(Self::parse(n, token.span.start)?)
                    }
                    Token::Number(n, _) if self.consume_token(&Token::Comma) => {
                        let next_token = self.next_token();
                        match next_token.token {
                            Token::Number(m, _) => {
                                self.expect_token(&Token::RBrace)?;
                                RepetitionQuantifier::Range(
                                    Self::parse(n, token.span.start)?,
                                    Self::parse(m, token.span.start)?,
                                )
                            }
                            Token::RBrace => {
                                RepetitionQuantifier::AtLeast(Self::parse(n, token.span.start)?)
                            }
                            _ => return self.expected("} or upper bound", next_token),
                        }
                    }
                    Token::Number(n, _) => {
                        self.expect_token(&Token::RBrace)?;
                        RepetitionQuantifier::Exactly(Self::parse(n, token.span.start)?)
                    }
                    _ => return self.expected("quantifier range", token),
                }
            }
            _ => {
                self.prev_token();
                return Ok(pattern);
            }
        };
        let quantifier = if self.consume_token(&Token::Placeholder("?".into())) {
            RepetitionQuantifier::Reluctant(Box::new(quantifier))
        } else {
            quantifier
        };
        Ok(MatchRecognizePattern::Repetition(
            Box::new(pattern),
            quantifier,
        ))
    }

    fn parse_concat_pattern(&mut self) -> Result<MatchRecognizePattern, ParserError> {
        let mut patterns = vec![self.parse_repetition_pattern()?];
        while !matches!(self.peek_token_ref().token, Token::RParen | Token::Pipe) {
            patterns.push(self.parse_repetition_pattern()?);
        }
        match <[MatchRecognizePattern; 1]>::try_from(patterns) {
            Ok([pattern]) => Ok(pattern),
            Err(patterns) => Ok(MatchRecognizePattern::Concat(patterns)),
        }
    }

    fn parse_pattern(&mut self) -> Result<MatchRecognizePattern, ParserError> {
        let pattern = self.parse_concat_pattern()?;
        if self.consume_token(&Token::Pipe) {
            match self.parse_pattern()? {
                // flatten nested alternations
                MatchRecognizePattern::Alternation(mut patterns) => {
                    patterns.insert(0, pattern);
                    Ok(MatchRecognizePattern::Alternation(patterns))
                }
                next => Ok(MatchRecognizePattern::Alternation(vec![pattern, next])),
            }
        } else {
            Ok(pattern)
        }
    }

    /// Parses a the timestamp version specifier (i.e. query historical data)
    pub fn maybe_parse_table_version(&mut self) -> Result<Option<TableVersion>, ParserError> {
        if self.dialect.supports_table_versioning() {
            if self.parse_keywords(&[Keyword::FOR, Keyword::SYSTEM_TIME, Keyword::AS, Keyword::OF])
            {
                let expr = self.parse_expr()?;
                return Ok(Some(TableVersion::ForSystemTimeAsOf(expr)));
            } else if self.peek_keyword(Keyword::CHANGES) {
                return self.parse_table_version_changes().map(Some);
            } else if self.peek_keyword(Keyword::AT) || self.peek_keyword(Keyword::BEFORE) {
                let func_name = self.parse_object_name(true)?;
                let func = self.parse_function(func_name)?;
                return Ok(Some(TableVersion::Function(func)));
            } else if self.parse_keywords(&[Keyword::TIMESTAMP, Keyword::AS, Keyword::OF]) {
                let expr = self.parse_expr()?;
                return Ok(Some(TableVersion::TimestampAsOf(expr)));
            } else if self.parse_keywords(&[Keyword::VERSION, Keyword::AS, Keyword::OF]) {
                let expr = Expr::Value(self.parse_number_value()?);
                return Ok(Some(TableVersion::VersionAsOf(expr)));
            }
        }
        Ok(None)
    }

    /// Parses the Snowflake `CHANGES` clause for change tracking queries.
    ///
    /// Syntax:
    /// ```sql
    /// CHANGES (INFORMATION => DEFAULT)
    ///   AT (TIMESTAMP => <expr>)
    ///   [END (TIMESTAMP => <expr>)]
    /// ```
    ///
    /// <https://docs.snowflake.com/en/sql-reference/constructs/changes>
    fn parse_table_version_changes(&mut self) -> Result<TableVersion, ParserError> {
        let changes_name = self.parse_object_name(true)?;
        let changes = self.parse_function(changes_name)?;
        let at_name = self.parse_object_name(true)?;
        let at = self.parse_function(at_name)?;
        let end = if self.peek_keyword(Keyword::END) {
            let end_name = self.parse_object_name(true)?;
            Some(self.parse_function(end_name)?)
        } else {
            None
        };
        Ok(TableVersion::Changes { changes, at, end })
    }

    /// Parses MySQL's JSON_TABLE column definition.
    /// For example: `id INT EXISTS PATH '$' DEFAULT '0' ON EMPTY ERROR ON ERROR`
    pub fn parse_json_table_column_def(&mut self) -> Result<JsonTableColumn, ParserError> {
        if self.parse_keyword(Keyword::NESTED) {
            let _has_path_keyword = self.parse_keyword(Keyword::PATH);
            let path = self.parse_value()?;
            self.expect_keyword_is(Keyword::COLUMNS)?;
            let columns = self.parse_parenthesized(|p| {
                p.parse_comma_separated(Self::parse_json_table_column_def)
            })?;
            return Ok(JsonTableColumn::Nested(JsonTableNestedColumn {
                path,
                columns,
            }));
        }
        let name = self.parse_identifier()?;
        if self.parse_keyword(Keyword::FOR) {
            self.expect_keyword_is(Keyword::ORDINALITY)?;
            return Ok(JsonTableColumn::ForOrdinality(name));
        }
        let r#type = self.parse_data_type()?;
        let exists = self.parse_keyword(Keyword::EXISTS);
        self.expect_keyword_is(Keyword::PATH)?;
        let path = self.parse_value()?;
        let mut on_empty = None;
        let mut on_error = None;
        while let Some(error_handling) = self.parse_json_table_column_error_handling()? {
            if self.parse_keyword(Keyword::EMPTY) {
                on_empty = Some(error_handling);
            } else {
                self.expect_keyword_is(Keyword::ERROR)?;
                on_error = Some(error_handling);
            }
        }
        Ok(JsonTableColumn::Named(JsonTableNamedColumn {
            name,
            r#type,
            path,
            exists,
            on_empty,
            on_error,
        }))
    }

    /// Parses MSSQL's `OPENJSON WITH` column definition.
    ///
    /// ```sql
    /// colName type [ column_path ] [ AS JSON ]
    /// ```
    ///
    /// Reference: <https://learn.microsoft.com/en-us/sql/t-sql/functions/openjson-transact-sql?view=sql-server-ver16#syntax>
    pub fn parse_openjson_table_column_def(&mut self) -> Result<OpenJsonTableColumn, ParserError> {
        let name = self.parse_identifier()?;
        let r#type = self.parse_data_type()?;
        let path = if let Token::SingleQuotedString(path) = self.peek_token().token {
            self.next_token();
            Some(path)
        } else {
            None
        };
        let as_json = self.parse_keyword(Keyword::AS);
        if as_json {
            self.expect_keyword_is(Keyword::JSON)?;
        }
        Ok(OpenJsonTableColumn {
            name,
            r#type,
            path,
            as_json,
        })
    }

    fn parse_json_table_column_error_handling(
        &mut self,
    ) -> Result<Option<JsonTableColumnErrorHandling>, ParserError> {
        let res = if self.parse_keyword(Keyword::NULL) {
            JsonTableColumnErrorHandling::Null
        } else if self.parse_keyword(Keyword::ERROR) {
            JsonTableColumnErrorHandling::Error
        } else if self.parse_keyword(Keyword::DEFAULT) {
            JsonTableColumnErrorHandling::Default(self.parse_value()?)
        } else {
            return Ok(None);
        };
        self.expect_keyword_is(Keyword::ON)?;
        Ok(Some(res))
    }

    /// Parse a derived table factor (a parenthesized subquery), handling optional LATERAL.
    pub fn parse_derived_table_factor(
        &mut self,
        lateral: IsLateral,
    ) -> Result<TableFactor, ParserError> {
        let subquery = self.parse_query()?;
        self.expect_token(&Token::RParen)?;
        let alias = self.maybe_parse_table_alias()?;

        // Parse optional SAMPLE clause after alias
        let sample = self
            .maybe_parse_table_sample()?
            .map(TableSampleKind::AfterTableAlias);

        Ok(TableFactor::Derived {
            lateral: match lateral {
                Lateral => true,
                NotLateral => false,
            },
            subquery,
            alias,
            sample,
        })
    }

    /// Parses an expression with an optional alias
    ///
    /// Examples:
    ///
    /// ```sql
    /// SUM(price) AS total_price
    /// ```
    /// ```sql
    /// SUM(price)
    /// ```
    ///
    /// Example
    /// ```
    /// # use sqlparser::parser::{Parser, ParserError};
    /// # use sqlparser::dialect::GenericDialect;
    /// # fn main() ->Result<(), ParserError> {
    /// let sql = r#"SUM("a") as "b""#;
    /// let mut parser = Parser::new(&GenericDialect).try_with_sql(sql)?;
    /// let expr_with_alias = parser.parse_expr_with_alias()?;
    /// assert_eq!(Some("b".to_string()), expr_with_alias.alias.map(|x|x.value));
    /// # Ok(())
    /// # }
    pub fn parse_expr_with_alias(&mut self) -> Result<ExprWithAlias, ParserError> {
        let expr = self.parse_expr()?;
        let alias = if self.parse_keyword(Keyword::AS) {
            Some(self.parse_identifier()?)
        } else {
            None
        };

        Ok(ExprWithAlias { expr, alias })
    }

    /// Parse an expression followed by an optional alias; Unlike
    /// [Self::parse_expr_with_alias] the "AS" keyword between the expression
    /// and the alias is optional.
    fn parse_expr_with_alias_optional_as_keyword(&mut self) -> Result<ExprWithAlias, ParserError> {
        let expr = self.parse_expr()?;
        let alias = self.parse_identifier_optional_alias()?;
        Ok(ExprWithAlias { expr, alias })
    }

    /// Parses a plain function call with an optional alias for the `PIVOT` clause
    fn parse_pivot_aggregate_function(&mut self) -> Result<ExprWithAlias, ParserError> {
        let function_name = match self.next_token().token {
            Token::Word(w) => Ok(w.value),
            _ => self.expected_ref("a function identifier", self.peek_token_ref()),
        }?;
        let expr = self.parse_function(ObjectName::from(vec![Ident::new(function_name)]))?;
        let alias = {
            fn validator(explicit: bool, kw: &Keyword, parser: &mut Parser) -> bool {
                // ~ for a PIVOT aggregate function the alias must not be a "FOR"; in any dialect
                kw != &Keyword::FOR && parser.dialect.is_select_item_alias(explicit, kw, parser)
            }
            self.parse_optional_alias_inner(None, validator)?
        };
        Ok(ExprWithAlias { expr, alias })
    }

    /// Parse a PIVOT table factor (ClickHouse/Oracle style pivot), returning a TableFactor.
    pub fn parse_pivot_table_factor(
        &mut self,
        table: TableFactor,
    ) -> Result<TableFactor, ParserError> {
        self.expect_token(&Token::LParen)?;
        let aggregate_functions =
            self.parse_comma_separated(Self::parse_pivot_aggregate_function)?;
        self.expect_keyword_is(Keyword::FOR)?;
        let value_column = if self.peek_token_ref().token == Token::LParen {
            self.parse_parenthesized_column_list_inner(Mandatory, false, |p| {
                p.parse_subexpr(self.dialect.prec_value(Precedence::Between))
            })?
        } else {
            vec![self.parse_subexpr(self.dialect.prec_value(Precedence::Between))?]
        };
        self.expect_keyword_is(Keyword::IN)?;

        self.expect_token(&Token::LParen)?;
        let value_source = if self.parse_keyword(Keyword::ANY) {
            let order_by = if self.parse_keywords(&[Keyword::ORDER, Keyword::BY]) {
                self.parse_comma_separated(Parser::parse_order_by_expr)?
            } else {
                vec![]
            };
            PivotValueSource::Any(order_by)
        } else if self.peek_sub_query() {
            PivotValueSource::Subquery(self.parse_query()?)
        } else {
            PivotValueSource::List(
                self.parse_comma_separated(Self::parse_expr_with_alias_optional_as_keyword)?,
            )
        };
        self.expect_token(&Token::RParen)?;

        let default_on_null =
            if self.parse_keywords(&[Keyword::DEFAULT, Keyword::ON, Keyword::NULL]) {
                self.expect_token(&Token::LParen)?;
                let expr = self.parse_expr()?;
                self.expect_token(&Token::RParen)?;
                Some(expr)
            } else {
                None
            };

        self.expect_token(&Token::RParen)?;
        let alias = self.maybe_parse_table_alias()?;
        Ok(TableFactor::Pivot {
            table: Box::new(table),
            aggregate_functions,
            value_column,
            value_source,
            default_on_null,
            alias,
        })
    }

    /// Parse an UNPIVOT table factor, returning a TableFactor.
    pub fn parse_unpivot_table_factor(
        &mut self,
        table: TableFactor,
    ) -> Result<TableFactor, ParserError> {
        let null_inclusion = if self.parse_keyword(Keyword::INCLUDE) {
            self.expect_keyword_is(Keyword::NULLS)?;
            Some(NullInclusion::IncludeNulls)
        } else if self.parse_keyword(Keyword::EXCLUDE) {
            self.expect_keyword_is(Keyword::NULLS)?;
            Some(NullInclusion::ExcludeNulls)
        } else {
            None
        };
        self.expect_token(&Token::LParen)?;
        let value = self.parse_expr()?;
        self.expect_keyword_is(Keyword::FOR)?;
        let name = self.parse_identifier()?;
        self.expect_keyword_is(Keyword::IN)?;
        let columns = self.parse_parenthesized_column_list_inner(Mandatory, false, |p| {
            p.parse_expr_with_alias()
        })?;
        self.expect_token(&Token::RParen)?;
        let alias = self.maybe_parse_table_alias()?;
        Ok(TableFactor::Unpivot {
            table: Box::new(table),
            value,
            null_inclusion,
            name,
            columns,
            alias,
        })
    }

    /// Parse an object UNPIVOT table factor in FROM clause.
    ///
    /// Syntax:
    /// `UNPIVOT expression AS value_alias [AT attribute_alias]`
    pub fn parse_unpivot_expr_table_factor(&mut self) -> Result<TableFactor, ParserError> {
        self.expect_keyword_is(Keyword::UNPIVOT)?;
        let expression = self.parse_expr()?;
        self.expect_keyword_is(Keyword::AS)?;
        let value_alias = self.parse_identifier()?;
        let attribute_alias = if self.parse_keyword(Keyword::AT) {
            Some(self.parse_identifier()?)
        } else {
            None
        };

        Ok(TableFactor::UnpivotExpr {
            expression,
            value_alias,
            attribute_alias,
        })
    }

    /// Parse a JOIN constraint (`NATURAL`, `ON <expr>`, `USING (...)`, or no constraint).
    pub fn parse_join_constraint(&mut self, natural: bool) -> Result<JoinConstraint, ParserError> {
        if natural {
            Ok(JoinConstraint::Natural)
        } else if self.parse_keyword(Keyword::ON) {
            let constraint = self.parse_expr()?;
            Ok(JoinConstraint::On(constraint))
        } else if self.parse_keyword(Keyword::USING) {
            let columns = self.parse_parenthesized_qualified_column_list(Mandatory, false)?;
            if self.parse_keyword(Keyword::AS) {
                Ok(JoinConstraint::UsingAlias(
                    columns,
                    self.parse_identifier()?,
                ))
            } else {
                Ok(JoinConstraint::Using(columns))
            }
        } else {
            Ok(JoinConstraint::None)
            //self.expected_ref("ON, or USING after JOIN", self.peek_token_ref())
        }
    }

    /// Parse a GRANT statement.
    pub fn parse_grant(&mut self) -> Result<Grant, ParserError> {
        let (privileges, objects) = self.parse_grant_deny_revoke_privileges_objects()?;

        self.expect_keyword_is(Keyword::TO)?;
        let grantees = self.parse_grantees()?;

        let with_grant_option =
            self.parse_keywords(&[Keyword::WITH, Keyword::GRANT, Keyword::OPTION]);

        let current_grants =
            if self.parse_keywords(&[Keyword::COPY, Keyword::CURRENT, Keyword::GRANTS]) {
                Some(CurrentGrantsKind::CopyCurrentGrants)
            } else if self.parse_keywords(&[Keyword::REVOKE, Keyword::CURRENT, Keyword::GRANTS]) {
                Some(CurrentGrantsKind::RevokeCurrentGrants)
            } else {
                None
            };

        let as_grantor = if self.parse_keywords(&[Keyword::AS]) {
            Some(self.parse_identifier()?)
        } else {
            None
        };

        let granted_by = if self.parse_keywords(&[Keyword::GRANTED, Keyword::BY]) {
            Some(self.parse_identifier()?)
        } else {
            None
        };

        Ok(Grant {
            privileges,
            objects,
            grantees,
            with_grant_option,
            as_grantor,
            granted_by,
            current_grants,
        })
    }

    fn parse_grantees(&mut self) -> Result<Vec<Grantee>, ParserError> {
        let mut values = vec![];
        let mut grantee_type = GranteesType::None;
        loop {
            let new_grantee_type = if self.parse_keyword(Keyword::ROLE) {
                GranteesType::Role
            } else if self.parse_keyword(Keyword::USER) {
                GranteesType::User
            } else if self.parse_keyword(Keyword::SHARE) {
                GranteesType::Share
            } else if self.parse_keyword(Keyword::GROUP) {
                GranteesType::Group
            } else if self.parse_keyword(Keyword::PUBLIC) {
                GranteesType::Public
            } else if self.parse_keywords(&[Keyword::DATABASE, Keyword::ROLE]) {
                GranteesType::DatabaseRole
            } else if self.parse_keywords(&[Keyword::APPLICATION, Keyword::ROLE]) {
                GranteesType::ApplicationRole
            } else if self.parse_keyword(Keyword::APPLICATION) {
                GranteesType::Application
            } else {
                grantee_type.clone() // keep from previous iteraton, if not specified
            };

            if self
                .dialect
                .get_reserved_grantees_types()
                .contains(&new_grantee_type)
            {
                self.prev_token();
            } else {
                grantee_type = new_grantee_type;
            }

            let grantee = if grantee_type == GranteesType::Public {
                Grantee {
                    grantee_type: grantee_type.clone(),
                    name: None,
                }
            } else {
                let mut name = self.parse_grantee_name()?;
                if self.consume_token(&Token::Colon) {
                    // Redshift supports namespace prefix for external users and groups:
                    // <Namespace>:<GroupName> or <Namespace>:<UserName>
                    // https://docs.aws.amazon.com/redshift/latest/mgmt/redshift-iam-access-control-native-idp.html
                    let ident = self.parse_identifier()?;
                    if let GranteeName::ObjectName(namespace) = name {
                        name = GranteeName::ObjectName(ObjectName::from(vec![Ident::new(
                            format!("{namespace}:{ident}"),
                        )]));
                    };
                }
                Grantee {
                    grantee_type: grantee_type.clone(),
                    name: Some(name),
                }
            };

            values.push(grantee);

            if !self.consume_token(&Token::Comma) {
                break;
            }
        }

        Ok(values)
    }

    /// Parse privileges and optional target objects for GRANT/DENY/REVOKE statements.
    pub fn parse_grant_deny_revoke_privileges_objects(
        &mut self,
    ) -> Result<(Privileges, Option<GrantObjects>), ParserError> {
        let privileges = if self.parse_keyword(Keyword::ALL) {
            Privileges::All {
                with_privileges_keyword: self.parse_keyword(Keyword::PRIVILEGES),
            }
        } else {
            let actions = self.parse_actions_list()?;
            Privileges::Actions(actions)
        };

        let objects = if self.parse_keyword(Keyword::ON) {
            if self.parse_keywords(&[Keyword::ALL, Keyword::TABLES, Keyword::IN, Keyword::SCHEMA]) {
                Some(GrantObjects::AllTablesInSchema {
                    schemas: self.parse_comma_separated(|p| p.parse_object_name(false))?,
                })
            } else if self.parse_keywords(&[
                Keyword::ALL,
                Keyword::EXTERNAL,
                Keyword::TABLES,
                Keyword::IN,
                Keyword::SCHEMA,
            ]) {
                Some(GrantObjects::AllExternalTablesInSchema {
                    schemas: self.parse_comma_separated(|p| p.parse_object_name(false))?,
                })
            } else if self.parse_keywords(&[
                Keyword::ALL,
                Keyword::VIEWS,
                Keyword::IN,
                Keyword::SCHEMA,
            ]) {
                Some(GrantObjects::AllViewsInSchema {
                    schemas: self.parse_comma_separated(|p| p.parse_object_name(false))?,
                })
            } else if self.parse_keywords(&[
                Keyword::ALL,
                Keyword::MATERIALIZED,
                Keyword::VIEWS,
                Keyword::IN,
                Keyword::SCHEMA,
            ]) {
                Some(GrantObjects::AllMaterializedViewsInSchema {
                    schemas: self.parse_comma_separated(|p| p.parse_object_name(false))?,
                })
            } else if self.parse_keywords(&[
                Keyword::ALL,
                Keyword::FUNCTIONS,
                Keyword::IN,
                Keyword::SCHEMA,
            ]) {
                Some(GrantObjects::AllFunctionsInSchema {
                    schemas: self.parse_comma_separated(|p| p.parse_object_name(false))?,
                })
            } else if self.parse_keywords(&[
                Keyword::FUTURE,
                Keyword::SCHEMAS,
                Keyword::IN,
                Keyword::DATABASE,
            ]) {
                Some(GrantObjects::FutureSchemasInDatabase {
                    databases: self.parse_comma_separated(|p| p.parse_object_name(false))?,
                })
            } else if self.parse_keywords(&[
                Keyword::FUTURE,
                Keyword::TABLES,
                Keyword::IN,
                Keyword::SCHEMA,
            ]) {
                Some(GrantObjects::FutureTablesInSchema {
                    schemas: self.parse_comma_separated(|p| p.parse_object_name(false))?,
                })
            } else if self.parse_keywords(&[
                Keyword::FUTURE,
                Keyword::EXTERNAL,
                Keyword::TABLES,
                Keyword::IN,
                Keyword::SCHEMA,
            ]) {
                Some(GrantObjects::FutureExternalTablesInSchema {
                    schemas: self.parse_comma_separated(|p| p.parse_object_name(false))?,
                })
            } else if self.parse_keywords(&[
                Keyword::FUTURE,
                Keyword::VIEWS,
                Keyword::IN,
                Keyword::SCHEMA,
            ]) {
                Some(GrantObjects::FutureViewsInSchema {
                    schemas: self.parse_comma_separated(|p| p.parse_object_name(false))?,
                })
            } else if self.parse_keywords(&[
                Keyword::FUTURE,
                Keyword::MATERIALIZED,
                Keyword::VIEWS,
                Keyword::IN,
                Keyword::SCHEMA,
            ]) {
                Some(GrantObjects::FutureMaterializedViewsInSchema {
                    schemas: self.parse_comma_separated(|p| p.parse_object_name(false))?,
                })
            } else if self.parse_keywords(&[
                Keyword::ALL,
                Keyword::SEQUENCES,
                Keyword::IN,
                Keyword::SCHEMA,
            ]) {
                Some(GrantObjects::AllSequencesInSchema {
                    schemas: self.parse_comma_separated(|p| p.parse_object_name(false))?,
                })
            } else if self.parse_keywords(&[
                Keyword::FUTURE,
                Keyword::SEQUENCES,
                Keyword::IN,
                Keyword::SCHEMA,
            ]) {
                Some(GrantObjects::FutureSequencesInSchema {
                    schemas: self.parse_comma_separated(|p| p.parse_object_name(false))?,
                })
            } else if self.parse_keywords(&[Keyword::RESOURCE, Keyword::MONITOR]) {
                Some(GrantObjects::ResourceMonitors(
                    self.parse_comma_separated(|p| p.parse_object_name(false))?,
                ))
            } else if self.parse_keywords(&[Keyword::COMPUTE, Keyword::POOL]) {
                Some(GrantObjects::ComputePools(
                    self.parse_comma_separated(|p| p.parse_object_name(false))?,
                ))
            } else if self.parse_keywords(&[Keyword::FAILOVER, Keyword::GROUP]) {
                Some(GrantObjects::FailoverGroup(
                    self.parse_comma_separated(|p| p.parse_object_name(false))?,
                ))
            } else if self.parse_keywords(&[Keyword::REPLICATION, Keyword::GROUP]) {
                Some(GrantObjects::ReplicationGroup(
                    self.parse_comma_separated(|p| p.parse_object_name(false))?,
                ))
            } else if self.parse_keywords(&[Keyword::EXTERNAL, Keyword::VOLUME]) {
                Some(GrantObjects::ExternalVolumes(
                    self.parse_comma_separated(|p| p.parse_object_name(false))?,
                ))
            } else {
                let object_type = self.parse_one_of_keywords(&[
                    Keyword::SEQUENCE,
                    Keyword::DATABASE,
                    Keyword::SCHEMA,
                    Keyword::TABLE,
                    Keyword::VIEW,
                    Keyword::WAREHOUSE,
                    Keyword::INTEGRATION,
                    Keyword::VIEW,
                    Keyword::WAREHOUSE,
                    Keyword::INTEGRATION,
                    Keyword::USER,
                    Keyword::CONNECTION,
                    Keyword::PROCEDURE,
                    Keyword::FUNCTION,
                ]);
                let objects =
                    self.parse_comma_separated(|p| p.parse_object_name_inner(false, true));
                match object_type {
                    Some(Keyword::DATABASE) => Some(GrantObjects::Databases(objects?)),
                    Some(Keyword::SCHEMA) => Some(GrantObjects::Schemas(objects?)),
                    Some(Keyword::SEQUENCE) => Some(GrantObjects::Sequences(objects?)),
                    Some(Keyword::WAREHOUSE) => Some(GrantObjects::Warehouses(objects?)),
                    Some(Keyword::INTEGRATION) => Some(GrantObjects::Integrations(objects?)),
                    Some(Keyword::VIEW) => Some(GrantObjects::Views(objects?)),
                    Some(Keyword::USER) => Some(GrantObjects::Users(objects?)),
                    Some(Keyword::CONNECTION) => Some(GrantObjects::Connections(objects?)),
                    kw @ (Some(Keyword::PROCEDURE) | Some(Keyword::FUNCTION)) => {
                        if let Some(name) = objects?.first() {
                            self.parse_grant_procedure_or_function(name, &kw)?
                        } else {
                            self.expected_ref("procedure or function name", self.peek_token_ref())?
                        }
                    }
                    Some(Keyword::TABLE) | None => Some(GrantObjects::Tables(objects?)),
                    Some(unexpected_keyword) => return Err(ParserError::ParserError(
                        format!("Internal parser error: unexpected keyword `{unexpected_keyword}` in grant objects"),
                    )),
                }
            }
        } else {
            None
        };

        Ok((privileges, objects))
    }

    fn parse_grant_procedure_or_function(
        &mut self,
        name: &ObjectName,
        kw: &Option<Keyword>,
    ) -> Result<Option<GrantObjects>, ParserError> {
        let arg_types = if self.consume_token(&Token::LParen) {
            let list = self.parse_comma_separated0(Self::parse_data_type, Token::RParen)?;
            self.expect_token(&Token::RParen)?;
            list
        } else {
            vec![]
        };
        match kw {
            Some(Keyword::PROCEDURE) => Ok(Some(GrantObjects::Procedure {
                name: name.clone(),
                arg_types,
            })),
            Some(Keyword::FUNCTION) => Ok(Some(GrantObjects::Function {
                name: name.clone(),
                arg_types,
            })),
            _ => self.expected_ref("procedure or function keywords", self.peek_token_ref())?,
        }
    }

    /// Parse a single grantable permission/action (used within GRANT statements).
    pub fn parse_grant_permission(&mut self) -> Result<Action, ParserError> {
        fn parse_columns(parser: &mut Parser) -> Result<Option<Vec<Ident>>, ParserError> {
            let columns = parser.parse_parenthesized_column_list(Optional, false)?;
            if columns.is_empty() {
                Ok(None)
            } else {
                Ok(Some(columns))
            }
        }

        // Multi-word privileges
        if self.parse_keywords(&[Keyword::IMPORTED, Keyword::PRIVILEGES]) {
            Ok(Action::ImportedPrivileges)
        } else if self.parse_keywords(&[Keyword::ADD, Keyword::SEARCH, Keyword::OPTIMIZATION]) {
            Ok(Action::AddSearchOptimization)
        } else if self.parse_keywords(&[Keyword::ATTACH, Keyword::LISTING]) {
            Ok(Action::AttachListing)
        } else if self.parse_keywords(&[Keyword::ATTACH, Keyword::POLICY]) {
            Ok(Action::AttachPolicy)
        } else if self.parse_keywords(&[Keyword::BIND, Keyword::SERVICE, Keyword::ENDPOINT]) {
            Ok(Action::BindServiceEndpoint)
        } else if self.parse_keywords(&[Keyword::DATABASE, Keyword::ROLE]) {
            let role = self.parse_object_name(false)?;
            Ok(Action::DatabaseRole { role })
        } else if self.parse_keywords(&[Keyword::EVOLVE, Keyword::SCHEMA]) {
            Ok(Action::EvolveSchema)
        } else if self.parse_keywords(&[Keyword::IMPORT, Keyword::SHARE]) {
            Ok(Action::ImportShare)
        } else if self.parse_keywords(&[Keyword::MANAGE, Keyword::VERSIONS]) {
            Ok(Action::ManageVersions)
        } else if self.parse_keywords(&[Keyword::MANAGE, Keyword::RELEASES]) {
            Ok(Action::ManageReleases)
        } else if self.parse_keywords(&[Keyword::OVERRIDE, Keyword::SHARE, Keyword::RESTRICTIONS]) {
            Ok(Action::OverrideShareRestrictions)
        } else if self.parse_keywords(&[
            Keyword::PURCHASE,
            Keyword::DATA,
            Keyword::EXCHANGE,
            Keyword::LISTING,
        ]) {
            Ok(Action::PurchaseDataExchangeListing)
        } else if self.parse_keywords(&[Keyword::RESOLVE, Keyword::ALL]) {
            Ok(Action::ResolveAll)
        } else if self.parse_keywords(&[Keyword::READ, Keyword::SESSION]) {
            Ok(Action::ReadSession)

        // Single-word privileges
        } else if self.parse_keyword(Keyword::APPLY) {
            let apply_type = self.parse_action_apply_type()?;
            Ok(Action::Apply { apply_type })
        } else if self.parse_keyword(Keyword::APPLYBUDGET) {
            Ok(Action::ApplyBudget)
        } else if self.parse_keyword(Keyword::AUDIT) {
            Ok(Action::Audit)
        } else if self.parse_keyword(Keyword::CONNECT) {
            Ok(Action::Connect)
        } else if self.parse_keyword(Keyword::CREATE) {
            let obj_type = self.maybe_parse_action_create_object_type();
            Ok(Action::Create { obj_type })
        } else if self.parse_keyword(Keyword::DELETE) {
            Ok(Action::Delete)
        } else if self.parse_keyword(Keyword::EXEC) {
            let obj_type = self.maybe_parse_action_execute_obj_type();
            Ok(Action::Exec { obj_type })
        } else if self.parse_keyword(Keyword::EXECUTE) {
            let obj_type = self.maybe_parse_action_execute_obj_type();
            Ok(Action::Execute { obj_type })
        } else if self.parse_keyword(Keyword::FAILOVER) {
            Ok(Action::Failover)
        } else if self.parse_keyword(Keyword::INSERT) {
            Ok(Action::Insert {
                columns: parse_columns(self)?,
            })
        } else if self.parse_keyword(Keyword::MANAGE) {
            let manage_type = self.parse_action_manage_type()?;
            Ok(Action::Manage { manage_type })
        } else if self.parse_keyword(Keyword::MODIFY) {
            let modify_type = self.parse_action_modify_type();
            Ok(Action::Modify { modify_type })
        } else if self.parse_keyword(Keyword::MONITOR) {
            let monitor_type = self.parse_action_monitor_type();
            Ok(Action::Monitor { monitor_type })
        } else if self.parse_keyword(Keyword::OPERATE) {
            Ok(Action::Operate)
        } else if self.parse_keyword(Keyword::REFERENCES) {
            Ok(Action::References {
                columns: parse_columns(self)?,
            })
        } else if self.parse_keyword(Keyword::READ) {
            Ok(Action::Read)
        } else if self.parse_keyword(Keyword::REPLICATE) {
            Ok(Action::Replicate)
        } else if self.parse_keyword(Keyword::ROLE) {
            let role = self.parse_object_name(false)?;
            Ok(Action::Role { role })
        } else if self.parse_keyword(Keyword::SELECT) {
            Ok(Action::Select {
                columns: parse_columns(self)?,
            })
        } else if self.parse_keyword(Keyword::TEMPORARY) {
            Ok(Action::Temporary)
        } else if self.parse_keyword(Keyword::TRIGGER) {
            Ok(Action::Trigger)
        } else if self.parse_keyword(Keyword::TRUNCATE) {
            Ok(Action::Truncate)
        } else if self.parse_keyword(Keyword::UPDATE) {
            Ok(Action::Update {
                columns: parse_columns(self)?,
            })
        } else if self.parse_keyword(Keyword::USAGE) {
            Ok(Action::Usage)
        } else if self.parse_keyword(Keyword::OWNERSHIP) {
            Ok(Action::Ownership)
        } else if self.parse_keyword(Keyword::DROP) {
            Ok(Action::Drop)
        } else {
            self.expected_ref("a privilege keyword", self.peek_token_ref())?
        }
    }

    fn maybe_parse_action_create_object_type(&mut self) -> Option<ActionCreateObjectType> {
        // Multi-word object types
        if self.parse_keywords(&[Keyword::APPLICATION, Keyword::PACKAGE]) {
            Some(ActionCreateObjectType::ApplicationPackage)
        } else if self.parse_keywords(&[Keyword::COMPUTE, Keyword::POOL]) {
            Some(ActionCreateObjectType::ComputePool)
        } else if self.parse_keywords(&[Keyword::DATA, Keyword::EXCHANGE, Keyword::LISTING]) {
            Some(ActionCreateObjectType::DataExchangeListing)
        } else if self.parse_keywords(&[Keyword::EXTERNAL, Keyword::VOLUME]) {
            Some(ActionCreateObjectType::ExternalVolume)
        } else if self.parse_keywords(&[Keyword::FAILOVER, Keyword::GROUP]) {
            Some(ActionCreateObjectType::FailoverGroup)
        } else if self.parse_keywords(&[Keyword::NETWORK, Keyword::POLICY]) {
            Some(ActionCreateObjectType::NetworkPolicy)
        } else if self.parse_keywords(&[Keyword::ORGANIZATION, Keyword::LISTING]) {
            Some(ActionCreateObjectType::OrganiationListing)
        } else if self.parse_keywords(&[Keyword::REPLICATION, Keyword::GROUP]) {
            Some(ActionCreateObjectType::ReplicationGroup)
        }
        // Single-word object types
        else if self.parse_keyword(Keyword::ACCOUNT) {
            Some(ActionCreateObjectType::Account)
        } else if self.parse_keyword(Keyword::APPLICATION) {
            Some(ActionCreateObjectType::Application)
        } else if self.parse_keyword(Keyword::DATABASE) {
            Some(ActionCreateObjectType::Database)
        } else if self.parse_keyword(Keyword::INTEGRATION) {
            Some(ActionCreateObjectType::Integration)
        } else if self.parse_keyword(Keyword::ROLE) {
            Some(ActionCreateObjectType::Role)
        } else if self.parse_keyword(Keyword::SCHEMA) {
            Some(ActionCreateObjectType::Schema)
        } else if self.parse_keyword(Keyword::SHARE) {
            Some(ActionCreateObjectType::Share)
        } else if self.parse_keyword(Keyword::USER) {
            Some(ActionCreateObjectType::User)
        } else if self.parse_keyword(Keyword::WAREHOUSE) {
            Some(ActionCreateObjectType::Warehouse)
        } else {
            None
        }
    }

    fn parse_action_apply_type(&mut self) -> Result<ActionApplyType, ParserError> {
        if self.parse_keywords(&[Keyword::AGGREGATION, Keyword::POLICY]) {
            Ok(ActionApplyType::AggregationPolicy)
        } else if self.parse_keywords(&[Keyword::AUTHENTICATION, Keyword::POLICY]) {
            Ok(ActionApplyType::AuthenticationPolicy)
        } else if self.parse_keywords(&[Keyword::JOIN, Keyword::POLICY]) {
            Ok(ActionApplyType::JoinPolicy)
        } else if self.parse_keywords(&[Keyword::MASKING, Keyword::POLICY]) {
            Ok(ActionApplyType::MaskingPolicy)
        } else if self.parse_keywords(&[Keyword::PACKAGES, Keyword::POLICY]) {
            Ok(ActionApplyType::PackagesPolicy)
        } else if self.parse_keywords(&[Keyword::PASSWORD, Keyword::POLICY]) {
            Ok(ActionApplyType::PasswordPolicy)
        } else if self.parse_keywords(&[Keyword::PROJECTION, Keyword::POLICY]) {
            Ok(ActionApplyType::ProjectionPolicy)
        } else if self.parse_keywords(&[Keyword::ROW, Keyword::ACCESS, Keyword::POLICY]) {
            Ok(ActionApplyType::RowAccessPolicy)
        } else if self.parse_keywords(&[Keyword::SESSION, Keyword::POLICY]) {
            Ok(ActionApplyType::SessionPolicy)
        } else if self.parse_keyword(Keyword::TAG) {
            Ok(ActionApplyType::Tag)
        } else {
            self.expected_ref("GRANT APPLY type", self.peek_token_ref())
        }
    }

    fn maybe_parse_action_execute_obj_type(&mut self) -> Option<ActionExecuteObjectType> {
        if self.parse_keywords(&[Keyword::DATA, Keyword::METRIC, Keyword::FUNCTION]) {
            Some(ActionExecuteObjectType::DataMetricFunction)
        } else if self.parse_keywords(&[Keyword::MANAGED, Keyword::ALERT]) {
            Some(ActionExecuteObjectType::ManagedAlert)
        } else if self.parse_keywords(&[Keyword::MANAGED, Keyword::TASK]) {
            Some(ActionExecuteObjectType::ManagedTask)
        } else if self.parse_keyword(Keyword::ALERT) {
            Some(ActionExecuteObjectType::Alert)
        } else if self.parse_keyword(Keyword::TASK) {
            Some(ActionExecuteObjectType::Task)
        } else {
            None
        }
    }

    fn parse_action_manage_type(&mut self) -> Result<ActionManageType, ParserError> {
        if self.parse_keywords(&[Keyword::ACCOUNT, Keyword::SUPPORT, Keyword::CASES]) {
            Ok(ActionManageType::AccountSupportCases)
        } else if self.parse_keywords(&[Keyword::EVENT, Keyword::SHARING]) {
            Ok(ActionManageType::EventSharing)
        } else if self.parse_keywords(&[Keyword::LISTING, Keyword::AUTO, Keyword::FULFILLMENT]) {
            Ok(ActionManageType::ListingAutoFulfillment)
        } else if self.parse_keywords(&[Keyword::ORGANIZATION, Keyword::SUPPORT, Keyword::CASES]) {
            Ok(ActionManageType::OrganizationSupportCases)
        } else if self.parse_keywords(&[Keyword::USER, Keyword::SUPPORT, Keyword::CASES]) {
            Ok(ActionManageType::UserSupportCases)
        } else if self.parse_keyword(Keyword::GRANTS) {
            Ok(ActionManageType::Grants)
        } else if self.parse_keyword(Keyword::WAREHOUSES) {
            Ok(ActionManageType::Warehouses)
        } else {
            self.expected_ref("GRANT MANAGE type", self.peek_token_ref())
        }
    }

    fn parse_action_modify_type(&mut self) -> Option<ActionModifyType> {
        if self.parse_keywords(&[Keyword::LOG, Keyword::LEVEL]) {
            Some(ActionModifyType::LogLevel)
        } else if self.parse_keywords(&[Keyword::TRACE, Keyword::LEVEL]) {
            Some(ActionModifyType::TraceLevel)
        } else if self.parse_keywords(&[Keyword::SESSION, Keyword::LOG, Keyword::LEVEL]) {
            Some(ActionModifyType::SessionLogLevel)
        } else if self.parse_keywords(&[Keyword::SESSION, Keyword::TRACE, Keyword::LEVEL]) {
            Some(ActionModifyType::SessionTraceLevel)
        } else {
            None
        }
    }

    fn parse_action_monitor_type(&mut self) -> Option<ActionMonitorType> {
        if self.parse_keyword(Keyword::EXECUTION) {
            Some(ActionMonitorType::Execution)
        } else if self.parse_keyword(Keyword::SECURITY) {
            Some(ActionMonitorType::Security)
        } else if self.parse_keyword(Keyword::USAGE) {
            Some(ActionMonitorType::Usage)
        } else {
            None
        }
    }

    /// Parse a grantee name, possibly with a host qualifier (user@host).
    pub fn parse_grantee_name(&mut self) -> Result<GranteeName, ParserError> {
        let mut name = self.parse_object_name(false)?;
        if self.dialect.supports_user_host_grantee()
            && name.0.len() == 1
            && name.0[0].as_ident().is_some()
            && self.consume_token(&Token::AtSign)
        {
            let user = name.0.pop().unwrap().as_ident().unwrap().clone();
            let host = self.parse_identifier()?;
            Ok(GranteeName::UserHost { user, host })
        } else {
            Ok(GranteeName::ObjectName(name))
        }
    }

    /// Parse [`Statement::Deny`]
    pub fn parse_deny(&mut self) -> Result<Statement, ParserError> {
        self.expect_keyword(Keyword::DENY)?;

        let (privileges, objects) = self.parse_grant_deny_revoke_privileges_objects()?;
        let objects = match objects {
            Some(o) => o,
            None => {
                return parser_err!(
                    "DENY statements must specify an object",
                    self.peek_token_ref().span.start
                )
            }
        };

        self.expect_keyword_is(Keyword::TO)?;
        let grantees = self.parse_grantees()?;
        let cascade = self.parse_cascade_option();
        let granted_by = if self.parse_keywords(&[Keyword::AS]) {
            Some(self.parse_identifier()?)
        } else {
            None
        };

        Ok(Statement::Deny(DenyStatement {
            privileges,
            objects,
            grantees,
            cascade,
            granted_by,
        }))
    }

    /// Parse a REVOKE statement
    pub fn parse_revoke(&mut self) -> Result<Revoke, ParserError> {
        let grant_option_for =
            self.parse_keywords(&[Keyword::GRANT, Keyword::OPTION, Keyword::FOR]);

        let (privileges, objects) = self.parse_grant_deny_revoke_privileges_objects()?;

        self.expect_keyword_is(Keyword::FROM)?;
        let grantees = self.parse_grantees()?;

        let granted_by = if self.parse_keywords(&[Keyword::GRANTED, Keyword::BY]) {
            Some(self.parse_identifier()?)
        } else {
            None
        };

        let cascade = self.parse_cascade_option();

        Ok(Revoke {
            grant_option_for,
            privileges,
            objects,
            grantees,
            granted_by,
            cascade,
        })
    }

    /// Parse an REPLACE statement
    pub fn parse_replace(
        &mut self,
        replace_token: TokenWithSpan,
    ) -> Result<Statement, ParserError> {
        if !dialect_of!(self is MySqlDialect | GenericDialect) {
            return parser_err!(
                "Unsupported statement REPLACE",
                self.peek_token_ref().span.start
            );
        }

        let mut insert = self.parse_insert(replace_token)?;
        if let Statement::Insert(Insert { replace_into, .. }) = &mut insert {
            *replace_into = true;
        }

        Ok(insert)
    }

    /// Parse an INSERT statement, returning a `Box`ed SetExpr
    ///
    /// This is used to reduce the size of the stack frames in debug builds
    fn parse_insert_setexpr_boxed(
        &mut self,
        insert_token: TokenWithSpan,
    ) -> Result<Box<SetExpr>, ParserError> {
        Ok(Box::new(SetExpr::Insert(self.parse_insert(insert_token)?)))
    }

    /// Parse an INSERT statement
    pub fn parse_insert(&mut self, insert_token: TokenWithSpan) -> Result<Statement, ParserError> {
        let optimizer_hints = self.maybe_parse_optimizer_hints()?;
        let or = self.parse_conflict_clause();
        let priority = if !dialect_of!(self is MySqlDialect | GenericDialect) {
            None
        } else if self.parse_keyword(Keyword::LOW_PRIORITY) {
            Some(MysqlInsertPriority::LowPriority)
        } else if self.parse_keyword(Keyword::DELAYED) {
            Some(MysqlInsertPriority::Delayed)
        } else if self.parse_keyword(Keyword::HIGH_PRIORITY) {
            Some(MysqlInsertPriority::HighPriority)
        } else {
            None
        };

        let ignore = dialect_of!(self is MySqlDialect | GenericDialect)
            && self.parse_keyword(Keyword::IGNORE);

        let replace_into = false;

        let overwrite = self.parse_keyword(Keyword::OVERWRITE);
        let into = self.parse_keyword(Keyword::INTO);

        let local = self.parse_keyword(Keyword::LOCAL);

        if self.parse_keyword(Keyword::DIRECTORY) {
            let path = self.parse_literal_string()?;
            let file_format = if self.parse_keywords(&[Keyword::STORED, Keyword::AS]) {
                Some(self.parse_file_format()?)
            } else {
                None
            };
            let source = self.parse_query()?;
            Ok(Statement::Directory {
                local,
                path,
                overwrite,
                file_format,
                source,
            })
        } else {
            // Hive lets you put table here regardless
            let table = self.parse_keyword(Keyword::TABLE);
            let table_object = self.parse_table_object()?;

            // `BY NAME` and `OVERRIDING { SYSTEM | USER } VALUE` are INSERT clauses, not table
            // aliases.
            let table_alias = if self.dialect.supports_insert_table_alias()
                && !self.peek_keywords(&[Keyword::BY, Keyword::NAME])
                && !self.peek_keywords(&[Keyword::OVERRIDING, Keyword::SYSTEM])
                && !self.peek_keywords(&[Keyword::OVERRIDING, Keyword::USER])
                && !self.peek_sub_query()
                && self
                    .peek_one_of_keywords(&[Keyword::DEFAULT, Keyword::VALUES])
                    .is_none()
            {
                if self.parse_keyword(Keyword::AS) {
                    Some(TableAliasWithoutColumns {
                        explicit: true,
                        alias: self.parse_identifier()?,
                    })
                } else {
                    self.maybe_parse(|parser| parser.parse_identifier())?
                        .map(|alias| TableAliasWithoutColumns {
                            explicit: false,
                            alias,
                        })
                }
            } else {
                None
            };

            let is_mysql = dialect_of!(self is MySqlDialect);

            let mut by_name = false;
            let mut overriding = None;
            let (columns, partitioned, after_columns, output, source, assignments) = if self
                .parse_keywords(&[Keyword::DEFAULT, Keyword::VALUES])
            {
                (vec![], None, vec![], None, None, vec![])
            } else {
                let (columns, partitioned, after_columns) = if !self.peek_subquery_start() {
                    let columns =
                        self.parse_parenthesized_qualified_column_list(Optional, is_mysql)?;

                    let partitioned = self.parse_insert_partition()?;
                    by_name = self.parse_keywords(&[Keyword::BY, Keyword::NAME]);
                    // Hive allows you to specify columns after partitions as well if you want.
                    let after_columns = if dialect_of!(self is HiveDialect) {
                        self.parse_parenthesized_column_list(Optional, false)?
                    } else {
                        vec![]
                    };
                    (columns, partitioned, after_columns)
                } else {
                    Default::default()
                };

                overriding = self.parse_insert_overriding()?;

                let output = self.maybe_parse_output_clause()?;

                let (source, assignments) = if self.peek_keyword(Keyword::FORMAT)
                    || self.peek_keyword(Keyword::SETTINGS)
                {
                    (None, vec![])
                } else if self.dialect.supports_insert_set() && self.parse_keyword(Keyword::SET) {
                    (None, self.parse_comma_separated(Parser::parse_assignment)?)
                } else {
                    (Some(self.parse_query()?), vec![])
                };

                (
                    columns,
                    partitioned,
                    after_columns,
                    output,
                    source,
                    assignments,
                )
            };

            let (format_clause, settings) = if self.dialect.supports_insert_format() {
                // Settings always comes before `FORMAT` for ClickHouse:
                // <https://clickhouse.com/docs/en/sql-reference/statements/insert-into>
                let settings = self.parse_settings()?;

                let format = if self.parse_keyword(Keyword::FORMAT) {
                    Some(self.parse_input_format_clause()?)
                } else {
                    None
                };

                (format, settings)
            } else {
                Default::default()
            };

            let insert_alias = if dialect_of!(self is MySqlDialect | GenericDialect)
                && self.parse_keyword(Keyword::AS)
            {
                let row_alias = self.parse_object_name(false)?;
                let col_aliases = Some(self.parse_parenthesized_column_list(Optional, false)?);
                Some(InsertAliases {
                    row_alias,
                    col_aliases,
                })
            } else {
                None
            };

            let on = if self.parse_keyword(Keyword::ON) {
                if self.parse_keyword(Keyword::CONFLICT) {
                    let conflict_target =
                        if self.parse_keywords(&[Keyword::ON, Keyword::CONSTRAINT]) {
                            Some(ConflictTarget::OnConstraint(self.parse_object_name(false)?))
                        } else if self.peek_token_ref().token == Token::LParen {
                            Some(ConflictTarget::Columns(
                                self.parse_parenthesized_column_list(IsOptional::Mandatory, false)?,
                            ))
                        } else {
                            None
                        };

                    self.expect_keyword_is(Keyword::DO)?;
                    let action = if self.parse_keyword(Keyword::NOTHING) {
                        OnConflictAction::DoNothing
                    } else {
                        self.expect_keyword_is(Keyword::UPDATE)?;
                        self.expect_keyword_is(Keyword::SET)?;
                        let assignments = self.parse_comma_separated(Parser::parse_assignment)?;
                        let selection = if self.parse_keyword(Keyword::WHERE) {
                            Some(self.parse_expr()?)
                        } else {
                            None
                        };
                        OnConflictAction::DoUpdate(DoUpdate {
                            assignments,
                            selection,
                        })
                    };

                    Some(OnInsert::OnConflict(OnConflict {
                        conflict_target,
                        action,
                    }))
                } else {
                    self.expect_keyword_is(Keyword::DUPLICATE)?;
                    self.expect_keyword_is(Keyword::KEY)?;
                    self.expect_keyword_is(Keyword::UPDATE)?;
                    let l = self.parse_comma_separated(Parser::parse_assignment)?;

                    Some(OnInsert::DuplicateKeyUpdate(l))
                }
            } else {
                None
            };

            let returning = if self.parse_keyword(Keyword::RETURNING) {
                Some(self.parse_comma_separated(Parser::parse_select_item)?)
            } else {
                None
            };

            Ok(Insert {
                insert_token: insert_token.into(),
                optimizer_hints,
                or,
                table: table_object,
                table_alias,
                ignore,
                into,
                overwrite,
                by_name,
                partitioned,
                columns,
                after_columns,
                overriding,
                source,
                assignments,
                has_table_keyword: table,
                on,
                returning,
                output,
                replace_into,
                priority,
                insert_alias,
                settings,
                format_clause,
                multi_table_insert_type: None,
                multi_table_into_clauses: vec![],
                multi_table_when_clauses: vec![],
                multi_table_else_clause: None,
            }
            .into())
        }
    }

    /// Parses input format clause used for ClickHouse.
    ///
    /// <https://clickhouse.com/docs/en/interfaces/formats>
    pub fn parse_input_format_clause(&mut self) -> Result<InputFormatClause, ParserError> {
        let ident = self.parse_identifier()?;
        let values = self
            .maybe_parse(|p| p.parse_comma_separated(|p| p.parse_expr()))?
            .unwrap_or_default();

        Ok(InputFormatClause { ident, values })
    }

    /// Returns true if the immediate tokens look like the
    /// beginning of a subquery. `(SELECT ...` or `((SELECT ...` etc.
    fn peek_subquery_start(&mut self) -> bool {
        // Handle (SELECT, ((SELECT, (((SELECT, etc.
        // This makes INSERT consistent with other contexts where nested
        // parentheses around subqueries are handled by recursive descent.
        let mut i = 0;
        loop {
            match &self.peek_nth_token_ref(i).token {
                Token::LParen => i += 1,
                Token::Word(w) if w.keyword == Keyword::SELECT => return i > 0,
                _ => return false,
            }
        }
    }

    /// Returns true if the immediate tokens look like the
    /// beginning of a subquery possibly preceded by CTEs;
    /// i.e. `(WITH ...` or `(SELECT ...`.
    fn peek_subquery_or_cte_start(&mut self) -> bool {
        matches!(
            self.peek_tokens_ref(),
            [
                TokenWithSpan {
                    token: Token::LParen,
                    ..
                },
                TokenWithSpan {
                    token: Token::Word(Word {
                        keyword: Keyword::SELECT | Keyword::WITH,
                        ..
                    }),
                    ..
                },
            ]
        )
    }

    fn parse_conflict_clause(&mut self) -> Option<SqliteOnConflict> {
        if self.parse_keywords(&[Keyword::OR, Keyword::REPLACE]) {
            Some(SqliteOnConflict::Replace)
        } else if self.parse_keywords(&[Keyword::OR, Keyword::ROLLBACK]) {
            Some(SqliteOnConflict::Rollback)
        } else if self.parse_keywords(&[Keyword::OR, Keyword::ABORT]) {
            Some(SqliteOnConflict::Abort)
        } else if self.parse_keywords(&[Keyword::OR, Keyword::FAIL]) {
            Some(SqliteOnConflict::Fail)
        } else if self.parse_keywords(&[Keyword::OR, Keyword::IGNORE]) {
            Some(SqliteOnConflict::Ignore)
        } else if self.parse_keyword(Keyword::REPLACE) {
            Some(SqliteOnConflict::Replace)
        } else {
            None
        }
    }

    /// Parse PostgreSQL's `OVERRIDING { SYSTEM | USER } VALUE` in an `INSERT`, if present.
    fn parse_insert_overriding(&mut self) -> Result<Option<InsertOverriding>, ParserError> {
        if !self.parse_keyword(Keyword::OVERRIDING) {
            return Ok(None);
        }
        let overriding = if self.parse_keyword(Keyword::SYSTEM) {
            InsertOverriding::System
        } else if self.parse_keyword(Keyword::USER) {
            InsertOverriding::User
        } else {
            return self.expected_ref("SYSTEM or USER", self.peek_token_ref());
        };
        self.expect_keyword_is(Keyword::VALUE)?;
        Ok(Some(overriding))
    }

    /// Parse an optional `PARTITION (...)` clause for INSERT statements.
    pub fn parse_insert_partition(&mut self) -> Result<Option<Vec<Expr>>, ParserError> {
        if self.parse_keyword(Keyword::PARTITION) {
            self.expect_token(&Token::LParen)?;
            let partition_cols = Some(self.parse_comma_separated(Parser::parse_expr)?);
            self.expect_token(&Token::RParen)?;
            Ok(partition_cols)
        } else {
            Ok(None)
        }
    }

    /// Parse optional Hive `INPUTFORMAT ... SERDE ...` clause used by LOAD DATA.
    pub fn parse_load_data_table_format(
        &mut self,
    ) -> Result<Option<HiveLoadDataFormat>, ParserError> {
        if self.parse_keyword(Keyword::INPUTFORMAT) {
            let input_format = self.parse_expr()?;
            self.expect_keyword_is(Keyword::SERDE)?;
            let serde = self.parse_expr()?;
            Ok(Some(HiveLoadDataFormat {
                input_format,
                serde,
            }))
        } else {
            Ok(None)
        }
    }

    /// Parse an UPDATE statement, returning a `Box`ed SetExpr
    ///
    /// This is used to reduce the size of the stack frames in debug builds
    fn parse_update_setexpr_boxed(
        &mut self,
        update_token: TokenWithSpan,
    ) -> Result<Box<SetExpr>, ParserError> {
        Ok(Box::new(SetExpr::Update(self.parse_update(update_token)?)))
    }

    /// Parse an `UPDATE` statement and return `Statement::Update`.
    pub fn parse_update(&mut self, update_token: TokenWithSpan) -> Result<Statement, ParserError> {
        let optimizer_hints = self.maybe_parse_optimizer_hints()?;
        let or = self.parse_conflict_clause();
        let table = self.parse_table_and_joins()?;
        let on_cluster = self.parse_optional_on_cluster()?;
        let from_before_set = if self.parse_keyword(Keyword::FROM) {
            Some(UpdateTableFromKind::BeforeSet(
                self.parse_table_with_joins()?,
            ))
        } else {
            None
        };
        self.expect_keyword(Keyword::SET)?;
        let assignments = self.parse_comma_separated(Parser::parse_assignment)?;

        let output = self.maybe_parse_output_clause()?;

        let from = if from_before_set.is_none() && self.parse_keyword(Keyword::FROM) {
            Some(UpdateTableFromKind::AfterSet(
                self.parse_table_with_joins()?,
            ))
        } else {
            from_before_set
        };
        let selection = if self.parse_keyword(Keyword::WHERE) {
            Some(self.parse_expr()?)
        } else {
            None
        };
        let returning = if self.parse_keyword(Keyword::RETURNING) {
            Some(self.parse_comma_separated(Parser::parse_select_item)?)
        } else {
            None
        };
        let order_by = if self.dialect.supports_update_order_by()
            && self.parse_keywords(&[Keyword::ORDER, Keyword::BY])
        {
            self.parse_comma_separated(Parser::parse_order_by_expr)?
        } else {
            vec![]
        };
        let limit = if self.parse_keyword(Keyword::LIMIT) {
            Some(self.parse_expr()?)
        } else {
            None
        };
        let settings = self.parse_settings()?;
        Ok(Update {
            update_token: update_token.into(),
            optimizer_hints,
            table,
            on_cluster,
            assignments,
            from,
            selection,
            returning,
            output,
            or,
            order_by,
            limit,
            settings,
        }
        .into())
    }

    /// Parse a `var = expr` assignment, used in an UPDATE statement
    pub fn parse_assignment(&mut self) -> Result<Assignment, ParserError> {
        let target = self.parse_assignment_target()?;
        if self.dialect.supports_double_eq_assignment() {
            if !self.consume_token(&Token::Eq) && !self.consume_token(&Token::DoubleEq) {
                return self.expected("= or == (for assignment)", self.peek_token());
            }
        } else {
            self.expect_token(&Token::Eq)?;
        }
        let value = self.parse_expr()?;
        Ok(Assignment { target, value })
    }

    /// Parse the left-hand side of an assignment, used in an UPDATE statement
    pub fn parse_assignment_target(&mut self) -> Result<AssignmentTarget, ParserError> {
        if self.consume_token(&Token::LParen) {
            let columns = self.parse_comma_separated(|p| p.parse_object_name(false))?;
            self.expect_token(&Token::RParen)?;
            Ok(AssignmentTarget::Tuple(columns))
        } else {
            let column = self.parse_object_name(false)?;
            Ok(AssignmentTarget::ColumnName(column))
        }
    }

    /// Parse a single function argument, handling named and unnamed variants.
    pub fn parse_function_args(&mut self) -> Result<FunctionArg, ParserError> {
        // Parse the argument expression once, then check for a named-arg
        // operator. Parsing it speculatively and re-parsing on the unnamed
        // path is O(2^depth) on nested calls like `CAST(CASE (CAST(CASE (…`.
        if self.dialect.supports_named_fn_args_with_expr_name() {
            let expr = self.parse_wildcard_expr()?;
            // A wildcard is never a named-arg name; only the unnamed form applies.
            if !matches!(expr, Expr::Wildcard(_) | Expr::QualifiedWildcard(..)) {
                if let Some(operator) =
                    self.maybe_parse(|p| p.parse_function_named_arg_operator())?
                {
                    let arg = self.parse_wildcard_expr()?.into();
                    return Ok(FunctionArg::ExprNamed {
                        name: expr,
                        arg,
                        operator,
                    });
                }
            }
            let arg_expr = self.function_arg_expr_from_wildcard(expr)?;
            return Ok(FunctionArg::Unnamed(
                self.maybe_parse_aliased_function_arg(arg_expr)?,
            ));
        }

        let arg = self.maybe_parse(|p| {
            let name = p.parse_identifier()?;
            let operator = p.parse_function_named_arg_operator()?;
            let arg = p.parse_wildcard_expr()?.into();
            Ok(FunctionArg::Named {
                name,
                arg,
                operator,
            })
        })?;
        if let Some(arg) = arg {
            return Ok(arg);
        }
        let wildcard_expr = self.parse_wildcard_expr()?;
        let arg_expr = self.function_arg_expr_from_wildcard(wildcard_expr)?;
        Ok(FunctionArg::Unnamed(
            self.maybe_parse_aliased_function_arg(arg_expr)?,
        ))
    }

    /// Wrap an already-parsed expression as a function argument, parsing any
    /// trailing wildcard options (e.g. Snowflake's `HASH(* EXCLUDE(col))`).
    fn function_arg_expr_from_wildcard(
        &mut self,
        wildcard_expr: Expr,
    ) -> Result<FunctionArgExpr, ParserError> {
        Ok(match wildcard_expr {
            Expr::Wildcard(ref token) if self.dialect.supports_select_wildcard_exclude() => {
                // Parse the options the same way SELECT items do.
                let opts = self.parse_wildcard_additional_options(token.0.clone())?;
                if opts.opt_exclude.is_some()
                    || opts.opt_except.is_some()
                    || opts.opt_replace.is_some()
                    || opts.opt_rename.is_some()
                    || opts.opt_ilike.is_some()
                {
                    FunctionArgExpr::WildcardWithOptions(opts)
                } else {
                    wildcard_expr.into()
                }
            }
            other => other.into(),
        })
    }

    /// Parse an optional `AS <alias>` on an unnamed function argument
    /// (e.g. `XMLFOREST(a AS x)` in PostgreSQL).
    fn maybe_parse_aliased_function_arg(
        &mut self,
        arg_expr: FunctionArgExpr,
    ) -> Result<FunctionArgExpr, ParserError> {
        Ok(match arg_expr {
            FunctionArgExpr::Expr(expr)
                if self.dialect.supports_aliased_function_args()
                    && self.parse_keyword(Keyword::AS) =>
            {
                FunctionArgExpr::Expr(Expr::Named {
                    expr: expr.into(),
                    name: self.parse_identifier()?,
                })
            }
            other => other,
        })
    }

    fn parse_function_named_arg_operator(&mut self) -> Result<FunctionArgOperator, ParserError> {
        if self.parse_keyword(Keyword::VALUE) {
            return Ok(FunctionArgOperator::Value);
        }
        let tok = self.next_token();
        match tok.token {
            Token::RArrow if self.dialect.supports_named_fn_args_with_rarrow_operator() => {
                Ok(FunctionArgOperator::RightArrow)
            }
            Token::Eq if self.dialect.supports_named_fn_args_with_eq_operator() => {
                Ok(FunctionArgOperator::Equals)
            }
            Token::Assignment
                if self
                    .dialect
                    .supports_named_fn_args_with_assignment_operator() =>
            {
                Ok(FunctionArgOperator::Assignment)
            }
            Token::Colon if self.dialect.supports_named_fn_args_with_colon_operator() => {
                Ok(FunctionArgOperator::Colon)
            }
            _ => {
                self.prev_token();
                self.expected("argument operator", tok)
            }
        }
    }

    /// Parse an optional, comma-separated list of function arguments (consumes closing paren).
    pub fn parse_optional_args(&mut self) -> Result<Vec<FunctionArg>, ParserError> {
        if self.consume_token(&Token::RParen) {
            Ok(vec![])
        } else {
            let args = self.parse_comma_separated(Parser::parse_function_args)?;
            self.expect_token(&Token::RParen)?;
            Ok(args)
        }
    }

    fn parse_table_function_args(&mut self) -> Result<TableFunctionArgs, ParserError> {
        if self.consume_token(&Token::RParen) {
            return Ok(TableFunctionArgs {
                args: vec![],
                settings: None,
            });
        }
        let mut args = vec![];
        let settings = loop {
            if let Some(settings) = self.parse_settings()? {
                break Some(settings);
            }
            args.push(self.parse_function_args()?);
            if self.is_parse_comma_separated_end() {
                break None;
            }
        };
        self.expect_token(&Token::RParen)?;
        Ok(TableFunctionArgs { args, settings })
    }

    /// Parses a potentially empty list of arguments to a function
    /// (including the closing parenthesis).
    ///
    /// Examples:
    /// ```sql
    /// FIRST_VALUE(x ORDER BY 1,2,3);
    /// FIRST_VALUE(x IGNORE NULL);
    /// ```
    fn parse_function_argument_list(&mut self) -> Result<FunctionArgumentList, ParserError> {
        let mut clauses = vec![];

        // Handle clauses that may exist with an empty argument list

        if let Some(null_clause) = self.parse_json_null_clause() {
            clauses.push(FunctionArgumentClause::JsonNullClause(null_clause));
        }

        if let Some(json_returning_clause) = self.maybe_parse_json_returning_clause()? {
            clauses.push(FunctionArgumentClause::JsonReturningClause(
                json_returning_clause,
            ));
        }

        if self.consume_token(&Token::RParen) {
            return Ok(FunctionArgumentList {
                duplicate_treatment: None,
                args: vec![],
                clauses,
            });
        }

        let duplicate_treatment = self.parse_duplicate_treatment()?;
        let args = self.parse_comma_separated(Parser::parse_function_args)?;

        if self.parse_keyword(Keyword::WHERE) {
            clauses.push(FunctionArgumentClause::Where(self.parse_expr()?));
        }

        if self.dialect.supports_window_function_null_treatment_arg() {
            if let Some(null_treatment) = self.parse_null_treatment()? {
                clauses.push(FunctionArgumentClause::IgnoreOrRespectNulls(null_treatment));
            }
        }

        if self.parse_keywords(&[Keyword::ORDER, Keyword::BY]) {
            clauses.push(FunctionArgumentClause::OrderBy(
                self.parse_comma_separated(Parser::parse_order_by_expr)?,
            ));
        }

        if self.parse_keyword(Keyword::LIMIT) {
            clauses.push(FunctionArgumentClause::Limit(self.parse_expr()?));
        }

        if dialect_of!(self is GenericDialect | BigQueryDialect)
            && self.parse_keyword(Keyword::HAVING)
        {
            let kind = match self.expect_one_of_keywords(&[Keyword::MIN, Keyword::MAX])? {
                Keyword::MIN => HavingBoundKind::Min,
                Keyword::MAX => HavingBoundKind::Max,
                unexpected_keyword => return Err(ParserError::ParserError(
                    format!("Internal parser error: unexpected keyword `{unexpected_keyword}` in having bound"),
                )),
            };
            clauses.push(FunctionArgumentClause::Having(HavingBound(
                kind,
                self.parse_expr()?,
            )))
        }

        if dialect_of!(self is GenericDialect | MySqlDialect)
            && self.parse_keyword(Keyword::SEPARATOR)
        {
            clauses.push(FunctionArgumentClause::Separator(self.parse_value()?));
        }

        if let Some(on_overflow) = self.parse_listagg_on_overflow()? {
            clauses.push(FunctionArgumentClause::OnOverflow(on_overflow));
        }

        if let Some(null_clause) = self.parse_json_null_clause() {
            clauses.push(FunctionArgumentClause::JsonNullClause(null_clause));
        }

        if let Some(json_returning_clause) = self.maybe_parse_json_returning_clause()? {
            clauses.push(FunctionArgumentClause::JsonReturningClause(
                json_returning_clause,
            ));
        }

        self.expect_token(&Token::RParen)?;
        Ok(FunctionArgumentList {
            duplicate_treatment,
            args,
            clauses,
        })
    }

    fn parse_json_null_clause(&mut self) -> Option<JsonNullClause> {
        if self.parse_keywords(&[Keyword::ABSENT, Keyword::ON, Keyword::NULL]) {
            Some(JsonNullClause::AbsentOnNull)
        } else if self.parse_keywords(&[Keyword::NULL, Keyword::ON, Keyword::NULL]) {
            Some(JsonNullClause::NullOnNull)
        } else {
            None
        }
    }

    fn maybe_parse_json_returning_clause(
        &mut self,
    ) -> Result<Option<JsonReturningClause>, ParserError> {
        if self.parse_keyword(Keyword::RETURNING) {
            let data_type = self.parse_data_type()?;
            Ok(Some(JsonReturningClause { data_type }))
        } else {
            Ok(None)
        }
    }

    fn parse_duplicate_treatment(&mut self) -> Result<Option<DuplicateTreatment>, ParserError> {
        let loc = self.peek_token_ref().span.start;
        match (
            self.parse_keyword(Keyword::ALL),
            self.parse_keyword(Keyword::DISTINCT),
        ) {
            (true, false) => Ok(Some(DuplicateTreatment::All)),
            (false, true) => Ok(Some(DuplicateTreatment::Distinct)),
            (false, false) => Ok(None),
            (true, true) => parser_err!("Cannot specify both ALL and DISTINCT".to_string(), loc),
        }
    }

    /// Parse a comma-delimited list of projections after SELECT
    pub fn parse_select_item(&mut self) -> Result<SelectItem, ParserError> {
        let prefix = self
            .parse_one_of_keywords(
                self.dialect
                    .get_reserved_keywords_for_select_item_operator(),
            )
            .map(|keyword| Ident::new(format!("{keyword:?}")));

        match self.parse_wildcard_expr()? {
            Expr::QualifiedWildcard(prefix, token) => Ok(SelectItem::QualifiedWildcard(
                SelectItemQualifiedWildcardKind::ObjectName(prefix),
                self.parse_wildcard_additional_options(token.0)?,
            )),
            Expr::Wildcard(token) => Ok(SelectItem::Wildcard(
                self.parse_wildcard_additional_options(token.0)?,
            )),
            Expr::Identifier(v) if v.value.to_lowercase() == "from" && v.quote_style.is_none() => {
                parser_err!(
                    format!("Expected an expression, found: {}", v),
                    self.peek_token_ref().span.start
                )
            }
            Expr::BinaryOp {
                left,
                op: BinaryOperator::Eq,
                right,
            } if self.dialect.supports_eq_alias_assignment()
                && matches!(left.as_ref(), Expr::Identifier(_)) =>
            {
                if matches!(right.as_ref(), Expr::Identifier(v) if v.value.to_lowercase() == "from" && v.quote_style.is_none())
                {
                    return parser_err!(
                        format!("Expected an expression, found: {right}"),
                        self.peek_token_ref().span.start
                    );
                }
                let Expr::Identifier(alias) = *left else {
                    return parser_err!(
                        "BUG: expected identifier expression as alias",
                        self.peek_token_ref().span.start
                    );
                };
                Ok(SelectItem::ExprWithAlias {
                    expr: *right,
                    alias,
                })
            }
            expr if self.dialect.supports_select_expr_star()
                && self.consume_tokens(&[Token::Period, Token::Mul]) =>
            {
                let wildcard_token = self.get_previous_token().clone();
                Ok(SelectItem::QualifiedWildcard(
                    SelectItemQualifiedWildcardKind::Expr(expr),
                    self.parse_wildcard_additional_options(wildcard_token)?,
                ))
            }
            expr if self.dialect.supports_select_item_multi_column_alias()
                && self.peek_keyword(Keyword::AS)
                && self.peek_nth_token(1).token == Token::LParen =>
            {
                self.expect_keyword(Keyword::AS)?;
                self.expect_token(&Token::LParen)?;
                let aliases = self.parse_comma_separated(|p| p.parse_identifier())?;
                self.expect_token(&Token::RParen)?;
                Ok(SelectItem::ExprWithAliases {
                    expr: maybe_prefixed_expr(expr, prefix),
                    aliases,
                })
            }
            expr => self
                .maybe_parse_select_item_alias()
                .map(|alias| match alias {
                    Some(alias) => SelectItem::ExprWithAlias {
                        expr: maybe_prefixed_expr(expr, prefix),
                        alias,
                    },
                    None => SelectItem::UnnamedExpr(maybe_prefixed_expr(expr, prefix)),
                }),
        }
    }

    /// Parse an [`WildcardAdditionalOptions`] information for wildcard select items.
    ///
    /// If it is not possible to parse it, will return an option.
    pub fn parse_wildcard_additional_options(
        &mut self,
        wildcard_token: TokenWithSpan,
    ) -> Result<WildcardAdditionalOptions, ParserError> {
        let opt_ilike = if self.dialect.supports_select_wildcard_ilike() {
            self.parse_optional_select_item_ilike()?
        } else {
            None
        };
        let opt_exclude = if opt_ilike.is_none() && self.dialect.supports_select_wildcard_exclude()
        {
            self.parse_optional_select_item_exclude()?
        } else {
            None
        };
        let opt_except = if self.dialect.supports_select_wildcard_except() {
            self.parse_optional_select_item_except()?
        } else {
            None
        };
        let opt_replace = if self.dialect.supports_select_wildcard_replace() {
            self.parse_optional_select_item_replace()?
        } else {
            None
        };
        let opt_rename = if self.dialect.supports_select_wildcard_rename() {
            self.parse_optional_select_item_rename()?
        } else {
            None
        };

        let opt_alias = if self.dialect.supports_select_wildcard_with_alias() {
            self.maybe_parse_select_item_alias()?
        } else {
            None
        };

        Ok(WildcardAdditionalOptions {
            wildcard_token: wildcard_token.into(),
            opt_ilike,
            opt_exclude,
            opt_except,
            opt_rename,
            opt_replace,
            opt_alias,
        })
    }

    /// Parse an [`Ilike`](IlikeSelectItem) information for wildcard select items.
    ///
    /// If it is not possible to parse it, will return an option.
    pub fn parse_optional_select_item_ilike(
        &mut self,
    ) -> Result<Option<IlikeSelectItem>, ParserError> {
        let opt_ilike = if self.parse_keyword(Keyword::ILIKE) {
            let next_token = self.next_token();
            let pattern = match next_token.token {
                Token::SingleQuotedString(s) => s,
                _ => return self.expected("ilike pattern", next_token),
            };
            Some(IlikeSelectItem { pattern })
        } else {
            None
        };
        Ok(opt_ilike)
    }

    /// Parse an [`Exclude`](ExcludeSelectItem) information for wildcard select items.
    ///
    /// If it is not possible to parse it, will return an option.
    pub fn parse_optional_select_item_exclude(
        &mut self,
    ) -> Result<Option<ExcludeSelectItem>, ParserError> {
        let opt_exclude = if self.parse_keyword(Keyword::EXCLUDE) {
            if self.consume_token(&Token::LParen) {
                let columns =
                    self.parse_comma_separated(|parser| parser.parse_object_name(false))?;
                self.expect_token(&Token::RParen)?;
                Some(ExcludeSelectItem::Multiple(columns))
            } else {
                let column = self.parse_object_name(false)?;
                Some(ExcludeSelectItem::Single(column))
            }
        } else {
            None
        };

        Ok(opt_exclude)
    }

    /// Parse an [`Except`](ExceptSelectItem) information for wildcard select items.
    ///
    /// If it is not possible to parse it, will return an option.
    pub fn parse_optional_select_item_except(
        &mut self,
    ) -> Result<Option<ExceptSelectItem>, ParserError> {
        let opt_except = if self.parse_keyword(Keyword::EXCEPT) {
            if self.peek_token_ref().token == Token::LParen {
                let idents = self.parse_parenthesized_column_list(Mandatory, false)?;
                match &idents[..] {
                    [] => {
                        return self.expected_ref(
                            "at least one column should be parsed by the expect clause",
                            self.peek_token_ref(),
                        )?;
                    }
                    [first, idents @ ..] => Some(ExceptSelectItem {
                        first_element: first.clone(),
                        additional_elements: idents.to_vec(),
                    }),
                }
            } else {
                // Clickhouse allows EXCEPT column_name
                let ident = self.parse_identifier()?;
                Some(ExceptSelectItem {
                    first_element: ident,
                    additional_elements: vec![],
                })
            }
        } else {
            None
        };

        Ok(opt_except)
    }

    /// Parse a [`Rename`](RenameSelectItem) information for wildcard select items.
    pub fn parse_optional_select_item_rename(
        &mut self,
    ) -> Result<Option<RenameSelectItem>, ParserError> {
        let opt_rename = if self.parse_keyword(Keyword::RENAME) {
            if self.consume_token(&Token::LParen) {
                let idents =
                    self.parse_comma_separated(|parser| parser.parse_identifier_with_alias())?;
                self.expect_token(&Token::RParen)?;
                Some(RenameSelectItem::Multiple(idents))
            } else {
                let ident = self.parse_identifier_with_alias()?;
                Some(RenameSelectItem::Single(ident))
            }
        } else {
            None
        };

        Ok(opt_rename)
    }

    /// Parse a [`Replace`](ReplaceSelectItem) information for wildcard select items.
    pub fn parse_optional_select_item_replace(
        &mut self,
    ) -> Result<Option<ReplaceSelectItem>, ParserError> {
        let opt_replace = if self.parse_keyword(Keyword::REPLACE) {
            if self.consume_token(&Token::LParen) {
                let items = self.parse_comma_separated(|parser| {
                    Ok(Box::new(parser.parse_replace_elements()?))
                })?;
                self.expect_token(&Token::RParen)?;
                Some(ReplaceSelectItem { items })
            } else {
                let tok = self.next_token();
                return self.expected("( after REPLACE but", tok);
            }
        } else {
            None
        };

        Ok(opt_replace)
    }
    /// Parse a single element of a `REPLACE (...)` select-item clause.
    pub fn parse_replace_elements(&mut self) -> Result<ReplaceSelectElement, ParserError> {
        let expr = self.parse_expr()?;
        let as_keyword = self.parse_keyword(Keyword::AS);
        let ident = self.parse_identifier()?;
        Ok(ReplaceSelectElement {
            expr,
            column_name: ident,
            as_keyword,
        })
    }

    /// Parse ASC or DESC, returns an Option with true if ASC, false of DESC or `None` if none of
    /// them.
    pub fn parse_asc_desc(&mut self) -> Option<bool> {
        if self.parse_keyword(Keyword::ASC) {
            Some(true)
        } else if self.parse_keyword(Keyword::DESC) {
            Some(false)
        } else {
            None
        }
    }

    /// Parse ASC or DESC and map to [OrderBySort].
    fn parse_optional_order_by_sort(&mut self) -> Option<OrderBySort> {
        match self.parse_asc_desc() {
            Some(true) => Some(OrderBySort::Asc),
            Some(false) => Some(OrderBySort::Desc),
            None => None,
        }
    }

    /// Parse an [OrderByExpr] expression.
    pub fn parse_order_by_expr(&mut self) -> Result<OrderByExpr, ParserError> {
        self.parse_order_by_expr_inner(false)
            .map(|(order_by, _)| order_by)
    }

    /// Parse an [IndexColumn].
    pub fn parse_create_index_expr(&mut self) -> Result<IndexColumn, ParserError> {
        self.parse_order_by_expr_inner(true)
            .map(|(column, operator_class)| IndexColumn {
                column,
                operator_class,
            })
    }

    fn parse_order_by_expr_inner(
        &mut self,
        with_operator_class: bool,
    ) -> Result<(OrderByExpr, Option<ObjectName>), ParserError> {
        let expr = self.parse_expr()?;

        let operator_class: Option<ObjectName> = if with_operator_class {
            // We check that if non of the following keywords are present, then we parse an
            // identifier as operator class.
            if self
                .peek_one_of_keywords(&[Keyword::ASC, Keyword::DESC, Keyword::NULLS, Keyword::WITH])
                .is_some()
            {
                None
            } else {
                self.maybe_parse(|parser| parser.parse_object_name(false))?
            }
        } else {
            None
        };

        let options = if !with_operator_class
            && self.dialect.supports_order_by_using_operator()
            && self.parse_keyword(Keyword::USING)
        {
            let op = self.parse_order_by_using_operator()?;
            OrderByOptions {
                sort: Some(OrderBySort::Using(op)),
                nulls_first: self.parse_null_ordering_modifier(),
            }
        } else {
            self.parse_order_by_options()?
        };

        let with_fill = if self.dialect.supports_with_fill()
            && self.parse_keywords(&[Keyword::WITH, Keyword::FILL])
        {
            Some(self.parse_with_fill()?)
        } else {
            None
        };

        Ok((
            OrderByExpr {
                expr,
                options,
                with_fill,
            },
            operator_class,
        ))
    }

    fn parse_order_by_using_operator(&mut self) -> Result<ObjectName, ParserError> {
        if self.parse_keyword(Keyword::OPERATOR) {
            self.expect_token(&Token::LParen)?;
            let operator_name = self.parse_operator_name()?;
            self.expect_token(&Token::RParen)?;
            return Ok(operator_name);
        }

        let token = self.next_token();
        Ok(ObjectName::from(vec![Ident::new(token.token.to_string())]))
    }

    fn parse_null_ordering_modifier(&mut self) -> Option<bool> {
        if self.parse_keywords(&[Keyword::NULLS, Keyword::FIRST]) {
            Some(true)
        } else if self.parse_keywords(&[Keyword::NULLS, Keyword::LAST]) {
            Some(false)
        } else {
            None
        }
    }

    fn parse_order_by_options(&mut self) -> Result<OrderByOptions, ParserError> {
        let sort = self.parse_optional_order_by_sort();
        let nulls_first = self.parse_null_ordering_modifier();

        Ok(OrderByOptions { sort, nulls_first })
    }

    // Parse a WITH FILL clause (ClickHouse dialect)
    // that follow the WITH FILL keywords in a ORDER BY clause
    /// Parse a `WITH FILL` clause used in ORDER BY (ClickHouse dialect).
    pub fn parse_with_fill(&mut self) -> Result<WithFill, ParserError> {
        let from = if self.parse_keyword(Keyword::FROM) {
            Some(self.parse_expr()?)
        } else {
            None
        };

        let to = if self.parse_keyword(Keyword::TO) {
            Some(self.parse_expr()?)
        } else {
            None
        };

        let step = if self.parse_keyword(Keyword::STEP) {
            Some(self.parse_expr()?)
        } else {
            None
        };

        Ok(WithFill { from, to, step })
    }

    /// Parse a set of comma separated INTERPOLATE expressions (ClickHouse dialect)
    /// that follow the INTERPOLATE keyword in an ORDER BY clause with the WITH FILL modifier
    pub fn parse_interpolations(&mut self) -> Result<Option<Interpolate>, ParserError> {
        if !self.parse_keyword(Keyword::INTERPOLATE) {
            return Ok(None);
        }

        if self.consume_token(&Token::LParen) {
            let interpolations =
                self.parse_comma_separated0(|p| p.parse_interpolation(), Token::RParen)?;
            self.expect_token(&Token::RParen)?;
            // INTERPOLATE () and INTERPOLATE ( ... ) variants
            return Ok(Some(Interpolate {
                exprs: Some(interpolations),
            }));
        }

        // INTERPOLATE
        Ok(Some(Interpolate { exprs: None }))
    }

    /// Parse a INTERPOLATE expression (ClickHouse dialect)
    pub fn parse_interpolation(&mut self) -> Result<InterpolateExpr, ParserError> {
        let column = self.parse_identifier()?;
        let expr = if self.parse_keyword(Keyword::AS) {
            Some(self.parse_expr()?)
        } else {
            None
        };
        Ok(InterpolateExpr { column, expr })
    }

    /// Parse a TOP clause, MSSQL equivalent of LIMIT,
    /// that follows after `SELECT [DISTINCT]`.
    pub fn parse_top(&mut self) -> Result<Top, ParserError> {
        let quantity = if self.consume_token(&Token::LParen) {
            let quantity = self.parse_expr()?;
            self.expect_token(&Token::RParen)?;
            Some(TopQuantity::Expr(quantity))
        } else {
            let next_token = self.next_token();
            let quantity = match next_token.token {
                Token::Number(s, _) => Self::parse::<u64>(s, next_token.span.start)?,
                _ => self.expected("literal int", next_token)?,
            };
            Some(TopQuantity::Constant(quantity))
        };

        let percent = self.parse_keyword(Keyword::PERCENT);

        let with_ties = self.parse_keywords(&[Keyword::WITH, Keyword::TIES]);

        Ok(Top {
            with_ties,
            percent,
            quantity,
        })
    }

    /// Parse a LIMIT clause
    pub fn parse_limit(&mut self) -> Result<Option<Expr>, ParserError> {
        if self.parse_keyword(Keyword::ALL) {
            Ok(None)
        } else {
            Ok(Some(self.parse_expr()?))
        }
    }

    /// Parse an OFFSET clause
    pub fn parse_offset(&mut self) -> Result<Offset, ParserError> {
        let value = self.parse_expr()?;
        let rows = if self.parse_keyword(Keyword::ROW) {
            OffsetRows::Row
        } else if self.parse_keyword(Keyword::ROWS) {
            OffsetRows::Rows
        } else {
            OffsetRows::None
        };
        Ok(Offset { value, rows })
    }

    /// Parse a FETCH clause
    pub fn parse_fetch(&mut self) -> Result<Fetch, ParserError> {
        let _ = self.parse_one_of_keywords(&[Keyword::FIRST, Keyword::NEXT]);

        let (quantity, percent) = if self
            .parse_one_of_keywords(&[Keyword::ROW, Keyword::ROWS])
            .is_some()
        {
            (None, false)
        } else {
            let quantity = Expr::Value(self.parse_value()?);
            let percent = self.parse_keyword(Keyword::PERCENT);
            let _ = self.parse_one_of_keywords(&[Keyword::ROW, Keyword::ROWS]);
            (Some(quantity), percent)
        };

        let with_ties = if self.parse_keyword(Keyword::ONLY) {
            false
        } else {
            self.parse_keywords(&[Keyword::WITH, Keyword::TIES])
        };

        Ok(Fetch {
            with_ties,
            percent,
            quantity,
        })
    }

    /// Parse a FOR UPDATE/FOR SHARE clause
    pub fn parse_lock(&mut self) -> Result<LockClause, ParserError> {
        let lock_type = match self.expect_one_of_keywords(&[Keyword::UPDATE, Keyword::SHARE])? {
            Keyword::UPDATE => LockType::Update,
            Keyword::SHARE => LockType::Share,
            unexpected_keyword => return Err(ParserError::ParserError(
                format!("Internal parser error: expected any of {{UPDATE, SHARE}}, got {unexpected_keyword:?}"),
            )),
        };
        let of = if self.parse_keyword(Keyword::OF) {
            Some(self.parse_object_name(false)?)
        } else {
            None
        };
        let nonblock = if self.parse_keyword(Keyword::NOWAIT) {
            Some(NonBlock::Nowait)
        } else if self.parse_keywords(&[Keyword::SKIP, Keyword::LOCKED]) {
            Some(NonBlock::SkipLocked)
        } else {
            None
        };
        Ok(LockClause {
            lock_type,
            of,
            nonblock,
        })
    }

    /// Parse a PostgreSQL `LOCK` statement.
    pub fn parse_lock_statement(&mut self) -> Result<Lock, ParserError> {
        self.expect_keyword(Keyword::LOCK)?;

        if self.peek_keyword(Keyword::TABLES) {
            return self.expected_ref("TABLE or a table name", self.peek_token_ref());
        }

        let _ = self.parse_keyword(Keyword::TABLE);
        let tables = self.parse_comma_separated(Parser::parse_lock_table_target)?;
        let lock_mode = if self.parse_keyword(Keyword::IN) {
            let lock_mode = self.parse_lock_table_mode()?;
            self.expect_keyword(Keyword::MODE)?;
            Some(lock_mode)
        } else {
            None
        };
        let nowait = self.parse_keyword(Keyword::NOWAIT);

        Ok(Lock {
            tables,
            lock_mode,
            nowait,
        })
    }

    fn parse_lock_table_target(&mut self) -> Result<LockTableTarget, ParserError> {
        let only = self.parse_keyword(Keyword::ONLY);
        let name = self.parse_object_name(false)?;
        let has_asterisk = self.consume_token(&Token::Mul);

        Ok(LockTableTarget {
            name,
            only,
            has_asterisk,
        })
    }

    fn parse_lock_table_mode(&mut self) -> Result<LockTableMode, ParserError> {
        if self.parse_keywords(&[Keyword::ACCESS, Keyword::SHARE]) {
            Ok(LockTableMode::AccessShare)
        } else if self.parse_keywords(&[Keyword::ACCESS, Keyword::EXCLUSIVE]) {
            Ok(LockTableMode::AccessExclusive)
        } else if self.parse_keywords(&[Keyword::ROW, Keyword::SHARE]) {
            Ok(LockTableMode::RowShare)
        } else if self.parse_keywords(&[Keyword::ROW, Keyword::EXCLUSIVE]) {
            Ok(LockTableMode::RowExclusive)
        } else if self.parse_keywords(&[Keyword::SHARE, Keyword::UPDATE, Keyword::EXCLUSIVE]) {
            Ok(LockTableMode::ShareUpdateExclusive)
        } else if self.parse_keywords(&[Keyword::SHARE, Keyword::ROW, Keyword::EXCLUSIVE]) {
            Ok(LockTableMode::ShareRowExclusive)
        } else if self.parse_keyword(Keyword::SHARE) {
            Ok(LockTableMode::Share)
        } else if self.parse_keyword(Keyword::EXCLUSIVE) {
            Ok(LockTableMode::Exclusive)
        } else {
            self.expected_ref("a PostgreSQL LOCK TABLE mode", self.peek_token_ref())
        }
    }

    /// Parse a VALUES clause
    pub fn parse_values(
        &mut self,
        allow_empty: bool,
        value_keyword: bool,
    ) -> Result<Values, ParserError> {
        let mut explicit_row = false;

        let rows = self.parse_comma_separated(|parser| {
            if parser.parse_keyword(Keyword::ROW) {
                explicit_row = true;
            }
            Ok(Parens {
                opening_token: parser.expect_token(&Token::LParen)?.into(),
                content: if allow_empty && parser.peek_token_ref().token == Token::RParen {
                    vec![]
                } else {
                    parser.parse_comma_separated(Parser::parse_expr)?
                },
                closing_token: parser.expect_token(&Token::RParen)?.into(),
            })
        })?;
        Ok(Values {
            explicit_row,
            rows,
            value_keyword,
        })
    }

    /// Parse a 'START TRANSACTION' statement
    pub fn parse_start_transaction(&mut self) -> Result<Statement, ParserError> {
        self.expect_keyword_is(Keyword::TRANSACTION)?;
        Ok(Statement::StartTransaction {
            modes: self.parse_transaction_modes()?,
            begin: false,
            transaction: Some(BeginTransactionKind::Transaction),
            modifier: None,
            statements: vec![],
            exception: None,
            has_end_keyword: false,
        })
    }

    /// Parse a transaction modifier keyword that can follow a `BEGIN` statement.
    pub(crate) fn parse_transaction_modifier(&mut self) -> Option<TransactionModifier> {
        if !self.dialect.supports_start_transaction_modifier() {
            None
        } else if self.parse_keyword(Keyword::DEFERRED) {
            Some(TransactionModifier::Deferred)
        } else if self.parse_keyword(Keyword::IMMEDIATE) {
            Some(TransactionModifier::Immediate)
        } else if self.parse_keyword(Keyword::EXCLUSIVE) {
            Some(TransactionModifier::Exclusive)
        } else if self.parse_keyword(Keyword::TRY) {
            Some(TransactionModifier::Try)
        } else if self.parse_keyword(Keyword::CATCH) {
            Some(TransactionModifier::Catch)
        } else {
            None
        }
    }

    /// Parse a 'BEGIN' statement
    pub fn parse_begin(&mut self) -> Result<Statement, ParserError> {
        let modifier = self.parse_transaction_modifier();
        let transaction =
            match self.parse_one_of_keywords(&[Keyword::TRANSACTION, Keyword::WORK, Keyword::TRAN])
            {
                Some(Keyword::TRANSACTION) => Some(BeginTransactionKind::Transaction),
                Some(Keyword::WORK) => Some(BeginTransactionKind::Work),
                Some(Keyword::TRAN) => Some(BeginTransactionKind::Tran),
                _ => None,
            };
        Ok(Statement::StartTransaction {
            modes: self.parse_transaction_modes()?,
            begin: true,
            transaction,
            modifier,
            statements: vec![],
            exception: None,
            has_end_keyword: false,
        })
    }

    /// Parse a 'BEGIN ... EXCEPTION ... END' block
    pub fn parse_begin_exception_end(&mut self) -> Result<Statement, ParserError> {
        let statements = self.parse_statement_list(&[Keyword::EXCEPTION, Keyword::END])?;

        let exception = if self.parse_keyword(Keyword::EXCEPTION) {
            let mut when = Vec::new();

            // We can have multiple `WHEN` arms so we consume all cases until `END`
            while !self.peek_keyword(Keyword::END) {
                self.expect_keyword(Keyword::WHEN)?;

                // Each `WHEN` case can have one or more conditions, e.g.
                // WHEN EXCEPTION_1 [OR EXCEPTION_2] THEN
                // So we parse identifiers until the `THEN` keyword.
                let mut idents = Vec::new();

                while !self.parse_keyword(Keyword::THEN) {
                    let ident = self.parse_identifier()?;
                    idents.push(ident);

                    self.maybe_parse(|p| p.expect_keyword(Keyword::OR))?;
                }

                let statements = self.parse_statement_list(&[Keyword::WHEN, Keyword::END])?;

                when.push(ExceptionWhen { idents, statements });
            }

            Some(when)
        } else {
            None
        };

        self.expect_keyword(Keyword::END)?;

        Ok(Statement::StartTransaction {
            begin: true,
            statements,
            exception,
            has_end_keyword: true,
            transaction: None,
            modifier: None,
            modes: Default::default(),
        })
    }

    /// Parse an 'END' statement
    pub fn parse_end(&mut self) -> Result<Statement, ParserError> {
        let modifier = if !self.dialect.supports_end_transaction_modifier() {
            None
        } else if self.parse_keyword(Keyword::TRY) {
            Some(TransactionModifier::Try)
        } else if self.parse_keyword(Keyword::CATCH) {
            Some(TransactionModifier::Catch)
        } else {
            None
        };
        Ok(Statement::Commit {
            chain: self.parse_commit_rollback_chain()?,
            end: true,
            modifier,
        })
    }

    /// Parse a list of transaction modes
    pub fn parse_transaction_modes(&mut self) -> Result<Vec<TransactionMode>, ParserError> {
        let mut modes = vec![];
        let mut required = false;
        loop {
            let mode = if self.parse_keywords(&[Keyword::ISOLATION, Keyword::LEVEL]) {
                let iso_level = if self.parse_keywords(&[Keyword::READ, Keyword::UNCOMMITTED]) {
                    TransactionIsolationLevel::ReadUncommitted
                } else if self.parse_keywords(&[Keyword::READ, Keyword::COMMITTED]) {
                    TransactionIsolationLevel::ReadCommitted
                } else if self.parse_keywords(&[Keyword::REPEATABLE, Keyword::READ]) {
                    TransactionIsolationLevel::RepeatableRead
                } else if self.parse_keyword(Keyword::SERIALIZABLE) {
                    TransactionIsolationLevel::Serializable
                } else if self.parse_keyword(Keyword::SNAPSHOT) {
                    TransactionIsolationLevel::Snapshot
                } else {
                    self.expected_ref("isolation level", self.peek_token_ref())?
                };
                TransactionMode::IsolationLevel(iso_level)
            } else if self.parse_keywords(&[Keyword::READ, Keyword::ONLY]) {
                TransactionMode::AccessMode(TransactionAccessMode::ReadOnly)
            } else if self.parse_keywords(&[Keyword::READ, Keyword::WRITE]) {
                TransactionMode::AccessMode(TransactionAccessMode::ReadWrite)
            } else if required {
                self.expected_ref("transaction mode", self.peek_token_ref())?
            } else {
                break;
            };
            modes.push(mode);
            // ANSI requires a comma after each transaction mode, but
            // PostgreSQL, for historical reasons, does not. We follow
            // PostgreSQL in making the comma optional, since that is strictly
            // more general.
            required = self.consume_token(&Token::Comma);
        }
        Ok(modes)
    }

    /// Parse a 'COMMIT' statement
    pub fn parse_commit(&mut self) -> Result<Statement, ParserError> {
        Ok(Statement::Commit {
            chain: self.parse_commit_rollback_chain()?,
            end: false,
            modifier: None,
        })
    }

    /// Parse a 'ROLLBACK' statement
    pub fn parse_rollback(&mut self) -> Result<Statement, ParserError> {
        let chain = self.parse_commit_rollback_chain()?;
        let savepoint = self.parse_rollback_savepoint()?;

        Ok(Statement::Rollback { chain, savepoint })
    }

    /// Parse an 'ABORT' statement
    ///
    /// ```sql
    /// ABORT [ TRANSACTION | WORK ] [ AND [ NO ] CHAIN ]
    /// ```
    pub fn parse_abort(&mut self) -> Result<Statement, ParserError> {
        let chain = self.parse_commit_rollback_chain()?;

        Ok(Statement::Rollback {
            chain,
            savepoint: None,
        })
    }

    /// Parse an optional `AND [NO] CHAIN` clause for `COMMIT` and `ROLLBACK` statements
    pub fn parse_commit_rollback_chain(&mut self) -> Result<bool, ParserError> {
        let _ = self.parse_one_of_keywords(&[Keyword::TRANSACTION, Keyword::WORK, Keyword::TRAN]);
        if self.parse_keyword(Keyword::AND) {
            let chain = !self.parse_keyword(Keyword::NO);
            self.expect_keyword_is(Keyword::CHAIN)?;
            Ok(chain)
        } else {
            Ok(false)
        }
    }

    /// Parse an optional 'TO SAVEPOINT savepoint_name' clause for ROLLBACK statements
    pub fn parse_rollback_savepoint(&mut self) -> Result<Option<Ident>, ParserError> {
        if self.parse_keyword(Keyword::TO) {
            let _ = self.parse_keyword(Keyword::SAVEPOINT);
            let savepoint = self.parse_identifier()?;

            Ok(Some(savepoint))
        } else {
            Ok(None)
        }
    }

    /// Parse a 'RAISERROR' statement
    pub fn parse_raiserror(&mut self) -> Result<Statement, ParserError> {
        self.expect_token(&Token::LParen)?;
        let message = Box::new(self.parse_expr()?);
        self.expect_token(&Token::Comma)?;
        let severity = Box::new(self.parse_expr()?);
        self.expect_token(&Token::Comma)?;
        let state = Box::new(self.parse_expr()?);
        let arguments = if self.consume_token(&Token::Comma) {
            self.parse_comma_separated(Parser::parse_expr)?
        } else {
            vec![]
        };
        self.expect_token(&Token::RParen)?;
        let options = if self.parse_keyword(Keyword::WITH) {
            self.parse_comma_separated(Parser::parse_raiserror_option)?
        } else {
            vec![]
        };
        Ok(Statement::RaisError {
            message,
            severity,
            state,
            arguments,
            options,
        })
    }

    /// Parse a single `RAISERROR` option
    pub fn parse_raiserror_option(&mut self) -> Result<RaisErrorOption, ParserError> {
        match self.expect_one_of_keywords(&[Keyword::LOG, Keyword::NOWAIT, Keyword::SETERROR])? {
            Keyword::LOG => Ok(RaisErrorOption::Log),
            Keyword::NOWAIT => Ok(RaisErrorOption::NoWait),
            Keyword::SETERROR => Ok(RaisErrorOption::SetError),
            _ => self.expected_ref(
                "LOG, NOWAIT OR SETERROR raiserror option",
                self.peek_token_ref(),
            ),
        }
    }

    /// Parse a MSSQL `THROW` statement.
    ///
    /// See [Statement::Throw]
    pub fn parse_throw(&mut self) -> Result<ThrowStatement, ParserError> {
        self.expect_keyword_is(Keyword::THROW)?;

        let error_number = self.maybe_parse(|p| p.parse_expr().map(Box::new))?;
        let (message, state) = if error_number.is_some() {
            self.expect_token(&Token::Comma)?;
            let message = Box::new(self.parse_expr()?);
            self.expect_token(&Token::Comma)?;
            let state = Box::new(self.parse_expr()?);
            (Some(message), Some(state))
        } else {
            (None, None)
        };

        Ok(ThrowStatement {
            error_number,
            message,
            state,
        })
    }

    /// Parse a SQL `DEALLOCATE` statement
    pub fn parse_deallocate(&mut self) -> Result<Statement, ParserError> {
        let prepare = self.parse_keyword(Keyword::PREPARE);
        let name = self.parse_identifier()?;
        Ok(Statement::Deallocate { name, prepare })
    }

    /// Parse a SQL `EXECUTE` statement
    pub fn parse_execute(&mut self) -> Result<Statement, ParserError> {
        let immediate =
            self.dialect.supports_execute_immediate() && self.parse_keyword(Keyword::IMMEDIATE);

        // When `EXEC` is immediately followed by `(`, the content is a dynamic-SQL
        // expression — e.g. `EXEC (@sql)`, `EXEC ('SELECT ...')`, or
        // `EXEC ('SELECT ... FROM ' + @tbl + ' WHERE ...')`.
        // Skip name parsing; the expression ends up in `parameters` via the
        // `has_parentheses` path below, consistent with `EXECUTE IMMEDIATE <expr>`.
        let name = if immediate || matches!(self.peek_token_ref().token, Token::LParen) {
            None
        } else {
            Some(self.parse_object_name(false)?)
        };

        let has_parentheses = self.consume_token(&Token::LParen);

        let end_kws = &[Keyword::USING, Keyword::OUTPUT, Keyword::DEFAULT];
        let end_token = match (has_parentheses, self.peek_token().token) {
            (true, _) => Token::RParen,
            (false, Token::EOF) => Token::EOF,
            (false, Token::Word(w)) if end_kws.contains(&w.keyword) => Token::Word(w),
            (false, _) => Token::SemiColon,
        };

        let parameters = self.parse_comma_separated0(Parser::parse_expr, end_token)?;

        if has_parentheses {
            self.expect_token(&Token::RParen)?;
        }

        let into = if self.parse_keyword(Keyword::INTO) {
            self.parse_comma_separated(Self::parse_identifier)?
        } else {
            vec![]
        };

        let using = if self.parse_keyword(Keyword::USING) {
            self.parse_comma_separated(Self::parse_expr_with_alias)?
        } else {
            vec![]
        };

        let output = self.parse_keyword(Keyword::OUTPUT);

        let default = self.parse_keyword(Keyword::DEFAULT);

        Ok(Statement::Execute {
            immediate,
            name,
            parameters,
            has_parentheses,
            into,
            using,
            output,
            default,
        })
    }

    /// Parse a SQL `PREPARE` statement
    pub fn parse_prepare(&mut self) -> Result<Statement, ParserError> {
        let name = self.parse_identifier()?;

        let mut data_types = vec![];
        if self.consume_token(&Token::LParen) {
            data_types = self.parse_comma_separated(Parser::parse_data_type)?;
            self.expect_token(&Token::RParen)?;
        }

        self.expect_keyword_is(Keyword::AS)?;
        let statement = Box::new(self.parse_statement()?);
        Ok(Statement::Prepare {
            name,
            data_types,
            statement,
        })
    }

    /// Parse a SQL `UNLOAD` statement
    pub fn parse_unload(&mut self) -> Result<Statement, ParserError> {
        self.expect_keyword(Keyword::UNLOAD)?;
        self.expect_token(&Token::LParen)?;
        let (query, query_text) =
            if matches!(self.peek_token_ref().token, Token::SingleQuotedString(_)) {
                (None, Some(self.parse_literal_string()?))
            } else {
                (Some(self.parse_query()?), None)
            };
        self.expect_token(&Token::RParen)?;

        self.expect_keyword_is(Keyword::TO)?;
        let to = self.parse_identifier()?;
        let auth = if self.parse_keyword(Keyword::IAM_ROLE) {
            Some(self.parse_iam_role_kind()?)
        } else {
            None
        };
        let with = self.parse_options(Keyword::WITH)?;
        let mut options = vec![];
        while let Some(opt) = self.maybe_parse(|parser| parser.parse_copy_legacy_option())? {
            options.push(opt);
        }
        Ok(Statement::Unload {
            query,
            query_text,
            to,
            auth,
            with,
            options,
        })
    }

    fn parse_select_into(&mut self) -> Result<SelectInto, ParserError> {
        let temporary = self
            .parse_one_of_keywords(&[Keyword::TEMP, Keyword::TEMPORARY])
            .is_some();
        let unlogged = self.parse_keyword(Keyword::UNLOGGED);
        let table = self.parse_keyword(Keyword::TABLE);
        let targets = self.parse_comma_separated(Parser::parse_expr)?;

        Ok(SelectInto {
            temporary,
            unlogged,
            table,
            targets,
        })
    }

    fn parse_pragma_value(&mut self) -> Result<ValueWithSpan, ParserError> {
        let v = self.parse_value()?;
        match &v.value {
            Value::SingleQuotedString(_) => Ok(v),
            Value::DoubleQuotedString(_) => Ok(v),
            Value::Number(_, _) => Ok(v),
            Value::Placeholder(_) => Ok(v),
            _ => {
                self.prev_token();
                self.expected_ref("number or string or ? placeholder", self.peek_token_ref())
            }
        }
    }

    /// PRAGMA [schema-name '.'] pragma-name [('=' pragma-value) | '(' pragma-value ')']
    pub fn parse_pragma(&mut self) -> Result<Statement, ParserError> {
        let name = self.parse_object_name(false)?;
        if self.consume_token(&Token::LParen) {
            let value = self.parse_pragma_value()?;
            self.expect_token(&Token::RParen)?;
            Ok(Statement::Pragma {
                name,
                value: Some(value),
                is_eq: false,
            })
        } else if self.consume_token(&Token::Eq) {
            Ok(Statement::Pragma {
                name,
                value: Some(self.parse_pragma_value()?),
                is_eq: true,
            })
        } else {
            Ok(Statement::Pragma {
                name,
                value: None,
                is_eq: false,
            })
        }
    }

    /// `INSTALL [extension_name]`
    pub fn parse_install(&mut self) -> Result<Statement, ParserError> {
        let extension_name = self.parse_identifier()?;

        Ok(Statement::Install { extension_name })
    }

    /// Parse a SQL LOAD statement
    pub fn parse_load(&mut self) -> Result<Statement, ParserError> {
        if self.dialect.supports_load_extension() {
            let extension_name = self.parse_identifier()?;
            Ok(Statement::Load { extension_name })
        } else if self.parse_keyword(Keyword::DATA) && self.dialect.supports_load_data() {
            let local = self.parse_one_of_keywords(&[Keyword::LOCAL]).is_some();
            self.expect_keyword_is(Keyword::INPATH)?;
            let inpath = self.parse_literal_string()?;
            let overwrite = self.parse_one_of_keywords(&[Keyword::OVERWRITE]).is_some();
            self.expect_keyword_is(Keyword::INTO)?;
            self.expect_keyword_is(Keyword::TABLE)?;
            let table_name = self.parse_object_name(false)?;
            let partitioned = self.parse_insert_partition()?;
            let table_format = self.parse_load_data_table_format()?;
            Ok(Statement::LoadData {
                local,
                inpath,
                overwrite,
                table_name,
                partitioned,
                table_format,
            })
        } else {
            self.expected_ref(
                "`DATA` or an extension name after `LOAD`",
                self.peek_token_ref(),
            )
        }
    }

    /// ClickHouse:
    /// ```sql
    /// OPTIMIZE TABLE [db.]name [ON CLUSTER cluster] [PARTITION partition | PARTITION ID 'partition_id'] [FINAL] [DEDUPLICATE [BY expression]]
    /// ```
    /// [ClickHouse](https://clickhouse.com/docs/en/sql-reference/statements/optimize)
    ///
    /// Databricks:
    /// ```sql
    /// OPTIMIZE table_name [WHERE predicate] [ZORDER BY (col_name1 [, ...])]
    /// ```
    /// [Databricks](https://docs.databricks.com/en/sql/language-manual/delta-optimize.html)
    pub fn parse_optimize_table(&mut self) -> Result<Statement, ParserError> {
        let has_table_keyword = self.parse_keyword(Keyword::TABLE);

        let name = self.parse_object_name(false)?;

        // ClickHouse-specific options
        let on_cluster = self.parse_optional_on_cluster()?;

        let partition = if self.parse_keyword(Keyword::PARTITION) {
            if self.parse_keyword(Keyword::ID) {
                Some(Partition::Identifier(self.parse_identifier()?))
            } else {
                Some(Partition::Expr(self.parse_expr()?))
            }
        } else {
            None
        };

        let include_final = self.parse_keyword(Keyword::FINAL);

        let deduplicate = if self.parse_keyword(Keyword::DEDUPLICATE) {
            if self.parse_keyword(Keyword::BY) {
                Some(Deduplicate::ByExpression(self.parse_expr()?))
            } else {
                Some(Deduplicate::All)
            }
        } else {
            None
        };

        // Databricks-specific options
        let predicate = if self.parse_keyword(Keyword::WHERE) {
            Some(self.parse_expr()?)
        } else {
            None
        };

        let zorder = if self.parse_keywords(&[Keyword::ZORDER, Keyword::BY]) {
            self.expect_token(&Token::LParen)?;
            let columns = self.parse_comma_separated(|p| p.parse_expr())?;
            self.expect_token(&Token::RParen)?;
            Some(columns)
        } else {
            None
        };

        Ok(Statement::OptimizeTable {
            name,
            has_table_keyword,
            on_cluster,
            partition,
            include_final,
            deduplicate,
            predicate,
            zorder,
        })
    }

    /// ```sql
    /// CREATE [ { TEMPORARY | TEMP } ] SEQUENCE [ IF NOT EXISTS ] <sequence_name>
    /// ```
    ///
    /// See [Postgres docs](https://www.postgresql.org/docs/current/sql-createsequence.html) for more details.
    pub fn parse_create_sequence(&mut self, temporary: bool) -> Result<Statement, ParserError> {
        //[ IF NOT EXISTS ]
        let if_not_exists = self.parse_keywords(&[Keyword::IF, Keyword::NOT, Keyword::EXISTS]);
        //name
        let name = self.parse_object_name(false)?;
        //[ AS data_type ]
        let mut data_type: Option<DataType> = None;
        if self.parse_keywords(&[Keyword::AS]) {
            data_type = Some(self.parse_data_type()?)
        }
        let sequence_options = self.parse_create_sequence_options()?;
        // [ OWNED BY { table_name.column_name | NONE } ]
        let owned_by = if self.parse_keywords(&[Keyword::OWNED, Keyword::BY]) {
            if self.parse_keywords(&[Keyword::NONE]) {
                Some(ObjectName::from(vec![Ident::new("NONE")]))
            } else {
                Some(self.parse_object_name(false)?)
            }
        } else {
            None
        };
        Ok(Statement::CreateSequence {
            temporary,
            if_not_exists,
            name,
            data_type,
            sequence_options,
            owned_by,
        })
    }

    fn parse_create_sequence_options(&mut self) -> Result<Vec<SequenceOptions>, ParserError> {
        let mut sequence_options = vec![];
        //[ INCREMENT [ BY ] increment ]
        if self.parse_keywords(&[Keyword::INCREMENT]) {
            if self.parse_keywords(&[Keyword::BY]) {
                sequence_options.push(SequenceOptions::IncrementBy(self.parse_number()?, true));
            } else {
                sequence_options.push(SequenceOptions::IncrementBy(self.parse_number()?, false));
            }
        }
        //[ MINVALUE minvalue | NO MINVALUE ]
        if self.parse_keyword(Keyword::MINVALUE) {
            sequence_options.push(SequenceOptions::MinValue(Some(self.parse_number()?)));
        } else if self.parse_keywords(&[Keyword::NO, Keyword::MINVALUE]) {
            sequence_options.push(SequenceOptions::MinValue(None));
        }
        //[ MAXVALUE maxvalue | NO MAXVALUE ]
        if self.parse_keywords(&[Keyword::MAXVALUE]) {
            sequence_options.push(SequenceOptions::MaxValue(Some(self.parse_number()?)));
        } else if self.parse_keywords(&[Keyword::NO, Keyword::MAXVALUE]) {
            sequence_options.push(SequenceOptions::MaxValue(None));
        }

        //[ START [ WITH ] start ]
        if self.parse_keywords(&[Keyword::START]) {
            if self.parse_keywords(&[Keyword::WITH]) {
                sequence_options.push(SequenceOptions::StartWith(self.parse_number()?, true));
            } else {
                sequence_options.push(SequenceOptions::StartWith(self.parse_number()?, false));
            }
        }
        //[ CACHE cache ]
        if self.parse_keywords(&[Keyword::CACHE]) {
            sequence_options.push(SequenceOptions::Cache(self.parse_number()?));
        }
        // [ [ NO ] CYCLE ]
        if self.parse_keywords(&[Keyword::NO, Keyword::CYCLE]) {
            sequence_options.push(SequenceOptions::Cycle(true));
        } else if self.parse_keywords(&[Keyword::CYCLE]) {
            sequence_options.push(SequenceOptions::Cycle(false));
        }

        Ok(sequence_options)
    }

    ///   Parse a `CREATE SERVER` statement.
    ///
    ///  See [Statement::CreateServer]
    pub fn parse_pg_create_server(&mut self) -> Result<Statement, ParserError> {
        let ine = self.parse_keywords(&[Keyword::IF, Keyword::NOT, Keyword::EXISTS]);
        let name = self.parse_object_name(false)?;

        let server_type = if self.parse_keyword(Keyword::TYPE) {
            Some(self.parse_identifier()?)
        } else {
            None
        };

        let version = if self.parse_keyword(Keyword::VERSION) {
            Some(self.parse_identifier()?)
        } else {
            None
        };

        self.expect_keywords(&[Keyword::FOREIGN, Keyword::DATA, Keyword::WRAPPER])?;
        let foreign_data_wrapper = self.parse_object_name(false)?;

        let options = self.parse_pg_options_clause()?;

        Ok(Statement::CreateServer(CreateServerStatement {
            name,
            if_not_exists: ine,
            server_type,
            version,
            foreign_data_wrapper,
            options,
        }))
    }

    /// Parse an optional Postgres `OPTIONS ( key value [, ...] )` clause.
    fn parse_pg_options_clause(&mut self) -> Result<Option<Vec<CreateServerOption>>, ParserError> {
        if !self.parse_keyword(Keyword::OPTIONS) {
            return Ok(None);
        }
        self.expect_token(&Token::LParen)?;
        let options = self.parse_comma_separated(|p| {
            let key = p.parse_identifier()?;
            let value = p.parse_identifier()?;
            Ok(CreateServerOption { key, value })
        })?;
        self.expect_token(&Token::RParen)?;
        Ok(Some(options))
    }

    /// Parse a `CREATE FOREIGN TABLE` statement.
    ///
    /// Per-column `OPTIONS ( ... )`, `INHERITS`, and the `PARTITION OF` form are
    /// not parsed yet.
    ///
    /// See <https://www.postgresql.org/docs/current/sql-createforeigntable.html>
    pub fn parse_create_foreign_table(&mut self) -> Result<CreateForeignTable, ParserError> {
        let if_not_exists = self.parse_keywords(&[Keyword::IF, Keyword::NOT, Keyword::EXISTS]);
        let name = self.parse_object_name(false)?;
        if self.peek_token_ref().token != Token::LParen {
            return self.expected_ref(
                "'(' before the column list of CREATE FOREIGN TABLE",
                self.peek_token_ref(),
            );
        }
        let (columns, constraints) = self.parse_columns()?;
        self.expect_keyword_is(Keyword::SERVER)?;
        let server_name = self.parse_identifier()?;
        let options = self.parse_pg_options_clause()?;

        Ok(CreateForeignTable {
            name,
            if_not_exists,
            columns,
            constraints,
            server_name,
            options,
        })
    }

    /// The index of the first unprocessed token.
    pub fn index(&self) -> usize {
        self.index
    }

    /// Parse a named window definition.
    pub fn parse_named_window(&mut self) -> Result<NamedWindowDefinition, ParserError> {
        let ident = self.parse_identifier()?;
        self.expect_keyword_is(Keyword::AS)?;

        let window_expr = if self.consume_token(&Token::LParen) {
            NamedWindowExpr::WindowSpec(self.parse_window_spec()?)
        } else if self.dialect.supports_window_clause_named_window_reference() {
            NamedWindowExpr::NamedWindow(self.parse_identifier()?)
        } else {
            return self.expected_ref("(", self.peek_token_ref());
        };

        Ok(NamedWindowDefinition(ident, window_expr))
    }

    /// Parse `CREATE PROCEDURE` statement.
    pub fn parse_create_procedure(&mut self, or_alter: bool) -> Result<Statement, ParserError> {
        let name = self.parse_object_name(false)?;
        let params = self.parse_optional_procedure_parameters()?;

        let language = if self.parse_keyword(Keyword::LANGUAGE) {
            Some(self.parse_identifier()?)
        } else {
            None
        };

        self.expect_keyword_is(Keyword::AS)?;

        let body = self.parse_conditional_statements(&[Keyword::END])?;

        Ok(Statement::CreateProcedure {
            name,
            or_alter,
            params,
            language,
            body,
        })
    }

    /// Parse a window specification.
    pub fn parse_window_spec(&mut self) -> Result<WindowSpec, ParserError> {
        let window_name = match &self.peek_token_ref().token {
            Token::Word(word) if word.keyword == Keyword::NoKeyword => {
                self.parse_optional_ident()?
            }
            _ => None,
        };

        let partition_by = if self.parse_keywords(&[Keyword::PARTITION, Keyword::BY]) {
            self.parse_comma_separated(Parser::parse_expr)?
        } else {
            vec![]
        };
        let order_by = if self.parse_keywords(&[Keyword::ORDER, Keyword::BY]) {
            self.parse_comma_separated(Parser::parse_order_by_expr)?
        } else {
            vec![]
        };

        let window_frame = if !self.consume_token(&Token::RParen) {
            let window_frame = self.parse_window_frame()?;
            self.expect_token(&Token::RParen)?;
            Some(window_frame)
        } else {
            None
        };
        Ok(WindowSpec {
            window_name,
            partition_by,
            order_by,
            window_frame,
        })
    }

    /// Parse `CREATE TYPE` statement.
    pub fn parse_create_type(&mut self) -> Result<Statement, ParserError> {
        let name = self.parse_object_name(false)?;

        // Check if we have AS keyword
        let has_as = self.parse_keyword(Keyword::AS);

        if !has_as {
            // Two cases: CREATE TYPE name; or CREATE TYPE name (options);
            if self.consume_token(&Token::LParen) {
                // CREATE TYPE name (options) - SQL definition without AS
                let options = self.parse_create_type_sql_definition_options()?;
                self.expect_token(&Token::RParen)?;
                return Ok(Statement::CreateType {
                    name,
                    representation: Some(UserDefinedTypeRepresentation::SqlDefinition { options }),
                });
            }

            // CREATE TYPE name; - no representation
            return Ok(Statement::CreateType {
                name,
                representation: None,
            });
        }

        // We have AS keyword
        if self.parse_keyword(Keyword::ENUM) {
            // CREATE TYPE name AS ENUM (labels)
            self.parse_create_type_enum(name)
        } else if self.parse_keyword(Keyword::RANGE) {
            // CREATE TYPE name AS RANGE (options)
            self.parse_create_type_range(name)
        } else if self.consume_token(&Token::LParen) {
            // CREATE TYPE name AS (attributes) - Composite
            self.parse_create_type_composite(name)
        } else {
            self.expected_ref("ENUM, RANGE, or '(' after AS", self.peek_token_ref())
        }
    }

    /// Parse remainder of `CREATE TYPE AS (attributes)` statement (composite type)
    ///
    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-createtype.html)
    fn parse_create_type_composite(&mut self, name: ObjectName) -> Result<Statement, ParserError> {
        if self.consume_token(&Token::RParen) {
            // Empty composite type
            return Ok(Statement::CreateType {
                name,
                representation: Some(UserDefinedTypeRepresentation::Composite {
                    attributes: vec![],
                }),
            });
        }

        let mut attributes = vec![];
        loop {
            let attr_name = self.parse_identifier()?;
            let attr_data_type = self.parse_data_type()?;
            let attr_collation = if self.parse_keyword(Keyword::COLLATE) {
                Some(self.parse_object_name(false)?)
            } else {
                None
            };
            attributes.push(UserDefinedTypeCompositeAttributeDef {
                name: attr_name,
                data_type: attr_data_type,
                collation: attr_collation,
            });

            if !self.consume_token(&Token::Comma) {
                break;
            }
        }
        self.expect_token(&Token::RParen)?;

        Ok(Statement::CreateType {
            name,
            representation: Some(UserDefinedTypeRepresentation::Composite { attributes }),
        })
    }

    /// Parse remainder of `CREATE TYPE AS ENUM` statement (see [Statement::CreateType] and [Self::parse_create_type])
    ///
    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-createtype.html)
    pub fn parse_create_type_enum(&mut self, name: ObjectName) -> Result<Statement, ParserError> {
        self.expect_token(&Token::LParen)?;
        let labels = self.parse_comma_separated0(|p| p.parse_identifier(), Token::RParen)?;
        self.expect_token(&Token::RParen)?;

        Ok(Statement::CreateType {
            name,
            representation: Some(UserDefinedTypeRepresentation::Enum { labels }),
        })
    }

    /// Parse remainder of `CREATE TYPE AS RANGE` statement
    ///
    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-createtype.html)
    fn parse_create_type_range(&mut self, name: ObjectName) -> Result<Statement, ParserError> {
        self.expect_token(&Token::LParen)?;
        let options = self.parse_comma_separated0(|p| p.parse_range_option(), Token::RParen)?;
        self.expect_token(&Token::RParen)?;

        Ok(Statement::CreateType {
            name,
            representation: Some(UserDefinedTypeRepresentation::Range { options }),
        })
    }

    /// Parse a single range option for a `CREATE TYPE AS RANGE` statement
    fn parse_range_option(&mut self) -> Result<UserDefinedTypeRangeOption, ParserError> {
        let keyword = self.parse_one_of_keywords(&[
            Keyword::SUBTYPE,
            Keyword::SUBTYPE_OPCLASS,
            Keyword::COLLATION,
            Keyword::CANONICAL,
            Keyword::SUBTYPE_DIFF,
            Keyword::MULTIRANGE_TYPE_NAME,
        ]);

        match keyword {
            Some(Keyword::SUBTYPE) => {
                self.expect_token(&Token::Eq)?;
                let data_type = self.parse_data_type()?;
                Ok(UserDefinedTypeRangeOption::Subtype(data_type))
            }
            Some(Keyword::SUBTYPE_OPCLASS) => {
                self.expect_token(&Token::Eq)?;
                let name = self.parse_object_name(false)?;
                Ok(UserDefinedTypeRangeOption::SubtypeOpClass(name))
            }
            Some(Keyword::COLLATION) => {
                self.expect_token(&Token::Eq)?;
                let name = self.parse_object_name(false)?;
                Ok(UserDefinedTypeRangeOption::Collation(name))
            }
            Some(Keyword::CANONICAL) => {
                self.expect_token(&Token::Eq)?;
                let name = self.parse_object_name(false)?;
                Ok(UserDefinedTypeRangeOption::Canonical(name))
            }
            Some(Keyword::SUBTYPE_DIFF) => {
                self.expect_token(&Token::Eq)?;
                let name = self.parse_object_name(false)?;
                Ok(UserDefinedTypeRangeOption::SubtypeDiff(name))
            }
            Some(Keyword::MULTIRANGE_TYPE_NAME) => {
                self.expect_token(&Token::Eq)?;
                let name = self.parse_object_name(false)?;
                Ok(UserDefinedTypeRangeOption::MultirangeTypeName(name))
            }
            _ => self.expected_ref("range option keyword", self.peek_token_ref()),
        }
    }

    /// Parse SQL definition options for CREATE TYPE (options)
    fn parse_create_type_sql_definition_options(
        &mut self,
    ) -> Result<Vec<UserDefinedTypeSqlDefinitionOption>, ParserError> {
        self.parse_comma_separated0(|p| p.parse_sql_definition_option(), Token::RParen)
    }

    /// Parse a single SQL definition option for CREATE TYPE (options)
    fn parse_sql_definition_option(
        &mut self,
    ) -> Result<UserDefinedTypeSqlDefinitionOption, ParserError> {
        let keyword = self.parse_one_of_keywords(&[
            Keyword::INPUT,
            Keyword::OUTPUT,
            Keyword::RECEIVE,
            Keyword::SEND,
            Keyword::TYPMOD_IN,
            Keyword::TYPMOD_OUT,
            Keyword::ANALYZE,
            Keyword::SUBSCRIPT,
            Keyword::INTERNALLENGTH,
            Keyword::PASSEDBYVALUE,
            Keyword::ALIGNMENT,
            Keyword::STORAGE,
            Keyword::LIKE,
            Keyword::CATEGORY,
            Keyword::PREFERRED,
            Keyword::DEFAULT,
            Keyword::ELEMENT,
            Keyword::DELIMITER,
            Keyword::COLLATABLE,
        ]);

        match keyword {
            Some(Keyword::INPUT) => {
                self.expect_token(&Token::Eq)?;
                let name = self.parse_object_name(false)?;
                Ok(UserDefinedTypeSqlDefinitionOption::Input(name))
            }
            Some(Keyword::OUTPUT) => {
                self.expect_token(&Token::Eq)?;
                let name = self.parse_object_name(false)?;
                Ok(UserDefinedTypeSqlDefinitionOption::Output(name))
            }
            Some(Keyword::RECEIVE) => {
                self.expect_token(&Token::Eq)?;
                let name = self.parse_object_name(false)?;
                Ok(UserDefinedTypeSqlDefinitionOption::Receive(name))
            }
            Some(Keyword::SEND) => {
                self.expect_token(&Token::Eq)?;
                let name = self.parse_object_name(false)?;
                Ok(UserDefinedTypeSqlDefinitionOption::Send(name))
            }
            Some(Keyword::TYPMOD_IN) => {
                self.expect_token(&Token::Eq)?;
                let name = self.parse_object_name(false)?;
                Ok(UserDefinedTypeSqlDefinitionOption::TypmodIn(name))
            }
            Some(Keyword::TYPMOD_OUT) => {
                self.expect_token(&Token::Eq)?;
                let name = self.parse_object_name(false)?;
                Ok(UserDefinedTypeSqlDefinitionOption::TypmodOut(name))
            }
            Some(Keyword::ANALYZE) => {
                self.expect_token(&Token::Eq)?;
                let name = self.parse_object_name(false)?;
                Ok(UserDefinedTypeSqlDefinitionOption::Analyze(name))
            }
            Some(Keyword::SUBSCRIPT) => {
                self.expect_token(&Token::Eq)?;
                let name = self.parse_object_name(false)?;
                Ok(UserDefinedTypeSqlDefinitionOption::Subscript(name))
            }
            Some(Keyword::INTERNALLENGTH) => {
                self.expect_token(&Token::Eq)?;
                if self.parse_keyword(Keyword::VARIABLE) {
                    Ok(UserDefinedTypeSqlDefinitionOption::InternalLength(
                        UserDefinedTypeInternalLength::Variable,
                    ))
                } else {
                    let value = self.parse_literal_uint()?;
                    Ok(UserDefinedTypeSqlDefinitionOption::InternalLength(
                        UserDefinedTypeInternalLength::Fixed(value),
                    ))
                }
            }
            Some(Keyword::PASSEDBYVALUE) => Ok(UserDefinedTypeSqlDefinitionOption::PassedByValue),
            Some(Keyword::ALIGNMENT) => {
                self.expect_token(&Token::Eq)?;
                let align_keyword = self.parse_one_of_keywords(&[
                    Keyword::CHAR,
                    Keyword::INT2,
                    Keyword::INT4,
                    Keyword::DOUBLE,
                ]);
                match align_keyword {
                    Some(Keyword::CHAR) => Ok(UserDefinedTypeSqlDefinitionOption::Alignment(
                        Alignment::Char,
                    )),
                    Some(Keyword::INT2) => Ok(UserDefinedTypeSqlDefinitionOption::Alignment(
                        Alignment::Int2,
                    )),
                    Some(Keyword::INT4) => Ok(UserDefinedTypeSqlDefinitionOption::Alignment(
                        Alignment::Int4,
                    )),
                    Some(Keyword::DOUBLE) => Ok(UserDefinedTypeSqlDefinitionOption::Alignment(
                        Alignment::Double,
                    )),
                    _ => self.expected_ref(
                        "alignment value (char, int2, int4, or double)",
                        self.peek_token_ref(),
                    ),
                }
            }
            Some(Keyword::STORAGE) => {
                self.expect_token(&Token::Eq)?;
                let storage_keyword = self.parse_one_of_keywords(&[
                    Keyword::PLAIN,
                    Keyword::EXTERNAL,
                    Keyword::EXTENDED,
                    Keyword::MAIN,
                ]);
                match storage_keyword {
                    Some(Keyword::PLAIN) => Ok(UserDefinedTypeSqlDefinitionOption::Storage(
                        UserDefinedTypeStorage::Plain,
                    )),
                    Some(Keyword::EXTERNAL) => Ok(UserDefinedTypeSqlDefinitionOption::Storage(
                        UserDefinedTypeStorage::External,
                    )),
                    Some(Keyword::EXTENDED) => Ok(UserDefinedTypeSqlDefinitionOption::Storage(
                        UserDefinedTypeStorage::Extended,
                    )),
                    Some(Keyword::MAIN) => Ok(UserDefinedTypeSqlDefinitionOption::Storage(
                        UserDefinedTypeStorage::Main,
                    )),
                    _ => self.expected_ref(
                        "storage value (plain, external, extended, or main)",
                        self.peek_token_ref(),
                    ),
                }
            }
            Some(Keyword::LIKE) => {
                self.expect_token(&Token::Eq)?;
                let name = self.parse_object_name(false)?;
                Ok(UserDefinedTypeSqlDefinitionOption::Like(name))
            }
            Some(Keyword::CATEGORY) => {
                self.expect_token(&Token::Eq)?;
                let category_str = self.parse_literal_string()?;
                let category_char = category_str.chars().next().ok_or_else(|| {
                    ParserError::ParserError(
                        "CATEGORY value must be a single character".to_string(),
                    )
                })?;
                Ok(UserDefinedTypeSqlDefinitionOption::Category(category_char))
            }
            Some(Keyword::PREFERRED) => {
                self.expect_token(&Token::Eq)?;
                let value =
                    self.parse_keyword(Keyword::TRUE) || !self.parse_keyword(Keyword::FALSE);
                Ok(UserDefinedTypeSqlDefinitionOption::Preferred(value))
            }
            Some(Keyword::DEFAULT) => {
                self.expect_token(&Token::Eq)?;
                let expr = self.parse_expr()?;
                Ok(UserDefinedTypeSqlDefinitionOption::Default(expr))
            }
            Some(Keyword::ELEMENT) => {
                self.expect_token(&Token::Eq)?;
                let data_type = self.parse_data_type()?;
                Ok(UserDefinedTypeSqlDefinitionOption::Element(data_type))
            }
            Some(Keyword::DELIMITER) => {
                self.expect_token(&Token::Eq)?;
                let delimiter = self.parse_literal_string()?;
                Ok(UserDefinedTypeSqlDefinitionOption::Delimiter(delimiter))
            }
            Some(Keyword::COLLATABLE) => {
                self.expect_token(&Token::Eq)?;
                let value =
                    self.parse_keyword(Keyword::TRUE) || !self.parse_keyword(Keyword::FALSE);
                Ok(UserDefinedTypeSqlDefinitionOption::Collatable(value))
            }
            _ => self.expected_ref("SQL definition option keyword", self.peek_token_ref()),
        }
    }

    fn parse_parenthesized_identifiers(&mut self) -> Result<Vec<Ident>, ParserError> {
        self.expect_token(&Token::LParen)?;
        let idents = self.parse_comma_separated0(|p| p.parse_identifier(), Token::RParen)?;
        self.expect_token(&Token::RParen)?;
        Ok(idents)
    }

    fn parse_column_position(&mut self) -> Result<Option<MySQLColumnPosition>, ParserError> {
        if self.dialect.supports_alter_column_position() {
            if self.parse_keyword(Keyword::FIRST) {
                Ok(Some(MySQLColumnPosition::First))
            } else if self.parse_keyword(Keyword::AFTER) {
                let ident = self.parse_identifier()?;
                Ok(Some(MySQLColumnPosition::After(ident)))
            } else {
                Ok(None)
            }
        } else {
            Ok(None)
        }
    }

    /// Parse [Statement::Print]
    fn parse_print(&mut self) -> Result<Statement, ParserError> {
        Ok(Statement::Print(PrintStatement {
            message: Box::new(self.parse_expr()?),
        }))
    }

    /// Parse [Statement::WaitFor]
    ///
    /// See: <https://learn.microsoft.com/en-us/sql/t-sql/language-elements/waitfor-transact-sql>
    fn parse_waitfor(&mut self) -> Result<Statement, ParserError> {
        let wait_type = if self.parse_keyword(Keyword::DELAY) {
            WaitForType::Delay
        } else if self.parse_keyword(Keyword::TIME) {
            WaitForType::Time
        } else {
            return self.expected_ref("DELAY or TIME", self.peek_token_ref());
        };
        let expr = self.parse_expr()?;
        Ok(Statement::WaitFor(WaitForStatement { wait_type, expr }))
    }

    /// Parse [Statement::Return]
    fn parse_return(&mut self) -> Result<Statement, ParserError> {
        match self.maybe_parse(|p| p.parse_expr())? {
            Some(expr) => Ok(Statement::Return(ReturnStatement {
                value: Some(ReturnStatementValue::Expr(expr)),
            })),
            None => Ok(Statement::Return(ReturnStatement { value: None })),
        }
    }

    /// /// Parse a `EXPORT DATA` statement.
    ///
    /// See [Statement::ExportData]
    fn parse_export_data(&mut self) -> Result<Statement, ParserError> {
        self.expect_keywords(&[Keyword::EXPORT, Keyword::DATA])?;

        let connection = if self.parse_keywords(&[Keyword::WITH, Keyword::CONNECTION]) {
            Some(self.parse_object_name(false)?)
        } else {
            None
        };
        self.expect_keyword(Keyword::OPTIONS)?;
        self.expect_token(&Token::LParen)?;
        let options = self.parse_comma_separated(|p| p.parse_sql_option())?;
        self.expect_token(&Token::RParen)?;
        self.expect_keyword(Keyword::AS)?;
        let query = self.parse_query()?;
        Ok(Statement::ExportData(ExportData {
            options,
            query,
            connection,
        }))
    }

    fn parse_vacuum(&mut self) -> Result<Statement, ParserError> {
        self.expect_keyword(Keyword::VACUUM)?;
        let full = self.parse_keyword(Keyword::FULL);
        let sort_only = self.parse_keywords(&[Keyword::SORT, Keyword::ONLY]);
        let delete_only = self.parse_keywords(&[Keyword::DELETE, Keyword::ONLY]);
        let reindex = self.parse_keyword(Keyword::REINDEX);
        let recluster = self.parse_keyword(Keyword::RECLUSTER);
        let (table_name, threshold, boost) =
            match self.maybe_parse(|p| p.parse_object_name(false))? {
                Some(table_name) => {
                    let threshold = if self.parse_keyword(Keyword::TO) {
                        let value = self.parse_value()?;
                        self.expect_keyword(Keyword::PERCENT)?;
                        Some(value)
                    } else {
                        None
                    };
                    let boost = self.parse_keyword(Keyword::BOOST);
                    (Some(table_name), threshold, boost)
                }
                _ => (None, None, false),
            };
        Ok(Statement::Vacuum(VacuumStatement {
            full,
            sort_only,
            delete_only,
            reindex,
            recluster,
            table_name,
            threshold,
            boost,
        }))
    }

    /// Consume the parser and return its underlying token buffer
    pub fn into_tokens(self) -> Vec<TokenWithSpan> {
        self.tokens
    }

    /// Returns true if the next keyword indicates a sub query, i.e. SELECT or WITH
    fn peek_sub_query(&mut self) -> bool {
        self.peek_one_of_keywords(&[Keyword::SELECT, Keyword::WITH])
            .is_some()
    }

    pub(crate) fn parse_show_stmt_options(&mut self) -> Result<ShowStatementOptions, ParserError> {
        let show_in;
        let mut filter_position = None;
        if self.dialect.supports_show_like_before_in() {
            if let Some(filter) = self.parse_show_statement_filter()? {
                filter_position = Some(ShowStatementFilterPosition::Infix(filter));
            }
            show_in = self.maybe_parse_show_stmt_in()?;
        } else {
            show_in = self.maybe_parse_show_stmt_in()?;
            if let Some(filter) = self.parse_show_statement_filter()? {
                filter_position = Some(ShowStatementFilterPosition::Suffix(filter));
            }
        }
        let starts_with = self.maybe_parse_show_stmt_starts_with()?;
        let limit = self.maybe_parse_show_stmt_limit()?;
        let from = self.maybe_parse_show_stmt_from()?;
        Ok(ShowStatementOptions {
            filter_position,
            show_in,
            starts_with,
            limit,
            limit_from: from,
        })
    }

    fn maybe_parse_show_stmt_in(&mut self) -> Result<Option<ShowStatementIn>, ParserError> {
        let clause = match self.parse_one_of_keywords(&[Keyword::FROM, Keyword::IN]) {
            Some(Keyword::FROM) => ShowStatementInClause::FROM,
            Some(Keyword::IN) => ShowStatementInClause::IN,
            None => return Ok(None),
            _ => return self.expected_ref("FROM or IN", self.peek_token_ref()),
        };

        let (parent_type, parent_name) = match self.parse_one_of_keywords(&[
            Keyword::ACCOUNT,
            Keyword::DATABASE,
            Keyword::SCHEMA,
            Keyword::TABLE,
            Keyword::VIEW,
        ]) {
            // If we see these next keywords it means we don't have a parent name
            Some(Keyword::DATABASE)
                if self.peek_keywords(&[Keyword::STARTS, Keyword::WITH])
                    | self.peek_keyword(Keyword::LIMIT) =>
            {
                (Some(ShowStatementInParentType::Database), None)
            }
            Some(Keyword::SCHEMA)
                if self.peek_keywords(&[Keyword::STARTS, Keyword::WITH])
                    | self.peek_keyword(Keyword::LIMIT) =>
            {
                (Some(ShowStatementInParentType::Schema), None)
            }
            Some(parent_kw) => {
                // The parent name here is still optional, for example:
                // SHOW TABLES IN ACCOUNT, so parsing the object name
                // may fail because the statement ends.
                let parent_name = self.maybe_parse(|p| p.parse_object_name(false))?;
                match parent_kw {
                    Keyword::ACCOUNT => (Some(ShowStatementInParentType::Account), parent_name),
                    Keyword::DATABASE => (Some(ShowStatementInParentType::Database), parent_name),
                    Keyword::SCHEMA => (Some(ShowStatementInParentType::Schema), parent_name),
                    Keyword::TABLE => (Some(ShowStatementInParentType::Table), parent_name),
                    Keyword::VIEW => (Some(ShowStatementInParentType::View), parent_name),
                    _ => {
                        return self.expected_ref(
                            "one of ACCOUNT, DATABASE, SCHEMA, TABLE or VIEW",
                            self.peek_token_ref(),
                        )
                    }
                }
            }
            None => {
                // Parsing MySQL style FROM tbl_name FROM db_name
                // which is equivalent to FROM tbl_name.db_name
                let mut parent_name = self.parse_object_name(false)?;
                if self
                    .parse_one_of_keywords(&[Keyword::FROM, Keyword::IN])
                    .is_some()
                {
                    parent_name
                        .0
                        .insert(0, ObjectNamePart::Identifier(self.parse_identifier()?));
                }
                (None, Some(parent_name))
            }
        };

        Ok(Some(ShowStatementIn {
            clause,
            parent_type,
            parent_name,
        }))
    }

    fn maybe_parse_show_stmt_starts_with(&mut self) -> Result<Option<ValueWithSpan>, ParserError> {
        if self.parse_keywords(&[Keyword::STARTS, Keyword::WITH]) {
            Ok(Some(self.parse_value()?))
        } else {
            Ok(None)
        }
    }

    fn maybe_parse_show_stmt_limit(&mut self) -> Result<Option<Expr>, ParserError> {
        if self.parse_keyword(Keyword::LIMIT) {
            Ok(self.parse_limit()?)
        } else {
            Ok(None)
        }
    }

    fn maybe_parse_show_stmt_from(&mut self) -> Result<Option<ValueWithSpan>, ParserError> {
        if self.parse_keyword(Keyword::FROM) {
            Ok(Some(self.parse_value()?))
        } else {
            Ok(None)
        }
    }

    pub(crate) fn in_column_definition_state(&self) -> bool {
        matches!(self.state, ColumnDefinition)
    }

    /// Parses options provided in key-value format.
    ///
    /// * `parenthesized` - true if the options are enclosed in parenthesis
    /// * `end_words` - a list of keywords that any of them indicates the end of the options section
    pub(crate) fn parse_key_value_options(
        &mut self,
        parenthesized: bool,
        end_words: &[Keyword],
    ) -> Result<KeyValueOptions, ParserError> {
        let mut options: Vec<KeyValueOption> = Vec::new();
        let mut delimiter = KeyValueOptionsDelimiter::Space;
        if parenthesized {
            self.expect_token(&Token::LParen)?;
        }
        loop {
            match self.next_token().token {
                Token::RParen => {
                    if parenthesized {
                        break;
                    } else {
                        return self.expected_ref(" another option or EOF", self.peek_token_ref());
                    }
                }
                Token::EOF => break,
                Token::SemiColon => {
                    self.prev_token();
                    break;
                }
                Token::Comma => {
                    delimiter = KeyValueOptionsDelimiter::Comma;
                    continue;
                }
                Token::Word(w) if !end_words.contains(&w.keyword) => {
                    options.push(self.parse_key_value_option(&w)?)
                }
                Token::Word(w) if end_words.contains(&w.keyword) => {
                    self.prev_token();
                    break;
                }
                _ => {
                    return self.expected_ref(
                        "another option, EOF, SemiColon, Comma or ')'",
                        self.peek_token_ref(),
                    )
                }
            };
        }

        Ok(KeyValueOptions { delimiter, options })
    }

    /// Parses a `KEY = VALUE` construct based on the specified key
    pub(crate) fn parse_key_value_option(
        &mut self,
        key: &Word,
    ) -> Result<KeyValueOption, ParserError> {
        self.expect_token(&Token::Eq)?;
        let peeked_token = self.peek_token();
        match peeked_token.token {
            Token::SingleQuotedString(_) => Ok(KeyValueOption {
                option_name: key.value.clone(),
                option_value: KeyValueOptionKind::Single(self.parse_value()?),
            }),
            Token::Word(word)
                if word.keyword == Keyword::TRUE || word.keyword == Keyword::FALSE =>
            {
                Ok(KeyValueOption {
                    option_name: key.value.clone(),
                    option_value: KeyValueOptionKind::Single(self.parse_value()?),
                })
            }
            Token::Number(..) => Ok(KeyValueOption {
                option_name: key.value.clone(),
                option_value: KeyValueOptionKind::Single(self.parse_value()?),
            }),
            Token::Word(word) => {
                self.next_token();
                Ok(KeyValueOption {
                    option_name: key.value.clone(),
                    option_value: KeyValueOptionKind::Single(
                        Value::Placeholder(word.value.clone()).with_span(peeked_token.span),
                    ),
                })
            }
            Token::LParen => {
                // Can be a list of values or a list of key value properties.
                // Try to parse a list of values and if that fails, try to parse
                // a list of key-value properties.
                match self.maybe_parse(|parser| {
                    parser.expect_token(&Token::LParen)?;
                    let values = parser.parse_comma_separated0(|p| p.parse_value(), Token::RParen);
                    parser.expect_token(&Token::RParen)?;
                    values
                })? {
                    Some(values) => Ok(KeyValueOption {
                        option_name: key.value.clone(),
                        option_value: KeyValueOptionKind::Multi(values),
                    }),
                    None => Ok(KeyValueOption {
                        option_name: key.value.clone(),
                        option_value: KeyValueOptionKind::KeyValueOptions(Box::new(
                            self.parse_key_value_options(true, &[])?,
                        )),
                    }),
                }
            }
            _ => self.expected_ref("expected option value", self.peek_token_ref()),
        }
    }

    /// Parses a RESET statement
    fn parse_reset(&mut self) -> Result<ResetStatement, ParserError> {
        if self.parse_keyword(Keyword::ALL) {
            return Ok(ResetStatement { reset: Reset::ALL });
        }

        if self.parse_keywords(&[Keyword::SESSION, Keyword::AUTHORIZATION]) {
            return Ok(ResetStatement {
                reset: Reset::SessionAuthorization,
            });
        }

        let obj = self.parse_object_name(false)?;
        Ok(ResetStatement {
            reset: Reset::ConfigurationParameter(obj),
        })
    }
}

fn maybe_prefixed_expr(expr: Expr, prefix: Option<Ident>) -> Expr {
    if let Some(prefix) = prefix {
        Expr::Prefixed {
            prefix,
            value: Box::new(expr),
        }
    } else {
        expr
    }
}

impl Word {
    /// Convert a reference to this word into an [`Ident`] by cloning the value.
    ///
    /// Use this method when you need to keep the original `Word` around.
    /// If you can consume the `Word`, prefer [`into_ident`](Self::into_ident) instead
    /// to avoid cloning.
    #[inline]
    pub fn to_ident(&self, span: Span) -> Ident {
        Ident {
            value: self.value.clone(),
            quote_style: self.quote_style,
            span,
        }
    }

    /// Convert this word into an [`Ident`] identifier, consuming the `Word`.
    ///
    /// This avoids cloning the string value. If you need to keep the original
    /// `Word`, use [`to_ident`](Self::to_ident) instead.
    pub fn into_ident(self, span: Span) -> Ident {
        Ident {
            value: self.value,
            quote_style: self.quote_style,
            span,
        }
    }
}

#[cfg(test)]
mod tests {
    use crate::test_utils::{all_dialects, TestedDialects};

    use super::*;

    #[test]
    fn test_prev_index() {
        let sql = "SELECT version";
        all_dialects().run_parser_method(sql, |parser| {
            assert_eq!(parser.peek_token(), Token::make_keyword("SELECT"));
            assert_eq!(parser.next_token(), Token::make_keyword("SELECT"));
            parser.prev_token();
            assert_eq!(parser.next_token(), Token::make_keyword("SELECT"));
            assert_eq!(parser.next_token(), Token::make_word("version", None));
            parser.prev_token();
            assert_eq!(parser.peek_token(), Token::make_word("version", None));
            assert_eq!(parser.next_token(), Token::make_word("version", None));
            assert_eq!(parser.peek_token(), Token::EOF);
            parser.prev_token();
            assert_eq!(parser.next_token(), Token::make_word("version", None));
            assert_eq!(parser.next_token(), Token::EOF);
            assert_eq!(parser.next_token(), Token::EOF);
            parser.prev_token();
        });
    }

    #[test]
    fn test_peek_tokens() {
        all_dialects().run_parser_method("SELECT foo AS bar FROM baz", |parser| {
            assert!(matches!(
                parser.peek_tokens(),
                [Token::Word(Word {
                    keyword: Keyword::SELECT,
                    ..
                })]
            ));

            assert!(matches!(
                parser.peek_tokens(),
                [
                    Token::Word(Word {
                        keyword: Keyword::SELECT,
                        ..
                    }),
                    Token::Word(_),
                    Token::Word(Word {
                        keyword: Keyword::AS,
                        ..
                    }),
                ]
            ));

            for _ in 0..4 {
                parser.next_token();
            }

            assert!(matches!(
                parser.peek_tokens(),
                [
                    Token::Word(Word {
                        keyword: Keyword::FROM,
                        ..
                    }),
                    Token::Word(_),
                    Token::EOF,
                    Token::EOF,
                ]
            ))
        })
    }

    #[cfg(test)]
    mod test_parse_data_type {
        use crate::ast::{
            CharLengthUnits, CharacterLength, DataType, ExactNumberInfo, ObjectName, TimezoneInfo,
        };
        use crate::dialect::{AnsiDialect, GenericDialect, PostgreSqlDialect};
        use crate::test_utils::TestedDialects;

        macro_rules! test_parse_data_type {
            ($dialect:expr, $input:expr, $expected_type:expr $(,)?) => {{
                $dialect.run_parser_method(&*$input, |parser| {
                    let data_type = parser.parse_data_type().unwrap();
                    assert_eq!($expected_type, data_type);
                    assert_eq!($input.to_string(), data_type.to_string());
                });
            }};
        }

        #[test]
        fn test_ansii_character_string_types() {
            // Character string types: <https://jakewheat.github.io/sql-overview/sql-2016-foundation-grammar.html#character-string-type>
            let dialect =
                TestedDialects::new(vec![Box::new(GenericDialect {}), Box::new(AnsiDialect {})]);

            test_parse_data_type!(dialect, "CHARACTER", DataType::Character(None));

            test_parse_data_type!(
                dialect,
                "CHARACTER(20)",
                DataType::Character(Some(CharacterLength::IntegerLength {
                    length: 20,
                    unit: None
                }))
            );

            test_parse_data_type!(
                dialect,
                "CHARACTER(20 CHARACTERS)",
                DataType::Character(Some(CharacterLength::IntegerLength {
                    length: 20,
                    unit: Some(CharLengthUnits::Characters)
                }))
            );

            test_parse_data_type!(
                dialect,
                "CHARACTER(20 OCTETS)",
                DataType::Character(Some(CharacterLength::IntegerLength {
                    length: 20,
                    unit: Some(CharLengthUnits::Octets)
                }))
            );

            test_parse_data_type!(dialect, "CHAR", DataType::Char(None));

            test_parse_data_type!(
                dialect,
                "CHAR(20)",
                DataType::Char(Some(CharacterLength::IntegerLength {
                    length: 20,
                    unit: None
                }))
            );

            test_parse_data_type!(
                dialect,
                "CHAR(20 CHARACTERS)",
                DataType::Char(Some(CharacterLength::IntegerLength {
                    length: 20,
                    unit: Some(CharLengthUnits::Characters)
                }))
            );

            test_parse_data_type!(
                dialect,
                "CHAR(20 OCTETS)",
                DataType::Char(Some(CharacterLength::IntegerLength {
                    length: 20,
                    unit: Some(CharLengthUnits::Octets)
                }))
            );

            test_parse_data_type!(
                dialect,
                "CHARACTER VARYING(20)",
                DataType::CharacterVarying(Some(CharacterLength::IntegerLength {
                    length: 20,
                    unit: None
                }))
            );

            test_parse_data_type!(
                dialect,
                "CHARACTER VARYING(20 CHARACTERS)",
                DataType::CharacterVarying(Some(CharacterLength::IntegerLength {
                    length: 20,
                    unit: Some(CharLengthUnits::Characters)
                }))
            );

            test_parse_data_type!(
                dialect,
                "CHARACTER VARYING(20 OCTETS)",
                DataType::CharacterVarying(Some(CharacterLength::IntegerLength {
                    length: 20,
                    unit: Some(CharLengthUnits::Octets)
                }))
            );

            test_parse_data_type!(
                dialect,
                "CHAR VARYING(20)",
                DataType::CharVarying(Some(CharacterLength::IntegerLength {
                    length: 20,
                    unit: None
                }))
            );

            test_parse_data_type!(
                dialect,
                "CHAR VARYING(20 CHARACTERS)",
                DataType::CharVarying(Some(CharacterLength::IntegerLength {
                    length: 20,
                    unit: Some(CharLengthUnits::Characters)
                }))
            );

            test_parse_data_type!(
                dialect,
                "CHAR VARYING(20 OCTETS)",
                DataType::CharVarying(Some(CharacterLength::IntegerLength {
                    length: 20,
                    unit: Some(CharLengthUnits::Octets)
                }))
            );

            test_parse_data_type!(
                dialect,
                "VARCHAR(20)",
                DataType::Varchar(Some(CharacterLength::IntegerLength {
                    length: 20,
                    unit: None
                }))
            );
        }

        #[test]
        fn test_ansii_character_large_object_types() {
            // Character large object types: <https://jakewheat.github.io/sql-overview/sql-2016-foundation-grammar.html#character-large-object-length>
            let dialect =
                TestedDialects::new(vec![Box::new(GenericDialect {}), Box::new(AnsiDialect {})]);

            test_parse_data_type!(
                dialect,
                "CHARACTER LARGE OBJECT",
                DataType::CharacterLargeObject(None)
            );
            test_parse_data_type!(
                dialect,
                "CHARACTER LARGE OBJECT(20)",
                DataType::CharacterLargeObject(Some(20))
            );

            test_parse_data_type!(
                dialect,
                "CHAR LARGE OBJECT",
                DataType::CharLargeObject(None)
            );
            test_parse_data_type!(
                dialect,
                "CHAR LARGE OBJECT(20)",
                DataType::CharLargeObject(Some(20))
            );

            test_parse_data_type!(dialect, "CLOB", DataType::Clob(None));
            test_parse_data_type!(dialect, "CLOB(20)", DataType::Clob(Some(20)));
        }

        #[test]
        fn test_parse_custom_types() {
            let dialect =
                TestedDialects::new(vec![Box::new(GenericDialect {}), Box::new(AnsiDialect {})]);

            test_parse_data_type!(
                dialect,
                "GEOMETRY",
                DataType::Custom(ObjectName::from(vec!["GEOMETRY".into()]), vec![])
            );

            test_parse_data_type!(
                dialect,
                "GEOMETRY(POINT)",
                DataType::Custom(
                    ObjectName::from(vec!["GEOMETRY".into()]),
                    vec!["POINT".to_string()]
                )
            );

            test_parse_data_type!(
                dialect,
                "GEOMETRY(POINT, 4326)",
                DataType::Custom(
                    ObjectName::from(vec!["GEOMETRY".into()]),
                    vec!["POINT".to_string(), "4326".to_string()]
                )
            );
        }

        #[test]
        fn test_ansii_exact_numeric_types() {
            // Exact numeric types: <https://jakewheat.github.io/sql-overview/sql-2016-foundation-grammar.html#exact-numeric-type>
            let dialect = TestedDialects::new(vec![
                Box::new(GenericDialect {}),
                Box::new(AnsiDialect {}),
                Box::new(PostgreSqlDialect {}),
            ]);

            test_parse_data_type!(dialect, "NUMERIC", DataType::Numeric(ExactNumberInfo::None));

            test_parse_data_type!(
                dialect,
                "NUMERIC(2)",
                DataType::Numeric(ExactNumberInfo::Precision(2))
            );

            test_parse_data_type!(
                dialect,
                "NUMERIC(2,10)",
                DataType::Numeric(ExactNumberInfo::PrecisionAndScale(2, 10))
            );

            test_parse_data_type!(dialect, "DECIMAL", DataType::Decimal(ExactNumberInfo::None));

            test_parse_data_type!(
                dialect,
                "DECIMAL(2)",
                DataType::Decimal(ExactNumberInfo::Precision(2))
            );

            test_parse_data_type!(
                dialect,
                "DECIMAL(2,10)",
                DataType::Decimal(ExactNumberInfo::PrecisionAndScale(2, 10))
            );

            test_parse_data_type!(dialect, "DEC", DataType::Dec(ExactNumberInfo::None));

            test_parse_data_type!(
                dialect,
                "DEC(2)",
                DataType::Dec(ExactNumberInfo::Precision(2))
            );

            test_parse_data_type!(
                dialect,
                "DEC(2,10)",
                DataType::Dec(ExactNumberInfo::PrecisionAndScale(2, 10))
            );

            // Test negative scale values.
            test_parse_data_type!(
                dialect,
                "NUMERIC(10,-2)",
                DataType::Numeric(ExactNumberInfo::PrecisionAndScale(10, -2))
            );

            test_parse_data_type!(
                dialect,
                "DECIMAL(1000,-10)",
                DataType::Decimal(ExactNumberInfo::PrecisionAndScale(1000, -10))
            );

            test_parse_data_type!(
                dialect,
                "DEC(5,-1000)",
                DataType::Dec(ExactNumberInfo::PrecisionAndScale(5, -1000))
            );

            test_parse_data_type!(
                dialect,
                "NUMERIC(10,-5)",
                DataType::Numeric(ExactNumberInfo::PrecisionAndScale(10, -5))
            );

            test_parse_data_type!(
                dialect,
                "DECIMAL(20,-10)",
                DataType::Decimal(ExactNumberInfo::PrecisionAndScale(20, -10))
            );

            test_parse_data_type!(
                dialect,
                "DEC(5,-2)",
                DataType::Dec(ExactNumberInfo::PrecisionAndScale(5, -2))
            );

            dialect.run_parser_method("NUMERIC(10,+5)", |parser| {
                let data_type = parser.parse_data_type().unwrap();
                assert_eq!(
                    DataType::Numeric(ExactNumberInfo::PrecisionAndScale(10, 5)),
                    data_type
                );
                // Note: Explicit '+' sign is not preserved in output, which is correct
                assert_eq!("NUMERIC(10,5)", data_type.to_string());
            });
        }

        #[test]
        fn test_ansii_date_type() {
            // Datetime types: <https://jakewheat.github.io/sql-overview/sql-2016-foundation-grammar.html#datetime-type>
            let dialect =
                TestedDialects::new(vec![Box::new(GenericDialect {}), Box::new(AnsiDialect {})]);

            test_parse_data_type!(dialect, "DATE", DataType::Date);

            test_parse_data_type!(dialect, "TIME", DataType::Time(None, TimezoneInfo::None));

            test_parse_data_type!(
                dialect,
                "TIME(6)",
                DataType::Time(Some(6), TimezoneInfo::None)
            );

            test_parse_data_type!(
                dialect,
                "TIME WITH TIME ZONE",
                DataType::Time(None, TimezoneInfo::WithTimeZone)
            );

            test_parse_data_type!(
                dialect,
                "TIME(6) WITH TIME ZONE",
                DataType::Time(Some(6), TimezoneInfo::WithTimeZone)
            );

            test_parse_data_type!(
                dialect,
                "TIME WITHOUT TIME ZONE",
                DataType::Time(None, TimezoneInfo::WithoutTimeZone)
            );

            test_parse_data_type!(
                dialect,
                "TIME(6) WITHOUT TIME ZONE",
                DataType::Time(Some(6), TimezoneInfo::WithoutTimeZone)
            );

            test_parse_data_type!(
                dialect,
                "TIMESTAMP",
                DataType::Timestamp(None, TimezoneInfo::None)
            );

            test_parse_data_type!(
                dialect,
                "TIMESTAMP(22)",
                DataType::Timestamp(Some(22), TimezoneInfo::None)
            );

            test_parse_data_type!(
                dialect,
                "TIMESTAMP(22) WITH TIME ZONE",
                DataType::Timestamp(Some(22), TimezoneInfo::WithTimeZone)
            );

            test_parse_data_type!(
                dialect,
                "TIMESTAMP(33) WITHOUT TIME ZONE",
                DataType::Timestamp(Some(33), TimezoneInfo::WithoutTimeZone)
            );
        }
    }

    #[test]
    fn test_parse_schema_name() {
        // The expected name should be identical as the input name, that's why I don't receive both
        macro_rules! test_parse_schema_name {
            ($input:expr, $expected_name:expr $(,)?) => {{
                all_dialects().run_parser_method(&*$input, |parser| {
                    let schema_name = parser.parse_schema_name().unwrap();
                    // Validate that the structure is the same as expected
                    assert_eq!(schema_name, $expected_name);
                    // Validate that the input and the expected structure serialization are the same
                    assert_eq!(schema_name.to_string(), $input.to_string());
                });
            }};
        }

        let dummy_name = ObjectName::from(vec![Ident::new("dummy_name")]);
        let dummy_authorization = Ident::new("dummy_authorization");

        test_parse_schema_name!(
            format!("{dummy_name}"),
            SchemaName::Simple(dummy_name.clone())
        );

        test_parse_schema_name!(
            format!("AUTHORIZATION {dummy_authorization}"),
            SchemaName::UnnamedAuthorization(dummy_authorization.clone()),
        );
        test_parse_schema_name!(
            format!("{dummy_name} AUTHORIZATION {dummy_authorization}"),
            SchemaName::NamedAuthorization(dummy_name.clone(), dummy_authorization.clone()),
        );
    }

    #[test]
    fn mysql_parse_index_table_constraint() {
        macro_rules! test_parse_table_constraint {
            ($dialect:expr, $input:expr, $expected:expr $(,)?) => {{
                $dialect.run_parser_method(&*$input, |parser| {
                    let constraint = parser.parse_optional_table_constraint().unwrap().unwrap();
                    // Validate that the structure is the same as expected
                    assert_eq!(constraint, $expected);
                    // Validate that the input and the expected structure serialization are the same
                    assert_eq!(constraint.to_string(), $input.to_string());
                });
            }};
        }

        fn mk_expected_col(name: &str) -> IndexColumn {
            IndexColumn {
                column: OrderByExpr {
                    expr: Expr::Identifier(name.into()),
                    options: OrderByOptions {
                        sort: None,
                        nulls_first: None,
                    },
                    with_fill: None,
                },
                operator_class: None,
            }
        }

        let dialect =
            TestedDialects::new(vec![Box::new(GenericDialect {}), Box::new(MySqlDialect {})]);

        test_parse_table_constraint!(
            dialect,
            "INDEX (c1)",
            IndexConstraint {
                display_as_key: false,
                name: None,
                index_type: None,
                columns: vec![mk_expected_col("c1")],
                index_options: vec![],
            }
            .into()
        );

        test_parse_table_constraint!(
            dialect,
            "KEY (c1)",
            IndexConstraint {
                display_as_key: true,
                name: None,
                index_type: None,
                columns: vec![mk_expected_col("c1")],
                index_options: vec![],
            }
            .into()
        );

        test_parse_table_constraint!(
            dialect,
            "INDEX 'index' (c1, c2)",
            TableConstraint::Index(IndexConstraint {
                display_as_key: false,
                name: Some(Ident::with_quote('\'', "index")),
                index_type: None,
                columns: vec![mk_expected_col("c1"), mk_expected_col("c2")],
                index_options: vec![],
            })
        );

        test_parse_table_constraint!(
            dialect,
            "INDEX USING BTREE (c1)",
            IndexConstraint {
                display_as_key: false,
                name: None,
                index_type: Some(IndexType::BTree),
                columns: vec![mk_expected_col("c1")],
                index_options: vec![],
            }
            .into()
        );

        test_parse_table_constraint!(
            dialect,
            "INDEX USING HASH (c1)",
            IndexConstraint {
                display_as_key: false,
                name: None,
                index_type: Some(IndexType::Hash),
                columns: vec![mk_expected_col("c1")],
                index_options: vec![],
            }
            .into()
        );

        test_parse_table_constraint!(
            dialect,
            "INDEX idx_name USING BTREE (c1)",
            IndexConstraint {
                display_as_key: false,
                name: Some(Ident::new("idx_name")),
                index_type: Some(IndexType::BTree),
                columns: vec![mk_expected_col("c1")],
                index_options: vec![],
            }
            .into()
        );

        test_parse_table_constraint!(
            dialect,
            "INDEX idx_name USING HASH (c1)",
            IndexConstraint {
                display_as_key: false,
                name: Some(Ident::new("idx_name")),
                index_type: Some(IndexType::Hash),
                columns: vec![mk_expected_col("c1")],
                index_options: vec![],
            }
            .into()
        );
    }

    #[test]
    fn test_tokenizer_error_loc() {
        let sql = "foo '";
        let ast = Parser::parse_sql(&GenericDialect, sql);
        assert_eq!(
            ast,
            Err(ParserError::TokenizerError(
                "Unterminated string literal at Line: 1, Column: 5".to_string()
            ))
        );
    }

    #[test]
    fn test_parser_error_loc() {
        let sql = "SELECT this is a syntax error";
        let ParserError::ParserError(msg) = Parser::parse_sql(&GenericDialect, sql).unwrap_err()
        else {
            panic!("expected ParserError::ParserError");
        };
        assert!(
            msg.ends_with("found: a at Line: 1, Column: 16"),
            "unexpected error message: {msg}"
        );
    }

    #[test]
    fn test_nested_explain_error() {
        let sql = "EXPLAIN EXPLAIN SELECT 1";
        let ast = Parser::parse_sql(&GenericDialect, sql);
        assert_eq!(
            ast,
            Err(ParserError::ParserError(
                "Explain must be root of the plan".to_string()
            ))
        );
    }

    #[test]
    fn test_parse_multipart_identifier_positive() {
        let dialect = TestedDialects::new(vec![Box::new(GenericDialect {})]);

        // parse multipart with quotes
        let expected = vec![
            Ident {
                value: "CATALOG".to_string(),
                quote_style: None,
                span: Span::empty(),
            },
            Ident {
                value: "F(o)o. \"bar".to_string(),
                quote_style: Some('"'),
                span: Span::empty(),
            },
            Ident {
                value: "table".to_string(),
                quote_style: None,
                span: Span::empty(),
            },
        ];
        dialect.run_parser_method(r#"CATALOG."F(o)o. ""bar".table"#, |parser| {
            let actual = parser.parse_multipart_identifier().unwrap();
            assert_eq!(expected, actual);
        });

        // allow whitespace between ident parts
        let expected = vec![
            Ident {
                value: "CATALOG".to_string(),
                quote_style: None,
                span: Span::empty(),
            },
            Ident {
                value: "table".to_string(),
                quote_style: None,
                span: Span::empty(),
            },
        ];
        dialect.run_parser_method("CATALOG . table", |parser| {
            let actual = parser.parse_multipart_identifier().unwrap();
            assert_eq!(expected, actual);
        });
    }

    #[test]
    fn test_parse_multipart_identifier_negative() {
        macro_rules! test_parse_multipart_identifier_error {
            ($input:expr, $expected_err:expr $(,)?) => {{
                all_dialects().run_parser_method(&*$input, |parser| {
                    let actual_err = parser.parse_multipart_identifier().unwrap_err();
                    assert_eq!(actual_err.to_string(), $expected_err);
                });
            }};
        }

        test_parse_multipart_identifier_error!(
            "",
            "sql parser error: Empty input when parsing identifier",
        );

        test_parse_multipart_identifier_error!(
            "*schema.table",
            "sql parser error: Unexpected token in identifier: *",
        );

        test_parse_multipart_identifier_error!(
            "schema.table*",
            "sql parser error: Unexpected token in identifier: *",
        );

        test_parse_multipart_identifier_error!(
            "schema.table.",
            "sql parser error: Trailing period in identifier",
        );

        test_parse_multipart_identifier_error!(
            "schema.*",
            "sql parser error: Unexpected token following period in identifier: *",
        );
    }

    #[test]
    fn test_mysql_partition_selection() {
        let sql = "SELECT * FROM employees PARTITION (p0, p2)";
        let expected = vec!["p0", "p2"];

        let ast: Vec<Statement> = Parser::parse_sql(&MySqlDialect {}, sql).unwrap();
        assert_eq!(ast.len(), 1);
        if let Statement::Query(v) = &ast[0] {
            if let SetExpr::Select(select) = &*v.body {
                assert_eq!(select.from.len(), 1);
                let from: &TableWithJoins = &select.from[0];
                let table_factor = &from.relation;
                if let TableFactor::Table { partitions, .. } = table_factor {
                    let actual: Vec<&str> = partitions
                        .iter()
                        .map(|ident| ident.value.as_str())
                        .collect();
                    assert_eq!(expected, actual);
                }
            }
        } else {
            panic!("fail to parse mysql partition selection");
        }
    }

    #[test]
    fn test_replace_into_placeholders() {
        let sql = "REPLACE INTO t (a) VALUES (&a)";

        assert_eq!(
            ParserError::ParserError(
                "Expected: an expression, found: & at Line: 1, Column: 28".to_string()
            ),
            Parser::parse_sql(&GenericDialect {}, sql).unwrap_err()
        );
    }

    #[test]
    fn test_replace_into_set_placeholder() {
        let sql = "REPLACE INTO t SET ?";

        assert_eq!(
            ParserError::ParserError(
                "Expected: SELECT, VALUES, or a subquery in the query body, found: SET at Line: 1, Column: 16"
                    .to_string()
            ),
            Parser::parse_sql(&GenericDialect {}, sql).unwrap_err()
        );
    }

    #[test]
    fn test_replace_incomplete() {
        let sql = r#"REPLACE"#;

        assert_eq!(
            ParserError::ParserError("Expected: identifier, found: EOF".to_string()),
            Parser::parse_sql(&MySqlDialect {}, sql).unwrap_err()
        );
    }

    #[test]
    fn test_placeholder_invalid_whitespace() {
        for (w, expected) in [
            (
                "  ",
                "Expected: placeholder, found:   at Line: 3, Column: 4",
            ),
            (
                "/*invalid*/",
                "Expected: placeholder, found: /*invalid*/ at Line: 3, Column: 4",
            ),
        ] {
            let sql = format!("\nSELECT\n  :{w}fooBar");
            assert_eq!(
                ParserError::ParserError(expected.to_string()),
                Parser::parse_sql(&GenericDialect, &sql).unwrap_err()
            );
        }
    }
}
