use itertools::Itertools;
use sqruff_lib_core::dialects::Dialect;
use sqruff_lib_core::dialects::init::DialectKind;
use sqruff_lib_core::dialects::syntax::SyntaxKind;
use sqruff_lib_core::helpers::{Config, ToMatchable};
use sqruff_lib_core::parser::grammar::anyof::{
    AnyNumberOf, any_set_of, one_of, optionally_bracketed,
};
use sqruff_lib_core::parser::grammar::delimited::Delimited;
use sqruff_lib_core::parser::grammar::sequence::{Bracketed, Sequence};
use sqruff_lib_core::parser::grammar::{Anything, Nothing, Ref};
use sqruff_lib_core::parser::lexer::Matcher;
use sqruff_lib_core::parser::matchable::MatchableTrait;
use sqruff_lib_core::parser::node_matcher::NodeMatcher;
use sqruff_lib_core::parser::parsers::RegexParser;
use sqruff_lib_core::parser::segments::generator::SegmentGenerator;
use sqruff_lib_core::parser::segments::meta::MetaSegment;
use sqruff_lib_core::parser::types::ParseMode;

use crate::redshift_keywords::{REDSHIFT_RESERVED_KEYWORDS, REDSHIFT_UNRESERVED_KEYWORDS};
use sqruff_lib_core::dialects::init::DialectConfig;
use sqruff_lib_core::value::Value;

sqruff_lib_core::dialect_config!(RedshiftDialectConfig {});

pub fn dialect(config: Option<&Value>) -> Dialect {
    // Parse and validate dialect configuration, falling back to defaults on failure
    let _dialect_config: RedshiftDialectConfig = config
        .map(RedshiftDialectConfig::from_value)
        .unwrap_or_default();

    raw_dialect().config(|this| this.expand())
}

pub fn raw_dialect() -> Dialect {
    let postgres_dialect = super::postgres::raw_dialect();
    let ansi_dialect = super::ansi::raw_dialect();
    let mut redshift_dialect = postgres_dialect.clone();
    redshift_dialect.name = DialectKind::Redshift;

    redshift_dialect.sets_mut("unreserved_keywords").clear();
    redshift_dialect.update_keywords_set_from_multiline_string(
        "unreserved_keywords",
        REDSHIFT_UNRESERVED_KEYWORDS,
    );
    redshift_dialect.sets_mut("reserved_keywords").clear();
    redshift_dialect
        .update_keywords_set_from_multiline_string("reserved_keywords", REDSHIFT_RESERVED_KEYWORDS);
    redshift_dialect.sets_mut("bare_functions").clear();
    redshift_dialect.sets_mut("bare_functions").extend([
        "current_date",
        "sysdate",
        "current_time",
        "current_timestamp",
        "user",
        "current_user",
        "current_aws_account",
        "current_namespace",
        "current_user_id",
    ]);
    redshift_dialect
        .sets_mut("date_part_function_name")
        .extend(["DATEADD", "DATEDIFF", "EXTRACT", "DATE_PART"]);
    redshift_dialect.sets_mut("datetime_units").extend([
        "MILLENNIUM",
        "MILLENNIA",
        "MIL",
        "MILS",
        "CENTURY",
        "CENTURIES",
        "C",
        "CENT",
        "CENTS",
        "DECADE",
        "DECADES",
        "DEC",
        "DECS",
        "EPOCH",
        "YEAR",
        "YEARS",
        "Y",
        "YR",
        "YRS",
        "QUARTER",
        "QUARTERS",
        "QTR",
        "QTRS",
        "MONTH",
        "MONTHS",
        "MON",
        "MONS",
        "WEEK",
        "WEEKS",
        "W",
        "DAYOFWEEK",
        "DOW",
        "DW",
        "WEEKDAY",
        "DAYOFYEAR",
        "DOY",
        "DY",
        "YEARDAY",
        "DAY",
        "DAYS",
        "D",
        "HOUR",
        "HOURS",
        "H",
        "HR",
        "HRS",
        "MINUTE",
        "MINUTES",
        "M",
        "MIN",
        "MINS",
        "SECOND",
        "SECONDS",
        "S",
        "SEC",
        "SECS",
        "MILLISECOND",
        "MILLISECONDS",
        "MS",
        "MSEC",
        "MSECS",
        "MSECOND",
        "MSECONDS",
        "MILLISEC",
        "MILLISECS",
        "MILLISECON",
        "MICROSECOND",
        "MICROSECONDS",
        "MICROSEC",
        "MICROSECS",
        "MICROSECOND",
        "USECOND",
        "USECONDS",
        "US",
        "USEC",
        "USECS",
        "TIMEZONE",
        "TIMEZONE_HOUR",
        "TIMEZONE_MINUTE",
    ]);
    redshift_dialect.add([
        (
            "WellKnownTextGeometrySegment".into(),
            Nothing::new().to_matchable().into(),
        ),
        (
            "JoinLikeClauseGrammar".into(),
            Sequence::new(vec![
                any_set_of(vec![
                    Ref::new("FromPivotExpressionSegment").to_matchable(),
                    Ref::new("FromUnpivotExpressionSegment").to_matchable(),
                ])
                .config(|this| {
                    this.min_times = 1;
                })
                .to_matchable(),
                Ref::new("AliasExpressionSegment").optional().to_matchable(),
            ])
            .to_matchable()
            .into(),
        ),
        (
            "NakedIdentifierSegment".into(),
            SegmentGenerator::new(|dialect| {
                // Generate the anti template from the set of reserved keywords
                let reserved_keywords = dialect.sets("reserved_keywords");
                let pattern = reserved_keywords.iter().join("|");
                let anti_template = format!("^({pattern})$");

                RegexParser::new(
                    "#?([A-Z_]+|[0-9]+[A-Z_$])[A-Z0-9_$]*",
                    SyntaxKind::NakedIdentifier,
                )
                .anti_template(&anti_template)
                .to_matchable()
            })
            .into(),
        ),
    ]);

    redshift_dialect.patch_lexer_matchers(vec![Matcher::regex(
        "word",
        r"#?[0-9a-zA-Z_]+[0-9a-zA-Z_$]*",
        SyntaxKind::Word,
    )]);

    redshift_dialect.add([
        (
            "CompressionTypeGrammar".into(),
            one_of(vec![
                Ref::keyword("BZIP2").to_matchable(),
                Ref::keyword("GZIP").to_matchable(),
                Ref::keyword("LZOP").to_matchable(),
                Ref::keyword("ZSTD").to_matchable(),
            ])
            .to_matchable()
            .into(),
        ),
        (
            "ArgModeGrammar".into(),
            one_of(vec![
                Ref::keyword("IN").to_matchable(),
                Ref::keyword("OUT").to_matchable(),
                Ref::keyword("INOUT").to_matchable(),
            ])
            .to_matchable()
            .into(),
        ),
        (
            "ColumnEncodingGrammar".into(),
            one_of(vec![
                Ref::keyword("RAW").to_matchable(),
                Ref::keyword("AZ64").to_matchable(),
                Ref::keyword("BYTEDICT").to_matchable(),
                Ref::keyword("DELTA").to_matchable(),
                Ref::keyword("DELTA32K").to_matchable(),
                Ref::keyword("LZO").to_matchable(),
                Ref::keyword("MOSTLY8").to_matchable(),
                Ref::keyword("MOSTLY16").to_matchable(),
                Ref::keyword("MOSTLY32").to_matchable(),
                Ref::keyword("RUNLENGTH").to_matchable(),
                Ref::keyword("TEXT255").to_matchable(),
                Ref::keyword("TEXT32K").to_matchable(),
                Ref::keyword("ZSTD").to_matchable(),
            ])
            .to_matchable()
            .into(),
        ),
        (
            "QuotaGrammar".into(),
            Sequence::new(vec![
                Ref::keyword("QUOTA").to_matchable(),
                one_of(vec![
                    Sequence::new(vec![
                        Ref::new("NumericLiteralSegment").to_matchable(),
                        one_of(vec![
                            Ref::keyword("MB").to_matchable(),
                            Ref::keyword("GB").to_matchable(),
                            Ref::keyword("TB").to_matchable(),
                        ])
                        .to_matchable(),
                    ])
                    .to_matchable(),
                    Ref::keyword("UNLIMITED").to_matchable(),
                ])
                .to_matchable(),
            ])
            .to_matchable()
            .into(),
        ),
    ]);

    redshift_dialect.add([
        (
            "FromUnpivotExpressionSegment".into(),
            NodeMatcher::new(SyntaxKind::FromUnpivotExpression, |_| {
                Sequence::new(vec![
                    Ref::keyword("UNPIVOT").to_matchable(),
                    Sequence::new(vec![
                        one_of(vec![
                            Ref::keyword("INCLUDE").to_matchable(),
                            Ref::keyword("EXCLUDE").to_matchable(),
                        ])
                        .to_matchable(),
                        Ref::keyword("NULLS").to_matchable(),
                    ])
                    .config(|this| {
                        this.optional();
                    })
                    .to_matchable(),
                    Bracketed::new(vec![
                        Sequence::new(vec![
                            Ref::new("ColumnReferenceSegment").to_matchable(),
                            Ref::keyword("FOR").to_matchable(),
                            Ref::new("ColumnReferenceSegment").to_matchable(),
                            Ref::keyword("IN").to_matchable(),
                            Bracketed::new(vec![
                                Delimited::new(vec![
                                    Sequence::new(vec![
                                        Ref::new("ColumnReferenceSegment").to_matchable(),
                                        Ref::new("AliasExpressionSegment")
                                            .optional()
                                            .to_matchable(),
                                    ])
                                    .to_matchable(),
                                ])
                                .to_matchable(),
                            ])
                            .to_matchable(),
                        ])
                        .to_matchable(),
                    ])
                    .to_matchable(),
                ])
                .to_matchable()
            })
            .to_matchable()
            .into(),
        ),
        (
            "FromPivotExpressionSegment".into(),
            NodeMatcher::new(SyntaxKind::FromPivotExpression, |_| {
                Sequence::new(vec![
                    Ref::keyword("PIVOT").to_matchable(),
                    Bracketed::new(vec![
                        Sequence::new(vec![
                            optionally_bracketed(vec![Ref::new("FunctionSegment").to_matchable()])
                                .to_matchable(),
                            Ref::new("AliasExpressionSegment").optional().to_matchable(),
                            Ref::keyword("FOR").to_matchable(),
                            Ref::new("ColumnReferenceSegment").to_matchable(),
                            Ref::keyword("IN").to_matchable(),
                            Bracketed::new(vec![
                                Delimited::new(vec![
                                    Sequence::new(vec![
                                        Ref::new("ExpressionSegment").to_matchable(),
                                        Ref::new("AliasExpressionSegment")
                                            .optional()
                                            .to_matchable(),
                                    ])
                                    .to_matchable(),
                                ])
                                .to_matchable(),
                            ])
                            .to_matchable(),
                        ])
                        .to_matchable(),
                    ])
                    .to_matchable(),
                ])
                .to_matchable()
            })
            .to_matchable()
            .into(),
        ),
        (
            "DateTimeTypeIdentifier".into(),
            NodeMatcher::new(SyntaxKind::DatetimeTypeIdentifier, |_| {
                one_of(vec![
                    Ref::keyword("DATE").to_matchable(),
                    Ref::keyword("DATETIME").to_matchable(),
                    Sequence::new(vec![
                        one_of(vec![
                            Ref::keyword("TIME").to_matchable(),
                            Ref::keyword("TIMESTAMP").to_matchable(),
                        ])
                        .to_matchable(),
                        Sequence::new(vec![
                            one_of(vec![
                                Ref::keyword("WITH").to_matchable(),
                                Ref::keyword("WITHOUT").to_matchable(),
                            ])
                            .to_matchable(),
                            Ref::keyword("TIME").to_matchable(),
                            Ref::keyword("ZONE").to_matchable(),
                        ])
                        .config(|this| {
                            this.optional();
                        })
                        .to_matchable(),
                    ])
                    .to_matchable(),
                    one_of(vec![
                        Ref::keyword("TIMETZ").to_matchable(),
                        Ref::keyword("TIMESTAMPTZ").to_matchable(),
                    ])
                    .to_matchable(),
                ])
                .to_matchable()
            })
            .to_matchable()
            .into(),
        ),
    ]);
    redshift_dialect.replace_grammar(
        "BracketedArguments",
        Bracketed::new(vec![
            Delimited::new(vec![
                one_of(vec![
                    Ref::new("LiteralGrammar").to_matchable(),
                    Ref::keyword("MAX").to_matchable(),
                ])
                .to_matchable(),
            ])
            .config(|this| {
                this.optional();
            })
            .to_matchable(),
        ])
        .to_matchable(),
    );

    redshift_dialect.add([
        (
            "DatatypeSegment".into(),
            NodeMatcher::new(SyntaxKind::DataType, |_| {
                one_of(vec![
                    Ref::keyword("SMALLINT").to_matchable(),
                    Ref::keyword("INT2").to_matchable(),
                    Ref::keyword("INTEGER").to_matchable(),
                    Ref::keyword("INT").to_matchable(),
                    Ref::keyword("INT4").to_matchable(),
                    Ref::keyword("BIGINT").to_matchable(),
                    Ref::keyword("INT8").to_matchable(),
                    Ref::keyword("REAL").to_matchable(),
                    Ref::keyword("FLOAT4").to_matchable(),
                    Sequence::new(vec![
                        Ref::keyword("DOUBLE").to_matchable(),
                        Ref::keyword("PRECISION").to_matchable(),
                    ])
                    .to_matchable(),
                    Ref::keyword("FLOAT8").to_matchable(),
                    Ref::keyword("FLOAT").to_matchable(),
                    Sequence::new(vec![
                        one_of(vec![
                            Ref::keyword("DECIMAL").to_matchable(),
                            Ref::keyword("NUMERIC").to_matchable(),
                        ])
                        .to_matchable(),
                        Ref::new("BracketedArguments").optional().to_matchable(),
                    ])
                    .to_matchable(),
                    one_of(vec![
                        Sequence::new(vec![
                            one_of(vec![
                                Ref::keyword("CHAR").to_matchable(),
                                Ref::keyword("CHARACTER").to_matchable(),
                                Ref::keyword("NCHAR").to_matchable(),
                                Ref::keyword("VARCHAR").to_matchable(),
                                Sequence::new(vec![
                                    Ref::keyword("CHARACTER").to_matchable(),
                                    Ref::keyword("VARYING").to_matchable(),
                                ])
                                .to_matchable(),
                                Ref::keyword("NVARCHAR").to_matchable(),
                            ])
                            .to_matchable(),
                            Ref::new("BracketedArguments").optional().to_matchable(),
                        ])
                        .to_matchable(),
                        Ref::keyword("BPCHAR").to_matchable(),
                        Ref::keyword("TEXT").to_matchable(),
                    ])
                    .to_matchable(),
                    Ref::new("DateTimeTypeIdentifier").to_matchable(),
                    Ref::keyword("INTERVAL").to_matchable(),
                    one_of(vec![
                        Ref::keyword("BOOLEAN").to_matchable(),
                        Ref::keyword("BOOL").to_matchable(),
                    ])
                    .to_matchable(),
                    Ref::keyword("HLLSKETCH").to_matchable(),
                    Ref::keyword("SUPER").to_matchable(),
                    Ref::keyword("GEOMETRY").to_matchable(),
                    Ref::keyword("GEOGRAPHY").to_matchable(),
                    Sequence::new(vec![
                        one_of(vec![
                            Ref::keyword("VARBYTE").to_matchable(),
                            Ref::keyword("VARBINARY").to_matchable(),
                            Sequence::new(vec![
                                Ref::keyword("BINARY").to_matchable(),
                                Ref::keyword("VARYING").to_matchable(),
                            ])
                            .to_matchable(),
                        ])
                        .to_matchable(),
                        Ref::new("BracketedArguments").optional().to_matchable(),
                    ])
                    .to_matchable(),
                    Ref::keyword("ANYELEMENT").to_matchable(),
                ])
                .to_matchable()
            })
            .to_matchable()
            .into(),
        ),
        (
            "DataFormatSegment".into(),
            NodeMatcher::new(SyntaxKind::DataFormatSegment, |_| {
                Sequence::new(vec![
                    Sequence::new(vec![
                        Ref::keyword("FORMAT").to_matchable(),
                        Ref::keyword("AS").optional().to_matchable(),
                    ])
                    .config(|this| {
                        this.optional();
                    })
                    .to_matchable(),
                    one_of(vec![
                        Sequence::new(vec![
                            Ref::keyword("CSV").to_matchable(),
                            Sequence::new(vec![
                                Ref::keyword("QUOTE").to_matchable(),
                                Ref::keyword("AS").optional().to_matchable(),
                                Ref::new("QuotedLiteralSegment").to_matchable(),
                            ])
                            .config(|this| {
                                this.optional();
                            })
                            .to_matchable(),
                        ])
                        .to_matchable(),
                        Sequence::new(vec![
                            Ref::keyword("SHAPEFILE").to_matchable(),
                            Sequence::new(vec![
                                Ref::keyword("SIMPLIFY").to_matchable(),
                                Ref::keyword("AUTO").optional().to_matchable(),
                                Ref::new("NumericLiteralSegment").optional().to_matchable(),
                            ])
                            .config(|this| {
                                this.optional();
                            })
                            .to_matchable(),
                        ])
                        .to_matchable(),
                        Sequence::new(vec![
                            one_of(vec![
                                Ref::keyword("AVRO").to_matchable(),
                                Ref::keyword("JSON").to_matchable(),
                            ])
                            .to_matchable(),
                            Sequence::new(vec![
                                Ref::keyword("AS").optional().to_matchable(),
                                Ref::new("QuotedLiteralSegment").to_matchable(),
                            ])
                            .config(|this| {
                                this.optional();
                            })
                            .to_matchable(),
                        ])
                        .to_matchable(),
                        Ref::keyword("PARQUET").to_matchable(),
                        Ref::keyword("ORC").to_matchable(),
                        Ref::keyword("RCFILE").to_matchable(),
                        Ref::keyword("SEQUENCEFILE").to_matchable(),
                    ])
                    .to_matchable(),
                ])
                .to_matchable()
            })
            .to_matchable()
            .into(),
        ),
        (
            "AuthorizationSegment".into(),
            NodeMatcher::new(SyntaxKind::AuthorizationSegment, |_| {
                any_set_of(vec![
                    one_of(vec![
                        Sequence::new(vec![
                            Ref::keyword("IAM_ROLE").to_matchable(),
                            one_of(vec![
                                Ref::keyword("DEFAULT").to_matchable(),
                                Ref::new("QuotedLiteralSegment").to_matchable(),
                            ])
                            .to_matchable(),
                        ])
                        .to_matchable(),
                        Sequence::new(vec![
                            Ref::keyword("WITH").optional().to_matchable(),
                            Ref::keyword("CREDENTIALS").to_matchable(),
                            Ref::keyword("AS").optional().to_matchable(),
                            Ref::new("QuotedLiteralSegment").to_matchable(),
                        ])
                        .to_matchable(),
                        Sequence::new(vec![
                            Ref::keyword("ACCESS_KEY_ID").to_matchable(),
                            Ref::new("QuotedLiteralSegment").to_matchable(),
                            Ref::keyword("SECRET_ACCESS_KEY").to_matchable(),
                            Ref::new("QuotedLiteralSegment").to_matchable(),
                            Sequence::new(vec![
                                Ref::keyword("SESSION_TOKEN").to_matchable(),
                                Ref::new("QuotedLiteralSegment").to_matchable(),
                            ])
                            .config(|this| {
                                this.optional();
                            })
                            .to_matchable(),
                        ])
                        .to_matchable(),
                    ])
                    .to_matchable(),
                    Sequence::new(vec![
                        Ref::keyword("KMS_KEY_ID").to_matchable(),
                        Ref::new("QuotedLiteralSegment").to_matchable(),
                    ])
                    .config(|this| {
                        this.optional();
                    })
                    .to_matchable(),
                    Sequence::new(vec![
                        Ref::keyword("MASTER_SYMMETRIC_KEY").to_matchable(),
                        Ref::new("QuotedLiteralSegment").to_matchable(),
                    ])
                    .config(|this| {
                        this.optional();
                    })
                    .to_matchable(),
                ])
                .to_matchable()
            })
            .to_matchable()
            .into(),
        ),
        (
            "ColumnAttributeSegment".into(),
            NodeMatcher::new(SyntaxKind::ColumnAttributeSegment, |_| {
                any_set_of(vec![
                    Sequence::new(vec![
                        Ref::keyword("DEFAULT").to_matchable(),
                        Ref::new("ExpressionSegment").to_matchable(),
                    ])
                    .to_matchable(),
                    Sequence::new(vec![
                        Ref::keyword("IDENTITY").to_matchable(),
                        Bracketed::new(vec![
                            Delimited::new(vec![Ref::new("NumericLiteralSegment").to_matchable()])
                                .to_matchable(),
                        ])
                        .config(|this| {
                            this.optional();
                        })
                        .to_matchable(),
                    ])
                    .to_matchable(),
                    Sequence::new(vec![
                        Ref::keyword("GENERATED").to_matchable(),
                        Ref::keyword("BY").to_matchable(),
                        Ref::keyword("DEFAULT").to_matchable(),
                        Ref::keyword("AS").to_matchable(),
                        Ref::keyword("IDENTITY").to_matchable(),
                        Bracketed::new(vec![
                            Delimited::new(vec![Ref::new("NumericLiteralSegment").to_matchable()])
                                .to_matchable(),
                        ])
                        .config(|this| {
                            this.optional();
                        })
                        .to_matchable(),
                    ])
                    .to_matchable(),
                    Sequence::new(vec![
                        Ref::keyword("ENCODE").to_matchable(),
                        Ref::new("ColumnEncodingGrammar").to_matchable(),
                    ])
                    .to_matchable(),
                    Ref::keyword("DISTKEY").to_matchable(),
                    Ref::keyword("SORTKEY").to_matchable(),
                    Sequence::new(vec![
                        Ref::keyword("COLLATE").to_matchable(),
                        one_of(vec![
                            Ref::keyword("CASE_SENSITIVE").to_matchable(),
                            Ref::keyword("CASE_INSENSITIVE").to_matchable(),
                        ])
                        .to_matchable(),
                    ])
                    .to_matchable(),
                ])
                .to_matchable()
            })
            .to_matchable()
            .into(),
        ),
        (
            "ColumnConstraintSegment".into(),
            NodeMatcher::new(SyntaxKind::ColumnConstraintSegment, |_| {
                any_set_of(vec![
                    one_of(vec![
                        Sequence::new(vec![
                            Ref::keyword("NOT").to_matchable(),
                            Ref::keyword("NULL").to_matchable(),
                        ])
                        .to_matchable(),
                        Ref::keyword("NULL").to_matchable(),
                    ])
                    .to_matchable(),
                    one_of(vec![
                        Ref::keyword("UNIQUE").to_matchable(),
                        Ref::new("PrimaryKeyGrammar").to_matchable(),
                    ])
                    .to_matchable(),
                    Sequence::new(vec![
                        Ref::keyword("REFERENCES").to_matchable(),
                        Ref::new("TableReferenceSegment").to_matchable(),
                        Bracketed::new(vec![Ref::new("ColumnReferenceSegment").to_matchable()])
                            .config(|this| {
                                this.optional();
                            })
                            .to_matchable(),
                    ])
                    .to_matchable(),
                ])
                .to_matchable()
            })
            .to_matchable()
            .into(),
        ),
        (
            "AlterTableActionSegment".into(),
            NodeMatcher::new(SyntaxKind::AlterTableActionSegment, |_| {
                one_of(vec![
                    Sequence::new(vec![
                        Ref::keyword("ADD").to_matchable(),
                        Ref::new("TableConstraintSegment").to_matchable(),
                        Sequence::new(vec![
                            Ref::keyword("NOT").to_matchable(),
                            Ref::keyword("VALID").to_matchable(),
                        ])
                        .config(|this| {
                            this.optional();
                        })
                        .to_matchable(),
                    ])
                    .to_matchable(),
                    Sequence::new(vec![
                        Ref::keyword("VALIDATE").to_matchable(),
                        Ref::keyword("CONSTRAINT").to_matchable(),
                        Ref::new("ParameterNameSegment").to_matchable(),
                    ])
                    .to_matchable(),
                    Sequence::new(vec![
                        Ref::keyword("DROP").to_matchable(),
                        Ref::keyword("CONSTRAINT").to_matchable(),
                        Ref::new("ParameterNameSegment").to_matchable(),
                        Ref::new("DropBehaviorGrammar").optional().to_matchable(),
                    ])
                    .to_matchable(),
                    Sequence::new(vec![
                        Ref::keyword("OWNER").to_matchable(),
                        Ref::keyword("TO").to_matchable(),
                        one_of(vec![
                            one_of(vec![
                                Ref::new("ParameterNameSegment").to_matchable(),
                                Ref::new("QuotedIdentifierSegment").to_matchable(),
                            ])
                            .to_matchable(),
                        ])
                        .to_matchable(),
                    ])
                    .to_matchable(),
                    Sequence::new(vec![
                        Ref::keyword("RENAME").to_matchable(),
                        Ref::keyword("TO").to_matchable(),
                        one_of(vec![
                            one_of(vec![
                                Ref::new("ParameterNameSegment").to_matchable(),
                                Ref::new("QuotedIdentifierSegment").to_matchable(),
                            ])
                            .to_matchable(),
                        ])
                        .to_matchable(),
                    ])
                    .to_matchable(),
                    Sequence::new(vec![
                        Ref::keyword("RENAME").to_matchable(),
                        Ref::keyword("COLUMN").to_matchable(),
                        Ref::keyword("TO").to_matchable(),
                        one_of(vec![Ref::new("ColumnReferenceSegment").to_matchable()])
                            .to_matchable(),
                    ])
                    .to_matchable(),
                    Sequence::new(vec![
                        Ref::keyword("ALTER").to_matchable(),
                        Ref::keyword("COLUMN").optional().to_matchable(),
                        Ref::new("ColumnReferenceSegment").to_matchable(),
                        one_of(vec![
                            Sequence::new(vec![
                                Ref::keyword("TYPE").to_matchable(),
                                Ref::new("DatatypeSegment").to_matchable(),
                            ])
                            .to_matchable(),
                            Sequence::new(vec![
                                Ref::keyword("ENCODE").to_matchable(),
                                Delimited::new(vec![
                                    Ref::new("ColumnEncodingGrammar").to_matchable(),
                                ])
                                .to_matchable(),
                            ])
                            .to_matchable(),
                        ])
                        .to_matchable(),
                    ])
                    .to_matchable(),
                    Sequence::new(vec![
                        Ref::keyword("ALTER").to_matchable(),
                        Ref::keyword("DISTKEY").to_matchable(),
                        Ref::new("ColumnReferenceSegment").to_matchable(),
                    ])
                    .to_matchable(),
                    Sequence::new(vec![
                        Ref::keyword("ALTER").to_matchable(),
                        Ref::keyword("DISTSTYLE").to_matchable(),
                        one_of(vec![
                            Ref::keyword("ALL").to_matchable(),
                            Ref::keyword("EVEN").to_matchable(),
                            Sequence::new(vec![
                                Ref::keyword("KEY").to_matchable(),
                                Ref::keyword("DISTKEY").to_matchable(),
                                Ref::new("ColumnReferenceSegment").to_matchable(),
                            ])
                            .to_matchable(),
                            Ref::keyword("AUTO").to_matchable(),
                        ])
                        .to_matchable(),
                    ])
                    .to_matchable(),
                    Sequence::new(vec![
                        Ref::keyword("ALTER").to_matchable(),
                        Ref::keyword("COMPOUND").optional().to_matchable(),
                        Ref::keyword("SORTKEY").to_matchable(),
                        Bracketed::new(vec![
                            Delimited::new(vec![Ref::new("ColumnReferenceSegment").to_matchable()])
                                .to_matchable(),
                        ])
                        .to_matchable(),
                    ])
                    .to_matchable(),
                    Sequence::new(vec![
                        Ref::keyword("ALTER").to_matchable(),
                        Ref::keyword("SORTKEY").to_matchable(),
                        one_of(vec![
                            Ref::keyword("AUTO").to_matchable(),
                            Ref::keyword("NONE").to_matchable(),
                        ])
                        .to_matchable(),
                    ])
                    .to_matchable(),
                    Sequence::new(vec![
                        Ref::keyword("ALTER").to_matchable(),
                        Ref::keyword("ENCODE").to_matchable(),
                        Ref::keyword("AUTO").to_matchable(),
                    ])
                    .to_matchable(),
                    Sequence::new(vec![
                        Ref::keyword("ADD").to_matchable(),
                        Ref::keyword("COLUMN").optional().to_matchable(),
                        Ref::new("ColumnReferenceSegment").to_matchable(),
                        Ref::new("DatatypeSegment").to_matchable(),
                        Sequence::new(vec![
                            Ref::keyword("DEFAULT").to_matchable(),
                            Ref::new("ExpressionSegment").to_matchable(),
                        ])
                        .config(|this| {
                            this.optional();
                        })
                        .to_matchable(),
                        Sequence::new(vec![
                            Ref::keyword("COLLATE").to_matchable(),
                            Ref::new("CollationReferenceSegment").to_matchable(),
                        ])
                        .config(|this| {
                            this.optional();
                        })
                        .to_matchable(),
                        AnyNumberOf::new(vec![Ref::new("ColumnConstraintSegment").to_matchable()])
                            .to_matchable(),
                    ])
                    .to_matchable(),
                    Sequence::new(vec![
                        Ref::keyword("DROP").to_matchable(),
                        Ref::keyword("COLUMN").optional().to_matchable(),
                        Ref::new("ColumnReferenceSegment").to_matchable(),
                        Ref::new("DropBehaviorGrammar").optional().to_matchable(),
                    ])
                    .to_matchable(),
                ])
                .to_matchable()
            })
            .to_matchable()
            .into(),
        ),
        (
            "TableAttributeSegment".into(),
            NodeMatcher::new(SyntaxKind::TableConstraint, |_| {
                any_set_of(vec![
                    Sequence::new(vec![
                        Ref::keyword("DISTSTYLE").to_matchable(),
                        one_of(vec![
                            Ref::keyword("AUTO").to_matchable(),
                            Ref::keyword("EVEN").to_matchable(),
                            Ref::keyword("KEY").to_matchable(),
                            Ref::keyword("ALL").to_matchable(),
                        ])
                        .to_matchable(),
                    ])
                    .config(|this| {
                        this.optional();
                    })
                    .to_matchable(),
                    Sequence::new(vec![
                        Ref::keyword("DISTKEY").to_matchable(),
                        Bracketed::new(vec![Ref::new("ColumnReferenceSegment").to_matchable()])
                            .to_matchable(),
                    ])
                    .config(|this| {
                        this.optional();
                    })
                    .to_matchable(),
                    one_of(vec![
                        Sequence::new(vec![
                            one_of(vec![
                                Ref::keyword("COMPOUND").to_matchable(),
                                Ref::keyword("INTERLEAVED").to_matchable(),
                            ])
                            .config(|this| {
                                this.optional();
                            })
                            .to_matchable(),
                            Ref::keyword("SORTKEY").to_matchable(),
                            Bracketed::new(vec![
                                Delimited::new(vec![
                                    Ref::new("ColumnReferenceSegment").to_matchable(),
                                ])
                                .to_matchable(),
                            ])
                            .to_matchable(),
                        ])
                        .to_matchable(),
                        Sequence::new(vec![
                            Ref::keyword("SORTKEY").to_matchable(),
                            Ref::keyword("AUTO").to_matchable(),
                        ])
                        .to_matchable(),
                    ])
                    .config(|this| {
                        this.optional();
                    })
                    .to_matchable(),
                    Sequence::new(vec![
                        Ref::keyword("ENCODE").to_matchable(),
                        Ref::keyword("AUTO").to_matchable(),
                    ])
                    .config(|this| {
                        this.optional();
                    })
                    .to_matchable(),
                ])
                .to_matchable()
            })
            .to_matchable()
            .into(),
        ),
        (
            "TableConstraintSegment".into(),
            NodeMatcher::new(SyntaxKind::TableConstraint, |_| {
                Sequence::new(vec![
                    Sequence::new(vec![
                        Ref::keyword("CONSTRAINT").to_matchable(),
                        Ref::new("ObjectReferenceSegment").to_matchable(),
                    ])
                    .config(|this| {
                        this.optional();
                    })
                    .to_matchable(),
                    one_of(vec![
                        Sequence::new(vec![
                            Ref::keyword("UNIQUE").to_matchable(),
                            Bracketed::new(vec![
                                Delimited::new(vec![
                                    Ref::new("ColumnReferenceSegment").to_matchable(),
                                ])
                                .to_matchable(),
                            ])
                            .to_matchable(),
                        ])
                        .to_matchable(),
                        Sequence::new(vec![
                            Ref::keyword("PRIMARY").to_matchable(),
                            Ref::keyword("KEY").to_matchable(),
                            Bracketed::new(vec![
                                Delimited::new(vec![
                                    Ref::new("ColumnReferenceSegment").to_matchable(),
                                ])
                                .to_matchable(),
                            ])
                            .to_matchable(),
                        ])
                        .to_matchable(),
                        Sequence::new(vec![
                            Ref::keyword("FOREIGN").to_matchable(),
                            Ref::keyword("KEY").to_matchable(),
                            Bracketed::new(vec![
                                Delimited::new(vec![
                                    Ref::new("ColumnReferenceSegment").to_matchable(),
                                ])
                                .to_matchable(),
                            ])
                            .to_matchable(),
                            Ref::keyword("REFERENCES").to_matchable(),
                            Ref::new("TableReferenceSegment").to_matchable(),
                            Sequence::new(vec![
                                Bracketed::new(vec![
                                    Ref::new("ColumnReferenceSegment").to_matchable(),
                                ])
                                .to_matchable(),
                            ])
                            .to_matchable(),
                        ])
                        .to_matchable(),
                    ])
                    .to_matchable(),
                ])
                .to_matchable()
            })
            .to_matchable()
            .into(),
        ),
        (
            "LikeOptionSegment".into(),
            NodeMatcher::new(SyntaxKind::LikeOptionSegment, |_| {
                Sequence::new(vec![
                    one_of(vec![
                        Ref::keyword("INCLUDING").to_matchable(),
                        Ref::keyword("EXCLUDING").to_matchable(),
                    ])
                    .to_matchable(),
                    Ref::keyword("DEFAULTS").to_matchable(),
                ])
                .to_matchable()
            })
            .to_matchable()
            .into(),
        ),
        (
            "CreateTableStatementSegment".into(),
            NodeMatcher::new(SyntaxKind::CreateTableStatement, |_| {
                Sequence::new(vec![
                    Ref::keyword("CREATE").to_matchable(),
                    Ref::keyword("LOCAL").optional().to_matchable(),
                    Ref::new("TemporaryGrammar").optional().to_matchable(),
                    Ref::keyword("TABLE").to_matchable(),
                    Ref::new("IfNotExistsGrammar").optional().to_matchable(),
                    Ref::new("TableReferenceSegment").to_matchable(),
                    Bracketed::new(vec![
                        Delimited::new(vec![
                            AnyNumberOf::new(vec![
                                Sequence::new(vec![
                                    Ref::new("ColumnReferenceSegment").to_matchable(),
                                    Ref::new("DatatypeSegment").to_matchable(),
                                    AnyNumberOf::new(vec![
                                        Ref::new("ColumnAttributeSegment").to_matchable(),
                                        Ref::new("ColumnConstraintSegment").to_matchable(),
                                    ])
                                    .config(|this| {
                                        this.optional();
                                    })
                                    .to_matchable(),
                                ])
                                .to_matchable(),
                                Ref::new("TableConstraintSegment").to_matchable(),
                                Sequence::new(vec![
                                    Ref::keyword("LIKE").to_matchable(),
                                    Ref::new("TableReferenceSegment").to_matchable(),
                                    AnyNumberOf::new(vec![
                                        Ref::new("LikeOptionSegment").to_matchable(),
                                    ])
                                    .config(|this| {
                                        this.optional();
                                    })
                                    .to_matchable(),
                                ])
                                .to_matchable(),
                            ])
                            .to_matchable(),
                        ])
                        .to_matchable(),
                    ])
                    .to_matchable(),
                    Sequence::new(vec![
                        Ref::keyword("BACKUP").to_matchable(),
                        one_of(vec![
                            Ref::keyword("YES").to_matchable(),
                            Ref::keyword("NO").to_matchable(),
                        ])
                        .config(|this| {
                            this.optional();
                        })
                        .to_matchable(),
                    ])
                    .config(|this| {
                        this.optional();
                    })
                    .to_matchable(),
                    AnyNumberOf::new(vec![Ref::new("TableAttributeSegment").to_matchable()])
                        .config(|this| {
                            this.optional();
                        })
                        .to_matchable(),
                ])
                .to_matchable()
            })
            .to_matchable()
            .into(),
        ),
        (
            "CreateTableAsStatementSegment".into(),
            NodeMatcher::new(SyntaxKind::CreateTableAsStatement, |_| {
                Sequence::new(vec![
                    Ref::keyword("CREATE").to_matchable(),
                    Sequence::new(vec![
                        Ref::keyword("LOCAL").optional().to_matchable(),
                        one_of(vec![
                            Ref::keyword("TEMPORARY").to_matchable(),
                            Ref::keyword("TEMP").to_matchable(),
                        ])
                        .to_matchable(),
                    ])
                    .config(|this| {
                        this.optional();
                    })
                    .to_matchable(),
                    Ref::keyword("TABLE").to_matchable(),
                    Ref::new("ObjectReferenceSegment").to_matchable(),
                    Bracketed::new(vec![
                        Delimited::new(vec![Ref::new("ColumnReferenceSegment").to_matchable()])
                            .to_matchable(),
                    ])
                    .config(|this| {
                        this.optional();
                    })
                    .to_matchable(),
                    Sequence::new(vec![
                        Ref::keyword("BACKUP").to_matchable(),
                        one_of(vec![
                            Ref::keyword("YES").to_matchable(),
                            Ref::keyword("NO").to_matchable(),
                        ])
                        .to_matchable(),
                    ])
                    .config(|this| {
                        this.optional();
                    })
                    .to_matchable(),
                    Ref::new("TableAttributeSegment").optional().to_matchable(),
                    Ref::keyword("AS").to_matchable(),
                    optionally_bracketed(vec![Ref::new("SelectableGrammar").to_matchable()])
                        .to_matchable(),
                ])
                .to_matchable()
            })
            .to_matchable()
            .into(),
        ),
        (
            "CreateModelStatementSegment".into(),
            NodeMatcher::new(SyntaxKind::CreateModelStatement, |_| {
                Sequence::new(vec![
                    Ref::keyword("CREATE").to_matchable(),
                    Ref::keyword("MODEL").to_matchable(),
                    Ref::new("ObjectReferenceSegment").to_matchable(),
                    Sequence::new(vec![
                        Ref::keyword("FROM").to_matchable(),
                        one_of(vec![
                            Ref::new("QuotedLiteralSegment").to_matchable(),
                            Bracketed::new(vec![Ref::new("SelectableGrammar").to_matchable()])
                                .to_matchable(),
                            Ref::new("ObjectReferenceSegment").to_matchable(),
                        ])
                        .to_matchable(),
                    ])
                    .config(|this| {
                        this.optional();
                    })
                    .to_matchable(),
                    Sequence::new(vec![
                        Ref::keyword("TARGET").to_matchable(),
                        Ref::new("ColumnReferenceSegment").to_matchable(),
                    ])
                    .config(|this| {
                        this.optional();
                    })
                    .to_matchable(),
                    Sequence::new(vec![
                        Ref::keyword("FUNCTION").to_matchable(),
                        Ref::new("ObjectReferenceSegment").to_matchable(),
                        Bracketed::new(vec![
                            Delimited::new(vec![Ref::new("DatatypeSegment").to_matchable()])
                                .to_matchable(),
                        ])
                        .config(|this| {
                            this.optional();
                        })
                        .to_matchable(),
                    ])
                    .to_matchable(),
                    Sequence::new(vec![
                        Ref::keyword("RETURNS").to_matchable(),
                        Ref::new("DatatypeSegment").to_matchable(),
                    ])
                    .config(|this| {
                        this.optional();
                    })
                    .to_matchable(),
                    Sequence::new(vec![
                        Ref::keyword("SAGEMAKER").to_matchable(),
                        Ref::new("QuotedLiteralSegment").to_matchable(),
                    ])
                    .config(|this| {
                        this.optional();
                    })
                    .to_matchable(),
                    Sequence::new(vec![
                        Ref::keyword("IAM_ROLE").to_matchable(),
                        one_of(vec![
                            Ref::keyword("DEFAULT").to_matchable(),
                            Ref::new("QuotedLiteralSegment").to_matchable(),
                        ])
                        .to_matchable(),
                    ])
                    .to_matchable(),
                    Sequence::new(vec![
                        Ref::keyword("AUTO").to_matchable(),
                        one_of(vec![
                            Ref::keyword("ON").to_matchable(),
                            Ref::keyword("OFF").to_matchable(),
                        ])
                        .to_matchable(),
                    ])
                    .config(|this| {
                        this.optional();
                    })
                    .to_matchable(),
                    Sequence::new(vec![
                        Ref::keyword("MODEL_TYPE").to_matchable(),
                        one_of(vec![
                            Ref::keyword("XGBOOST").to_matchable(),
                            Ref::keyword("MLP").to_matchable(),
                            Ref::keyword("KMEANS").to_matchable(),
                        ])
                        .to_matchable(),
                    ])
                    .config(|this| {
                        this.optional();
                    })
                    .to_matchable(),
                    Sequence::new(vec![
                        Ref::keyword("PROBLEM_TYPE").to_matchable(),
                        one_of(vec![
                            Ref::keyword("REGRESSION").to_matchable(),
                            Ref::keyword("BINARY_CLASSIFICATION").to_matchable(),
                            Ref::keyword("MULTICLASS_CLASSIFICATION").to_matchable(),
                        ])
                        .to_matchable(),
                    ])
                    .config(|this| {
                        this.optional();
                    })
                    .to_matchable(),
                    Sequence::new(vec![
                        Ref::keyword("OBJECTIVE").to_matchable(),
                        Ref::new("QuotedLiteralSegment").to_matchable(),
                    ])
                    .config(|this| {
                        this.optional();
                    })
                    .to_matchable(),
                    Sequence::new(vec![
                        Ref::keyword("PREPROCESSORS").to_matchable(),
                        Ref::new("QuotedLiteralSegment").to_matchable(),
                    ])
                    .config(|this| {
                        this.optional();
                    })
                    .to_matchable(),
                    Sequence::new(vec![
                        Ref::keyword("HYPERPARAMETERS").to_matchable(),
                        Ref::keyword("DEFAULT").to_matchable(),
                        Sequence::new(vec![
                            Ref::keyword("EXCEPT").to_matchable(),
                            Bracketed::new(vec![
                                Delimited::new(vec![Anything::new().to_matchable()]).to_matchable(),
                            ])
                            .to_matchable(),
                        ])
                        .config(|this| {
                            this.optional();
                        })
                        .to_matchable(),
                    ])
                    .config(|this| {
                        this.optional();
                    })
                    .to_matchable(),
                    Sequence::new(vec![
                        Ref::keyword("SETTINGS").to_matchable(),
                        Bracketed::new(vec![
                            Sequence::new(vec![
                                Ref::keyword("S3_BUCKET").to_matchable(),
                                Ref::new("QuotedLiteralSegment").to_matchable(),
                                Sequence::new(vec![
                                    Ref::keyword("KMS_KEY_ID").to_matchable(),
                                    Ref::new("QuotedLiteralSegment").to_matchable(),
                                ])
                                .config(|this| {
                                    this.optional();
                                })
                                .to_matchable(),
                                Sequence::new(vec![
                                    Ref::keyword("S3_GARBAGE_COLLECT").to_matchable(),
                                    one_of(vec![
                                        Ref::keyword("ON").to_matchable(),
                                        Ref::keyword("OFF").to_matchable(),
                                    ])
                                    .to_matchable(),
                                ])
                                .config(|this| {
                                    this.optional();
                                })
                                .to_matchable(),
                                Sequence::new(vec![
                                    Ref::keyword("MAX_CELLS").to_matchable(),
                                    Ref::new("NumericLiteralSegment").to_matchable(),
                                ])
                                .config(|this| {
                                    this.optional();
                                })
                                .to_matchable(),
                                Sequence::new(vec![
                                    Ref::keyword("MAX_RUNTIME").to_matchable(),
                                    Ref::new("NumericLiteralSegment").to_matchable(),
                                ])
                                .config(|this| {
                                    this.optional();
                                })
                                .to_matchable(),
                            ])
                            .to_matchable(),
                        ])
                        .to_matchable(),
                    ])
                    .config(|this| {
                        this.optional();
                    })
                    .to_matchable(),
                ])
                .to_matchable()
            })
            .to_matchable()
            .into(),
        ),
        (
            "ShowModelStatementSegment".into(),
            NodeMatcher::new(SyntaxKind::ShowModelStatement, |_| {
                Sequence::new(vec![
                    Ref::keyword("SHOW").to_matchable(),
                    Ref::keyword("MODEL").to_matchable(),
                    one_of(vec![
                        Ref::keyword("ALL").to_matchable(),
                        Ref::new("ObjectReferenceSegment").to_matchable(),
                    ])
                    .to_matchable(),
                ])
                .to_matchable()
            })
            .to_matchable()
            .into(),
        ),
        (
            "CreateExternalTableStatementSegment".into(),
            NodeMatcher::new(SyntaxKind::CreateExternalTableStatement, |_| {
                Sequence::new(vec![
                    Ref::keyword("CREATE").to_matchable(),
                    Ref::keyword("EXTERNAL").to_matchable(),
                    Ref::keyword("TABLE").to_matchable(),
                    Ref::new("TableReferenceSegment").to_matchable(),
                    Bracketed::new(vec![
                        Delimited::new(vec![
                            Sequence::new(vec![
                                Ref::new("ColumnReferenceSegment").to_matchable(),
                                Ref::new("DatatypeSegment").to_matchable(),
                            ])
                            .to_matchable(),
                        ])
                        .to_matchable(),
                    ])
                    .to_matchable(),
                    Ref::new("PartitionedBySegment").optional().to_matchable(),
                    Sequence::new(vec![
                        Ref::keyword("ROW").to_matchable(),
                        Ref::keyword("FORMAT").to_matchable(),
                        one_of(vec![
                            Sequence::new(vec![
                                Ref::keyword("DELIMITED").to_matchable(),
                                Ref::new("RowFormatDelimitedSegment").to_matchable(),
                            ])
                            .to_matchable(),
                            Sequence::new(vec![
                                Ref::keyword("SERDE").to_matchable(),
                                Ref::new("QuotedLiteralSegment").to_matchable(),
                                Sequence::new(vec![
                                    Ref::keyword("WITH").to_matchable(),
                                    Ref::keyword("SERDEPROPERTIES").to_matchable(),
                                    Bracketed::new(vec![
                                        Delimited::new(vec![
                                            Sequence::new(vec![
                                                Ref::new("QuotedLiteralSegment").to_matchable(),
                                                Ref::new("EqualsSegment").to_matchable(),
                                                Ref::new("QuotedLiteralSegment").to_matchable(),
                                            ])
                                            .to_matchable(),
                                        ])
                                        .to_matchable(),
                                    ])
                                    .to_matchable(),
                                ])
                                .config(|this| {
                                    this.optional();
                                })
                                .to_matchable(),
                            ])
                            .to_matchable(),
                        ])
                        .to_matchable(),
                    ])
                    .config(|this| {
                        this.optional();
                    })
                    .to_matchable(),
                    Ref::keyword("STORED").to_matchable(),
                    Ref::keyword("AS").to_matchable(),
                    one_of(vec![
                        Ref::keyword("PARQUET").to_matchable(),
                        Ref::keyword("RCFILE").to_matchable(),
                        Ref::keyword("SEQUENCEFILE").to_matchable(),
                        Ref::keyword("TEXTFILE").to_matchable(),
                        Ref::keyword("ORC").to_matchable(),
                        Ref::keyword("AVRO").to_matchable(),
                        Sequence::new(vec![
                            Ref::keyword("INPUTFORMAT").to_matchable(),
                            Ref::new("QuotedLiteralSegment").to_matchable(),
                            Ref::keyword("OUTPUTFORMAT").to_matchable(),
                            Ref::new("QuotedLiteralSegment").to_matchable(),
                        ])
                        .to_matchable(),
                    ])
                    .to_matchable(),
                    Ref::keyword("LOCATION").to_matchable(),
                    Ref::new("QuotedLiteralSegment").to_matchable(),
                    Sequence::new(vec![
                        Ref::keyword("TABLE").to_matchable(),
                        Ref::keyword("PROPERTIES").to_matchable(),
                        Bracketed::new(vec![
                            Delimited::new(vec![
                                Sequence::new(vec![
                                    Ref::new("QuotedLiteralSegment").to_matchable(),
                                    Ref::new("EqualsSegment").to_matchable(),
                                    Ref::new("QuotedLiteralSegment").to_matchable(),
                                ])
                                .to_matchable(),
                            ])
                            .to_matchable(),
                        ])
                        .to_matchable(),
                    ])
                    .config(|this| {
                        this.optional();
                    })
                    .to_matchable(),
                ])
                .to_matchable()
            })
            .to_matchable()
            .into(),
        ),
        (
            "CreateExternalTableAsStatementSegment".into(),
            NodeMatcher::new(SyntaxKind::CreateExternalTableStatement, |_| {
                Sequence::new(vec![
                    Ref::keyword("CREATE").to_matchable(),
                    Ref::keyword("EXTERNAL").to_matchable(),
                    Ref::keyword("TABLE").to_matchable(),
                    Ref::new("TableReferenceSegment").to_matchable(),
                    Ref::new("PartitionedBySegment").optional().to_matchable(),
                    Sequence::new(vec![
                        Ref::keyword("ROW").to_matchable(),
                        Ref::keyword("FORMAT").to_matchable(),
                        Ref::keyword("DELIMITED").to_matchable(),
                        Ref::new("RowFormatDelimitedSegment").to_matchable(),
                    ])
                    .config(|this| {
                        this.optional();
                    })
                    .to_matchable(),
                    Ref::keyword("STORED").to_matchable(),
                    Ref::keyword("AS").to_matchable(),
                    one_of(vec![
                        Ref::keyword("PARQUET").to_matchable(),
                        Ref::keyword("TEXTFILE").to_matchable(),
                    ])
                    .to_matchable(),
                    Ref::keyword("LOCATION").to_matchable(),
                    Ref::new("QuotedLiteralSegment").to_matchable(),
                    Sequence::new(vec![
                        Ref::keyword("TABLE").to_matchable(),
                        Ref::keyword("PROPERTIES").to_matchable(),
                        Bracketed::new(vec![
                            Delimited::new(vec![
                                Sequence::new(vec![
                                    Ref::new("QuotedLiteralSegment").to_matchable(),
                                    Ref::new("EqualsSegment").to_matchable(),
                                    Ref::new("QuotedLiteralSegment").to_matchable(),
                                ])
                                .to_matchable(),
                            ])
                            .to_matchable(),
                        ])
                        .to_matchable(),
                    ])
                    .config(|this| {
                        this.optional();
                    })
                    .to_matchable(),
                    Ref::keyword("AS").to_matchable(),
                    optionally_bracketed(vec![Ref::new("SelectableGrammar").to_matchable()])
                        .to_matchable(),
                ])
                .to_matchable()
            })
            .to_matchable()
            .into(),
        ),
        (
            "CreateExternalSchemaStatementSegment".into(),
            NodeMatcher::new(SyntaxKind::CreateExternalSchemaStatement, |_| {
                Sequence::new(vec![
                    Ref::keyword("CREATE").to_matchable(),
                    Ref::keyword("EXTERNAL").to_matchable(),
                    Ref::keyword("SCHEMA").to_matchable(),
                    Ref::new("IfNotExistsGrammar").optional().to_matchable(),
                    Ref::new("SchemaReferenceSegment").to_matchable(),
                    Ref::keyword("FROM").to_matchable(),
                    one_of(vec![
                        Sequence::new(vec![
                            Ref::keyword("DATA").to_matchable(),
                            Ref::keyword("CATALOG").to_matchable(),
                        ])
                        .to_matchable(),
                        Sequence::new(vec![
                            Ref::keyword("HIVE").to_matchable(),
                            Ref::keyword("METASTORE").to_matchable(),
                        ])
                        .to_matchable(),
                        Ref::keyword("POSTGRES").to_matchable(),
                        Ref::keyword("MYSQL").to_matchable(),
                        Ref::keyword("KINESIS").to_matchable(),
                        Ref::keyword("REDSHIFT").to_matchable(),
                    ])
                    .to_matchable(),
                    any_set_of(vec![
                        Sequence::new(vec![
                            Ref::keyword("DATABASE").to_matchable(),
                            Ref::new("QuotedLiteralSegment").to_matchable(),
                        ])
                        .to_matchable(),
                        Sequence::new(vec![
                            Ref::keyword("REGION").to_matchable(),
                            Ref::new("QuotedLiteralSegment").to_matchable(),
                        ])
                        .to_matchable(),
                        Sequence::new(vec![
                            Ref::keyword("SCHEMA").to_matchable(),
                            Ref::new("QuotedLiteralSegment").to_matchable(),
                        ])
                        .to_matchable(),
                        Sequence::new(vec![
                            Ref::keyword("URI").to_matchable(),
                            Ref::new("QuotedLiteralSegment").to_matchable(),
                            Sequence::new(vec![
                                Ref::keyword("PORT").to_matchable(),
                                Ref::new("NumericLiteralSegment").to_matchable(),
                            ])
                            .config(|this| {
                                this.optional();
                            })
                            .to_matchable(),
                        ])
                        .to_matchable(),
                        Sequence::new(vec![
                            Ref::keyword("IAM_ROLE").to_matchable(),
                            one_of(vec![
                                Ref::keyword("DEFAULT").to_matchable(),
                                Ref::new("QuotedLiteralSegment").to_matchable(),
                            ])
                            .to_matchable(),
                        ])
                        .to_matchable(),
                        Sequence::new(vec![
                            Ref::keyword("SECRET_ARN").to_matchable(),
                            Ref::new("QuotedLiteralSegment").to_matchable(),
                        ])
                        .to_matchable(),
                        Sequence::new(vec![
                            Ref::keyword("CATALOG_ROLE").to_matchable(),
                            Ref::new("QuotedLiteralSegment").to_matchable(),
                        ])
                        .to_matchable(),
                        Sequence::new(vec![
                            Ref::keyword("CREATE").to_matchable(),
                            Ref::keyword("EXTERNAL").to_matchable(),
                            Ref::keyword("DATABASE").to_matchable(),
                            Ref::keyword("IF").to_matchable(),
                            Ref::keyword("NOT").to_matchable(),
                            Ref::keyword("EXISTS").to_matchable(),
                        ])
                        .to_matchable(),
                    ])
                    .config(|this| {
                        this.optional();
                    })
                    .to_matchable(),
                ])
                .to_matchable()
            })
            .to_matchable()
            .into(),
        ),
        (
            "CreateLibraryStatementSegment".into(),
            NodeMatcher::new(SyntaxKind::CreateLibraryStatement, |_| {
                Sequence::new(vec![
                    Ref::keyword("CREATE").to_matchable(),
                    Ref::new("OrReplaceGrammar").optional().to_matchable(),
                    Ref::keyword("LIBRARY").to_matchable(),
                    Ref::new("ObjectReferenceSegment").to_matchable(),
                    Ref::keyword("LANGUAGE").to_matchable(),
                    Ref::keyword("PLPYTHONU").to_matchable(),
                    Ref::keyword("FROM").to_matchable(),
                    Ref::new("QuotedLiteralSegment").to_matchable(),
                    any_set_of(vec![
                        Ref::new("AuthorizationSegment").to_matchable(),
                        Sequence::new(vec![
                            Ref::keyword("REGION").to_matchable(),
                            Ref::keyword("AS").optional().to_matchable(),
                            Ref::new("QuotedLiteralSegment").to_matchable(),
                        ])
                        .config(|this| {
                            this.optional();
                        })
                        .to_matchable(),
                    ])
                    .to_matchable(),
                ])
                .to_matchable()
            })
            .to_matchable()
            .into(),
        ),
        (
            "UnloadStatementSegment".into(),
            NodeMatcher::new(SyntaxKind::UnloadStatement, |_| {
                Sequence::new(vec![
                    Ref::keyword("UNLOAD").to_matchable(),
                    Bracketed::new(vec![Ref::new("QuotedLiteralSegment").to_matchable()])
                        .to_matchable(),
                    Ref::keyword("TO").to_matchable(),
                    Ref::new("QuotedLiteralSegment").to_matchable(),
                    any_set_of(vec![
                        Ref::new("AuthorizationSegment").to_matchable(),
                        Sequence::new(vec![
                            Ref::keyword("REGION").to_matchable(),
                            Ref::keyword("AS").optional().to_matchable(),
                            Ref::new("QuotedLiteralSegment").to_matchable(),
                        ])
                        .config(|this| {
                            this.optional();
                        })
                        .to_matchable(),
                        Ref::new("CompressionTypeGrammar").optional().to_matchable(),
                        Sequence::new(vec![
                            Sequence::new(vec![
                                Ref::keyword("FORMAT").to_matchable(),
                                Ref::keyword("AS").optional().to_matchable(),
                            ])
                            .config(|this| {
                                this.optional();
                            })
                            .to_matchable(),
                            one_of(vec![
                                Ref::keyword("CSV").to_matchable(),
                                Ref::keyword("JSON").to_matchable(),
                                Ref::keyword("PARQUET").to_matchable(),
                            ])
                            .to_matchable(),
                        ])
                        .config(|this| {
                            this.optional();
                        })
                        .to_matchable(),
                        Sequence::new(vec![
                            Ref::keyword("PARTITION").to_matchable(),
                            Ref::keyword("BY").to_matchable(),
                            Ref::new("BracketedColumnReferenceListGrammar").to_matchable(),
                            Ref::keyword("INCLUDE").optional().to_matchable(),
                        ])
                        .to_matchable(),
                        Sequence::new(vec![
                            Ref::keyword("PARALLEL").to_matchable(),
                            one_of(vec![
                                Ref::keyword("PRESET").to_matchable(),
                                Ref::keyword("ON").to_matchable(),
                                Ref::keyword("OFF").to_matchable(),
                                Ref::keyword("TRUE").to_matchable(),
                                Ref::keyword("FALSE").to_matchable(),
                            ])
                            .config(|this| {
                                this.optional();
                            })
                            .to_matchable(),
                        ])
                        .config(|this| {
                            this.optional();
                        })
                        .to_matchable(),
                        one_of(vec![
                            Sequence::new(vec![
                                Ref::keyword("DELIMITER").to_matchable(),
                                Ref::keyword("AS").optional().to_matchable(),
                                Ref::new("QuotedLiteralSegment").to_matchable(),
                            ])
                            .to_matchable(),
                            Sequence::new(vec![
                                Ref::keyword("FIXEDWIDTH").to_matchable(),
                                Ref::keyword("AS").optional().to_matchable(),
                                Ref::new("QuotedLiteralSegment").to_matchable(),
                            ])
                            .to_matchable(),
                        ])
                        .config(|this| {
                            this.optional();
                        })
                        .to_matchable(),
                        Sequence::new(vec![
                            Ref::keyword("MANIFEST").to_matchable(),
                            Ref::keyword("VERBOSE").optional().to_matchable(),
                        ])
                        .config(|this| {
                            this.optional();
                        })
                        .to_matchable(),
                        Sequence::new(vec![
                            Ref::keyword("NULL").to_matchable(),
                            Ref::keyword("AS").to_matchable(),
                            Ref::new("QuotedLiteralSegment").to_matchable(),
                        ])
                        .config(|this| {
                            this.optional();
                        })
                        .to_matchable(),
                        Sequence::new(vec![
                            Ref::keyword("NULL").to_matchable(),
                            Ref::keyword("AS").to_matchable(),
                            Ref::new("QuotedLiteralSegment").to_matchable(),
                        ])
                        .config(|this| {
                            this.optional();
                        })
                        .to_matchable(),
                        any_set_of(vec![
                            one_of(vec![
                                Ref::keyword("MAXFILESIZE").to_matchable(),
                                Ref::keyword("ROWGROUPSIZE").to_matchable(),
                            ])
                            .to_matchable(),
                            Ref::keyword("AS").optional().to_matchable(),
                            Ref::new("NumericLiteralSegment").to_matchable(),
                            one_of(vec![
                                Ref::keyword("MB").to_matchable(),
                                Ref::keyword("GB").to_matchable(),
                            ])
                            .to_matchable(),
                        ])
                        .config(|this| {
                            this.optional();
                        })
                        .to_matchable(),
                        Sequence::new(vec![
                            Ref::keyword("ENCRYPTED").to_matchable(),
                            Ref::keyword("AUTO").optional().to_matchable(),
                        ])
                        .config(|this| {
                            this.optional();
                        })
                        .to_matchable(),
                        Ref::keyword("ALLOWOVERWRITE").optional().to_matchable(),
                        Ref::keyword("CLEANPATH").optional().to_matchable(),
                        Ref::keyword("ESCAPE").optional().to_matchable(),
                        Ref::keyword("ADDQUOTES").optional().to_matchable(),
                        Ref::keyword("HEADER").optional().to_matchable(),
                    ])
                    .to_matchable(),
                ])
                .to_matchable()
            })
            .to_matchable()
            .into(),
        ),
    ]);
    redshift_dialect.replace_grammar(
        "CopyStatementSegment",
        Sequence::new(vec![
            Ref::keyword("COPY").to_matchable(),
            Ref::new("TableReferenceSegment").to_matchable(),
            Ref::new("BracketedColumnReferenceListGrammar")
                .optional()
                .to_matchable(),
            Ref::keyword("FROM").to_matchable(),
            Ref::new("QuotedLiteralSegment").to_matchable(),
            any_set_of(vec![
                Ref::new("AuthorizationSegment").to_matchable(),
                Sequence::new(vec![
                    Ref::keyword("REGION").to_matchable(),
                    Ref::keyword("AS").optional().to_matchable(),
                    Ref::new("QuotedLiteralSegment").to_matchable(),
                ])
                .config(|this| {
                    this.optional();
                })
                .to_matchable(),
                Ref::new("CompressionTypeGrammar").optional().to_matchable(),
                Ref::new("DataFormatSegment").optional().to_matchable(),
                one_of(vec![
                    Sequence::new(vec![
                        Ref::keyword("DELIMITER").to_matchable(),
                        Ref::keyword("AS").optional().to_matchable(),
                        Ref::new("QuotedLiteralSegment").to_matchable(),
                    ])
                    .to_matchable(),
                    Sequence::new(vec![
                        Ref::keyword("FIXEDWIDTH").to_matchable(),
                        Ref::keyword("AS").optional().to_matchable(),
                        Ref::new("QuotedLiteralSegment").to_matchable(),
                    ])
                    .to_matchable(),
                ])
                .config(|this| {
                    this.optional();
                })
                .to_matchable(),
                Sequence::new(vec![
                    Ref::keyword("ENCRYPTED").to_matchable(),
                    Ref::keyword("AUTO").optional().to_matchable(),
                ])
                .config(|this| {
                    this.optional();
                })
                .to_matchable(),
                Ref::keyword("MANIFEST").optional().to_matchable(),
                Sequence::new(vec![
                    Ref::keyword("COMPROWS").to_matchable(),
                    Ref::new("NumericLiteralSegment").to_matchable(),
                ])
                .config(|this| {
                    this.optional();
                })
                .to_matchable(),
                Sequence::new(vec![
                    Ref::keyword("MAXERROR").to_matchable(),
                    Ref::keyword("AS").optional().to_matchable(),
                    Ref::new("NumericLiteralSegment").to_matchable(),
                ])
                .config(|this| {
                    this.optional();
                })
                .to_matchable(),
                Sequence::new(vec![
                    Ref::keyword("COMPUPDATE").to_matchable(),
                    one_of(vec![
                        Ref::keyword("PRESET").to_matchable(),
                        Ref::keyword("ON").to_matchable(),
                        Ref::keyword("OFF").to_matchable(),
                        Ref::keyword("TRUE").to_matchable(),
                        Ref::keyword("FALSE").to_matchable(),
                    ])
                    .config(|this| {
                        this.optional();
                    })
                    .to_matchable(),
                ])
                .config(|this| {
                    this.optional();
                })
                .to_matchable(),
                Sequence::new(vec![
                    Ref::keyword("STATUPDATE").to_matchable(),
                    one_of(vec![
                        Ref::keyword("ON").to_matchable(),
                        Ref::keyword("OFF").to_matchable(),
                        Ref::keyword("TRUE").to_matchable(),
                        Ref::keyword("FALSE").to_matchable(),
                    ])
                    .config(|this| {
                        this.optional();
                    })
                    .to_matchable(),
                ])
                .config(|this| {
                    this.optional();
                })
                .to_matchable(),
                Ref::keyword("NOLOAD").optional().to_matchable(),
                Ref::keyword("ACCEPTANYDATE").optional().to_matchable(),
                Sequence::new(vec![
                    Ref::keyword("ACCEPTINVCHARS").to_matchable(),
                    Ref::keyword("AS").optional().to_matchable(),
                    Ref::new("QuotedLiteralSegment").optional().to_matchable(),
                ])
                .config(|this| {
                    this.optional();
                })
                .to_matchable(),
                Ref::keyword("BLANKSASNULL").optional().to_matchable(),
                Sequence::new(vec![
                    Ref::keyword("DATEFORMAT").to_matchable(),
                    Ref::keyword("AS").optional().to_matchable(),
                    one_of(vec![
                        Ref::keyword("AUTO").to_matchable(),
                        Ref::new("QuotedLiteralSegment").to_matchable(),
                    ])
                    .to_matchable(),
                ])
                .config(|this| {
                    this.optional();
                })
                .to_matchable(),
                Ref::keyword("EMPTYASNULL").optional().to_matchable(),
                Sequence::new(vec![
                    Ref::keyword("ENCODING").to_matchable(),
                    Ref::keyword("AS").optional().to_matchable(),
                    one_of(vec![
                        Ref::keyword("UTF8").to_matchable(),
                        Ref::keyword("UTF16").to_matchable(),
                        Ref::keyword("UTF16BE").to_matchable(),
                        Ref::keyword("UTF16LE").to_matchable(),
                    ])
                    .to_matchable(),
                ])
                .config(|this| {
                    this.optional();
                })
                .to_matchable(),
                Ref::keyword("ESCAPE").optional().to_matchable(),
                Ref::keyword("EXPLICIT_IDS").optional().to_matchable(),
                Ref::keyword("FILLRECORD").optional().to_matchable(),
                Ref::keyword("IGNOREBLANKLINES").optional().to_matchable(),
                Sequence::new(vec![
                    Ref::keyword("IGNOREHEADER").to_matchable(),
                    Ref::keyword("AS").optional().to_matchable(),
                    Ref::new("LiteralGrammar").to_matchable(),
                ])
                .config(|this| {
                    this.optional();
                })
                .to_matchable(),
                Sequence::new(vec![
                    Ref::keyword("NULL").to_matchable(),
                    Ref::keyword("AS").to_matchable(),
                    Ref::new("QuotedLiteralSegment").to_matchable(),
                ])
                .config(|this| {
                    this.optional();
                })
                .to_matchable(),
                Sequence::new(vec![
                    Ref::keyword("READRATIO").to_matchable(),
                    Ref::new("NumericLiteralSegment").to_matchable(),
                ])
                .config(|this| {
                    this.optional();
                })
                .to_matchable(),
                Ref::keyword("REMOVEQUOTES").optional().to_matchable(),
                Ref::keyword("ROUNDEC").optional().to_matchable(),
                Sequence::new(vec![
                    Ref::keyword("TIMEFORMAT").to_matchable(),
                    Ref::keyword("AS").optional().to_matchable(),
                    one_of(vec![
                        Ref::keyword("AUTO").to_matchable(),
                        Ref::keyword("EPOCHSECS").to_matchable(),
                        Ref::keyword("EPOCHMILLISECS").to_matchable(),
                        Ref::new("QuotedLiteralSegment").to_matchable(),
                    ])
                    .to_matchable(),
                ])
                .config(|this| {
                    this.optional();
                })
                .to_matchable(),
                Ref::keyword("TRIMBLANKS").optional().to_matchable(),
                Ref::keyword("TRUNCATECOLUMNS").optional().to_matchable(),
            ])
            .to_matchable(),
        ])
        .to_matchable(),
    );
    redshift_dialect.add([
        (
            "InsertStatementSegment".into(),
            NodeMatcher::new(SyntaxKind::InsertStatement, |_| {
                Sequence::new(vec![
                    Ref::keyword("INSERT").to_matchable(),
                    Ref::keyword("INTO").to_matchable(),
                    Ref::new("TableReferenceSegment").to_matchable(),
                    one_of(vec![
                        optionally_bracketed(vec![Ref::new("SelectableGrammar").to_matchable()])
                            .to_matchable(),
                        Sequence::new(vec![
                            Ref::keyword("DEFAULT").to_matchable(),
                            Ref::keyword("VALUES").to_matchable(),
                        ])
                        .to_matchable(),
                        Sequence::new(vec![
                            Ref::new("BracketedColumnReferenceListGrammar")
                                .optional()
                                .to_matchable(),
                            one_of(vec![
                                Ref::new("ValuesClauseSegment").to_matchable(),
                                optionally_bracketed(vec![
                                    Ref::new("SelectableGrammar").to_matchable(),
                                ])
                                .to_matchable(),
                            ])
                            .to_matchable(),
                        ])
                        .to_matchable(),
                    ])
                    .to_matchable(),
                ])
                .to_matchable()
            })
            .to_matchable()
            .into(),
        ),
        (
            "CreateSchemaStatementSegment".into(),
            NodeMatcher::new(SyntaxKind::CreateSchemaStatement, |_| {
                Sequence::new(vec![
                    Ref::keyword("CREATE").to_matchable(),
                    Ref::keyword("SCHEMA").to_matchable(),
                    one_of(vec![
                        Sequence::new(vec![
                            Ref::new("IfNotExistsGrammar").optional().to_matchable(),
                            Ref::new("SchemaReferenceSegment").to_matchable(),
                            Sequence::new(vec![
                                Ref::keyword("AUTHORIZATION").to_matchable(),
                                Ref::new("RoleReferenceSegment").to_matchable(),
                            ])
                            .config(|this| {
                                this.optional();
                            })
                            .to_matchable(),
                        ])
                        .to_matchable(),
                        Sequence::new(vec![
                            Ref::keyword("AUTHORIZATION").to_matchable(),
                            Ref::new("RoleReferenceSegment").to_matchable(),
                        ])
                        .to_matchable(),
                    ])
                    .to_matchable(),
                    Ref::new("QuotaGrammar").optional().to_matchable(),
                ])
                .to_matchable()
            })
            .to_matchable()
            .into(),
        ),
        (
            "ProcedureParameterListSegment".into(),
            NodeMatcher::new(SyntaxKind::ProcedureParameterList, |_| {
                let param_type = one_of(vec![
                    Ref::keyword("REFCURSOR").to_matchable(),
                    Ref::new("DatatypeSegment").to_matchable(),
                ]);
                Bracketed::new(vec![
                    Delimited::new(vec![
                        Sequence::new(vec![
                            AnyNumberOf::new(vec![
                                Ref::new("ParameterNameSegment")
                                    .exclude(one_of(vec![
                                        param_type.clone().to_matchable(),
                                        Ref::new("ArgModeGrammar").to_matchable(),
                                    ]))
                                    .optional()
                                    .to_matchable(),
                                Ref::new("ArgModeGrammar").optional().to_matchable(),
                            ])
                            .config(|this| {
                                this.max_times_per_element = 1.into();
                            })
                            .to_matchable(),
                            param_type.clone().to_matchable(),
                        ])
                        .to_matchable(),
                    ])
                    .config(|this| {
                        this.optional();
                    })
                    .to_matchable(),
                ])
                .to_matchable()
            })
            .to_matchable()
            .into(),
        ),
        (
            "CreateProcedureStatementSegment".into(),
            NodeMatcher::new(SyntaxKind::CreateProcedureStatement, |_| {
                Sequence::new(vec![
                    Ref::keyword("CREATE").to_matchable(),
                    Ref::new("OrReplaceGrammar").optional().to_matchable(),
                    Ref::keyword("PROCEDURE").to_matchable(),
                    Ref::new("FunctionNameSegment").to_matchable(),
                    Ref::new("ProcedureParameterListSegment").to_matchable(),
                    Ref::new("FunctionDefinitionGrammar").to_matchable(),
                ])
                .to_matchable()
            })
            .to_matchable()
            .into(),
        ),
        (
            "AlterProcedureStatementSegment".into(),
            NodeMatcher::new(SyntaxKind::AlterProcedureStatement, |_| {
                Sequence::new(vec![
                    Ref::keyword("ALTER").to_matchable(),
                    Ref::keyword("PROCEDURE").to_matchable(),
                    Ref::new("FunctionNameSegment").to_matchable(),
                    Ref::new("ProcedureParameterListSegment")
                        .optional()
                        .to_matchable(),
                    one_of(vec![
                        Sequence::new(vec![
                            Ref::keyword("RENAME").to_matchable(),
                            Ref::keyword("TO").to_matchable(),
                            Ref::new("FunctionNameSegment").to_matchable(),
                        ])
                        .to_matchable(),
                        Sequence::new(vec![
                            Ref::keyword("OWNER").to_matchable(),
                            Ref::keyword("TO").to_matchable(),
                            one_of(vec![
                                one_of(vec![
                                    Ref::new("ParameterNameSegment").to_matchable(),
                                    Ref::new("QuotedIdentifierSegment").to_matchable(),
                                ])
                                .to_matchable(),
                                Ref::keyword("CURRENT_USER").to_matchable(),
                                Ref::keyword("SESSION_USER").to_matchable(),
                            ])
                            .to_matchable(),
                        ])
                        .to_matchable(),
                    ])
                    .to_matchable(),
                ])
                .to_matchable()
            })
            .to_matchable()
            .into(),
        ),
        (
            "DropProcedureStatementSegment".into(),
            NodeMatcher::new(SyntaxKind::DropProcedureStatement, |_| {
                Sequence::new(vec![
                    Ref::keyword("DROP").to_matchable(),
                    Ref::keyword("PROCEDURE").to_matchable(),
                    Ref::new("IfExistsGrammar").optional().to_matchable(),
                    Delimited::new(vec![
                        Sequence::new(vec![
                            Ref::new("FunctionNameSegment").to_matchable(),
                            Ref::new("ProcedureParameterListSegment")
                                .optional()
                                .to_matchable(),
                        ])
                        .to_matchable(),
                    ])
                    .to_matchable(),
                ])
                .to_matchable()
            })
            .to_matchable()
            .into(),
        ),
    ]);

    redshift_dialect.replace_grammar(
        "AlterDefaultPrivilegesSchemaObjectsSegment",
        postgres_dialect
            .grammar("AlterDefaultPrivilegesSchemaObjectsSegment")
            .match_grammar(&postgres_dialect)
            .unwrap()
            .copy(
                Some(vec![
                    Sequence::new(vec![Ref::keyword("PROCEDURES").to_matchable()]).to_matchable(),
                ]),
                None,
                None,
                None,
                Vec::new(),
                false,
            ),
    );

    redshift_dialect.add([
        (
            "DeclareStatementSegment".into(),
            NodeMatcher::new(SyntaxKind::DeclareStatement, |_| {
                Sequence::new(vec![
                    Ref::keyword("DECLARE").to_matchable(),
                    Ref::new("ObjectReferenceSegment").to_matchable(),
                    Ref::keyword("CURSOR").to_matchable(),
                    Ref::keyword("FOR").to_matchable(),
                    Ref::new("SelectableGrammar").to_matchable(),
                ])
                .to_matchable()
            })
            .to_matchable()
            .into(),
        ),
        (
            "FetchStatementSegment".into(),
            NodeMatcher::new(SyntaxKind::FetchStatement, |_| {
                Sequence::new(vec![
                    Ref::keyword("FETCH").to_matchable(),
                    one_of(vec![
                        Ref::keyword("NEXT").to_matchable(),
                        Ref::keyword("ALL").to_matchable(),
                        Sequence::new(vec![
                            Ref::keyword("FORWARD").to_matchable(),
                            one_of(vec![
                                Ref::keyword("ALL").to_matchable(),
                                Ref::new("NumericLiteralSegment").to_matchable(),
                            ])
                            .to_matchable(),
                        ])
                        .to_matchable(),
                    ])
                    .to_matchable(),
                    Ref::keyword("FROM").to_matchable(),
                    Ref::new("ObjectReferenceSegment").to_matchable(),
                ])
                .to_matchable()
            })
            .to_matchable()
            .into(),
        ),
        (
            "CloseStatementSegment".into(),
            NodeMatcher::new(SyntaxKind::CloseStatement, |_| {
                Sequence::new(vec![
                    Ref::keyword("CLOSE").to_matchable(),
                    Ref::new("ObjectReferenceSegment").to_matchable(),
                ])
                .to_matchable()
            })
            .to_matchable()
            .into(),
        ),
        (
            "AltereDatashareStatementSegment".into(),
            NodeMatcher::new(SyntaxKind::CreateDatashareStatement, |_| {
                Sequence::new(vec![
                    Ref::keyword("ALTER").to_matchable(),
                    Ref::keyword("DATASHARE").to_matchable(),
                    Ref::new("ObjectReferenceSegment").to_matchable(),
                    one_of(vec![
                        Sequence::new(vec![
                            one_of(vec![
                                Ref::keyword("ADD").to_matchable(),
                                Ref::keyword("REMOVE").to_matchable(),
                            ])
                            .to_matchable(),
                            one_of(vec![
                                Sequence::new(vec![
                                    Ref::keyword("TABLE").to_matchable(),
                                    Delimited::new(vec![
                                        Ref::new("TableReferenceSegment").to_matchable(),
                                    ])
                                    .to_matchable(),
                                ])
                                .to_matchable(),
                                Sequence::new(vec![
                                    Ref::keyword("SCHEMA").to_matchable(),
                                    Delimited::new(vec![
                                        Ref::new("SchemaReferenceSegment").to_matchable(),
                                    ])
                                    .to_matchable(),
                                ])
                                .to_matchable(),
                                Sequence::new(vec![
                                    Ref::keyword("FUNCTION").to_matchable(),
                                    Delimited::new(vec![
                                        Ref::new("FunctionNameSegment").to_matchable(),
                                    ])
                                    .to_matchable(),
                                ])
                                .to_matchable(),
                                Sequence::new(vec![
                                    Ref::keyword("ALL").to_matchable(),
                                    one_of(vec![
                                        Ref::keyword("TABLES").to_matchable(),
                                        Ref::keyword("FUNCTIONS").to_matchable(),
                                    ])
                                    .to_matchable(),
                                    Ref::keyword("IN").to_matchable(),
                                    Ref::keyword("SCHEMA").to_matchable(),
                                    Delimited::new(vec![
                                        Ref::new("SchemaReferenceSegment").to_matchable(),
                                    ])
                                    .to_matchable(),
                                ])
                                .to_matchable(),
                            ])
                            .to_matchable(),
                        ])
                        .to_matchable(),
                        Sequence::new(vec![
                            Ref::keyword("SET").to_matchable(),
                            one_of(vec![
                                Sequence::new(vec![
                                    Ref::keyword("PUBLICACCESSIBLE").to_matchable(),
                                    Ref::new("EqualsSegment").optional().to_matchable(),
                                    Ref::new("BooleanLiteralGrammar").to_matchable(),
                                ])
                                .to_matchable(),
                                Sequence::new(vec![
                                    Ref::keyword("INCLUDENEW").to_matchable(),
                                    Ref::new("EqualsSegment").optional().to_matchable(),
                                    Ref::new("BooleanLiteralGrammar").to_matchable(),
                                    Ref::keyword("FOR").to_matchable(),
                                    Ref::keyword("SCHEMA").to_matchable(),
                                    Ref::new("SchemaReferenceSegment").to_matchable(),
                                ])
                                .to_matchable(),
                            ])
                            .to_matchable(),
                        ])
                        .to_matchable(),
                    ])
                    .to_matchable(),
                ])
                .to_matchable()
            })
            .to_matchable()
            .into(),
        ),
        (
            "CreateDatashareStatementSegment".into(),
            NodeMatcher::new(SyntaxKind::CreateDatashareStatement, |_| {
                Sequence::new(vec![
                    Ref::keyword("CREATE").to_matchable(),
                    Ref::keyword("DATASHARE").to_matchable(),
                    Ref::new("ObjectReferenceSegment").to_matchable(),
                    Sequence::new(vec![
                        Ref::keyword("SET").optional().to_matchable(),
                        Ref::keyword("PUBLICACCESSIBLE").to_matchable(),
                        Ref::new("EqualsSegment").optional().to_matchable(),
                        one_of(vec![
                            Ref::keyword("TRUE").to_matchable(),
                            Ref::keyword("FALSE").to_matchable(),
                        ])
                        .to_matchable(),
                    ])
                    .config(|this| {
                        this.optional();
                    })
                    .to_matchable(),
                ])
                .to_matchable()
            })
            .to_matchable()
            .into(),
        ),
        (
            "DescDatashareStatementSegment".into(),
            NodeMatcher::new(SyntaxKind::DescDatashareStatement, |_| {
                Sequence::new(vec![
                    Ref::keyword("DESC").to_matchable(),
                    Ref::keyword("DATASHARE").to_matchable(),
                    Ref::new("ObjectReferenceSegment").to_matchable(),
                    Sequence::new(vec![
                        Ref::keyword("OF").to_matchable(),
                        Sequence::new(vec![
                            Ref::keyword("ACCOUNT").to_matchable(),
                            Ref::new("QuotedLiteralSegment").to_matchable(),
                        ])
                        .config(|this| {
                            this.optional();
                        })
                        .to_matchable(),
                        Ref::keyword("NAMESPACE").to_matchable(),
                        Ref::new("QuotedLiteralSegment").to_matchable(),
                    ])
                    .config(|this| {
                        this.optional();
                    })
                    .to_matchable(),
                ])
                .to_matchable()
            })
            .to_matchable()
            .into(),
        ),
        (
            "DropDatashareStatementSegment".into(),
            NodeMatcher::new(SyntaxKind::DropDatashareStatement, |_| {
                Sequence::new(vec![
                    Ref::keyword("DROP").to_matchable(),
                    Ref::keyword("DATASHARE").to_matchable(),
                    Ref::new("ObjectReferenceSegment").to_matchable(),
                ])
                .to_matchable()
            })
            .to_matchable()
            .into(),
        ),
        (
            "ShowDatasharesStatementSegment".into(),
            NodeMatcher::new(SyntaxKind::ShowDatasharesStatement, |_| {
                Sequence::new(vec![
                    Ref::keyword("SHOW").to_matchable(),
                    Ref::keyword("DATASHARES").to_matchable(),
                    Sequence::new(vec![
                        Ref::keyword("LIKE").to_matchable(),
                        Ref::new("QuotedLiteralSegment").to_matchable(),
                    ])
                    .config(|this| {
                        this.optional();
                    })
                    .to_matchable(),
                ])
                .to_matchable()
            })
            .to_matchable()
            .into(),
        ),
        (
            "GrantUsageDatashareStatementSegment".into(),
            NodeMatcher::new(SyntaxKind::GrantDatashareStatement, |_| {
                Sequence::new(vec![
                    one_of(vec![
                        Ref::keyword("GRANT").to_matchable(),
                        Ref::keyword("REVOKE").to_matchable(),
                    ])
                    .to_matchable(),
                    Ref::keyword("USAGE").to_matchable(),
                    Ref::keyword("ON").to_matchable(),
                    Ref::keyword("DATASHARE").to_matchable(),
                    Ref::new("ObjectReferenceSegment").to_matchable(),
                    one_of(vec![
                        Ref::keyword("TO").to_matchable(),
                        Ref::keyword("FROM").to_matchable(),
                    ])
                    .to_matchable(),
                    one_of(vec![
                        Sequence::new(vec![
                            Ref::keyword("NAMESPACE").to_matchable(),
                            Ref::new("QuotedLiteralSegment").to_matchable(),
                        ])
                        .to_matchable(),
                        Sequence::new(vec![
                            Ref::keyword("ACCOUNT").to_matchable(),
                            Sequence::new(vec![
                                Ref::new("QuotedLiteralSegment").to_matchable(),
                                Sequence::new(vec![
                                    Ref::keyword("VIA").to_matchable(),
                                    Ref::keyword("DATA").to_matchable(),
                                    Ref::keyword("CATALOG").to_matchable(),
                                ])
                                .config(|this| {
                                    this.optional();
                                })
                                .to_matchable(),
                            ])
                            .to_matchable(),
                        ])
                        .to_matchable(),
                    ])
                    .to_matchable(),
                ])
                .to_matchable()
            })
            .to_matchable()
            .into(),
        ),
        (
            "CreateRlsPolicyStatementSegment".into(),
            NodeMatcher::new(SyntaxKind::CreateRlsPolicyStatement, |_| {
                Sequence::new(vec![
                    Ref::keyword("CREATE").to_matchable(),
                    Ref::keyword("RLS").to_matchable(),
                    Ref::keyword("POLICY").to_matchable(),
                    Ref::new("ObjectReferenceSegment").to_matchable(),
                    Sequence::new(vec![
                        Ref::keyword("WITH").to_matchable(),
                        Bracketed::new(vec![
                            Delimited::new(vec![
                                Sequence::new(vec![
                                    Ref::new("ColumnReferenceSegment").to_matchable(),
                                    Ref::new("DatatypeSegment").to_matchable(),
                                ])
                                .to_matchable(),
                            ])
                            .to_matchable(),
                        ])
                        .to_matchable(),
                        Sequence::new(vec![
                            Ref::keyword("AS").optional().to_matchable(),
                            Ref::new("AliasExpressionSegment").to_matchable(),
                        ])
                        .config(|this| {
                            this.optional();
                        })
                        .to_matchable(),
                    ])
                    .config(|this| {
                        this.optional();
                    })
                    .to_matchable(),
                    Sequence::new(vec![
                        Ref::keyword("USING").to_matchable(),
                        Bracketed::new(vec![Ref::new("ExpressionSegment").to_matchable()])
                            .to_matchable(),
                    ])
                    .to_matchable(),
                ])
                .to_matchable()
            })
            .to_matchable()
            .into(),
        ),
        (
            "ManageRlsPolicyStatementSegment".into(),
            NodeMatcher::new(SyntaxKind::ManageRlsPolicyStatement, |_| {
                Sequence::new(vec![
                    one_of(vec![
                        Ref::keyword("ATTACH").to_matchable(),
                        Ref::keyword("DETACH").to_matchable(),
                    ])
                    .to_matchable(),
                    Ref::keyword("RLS").to_matchable(),
                    Ref::keyword("POLICY").to_matchable(),
                    Ref::new("ObjectReferenceSegment").to_matchable(),
                    Ref::keyword("ON").to_matchable(),
                    Ref::keyword("TABLE").optional().to_matchable(),
                    Delimited::new(vec![Ref::new("TableReferenceSegment").to_matchable()])
                        .to_matchable(),
                    one_of(vec![
                        Ref::keyword("TO").to_matchable(),
                        Ref::keyword("FROM").to_matchable(),
                    ])
                    .to_matchable(),
                    Delimited::new(vec![
                        one_of(vec![
                            Sequence::new(vec![
                                Ref::keyword("ROLE").optional().to_matchable(),
                                Ref::new("RoleReferenceSegment").to_matchable(),
                            ])
                            .to_matchable(),
                            Ref::keyword("PUBLIC").to_matchable(),
                        ])
                        .to_matchable(),
                    ])
                    .to_matchable(),
                ])
                .to_matchable()
            })
            .to_matchable()
            .into(),
        ),
        (
            "DropRlsPolicyStatementSegment".into(),
            NodeMatcher::new(SyntaxKind::DropRlsPolicyStatement, |_| {
                Sequence::new(vec![
                    Ref::keyword("DROP").to_matchable(),
                    Ref::keyword("RLS").to_matchable(),
                    Ref::keyword("POLICY").to_matchable(),
                    Ref::new("IfExistsGrammar").optional().to_matchable(),
                    Ref::new("ObjectReferenceSegment").to_matchable(),
                    one_of(vec![
                        Ref::keyword("CASCADE").to_matchable(),
                        Ref::keyword("RESTRICT").to_matchable(),
                    ])
                    .config(|this| {
                        this.optional();
                    })
                    .to_matchable(),
                ])
                .to_matchable()
            })
            .to_matchable()
            .into(),
        ),
        (
            "AnalyzeCompressionStatementSegment".into(),
            NodeMatcher::new(SyntaxKind::AnalyzeCompressionStatement, |_| {
                Sequence::new(vec![
                    one_of(vec![
                        Ref::keyword("ANALYZE").to_matchable(),
                        Ref::keyword("ANALYSE").to_matchable(),
                    ])
                    .to_matchable(),
                    Ref::keyword("COMPRESSION").to_matchable(),
                    Sequence::new(vec![
                        Ref::new("TableReferenceSegment").to_matchable(),
                        Bracketed::new(vec![
                            Delimited::new(vec![Ref::new("ColumnReferenceSegment").to_matchable()])
                                .to_matchable(),
                        ])
                        .config(|this| {
                            this.optional();
                        })
                        .to_matchable(),
                        Sequence::new(vec![
                            Ref::keyword("COMPROWS").to_matchable(),
                            Ref::new("NumericLiteralSegment").to_matchable(),
                        ])
                        .config(|this| {
                            this.optional();
                        })
                        .to_matchable(),
                    ])
                    .config(|this| {
                        this.optional();
                    })
                    .to_matchable(),
                ])
                .to_matchable()
            })
            .to_matchable()
            .into(),
        ),
    ]);
    redshift_dialect.replace_grammar(
        "VacuumStatementSegment",
        Sequence::new(vec![
            Ref::keyword("VACUUM").to_matchable(),
            one_of(vec![
                Ref::keyword("FULL").to_matchable(),
                Ref::keyword("REINDEX").to_matchable(),
                Ref::keyword("RECLUSTER").to_matchable(),
                Sequence::new(vec![
                    one_of(vec![
                        Ref::keyword("SORT").to_matchable(),
                        Ref::keyword("DELETE").to_matchable(),
                    ])
                    .to_matchable(),
                    Ref::keyword("ONLY").to_matchable(),
                ])
                .to_matchable(),
            ])
            .config(|this| {
                this.optional();
            })
            .to_matchable(),
            Ref::new("TableReferenceSegment").optional().to_matchable(),
            Sequence::new(vec![
                Ref::keyword("TO").to_matchable(),
                Ref::new("NumericLiteralSegment").to_matchable(),
                Ref::keyword("PERCENT").to_matchable(),
            ])
            .config(|this| {
                this.optional();
            })
            .to_matchable(),
            Ref::keyword("BOOST").optional().to_matchable(),
        ])
        .to_matchable(),
    );

    redshift_dialect.add([]);

    redshift_dialect.replace_grammar(
        "StatementSegment",
        postgres_dialect
            .grammar("StatementSegment")
            .match_grammar(&postgres_dialect)
            .unwrap()
            .copy(
                Some(vec![
                    Ref::new("CreateLibraryStatementSegment").to_matchable(),
                    Ref::new("CreateGroupStatementSegment").to_matchable(),
                    Ref::new("AlterUserStatementSegment").to_matchable(),
                    Ref::new("AlterGroupStatementSegment").to_matchable(),
                    Ref::new("CreateExternalTableAsStatementSegment").to_matchable(),
                    Ref::new("CreateExternalTableStatementSegment").to_matchable(),
                    Ref::new("CreateExternalSchemaStatementSegment").to_matchable(),
                    Ref::new("DataFormatSegment").to_matchable(),
                    Ref::new("UnloadStatementSegment").to_matchable(),
                    Ref::new("CopyStatementSegment").to_matchable(),
                    Ref::new("ShowModelStatementSegment").to_matchable(),
                    Ref::new("CreateDatashareStatementSegment").to_matchable(),
                    Ref::new("DescDatashareStatementSegment").to_matchable(),
                    Ref::new("DropDatashareStatementSegment").to_matchable(),
                    Ref::new("ShowDatasharesStatementSegment").to_matchable(),
                    Ref::new("AltereDatashareStatementSegment").to_matchable(),
                    Ref::new("DeclareStatementSegment").to_matchable(),
                    Ref::new("FetchStatementSegment").to_matchable(),
                    Ref::new("CloseStatementSegment").to_matchable(),
                    Ref::new("AnalyzeCompressionStatementSegment").to_matchable(),
                    Ref::new("AlterProcedureStatementSegment").to_matchable(),
                    Ref::new("CallStatementSegment").to_matchable(),
                    Ref::new("CreateRlsPolicyStatementSegment").to_matchable(),
                    Ref::new("ManageRlsPolicyStatementSegment").to_matchable(),
                    Ref::new("DropRlsPolicyStatementSegment").to_matchable(),
                    Ref::new("CreateExternalFunctionStatementSegment").to_matchable(),
                    Ref::new("GrantUsageDatashareStatementSegment").to_matchable(),
                ]),
                None,
                None,
                None,
                Vec::new(),
                false,
            ),
    );

    redshift_dialect.add([
        (
            "PartitionedBySegment".into(),
            NodeMatcher::new(SyntaxKind::PartitionedBySegment, |_| {
                Sequence::new(vec![
                    Ref::keyword("PARTITIONED").to_matchable(),
                    Ref::keyword("BY").to_matchable(),
                    Bracketed::new(vec![
                        Delimited::new(vec![
                            Sequence::new(vec![
                                Ref::new("ColumnReferenceSegment").to_matchable(),
                                Ref::new("DatatypeSegment").optional().to_matchable(),
                            ])
                            .to_matchable(),
                        ])
                        .to_matchable(),
                    ])
                    .to_matchable(),
                ])
                .to_matchable()
            })
            .to_matchable()
            .into(),
        ),
        (
            "RowFormatDelimitedSegment".into(),
            NodeMatcher::new(SyntaxKind::RowFormatDelimitedSegment, |_| {
                any_set_of(vec![
                    Sequence::new(vec![
                        Ref::keyword("FIELDS").to_matchable(),
                        Ref::keyword("TERMINATED").to_matchable(),
                        Ref::keyword("BY").to_matchable(),
                        Ref::new("QuotedLiteralSegment").to_matchable(),
                    ])
                    .to_matchable(),
                    Sequence::new(vec![
                        Ref::keyword("LINES").to_matchable(),
                        Ref::keyword("TERMINATED").to_matchable(),
                        Ref::keyword("BY").to_matchable(),
                        Ref::new("QuotedLiteralSegment").to_matchable(),
                    ])
                    .to_matchable(),
                ])
                .config(|this| {
                    this.optional();
                })
                .to_matchable()
            })
            .to_matchable()
            .into(),
        ),
    ]);

    redshift_dialect.replace_grammar(
        "CreateUserStatementSegment",
        Sequence::new(vec![
            Ref::keyword("CREATE").to_matchable(),
            Ref::keyword("USER").to_matchable(),
            Ref::new("RoleReferenceSegment").to_matchable(),
            Ref::keyword("WITH").optional().to_matchable(),
            Ref::keyword("PASSWORD").to_matchable(),
            one_of(vec![
                Ref::new("QuotedLiteralSegment").to_matchable(),
                Ref::keyword("DISABLE").to_matchable(),
            ])
            .to_matchable(),
            any_set_of(vec![
                one_of(vec![
                    Ref::keyword("CREATEDB").to_matchable(),
                    Ref::keyword("NOCREATEDB").to_matchable(),
                ])
                .to_matchable(),
                one_of(vec![
                    Ref::keyword("CREATEUSER").to_matchable(),
                    Ref::keyword("NOCREATEUSER").to_matchable(),
                ])
                .to_matchable(),
                Sequence::new(vec![
                    Ref::keyword("SYSLOG").to_matchable(),
                    Ref::keyword("ACCESS").to_matchable(),
                    one_of(vec![
                        Ref::keyword("RESTRICTED").to_matchable(),
                        Ref::keyword("UNRESTRICTED").to_matchable(),
                    ])
                    .to_matchable(),
                ])
                .to_matchable(),
                Sequence::new(vec![
                    Ref::keyword("IN").to_matchable(),
                    Ref::keyword("GROUP").to_matchable(),
                    Delimited::new(vec![Ref::new("ObjectReferenceSegment").to_matchable()])
                        .to_matchable(),
                ])
                .to_matchable(),
                Sequence::new(vec![
                    Ref::keyword("VALID").to_matchable(),
                    Ref::keyword("UNTIL").to_matchable(),
                    Ref::new("QuotedLiteralSegment").to_matchable(),
                ])
                .to_matchable(),
                Sequence::new(vec![
                    Ref::keyword("CONNECTION").to_matchable(),
                    Ref::keyword("LIMIT").to_matchable(),
                    one_of(vec![
                        Ref::new("NumericLiteralSegment").to_matchable(),
                        Ref::keyword("UNLIMITED").to_matchable(),
                    ])
                    .to_matchable(),
                ])
                .to_matchable(),
                Sequence::new(vec![
                    Ref::keyword("SESSION").to_matchable(),
                    Ref::keyword("TIMEOUT").to_matchable(),
                    Ref::new("NumericLiteralSegment").to_matchable(),
                ])
                .to_matchable(),
            ])
            .to_matchable(),
        ])
        .to_matchable(),
    );
    redshift_dialect.add([
        (
            "CreateGroupStatementSegment".into(),
            NodeMatcher::new(SyntaxKind::CreateGroup, |_| {
                Sequence::new(vec![
                    Ref::keyword("CREATE").to_matchable(),
                    Ref::keyword("GROUP").to_matchable(),
                    Ref::new("ObjectReferenceSegment").to_matchable(),
                    Sequence::new(vec![
                        Ref::keyword("WITH").optional().to_matchable(),
                        Ref::keyword("USER").to_matchable(),
                        Delimited::new(vec![Ref::new("ObjectReferenceSegment").to_matchable()])
                            .to_matchable(),
                    ])
                    .config(|this| {
                        this.optional();
                    })
                    .to_matchable(),
                ])
                .to_matchable()
            })
            .to_matchable()
            .into(),
        ),
        (
            "AlterUserStatementSegment".into(),
            NodeMatcher::new(SyntaxKind::AlterUserStatement, |_| {
                Sequence::new(vec![
                    Ref::keyword("ALTER").to_matchable(),
                    Ref::keyword("USER").to_matchable(),
                    Ref::new("RoleReferenceSegment").to_matchable(),
                    Ref::keyword("WITH").optional().to_matchable(),
                    any_set_of(vec![
                        one_of(vec![
                            Ref::keyword("CREATEDB").to_matchable(),
                            Ref::keyword("NOCREATEDB").to_matchable(),
                        ])
                        .to_matchable(),
                        one_of(vec![
                            Ref::keyword("CREATEUSER").to_matchable(),
                            Ref::keyword("NOCREATEUSER").to_matchable(),
                        ])
                        .to_matchable(),
                        Sequence::new(vec![
                            Ref::keyword("SYSLOG").to_matchable(),
                            Ref::keyword("ACCESS").to_matchable(),
                            one_of(vec![
                                Ref::keyword("RESTRICTED").to_matchable(),
                                Ref::keyword("UNRESTRICTED").to_matchable(),
                            ])
                            .to_matchable(),
                        ])
                        .to_matchable(),
                        Sequence::new(vec![
                            Ref::keyword("PASSWORD").to_matchable(),
                            one_of(vec![
                                Ref::new("QuotedLiteralSegment").to_matchable(),
                                Ref::keyword("DISABLE").to_matchable(),
                            ])
                            .to_matchable(),
                            Sequence::new(vec![
                                Ref::keyword("VALID").to_matchable(),
                                Ref::keyword("UNTIL").to_matchable(),
                                Ref::new("QuotedLiteralSegment").to_matchable(),
                            ])
                            .config(|this| {
                                this.optional();
                            })
                            .to_matchable(),
                        ])
                        .to_matchable(),
                        Sequence::new(vec![
                            Ref::keyword("RENAME").to_matchable(),
                            Ref::keyword("TO").to_matchable(),
                            Ref::new("ObjectReferenceSegment").to_matchable(),
                        ])
                        .to_matchable(),
                        Sequence::new(vec![
                            Ref::keyword("CONNECTION").to_matchable(),
                            Ref::keyword("LIMIT").to_matchable(),
                            one_of(vec![
                                Ref::new("NumericLiteralSegment").to_matchable(),
                                Ref::keyword("UNLIMITED").to_matchable(),
                            ])
                            .to_matchable(),
                        ])
                        .to_matchable(),
                        one_of(vec![
                            Sequence::new(vec![
                                Ref::keyword("SESSION").to_matchable(),
                                Ref::keyword("TIMEOUT").to_matchable(),
                                Ref::new("NumericLiteralSegment").to_matchable(),
                            ])
                            .to_matchable(),
                            Sequence::new(vec![
                                Ref::keyword("RESET").to_matchable(),
                                Ref::keyword("SESSION").to_matchable(),
                                Ref::keyword("TIMEOUT").to_matchable(),
                            ])
                            .to_matchable(),
                        ])
                        .to_matchable(),
                        one_of(vec![
                            Sequence::new(vec![
                                Ref::keyword("SET").to_matchable(),
                                Ref::new("ObjectReferenceSegment").to_matchable(),
                                one_of(vec![
                                    Ref::keyword("TO").to_matchable(),
                                    Ref::new("EqualsSegment").to_matchable(),
                                ])
                                .to_matchable(),
                                one_of(vec![
                                    Ref::keyword("DEFAULT").to_matchable(),
                                    Ref::new("LiteralGrammar").to_matchable(),
                                ])
                                .to_matchable(),
                            ])
                            .to_matchable(),
                            Sequence::new(vec![
                                Ref::keyword("RESET").to_matchable(),
                                Ref::new("ObjectReferenceSegment").to_matchable(),
                            ])
                            .to_matchable(),
                        ])
                        .to_matchable(),
                    ])
                    .config(|this| {
                        this.min_times = 1;
                    })
                    .to_matchable(),
                ])
                .to_matchable()
            })
            .to_matchable()
            .into(),
        ),
        (
            "AlterGroupStatementSegment".into(),
            NodeMatcher::new(SyntaxKind::AlterGroup, |_| {
                Sequence::new(vec![
                    Ref::keyword("ALTER").to_matchable(),
                    Ref::keyword("GROUP").to_matchable(),
                    Ref::new("ObjectReferenceSegment").to_matchable(),
                    one_of(vec![
                        Sequence::new(vec![
                            one_of(vec![
                                Ref::keyword("ADD").to_matchable(),
                                Ref::keyword("DROP").to_matchable(),
                            ])
                            .to_matchable(),
                            Ref::keyword("USER").to_matchable(),
                            Delimited::new(vec![Ref::new("ObjectReferenceSegment").to_matchable()])
                                .to_matchable(),
                        ])
                        .to_matchable(),
                        Sequence::new(vec![
                            Ref::keyword("RENAME").to_matchable(),
                            Ref::keyword("TO").to_matchable(),
                            Ref::new("ObjectReferenceSegment").to_matchable(),
                        ])
                        .to_matchable(),
                    ])
                    .to_matchable(),
                ])
                .to_matchable()
            })
            .to_matchable()
            .into(),
        ),
        (
            "TransactionStatementSegment".into(),
            NodeMatcher::new(SyntaxKind::TransactionStatement, |_| {
                Sequence::new(vec![
                    one_of(vec![
                        Ref::keyword("BEGIN").to_matchable(),
                        Ref::keyword("START").to_matchable(),
                        Ref::keyword("COMMIT").to_matchable(),
                        Ref::keyword("END").to_matchable(),
                        Ref::keyword("ROLLBACK").to_matchable(),
                        Ref::keyword("ABORT").to_matchable(),
                    ])
                    .to_matchable(),
                    one_of(vec![
                        Ref::keyword("TRANSACTION").to_matchable(),
                        Ref::keyword("WORK").to_matchable(),
                    ])
                    .config(|this| {
                        this.optional();
                    })
                    .to_matchable(),
                    Sequence::new(vec![
                        Ref::keyword("ISOLATION").to_matchable(),
                        Ref::keyword("LEVEL").to_matchable(),
                        one_of(vec![
                            Ref::keyword("SERIALIZABLE").to_matchable(),
                            Sequence::new(vec![
                                Ref::keyword("READ").to_matchable(),
                                Ref::keyword("COMMITTED").to_matchable(),
                            ])
                            .to_matchable(),
                            Sequence::new(vec![
                                Ref::keyword("READ").to_matchable(),
                                Ref::keyword("UNCOMMITTED").to_matchable(),
                            ])
                            .to_matchable(),
                            Sequence::new(vec![
                                Ref::keyword("REPEATABLE").to_matchable(),
                                Ref::keyword("READ").to_matchable(),
                            ])
                            .to_matchable(),
                        ])
                        .to_matchable(),
                    ])
                    .config(|this| {
                        this.optional();
                    })
                    .to_matchable(),
                    one_of(vec![
                        Sequence::new(vec![
                            Ref::keyword("READ").to_matchable(),
                            Ref::keyword("ONLY").to_matchable(),
                        ])
                        .to_matchable(),
                        Sequence::new(vec![
                            Ref::keyword("READ").to_matchable(),
                            Ref::keyword("WRITE").to_matchable(),
                        ])
                        .to_matchable(),
                    ])
                    .config(|this| {
                        this.optional();
                    })
                    .to_matchable(),
                ])
                .to_matchable()
            })
            .to_matchable()
            .into(),
        ),
        (
            "AlterSchemaStatementSegment".into(),
            NodeMatcher::new(SyntaxKind::AlterSchemaStatement, |_| {
                Sequence::new(vec![
                    Ref::keyword("ALTER").to_matchable(),
                    Ref::keyword("SCHEMA").to_matchable(),
                    Ref::new("SchemaReferenceSegment").to_matchable(),
                    one_of(vec![
                        Sequence::new(vec![
                            Ref::keyword("RENAME").to_matchable(),
                            Ref::keyword("TO").to_matchable(),
                            Ref::new("SchemaReferenceSegment").to_matchable(),
                        ])
                        .to_matchable(),
                        Sequence::new(vec![
                            Ref::keyword("OWNER").to_matchable(),
                            Ref::keyword("TO").to_matchable(),
                            Ref::new("RoleReferenceSegment").to_matchable(),
                        ])
                        .to_matchable(),
                        Ref::new("QuotaGrammar").to_matchable(),
                    ])
                    .to_matchable(),
                ])
                .to_matchable()
            })
            .to_matchable()
            .into(),
        ),
        (
            "LockTableStatementSegment".into(),
            NodeMatcher::new(SyntaxKind::LockTableStatement, |_| {
                Sequence::new(vec![
                    Ref::keyword("LOCK").to_matchable(),
                    Ref::keyword("TABLE").optional().to_matchable(),
                    Delimited::new(vec![Ref::new("TableReferenceSegment").to_matchable()])
                        .to_matchable(),
                ])
                .to_matchable()
            })
            .to_matchable()
            .into(),
        ),
    ]);

    redshift_dialect.replace_grammar(
        "TableExpressionSegment",
        ansi_dialect
            .grammar("TableExpressionSegment")
            .match_grammar(&ansi_dialect)
            .unwrap()
            .copy(
                Some(vec![
                    Ref::new("ObjectUnpivotSegment").optional().to_matchable(),
                    Ref::new("ArrayUnnestSegment").optional().to_matchable(),
                ]),
                None,
                Some(Ref::new("TableReferenceSegment").to_matchable()),
                None,
                Vec::new(),
                false,
            ),
    );

    redshift_dialect.add([(
        "ObjectUnpivotSegment".into(),
        NodeMatcher::new(SyntaxKind::ObjectUnpivoting, |_| {
            Sequence::new(vec![
                Ref::keyword("UNPIVOT").to_matchable(),
                Ref::new("ObjectReferenceSegment").to_matchable(),
                Ref::keyword("AS").to_matchable(),
                Ref::new("SingleIdentifierGrammar").to_matchable(),
                Ref::keyword("AT").to_matchable(),
                Ref::new("SingleIdentifierGrammar").to_matchable(),
            ])
            .to_matchable()
        })
        .to_matchable()
        .into(),
    )]);

    redshift_dialect.replace_grammar(
        "ArrayAccessorSegment",
        Sequence::new(vec![
            AnyNumberOf::new(vec![
                Bracketed::new(vec![
                    one_of(vec![
                        Ref::new("NumericLiteralSegment").to_matchable(),
                        Ref::new("ExpressionSegment").to_matchable(),
                    ])
                    .to_matchable(),
                ])
                .config(|this| {
                    this.bracket_type = "square";
                })
                .to_matchable(),
            ])
            .to_matchable(),
        ])
        .to_matchable(),
    );

    redshift_dialect.add([
        (
            "ArrayUnnestSegment".into(),
            NodeMatcher::new(SyntaxKind::ArrayUnnesting, |_| {
                Sequence::new(vec![
                    Ref::new("ObjectReferenceSegment").to_matchable(),
                    Ref::keyword("AS").to_matchable(),
                    Ref::new("SingleIdentifierGrammar").to_matchable(),
                    Ref::keyword("AT").to_matchable(),
                    Ref::new("SingleIdentifierGrammar").to_matchable(),
                ])
                .to_matchable()
            })
            .to_matchable()
            .into(),
        ),
        (
            "CallStatementSegment".into(),
            NodeMatcher::new(SyntaxKind::CallStatement, |_| {
                Sequence::new(vec![
                    Ref::keyword("CALL").to_matchable(),
                    Ref::new("FunctionSegment").to_matchable(),
                ])
                .to_matchable()
            })
            .to_matchable()
            .into(),
        ),
    ]);

    redshift_dialect.replace_grammar(
        "SelectClauseModifierSegment",
        postgres_dialect
            .grammar("SelectClauseModifierSegment")
            .match_grammar(&postgres_dialect)
            .unwrap()
            .copy(
                Some(vec![
                    Sequence::new(vec![
                        Ref::keyword("TOP").to_matchable(),
                        Ref::new("NumericLiteralSegment").to_matchable(),
                    ])
                    .to_matchable(),
                ]),
                None,
                None,
                None,
                Vec::new(),
                false,
            ),
    );

    redshift_dialect.add([(
        "ConvertFunctionNameSegment".into(),
        NodeMatcher::new(SyntaxKind::FunctionName, |_| {
            Sequence::new(vec![Ref::keyword("CONVERT").to_matchable()]).to_matchable()
        })
        .to_matchable()
        .into(),
    )]);

    redshift_dialect.replace_grammar(
        "FunctionSegment",
        one_of(vec![
            Sequence::new(vec![
                Sequence::new(vec![
                    Ref::new("DatePartFunctionNameSegment").to_matchable(),
                    Bracketed::new(vec![
                        Delimited::new(vec![
                            Ref::new("DatetimeUnitSegment").to_matchable(),
                            Ref::new("FunctionContentsGrammar")
                                .optional()
                                .to_matchable(),
                        ])
                        .to_matchable(),
                    ])
                    .config(|this| {
                        this.parse_mode = ParseMode::Greedy;
                    })
                    .to_matchable(),
                ])
                .to_matchable(),
            ])
            .to_matchable(),
            Sequence::new(vec![
                Sequence::new(vec![
                    one_of(vec![
                        Ref::new("FunctionNameSegment")
                            .exclude(one_of(vec![
                                Ref::new("DatePartFunctionNameSegment").to_matchable(),
                                Ref::new("ValuesClauseSegment").to_matchable(),
                                Ref::new("ConvertFunctionNameSegment").to_matchable(),
                            ]))
                            .to_matchable(),
                        Sequence::new(vec![
                            Ref::keyword("APPROXIMATE").to_matchable(),
                            Ref::new("FunctionNameSegment")
                                .exclude(one_of(vec![
                                    Ref::new("DatePartFunctionNameSegment").to_matchable(),
                                    Ref::new("ValuesClauseSegment").to_matchable(),
                                    Ref::new("ConvertFunctionNameSegment").to_matchable(),
                                ]))
                                .to_matchable(),
                        ])
                        .to_matchable(),
                    ])
                    .to_matchable(),
                    Bracketed::new(vec![
                        Ref::new("FunctionContentsGrammar")
                            .optional()
                            .to_matchable(),
                    ])
                    .config(|this| {
                        this.parse_mode = ParseMode::Greedy;
                    })
                    .to_matchable(),
                ])
                .to_matchable(),
                Ref::new("PostFunctionGrammar").optional().to_matchable(),
            ])
            .to_matchable(),
            Sequence::new(vec![
                Ref::new("ConvertFunctionNameSegment").to_matchable(),
                Bracketed::new(vec![
                    Ref::new("DatatypeSegment").to_matchable(),
                    Ref::new("CommaSegment").to_matchable(),
                    Ref::new("ExpressionSegment").to_matchable(),
                ])
                .to_matchable(),
            ])
            .to_matchable(),
        ])
        .to_matchable(),
    );

    redshift_dialect.add([]);

    redshift_dialect.replace_grammar(
        "FromClauseSegment",
        Sequence::new(vec![
            Ref::keyword("FROM").to_matchable(),
            Delimited::new(vec![
                optionally_bracketed(vec![Ref::new("FromExpressionSegment").to_matchable()])
                    .to_matchable(),
            ])
            .to_matchable(),
        ])
        .to_matchable(),
    );

    redshift_dialect.add([(
        "CreateViewStatementSegment".into(),
        NodeMatcher::new(SyntaxKind::CreateViewStatement, |_| {
            Sequence::new(vec![
                Ref::keyword("CREATE").to_matchable(),
                Ref::new("OrReplaceGrammar").optional().to_matchable(),
                Ref::keyword("VIEW").to_matchable(),
                Ref::new("IfNotExistsGrammar").optional().to_matchable(),
                Ref::new("TableReferenceSegment").to_matchable(),
                Ref::new("BracketedColumnReferenceListGrammar")
                    .optional()
                    .to_matchable(),
                Ref::keyword("AS").to_matchable(),
                optionally_bracketed(vec![Ref::new("SelectableGrammar").to_matchable()])
                    .to_matchable(),
                Ref::new("WithNoSchemaBindingClauseSegment")
                    .optional()
                    .to_matchable(),
            ])
            .to_matchable()
        })
        .to_matchable()
        .into(),
    )]);
    redshift_dialect.replace_grammar(
        "CreateMaterializedViewStatementSegment",
        Sequence::new(vec![
            Ref::keyword("CREATE").to_matchable(),
            Ref::keyword("MATERIALIZED").to_matchable(),
            Ref::keyword("VIEW").to_matchable(),
            Ref::new("TableReferenceSegment").to_matchable(),
            Sequence::new(vec![
                Ref::keyword("BACKUP").to_matchable(),
                one_of(vec![
                    Ref::keyword("YES").to_matchable(),
                    Ref::keyword("NO").to_matchable(),
                ])
                .to_matchable(),
            ])
            .config(|this| {
                this.optional();
            })
            .to_matchable(),
            Ref::new("TableAttributeSegment").optional().to_matchable(),
            Sequence::new(vec![
                Ref::keyword("AUTO").to_matchable(),
                Ref::keyword("REFRESH").to_matchable(),
                one_of(vec![
                    Ref::keyword("YES").to_matchable(),
                    Ref::keyword("NO").to_matchable(),
                ])
                .to_matchable(),
            ])
            .config(|this| {
                this.optional();
            })
            .to_matchable(),
            Ref::keyword("AS").to_matchable(),
            one_of(vec![
                optionally_bracketed(vec![Ref::new("SelectableGrammar").to_matchable()])
                    .to_matchable(),
                optionally_bracketed(vec![
                    Sequence::new(vec![
                        Ref::keyword("TABLE").to_matchable(),
                        Ref::new("TableReferenceSegment").to_matchable(),
                    ])
                    .to_matchable(),
                ])
                .to_matchable(),
                Ref::new("ValuesClauseSegment").to_matchable(),
                optionally_bracketed(vec![
                    Sequence::new(vec![
                        Ref::keyword("EXECUTE").to_matchable(),
                        Ref::new("FunctionSegment").to_matchable(),
                    ])
                    .to_matchable(),
                ])
                .to_matchable(),
            ])
            .to_matchable(),
            Ref::new("WithDataClauseSegment").optional().to_matchable(),
        ])
        .to_matchable(),
    );
    redshift_dialect.add([
        (
            "CreateExternalFunctionStatementSegment".into(),
            NodeMatcher::new(SyntaxKind::CreateExternalFunctionStatement, |_| {
                Sequence::new(vec![
                    Ref::keyword("CREATE").to_matchable(),
                    Ref::new("OrReplaceGrammar").optional().to_matchable(),
                    Ref::keyword("EXTERNAL").to_matchable(),
                    Ref::keyword("FUNCTION").to_matchable(),
                    Ref::new("FunctionNameSegment").to_matchable(),
                    Bracketed::new(vec![
                        Delimited::new(vec![Ref::new("DatatypeSegment").to_matchable()])
                            .config(|this| {
                                this.optional();
                            })
                            .to_matchable(),
                    ])
                    .to_matchable(),
                    Ref::keyword("RETURNS").to_matchable(),
                    Ref::new("DatatypeSegment").to_matchable(),
                    one_of(vec![
                        Ref::keyword("VOLATILE").to_matchable(),
                        Ref::keyword("STABLE").to_matchable(),
                        Ref::keyword("IMMUTABLE").to_matchable(),
                    ])
                    .to_matchable(),
                    one_of(vec![
                        Ref::keyword("LAMBDA").to_matchable(),
                        Ref::keyword("SAGEMAKER").to_matchable(),
                    ])
                    .to_matchable(),
                    Ref::new("QuotedLiteralSegment").to_matchable(),
                    Ref::keyword("IAM_ROLE").to_matchable(),
                    one_of(vec![
                        Ref::keyword("DEFAULT").to_matchable(),
                        Ref::new("QuotedLiteralSegment").to_matchable(),
                    ])
                    .to_matchable(),
                    Sequence::new(vec![
                        Ref::keyword("RETRY_TIMEOUT").to_matchable(),
                        Ref::new("NumericLiteralSegment").to_matchable(),
                    ])
                    .config(|this| {
                        this.optional();
                    })
                    .to_matchable(),
                ])
                .to_matchable()
            })
            .to_matchable()
            .into(),
        ),
        (
            "QualifyClauseSegment".into(),
            NodeMatcher::new(SyntaxKind::QualifyClause, |_| {
                Sequence::new(vec![
                    Ref::keyword("QUALIFY").to_matchable(),
                    MetaSegment::indent().to_matchable(),
                    Ref::new("ExpressionSegment").to_matchable(),
                    MetaSegment::dedent().to_matchable(),
                ])
                .to_matchable()
            })
            .to_matchable()
            .into(),
        ),
    ]);
    redshift_dialect.replace_grammar(
        "SelectStatementSegment",
        postgres_dialect
            .grammar("SelectStatementSegment")
            .match_grammar(&postgres_dialect)
            .unwrap()
            .copy(
                Some(vec![
                    Ref::new("QualifyClauseSegment").optional().to_matchable(),
                ]),
                None,
                Some(Ref::new("OrderByClauseSegment").optional().to_matchable()),
                None,
                vec![Ref::new("SetOperatorSegment").to_matchable()],
                false,
            ),
    );
    redshift_dialect.add([]);
    redshift_dialect.replace_grammar(
        "UnorderedSelectStatementSegment",
        ansi_dialect
            .grammar("UnorderedSelectStatementSegment")
            .match_grammar(&ansi_dialect)
            .unwrap()
            .copy(
                Some(vec![
                    Ref::new("QualifyClauseSegment").optional().to_matchable(),
                ]),
                None,
                Some(Ref::new("OverlapsClauseSegment").optional().to_matchable()),
                None,
                Vec::new(),
                false,
            ),
    );

    redshift_dialect
}
