use itertools::Itertools;
use sqruff_lib_core::dialects::base::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::{
    any_set_of, one_of, optionally_bracketed, AnyNumberOf,
};
use sqruff_lib_core::parser::grammar::base::{Anything, Nothing, Ref};
use sqruff_lib_core::parser::grammar::delimited::Delimited;
use sqruff_lib_core::parser::grammar::sequence::{Bracketed, Sequence};
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 sqruff_lib_core::vec_of_erased;

use crate::redshift_keywords::{REDSHIFT_RESERVED_KEYWORDS, REDSHIFT_UNRESERVED_KEYWORDS};

pub fn dialect() -> Dialect {
    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_of_erased![
                any_set_of(vec_of_erased![
                    Ref::new("FromPivotExpressionSegment"),
                    Ref::new("FromUnpivotExpressionSegment")
                ])
                .config(|this| {
                    this.min_times = 1;
                }),
                Ref::new("AliasExpressionSegment").optional()
            ])
            .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_of_erased![
                Ref::keyword("BZIP2"),
                Ref::keyword("GZIP"),
                Ref::keyword("LZOP"),
                Ref::keyword("ZSTD")
            ])
            .to_matchable()
            .into(),
        ),
        (
            "ArgModeGrammar".into(),
            one_of(vec_of_erased![
                Ref::keyword("IN"),
                Ref::keyword("OUT"),
                Ref::keyword("INOUT")
            ])
            .to_matchable()
            .into(),
        ),
        (
            "ColumnEncodingGrammar".into(),
            one_of(vec_of_erased![
                Ref::keyword("RAW"),
                Ref::keyword("AZ64"),
                Ref::keyword("BYTEDICT"),
                Ref::keyword("DELTA"),
                Ref::keyword("DELTA32K"),
                Ref::keyword("LZO"),
                Ref::keyword("MOSTLY8"),
                Ref::keyword("MOSTLY16"),
                Ref::keyword("MOSTLY32"),
                Ref::keyword("RUNLENGTH"),
                Ref::keyword("TEXT255"),
                Ref::keyword("TEXT32K"),
                Ref::keyword("ZSTD")
            ])
            .to_matchable()
            .into(),
        ),
        (
            "QuotaGrammar".into(),
            Sequence::new(vec_of_erased![
                Ref::keyword("QUOTA"),
                one_of(vec_of_erased![
                    Sequence::new(vec_of_erased![
                        Ref::new("NumericLiteralSegment"),
                        one_of(vec_of_erased![
                            Ref::keyword("MB"),
                            Ref::keyword("GB"),
                            Ref::keyword("TB")
                        ])
                    ]),
                    Ref::keyword("UNLIMITED")
                ])
            ])
            .to_matchable()
            .into(),
        ),
    ]);

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

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

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

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

    redshift_dialect.add([]);

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

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

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

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

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

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

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

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

    redshift_dialect.add([(
        "ConvertFunctionNameSegment".into(),
        NodeMatcher::new(
            SyntaxKind::FunctionName,
            Sequence::new(vec_of_erased![Ref::keyword("CONVERT")]).to_matchable(),
        )
        .to_matchable()
        .into(),
    )]);

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

    redshift_dialect.add([]);

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

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

    redshift_dialect
}
