// 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,
    format,
    string::{String, ToString},
    vec,
    vec::Vec,
};
use core::{
    fmt::{self, Display},
    str::FromStr,
};
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;

#[cfg(feature = "std")]
/// Implementation [`RecursionCounter`] if std is available
mod recursion {
    use std::cell::Cell;
    use std::rc::Rc;

    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 [`std::rc::Rc`] and [`std::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 + 1);
        }
    }
}

#[cfg(not(feature = "std"))]
mod recursion {
    /// Implementation [`RecursionCounter`] if std is NOT available (and does not
    /// guard against stack overflow).
    ///
    /// Has the same API as the std [`RecursionCounter`] implementation
    /// but does not actually limit stack depth.
    pub(crate) struct RecursionCounter {}

    impl RecursionCounter {
        pub fn new(_remaining_depth: usize) -> Self {
            Self {}
        }
        pub fn try_decrease(&self) -> Result<DepthGuard, super::ParserError> {
            Ok(DepthGuard {})
        }
    }

    pub struct DepthGuard {}
}

#[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)]
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,
}

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()),
        }
    }

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

    /// 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.
    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::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::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).unwrap().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),
                                ));
                            }
                            _ => {
                                return self
                                    .expected("an identifier or a '*' after '.'", next_token);
                            }
                        }
                    }
                }
            }
            Token::Mul => {
                return Ok(Expr::Wildcard(AttachedToken(next_token)));
            }
            // Handle parenthesized wildcard: (*)
            Token::LParen => {
                let [maybe_mul, maybe_rparen] = self.peek_tokens_ref();
                if maybe_mul.token == Token::Mul && maybe_rparen.token == Token::RParen {
                    let mul_token = self.next_token(); // consume Mul
                    self.next_token(); // consume RParen
                    return Ok(Expr::Wildcard(AttachedToken(mul_token)));
                }
            }
            _ => (),
        };

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

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

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

        fn validator(explicit: bool, kw: &Keyword, _parser: &mut Parser) -> bool {
            explicit || !&[Keyword::ASC, Keyword::DESC, Keyword::GROUP].contains(kw)
        }
        let alias = self.parse_optional_alias_inner(None, validator)?;
        let order_by = OrderByOptions {
            asc: self.parse_asc_desc(),
            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![])?;

        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::LAMBDA if self.dialect.supports_lambda_functions() => {
                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;
        }

        // 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),
                        array: false,
                        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();
                match self.try_parse(|parser| parser.parse_expr_prefix_by_reserved_word(&w, span)) {
                    // 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) => {
                        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),
        }?;

        if !self.in_column_definition_state() && self.parse_keyword(Keyword::COLLATE) {
            Ok(Expr::Collate {
                expr: Box::new(expr),
                collation: self.parse_object_name(false)?,
            })
        } else {
            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
                    }
                    // Fallback to parsing an arbitrary expression, but restrict to expression
                    // types that are valid after the dot operator. This ensures that e.g.
                    // `T.interval` is parsed as a compound identifier, not as an interval
                    // expression.
                    _ => {
                        let expr = self.maybe_parse(|parser| {
                            let expr = parser
                                .parse_subexpr(parser.dialect.prec_value(Precedence::Period))?;
                            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 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 = 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 = self.parse_data_type()?;
        let array = self.parse_keyword(Keyword::ARRAY);
        let format = self.parse_optional_cast_format()?;
        self.expect_token(&Token::RParen)?;
        Ok(Expr::Cast {
            kind,
            expr: Box::new(expr),
            data_type,
            array,
            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);
        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.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()?);
            }
        }
        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: None,
                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.
    pub fn parse_interval(&mut self) -> Result<Expr, ParserError> {
        // 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_helper()?;

        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 clickhouse [map]
    ///
    /// Syntax
    ///
    /// ```sql
    /// Map(key_data_type, value_data_type)
    /// ```
    ///
    /// [map]: https://clickhouse.com/docs/en/sql-reference/data-types/map
    fn parse_click_house_map_def(&mut self) -> Result<(DataType, DataType), 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()?;
        self.expect_token(&Token::RParen)?;

        Ok((key_data_type, value_data_type))
    }

    /// 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) => {
                    self.expect_token(&Token::LParen)?;
                    // 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
                    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)?;
                    Some(BinaryOperator::PGCustomBinaryOperator(idents))
                }
                _ => 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]) {
                        let expr2 = self.parse_expr()?;
                        Ok(Expr::IsDistinctFrom(Box::new(expr), Box::new(expr2)))
                    } else if self.parse_keywords(&[Keyword::NOT, Keyword::DISTINCT, Keyword::FROM])
                    {
                        let expr2 = self.parse_expr()?;
                        Ok(Expr::IsNotDistinctFrom(Box::new(expr), Box::new(expr2)))
                    } else if let Ok(is_normalized) = self.parse_unicode_is_normalized(expr) {
                        Ok(is_normalized)
                    } else {
                        self.expected_ref(
                            "[NOT] NULL | TRUE | FALSE | DISTINCT | [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::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)
                    } 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())
                    }
                }
                // 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()?,
                array: false,
                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<ValueWithSpan>, ParserError> {
        if self.parse_keyword(Keyword::ESCAPE) {
            Ok(Some(self.parse_value()?))
        } 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 `[ NOT ] IN` operator.
    pub fn parse_in(&mut self, expr: Expr, negated: bool) -> Result<Expr, ParserError> {
        // BigQuery allows `IN UNNEST(array_expression)`
        // https://cloud.google.com/bigquery/docs/reference/standard-sql/operators#in_operators
        if 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,
            });
        }
        self.expect_token(&Token::LParen)?;
        let in_op = match self.maybe_parse(|p| p.parse_query())? {
            Some(subquery) => Expr::InSubquery {
                expr: Box::new(expr),
                subquery,
                negated,
            },
            None => Expr::InList {
                expr: Box::new(expr),
                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)?
                },
                negated,
            },
        };
        self.expect_token(&Token::RParen)?;
        Ok(in_op)
    }

    /// 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()?,
            array: false,
            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 or_replace = self.parse_keywords(&[Keyword::OR, Keyword::REPLACE]);
        let or_alter = self.parse_keywords(&[Keyword::OR, Keyword::ALTER]);
        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 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.parse_keyword(Keyword::TABLE) {
            self.parse_create_table(or_replace, temporary, global, transient)
                .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 or_replace {
            self.expected_ref(
                "[EXTERNAL] TABLE or [MATERIALIZED] VIEW or FUNCTION 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::SCHEMA) {
            self.parse_create_schema()
        } 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::TYPE) {
            self.parse_create_type()
        } else if self.parse_keyword(Keyword::PROCEDURE) {
            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 {
            self.expected_ref("an object type after CREATE", self.peek_token_ref())
        }
    }

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

    /// 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) -> 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,
            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);

            // We ensure that the token is a `Word` token, and not other special tokens.
            if !matches!(token.token, Token::Word(_)) {
                return self.expected("a name or type", token.clone());
            }

            name = Some(Ident::new(token.to_string()));
            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);
            if !matches!(token.token, Token::Word(_)) {
                return self.expected("a name or type", token.clone());
            }

            name = Some(Ident::new(token.to_string()));
            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 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)
            .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 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()?;
        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 if self.consume_token(&Token::LParen) {
                    self.expect_token(&Token::RParen)?;
                    Some(vec![])
                } 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::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::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(
                "CONNECTOR, DATABASE, EXTENSION, FUNCTION, INDEX, OPERATOR, POLICY, PROCEDURE, ROLE, SCHEMA, SECRET, SEQUENCE, STAGE, TABLE, TRIGGER, TYPE, VIEW, MATERIALIZED VIEW or USER 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 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,
            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::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,
            ]) {
                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;
                    }
                }
                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()?,
                                    });
                                }
                            } else {
                                break;
                            }
                        }
                        Some(Keyword::COLLECTION) => {
                            if self.parse_keywords(&[
                                Keyword::ITEMS,
                                Keyword::TERMINATED,
                                Keyword::BY,
                            ]) {
                                row_delimiters.push(HiveRowDelimiter {
                                    delimiter: HiveDelimiter::CollectionItemsTerminatedBy,
                                    char: self.parse_identifier()?,
                                });
                            } else {
                                break;
                            }
                        }
                        Some(Keyword::MAP) => {
                            if self.parse_keywords(&[
                                Keyword::KEYS,
                                Keyword::TERMINATED,
                                Keyword::BY,
                            ]) {
                                row_delimiters.push(HiveRowDelimiter {
                                    delimiter: HiveDelimiter::MapKeysTerminatedBy,
                                    char: self.parse_identifier()?,
                                });
                            } else {
                                break;
                            }
                        }
                        Some(Keyword::LINES) => {
                            if self.parse_keywords(&[Keyword::TERMINATED, Keyword::BY]) {
                                row_delimiters.push(HiveRowDelimiter {
                                    delimiter: HiveDelimiter::LinesTerminatedBy,
                                    char: self.parse_identifier()?,
                                });
                            } else {
                                break;
                            }
                        }
                        Some(Keyword::NULL) => {
                            if self.parse_keywords(&[Keyword::DEFINED, Keyword::AS]) {
                                row_delimiters.push(HiveRowDelimiter {
                                    delimiter: HiveDelimiter::NullDefinedAs,
                                    char: self.parse_identifier()?,
                                });
                            } else {
                                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.
    pub fn parse_create_table(
        &mut self,
        or_replace: bool,
        temporary: bool,
        global: Option<bool>,
        transient: 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)?;

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

        // SQLite supports `WITHOUT ROWID` at the end of `CREATE TABLE`
        let without_rowid = self.parse_keywords(&[Keyword::WITHOUT, Keyword::ROWID]);

        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]) {
            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)?;
                Some(OneOrManyWithParens::Many(columns))
            } else {
                Some(OneOrManyWithParens::One(self.parse_expr()?))
            }
        } else {
            None
        };

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

        let strict = self.parse_keyword(Keyword::STRICT);

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

        Ok(CreateTableBuilder::new(table_name)
            .temporary(temporary)
            .columns(columns)
            .constraints(constraints)
            .or_replace(or_replace)
            .if_not_exists(if_not_exists)
            .transient(transient)
            .hive_distribution(hive_distribution)
            .hive_formats(hive_formats)
            .global(global)
            .query(query)
            .without_rowid(without_rowid)
            .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(create_table_config.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)
            .strict(strict)
            .backup(backup)
            .diststyle(diststyle)
            .distkey(distkey)
            .sortkey(sortkey)
            .build())
    }

    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(Ident::new(w.value)),
                            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 {
                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![],
                    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![],
                    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![],
                    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 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),
                    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 index_options = self.parse_index_options()?;
                let characteristics = self.parse_constraint_characteristics()?;
                Ok(Some(
                    UniqueConstraint {
                        name,
                        index_name,
                        index_type_display,
                        index_type,
                        columns,
                        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 index_options = self.parse_index_options()?;
                let characteristics = self.parse_constraint_characteristics()?;
                Ok(Some(
                    PrimaryKeyConstraint {
                        name,
                        index_name,
                        index_type,
                        columns,
                        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 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,
                        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(),
                ))
            }
            _ => {
                if name.is_some() {
                    self.expected("PRIMARY, UNIQUE, FOREIGN, or CHECK", next_token)
                } else {
                    self.prev_token();
                    Ok(None)
                }
            }
        }
    }

    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 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 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_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 {
            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> {
        let object_type = self.expect_one_of_keywords(&[
            Keyword::VIEW,
            Keyword::TYPE,
            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::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 => 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 {{VIEW, TYPE, 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::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 if self.consume_token(&Token::LParen) {
                self.expect_token(&Token::RParen)?;
                Some(vec![])
            } 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) => 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 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)
    }

    fn parse_data_type_helper(
        &mut self,
    ) -> Result<(DataType, MatchedTrailingBracket), ParserError> {
        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::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 => 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_without_element_type() {
                        Ok(DataType::Array(ArrayElemTypeDef::None))
                    } else if dialect_of!(self is ClickHouseDialect) {
                        Ok(self.parse_sub_type(|internal_type| {
                            DataType::Array(ArrayElemTypeDef::Parenthesis(internal_type))
                        })?)
                    } else {
                        self.expect_token(&Token::Lt)?;
                        let (inside_type, _trailing_bracket) = self.parse_data_type_helper()?;
                        trailing_bracket = self.expect_closing_angle_bracket(_trailing_bracket)?;
                        Ok(DataType::Array(ArrayElemTypeDef::AngleBracket(Box::new(
                            inside_type,
                        ))))
                    }
                }
                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 dialect_is!(dialect is BigQueryDialect | DatabricksDialect | GenericDialect) =>
                {
                    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 dialect_is!(dialect is ClickHouseDialect | GenericDialect) => {
                    self.prev_token();
                    let (key_data_type, value_data_type) = self.parse_click_house_map_def()?;
                    Ok(DataType::Map(
                        Box::new(key_data_type),
                        Box::new(value_data_type),
                    ))
                }
                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),
        }?;

        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))
            }
        }
        Ok((data, trailing_bracket))
    }

    fn parse_returns_table_column(&mut self) -> Result<ColumnDef, ParserError> {
        self.parse_column_def()
    }

    fn parse_returns_table_columns(&mut self) -> Result<Vec<ColumnDef>, ParserError> {
        self.expect_token(&Token::LParen)?;
        let columns = self.parse_comma_separated(Parser::parse_returns_table_column)?;
        self.expect_token(&Token::RParen)?;
        Ok(columns)
    }

    /// Parse a parenthesized, comma-separated list of single-quoted strings.
    pub fn parse_string_values(&mut self) -> Result<Vec<String>, ParserError> {
        self.expect_token(&Token::LParen)?;
        let mut values = Vec::new();
        loop {
            let next_token = self.next_token();
            match next_token.token {
                Token::SingleQuotedString(value) => values.push(value),
                _ => self.expected("a string", next_token)?,
            }
            let next_token = self.next_token();
            match next_token.token {
                Token::Comma => (),
                Token::RParen => break,
                _ => self.expected(", or }", next_token)?,
            }
        }
        Ok(values)
    }

    /// Strictly parse `identifier AS identifier`
    pub fn parse_identifier_with_alias(&mut self) -> Result<IdentWithAlias, ParserError> {
        let ident = self.parse_identifier()?;
        self.expect_keyword_is(Keyword::AS)?;
        let alias = self.parse_identifier()?;
        Ok(IdentWithAlias { ident, alias })
    }

    /// Parse `identifier [AS] identifier` where the AS keyword is optional
    fn parse_identifier_with_optional_alias(&mut self) -> Result<IdentWithAlias, ParserError> {
        let ident = self.parse_identifier()?;
        let _after_as = self.parse_keyword(Keyword::AS);
        let alias = self.parse_identifier()?;
        Ok(IdentWithAlias { ident, alias })
    }

    /// Parse comma-separated list of parenthesized queries for pipe operators
    fn parse_pipe_operator_queries(&mut self) -> Result<Vec<Query>, ParserError> {
        self.parse_comma_separated(|parser| {
            parser.expect_token(&Token::LParen)?;
            let query = parser.parse_query()?;
            parser.expect_token(&Token::RParen)?;
            Ok(*query)
        })
    }

    /// Parse set quantifier for pipe operators that require DISTINCT. E.g. INTERSECT and EXCEPT
    fn parse_distinct_required_set_quantifier(
        &mut self,
        operator_name: &str,
    ) -> Result<SetQuantifier, ParserError> {
        let quantifier = self.parse_set_quantifier(&Some(SetOperator::Intersect));
        match quantifier {
            SetQuantifier::Distinct | SetQuantifier::DistinctByName => Ok(quantifier),
            _ => Err(ParserError::ParserError(format!(
                "{operator_name} pipe operator requires DISTINCT modifier",
            ))),
        }
    }

    /// Parse optional identifier alias (with or without AS keyword)
    fn parse_identifier_optional_alias(&mut self) -> Result<Option<Ident>, ParserError> {
        if self.parse_keyword(Keyword::AS) {
            Ok(Some(self.parse_identifier()?))
        } else {
            // Check if the next token is an identifier (implicit alias)
            self.maybe_parse(|parser| parser.parse_identifier())
        }
    }

    /// Optionally parses an alias for a select list item
    fn maybe_parse_select_item_alias(&mut self) -> Result<Option<Ident>, ParserError> {
        fn validator(explicit: bool, kw: &Keyword, parser: &mut Parser) -> bool {
            parser.dialect.is_select_item_alias(explicit, kw, parser)
        }
        self.parse_optional_alias_inner(None, validator)
    }

    /// Optionally parses an alias for a table like in `... FROM generate_series(1, 10) AS t (col)`.
    /// In this case, the alias is allowed to optionally name the columns in the table, in
    /// addition to the table itself.
    pub fn maybe_parse_table_alias(&mut self) -> Result<Option<TableAlias>, ParserError> {
        fn validator(explicit: bool, kw: &Keyword, parser: &mut Parser) -> bool {
            parser.dialect.is_table_factor_alias(explicit, kw, parser)
        }
        let explicit = self.peek_keyword(Keyword::AS);
        match self.parse_optional_alias_inner(None, validator)? {
            Some(name) => {
                let columns = self.parse_table_alias_column_defs()?;
                Ok(Some(TableAlias {
                    explicit,
                    name,
                    columns,
                }))
            }
            None => Ok(None),
        }
    }

    fn parse_table_index_hints(&mut self) -> Result<Vec<TableIndexHints>, ParserError> {
        let mut hints = vec![];
        while let Some(hint_type) =
            self.parse_one_of_keywords(&[Keyword::USE, Keyword::IGNORE, Keyword::FORCE])
        {
            let hint_type = match hint_type {
                Keyword::USE => TableIndexHintType::Use,
                Keyword::IGNORE => TableIndexHintType::Ignore,
                Keyword::FORCE => TableIndexHintType::Force,
                _ => {
                    return self.expected_ref(
                        "expected to match USE/IGNORE/FORCE keyword",
                        self.peek_token_ref(),
                    )
                }
            };
            let index_type = match self.parse_one_of_keywords(&[Keyword::INDEX, Keyword::KEY]) {
                Some(Keyword::INDEX) => TableIndexType::Index,
                Some(Keyword::KEY) => TableIndexType::Key,
                _ => {
                    return self
                        .expected_ref("expected to match INDEX/KEY keyword", self.peek_token_ref())
                }
            };
            let for_clause = if self.parse_keyword(Keyword::FOR) {
                let clause = if self.parse_keyword(Keyword::JOIN) {
                    TableIndexHintForClause::Join
                } else if self.parse_keywords(&[Keyword::ORDER, Keyword::BY]) {
                    TableIndexHintForClause::OrderBy
                } else if self.parse_keywords(&[Keyword::GROUP, Keyword::BY]) {
                    TableIndexHintForClause::GroupBy
                } else {
                    return self.expected_ref(
                        "expected to match FOR/ORDER BY/GROUP BY table hint in for clause",
                        self.peek_token_ref(),
                    );
                };
                Some(clause)
            } else {
                None
            };

            self.expect_token(&Token::LParen)?;
            let index_names = if self.peek_token_ref().token != Token::RParen {
                self.parse_comma_separated(Parser::parse_identifier)?
            } else {
                vec![]
            };
            self.expect_token(&Token::RParen)?;
            hints.push(TableIndexHints {
                hint_type,
                index_type,
                for_clause,
                index_names,
            });
        }
        Ok(hints)
    }

    /// Wrapper for parse_optional_alias_inner, left for backwards-compatibility
    /// but new flows should use the context-specific methods such as `maybe_parse_select_item_alias`
    /// and `maybe_parse_table_alias`.
    pub fn parse_optional_alias(
        &mut self,
        reserved_kwds: &[Keyword],
    ) -> Result<Option<Ident>, ParserError> {
        fn validator(_explicit: bool, _kw: &Keyword, _parser: &mut Parser) -> bool {
            false
        }
        self.parse_optional_alias_inner(Some(reserved_kwds), validator)
    }

    /// Parses an optional alias after a SQL element such as a select list item
    /// or a table name.
    ///
    /// This method accepts an optional list of reserved keywords or a function
    /// to call to validate if a keyword should be parsed as an alias, to allow
    /// callers to customize the parsing logic based on their context.
    fn parse_optional_alias_inner<F>(
        &mut self,
        reserved_kwds: Option<&[Keyword]>,
        validator: F,
    ) -> Result<Option<Ident>, ParserError>
    where
        F: Fn(bool, &Keyword, &mut Parser) -> bool,
    {
        let after_as = self.parse_keyword(Keyword::AS);

        let next_token = self.next_token();
        match next_token.token {
            // Accepts a keyword as an alias if the AS keyword explicitly indicate an alias or if the
            // caller provided a list of reserved keywords and the keyword is not on that list.
            Token::Word(w)
                if reserved_kwds.is_some()
                    && (after_as || reserved_kwds.is_some_and(|x| !x.contains(&w.keyword))) =>
            {
                Ok(Some(w.into_ident(next_token.span)))
            }
            // Accepts a keyword as alias based on the caller's context, such as to what SQL element
            // this word is a potential alias of using the validator call-back. This allows for
            // dialect-specific logic.
            Token::Word(w) if validator(after_as, &w.keyword, self) => {
                Ok(Some(w.into_ident(next_token.span)))
            }
            // For backwards-compatibility, we accept quoted strings as aliases regardless of the context.
            Token::SingleQuotedString(s) => 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 => {
                    return 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('\'', s)),
            Token::DoubleQuotedString(s) => Ok(Ident::with_quote('\"', 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)
        }
    }

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

        Ok(Statement::Delete(Delete {
            delete_token: delete_token.into(),
            optimizer_hints,
            tables,
            from: if with_from_keyword {
                FromTable::WithFromKeyword(from)
            } else {
                FromTable::WithoutKeyword(from)
            },
            using,
            selection,
            returning,
            output,
            order_by,
            limit,
        }))
    }

    /// 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 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()?);
                }
            }
            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![],
                    },
                    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 dialect_of!(self is PostgreSqlDialect) {
            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,
            },
            query,
            from: None,
            materialized: is_materialized,
            closing_paren_token: closing_paren_token.into(),
        };
        if 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 token1 = self.next_token();
        let token2 = self.next_token();
        let token3 = self.next_token();

        let table_name;
        let schema_name;
        if token2 == Token::Period {
            match token1.token {
                Token::Word(w) => {
                    schema_name = w.value;
                }
                _ => {
                    return self.expected("Schema name", token1);
                }
            }
            match token3.token {
                Token::Word(w) => {
                    table_name = w.value;
                }
                _ => {
                    return self.expected("Table name", token3);
                }
            }
            Ok(Table {
                table_name: Some(table_name),
                schema_name: Some(schema_name),
            })
        } else {
            match token1.token {
                Token::Word(w) => {
                    table_name = w.value;
                }
                _ => {
                    return self.expected("Table name", token1);
                }
            }
            Ok(Table {
                table_name: Some(table_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::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_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 {
                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()
                    && 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 alias = self.maybe_parse_table_alias()?;
                Ok(TableFactor::Function {
                    lateral: true,
                    name,
                    args,
                    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).
            if let Some(mut table) =
                self.maybe_parse(|parser| parser.parse_derived_table_factor(NotLateral))?
            {
                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()?;

            #[allow(clippy::if_same_then_else)]
            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);
                        }
                    };
                }
                // 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.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.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 dialect_of!(self is MySqlDialect | GenericDialect)
                && 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();
                return 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 mut pattern = self.parse_base_pattern()?;
        loop {
            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();
                    break;
                }
            };
            pattern = MatchRecognizePattern::Repetition(Box::new(pattern), quantifier);
        }
        Ok(pattern)
    }

    fn parse_concat_pattern(&mut self) -> Result<MatchRecognizePattern, ParserError> {
        let mut patterns = vec![self.parse_repetition_pattern()?];
        while !matches!(self.peek_token_ref().token, Token::RParen | Token::Pipe) {
            patterns.push(self.parse_repetition_pattern()?);
        }
        match <[MatchRecognizePattern; 1]>::try_from(patterns) {
            Ok([pattern]) => Ok(pattern),
            Err(patterns) => Ok(MatchRecognizePattern::Concat(patterns)),
        }
    }

    fn parse_pattern(&mut self) -> Result<MatchRecognizePattern, ParserError> {
        let pattern = self.parse_concat_pattern()?;
        if self.consume_token(&Token::Pipe) {
            match self.parse_pattern()? {
                // flatten nested alternations
                MatchRecognizePattern::Alternation(mut patterns) => {
                    patterns.insert(0, pattern);
                    Ok(MatchRecognizePattern::Alternation(patterns))
                }
                next => Ok(MatchRecognizePattern::Alternation(vec![pattern, next])),
            }
        } else {
            Ok(pattern)
        }
    }

    /// Parses a the timestamp version specifier (i.e. query historical data)
    pub fn maybe_parse_table_version(&mut self) -> Result<Option<TableVersion>, ParserError> {
        if self.dialect.supports_table_versioning() {
            if self.parse_keywords(&[Keyword::FOR, Keyword::SYSTEM_TIME, Keyword::AS, Keyword::OF])
            {
                let expr = self.parse_expr()?;
                return Ok(Some(TableVersion::ForSystemTimeAsOf(expr)));
            } else if self.peek_keyword(Keyword::CHANGES) {
                return self.parse_table_version_changes().map(Some);
            } else if self.peek_keyword(Keyword::AT) || self.peek_keyword(Keyword::BEFORE) {
                let func_name = self.parse_object_name(true)?;
                let func = self.parse_function(func_name)?;
                return Ok(Some(TableVersion::Function(func)));
            } else if self.parse_keywords(&[Keyword::TIMESTAMP, Keyword::AS, Keyword::OF]) {
                let expr = self.parse_expr()?;
                return Ok(Some(TableVersion::TimestampAsOf(expr)));
            } else if self.parse_keywords(&[Keyword::VERSION, Keyword::AS, Keyword::OF]) {
                let expr = Expr::Value(self.parse_number_value()?);
                return Ok(Some(TableVersion::VersionAsOf(expr)));
            }
        }
        Ok(None)
    }

    /// Parses the Snowflake `CHANGES` clause for change tracking queries.
    ///
    /// Syntax:
    /// ```sql
    /// CHANGES (INFORMATION => DEFAULT)
    ///   AT (TIMESTAMP => <expr>)
    ///   [END (TIMESTAMP => <expr>)]
    /// ```
    ///
    /// <https://docs.snowflake.com/en/sql-reference/constructs/changes>
    fn parse_table_version_changes(&mut self) -> Result<TableVersion, ParserError> {
        let changes_name = self.parse_object_name(true)?;
        let changes = self.parse_function(changes_name)?;
        let at_name = self.parse_object_name(true)?;
        let at = self.parse_function(at_name)?;
        let end = if self.peek_keyword(Keyword::END) {
            let end_name = self.parse_object_name(true)?;
            Some(self.parse_function(end_name)?)
        } else {
            None
        };
        Ok(TableVersion::Changes { changes, at, end })
    }

    /// Parses MySQL's JSON_TABLE column definition.
    /// For example: `id INT EXISTS PATH '$' DEFAULT '0' ON EMPTY ERROR ON ERROR`
    pub fn parse_json_table_column_def(&mut self) -> Result<JsonTableColumn, ParserError> {
        if self.parse_keyword(Keyword::NESTED) {
            let _has_path_keyword = self.parse_keyword(Keyword::PATH);
            let path = self.parse_value()?;
            self.expect_keyword_is(Keyword::COLUMNS)?;
            let columns = self.parse_parenthesized(|p| {
                p.parse_comma_separated(Self::parse_json_table_column_def)
            })?;
            return Ok(JsonTableColumn::Nested(JsonTableNestedColumn {
                path,
                columns,
            }));
        }
        let name = self.parse_identifier()?;
        if self.parse_keyword(Keyword::FOR) {
            self.expect_keyword_is(Keyword::ORDINALITY)?;
            return Ok(JsonTableColumn::ForOrdinality(name));
        }
        let r#type = self.parse_data_type()?;
        let exists = self.parse_keyword(Keyword::EXISTS);
        self.expect_keyword_is(Keyword::PATH)?;
        let path = self.parse_value()?;
        let mut on_empty = None;
        let mut on_error = None;
        while let Some(error_handling) = self.parse_json_table_column_error_handling()? {
            if self.parse_keyword(Keyword::EMPTY) {
                on_empty = Some(error_handling);
            } else {
                self.expect_keyword_is(Keyword::ERROR)?;
                on_error = Some(error_handling);
            }
        }
        Ok(JsonTableColumn::Named(JsonTableNamedColumn {
            name,
            r#type,
            path,
            exists,
            on_empty,
            on_error,
        }))
    }

    /// Parses MSSQL's `OPENJSON WITH` column definition.
    ///
    /// ```sql
    /// colName type [ column_path ] [ AS JSON ]
    /// ```
    ///
    /// Reference: <https://learn.microsoft.com/en-us/sql/t-sql/functions/openjson-transact-sql?view=sql-server-ver16#syntax>
    pub fn parse_openjson_table_column_def(&mut self) -> Result<OpenJsonTableColumn, ParserError> {
        let name = self.parse_identifier()?;
        let r#type = self.parse_data_type()?;
        let path = if let Token::SingleQuotedString(path) = self.peek_token().token {
            self.next_token();
            Some(path)
        } else {
            None
        };
        let as_json = self.parse_keyword(Keyword::AS);
        if as_json {
            self.expect_keyword_is(Keyword::JSON)?;
        }
        Ok(OpenJsonTableColumn {
            name,
            r#type,
            path,
            as_json,
        })
    }

    fn parse_json_table_column_error_handling(
        &mut self,
    ) -> Result<Option<JsonTableColumnErrorHandling>, ParserError> {
        let res = if self.parse_keyword(Keyword::NULL) {
            JsonTableColumnErrorHandling::Null
        } else if self.parse_keyword(Keyword::ERROR) {
            JsonTableColumnErrorHandling::Error
        } else if self.parse_keyword(Keyword::DEFAULT) {
            JsonTableColumnErrorHandling::Default(self.parse_value()?)
        } else {
            return Ok(None);
        };
        self.expect_keyword_is(Keyword::ON)?;
        Ok(Some(res))
    }

    /// Parse a derived table factor (a parenthesized subquery), handling optional LATERAL.
    pub fn parse_derived_table_factor(
        &mut self,
        lateral: IsLateral,
    ) -> Result<TableFactor, ParserError> {
        let subquery = self.parse_query()?;
        self.expect_token(&Token::RParen)?;
        let alias = self.maybe_parse_table_alias()?;

        // Parse optional SAMPLE clause after alias
        let sample = self
            .maybe_parse_table_sample()?
            .map(TableSampleKind::AfterTableAlias);

        Ok(TableFactor::Derived {
            lateral: match lateral {
                Lateral => true,
                NotLateral => false,
            },
            subquery,
            alias,
            sample,
        })
    }

    /// Parses an expression with an optional alias
    ///
    /// Examples:
    ///
    /// ```sql
    /// SUM(price) AS total_price
    /// ```
    /// ```sql
    /// SUM(price)
    /// ```
    ///
    /// Example
    /// ```
    /// # use sqlparser::parser::{Parser, ParserError};
    /// # use sqlparser::dialect::GenericDialect;
    /// # fn main() ->Result<(), ParserError> {
    /// let sql = r#"SUM("a") as "b""#;
    /// let mut parser = Parser::new(&GenericDialect).try_with_sql(sql)?;
    /// let expr_with_alias = parser.parse_expr_with_alias()?;
    /// assert_eq!(Some("b".to_string()), expr_with_alias.alias.map(|x|x.value));
    /// # Ok(())
    /// # }
    pub fn parse_expr_with_alias(&mut self) -> Result<ExprWithAlias, ParserError> {
        let expr = self.parse_expr()?;
        let alias = if self.parse_keyword(Keyword::AS) {
            Some(self.parse_identifier()?)
        } else {
            None
        };

        Ok(ExprWithAlias { expr, alias })
    }

    /// Parse an expression followed by an optional alias; Unlike
    /// [Self::parse_expr_with_alias] the "AS" keyword between the expression
    /// and the alias is optional.
    fn parse_expr_with_alias_optional_as_keyword(&mut self) -> Result<ExprWithAlias, ParserError> {
        let expr = self.parse_expr()?;
        let alias = self.parse_identifier_optional_alias()?;
        Ok(ExprWithAlias { expr, alias })
    }

    /// Parses a plain function call with an optional alias for the `PIVOT` clause
    fn parse_pivot_aggregate_function(&mut self) -> Result<ExprWithAlias, ParserError> {
        let function_name = match self.next_token().token {
            Token::Word(w) => Ok(w.value),
            _ => self.expected_ref("a function identifier", self.peek_token_ref()),
        }?;
        let expr = self.parse_function(ObjectName::from(vec![Ident::new(function_name)]))?;
        let alias = {
            fn validator(explicit: bool, kw: &Keyword, parser: &mut Parser) -> bool {
                // ~ for a PIVOT aggregate function the alias must not be a "FOR"; in any dialect
                kw != &Keyword::FOR && parser.dialect.is_select_item_alias(explicit, kw, parser)
            }
            self.parse_optional_alias_inner(None, validator)?
        };
        Ok(ExprWithAlias { expr, alias })
    }

    /// Parse a PIVOT table factor (ClickHouse/Oracle style pivot), returning a TableFactor.
    pub fn parse_pivot_table_factor(
        &mut self,
        table: TableFactor,
    ) -> Result<TableFactor, ParserError> {
        self.expect_token(&Token::LParen)?;
        let aggregate_functions =
            self.parse_comma_separated(Self::parse_pivot_aggregate_function)?;
        self.expect_keyword_is(Keyword::FOR)?;
        let value_column = if self.peek_token_ref().token == Token::LParen {
            self.parse_parenthesized_column_list_inner(Mandatory, false, |p| {
                p.parse_subexpr(self.dialect.prec_value(Precedence::Between))
            })?
        } else {
            vec![self.parse_subexpr(self.dialect.prec_value(Precedence::Between))?]
        };
        self.expect_keyword_is(Keyword::IN)?;

        self.expect_token(&Token::LParen)?;
        let value_source = if self.parse_keyword(Keyword::ANY) {
            let order_by = if self.parse_keywords(&[Keyword::ORDER, Keyword::BY]) {
                self.parse_comma_separated(Parser::parse_order_by_expr)?
            } else {
                vec![]
            };
            PivotValueSource::Any(order_by)
        } else if self.peek_sub_query() {
            PivotValueSource::Subquery(self.parse_query()?)
        } else {
            PivotValueSource::List(
                self.parse_comma_separated(Self::parse_expr_with_alias_optional_as_keyword)?,
            )
        };
        self.expect_token(&Token::RParen)?;

        let default_on_null =
            if self.parse_keywords(&[Keyword::DEFAULT, Keyword::ON, Keyword::NULL]) {
                self.expect_token(&Token::LParen)?;
                let expr = self.parse_expr()?;
                self.expect_token(&Token::RParen)?;
                Some(expr)
            } else {
                None
            };

        self.expect_token(&Token::RParen)?;
        let alias = self.maybe_parse_table_alias()?;
        Ok(TableFactor::Pivot {
            table: Box::new(table),
            aggregate_functions,
            value_column,
            value_source,
            default_on_null,
            alias,
        })
    }

    /// Parse an UNPIVOT table factor, returning a TableFactor.
    pub fn parse_unpivot_table_factor(
        &mut self,
        table: TableFactor,
    ) -> Result<TableFactor, ParserError> {
        let null_inclusion = if self.parse_keyword(Keyword::INCLUDE) {
            self.expect_keyword_is(Keyword::NULLS)?;
            Some(NullInclusion::IncludeNulls)
        } else if self.parse_keyword(Keyword::EXCLUDE) {
            self.expect_keyword_is(Keyword::NULLS)?;
            Some(NullInclusion::ExcludeNulls)
        } else {
            None
        };
        self.expect_token(&Token::LParen)?;
        let value = self.parse_expr()?;
        self.expect_keyword_is(Keyword::FOR)?;
        let name = self.parse_identifier()?;
        self.expect_keyword_is(Keyword::IN)?;
        let columns = self.parse_parenthesized_column_list_inner(Mandatory, false, |p| {
            p.parse_expr_with_alias()
        })?;
        self.expect_token(&Token::RParen)?;
        let alias = self.maybe_parse_table_alias()?;
        Ok(TableFactor::Unpivot {
            table: Box::new(table),
            value,
            null_inclusion,
            name,
            columns,
            alias,
        })
    }

    /// Parse 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)?;
            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 (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 {
            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()?;

            let table_alias = if self.dialect.supports_insert_table_alias()
                && !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 (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()?;
                    // 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()
                };

                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,
                partitioned,
                columns,
                after_columns,
                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 ...`
    fn peek_subquery_start(&mut self) -> bool {
        matches!(
            self.peek_tokens_ref(),
            [
                TokenWithSpan {
                    token: Token::LParen,
                    ..
                },
                TokenWithSpan {
                    token: Token::Word(Word {
                        keyword: Keyword::SELECT,
                        ..
                    }),
                    ..
                },
            ]
        )
    }

    /// 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 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 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
        };
        Ok(Update {
            update_token: update_token.into(),
            optimizer_hints,
            table,
            assignments,
            from,
            selection,
            returning,
            output,
            or,
            order_by,
            limit,
        }
        .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()?;
        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> {
        let arg = if self.dialect.supports_named_fn_args_with_expr_name() {
            self.maybe_parse(|p| {
                let name = p.parse_expr()?;
                let operator = p.parse_function_named_arg_operator()?;
                let arg = p.parse_wildcard_expr()?.into();
                Ok(FunctionArg::ExprNamed {
                    name,
                    arg,
                    operator,
                })
            })?
        } else {
            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: FunctionArgExpr = match wildcard_expr {
            Expr::Wildcard(ref token) if self.dialect.supports_select_wildcard_exclude() => {
                // Support `* EXCLUDE(col1, col2, ...)` inside function calls (e.g. Snowflake's
                // `HASH(* EXCLUDE(col))`).  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(),
        };
        Ok(FunctionArg::Unnamed(arg_expr))
    }

    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.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(_)) =>
            {
                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() {
            if self.parse_keyword(Keyword::AS) {
                Some(self.parse_identifier()?)
            } else {
                None
            }
        } 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 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 = 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_options(&mut self) -> Result<OrderByOptions, ParserError> {
        let asc = self.parse_asc_desc();

        let nulls_first = if self.parse_keywords(&[Keyword::NULLS, Keyword::FIRST]) {
            Some(true)
        } else if self.parse_keywords(&[Keyword::NULLS, Keyword::LAST]) {
            Some(false)
        } else {
            None
        };

        Ok(OrderByOptions { asc, 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;
            }

            parser.expect_token(&Token::LParen)?;
            if allow_empty && parser.peek_token().token == Token::RParen {
                parser.next_token();
                Ok(vec![])
            } else {
                let exprs = parser.parse_comma_separated(Parser::parse_expr)?;
                parser.expect_token(&Token::RParen)?;
                Ok(exprs)
            }
        })?;
        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 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 name = self.parse_object_name(false)?;

        Ok(SelectInto {
            temporary,
            unlogged,
            table,
            name,
        })
    }

    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 mut options = None;
        if self.parse_keyword(Keyword::OPTIONS) {
            self.expect_token(&Token::LParen)?;
            options = Some(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(Statement::CreateServer(CreateServerStatement {
            name,
            if_not_exists: ine,
            server_type,
            version,
            foreign_data_wrapper,
            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 dialect_of!(self is MySqlDialect | GenericDialect) {
            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 | Token::SemiColon => 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 });
        }

        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.
    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 {
                        asc: 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 ast = Parser::parse_sql(&GenericDialect, sql);
        assert_eq!(
            ast,
            Err(ParserError::ParserError(
                "Expected: [NOT] NULL | TRUE | FALSE | DISTINCT | [form] NORMALIZED FROM after IS, found: a at Line: 1, Column: 16"
                    .to_string()
            ))
        );
    }

    #[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!(Parser::parse_sql(&GenericDialect {}, sql).is_err());
    }

    #[test]
    fn test_replace_into_set_placeholder() {
        let sql = "REPLACE INTO t SET ?";

        assert!(Parser::parse_sql(&GenericDialect {}, sql).is_err());
    }

    #[test]
    fn test_replace_incomplete() {
        let sql = r#"REPLACE"#;

        assert!(Parser::parse_sql(&MySqlDialect {}, sql).is_err());
    }

    #[test]
    fn test_placeholder_invalid_whitespace() {
        for w in ["  ", "/*invalid*/"] {
            let sql = format!("\nSELECT\n  :{w}fooBar");
            assert!(Parser::parse_sql(&GenericDialect, &sql).is_err());
        }
    }
}
