// 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>>,
}

/// Whether an alias names a select item or a table.
#[derive(Debug, Clone, Copy)]
enum AliasKind {
    Column,
    Table,
}

/// 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, AliasKind::Column, 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
        if !global && self.parse_keyword(Keyword::UNNEST) {
            self.expect_token(&Token::LParen)?;
            let array_expr = self.parse_expr()?;
            self.expect_token(&Token::RParen)?;
            return Ok(Expr::InUnnest {
                expr: Box::new(expr),
                array_expr: Box::new(array_expr),
                negated,
            });
        }
        if self.dialect.supports_in_unparenthesized_expr()
            && self.peek_token_ref().token != Token::LParen
        {
            return Ok(Expr::InList {
                expr: Box::new(expr),
                list: vec![self.parse_subexpr(self.dialect.prec_value(Precedence::Eq))?],
                negated,
                global,
            });
        }
        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(Expr::InSubquery {
                            expr: Box::new(expr),
                            subquery,
                            negated,
                            global,
                        });
                    }
                    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(Expr::InList {
                expr: Box::new(expr),
                list,
                negated,
                global,
            }),
            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, AliasKind::Column, 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, AliasKind::Table, 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), AliasKind::Column, 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]>,
        kind: AliasKind,
        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 match kind {
                    AliasKind::Column => {
                        self.dialect.supports_string_literal_column_alias(after_as)
                    }
                    AliasKind::Table => self.dialect.supports_string_literal_table_alias(after_as),
                } =>
            {
                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, AliasKind::Column, 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()
            );
        }
    }
}
