Edit on GitHub

sqlglot.parser

   1from __future__ import annotations
   2
   3import logging
   4import typing as t
   5from collections import defaultdict
   6
   7from sqlglot import exp
   8from sqlglot.errors import ErrorLevel, ParseError, concat_messages, merge_errors
   9from sqlglot.helper import apply_index_offset, ensure_list, seq_get
  10from sqlglot.time import format_time
  11from sqlglot.tokens import Token, Tokenizer, TokenType
  12from sqlglot.trie import TrieResult, in_trie, new_trie
  13
  14if t.TYPE_CHECKING:
  15    from sqlglot._typing import E
  16
  17logger = logging.getLogger("sqlglot")
  18
  19
  20def parse_var_map(args: t.List) -> exp.StarMap | exp.VarMap:
  21    if len(args) == 1 and args[0].is_star:
  22        return exp.StarMap(this=args[0])
  23
  24    keys = []
  25    values = []
  26    for i in range(0, len(args), 2):
  27        keys.append(args[i])
  28        values.append(args[i + 1])
  29
  30    return exp.VarMap(
  31        keys=exp.Array(expressions=keys),
  32        values=exp.Array(expressions=values),
  33    )
  34
  35
  36def parse_like(args: t.List) -> exp.Escape | exp.Like:
  37    like = exp.Like(this=seq_get(args, 1), expression=seq_get(args, 0))
  38    return exp.Escape(this=like, expression=seq_get(args, 2)) if len(args) > 2 else like
  39
  40
  41def binary_range_parser(
  42    expr_type: t.Type[exp.Expression],
  43) -> t.Callable[[Parser, t.Optional[exp.Expression]], t.Optional[exp.Expression]]:
  44    return lambda self, this: self._parse_escape(
  45        self.expression(expr_type, this=this, expression=self._parse_bitwise())
  46    )
  47
  48
  49class _Parser(type):
  50    def __new__(cls, clsname, bases, attrs):
  51        klass = super().__new__(cls, clsname, bases, attrs)
  52
  53        klass.SHOW_TRIE = new_trie(key.split(" ") for key in klass.SHOW_PARSERS)
  54        klass.SET_TRIE = new_trie(key.split(" ") for key in klass.SET_PARSERS)
  55
  56        return klass
  57
  58
  59class Parser(metaclass=_Parser):
  60    """
  61    Parser consumes a list of tokens produced by the Tokenizer and produces a parsed syntax tree.
  62
  63    Args:
  64        error_level: The desired error level.
  65            Default: ErrorLevel.IMMEDIATE
  66        error_message_context: Determines the amount of context to capture from a
  67            query string when displaying the error message (in number of characters).
  68            Default: 100
  69        max_errors: Maximum number of error messages to include in a raised ParseError.
  70            This is only relevant if error_level is ErrorLevel.RAISE.
  71            Default: 3
  72    """
  73
  74    FUNCTIONS: t.Dict[str, t.Callable] = {
  75        **{name: f.from_arg_list for f in exp.ALL_FUNCTIONS for name in f.sql_names()},
  76        "DATE_TO_DATE_STR": lambda args: exp.Cast(
  77            this=seq_get(args, 0),
  78            to=exp.DataType(this=exp.DataType.Type.TEXT),
  79        ),
  80        "GLOB": lambda args: exp.Glob(this=seq_get(args, 1), expression=seq_get(args, 0)),
  81        "LIKE": parse_like,
  82        "TIME_TO_TIME_STR": lambda args: exp.Cast(
  83            this=seq_get(args, 0),
  84            to=exp.DataType(this=exp.DataType.Type.TEXT),
  85        ),
  86        "TS_OR_DS_TO_DATE_STR": lambda args: exp.Substring(
  87            this=exp.Cast(
  88                this=seq_get(args, 0),
  89                to=exp.DataType(this=exp.DataType.Type.TEXT),
  90            ),
  91            start=exp.Literal.number(1),
  92            length=exp.Literal.number(10),
  93        ),
  94        "VAR_MAP": parse_var_map,
  95    }
  96
  97    NO_PAREN_FUNCTIONS = {
  98        TokenType.CURRENT_DATE: exp.CurrentDate,
  99        TokenType.CURRENT_DATETIME: exp.CurrentDate,
 100        TokenType.CURRENT_TIME: exp.CurrentTime,
 101        TokenType.CURRENT_TIMESTAMP: exp.CurrentTimestamp,
 102        TokenType.CURRENT_USER: exp.CurrentUser,
 103    }
 104
 105    NESTED_TYPE_TOKENS = {
 106        TokenType.ARRAY,
 107        TokenType.MAP,
 108        TokenType.NULLABLE,
 109        TokenType.STRUCT,
 110    }
 111
 112    ENUM_TYPE_TOKENS = {
 113        TokenType.ENUM,
 114    }
 115
 116    TYPE_TOKENS = {
 117        TokenType.BIT,
 118        TokenType.BOOLEAN,
 119        TokenType.TINYINT,
 120        TokenType.UTINYINT,
 121        TokenType.SMALLINT,
 122        TokenType.USMALLINT,
 123        TokenType.INT,
 124        TokenType.UINT,
 125        TokenType.BIGINT,
 126        TokenType.UBIGINT,
 127        TokenType.INT128,
 128        TokenType.UINT128,
 129        TokenType.INT256,
 130        TokenType.UINT256,
 131        TokenType.FLOAT,
 132        TokenType.DOUBLE,
 133        TokenType.CHAR,
 134        TokenType.NCHAR,
 135        TokenType.VARCHAR,
 136        TokenType.NVARCHAR,
 137        TokenType.TEXT,
 138        TokenType.MEDIUMTEXT,
 139        TokenType.LONGTEXT,
 140        TokenType.MEDIUMBLOB,
 141        TokenType.LONGBLOB,
 142        TokenType.BINARY,
 143        TokenType.VARBINARY,
 144        TokenType.JSON,
 145        TokenType.JSONB,
 146        TokenType.INTERVAL,
 147        TokenType.TIME,
 148        TokenType.TIMESTAMP,
 149        TokenType.TIMESTAMPTZ,
 150        TokenType.TIMESTAMPLTZ,
 151        TokenType.DATETIME,
 152        TokenType.DATETIME64,
 153        TokenType.DATE,
 154        TokenType.INT4RANGE,
 155        TokenType.INT4MULTIRANGE,
 156        TokenType.INT8RANGE,
 157        TokenType.INT8MULTIRANGE,
 158        TokenType.NUMRANGE,
 159        TokenType.NUMMULTIRANGE,
 160        TokenType.TSRANGE,
 161        TokenType.TSMULTIRANGE,
 162        TokenType.TSTZRANGE,
 163        TokenType.TSTZMULTIRANGE,
 164        TokenType.DATERANGE,
 165        TokenType.DATEMULTIRANGE,
 166        TokenType.DECIMAL,
 167        TokenType.BIGDECIMAL,
 168        TokenType.UUID,
 169        TokenType.GEOGRAPHY,
 170        TokenType.GEOMETRY,
 171        TokenType.HLLSKETCH,
 172        TokenType.HSTORE,
 173        TokenType.PSEUDO_TYPE,
 174        TokenType.SUPER,
 175        TokenType.SERIAL,
 176        TokenType.SMALLSERIAL,
 177        TokenType.BIGSERIAL,
 178        TokenType.XML,
 179        TokenType.UNIQUEIDENTIFIER,
 180        TokenType.USERDEFINED,
 181        TokenType.MONEY,
 182        TokenType.SMALLMONEY,
 183        TokenType.ROWVERSION,
 184        TokenType.IMAGE,
 185        TokenType.VARIANT,
 186        TokenType.OBJECT,
 187        TokenType.INET,
 188        TokenType.ENUM,
 189        *NESTED_TYPE_TOKENS,
 190    }
 191
 192    SUBQUERY_PREDICATES = {
 193        TokenType.ANY: exp.Any,
 194        TokenType.ALL: exp.All,
 195        TokenType.EXISTS: exp.Exists,
 196        TokenType.SOME: exp.Any,
 197    }
 198
 199    RESERVED_KEYWORDS = {
 200        *Tokenizer.SINGLE_TOKENS.values(),
 201        TokenType.SELECT,
 202    }
 203
 204    DB_CREATABLES = {
 205        TokenType.DATABASE,
 206        TokenType.SCHEMA,
 207        TokenType.TABLE,
 208        TokenType.VIEW,
 209        TokenType.DICTIONARY,
 210    }
 211
 212    CREATABLES = {
 213        TokenType.COLUMN,
 214        TokenType.FUNCTION,
 215        TokenType.INDEX,
 216        TokenType.PROCEDURE,
 217        *DB_CREATABLES,
 218    }
 219
 220    # Tokens that can represent identifiers
 221    ID_VAR_TOKENS = {
 222        TokenType.VAR,
 223        TokenType.ANTI,
 224        TokenType.APPLY,
 225        TokenType.ASC,
 226        TokenType.AUTO_INCREMENT,
 227        TokenType.BEGIN,
 228        TokenType.CACHE,
 229        TokenType.CASE,
 230        TokenType.COLLATE,
 231        TokenType.COMMAND,
 232        TokenType.COMMENT,
 233        TokenType.COMMIT,
 234        TokenType.CONSTRAINT,
 235        TokenType.DEFAULT,
 236        TokenType.DELETE,
 237        TokenType.DESC,
 238        TokenType.DESCRIBE,
 239        TokenType.DICTIONARY,
 240        TokenType.DIV,
 241        TokenType.END,
 242        TokenType.EXECUTE,
 243        TokenType.ESCAPE,
 244        TokenType.FALSE,
 245        TokenType.FIRST,
 246        TokenType.FILTER,
 247        TokenType.FORMAT,
 248        TokenType.FULL,
 249        TokenType.IF,
 250        TokenType.IS,
 251        TokenType.ISNULL,
 252        TokenType.INTERVAL,
 253        TokenType.KEEP,
 254        TokenType.LEFT,
 255        TokenType.LOAD,
 256        TokenType.MERGE,
 257        TokenType.NATURAL,
 258        TokenType.NEXT,
 259        TokenType.OFFSET,
 260        TokenType.ORDINALITY,
 261        TokenType.OVERWRITE,
 262        TokenType.PARTITION,
 263        TokenType.PERCENT,
 264        TokenType.PIVOT,
 265        TokenType.PRAGMA,
 266        TokenType.RANGE,
 267        TokenType.REFERENCES,
 268        TokenType.RIGHT,
 269        TokenType.ROW,
 270        TokenType.ROWS,
 271        TokenType.SEMI,
 272        TokenType.SET,
 273        TokenType.SETTINGS,
 274        TokenType.SHOW,
 275        TokenType.TEMPORARY,
 276        TokenType.TOP,
 277        TokenType.TRUE,
 278        TokenType.UNIQUE,
 279        TokenType.UNPIVOT,
 280        TokenType.UPDATE,
 281        TokenType.VOLATILE,
 282        TokenType.WINDOW,
 283        *CREATABLES,
 284        *SUBQUERY_PREDICATES,
 285        *TYPE_TOKENS,
 286        *NO_PAREN_FUNCTIONS,
 287    }
 288
 289    INTERVAL_VARS = ID_VAR_TOKENS - {TokenType.END}
 290
 291    TABLE_ALIAS_TOKENS = ID_VAR_TOKENS - {
 292        TokenType.APPLY,
 293        TokenType.ASOF,
 294        TokenType.FULL,
 295        TokenType.LEFT,
 296        TokenType.LOCK,
 297        TokenType.NATURAL,
 298        TokenType.OFFSET,
 299        TokenType.RIGHT,
 300        TokenType.WINDOW,
 301    }
 302
 303    COMMENT_TABLE_ALIAS_TOKENS = TABLE_ALIAS_TOKENS - {TokenType.IS}
 304
 305    UPDATE_ALIAS_TOKENS = TABLE_ALIAS_TOKENS - {TokenType.SET}
 306
 307    TRIM_TYPES = {"LEADING", "TRAILING", "BOTH"}
 308
 309    FUNC_TOKENS = {
 310        TokenType.COMMAND,
 311        TokenType.CURRENT_DATE,
 312        TokenType.CURRENT_DATETIME,
 313        TokenType.CURRENT_TIMESTAMP,
 314        TokenType.CURRENT_TIME,
 315        TokenType.CURRENT_USER,
 316        TokenType.FILTER,
 317        TokenType.FIRST,
 318        TokenType.FORMAT,
 319        TokenType.GLOB,
 320        TokenType.IDENTIFIER,
 321        TokenType.INDEX,
 322        TokenType.ISNULL,
 323        TokenType.ILIKE,
 324        TokenType.LIKE,
 325        TokenType.MERGE,
 326        TokenType.OFFSET,
 327        TokenType.PRIMARY_KEY,
 328        TokenType.RANGE,
 329        TokenType.REPLACE,
 330        TokenType.ROW,
 331        TokenType.UNNEST,
 332        TokenType.VAR,
 333        TokenType.LEFT,
 334        TokenType.RIGHT,
 335        TokenType.DATE,
 336        TokenType.DATETIME,
 337        TokenType.TABLE,
 338        TokenType.TIMESTAMP,
 339        TokenType.TIMESTAMPTZ,
 340        TokenType.WINDOW,
 341        *TYPE_TOKENS,
 342        *SUBQUERY_PREDICATES,
 343    }
 344
 345    CONJUNCTION = {
 346        TokenType.AND: exp.And,
 347        TokenType.OR: exp.Or,
 348    }
 349
 350    EQUALITY = {
 351        TokenType.EQ: exp.EQ,
 352        TokenType.NEQ: exp.NEQ,
 353        TokenType.NULLSAFE_EQ: exp.NullSafeEQ,
 354    }
 355
 356    COMPARISON = {
 357        TokenType.GT: exp.GT,
 358        TokenType.GTE: exp.GTE,
 359        TokenType.LT: exp.LT,
 360        TokenType.LTE: exp.LTE,
 361    }
 362
 363    BITWISE = {
 364        TokenType.AMP: exp.BitwiseAnd,
 365        TokenType.CARET: exp.BitwiseXor,
 366        TokenType.PIPE: exp.BitwiseOr,
 367        TokenType.DPIPE: exp.DPipe,
 368    }
 369
 370    TERM = {
 371        TokenType.DASH: exp.Sub,
 372        TokenType.PLUS: exp.Add,
 373        TokenType.MOD: exp.Mod,
 374        TokenType.COLLATE: exp.Collate,
 375    }
 376
 377    FACTOR = {
 378        TokenType.DIV: exp.IntDiv,
 379        TokenType.LR_ARROW: exp.Distance,
 380        TokenType.SLASH: exp.Div,
 381        TokenType.STAR: exp.Mul,
 382    }
 383
 384    TIMESTAMPS = {
 385        TokenType.TIME,
 386        TokenType.TIMESTAMP,
 387        TokenType.TIMESTAMPTZ,
 388        TokenType.TIMESTAMPLTZ,
 389    }
 390
 391    SET_OPERATIONS = {
 392        TokenType.UNION,
 393        TokenType.INTERSECT,
 394        TokenType.EXCEPT,
 395    }
 396
 397    JOIN_METHODS = {
 398        TokenType.NATURAL,
 399        TokenType.ASOF,
 400    }
 401
 402    JOIN_SIDES = {
 403        TokenType.LEFT,
 404        TokenType.RIGHT,
 405        TokenType.FULL,
 406    }
 407
 408    JOIN_KINDS = {
 409        TokenType.INNER,
 410        TokenType.OUTER,
 411        TokenType.CROSS,
 412        TokenType.SEMI,
 413        TokenType.ANTI,
 414    }
 415
 416    JOIN_HINTS: t.Set[str] = set()
 417
 418    LAMBDAS = {
 419        TokenType.ARROW: lambda self, expressions: self.expression(
 420            exp.Lambda,
 421            this=self._replace_lambda(
 422                self._parse_conjunction(),
 423                {node.name for node in expressions},
 424            ),
 425            expressions=expressions,
 426        ),
 427        TokenType.FARROW: lambda self, expressions: self.expression(
 428            exp.Kwarg,
 429            this=exp.var(expressions[0].name),
 430            expression=self._parse_conjunction(),
 431        ),
 432    }
 433
 434    COLUMN_OPERATORS = {
 435        TokenType.DOT: None,
 436        TokenType.DCOLON: lambda self, this, to: self.expression(
 437            exp.Cast if self.STRICT_CAST else exp.TryCast,
 438            this=this,
 439            to=to,
 440        ),
 441        TokenType.ARROW: lambda self, this, path: self.expression(
 442            exp.JSONExtract,
 443            this=this,
 444            expression=path,
 445        ),
 446        TokenType.DARROW: lambda self, this, path: self.expression(
 447            exp.JSONExtractScalar,
 448            this=this,
 449            expression=path,
 450        ),
 451        TokenType.HASH_ARROW: lambda self, this, path: self.expression(
 452            exp.JSONBExtract,
 453            this=this,
 454            expression=path,
 455        ),
 456        TokenType.DHASH_ARROW: lambda self, this, path: self.expression(
 457            exp.JSONBExtractScalar,
 458            this=this,
 459            expression=path,
 460        ),
 461        TokenType.PLACEHOLDER: lambda self, this, key: self.expression(
 462            exp.JSONBContains,
 463            this=this,
 464            expression=key,
 465        ),
 466    }
 467
 468    EXPRESSION_PARSERS = {
 469        exp.Cluster: lambda self: self._parse_sort(exp.Cluster, TokenType.CLUSTER_BY),
 470        exp.Column: lambda self: self._parse_column(),
 471        exp.Condition: lambda self: self._parse_conjunction(),
 472        exp.DataType: lambda self: self._parse_types(),
 473        exp.Expression: lambda self: self._parse_statement(),
 474        exp.From: lambda self: self._parse_from(),
 475        exp.Group: lambda self: self._parse_group(),
 476        exp.Having: lambda self: self._parse_having(),
 477        exp.Identifier: lambda self: self._parse_id_var(),
 478        exp.Join: lambda self: self._parse_join(),
 479        exp.Lambda: lambda self: self._parse_lambda(),
 480        exp.Lateral: lambda self: self._parse_lateral(),
 481        exp.Limit: lambda self: self._parse_limit(),
 482        exp.Offset: lambda self: self._parse_offset(),
 483        exp.Order: lambda self: self._parse_order(),
 484        exp.Ordered: lambda self: self._parse_ordered(),
 485        exp.Properties: lambda self: self._parse_properties(),
 486        exp.Qualify: lambda self: self._parse_qualify(),
 487        exp.Returning: lambda self: self._parse_returning(),
 488        exp.Sort: lambda self: self._parse_sort(exp.Sort, TokenType.SORT_BY),
 489        exp.Table: lambda self: self._parse_table_parts(),
 490        exp.TableAlias: lambda self: self._parse_table_alias(),
 491        exp.Where: lambda self: self._parse_where(),
 492        exp.Window: lambda self: self._parse_named_window(),
 493        exp.With: lambda self: self._parse_with(),
 494        "JOIN_TYPE": lambda self: self._parse_join_parts(),
 495    }
 496
 497    STATEMENT_PARSERS = {
 498        TokenType.ALTER: lambda self: self._parse_alter(),
 499        TokenType.BEGIN: lambda self: self._parse_transaction(),
 500        TokenType.CACHE: lambda self: self._parse_cache(),
 501        TokenType.COMMIT: lambda self: self._parse_commit_or_rollback(),
 502        TokenType.COMMENT: lambda self: self._parse_comment(),
 503        TokenType.CREATE: lambda self: self._parse_create(),
 504        TokenType.DELETE: lambda self: self._parse_delete(),
 505        TokenType.DESC: lambda self: self._parse_describe(),
 506        TokenType.DESCRIBE: lambda self: self._parse_describe(),
 507        TokenType.DROP: lambda self: self._parse_drop(),
 508        TokenType.END: lambda self: self._parse_commit_or_rollback(),
 509        TokenType.FROM: lambda self: exp.select("*").from_(
 510            t.cast(exp.From, self._parse_from(skip_from_token=True))
 511        ),
 512        TokenType.INSERT: lambda self: self._parse_insert(),
 513        TokenType.LOAD: lambda self: self._parse_load(),
 514        TokenType.MERGE: lambda self: self._parse_merge(),
 515        TokenType.PIVOT: lambda self: self._parse_simplified_pivot(),
 516        TokenType.PRAGMA: lambda self: self.expression(exp.Pragma, this=self._parse_expression()),
 517        TokenType.ROLLBACK: lambda self: self._parse_commit_or_rollback(),
 518        TokenType.SET: lambda self: self._parse_set(),
 519        TokenType.UNCACHE: lambda self: self._parse_uncache(),
 520        TokenType.UPDATE: lambda self: self._parse_update(),
 521        TokenType.USE: lambda self: self.expression(
 522            exp.Use,
 523            kind=self._match_texts(("ROLE", "WAREHOUSE", "DATABASE", "SCHEMA"))
 524            and exp.var(self._prev.text),
 525            this=self._parse_table(schema=False),
 526        ),
 527    }
 528
 529    UNARY_PARSERS = {
 530        TokenType.PLUS: lambda self: self._parse_unary(),  # Unary + is handled as a no-op
 531        TokenType.NOT: lambda self: self.expression(exp.Not, this=self._parse_equality()),
 532        TokenType.TILDA: lambda self: self.expression(exp.BitwiseNot, this=self._parse_unary()),
 533        TokenType.DASH: lambda self: self.expression(exp.Neg, this=self._parse_unary()),
 534    }
 535
 536    PRIMARY_PARSERS = {
 537        TokenType.STRING: lambda self, token: self.expression(
 538            exp.Literal, this=token.text, is_string=True
 539        ),
 540        TokenType.NUMBER: lambda self, token: self.expression(
 541            exp.Literal, this=token.text, is_string=False
 542        ),
 543        TokenType.STAR: lambda self, _: self.expression(
 544            exp.Star, **{"except": self._parse_except(), "replace": self._parse_replace()}
 545        ),
 546        TokenType.NULL: lambda self, _: self.expression(exp.Null),
 547        TokenType.TRUE: lambda self, _: self.expression(exp.Boolean, this=True),
 548        TokenType.FALSE: lambda self, _: self.expression(exp.Boolean, this=False),
 549        TokenType.BIT_STRING: lambda self, token: self.expression(exp.BitString, this=token.text),
 550        TokenType.HEX_STRING: lambda self, token: self.expression(exp.HexString, this=token.text),
 551        TokenType.BYTE_STRING: lambda self, token: self.expression(exp.ByteString, this=token.text),
 552        TokenType.INTRODUCER: lambda self, token: self._parse_introducer(token),
 553        TokenType.NATIONAL_STRING: lambda self, token: self.expression(
 554            exp.National, this=token.text
 555        ),
 556        TokenType.RAW_STRING: lambda self, token: self.expression(exp.RawString, this=token.text),
 557        TokenType.SESSION_PARAMETER: lambda self, _: self._parse_session_parameter(),
 558    }
 559
 560    PLACEHOLDER_PARSERS = {
 561        TokenType.PLACEHOLDER: lambda self: self.expression(exp.Placeholder),
 562        TokenType.PARAMETER: lambda self: self._parse_parameter(),
 563        TokenType.COLON: lambda self: self.expression(exp.Placeholder, this=self._prev.text)
 564        if self._match_set((TokenType.NUMBER, TokenType.VAR))
 565        else None,
 566    }
 567
 568    RANGE_PARSERS = {
 569        TokenType.BETWEEN: lambda self, this: self._parse_between(this),
 570        TokenType.GLOB: binary_range_parser(exp.Glob),
 571        TokenType.ILIKE: binary_range_parser(exp.ILike),
 572        TokenType.IN: lambda self, this: self._parse_in(this),
 573        TokenType.IRLIKE: binary_range_parser(exp.RegexpILike),
 574        TokenType.IS: lambda self, this: self._parse_is(this),
 575        TokenType.LIKE: binary_range_parser(exp.Like),
 576        TokenType.OVERLAPS: binary_range_parser(exp.Overlaps),
 577        TokenType.RLIKE: binary_range_parser(exp.RegexpLike),
 578        TokenType.SIMILAR_TO: binary_range_parser(exp.SimilarTo),
 579    }
 580
 581    PROPERTY_PARSERS: t.Dict[str, t.Callable] = {
 582        "ALGORITHM": lambda self: self._parse_property_assignment(exp.AlgorithmProperty),
 583        "AUTO_INCREMENT": lambda self: self._parse_property_assignment(exp.AutoIncrementProperty),
 584        "BLOCKCOMPRESSION": lambda self: self._parse_blockcompression(),
 585        "CHARACTER SET": lambda self: self._parse_character_set(),
 586        "CHECKSUM": lambda self: self._parse_checksum(),
 587        "CLUSTER BY": lambda self: self._parse_cluster(),
 588        "COLLATE": lambda self: self._parse_property_assignment(exp.CollateProperty),
 589        "COMMENT": lambda self: self._parse_property_assignment(exp.SchemaCommentProperty),
 590        "COPY": lambda self: self._parse_copy_property(),
 591        "DATABLOCKSIZE": lambda self, **kwargs: self._parse_datablocksize(**kwargs),
 592        "DEFINER": lambda self: self._parse_definer(),
 593        "DETERMINISTIC": lambda self: self.expression(
 594            exp.StabilityProperty, this=exp.Literal.string("IMMUTABLE")
 595        ),
 596        "DISTKEY": lambda self: self._parse_distkey(),
 597        "DISTSTYLE": lambda self: self._parse_property_assignment(exp.DistStyleProperty),
 598        "ENGINE": lambda self: self._parse_property_assignment(exp.EngineProperty),
 599        "EXECUTE": lambda self: self._parse_property_assignment(exp.ExecuteAsProperty),
 600        "EXTERNAL": lambda self: self.expression(exp.ExternalProperty),
 601        "FALLBACK": lambda self, **kwargs: self._parse_fallback(**kwargs),
 602        "FORMAT": lambda self: self._parse_property_assignment(exp.FileFormatProperty),
 603        "FREESPACE": lambda self: self._parse_freespace(),
 604        "IMMUTABLE": lambda self: self.expression(
 605            exp.StabilityProperty, this=exp.Literal.string("IMMUTABLE")
 606        ),
 607        "JOURNAL": lambda self, **kwargs: self._parse_journal(**kwargs),
 608        "LANGUAGE": lambda self: self._parse_property_assignment(exp.LanguageProperty),
 609        "LAYOUT": lambda self: self._parse_dict_property(this="LAYOUT"),
 610        "LIFETIME": lambda self: self._parse_dict_range(this="LIFETIME"),
 611        "LIKE": lambda self: self._parse_create_like(),
 612        "LOCATION": lambda self: self._parse_property_assignment(exp.LocationProperty),
 613        "LOCK": lambda self: self._parse_locking(),
 614        "LOCKING": lambda self: self._parse_locking(),
 615        "LOG": lambda self, **kwargs: self._parse_log(**kwargs),
 616        "MATERIALIZED": lambda self: self.expression(exp.MaterializedProperty),
 617        "MERGEBLOCKRATIO": lambda self, **kwargs: self._parse_mergeblockratio(**kwargs),
 618        "MULTISET": lambda self: self.expression(exp.SetProperty, multi=True),
 619        "NO": lambda self: self._parse_no_property(),
 620        "ON": lambda self: self._parse_on_property(),
 621        "ORDER BY": lambda self: self._parse_order(skip_order_token=True),
 622        "PARTITION BY": lambda self: self._parse_partitioned_by(),
 623        "PARTITIONED BY": lambda self: self._parse_partitioned_by(),
 624        "PARTITIONED_BY": lambda self: self._parse_partitioned_by(),
 625        "PRIMARY KEY": lambda self: self._parse_primary_key(in_props=True),
 626        "RANGE": lambda self: self._parse_dict_range(this="RANGE"),
 627        "RETURNS": lambda self: self._parse_returns(),
 628        "ROW": lambda self: self._parse_row(),
 629        "ROW_FORMAT": lambda self: self._parse_property_assignment(exp.RowFormatProperty),
 630        "SET": lambda self: self.expression(exp.SetProperty, multi=False),
 631        "SETTINGS": lambda self: self.expression(
 632            exp.SettingsProperty, expressions=self._parse_csv(self._parse_set_item)
 633        ),
 634        "SORTKEY": lambda self: self._parse_sortkey(),
 635        "SOURCE": lambda self: self._parse_dict_property(this="SOURCE"),
 636        "STABLE": lambda self: self.expression(
 637            exp.StabilityProperty, this=exp.Literal.string("STABLE")
 638        ),
 639        "STORED": lambda self: self._parse_stored(),
 640        "TBLPROPERTIES": lambda self: self._parse_wrapped_csv(self._parse_property),
 641        "TEMP": lambda self: self.expression(exp.TemporaryProperty),
 642        "TEMPORARY": lambda self: self.expression(exp.TemporaryProperty),
 643        "TO": lambda self: self._parse_to_table(),
 644        "TRANSIENT": lambda self: self.expression(exp.TransientProperty),
 645        "TTL": lambda self: self._parse_ttl(),
 646        "USING": lambda self: self._parse_property_assignment(exp.FileFormatProperty),
 647        "VOLATILE": lambda self: self._parse_volatile_property(),
 648        "WITH": lambda self: self._parse_with_property(),
 649    }
 650
 651    CONSTRAINT_PARSERS = {
 652        "AUTOINCREMENT": lambda self: self._parse_auto_increment(),
 653        "AUTO_INCREMENT": lambda self: self._parse_auto_increment(),
 654        "CASESPECIFIC": lambda self: self.expression(exp.CaseSpecificColumnConstraint, not_=False),
 655        "CHARACTER SET": lambda self: self.expression(
 656            exp.CharacterSetColumnConstraint, this=self._parse_var_or_string()
 657        ),
 658        "CHECK": lambda self: self.expression(
 659            exp.CheckColumnConstraint, this=self._parse_wrapped(self._parse_conjunction)
 660        ),
 661        "COLLATE": lambda self: self.expression(
 662            exp.CollateColumnConstraint, this=self._parse_var()
 663        ),
 664        "COMMENT": lambda self: self.expression(
 665            exp.CommentColumnConstraint, this=self._parse_string()
 666        ),
 667        "COMPRESS": lambda self: self._parse_compress(),
 668        "DEFAULT": lambda self: self.expression(
 669            exp.DefaultColumnConstraint, this=self._parse_bitwise()
 670        ),
 671        "ENCODE": lambda self: self.expression(exp.EncodeColumnConstraint, this=self._parse_var()),
 672        "FOREIGN KEY": lambda self: self._parse_foreign_key(),
 673        "FORMAT": lambda self: self.expression(
 674            exp.DateFormatColumnConstraint, this=self._parse_var_or_string()
 675        ),
 676        "GENERATED": lambda self: self._parse_generated_as_identity(),
 677        "IDENTITY": lambda self: self._parse_auto_increment(),
 678        "INLINE": lambda self: self._parse_inline(),
 679        "LIKE": lambda self: self._parse_create_like(),
 680        "NOT": lambda self: self._parse_not_constraint(),
 681        "NULL": lambda self: self.expression(exp.NotNullColumnConstraint, allow_null=True),
 682        "ON": lambda self: self._match(TokenType.UPDATE)
 683        and self.expression(exp.OnUpdateColumnConstraint, this=self._parse_function()),
 684        "PATH": lambda self: self.expression(exp.PathColumnConstraint, this=self._parse_string()),
 685        "PRIMARY KEY": lambda self: self._parse_primary_key(),
 686        "REFERENCES": lambda self: self._parse_references(match=False),
 687        "TITLE": lambda self: self.expression(
 688            exp.TitleColumnConstraint, this=self._parse_var_or_string()
 689        ),
 690        "TTL": lambda self: self.expression(exp.MergeTreeTTL, expressions=[self._parse_bitwise()]),
 691        "UNIQUE": lambda self: self._parse_unique(),
 692        "UPPERCASE": lambda self: self.expression(exp.UppercaseColumnConstraint),
 693    }
 694
 695    ALTER_PARSERS = {
 696        "ADD": lambda self: self._parse_alter_table_add(),
 697        "ALTER": lambda self: self._parse_alter_table_alter(),
 698        "DELETE": lambda self: self.expression(exp.Delete, where=self._parse_where()),
 699        "DROP": lambda self: self._parse_alter_table_drop(),
 700        "RENAME": lambda self: self._parse_alter_table_rename(),
 701    }
 702
 703    SCHEMA_UNNAMED_CONSTRAINTS = {"CHECK", "FOREIGN KEY", "LIKE", "PRIMARY KEY", "UNIQUE"}
 704
 705    NO_PAREN_FUNCTION_PARSERS = {
 706        TokenType.ANY: lambda self: self.expression(exp.Any, this=self._parse_bitwise()),
 707        TokenType.CASE: lambda self: self._parse_case(),
 708        TokenType.IF: lambda self: self._parse_if(),
 709        TokenType.NEXT_VALUE_FOR: lambda self: self.expression(
 710            exp.NextValueFor,
 711            this=self._parse_column(),
 712            order=self._match(TokenType.OVER) and self._parse_wrapped(self._parse_order),
 713        ),
 714    }
 715
 716    FUNCTIONS_WITH_ALIASED_ARGS = {"STRUCT"}
 717
 718    FUNCTION_PARSERS: t.Dict[str, t.Callable] = {
 719        "CAST": lambda self: self._parse_cast(self.STRICT_CAST),
 720        "CONCAT": lambda self: self._parse_concat(),
 721        "CONVERT": lambda self: self._parse_convert(self.STRICT_CAST),
 722        "DECODE": lambda self: self._parse_decode(),
 723        "EXTRACT": lambda self: self._parse_extract(),
 724        "JSON_OBJECT": lambda self: self._parse_json_object(),
 725        "LOG": lambda self: self._parse_logarithm(),
 726        "MATCH": lambda self: self._parse_match_against(),
 727        "OPENJSON": lambda self: self._parse_open_json(),
 728        "POSITION": lambda self: self._parse_position(),
 729        "SAFE_CAST": lambda self: self._parse_cast(False),
 730        "STRING_AGG": lambda self: self._parse_string_agg(),
 731        "SUBSTRING": lambda self: self._parse_substring(),
 732        "TRIM": lambda self: self._parse_trim(),
 733        "TRY_CAST": lambda self: self._parse_cast(False),
 734        "TRY_CONVERT": lambda self: self._parse_convert(False),
 735    }
 736
 737    QUERY_MODIFIER_PARSERS = {
 738        "joins": lambda self: list(iter(self._parse_join, None)),
 739        "laterals": lambda self: list(iter(self._parse_lateral, None)),
 740        "match": lambda self: self._parse_match_recognize(),
 741        "where": lambda self: self._parse_where(),
 742        "group": lambda self: self._parse_group(),
 743        "having": lambda self: self._parse_having(),
 744        "qualify": lambda self: self._parse_qualify(),
 745        "windows": lambda self: self._parse_window_clause(),
 746        "order": lambda self: self._parse_order(),
 747        "limit": lambda self: self._parse_limit(),
 748        "offset": lambda self: self._parse_offset(),
 749        "locks": lambda self: self._parse_locks(),
 750        "sample": lambda self: self._parse_table_sample(as_modifier=True),
 751    }
 752
 753    SET_PARSERS = {
 754        "GLOBAL": lambda self: self._parse_set_item_assignment("GLOBAL"),
 755        "LOCAL": lambda self: self._parse_set_item_assignment("LOCAL"),
 756        "SESSION": lambda self: self._parse_set_item_assignment("SESSION"),
 757        "TRANSACTION": lambda self: self._parse_set_transaction(),
 758    }
 759
 760    SHOW_PARSERS: t.Dict[str, t.Callable] = {}
 761
 762    TYPE_LITERAL_PARSERS: t.Dict[exp.DataType.Type, t.Callable] = {}
 763
 764    MODIFIABLES = (exp.Subquery, exp.Subqueryable, exp.Table)
 765
 766    DDL_SELECT_TOKENS = {TokenType.SELECT, TokenType.WITH, TokenType.L_PAREN}
 767
 768    PRE_VOLATILE_TOKENS = {TokenType.CREATE, TokenType.REPLACE, TokenType.UNIQUE}
 769
 770    TRANSACTION_KIND = {"DEFERRED", "IMMEDIATE", "EXCLUSIVE"}
 771    TRANSACTION_CHARACTERISTICS = {
 772        "ISOLATION LEVEL REPEATABLE READ",
 773        "ISOLATION LEVEL READ COMMITTED",
 774        "ISOLATION LEVEL READ UNCOMMITTED",
 775        "ISOLATION LEVEL SERIALIZABLE",
 776        "READ WRITE",
 777        "READ ONLY",
 778    }
 779
 780    INSERT_ALTERNATIVES = {"ABORT", "FAIL", "IGNORE", "REPLACE", "ROLLBACK"}
 781
 782    CLONE_KINDS = {"TIMESTAMP", "OFFSET", "STATEMENT"}
 783
 784    TABLE_INDEX_HINT_TOKENS = {TokenType.FORCE, TokenType.IGNORE, TokenType.USE}
 785
 786    WINDOW_ALIAS_TOKENS = ID_VAR_TOKENS - {TokenType.ROWS}
 787    WINDOW_BEFORE_PAREN_TOKENS = {TokenType.OVER}
 788    WINDOW_SIDES = {"FOLLOWING", "PRECEDING"}
 789
 790    ADD_CONSTRAINT_TOKENS = {TokenType.CONSTRAINT, TokenType.PRIMARY_KEY, TokenType.FOREIGN_KEY}
 791
 792    STRICT_CAST = True
 793
 794    # A NULL arg in CONCAT yields NULL by default
 795    CONCAT_NULL_OUTPUTS_STRING = False
 796
 797    CONVERT_TYPE_FIRST = False
 798
 799    PREFIXED_PIVOT_COLUMNS = False
 800    IDENTIFY_PIVOT_STRINGS = False
 801
 802    LOG_BASE_FIRST = True
 803    LOG_DEFAULTS_TO_LN = False
 804
 805    __slots__ = (
 806        "error_level",
 807        "error_message_context",
 808        "max_errors",
 809        "sql",
 810        "errors",
 811        "_tokens",
 812        "_index",
 813        "_curr",
 814        "_next",
 815        "_prev",
 816        "_prev_comments",
 817    )
 818
 819    # Autofilled
 820    INDEX_OFFSET: int = 0
 821    UNNEST_COLUMN_ONLY: bool = False
 822    ALIAS_POST_TABLESAMPLE: bool = False
 823    STRICT_STRING_CONCAT = False
 824    NULL_ORDERING: str = "nulls_are_small"
 825    SHOW_TRIE: t.Dict = {}
 826    SET_TRIE: t.Dict = {}
 827    FORMAT_MAPPING: t.Dict[str, str] = {}
 828    FORMAT_TRIE: t.Dict = {}
 829    TIME_MAPPING: t.Dict[str, str] = {}
 830    TIME_TRIE: t.Dict = {}
 831
 832    def __init__(
 833        self,
 834        error_level: t.Optional[ErrorLevel] = None,
 835        error_message_context: int = 100,
 836        max_errors: int = 3,
 837    ):
 838        self.error_level = error_level or ErrorLevel.IMMEDIATE
 839        self.error_message_context = error_message_context
 840        self.max_errors = max_errors
 841        self.reset()
 842
 843    def reset(self):
 844        self.sql = ""
 845        self.errors = []
 846        self._tokens = []
 847        self._index = 0
 848        self._curr = None
 849        self._next = None
 850        self._prev = None
 851        self._prev_comments = None
 852
 853    def parse(
 854        self, raw_tokens: t.List[Token], sql: t.Optional[str] = None
 855    ) -> t.List[t.Optional[exp.Expression]]:
 856        """
 857        Parses a list of tokens and returns a list of syntax trees, one tree
 858        per parsed SQL statement.
 859
 860        Args:
 861            raw_tokens: The list of tokens.
 862            sql: The original SQL string, used to produce helpful debug messages.
 863
 864        Returns:
 865            The list of the produced syntax trees.
 866        """
 867        return self._parse(
 868            parse_method=self.__class__._parse_statement, raw_tokens=raw_tokens, sql=sql
 869        )
 870
 871    def parse_into(
 872        self,
 873        expression_types: exp.IntoType,
 874        raw_tokens: t.List[Token],
 875        sql: t.Optional[str] = None,
 876    ) -> t.List[t.Optional[exp.Expression]]:
 877        """
 878        Parses a list of tokens into a given Expression type. If a collection of Expression
 879        types is given instead, this method will try to parse the token list into each one
 880        of them, stopping at the first for which the parsing succeeds.
 881
 882        Args:
 883            expression_types: The expression type(s) to try and parse the token list into.
 884            raw_tokens: The list of tokens.
 885            sql: The original SQL string, used to produce helpful debug messages.
 886
 887        Returns:
 888            The target Expression.
 889        """
 890        errors = []
 891        for expression_type in ensure_list(expression_types):
 892            parser = self.EXPRESSION_PARSERS.get(expression_type)
 893            if not parser:
 894                raise TypeError(f"No parser registered for {expression_type}")
 895
 896            try:
 897                return self._parse(parser, raw_tokens, sql)
 898            except ParseError as e:
 899                e.errors[0]["into_expression"] = expression_type
 900                errors.append(e)
 901
 902        raise ParseError(
 903            f"Failed to parse '{sql or raw_tokens}' into {expression_types}",
 904            errors=merge_errors(errors),
 905        ) from errors[-1]
 906
 907    def _parse(
 908        self,
 909        parse_method: t.Callable[[Parser], t.Optional[exp.Expression]],
 910        raw_tokens: t.List[Token],
 911        sql: t.Optional[str] = None,
 912    ) -> t.List[t.Optional[exp.Expression]]:
 913        self.reset()
 914        self.sql = sql or ""
 915
 916        total = len(raw_tokens)
 917        chunks: t.List[t.List[Token]] = [[]]
 918
 919        for i, token in enumerate(raw_tokens):
 920            if token.token_type == TokenType.SEMICOLON:
 921                if i < total - 1:
 922                    chunks.append([])
 923            else:
 924                chunks[-1].append(token)
 925
 926        expressions = []
 927
 928        for tokens in chunks:
 929            self._index = -1
 930            self._tokens = tokens
 931            self._advance()
 932
 933            expressions.append(parse_method(self))
 934
 935            if self._index < len(self._tokens):
 936                self.raise_error("Invalid expression / Unexpected token")
 937
 938            self.check_errors()
 939
 940        return expressions
 941
 942    def check_errors(self) -> None:
 943        """Logs or raises any found errors, depending on the chosen error level setting."""
 944        if self.error_level == ErrorLevel.WARN:
 945            for error in self.errors:
 946                logger.error(str(error))
 947        elif self.error_level == ErrorLevel.RAISE and self.errors:
 948            raise ParseError(
 949                concat_messages(self.errors, self.max_errors),
 950                errors=merge_errors(self.errors),
 951            )
 952
 953    def raise_error(self, message: str, token: t.Optional[Token] = None) -> None:
 954        """
 955        Appends an error in the list of recorded errors or raises it, depending on the chosen
 956        error level setting.
 957        """
 958        token = token or self._curr or self._prev or Token.string("")
 959        start = token.start
 960        end = token.end + 1
 961        start_context = self.sql[max(start - self.error_message_context, 0) : start]
 962        highlight = self.sql[start:end]
 963        end_context = self.sql[end : end + self.error_message_context]
 964
 965        error = ParseError.new(
 966            f"{message}. Line {token.line}, Col: {token.col}.\n"
 967            f"  {start_context}\033[4m{highlight}\033[0m{end_context}",
 968            description=message,
 969            line=token.line,
 970            col=token.col,
 971            start_context=start_context,
 972            highlight=highlight,
 973            end_context=end_context,
 974        )
 975
 976        if self.error_level == ErrorLevel.IMMEDIATE:
 977            raise error
 978
 979        self.errors.append(error)
 980
 981    def expression(
 982        self, exp_class: t.Type[E], comments: t.Optional[t.List[str]] = None, **kwargs
 983    ) -> E:
 984        """
 985        Creates a new, validated Expression.
 986
 987        Args:
 988            exp_class: The expression class to instantiate.
 989            comments: An optional list of comments to attach to the expression.
 990            kwargs: The arguments to set for the expression along with their respective values.
 991
 992        Returns:
 993            The target expression.
 994        """
 995        instance = exp_class(**kwargs)
 996        instance.add_comments(comments) if comments else self._add_comments(instance)
 997        return self.validate_expression(instance)
 998
 999    def _add_comments(self, expression: t.Optional[exp.Expression]) -> None:
1000        if expression and self._prev_comments:
1001            expression.add_comments(self._prev_comments)
1002            self._prev_comments = None
1003
1004    def validate_expression(self, expression: E, args: t.Optional[t.List] = None) -> E:
1005        """
1006        Validates an Expression, making sure that all its mandatory arguments are set.
1007
1008        Args:
1009            expression: The expression to validate.
1010            args: An optional list of items that was used to instantiate the expression, if it's a Func.
1011
1012        Returns:
1013            The validated expression.
1014        """
1015        if self.error_level != ErrorLevel.IGNORE:
1016            for error_message in expression.error_messages(args):
1017                self.raise_error(error_message)
1018
1019        return expression
1020
1021    def _find_sql(self, start: Token, end: Token) -> str:
1022        return self.sql[start.start : end.end + 1]
1023
1024    def _advance(self, times: int = 1) -> None:
1025        self._index += times
1026        self._curr = seq_get(self._tokens, self._index)
1027        self._next = seq_get(self._tokens, self._index + 1)
1028
1029        if self._index > 0:
1030            self._prev = self._tokens[self._index - 1]
1031            self._prev_comments = self._prev.comments
1032        else:
1033            self._prev = None
1034            self._prev_comments = None
1035
1036    def _retreat(self, index: int) -> None:
1037        if index != self._index:
1038            self._advance(index - self._index)
1039
1040    def _parse_command(self) -> exp.Command:
1041        return self.expression(exp.Command, this=self._prev.text, expression=self._parse_string())
1042
1043    def _parse_comment(self, allow_exists: bool = True) -> exp.Expression:
1044        start = self._prev
1045        exists = self._parse_exists() if allow_exists else None
1046
1047        self._match(TokenType.ON)
1048
1049        kind = self._match_set(self.CREATABLES) and self._prev
1050        if not kind:
1051            return self._parse_as_command(start)
1052
1053        if kind.token_type in (TokenType.FUNCTION, TokenType.PROCEDURE):
1054            this = self._parse_user_defined_function(kind=kind.token_type)
1055        elif kind.token_type == TokenType.TABLE:
1056            this = self._parse_table(alias_tokens=self.COMMENT_TABLE_ALIAS_TOKENS)
1057        elif kind.token_type == TokenType.COLUMN:
1058            this = self._parse_column()
1059        else:
1060            this = self._parse_id_var()
1061
1062        self._match(TokenType.IS)
1063
1064        return self.expression(
1065            exp.Comment, this=this, kind=kind.text, expression=self._parse_string(), exists=exists
1066        )
1067
1068    def _parse_to_table(
1069        self,
1070    ) -> exp.ToTableProperty:
1071        table = self._parse_table_parts(schema=True)
1072        return self.expression(exp.ToTableProperty, this=table)
1073
1074    # https://clickhouse.com/docs/en/engines/table-engines/mergetree-family/mergetree#mergetree-table-ttl
1075    def _parse_ttl(self) -> exp.Expression:
1076        def _parse_ttl_action() -> t.Optional[exp.Expression]:
1077            this = self._parse_bitwise()
1078
1079            if self._match_text_seq("DELETE"):
1080                return self.expression(exp.MergeTreeTTLAction, this=this, delete=True)
1081            if self._match_text_seq("RECOMPRESS"):
1082                return self.expression(
1083                    exp.MergeTreeTTLAction, this=this, recompress=self._parse_bitwise()
1084                )
1085            if self._match_text_seq("TO", "DISK"):
1086                return self.expression(
1087                    exp.MergeTreeTTLAction, this=this, to_disk=self._parse_string()
1088                )
1089            if self._match_text_seq("TO", "VOLUME"):
1090                return self.expression(
1091                    exp.MergeTreeTTLAction, this=this, to_volume=self._parse_string()
1092                )
1093
1094            return this
1095
1096        expressions = self._parse_csv(_parse_ttl_action)
1097        where = self._parse_where()
1098        group = self._parse_group()
1099
1100        aggregates = None
1101        if group and self._match(TokenType.SET):
1102            aggregates = self._parse_csv(self._parse_set_item)
1103
1104        return self.expression(
1105            exp.MergeTreeTTL,
1106            expressions=expressions,
1107            where=where,
1108            group=group,
1109            aggregates=aggregates,
1110        )
1111
1112    def _parse_statement(self) -> t.Optional[exp.Expression]:
1113        if self._curr is None:
1114            return None
1115
1116        if self._match_set(self.STATEMENT_PARSERS):
1117            return self.STATEMENT_PARSERS[self._prev.token_type](self)
1118
1119        if self._match_set(Tokenizer.COMMANDS):
1120            return self._parse_command()
1121
1122        expression = self._parse_expression()
1123        expression = self._parse_set_operations(expression) if expression else self._parse_select()
1124        return self._parse_query_modifiers(expression)
1125
1126    def _parse_drop(self) -> exp.Drop | exp.Command:
1127        start = self._prev
1128        temporary = self._match(TokenType.TEMPORARY)
1129        materialized = self._match_text_seq("MATERIALIZED")
1130
1131        kind = self._match_set(self.CREATABLES) and self._prev.text
1132        if not kind:
1133            return self._parse_as_command(start)
1134
1135        return self.expression(
1136            exp.Drop,
1137            exists=self._parse_exists(),
1138            this=self._parse_table(schema=True),
1139            kind=kind,
1140            temporary=temporary,
1141            materialized=materialized,
1142            cascade=self._match_text_seq("CASCADE"),
1143            constraints=self._match_text_seq("CONSTRAINTS"),
1144            purge=self._match_text_seq("PURGE"),
1145        )
1146
1147    def _parse_exists(self, not_: bool = False) -> t.Optional[bool]:
1148        return (
1149            self._match(TokenType.IF)
1150            and (not not_ or self._match(TokenType.NOT))
1151            and self._match(TokenType.EXISTS)
1152        )
1153
1154    def _parse_create(self) -> exp.Create | exp.Command:
1155        # Note: this can't be None because we've matched a statement parser
1156        start = self._prev
1157        replace = start.text.upper() == "REPLACE" or self._match_pair(
1158            TokenType.OR, TokenType.REPLACE
1159        )
1160        unique = self._match(TokenType.UNIQUE)
1161
1162        if self._match_pair(TokenType.TABLE, TokenType.FUNCTION, advance=False):
1163            self._advance()
1164
1165        properties = None
1166        create_token = self._match_set(self.CREATABLES) and self._prev
1167
1168        if not create_token:
1169            # exp.Properties.Location.POST_CREATE
1170            properties = self._parse_properties()
1171            create_token = self._match_set(self.CREATABLES) and self._prev
1172
1173            if not properties or not create_token:
1174                return self._parse_as_command(start)
1175
1176        exists = self._parse_exists(not_=True)
1177        this = None
1178        expression = None
1179        indexes = None
1180        no_schema_binding = None
1181        begin = None
1182        clone = None
1183
1184        def extend_props(temp_props: t.Optional[exp.Properties]) -> None:
1185            nonlocal properties
1186            if properties and temp_props:
1187                properties.expressions.extend(temp_props.expressions)
1188            elif temp_props:
1189                properties = temp_props
1190
1191        if create_token.token_type in (TokenType.FUNCTION, TokenType.PROCEDURE):
1192            this = self._parse_user_defined_function(kind=create_token.token_type)
1193
1194            # exp.Properties.Location.POST_SCHEMA ("schema" here is the UDF's type signature)
1195            extend_props(self._parse_properties())
1196
1197            self._match(TokenType.ALIAS)
1198            begin = self._match(TokenType.BEGIN)
1199            return_ = self._match_text_seq("RETURN")
1200            expression = self._parse_statement()
1201
1202            if return_:
1203                expression = self.expression(exp.Return, this=expression)
1204        elif create_token.token_type == TokenType.INDEX:
1205            this = self._parse_index(index=self._parse_id_var())
1206        elif create_token.token_type in self.DB_CREATABLES:
1207            table_parts = self._parse_table_parts(schema=True)
1208
1209            # exp.Properties.Location.POST_NAME
1210            self._match(TokenType.COMMA)
1211            extend_props(self._parse_properties(before=True))
1212
1213            this = self._parse_schema(this=table_parts)
1214
1215            # exp.Properties.Location.POST_SCHEMA and POST_WITH
1216            extend_props(self._parse_properties())
1217
1218            self._match(TokenType.ALIAS)
1219            if not self._match_set(self.DDL_SELECT_TOKENS, advance=False):
1220                # exp.Properties.Location.POST_ALIAS
1221                extend_props(self._parse_properties())
1222
1223            expression = self._parse_ddl_select()
1224
1225            if create_token.token_type == TokenType.TABLE:
1226                indexes = []
1227                while True:
1228                    index = self._parse_index()
1229
1230                    # exp.Properties.Location.POST_EXPRESSION and POST_INDEX
1231                    extend_props(self._parse_properties())
1232
1233                    if not index:
1234                        break
1235                    else:
1236                        self._match(TokenType.COMMA)
1237                        indexes.append(index)
1238            elif create_token.token_type == TokenType.VIEW:
1239                if self._match_text_seq("WITH", "NO", "SCHEMA", "BINDING"):
1240                    no_schema_binding = True
1241
1242            if self._match_text_seq("CLONE"):
1243                clone = self._parse_table(schema=True)
1244                when = self._match_texts({"AT", "BEFORE"}) and self._prev.text.upper()
1245                clone_kind = (
1246                    self._match(TokenType.L_PAREN)
1247                    and self._match_texts(self.CLONE_KINDS)
1248                    and self._prev.text.upper()
1249                )
1250                clone_expression = self._match(TokenType.FARROW) and self._parse_bitwise()
1251                self._match(TokenType.R_PAREN)
1252                clone = self.expression(
1253                    exp.Clone, this=clone, when=when, kind=clone_kind, expression=clone_expression
1254                )
1255
1256        return self.expression(
1257            exp.Create,
1258            this=this,
1259            kind=create_token.text,
1260            replace=replace,
1261            unique=unique,
1262            expression=expression,
1263            exists=exists,
1264            properties=properties,
1265            indexes=indexes,
1266            no_schema_binding=no_schema_binding,
1267            begin=begin,
1268            clone=clone,
1269        )
1270
1271    def _parse_property_before(self) -> t.Optional[exp.Expression]:
1272        # only used for teradata currently
1273        self._match(TokenType.COMMA)
1274
1275        kwargs = {
1276            "no": self._match_text_seq("NO"),
1277            "dual": self._match_text_seq("DUAL"),
1278            "before": self._match_text_seq("BEFORE"),
1279            "default": self._match_text_seq("DEFAULT"),
1280            "local": (self._match_text_seq("LOCAL") and "LOCAL")
1281            or (self._match_text_seq("NOT", "LOCAL") and "NOT LOCAL"),
1282            "after": self._match_text_seq("AFTER"),
1283            "minimum": self._match_texts(("MIN", "MINIMUM")),
1284            "maximum": self._match_texts(("MAX", "MAXIMUM")),
1285        }
1286
1287        if self._match_texts(self.PROPERTY_PARSERS):
1288            parser = self.PROPERTY_PARSERS[self._prev.text.upper()]
1289            try:
1290                return parser(self, **{k: v for k, v in kwargs.items() if v})
1291            except TypeError:
1292                self.raise_error(f"Cannot parse property '{self._prev.text}'")
1293
1294        return None
1295
1296    def _parse_property(self) -> t.Optional[exp.Expression]:
1297        if self._match_texts(self.PROPERTY_PARSERS):
1298            return self.PROPERTY_PARSERS[self._prev.text.upper()](self)
1299
1300        if self._match_pair(TokenType.DEFAULT, TokenType.CHARACTER_SET):
1301            return self._parse_character_set(default=True)
1302
1303        if self._match_text_seq("COMPOUND", "SORTKEY"):
1304            return self._parse_sortkey(compound=True)
1305
1306        if self._match_text_seq("SQL", "SECURITY"):
1307            return self.expression(exp.SqlSecurityProperty, definer=self._match_text_seq("DEFINER"))
1308
1309        assignment = self._match_pair(
1310            TokenType.VAR, TokenType.EQ, advance=False
1311        ) or self._match_pair(TokenType.STRING, TokenType.EQ, advance=False)
1312
1313        if assignment:
1314            key = self._parse_var_or_string()
1315            self._match(TokenType.EQ)
1316            return self.expression(exp.Property, this=key, value=self._parse_column())
1317
1318        return None
1319
1320    def _parse_stored(self) -> exp.FileFormatProperty:
1321        self._match(TokenType.ALIAS)
1322
1323        input_format = self._parse_string() if self._match_text_seq("INPUTFORMAT") else None
1324        output_format = self._parse_string() if self._match_text_seq("OUTPUTFORMAT") else None
1325
1326        return self.expression(
1327            exp.FileFormatProperty,
1328            this=self.expression(
1329                exp.InputOutputFormat, input_format=input_format, output_format=output_format
1330            )
1331            if input_format or output_format
1332            else self._parse_var_or_string() or self._parse_number() or self._parse_id_var(),
1333        )
1334
1335    def _parse_property_assignment(self, exp_class: t.Type[E]) -> E:
1336        self._match(TokenType.EQ)
1337        self._match(TokenType.ALIAS)
1338        return self.expression(exp_class, this=self._parse_field())
1339
1340    def _parse_properties(self, before: t.Optional[bool] = None) -> t.Optional[exp.Properties]:
1341        properties = []
1342        while True:
1343            if before:
1344                prop = self._parse_property_before()
1345            else:
1346                prop = self._parse_property()
1347
1348            if not prop:
1349                break
1350            for p in ensure_list(prop):
1351                properties.append(p)
1352
1353        if properties:
1354            return self.expression(exp.Properties, expressions=properties)
1355
1356        return None
1357
1358    def _parse_fallback(self, no: bool = False) -> exp.FallbackProperty:
1359        return self.expression(
1360            exp.FallbackProperty, no=no, protection=self._match_text_seq("PROTECTION")
1361        )
1362
1363    def _parse_volatile_property(self) -> exp.VolatileProperty | exp.StabilityProperty:
1364        if self._index >= 2:
1365            pre_volatile_token = self._tokens[self._index - 2]
1366        else:
1367            pre_volatile_token = None
1368
1369        if pre_volatile_token and pre_volatile_token.token_type in self.PRE_VOLATILE_TOKENS:
1370            return exp.VolatileProperty()
1371
1372        return self.expression(exp.StabilityProperty, this=exp.Literal.string("VOLATILE"))
1373
1374    def _parse_with_property(
1375        self,
1376    ) -> t.Optional[exp.Expression] | t.List[t.Optional[exp.Expression]]:
1377        self._match(TokenType.WITH)
1378        if self._match(TokenType.L_PAREN, advance=False):
1379            return self._parse_wrapped_csv(self._parse_property)
1380
1381        if self._match_text_seq("JOURNAL"):
1382            return self._parse_withjournaltable()
1383
1384        if self._match_text_seq("DATA"):
1385            return self._parse_withdata(no=False)
1386        elif self._match_text_seq("NO", "DATA"):
1387            return self._parse_withdata(no=True)
1388
1389        if not self._next:
1390            return None
1391
1392        return self._parse_withisolatedloading()
1393
1394    # https://dev.mysql.com/doc/refman/8.0/en/create-view.html
1395    def _parse_definer(self) -> t.Optional[exp.DefinerProperty]:
1396        self._match(TokenType.EQ)
1397
1398        user = self._parse_id_var()
1399        self._match(TokenType.PARAMETER)
1400        host = self._parse_id_var() or (self._match(TokenType.MOD) and self._prev.text)
1401
1402        if not user or not host:
1403            return None
1404
1405        return exp.DefinerProperty(this=f"{user}@{host}")
1406
1407    def _parse_withjournaltable(self) -> exp.WithJournalTableProperty:
1408        self._match(TokenType.TABLE)
1409        self._match(TokenType.EQ)
1410        return self.expression(exp.WithJournalTableProperty, this=self._parse_table_parts())
1411
1412    def _parse_log(self, no: bool = False) -> exp.LogProperty:
1413        return self.expression(exp.LogProperty, no=no)
1414
1415    def _parse_journal(self, **kwargs) -> exp.JournalProperty:
1416        return self.expression(exp.JournalProperty, **kwargs)
1417
1418    def _parse_checksum(self) -> exp.ChecksumProperty:
1419        self._match(TokenType.EQ)
1420
1421        on = None
1422        if self._match(TokenType.ON):
1423            on = True
1424        elif self._match_text_seq("OFF"):
1425            on = False
1426
1427        return self.expression(exp.ChecksumProperty, on=on, default=self._match(TokenType.DEFAULT))
1428
1429    def _parse_cluster(self) -> t.Optional[exp.Cluster]:
1430        return self.expression(exp.Cluster, expressions=self._parse_csv(self._parse_ordered))
1431
1432    def _parse_copy_property(self) -> t.Optional[exp.CopyGrantsProperty]:
1433        if not self._match_text_seq("GRANTS"):
1434            self._retreat(self._index - 1)
1435            return None
1436
1437        return self.expression(exp.CopyGrantsProperty)
1438
1439    def _parse_freespace(self) -> exp.FreespaceProperty:
1440        self._match(TokenType.EQ)
1441        return self.expression(
1442            exp.FreespaceProperty, this=self._parse_number(), percent=self._match(TokenType.PERCENT)
1443        )
1444
1445    def _parse_mergeblockratio(
1446        self, no: bool = False, default: bool = False
1447    ) -> exp.MergeBlockRatioProperty:
1448        if self._match(TokenType.EQ):
1449            return self.expression(
1450                exp.MergeBlockRatioProperty,
1451                this=self._parse_number(),
1452                percent=self._match(TokenType.PERCENT),
1453            )
1454
1455        return self.expression(exp.MergeBlockRatioProperty, no=no, default=default)
1456
1457    def _parse_datablocksize(
1458        self,
1459        default: t.Optional[bool] = None,
1460        minimum: t.Optional[bool] = None,
1461        maximum: t.Optional[bool] = None,
1462    ) -> exp.DataBlocksizeProperty:
1463        self._match(TokenType.EQ)
1464        size = self._parse_number()
1465
1466        units = None
1467        if self._match_texts(("BYTES", "KBYTES", "KILOBYTES")):
1468            units = self._prev.text
1469
1470        return self.expression(
1471            exp.DataBlocksizeProperty,
1472            size=size,
1473            units=units,
1474            default=default,
1475            minimum=minimum,
1476            maximum=maximum,
1477        )
1478
1479    def _parse_blockcompression(self) -> exp.BlockCompressionProperty:
1480        self._match(TokenType.EQ)
1481        always = self._match_text_seq("ALWAYS")
1482        manual = self._match_text_seq("MANUAL")
1483        never = self._match_text_seq("NEVER")
1484        default = self._match_text_seq("DEFAULT")
1485
1486        autotemp = None
1487        if self._match_text_seq("AUTOTEMP"):
1488            autotemp = self._parse_schema()
1489
1490        return self.expression(
1491            exp.BlockCompressionProperty,
1492            always=always,
1493            manual=manual,
1494            never=never,
1495            default=default,
1496            autotemp=autotemp,
1497        )
1498
1499    def _parse_withisolatedloading(self) -> exp.IsolatedLoadingProperty:
1500        no = self._match_text_seq("NO")
1501        concurrent = self._match_text_seq("CONCURRENT")
1502        self._match_text_seq("ISOLATED", "LOADING")
1503        for_all = self._match_text_seq("FOR", "ALL")
1504        for_insert = self._match_text_seq("FOR", "INSERT")
1505        for_none = self._match_text_seq("FOR", "NONE")
1506        return self.expression(
1507            exp.IsolatedLoadingProperty,
1508            no=no,
1509            concurrent=concurrent,
1510            for_all=for_all,
1511            for_insert=for_insert,
1512            for_none=for_none,
1513        )
1514
1515    def _parse_locking(self) -> exp.LockingProperty:
1516        if self._match(TokenType.TABLE):
1517            kind = "TABLE"
1518        elif self._match(TokenType.VIEW):
1519            kind = "VIEW"
1520        elif self._match(TokenType.ROW):
1521            kind = "ROW"
1522        elif self._match_text_seq("DATABASE"):
1523            kind = "DATABASE"
1524        else:
1525            kind = None
1526
1527        if kind in ("DATABASE", "TABLE", "VIEW"):
1528            this = self._parse_table_parts()
1529        else:
1530            this = None
1531
1532        if self._match(TokenType.FOR):
1533            for_or_in = "FOR"
1534        elif self._match(TokenType.IN):
1535            for_or_in = "IN"
1536        else:
1537            for_or_in = None
1538
1539        if self._match_text_seq("ACCESS"):
1540            lock_type = "ACCESS"
1541        elif self._match_texts(("EXCL", "EXCLUSIVE")):
1542            lock_type = "EXCLUSIVE"
1543        elif self._match_text_seq("SHARE"):
1544            lock_type = "SHARE"
1545        elif self._match_text_seq("READ"):
1546            lock_type = "READ"
1547        elif self._match_text_seq("WRITE"):
1548            lock_type = "WRITE"
1549        elif self._match_text_seq("CHECKSUM"):
1550            lock_type = "CHECKSUM"
1551        else:
1552            lock_type = None
1553
1554        override = self._match_text_seq("OVERRIDE")
1555
1556        return self.expression(
1557            exp.LockingProperty,
1558            this=this,
1559            kind=kind,
1560            for_or_in=for_or_in,
1561            lock_type=lock_type,
1562            override=override,
1563        )
1564
1565    def _parse_partition_by(self) -> t.List[t.Optional[exp.Expression]]:
1566        if self._match(TokenType.PARTITION_BY):
1567            return self._parse_csv(self._parse_conjunction)
1568        return []
1569
1570    def _parse_partitioned_by(self) -> exp.PartitionedByProperty:
1571        self._match(TokenType.EQ)
1572        return self.expression(
1573            exp.PartitionedByProperty,
1574            this=self._parse_schema() or self._parse_bracket(self._parse_field()),
1575        )
1576
1577    def _parse_withdata(self, no: bool = False) -> exp.WithDataProperty:
1578        if self._match_text_seq("AND", "STATISTICS"):
1579            statistics = True
1580        elif self._match_text_seq("AND", "NO", "STATISTICS"):
1581            statistics = False
1582        else:
1583            statistics = None
1584
1585        return self.expression(exp.WithDataProperty, no=no, statistics=statistics)
1586
1587    def _parse_no_property(self) -> t.Optional[exp.NoPrimaryIndexProperty]:
1588        if self._match_text_seq("PRIMARY", "INDEX"):
1589            return exp.NoPrimaryIndexProperty()
1590        return None
1591
1592    def _parse_on_property(self) -> t.Optional[exp.Expression]:
1593        if self._match_text_seq("COMMIT", "PRESERVE", "ROWS"):
1594            return exp.OnCommitProperty()
1595        elif self._match_text_seq("COMMIT", "DELETE", "ROWS"):
1596            return exp.OnCommitProperty(delete=True)
1597        return None
1598
1599    def _parse_distkey(self) -> exp.DistKeyProperty:
1600        return self.expression(exp.DistKeyProperty, this=self._parse_wrapped(self._parse_id_var))
1601
1602    def _parse_create_like(self) -> t.Optional[exp.LikeProperty]:
1603        table = self._parse_table(schema=True)
1604
1605        options = []
1606        while self._match_texts(("INCLUDING", "EXCLUDING")):
1607            this = self._prev.text.upper()
1608
1609            id_var = self._parse_id_var()
1610            if not id_var:
1611                return None
1612
1613            options.append(
1614                self.expression(exp.Property, this=this, value=exp.var(id_var.this.upper()))
1615            )
1616
1617        return self.expression(exp.LikeProperty, this=table, expressions=options)
1618
1619    def _parse_sortkey(self, compound: bool = False) -> exp.SortKeyProperty:
1620        return self.expression(
1621            exp.SortKeyProperty, this=self._parse_wrapped_id_vars(), compound=compound
1622        )
1623
1624    def _parse_character_set(self, default: bool = False) -> exp.CharacterSetProperty:
1625        self._match(TokenType.EQ)
1626        return self.expression(
1627            exp.CharacterSetProperty, this=self._parse_var_or_string(), default=default
1628        )
1629
1630    def _parse_returns(self) -> exp.ReturnsProperty:
1631        value: t.Optional[exp.Expression]
1632        is_table = self._match(TokenType.TABLE)
1633
1634        if is_table:
1635            if self._match(TokenType.LT):
1636                value = self.expression(
1637                    exp.Schema,
1638                    this="TABLE",
1639                    expressions=self._parse_csv(self._parse_struct_types),
1640                )
1641                if not self._match(TokenType.GT):
1642                    self.raise_error("Expecting >")
1643            else:
1644                value = self._parse_schema(exp.var("TABLE"))
1645        else:
1646            value = self._parse_types()
1647
1648        return self.expression(exp.ReturnsProperty, this=value, is_table=is_table)
1649
1650    def _parse_describe(self) -> exp.Describe:
1651        kind = self._match_set(self.CREATABLES) and self._prev.text
1652        this = self._parse_table()
1653        return self.expression(exp.Describe, this=this, kind=kind)
1654
1655    def _parse_insert(self) -> exp.Insert:
1656        overwrite = self._match(TokenType.OVERWRITE)
1657        local = self._match_text_seq("LOCAL")
1658        alternative = None
1659
1660        if self._match_text_seq("DIRECTORY"):
1661            this: t.Optional[exp.Expression] = self.expression(
1662                exp.Directory,
1663                this=self._parse_var_or_string(),
1664                local=local,
1665                row_format=self._parse_row_format(match_row=True),
1666            )
1667        else:
1668            if self._match(TokenType.OR):
1669                alternative = self._match_texts(self.INSERT_ALTERNATIVES) and self._prev.text
1670
1671            self._match(TokenType.INTO)
1672            self._match(TokenType.TABLE)
1673            this = self._parse_table(schema=True)
1674
1675        return self.expression(
1676            exp.Insert,
1677            this=this,
1678            exists=self._parse_exists(),
1679            partition=self._parse_partition(),
1680            where=self._match_pair(TokenType.REPLACE, TokenType.WHERE)
1681            and self._parse_conjunction(),
1682            expression=self._parse_ddl_select(),
1683            conflict=self._parse_on_conflict(),
1684            returning=self._parse_returning(),
1685            overwrite=overwrite,
1686            alternative=alternative,
1687        )
1688
1689    def _parse_on_conflict(self) -> t.Optional[exp.OnConflict]:
1690        conflict = self._match_text_seq("ON", "CONFLICT")
1691        duplicate = self._match_text_seq("ON", "DUPLICATE", "KEY")
1692
1693        if not conflict and not duplicate:
1694            return None
1695
1696        nothing = None
1697        expressions = None
1698        key = None
1699        constraint = None
1700
1701        if conflict:
1702            if self._match_text_seq("ON", "CONSTRAINT"):
1703                constraint = self._parse_id_var()
1704            else:
1705                key = self._parse_csv(self._parse_value)
1706
1707        self._match_text_seq("DO")
1708        if self._match_text_seq("NOTHING"):
1709            nothing = True
1710        else:
1711            self._match(TokenType.UPDATE)
1712            expressions = self._match(TokenType.SET) and self._parse_csv(self._parse_equality)
1713
1714        return self.expression(
1715            exp.OnConflict,
1716            duplicate=duplicate,
1717            expressions=expressions,
1718            nothing=nothing,
1719            key=key,
1720            constraint=constraint,
1721        )
1722
1723    def _parse_returning(self) -> t.Optional[exp.Returning]:
1724        if not self._match(TokenType.RETURNING):
1725            return None
1726
1727        return self.expression(exp.Returning, expressions=self._parse_csv(self._parse_column))
1728
1729    def _parse_row(self) -> t.Optional[exp.RowFormatSerdeProperty | exp.RowFormatDelimitedProperty]:
1730        if not self._match(TokenType.FORMAT):
1731            return None
1732        return self._parse_row_format()
1733
1734    def _parse_row_format(
1735        self, match_row: bool = False
1736    ) -> t.Optional[exp.RowFormatSerdeProperty | exp.RowFormatDelimitedProperty]:
1737        if match_row and not self._match_pair(TokenType.ROW, TokenType.FORMAT):
1738            return None
1739
1740        if self._match_text_seq("SERDE"):
1741            return self.expression(exp.RowFormatSerdeProperty, this=self._parse_string())
1742
1743        self._match_text_seq("DELIMITED")
1744
1745        kwargs = {}
1746
1747        if self._match_text_seq("FIELDS", "TERMINATED", "BY"):
1748            kwargs["fields"] = self._parse_string()
1749            if self._match_text_seq("ESCAPED", "BY"):
1750                kwargs["escaped"] = self._parse_string()
1751        if self._match_text_seq("COLLECTION", "ITEMS", "TERMINATED", "BY"):
1752            kwargs["collection_items"] = self._parse_string()
1753        if self._match_text_seq("MAP", "KEYS", "TERMINATED", "BY"):
1754            kwargs["map_keys"] = self._parse_string()
1755        if self._match_text_seq("LINES", "TERMINATED", "BY"):
1756            kwargs["lines"] = self._parse_string()
1757        if self._match_text_seq("NULL", "DEFINED", "AS"):
1758            kwargs["null"] = self._parse_string()
1759
1760        return self.expression(exp.RowFormatDelimitedProperty, **kwargs)  # type: ignore
1761
1762    def _parse_load(self) -> exp.LoadData | exp.Command:
1763        if self._match_text_seq("DATA"):
1764            local = self._match_text_seq("LOCAL")
1765            self._match_text_seq("INPATH")
1766            inpath = self._parse_string()
1767            overwrite = self._match(TokenType.OVERWRITE)
1768            self._match_pair(TokenType.INTO, TokenType.TABLE)
1769
1770            return self.expression(
1771                exp.LoadData,
1772                this=self._parse_table(schema=True),
1773                local=local,
1774                overwrite=overwrite,
1775                inpath=inpath,
1776                partition=self._parse_partition(),
1777                input_format=self._match_text_seq("INPUTFORMAT") and self._parse_string(),
1778                serde=self._match_text_seq("SERDE") and self._parse_string(),
1779            )
1780        return self._parse_as_command(self._prev)
1781
1782    def _parse_delete(self) -> exp.Delete:
1783        self._match(TokenType.FROM)
1784
1785        return self.expression(
1786            exp.Delete,
1787            this=self._parse_table(),
1788            using=self._parse_csv(lambda: self._match(TokenType.USING) and self._parse_table()),
1789            where=self._parse_where(),
1790            returning=self._parse_returning(),
1791            limit=self._parse_limit(),
1792        )
1793
1794    def _parse_update(self) -> exp.Update:
1795        return self.expression(
1796            exp.Update,
1797            **{  # type: ignore
1798                "this": self._parse_table(alias_tokens=self.UPDATE_ALIAS_TOKENS),
1799                "expressions": self._match(TokenType.SET) and self._parse_csv(self._parse_equality),
1800                "from": self._parse_from(modifiers=True),
1801                "where": self._parse_where(),
1802                "returning": self._parse_returning(),
1803                "limit": self._parse_limit(),
1804            },
1805        )
1806
1807    def _parse_uncache(self) -> exp.Uncache:
1808        if not self._match(TokenType.TABLE):
1809            self.raise_error("Expecting TABLE after UNCACHE")
1810
1811        return self.expression(
1812            exp.Uncache, exists=self._parse_exists(), this=self._parse_table(schema=True)
1813        )
1814
1815    def _parse_cache(self) -> exp.Cache:
1816        lazy = self._match_text_seq("LAZY")
1817        self._match(TokenType.TABLE)
1818        table = self._parse_table(schema=True)
1819
1820        options = []
1821        if self._match_text_seq("OPTIONS"):
1822            self._match_l_paren()
1823            k = self._parse_string()
1824            self._match(TokenType.EQ)
1825            v = self._parse_string()
1826            options = [k, v]
1827            self._match_r_paren()
1828
1829        self._match(TokenType.ALIAS)
1830        return self.expression(
1831            exp.Cache,
1832            this=table,
1833            lazy=lazy,
1834            options=options,
1835            expression=self._parse_select(nested=True),
1836        )
1837
1838    def _parse_partition(self) -> t.Optional[exp.Partition]:
1839        if not self._match(TokenType.PARTITION):
1840            return None
1841
1842        return self.expression(
1843            exp.Partition, expressions=self._parse_wrapped_csv(self._parse_conjunction)
1844        )
1845
1846    def _parse_value(self) -> exp.Tuple:
1847        if self._match(TokenType.L_PAREN):
1848            expressions = self._parse_csv(self._parse_conjunction)
1849            self._match_r_paren()
1850            return self.expression(exp.Tuple, expressions=expressions)
1851
1852        # In presto we can have VALUES 1, 2 which results in 1 column & 2 rows.
1853        # Source: https://prestodb.io/docs/current/sql/values.html
1854        return self.expression(exp.Tuple, expressions=[self._parse_conjunction()])
1855
1856    def _parse_select(
1857        self, nested: bool = False, table: bool = False, parse_subquery_alias: bool = True
1858    ) -> t.Optional[exp.Expression]:
1859        cte = self._parse_with()
1860        if cte:
1861            this = self._parse_statement()
1862
1863            if not this:
1864                self.raise_error("Failed to parse any statement following CTE")
1865                return cte
1866
1867            if "with" in this.arg_types:
1868                this.set("with", cte)
1869            else:
1870                self.raise_error(f"{this.key} does not support CTE")
1871                this = cte
1872        elif self._match(TokenType.SELECT):
1873            comments = self._prev_comments
1874
1875            hint = self._parse_hint()
1876            all_ = self._match(TokenType.ALL)
1877            distinct = self._match(TokenType.DISTINCT)
1878
1879            kind = (
1880                self._match(TokenType.ALIAS)
1881                and self._match_texts(("STRUCT", "VALUE"))
1882                and self._prev.text
1883            )
1884
1885            if distinct:
1886                distinct = self.expression(
1887                    exp.Distinct,
1888                    on=self._parse_value() if self._match(TokenType.ON) else None,
1889                )
1890
1891            if all_ and distinct:
1892                self.raise_error("Cannot specify both ALL and DISTINCT after SELECT")
1893
1894            limit = self._parse_limit(top=True)
1895            expressions = self._parse_csv(self._parse_expression)
1896
1897            this = self.expression(
1898                exp.Select,
1899                kind=kind,
1900                hint=hint,
1901                distinct=distinct,
1902                expressions=expressions,
1903                limit=limit,
1904            )
1905            this.comments = comments
1906
1907            into = self._parse_into()
1908            if into:
1909                this.set("into", into)
1910
1911            from_ = self._parse_from()
1912            if from_:
1913                this.set("from", from_)
1914
1915            this = self._parse_query_modifiers(this)
1916        elif (table or nested) and self._match(TokenType.L_PAREN):
1917            if self._match(TokenType.PIVOT):
1918                this = self._parse_simplified_pivot()
1919            elif self._match(TokenType.FROM):
1920                this = exp.select("*").from_(
1921                    t.cast(exp.From, self._parse_from(skip_from_token=True))
1922                )
1923            else:
1924                this = self._parse_table() if table else self._parse_select(nested=True)
1925                this = self._parse_set_operations(self._parse_query_modifiers(this))
1926
1927            self._match_r_paren()
1928
1929            # early return so that subquery unions aren't parsed again
1930            # SELECT * FROM (SELECT 1) UNION ALL SELECT 1
1931            # Union ALL should be a property of the top select node, not the subquery
1932            return self._parse_subquery(this, parse_alias=parse_subquery_alias)
1933        elif self._match(TokenType.VALUES):
1934            this = self.expression(
1935                exp.Values,
1936                expressions=self._parse_csv(self._parse_value),
1937                alias=self._parse_table_alias(),
1938            )
1939        else:
1940            this = None
1941
1942        return self._parse_set_operations(this)
1943
1944    def _parse_with(self, skip_with_token: bool = False) -> t.Optional[exp.With]:
1945        if not skip_with_token and not self._match(TokenType.WITH):
1946            return None
1947
1948        comments = self._prev_comments
1949        recursive = self._match(TokenType.RECURSIVE)
1950
1951        expressions = []
1952        while True:
1953            expressions.append(self._parse_cte())
1954
1955            if not self._match(TokenType.COMMA) and not self._match(TokenType.WITH):
1956                break
1957            else:
1958                self._match(TokenType.WITH)
1959
1960        return self.expression(
1961            exp.With, comments=comments, expressions=expressions, recursive=recursive
1962        )
1963
1964    def _parse_cte(self) -> exp.CTE:
1965        alias = self._parse_table_alias()
1966        if not alias or not alias.this:
1967            self.raise_error("Expected CTE to have alias")
1968
1969        self._match(TokenType.ALIAS)
1970        return self.expression(
1971            exp.CTE, this=self._parse_wrapped(self._parse_statement), alias=alias
1972        )
1973
1974    def _parse_table_alias(
1975        self, alias_tokens: t.Optional[t.Collection[TokenType]] = None
1976    ) -> t.Optional[exp.TableAlias]:
1977        any_token = self._match(TokenType.ALIAS)
1978        alias = (
1979            self._parse_id_var(any_token=any_token, tokens=alias_tokens or self.TABLE_ALIAS_TOKENS)
1980            or self._parse_string_as_identifier()
1981        )
1982
1983        index = self._index
1984        if self._match(TokenType.L_PAREN):
1985            columns = self._parse_csv(self._parse_function_parameter)
1986            self._match_r_paren() if columns else self._retreat(index)
1987        else:
1988            columns = None
1989
1990        if not alias and not columns:
1991            return None
1992
1993        return self.expression(exp.TableAlias, this=alias, columns=columns)
1994
1995    def _parse_subquery(
1996        self, this: t.Optional[exp.Expression], parse_alias: bool = True
1997    ) -> t.Optional[exp.Subquery]:
1998        if not this:
1999            return None
2000
2001        return self.expression(
2002            exp.Subquery,
2003            this=this,
2004            pivots=self._parse_pivots(),
2005            alias=self._parse_table_alias() if parse_alias else None,
2006        )
2007
2008    def _parse_query_modifiers(
2009        self, this: t.Optional[exp.Expression]
2010    ) -> t.Optional[exp.Expression]:
2011        if isinstance(this, self.MODIFIABLES):
2012            for key, parser in self.QUERY_MODIFIER_PARSERS.items():
2013                expression = parser(self)
2014
2015                if expression:
2016                    if key == "limit":
2017                        offset = expression.args.pop("offset", None)
2018                        if offset:
2019                            this.set("offset", exp.Offset(expression=offset))
2020                    this.set(key, expression)
2021        return this
2022
2023    def _parse_hint(self) -> t.Optional[exp.Hint]:
2024        if self._match(TokenType.HINT):
2025            hints = self._parse_csv(self._parse_function)
2026
2027            if not self._match_pair(TokenType.STAR, TokenType.SLASH):
2028                self.raise_error("Expected */ after HINT")
2029
2030            return self.expression(exp.Hint, expressions=hints)
2031
2032        return None
2033
2034    def _parse_into(self) -> t.Optional[exp.Into]:
2035        if not self._match(TokenType.INTO):
2036            return None
2037
2038        temp = self._match(TokenType.TEMPORARY)
2039        unlogged = self._match_text_seq("UNLOGGED")
2040        self._match(TokenType.TABLE)
2041
2042        return self.expression(
2043            exp.Into, this=self._parse_table(schema=True), temporary=temp, unlogged=unlogged
2044        )
2045
2046    def _parse_from(
2047        self, modifiers: bool = False, skip_from_token: bool = False
2048    ) -> t.Optional[exp.From]:
2049        if not skip_from_token and not self._match(TokenType.FROM):
2050            return None
2051
2052        comments = self._prev_comments
2053        this = self._parse_table()
2054
2055        return self.expression(
2056            exp.From,
2057            comments=comments,
2058            this=self._parse_query_modifiers(this) if modifiers else this,
2059        )
2060
2061    def _parse_match_recognize(self) -> t.Optional[exp.MatchRecognize]:
2062        if not self._match(TokenType.MATCH_RECOGNIZE):
2063            return None
2064
2065        self._match_l_paren()
2066
2067        partition = self._parse_partition_by()
2068        order = self._parse_order()
2069        measures = (
2070            self._parse_csv(self._parse_expression) if self._match_text_seq("MEASURES") else None
2071        )
2072
2073        if self._match_text_seq("ONE", "ROW", "PER", "MATCH"):
2074            rows = exp.var("ONE ROW PER MATCH")
2075        elif self._match_text_seq("ALL", "ROWS", "PER", "MATCH"):
2076            text = "ALL ROWS PER MATCH"
2077            if self._match_text_seq("SHOW", "EMPTY", "MATCHES"):
2078                text += f" SHOW EMPTY MATCHES"
2079            elif self._match_text_seq("OMIT", "EMPTY", "MATCHES"):
2080                text += f" OMIT EMPTY MATCHES"
2081            elif self._match_text_seq("WITH", "UNMATCHED", "ROWS"):
2082                text += f" WITH UNMATCHED ROWS"
2083            rows = exp.var(text)
2084        else:
2085            rows = None
2086
2087        if self._match_text_seq("AFTER", "MATCH", "SKIP"):
2088            text = "AFTER MATCH SKIP"
2089            if self._match_text_seq("PAST", "LAST", "ROW"):
2090                text += f" PAST LAST ROW"
2091            elif self._match_text_seq("TO", "NEXT", "ROW"):
2092                text += f" TO NEXT ROW"
2093            elif self._match_text_seq("TO", "FIRST"):
2094                text += f" TO FIRST {self._advance_any().text}"  # type: ignore
2095            elif self._match_text_seq("TO", "LAST"):
2096                text += f" TO LAST {self._advance_any().text}"  # type: ignore
2097            after = exp.var(text)
2098        else:
2099            after = None
2100
2101        if self._match_text_seq("PATTERN"):
2102            self._match_l_paren()
2103
2104            if not self._curr:
2105                self.raise_error("Expecting )", self._curr)
2106
2107            paren = 1
2108            start = self._curr
2109
2110            while self._curr and paren > 0:
2111                if self._curr.token_type == TokenType.L_PAREN:
2112                    paren += 1
2113                if self._curr.token_type == TokenType.R_PAREN:
2114                    paren -= 1
2115
2116                end = self._prev
2117                self._advance()
2118
2119            if paren > 0:
2120                self.raise_error("Expecting )", self._curr)
2121
2122            pattern = exp.var(self._find_sql(start, end))
2123        else:
2124            pattern = None
2125
2126        define = (
2127            self._parse_csv(
2128                lambda: self.expression(
2129                    exp.Alias,
2130                    alias=self._parse_id_var(any_token=True),
2131                    this=self._match(TokenType.ALIAS) and self._parse_conjunction(),
2132                )
2133            )
2134            if self._match_text_seq("DEFINE")
2135            else None
2136        )
2137
2138        self._match_r_paren()
2139
2140        return self.expression(
2141            exp.MatchRecognize,
2142            partition_by=partition,
2143            order=order,
2144            measures=measures,
2145            rows=rows,
2146            after=after,
2147            pattern=pattern,
2148            define=define,
2149            alias=self._parse_table_alias(),
2150        )
2151
2152    def _parse_lateral(self) -> t.Optional[exp.Lateral]:
2153        outer_apply = self._match_pair(TokenType.OUTER, TokenType.APPLY)
2154        cross_apply = self._match_pair(TokenType.CROSS, TokenType.APPLY)
2155
2156        if outer_apply or cross_apply:
2157            this = self._parse_select(table=True)
2158            view = None
2159            outer = not cross_apply
2160        elif self._match(TokenType.LATERAL):
2161            this = self._parse_select(table=True)
2162            view = self._match(TokenType.VIEW)
2163            outer = self._match(TokenType.OUTER)
2164        else:
2165            return None
2166
2167        if not this:
2168            this = self._parse_function() or self._parse_id_var(any_token=False)
2169            while self._match(TokenType.DOT):
2170                this = exp.Dot(
2171                    this=this,
2172                    expression=self._parse_function() or self._parse_id_var(any_token=False),
2173                )
2174
2175        if view:
2176            table = self._parse_id_var(any_token=False)
2177            columns = self._parse_csv(self._parse_id_var) if self._match(TokenType.ALIAS) else []
2178            table_alias: t.Optional[exp.TableAlias] = self.expression(
2179                exp.TableAlias, this=table, columns=columns
2180            )
2181        elif isinstance(this, exp.Subquery) and this.alias:
2182            # Ensures parity between the Subquery's and the Lateral's "alias" args
2183            table_alias = this.args["alias"].copy()
2184        else:
2185            table_alias = self._parse_table_alias()
2186
2187        return self.expression(exp.Lateral, this=this, view=view, outer=outer, alias=table_alias)
2188
2189    def _parse_join_parts(
2190        self,
2191    ) -> t.Tuple[t.Optional[Token], t.Optional[Token], t.Optional[Token]]:
2192        return (
2193            self._match_set(self.JOIN_METHODS) and self._prev,
2194            self._match_set(self.JOIN_SIDES) and self._prev,
2195            self._match_set(self.JOIN_KINDS) and self._prev,
2196        )
2197
2198    def _parse_join(self, skip_join_token: bool = False) -> t.Optional[exp.Join]:
2199        if self._match(TokenType.COMMA):
2200            return self.expression(exp.Join, this=self._parse_table())
2201
2202        index = self._index
2203        method, side, kind = self._parse_join_parts()
2204        hint = self._prev.text if self._match_texts(self.JOIN_HINTS) else None
2205        join = self._match(TokenType.JOIN)
2206
2207        if not skip_join_token and not join:
2208            self._retreat(index)
2209            kind = None
2210            method = None
2211            side = None
2212
2213        outer_apply = self._match_pair(TokenType.OUTER, TokenType.APPLY, False)
2214        cross_apply = self._match_pair(TokenType.CROSS, TokenType.APPLY, False)
2215
2216        if not skip_join_token and not join and not outer_apply and not cross_apply:
2217            return None
2218
2219        if outer_apply:
2220            side = Token(TokenType.LEFT, "LEFT")
2221
2222        kwargs: t.Dict[str, t.Any] = {"this": self._parse_table()}
2223
2224        if method:
2225            kwargs["method"] = method.text
2226        if side:
2227            kwargs["side"] = side.text
2228        if kind:
2229            kwargs["kind"] = kind.text
2230        if hint:
2231            kwargs["hint"] = hint
2232
2233        if self._match(TokenType.ON):
2234            kwargs["on"] = self._parse_conjunction()
2235        elif self._match(TokenType.USING):
2236            kwargs["using"] = self._parse_wrapped_id_vars()
2237
2238        return self.expression(exp.Join, **kwargs)
2239
2240    def _parse_index(
2241        self,
2242        index: t.Optional[exp.Expression] = None,
2243    ) -> t.Optional[exp.Index]:
2244        if index:
2245            unique = None
2246            primary = None
2247            amp = None
2248
2249            self._match(TokenType.ON)
2250            self._match(TokenType.TABLE)  # hive
2251            table = self._parse_table_parts(schema=True)
2252        else:
2253            unique = self._match(TokenType.UNIQUE)
2254            primary = self._match_text_seq("PRIMARY")
2255            amp = self._match_text_seq("AMP")
2256
2257            if not self._match(TokenType.INDEX):
2258                return None
2259
2260            index = self._parse_id_var()
2261            table = None
2262
2263        using = self._parse_field() if self._match(TokenType.USING) else None
2264
2265        if self._match(TokenType.L_PAREN, advance=False):
2266            columns = self._parse_wrapped_csv(self._parse_ordered)
2267        else:
2268            columns = None
2269
2270        return self.expression(
2271            exp.Index,
2272            this=index,
2273            table=table,
2274            using=using,
2275            columns=columns,
2276            unique=unique,
2277            primary=primary,
2278            amp=amp,
2279            partition_by=self._parse_partition_by(),
2280        )
2281
2282    def _parse_table_hints(self) -> t.Optional[t.List[exp.Expression]]:
2283        hints: t.List[exp.Expression] = []
2284        if self._match_pair(TokenType.WITH, TokenType.L_PAREN):
2285            # https://learn.microsoft.com/en-us/sql/t-sql/queries/hints-transact-sql-table?view=sql-server-ver16
2286            hints.append(
2287                self.expression(
2288                    exp.WithTableHint,
2289                    expressions=self._parse_csv(
2290                        lambda: self._parse_function() or self._parse_var(any_token=True)
2291                    ),
2292                )
2293            )
2294            self._match_r_paren()
2295        else:
2296            # https://dev.mysql.com/doc/refman/8.0/en/index-hints.html
2297            while self._match_set(self.TABLE_INDEX_HINT_TOKENS):
2298                hint = exp.IndexTableHint(this=self._prev.text.upper())
2299
2300                self._match_texts({"INDEX", "KEY"})
2301                if self._match(TokenType.FOR):
2302                    hint.set("target", self._advance_any() and self._prev.text.upper())
2303
2304                hint.set("expressions", self._parse_wrapped_id_vars())
2305                hints.append(hint)
2306
2307        return hints or None
2308
2309    def _parse_table_part(self, schema: bool = False) -> t.Optional[exp.Expression]:
2310        return (
2311            (not schema and self._parse_function(optional_parens=False))
2312            or self._parse_id_var(any_token=False)
2313            or self._parse_string_as_identifier()
2314            or self._parse_placeholder()
2315        )
2316
2317    def _parse_table_parts(self, schema: bool = False) -> exp.Table:
2318        catalog = None
2319        db = None
2320        table = self._parse_table_part(schema=schema)
2321
2322        while self._match(TokenType.DOT):
2323            if catalog:
2324                # This allows nesting the table in arbitrarily many dot expressions if needed
2325                table = self.expression(
2326                    exp.Dot, this=table, expression=self._parse_table_part(schema=schema)
2327                )
2328            else:
2329                catalog = db
2330                db = table
2331                table = self._parse_table_part(schema=schema)
2332
2333        if not table:
2334            self.raise_error(f"Expected table name but got {self._curr}")
2335
2336        return self.expression(
2337            exp.Table, this=table, db=db, catalog=catalog, pivots=self._parse_pivots()
2338        )
2339
2340    def _parse_table(
2341        self, schema: bool = False, alias_tokens: t.Optional[t.Collection[TokenType]] = None
2342    ) -> t.Optional[exp.Expression]:
2343        lateral = self._parse_lateral()
2344        if lateral:
2345            return lateral
2346
2347        unnest = self._parse_unnest()
2348        if unnest:
2349            return unnest
2350
2351        values = self._parse_derived_table_values()
2352        if values:
2353            return values
2354
2355        subquery = self._parse_select(table=True)
2356        if subquery:
2357            if not subquery.args.get("pivots"):
2358                subquery.set("pivots", self._parse_pivots())
2359            return subquery
2360
2361        this: exp.Expression = self._parse_table_parts(schema=schema)
2362
2363        if schema:
2364            return self._parse_schema(this=this)
2365
2366        if self.ALIAS_POST_TABLESAMPLE:
2367            table_sample = self._parse_table_sample()
2368
2369        alias = self._parse_table_alias(alias_tokens=alias_tokens or self.TABLE_ALIAS_TOKENS)
2370        if alias:
2371            this.set("alias", alias)
2372
2373        if not this.args.get("pivots"):
2374            this.set("pivots", self._parse_pivots())
2375
2376        this.set("hints", self._parse_table_hints())
2377
2378        if not self.ALIAS_POST_TABLESAMPLE:
2379            table_sample = self._parse_table_sample()
2380
2381        if table_sample:
2382            table_sample.set("this", this)
2383            this = table_sample
2384
2385        return this
2386
2387    def _parse_unnest(self, with_alias: bool = True) -> t.Optional[exp.Unnest]:
2388        if not self._match(TokenType.UNNEST):
2389            return None
2390
2391        expressions = self._parse_wrapped_csv(self._parse_type)
2392        ordinality = self._match_pair(TokenType.WITH, TokenType.ORDINALITY)
2393
2394        alias = self._parse_table_alias() if with_alias else None
2395
2396        if alias and self.UNNEST_COLUMN_ONLY:
2397            if alias.args.get("columns"):
2398                self.raise_error("Unexpected extra column alias in unnest.")
2399
2400            alias.set("columns", [alias.this])
2401            alias.set("this", None)
2402
2403        offset = None
2404        if self._match_pair(TokenType.WITH, TokenType.OFFSET):
2405            self._match(TokenType.ALIAS)
2406            offset = self._parse_id_var() or exp.to_identifier("offset")
2407
2408        return self.expression(
2409            exp.Unnest, expressions=expressions, ordinality=ordinality, alias=alias, offset=offset
2410        )
2411
2412    def _parse_derived_table_values(self) -> t.Optional[exp.Values]:
2413        is_derived = self._match_pair(TokenType.L_PAREN, TokenType.VALUES)
2414        if not is_derived and not self._match(TokenType.VALUES):
2415            return None
2416
2417        expressions = self._parse_csv(self._parse_value)
2418        alias = self._parse_table_alias()
2419
2420        if is_derived:
2421            self._match_r_paren()
2422
2423        return self.expression(
2424            exp.Values, expressions=expressions, alias=alias or self._parse_table_alias()
2425        )
2426
2427    def _parse_table_sample(self, as_modifier: bool = False) -> t.Optional[exp.TableSample]:
2428        if not self._match(TokenType.TABLE_SAMPLE) and not (
2429            as_modifier and self._match_text_seq("USING", "SAMPLE")
2430        ):
2431            return None
2432
2433        bucket_numerator = None
2434        bucket_denominator = None
2435        bucket_field = None
2436        percent = None
2437        rows = None
2438        size = None
2439        seed = None
2440
2441        kind = (
2442            self._prev.text if self._prev.token_type == TokenType.TABLE_SAMPLE else "USING SAMPLE"
2443        )
2444        method = self._parse_var(tokens=(TokenType.ROW,))
2445
2446        self._match(TokenType.L_PAREN)
2447
2448        num = self._parse_number()
2449
2450        if self._match_text_seq("BUCKET"):
2451            bucket_numerator = self._parse_number()
2452            self._match_text_seq("OUT", "OF")
2453            bucket_denominator = bucket_denominator = self._parse_number()
2454            self._match(TokenType.ON)
2455            bucket_field = self._parse_field()
2456        elif self._match_set((TokenType.PERCENT, TokenType.MOD)):
2457            percent = num
2458        elif self._match(TokenType.ROWS):
2459            rows = num
2460        else:
2461            size = num
2462
2463        self._match(TokenType.R_PAREN)
2464
2465        if self._match(TokenType.L_PAREN):
2466            method = self._parse_var()
2467            seed = self._match(TokenType.COMMA) and self._parse_number()
2468            self._match_r_paren()
2469        elif self._match_texts(("SEED", "REPEATABLE")):
2470            seed = self._parse_wrapped(self._parse_number)
2471
2472        return self.expression(
2473            exp.TableSample,
2474            method=method,
2475            bucket_numerator=bucket_numerator,
2476            bucket_denominator=bucket_denominator,
2477            bucket_field=bucket_field,
2478            percent=percent,
2479            rows=rows,
2480            size=size,
2481            seed=seed,
2482            kind=kind,
2483        )
2484
2485    def _parse_pivots(self) -> t.List[t.Optional[exp.Expression]]:
2486        return list(iter(self._parse_pivot, None))
2487
2488    # https://duckdb.org/docs/sql/statements/pivot
2489    def _parse_simplified_pivot(self) -> exp.Pivot:
2490        def _parse_on() -> t.Optional[exp.Expression]:
2491            this = self._parse_bitwise()
2492            return self._parse_in(this) if self._match(TokenType.IN) else this
2493
2494        this = self._parse_table()
2495        expressions = self._match(TokenType.ON) and self._parse_csv(_parse_on)
2496        using = self._match(TokenType.USING) and self._parse_csv(
2497            lambda: self._parse_alias(self._parse_function())
2498        )
2499        group = self._parse_group()
2500        return self.expression(
2501            exp.Pivot, this=this, expressions=expressions, using=using, group=group
2502        )
2503
2504    def _parse_pivot(self) -> t.Optional[exp.Pivot]:
2505        index = self._index
2506
2507        if self._match(TokenType.PIVOT):
2508            unpivot = False
2509        elif self._match(TokenType.UNPIVOT):
2510            unpivot = True
2511        else:
2512            return None
2513
2514        expressions = []
2515        field = None
2516
2517        if not self._match(TokenType.L_PAREN):
2518            self._retreat(index)
2519            return None
2520
2521        if unpivot:
2522            expressions = self._parse_csv(self._parse_column)
2523        else:
2524            expressions = self._parse_csv(lambda: self._parse_alias(self._parse_function()))
2525
2526        if not expressions:
2527            self.raise_error("Failed to parse PIVOT's aggregation list")
2528
2529        if not self._match(TokenType.FOR):
2530            self.raise_error("Expecting FOR")
2531
2532        value = self._parse_column()
2533
2534        if not self._match(TokenType.IN):
2535            self.raise_error("Expecting IN")
2536
2537        field = self._parse_in(value, alias=True)
2538
2539        self._match_r_paren()
2540
2541        pivot = self.expression(exp.Pivot, expressions=expressions, field=field, unpivot=unpivot)
2542
2543        if not self._match_set((TokenType.PIVOT, TokenType.UNPIVOT), advance=False):
2544            pivot.set("alias", self._parse_table_alias())
2545
2546        if not unpivot:
2547            names = self._pivot_column_names(t.cast(t.List[exp.Expression], expressions))
2548
2549            columns: t.List[exp.Expression] = []
2550            for fld in pivot.args["field"].expressions:
2551                field_name = fld.sql() if self.IDENTIFY_PIVOT_STRINGS else fld.alias_or_name
2552                for name in names:
2553                    if self.PREFIXED_PIVOT_COLUMNS:
2554                        name = f"{name}_{field_name}" if name else field_name
2555                    else:
2556                        name = f"{field_name}_{name}" if name else field_name
2557
2558                    columns.append(exp.to_identifier(name))
2559
2560            pivot.set("columns", columns)
2561
2562        return pivot
2563
2564    def _pivot_column_names(self, aggregations: t.List[exp.Expression]) -> t.List[str]:
2565        return [agg.alias for agg in aggregations]
2566
2567    def _parse_where(self, skip_where_token: bool = False) -> t.Optional[exp.Where]:
2568        if not skip_where_token and not self._match(TokenType.WHERE):
2569            return None
2570
2571        return self.expression(
2572            exp.Where, comments=self._prev_comments, this=self._parse_conjunction()
2573        )
2574
2575    def _parse_group(self, skip_group_by_token: bool = False) -> t.Optional[exp.Group]:
2576        if not skip_group_by_token and not self._match(TokenType.GROUP_BY):
2577            return None
2578
2579        elements = defaultdict(list)
2580
2581        while True:
2582            expressions = self._parse_csv(self._parse_conjunction)
2583            if expressions:
2584                elements["expressions"].extend(expressions)
2585
2586            grouping_sets = self._parse_grouping_sets()
2587            if grouping_sets:
2588                elements["grouping_sets"].extend(grouping_sets)
2589
2590            rollup = None
2591            cube = None
2592            totals = None
2593
2594            with_ = self._match(TokenType.WITH)
2595            if self._match(TokenType.ROLLUP):
2596                rollup = with_ or self._parse_wrapped_csv(self._parse_column)
2597                elements["rollup"].extend(ensure_list(rollup))
2598
2599            if self._match(TokenType.CUBE):
2600                cube = with_ or self._parse_wrapped_csv(self._parse_column)
2601                elements["cube"].extend(ensure_list(cube))
2602
2603            if self._match_text_seq("TOTALS"):
2604                totals = True
2605                elements["totals"] = True  # type: ignore
2606
2607            if not (grouping_sets or rollup or cube or totals):
2608                break
2609
2610        return self.expression(exp.Group, **elements)  # type: ignore
2611
2612    def _parse_grouping_sets(self) -> t.Optional[t.List[t.Optional[exp.Expression]]]:
2613        if not self._match(TokenType.GROUPING_SETS):
2614            return None
2615
2616        return self._parse_wrapped_csv(self._parse_grouping_set)
2617
2618    def _parse_grouping_set(self) -> t.Optional[exp.Expression]:
2619        if self._match(TokenType.L_PAREN):
2620            grouping_set = self._parse_csv(self._parse_column)
2621            self._match_r_paren()
2622            return self.expression(exp.Tuple, expressions=grouping_set)
2623
2624        return self._parse_column()
2625
2626    def _parse_having(self, skip_having_token: bool = False) -> t.Optional[exp.Having]:
2627        if not skip_having_token and not self._match(TokenType.HAVING):
2628            return None
2629        return self.expression(exp.Having, this=self._parse_conjunction())
2630
2631    def _parse_qualify(self) -> t.Optional[exp.Qualify]:
2632        if not self._match(TokenType.QUALIFY):
2633            return None
2634        return self.expression(exp.Qualify, this=self._parse_conjunction())
2635
2636    def _parse_order(
2637        self, this: t.Optional[exp.Expression] = None, skip_order_token: bool = False
2638    ) -> t.Optional[exp.Expression]:
2639        if not skip_order_token and not self._match(TokenType.ORDER_BY):
2640            return this
2641
2642        return self.expression(
2643            exp.Order, this=this, expressions=self._parse_csv(self._parse_ordered)
2644        )
2645
2646    def _parse_sort(self, exp_class: t.Type[E], token: TokenType) -> t.Optional[E]:
2647        if not self._match(token):
2648            return None
2649        return self.expression(exp_class, expressions=self._parse_csv(self._parse_ordered))
2650
2651    def _parse_ordered(self) -> exp.Ordered:
2652        this = self._parse_conjunction()
2653        self._match(TokenType.ASC)
2654
2655        is_desc = self._match(TokenType.DESC)
2656        is_nulls_first = self._match_text_seq("NULLS", "FIRST")
2657        is_nulls_last = self._match_text_seq("NULLS", "LAST")
2658        desc = is_desc or False
2659        asc = not desc
2660        nulls_first = is_nulls_first or False
2661        explicitly_null_ordered = is_nulls_first or is_nulls_last
2662
2663        if (
2664            not explicitly_null_ordered
2665            and (
2666                (asc and self.NULL_ORDERING == "nulls_are_small")
2667                or (desc and self.NULL_ORDERING != "nulls_are_small")
2668            )
2669            and self.NULL_ORDERING != "nulls_are_last"
2670        ):
2671            nulls_first = True
2672
2673        return self.expression(exp.Ordered, this=this, desc=desc, nulls_first=nulls_first)
2674
2675    def _parse_limit(
2676        self, this: t.Optional[exp.Expression] = None, top: bool = False
2677    ) -> t.Optional[exp.Expression]:
2678        if self._match(TokenType.TOP if top else TokenType.LIMIT):
2679            limit_paren = self._match(TokenType.L_PAREN)
2680            expression = self._parse_number() if top else self._parse_term()
2681
2682            if self._match(TokenType.COMMA):
2683                offset = expression
2684                expression = self._parse_term()
2685            else:
2686                offset = None
2687
2688            limit_exp = self.expression(exp.Limit, this=this, expression=expression, offset=offset)
2689
2690            if limit_paren:
2691                self._match_r_paren()
2692
2693            return limit_exp
2694
2695        if self._match(TokenType.FETCH):
2696            direction = self._match_set((TokenType.FIRST, TokenType.NEXT))
2697            direction = self._prev.text if direction else "FIRST"
2698
2699            count = self._parse_number()
2700            percent = self._match(TokenType.PERCENT)
2701
2702            self._match_set((TokenType.ROW, TokenType.ROWS))
2703
2704            only = self._match_text_seq("ONLY")
2705            with_ties = self._match_text_seq("WITH", "TIES")
2706
2707            if only and with_ties:
2708                self.raise_error("Cannot specify both ONLY and WITH TIES in FETCH clause")
2709
2710            return self.expression(
2711                exp.Fetch,
2712                direction=direction,
2713                count=count,
2714                percent=percent,
2715                with_ties=with_ties,
2716            )
2717
2718        return this
2719
2720    def _parse_offset(self, this: t.Optional[exp.Expression] = None) -> t.Optional[exp.Expression]:
2721        if not self._match(TokenType.OFFSET):
2722            return this
2723
2724        count = self._parse_number()
2725        self._match_set((TokenType.ROW, TokenType.ROWS))
2726        return self.expression(exp.Offset, this=this, expression=count)
2727
2728    def _parse_locks(self) -> t.List[exp.Lock]:
2729        locks = []
2730        while True:
2731            if self._match_text_seq("FOR", "UPDATE"):
2732                update = True
2733            elif self._match_text_seq("FOR", "SHARE") or self._match_text_seq(
2734                "LOCK", "IN", "SHARE", "MODE"
2735            ):
2736                update = False
2737            else:
2738                break
2739
2740            expressions = None
2741            if self._match_text_seq("OF"):
2742                expressions = self._parse_csv(lambda: self._parse_table(schema=True))
2743
2744            wait: t.Optional[bool | exp.Expression] = None
2745            if self._match_text_seq("NOWAIT"):
2746                wait = True
2747            elif self._match_text_seq("WAIT"):
2748                wait = self._parse_primary()
2749            elif self._match_text_seq("SKIP", "LOCKED"):
2750                wait = False
2751
2752            locks.append(
2753                self.expression(exp.Lock, update=update, expressions=expressions, wait=wait)
2754            )
2755
2756        return locks
2757
2758    def _parse_set_operations(self, this: t.Optional[exp.Expression]) -> t.Optional[exp.Expression]:
2759        if not self._match_set(self.SET_OPERATIONS):
2760            return this
2761
2762        token_type = self._prev.token_type
2763
2764        if token_type == TokenType.UNION:
2765            expression = exp.Union
2766        elif token_type == TokenType.EXCEPT:
2767            expression = exp.Except
2768        else:
2769            expression = exp.Intersect
2770
2771        return self.expression(
2772            expression,
2773            this=this,
2774            distinct=self._match(TokenType.DISTINCT) or not self._match(TokenType.ALL),
2775            expression=self._parse_set_operations(self._parse_select(nested=True)),
2776        )
2777
2778    def _parse_expression(self) -> t.Optional[exp.Expression]:
2779        return self._parse_alias(self._parse_conjunction())
2780
2781    def _parse_conjunction(self) -> t.Optional[exp.Expression]:
2782        return self._parse_tokens(self._parse_equality, self.CONJUNCTION)
2783
2784    def _parse_equality(self) -> t.Optional[exp.Expression]:
2785        return self._parse_tokens(self._parse_comparison, self.EQUALITY)
2786
2787    def _parse_comparison(self) -> t.Optional[exp.Expression]:
2788        return self._parse_tokens(self._parse_range, self.COMPARISON)
2789
2790    def _parse_range(self) -> t.Optional[exp.Expression]:
2791        this = self._parse_bitwise()
2792        negate = self._match(TokenType.NOT)
2793
2794        if self._match_set(self.RANGE_PARSERS):
2795            expression = self.RANGE_PARSERS[self._prev.token_type](self, this)
2796            if not expression:
2797                return this
2798
2799            this = expression
2800        elif self._match(TokenType.ISNULL):
2801            this = self.expression(exp.Is, this=this, expression=exp.Null())
2802
2803        # Postgres supports ISNULL and NOTNULL for conditions.
2804        # https://blog.andreiavram.ro/postgresql-null-composite-type/
2805        if self._match(TokenType.NOTNULL):
2806            this = self.expression(exp.Is, this=this, expression=exp.Null())
2807            this = self.expression(exp.Not, this=this)
2808
2809        if negate:
2810            this = self.expression(exp.Not, this=this)
2811
2812        if self._match(TokenType.IS):
2813            this = self._parse_is(this)
2814
2815        return this
2816
2817    def _parse_is(self, this: t.Optional[exp.Expression]) -> t.Optional[exp.Expression]:
2818        index = self._index - 1
2819        negate = self._match(TokenType.NOT)
2820
2821        if self._match_text_seq("DISTINCT", "FROM"):
2822            klass = exp.NullSafeEQ if negate else exp.NullSafeNEQ
2823            return self.expression(klass, this=this, expression=self._parse_expression())
2824
2825        expression = self._parse_null() or self._parse_boolean()
2826        if not expression:
2827            self._retreat(index)
2828            return None
2829
2830        this = self.expression(exp.Is, this=this, expression=expression)
2831        return self.expression(exp.Not, this=this) if negate else this
2832
2833    def _parse_in(self, this: t.Optional[exp.Expression], alias: bool = False) -> exp.In:
2834        unnest = self._parse_unnest(with_alias=False)
2835        if unnest:
2836            this = self.expression(exp.In, this=this, unnest=unnest)
2837        elif self._match(TokenType.L_PAREN):
2838            expressions = self._parse_csv(lambda: self._parse_select_or_expression(alias=alias))
2839
2840            if len(expressions) == 1 and isinstance(expressions[0], exp.Subqueryable):
2841                this = self.expression(exp.In, this=this, query=expressions[0])
2842            else:
2843                this = self.expression(exp.In, this=this, expressions=expressions)
2844
2845            self._match_r_paren(this)
2846        else:
2847            this = self.expression(exp.In, this=this, field=self._parse_field())
2848
2849        return this
2850
2851    def _parse_between(self, this: exp.Expression) -> exp.Between:
2852        low = self._parse_bitwise()
2853        self._match(TokenType.AND)
2854        high = self._parse_bitwise()
2855        return self.expression(exp.Between, this=this, low=low, high=high)
2856
2857    def _parse_escape(self, this: t.Optional[exp.Expression]) -> t.Optional[exp.Expression]:
2858        if not self._match(TokenType.ESCAPE):
2859            return this
2860        return self.expression(exp.Escape, this=this, expression=self._parse_string())
2861
2862    def _parse_interval(self) -> t.Optional[exp.Interval]:
2863        if not self._match(TokenType.INTERVAL):
2864            return None
2865
2866        this = self._parse_primary() or self._parse_term()
2867        unit = self._parse_function() or self._parse_var()
2868
2869        # Most dialects support, e.g., the form INTERVAL '5' day, thus we try to parse
2870        # each INTERVAL expression into this canonical form so it's easy to transpile
2871        if this and this.is_number:
2872            this = exp.Literal.string(this.name)
2873        elif this and this.is_string:
2874            parts = this.name.split()
2875
2876            if len(parts) == 2:
2877                if unit:
2878                    # this is not actually a unit, it's something else
2879                    unit = None
2880                    self._retreat(self._index - 1)
2881                else:
2882                    this = exp.Literal.string(parts[0])
2883                    unit = self.expression(exp.Var, this=parts[1])
2884
2885        return self.expression(exp.Interval, this=this, unit=unit)
2886
2887    def _parse_bitwise(self) -> t.Optional[exp.Expression]:
2888        this = self._parse_term()
2889
2890        while True:
2891            if self._match_set(self.BITWISE):
2892                this = self.expression(
2893                    self.BITWISE[self._prev.token_type], this=this, expression=self._parse_term()
2894                )
2895            elif self._match_pair(TokenType.LT, TokenType.LT):
2896                this = self.expression(
2897                    exp.BitwiseLeftShift, this=this, expression=self._parse_term()
2898                )
2899            elif self._match_pair(TokenType.GT, TokenType.GT):
2900                this = self.expression(
2901                    exp.BitwiseRightShift, this=this, expression=self._parse_term()
2902                )
2903            else:
2904                break
2905
2906        return this
2907
2908    def _parse_term(self) -> t.Optional[exp.Expression]:
2909        return self._parse_tokens(self._parse_factor, self.TERM)
2910
2911    def _parse_factor(self) -> t.Optional[exp.Expression]:
2912        return self._parse_tokens(self._parse_unary, self.FACTOR)
2913
2914    def _parse_unary(self) -> t.Optional[exp.Expression]:
2915        if self._match_set(self.UNARY_PARSERS):
2916            return self.UNARY_PARSERS[self._prev.token_type](self)
2917        return self._parse_at_time_zone(self._parse_type())
2918
2919    def _parse_type(self) -> t.Optional[exp.Expression]:
2920        interval = self._parse_interval()
2921        if interval:
2922            return interval
2923
2924        index = self._index
2925        data_type = self._parse_types(check_func=True)
2926        this = self._parse_column()
2927
2928        if data_type:
2929            if isinstance(this, exp.Literal):
2930                parser = self.TYPE_LITERAL_PARSERS.get(data_type.this)
2931                if parser:
2932                    return parser(self, this, data_type)
2933                return self.expression(exp.Cast, this=this, to=data_type)
2934            if not data_type.expressions:
2935                self._retreat(index)
2936                return self._parse_column()
2937            return self._parse_column_ops(data_type)
2938
2939        return this
2940
2941    def _parse_type_size(self) -> t.Optional[exp.DataTypeSize]:
2942        this = self._parse_type()
2943        if not this:
2944            return None
2945
2946        return self.expression(
2947            exp.DataTypeSize, this=this, expression=self._parse_var(any_token=True)
2948        )
2949
2950    def _parse_types(
2951        self, check_func: bool = False, schema: bool = False
2952    ) -> t.Optional[exp.Expression]:
2953        index = self._index
2954
2955        prefix = self._match_text_seq("SYSUDTLIB", ".")
2956
2957        if not self._match_set(self.TYPE_TOKENS):
2958            return None
2959
2960        type_token = self._prev.token_type
2961
2962        if type_token == TokenType.PSEUDO_TYPE:
2963            return self.expression(exp.PseudoType, this=self._prev.text)
2964
2965        nested = type_token in self.NESTED_TYPE_TOKENS
2966        is_struct = type_token == TokenType.STRUCT
2967        expressions = None
2968        maybe_func = False
2969
2970        if self._match(TokenType.L_PAREN):
2971            if is_struct:
2972                expressions = self._parse_csv(self._parse_struct_types)
2973            elif nested:
2974                expressions = self._parse_csv(
2975                    lambda: self._parse_types(check_func=check_func, schema=schema)
2976                )
2977            elif type_token in self.ENUM_TYPE_TOKENS:
2978                expressions = self._parse_csv(self._parse_primary)
2979            else:
2980                expressions = self._parse_csv(self._parse_type_size)
2981
2982            if not expressions or not self._match(TokenType.R_PAREN):
2983                self._retreat(index)
2984                return None
2985
2986            maybe_func = True
2987
2988        if self._match_pair(TokenType.L_BRACKET, TokenType.R_BRACKET):
2989            this = exp.DataType(
2990                this=exp.DataType.Type.ARRAY,
2991                expressions=[exp.DataType.build(type_token.value, expressions=expressions)],
2992                nested=True,
2993            )
2994
2995            while self._match_pair(TokenType.L_BRACKET, TokenType.R_BRACKET):
2996                this = exp.DataType(this=exp.DataType.Type.ARRAY, expressions=[this], nested=True)
2997
2998            return this
2999
3000        if self._match(TokenType.L_BRACKET):
3001            self._retreat(index)
3002            return None
3003
3004        values: t.Optional[t.List[t.Optional[exp.Expression]]] = None
3005        if nested and self._match(TokenType.LT):
3006            if is_struct:
3007                expressions = self._parse_csv(self._parse_struct_types)
3008            else:
3009                expressions = self._parse_csv(
3010                    lambda: self._parse_types(check_func=check_func, schema=schema)
3011                )
3012
3013            if not self._match(TokenType.GT):
3014                self.raise_error("Expecting >")
3015
3016            if self._match_set((TokenType.L_BRACKET, TokenType.L_PAREN)):
3017                values = self._parse_csv(self._parse_conjunction)
3018                self._match_set((TokenType.R_BRACKET, TokenType.R_PAREN))
3019
3020        value: t.Optional[exp.Expression] = None
3021        if type_token in self.TIMESTAMPS:
3022            if self._match_text_seq("WITH", "TIME", "ZONE"):
3023                maybe_func = False
3024                value = exp.DataType(this=exp.DataType.Type.TIMESTAMPTZ, expressions=expressions)
3025            elif self._match_text_seq("WITH", "LOCAL", "TIME", "ZONE"):
3026                maybe_func = False
3027                value = exp.DataType(this=exp.DataType.Type.TIMESTAMPLTZ, expressions=expressions)
3028            elif self._match_text_seq("WITHOUT", "TIME", "ZONE"):
3029                maybe_func = False
3030        elif type_token == TokenType.INTERVAL:
3031            unit = self._parse_var()
3032
3033            if not unit:
3034                value = self.expression(exp.DataType, this=exp.DataType.Type.INTERVAL)
3035            else:
3036                value = self.expression(exp.Interval, unit=unit)
3037
3038        if maybe_func and check_func:
3039            index2 = self._index
3040            peek = self._parse_string()
3041
3042            if not peek:
3043                self._retreat(index)
3044                return None
3045
3046            self._retreat(index2)
3047
3048        if value:
3049            return value
3050
3051        return exp.DataType(
3052            this=exp.DataType.Type[type_token.value.upper()],
3053            expressions=expressions,
3054            nested=nested,
3055            values=values,
3056            prefix=prefix,
3057        )
3058
3059    def _parse_struct_types(self) -> t.Optional[exp.Expression]:
3060        this = self._parse_type() or self._parse_id_var()
3061        self._match(TokenType.COLON)
3062        return self._parse_column_def(this)
3063
3064    def _parse_at_time_zone(self, this: t.Optional[exp.Expression]) -> t.Optional[exp.Expression]:
3065        if not self._match_text_seq("AT", "TIME", "ZONE"):
3066            return this
3067        return self.expression(exp.AtTimeZone, this=this, zone=self._parse_unary())
3068
3069    def _parse_column(self) -> t.Optional[exp.Expression]:
3070        this = self._parse_field()
3071        if isinstance(this, exp.Identifier):
3072            this = self.expression(exp.Column, this=this)
3073        elif not this:
3074            return self._parse_bracket(this)
3075        return self._parse_column_ops(this)
3076
3077    def _parse_column_ops(self, this: t.Optional[exp.Expression]) -> t.Optional[exp.Expression]:
3078        this = self._parse_bracket(this)
3079
3080        while self._match_set(self.COLUMN_OPERATORS):
3081            op_token = self._prev.token_type
3082            op = self.COLUMN_OPERATORS.get(op_token)
3083
3084            if op_token == TokenType.DCOLON:
3085                field = self._parse_types()
3086                if not field:
3087                    self.raise_error("Expected type")
3088            elif op and self._curr:
3089                self._advance()
3090                value = self._prev.text
3091                field = (
3092                    exp.Literal.number(value)
3093                    if self._prev.token_type == TokenType.NUMBER
3094                    else exp.Literal.string(value)
3095                )
3096            else:
3097                field = self._parse_field(anonymous_func=True, any_token=True)
3098
3099            if isinstance(field, exp.Func):
3100                # bigquery allows function calls like x.y.count(...)
3101                # SAFE.SUBSTR(...)
3102                # https://cloud.google.com/bigquery/docs/reference/standard-sql/functions-reference#function_call_rules
3103                this = self._replace_columns_with_dots(this)
3104
3105            if op:
3106                this = op(self, this, field)
3107            elif isinstance(this, exp.Column) and not this.args.get("catalog"):
3108                this = self.expression(
3109                    exp.Column,
3110                    this=field,
3111                    table=this.this,
3112                    db=this.args.get("table"),
3113                    catalog=this.args.get("db"),
3114                )
3115            else:
3116                this = self.expression(exp.Dot, this=this, expression=field)
3117            this = self._parse_bracket(this)
3118        return this
3119
3120    def _parse_primary(self) -> t.Optional[exp.Expression]:
3121        if self._match_set(self.PRIMARY_PARSERS):
3122            token_type = self._prev.token_type
3123            primary = self.PRIMARY_PARSERS[token_type](self, self._prev)
3124
3125            if token_type == TokenType.STRING:
3126                expressions = [primary]
3127                while self._match(TokenType.STRING):
3128                    expressions.append(exp.Literal.string(self._prev.text))
3129
3130                if len(expressions) > 1:
3131                    return self.expression(exp.Concat, expressions=expressions)
3132
3133            return primary
3134
3135        if self._match_pair(TokenType.DOT, TokenType.NUMBER):
3136            return exp.Literal.number(f"0.{self._prev.text}")
3137
3138        if self._match(TokenType.L_PAREN):
3139            comments = self._prev_comments
3140            query = self._parse_select()
3141
3142            if query:
3143                expressions = [query]
3144            else:
3145                expressions = self._parse_csv(self._parse_expression)
3146
3147            this = self._parse_query_modifiers(seq_get(expressions, 0))
3148
3149            if isinstance(this, exp.Subqueryable):
3150                this = self._parse_set_operations(
3151                    self._parse_subquery(this=this, parse_alias=False)
3152                )
3153            elif len(expressions) > 1:
3154                this = self.expression(exp.Tuple, expressions=expressions)
3155            else:
3156                this = self.expression(exp.Paren, this=self._parse_set_operations(this))
3157
3158            if this:
3159                this.add_comments(comments)
3160
3161            self._match_r_paren(expression=this)
3162            return this
3163
3164        return None
3165
3166    def _parse_field(
3167        self,
3168        any_token: bool = False,
3169        tokens: t.Optional[t.Collection[TokenType]] = None,
3170        anonymous_func: bool = False,
3171    ) -> t.Optional[exp.Expression]:
3172        return (
3173            self._parse_primary()
3174            or self._parse_function(anonymous=anonymous_func)
3175            or self._parse_id_var(any_token=any_token, tokens=tokens)
3176        )
3177
3178    def _parse_function(
3179        self,
3180        functions: t.Optional[t.Dict[str, t.Callable]] = None,
3181        anonymous: bool = False,
3182        optional_parens: bool = True,
3183    ) -> t.Optional[exp.Expression]:
3184        if not self._curr:
3185            return None
3186
3187        token_type = self._curr.token_type
3188
3189        if optional_parens and self._match_set(self.NO_PAREN_FUNCTION_PARSERS):
3190            return self.NO_PAREN_FUNCTION_PARSERS[token_type](self)
3191
3192        if not self._next or self._next.token_type != TokenType.L_PAREN:
3193            if optional_parens and token_type in self.NO_PAREN_FUNCTIONS:
3194                self._advance()
3195                return self.expression(self.NO_PAREN_FUNCTIONS[token_type])
3196
3197            return None
3198
3199        if token_type not in self.FUNC_TOKENS:
3200            return None
3201
3202        this = self._curr.text
3203        upper = this.upper()
3204        self._advance(2)
3205
3206        parser = self.FUNCTION_PARSERS.get(upper)
3207
3208        if parser and not anonymous:
3209            this = parser(self)
3210        else:
3211            subquery_predicate = self.SUBQUERY_PREDICATES.get(token_type)
3212
3213            if subquery_predicate and self._curr.token_type in (TokenType.SELECT, TokenType.WITH):
3214                this = self.expression(subquery_predicate, this=self._parse_select())
3215                self._match_r_paren()
3216                return this
3217
3218            if functions is None:
3219                functions = self.FUNCTIONS
3220
3221            function = functions.get(upper)
3222
3223            alias = upper in self.FUNCTIONS_WITH_ALIASED_ARGS
3224            args = self._parse_csv(lambda: self._parse_lambda(alias=alias))
3225
3226            if function and not anonymous:
3227                this = self.validate_expression(function(args), args)
3228            else:
3229                this = self.expression(exp.Anonymous, this=this, expressions=args)
3230
3231        self._match_r_paren(this)
3232        return self._parse_window(this)
3233
3234    def _parse_function_parameter(self) -> t.Optional[exp.Expression]:
3235        return self._parse_column_def(self._parse_id_var())
3236
3237    def _parse_user_defined_function(
3238        self, kind: t.Optional[TokenType] = None
3239    ) -> t.Optional[exp.Expression]:
3240        this = self._parse_id_var()
3241
3242        while self._match(TokenType.DOT):
3243            this = self.expression(exp.Dot, this=this, expression=self._parse_id_var())
3244
3245        if not self._match(TokenType.L_PAREN):
3246            return this
3247
3248        expressions = self._parse_csv(self._parse_function_parameter)
3249        self._match_r_paren()
3250        return self.expression(
3251            exp.UserDefinedFunction, this=this, expressions=expressions, wrapped=True
3252        )
3253
3254    def _parse_introducer(self, token: Token) -> exp.Introducer | exp.Identifier:
3255        literal = self._parse_primary()
3256        if literal:
3257            return self.expression(exp.Introducer, this=token.text, expression=literal)
3258
3259        return self.expression(exp.Identifier, this=token.text)
3260
3261    def _parse_session_parameter(self) -> exp.SessionParameter:
3262        kind = None
3263        this = self._parse_id_var() or self._parse_primary()
3264
3265        if this and self._match(TokenType.DOT):
3266            kind = this.name
3267            this = self._parse_var() or self._parse_primary()
3268
3269        return self.expression(exp.SessionParameter, this=this, kind=kind)
3270
3271    def _parse_lambda(self, alias: bool = False) -> t.Optional[exp.Expression]:
3272        index = self._index
3273
3274        if self._match(TokenType.L_PAREN):
3275            expressions = self._parse_csv(self._parse_id_var)
3276
3277            if not self._match(TokenType.R_PAREN):
3278                self._retreat(index)
3279        else:
3280            expressions = [self._parse_id_var()]
3281
3282        if self._match_set(self.LAMBDAS):
3283            return self.LAMBDAS[self._prev.token_type](self, expressions)
3284
3285        self._retreat(index)
3286
3287        this: t.Optional[exp.Expression]
3288
3289        if self._match(TokenType.DISTINCT):
3290            this = self.expression(
3291                exp.Distinct, expressions=self._parse_csv(self._parse_conjunction)
3292            )
3293        else:
3294            this = self._parse_select_or_expression(alias=alias)
3295
3296            if isinstance(this, exp.EQ):
3297                left = this.this
3298                if isinstance(left, exp.Column):
3299                    left.replace(exp.var(left.text("this")))
3300
3301        return self._parse_limit(self._parse_order(self._parse_respect_or_ignore_nulls(this)))
3302
3303    def _parse_schema(self, this: t.Optional[exp.Expression] = None) -> t.Optional[exp.Expression]:
3304        index = self._index
3305
3306        if not self.errors:
3307            try:
3308                if self._parse_select(nested=True):
3309                    return this
3310            except ParseError:
3311                pass
3312            finally:
3313                self.errors.clear()
3314                self._retreat(index)
3315
3316        if not self._match(TokenType.L_PAREN):
3317            return this
3318
3319        args = self._parse_csv(
3320            lambda: self._parse_constraint()
3321            or self._parse_column_def(self._parse_field(any_token=True))
3322        )
3323
3324        self._match_r_paren()
3325        return self.expression(exp.Schema, this=this, expressions=args)
3326
3327    def _parse_column_def(self, this: t.Optional[exp.Expression]) -> t.Optional[exp.Expression]:
3328        # column defs are not really columns, they're identifiers
3329        if isinstance(this, exp.Column):
3330            this = this.this
3331
3332        kind = self._parse_types(schema=True)
3333
3334        if self._match_text_seq("FOR", "ORDINALITY"):
3335            return self.expression(exp.ColumnDef, this=this, ordinality=True)
3336
3337        constraints = []
3338        while True:
3339            constraint = self._parse_column_constraint()
3340            if not constraint:
3341                break
3342            constraints.append(constraint)
3343
3344        if not kind and not constraints:
3345            return this
3346
3347        return self.expression(exp.ColumnDef, this=this, kind=kind, constraints=constraints)
3348
3349    def _parse_auto_increment(
3350        self,
3351    ) -> exp.GeneratedAsIdentityColumnConstraint | exp.AutoIncrementColumnConstraint:
3352        start = None
3353        increment = None
3354
3355        if self._match(TokenType.L_PAREN, advance=False):
3356            args = self._parse_wrapped_csv(self._parse_bitwise)
3357            start = seq_get(args, 0)
3358            increment = seq_get(args, 1)
3359        elif self._match_text_seq("START"):
3360            start = self._parse_bitwise()
3361            self._match_text_seq("INCREMENT")
3362            increment = self._parse_bitwise()
3363
3364        if start and increment:
3365            return exp.GeneratedAsIdentityColumnConstraint(start=start, increment=increment)
3366
3367        return exp.AutoIncrementColumnConstraint()
3368
3369    def _parse_compress(self) -> exp.CompressColumnConstraint:
3370        if self._match(TokenType.L_PAREN, advance=False):
3371            return self.expression(
3372                exp.CompressColumnConstraint, this=self._parse_wrapped_csv(self._parse_bitwise)
3373            )
3374
3375        return self.expression(exp.CompressColumnConstraint, this=self._parse_bitwise())
3376
3377    def _parse_generated_as_identity(self) -> exp.GeneratedAsIdentityColumnConstraint:
3378        if self._match_text_seq("BY", "DEFAULT"):
3379            on_null = self._match_pair(TokenType.ON, TokenType.NULL)
3380            this = self.expression(
3381                exp.GeneratedAsIdentityColumnConstraint, this=False, on_null=on_null
3382            )
3383        else:
3384            self._match_text_seq("ALWAYS")
3385            this = self.expression(exp.GeneratedAsIdentityColumnConstraint, this=True)
3386
3387        self._match(TokenType.ALIAS)
3388        identity = self._match_text_seq("IDENTITY")
3389
3390        if self._match(TokenType.L_PAREN):
3391            if self._match_text_seq("START", "WITH"):
3392                this.set("start", self._parse_bitwise())
3393            if self._match_text_seq("INCREMENT", "BY"):
3394                this.set("increment", self._parse_bitwise())
3395            if self._match_text_seq("MINVALUE"):
3396                this.set("minvalue", self._parse_bitwise())
3397            if self._match_text_seq("MAXVALUE"):
3398                this.set("maxvalue", self._parse_bitwise())
3399
3400            if self._match_text_seq("CYCLE"):
3401                this.set("cycle", True)
3402            elif self._match_text_seq("NO", "CYCLE"):
3403                this.set("cycle", False)
3404
3405            if not identity:
3406                this.set("expression", self._parse_bitwise())
3407
3408            self._match_r_paren()
3409
3410        return this
3411
3412    def _parse_inline(self) -> exp.InlineLengthColumnConstraint:
3413        self._match_text_seq("LENGTH")
3414        return self.expression(exp.InlineLengthColumnConstraint, this=self._parse_bitwise())
3415
3416    def _parse_not_constraint(
3417        self,
3418    ) -> t.Optional[exp.NotNullColumnConstraint | exp.CaseSpecificColumnConstraint]:
3419        if self._match_text_seq("NULL"):
3420            return self.expression(exp.NotNullColumnConstraint)
3421        if self._match_text_seq("CASESPECIFIC"):
3422            return self.expression(exp.CaseSpecificColumnConstraint, not_=True)
3423        return None
3424
3425    def _parse_column_constraint(self) -> t.Optional[exp.Expression]:
3426        if self._match(TokenType.CONSTRAINT):
3427            this = self._parse_id_var()
3428        else:
3429            this = None
3430
3431        if self._match_texts(self.CONSTRAINT_PARSERS):
3432            return self.expression(
3433                exp.ColumnConstraint,
3434                this=this,
3435                kind=self.CONSTRAINT_PARSERS[self._prev.text.upper()](self),
3436            )
3437
3438        return this
3439
3440    def _parse_constraint(self) -> t.Optional[exp.Expression]:
3441        if not self._match(TokenType.CONSTRAINT):
3442            return self._parse_unnamed_constraint(constraints=self.SCHEMA_UNNAMED_CONSTRAINTS)
3443
3444        this = self._parse_id_var()
3445        expressions = []
3446
3447        while True:
3448            constraint = self._parse_unnamed_constraint() or self._parse_function()
3449            if not constraint:
3450                break
3451            expressions.append(constraint)
3452
3453        return self.expression(exp.Constraint, this=this, expressions=expressions)
3454
3455    def _parse_unnamed_constraint(
3456        self, constraints: t.Optional[t.Collection[str]] = None
3457    ) -> t.Optional[exp.Expression]:
3458        if not self._match_texts(constraints or self.CONSTRAINT_PARSERS):
3459            return None
3460
3461        constraint = self._prev.text.upper()
3462        if constraint not in self.CONSTRAINT_PARSERS:
3463            self.raise_error(f"No parser found for schema constraint {constraint}.")
3464
3465        return self.CONSTRAINT_PARSERS[constraint](self)
3466
3467    def _parse_unique(self) -> exp.UniqueColumnConstraint:
3468        self._match_text_seq("KEY")
3469        return self.expression(
3470            exp.UniqueColumnConstraint, this=self._parse_schema(self._parse_id_var(any_token=False))
3471        )
3472
3473    def _parse_key_constraint_options(self) -> t.List[str]:
3474        options = []
3475        while True:
3476            if not self._curr:
3477                break
3478
3479            if self._match(TokenType.ON):
3480                action = None
3481                on = self._advance_any() and self._prev.text
3482
3483                if self._match_text_seq("NO", "ACTION"):
3484                    action = "NO ACTION"
3485                elif self._match_text_seq("CASCADE"):
3486                    action = "CASCADE"
3487                elif self._match_pair(TokenType.SET, TokenType.NULL):
3488                    action = "SET NULL"
3489                elif self._match_pair(TokenType.SET, TokenType.DEFAULT):
3490                    action = "SET DEFAULT"
3491                else:
3492                    self.raise_error("Invalid key constraint")
3493
3494                options.append(f"ON {on} {action}")
3495            elif self._match_text_seq("NOT", "ENFORCED"):
3496                options.append("NOT ENFORCED")
3497            elif self._match_text_seq("DEFERRABLE"):
3498                options.append("DEFERRABLE")
3499            elif self._match_text_seq("INITIALLY", "DEFERRED"):
3500                options.append("INITIALLY DEFERRED")
3501            elif self._match_text_seq("NORELY"):
3502                options.append("NORELY")
3503            elif self._match_text_seq("MATCH", "FULL"):
3504                options.append("MATCH FULL")
3505            else:
3506                break
3507
3508        return options
3509
3510    def _parse_references(self, match: bool = True) -> t.Optional[exp.Reference]:
3511        if match and not self._match(TokenType.REFERENCES):
3512            return None
3513
3514        expressions = None
3515        this = self._parse_id_var()
3516
3517        if self._match(TokenType.L_PAREN, advance=False):
3518            expressions = self._parse_wrapped_id_vars()
3519
3520        options = self._parse_key_constraint_options()
3521        return self.expression(exp.Reference, this=this, expressions=expressions, options=options)
3522
3523    def _parse_foreign_key(self) -> exp.ForeignKey:
3524        expressions = self._parse_wrapped_id_vars()
3525        reference = self._parse_references()
3526        options = {}
3527
3528        while self._match(TokenType.ON):
3529            if not self._match_set((TokenType.DELETE, TokenType.UPDATE)):
3530                self.raise_error("Expected DELETE or UPDATE")
3531
3532            kind = self._prev.text.lower()
3533
3534            if self._match_text_seq("NO", "ACTION"):
3535                action = "NO ACTION"
3536            elif self._match(TokenType.SET):
3537                self._match_set((TokenType.NULL, TokenType.DEFAULT))
3538                action = "SET " + self._prev.text.upper()
3539            else:
3540                self._advance()
3541                action = self._prev.text.upper()
3542
3543            options[kind] = action
3544
3545        return self.expression(
3546            exp.ForeignKey, expressions=expressions, reference=reference, **options  # type: ignore
3547        )
3548
3549    def _parse_primary_key(
3550        self, wrapped_optional: bool = False, in_props: bool = False
3551    ) -> exp.PrimaryKeyColumnConstraint | exp.PrimaryKey:
3552        desc = (
3553            self._match_set((TokenType.ASC, TokenType.DESC))
3554            and self._prev.token_type == TokenType.DESC
3555        )
3556
3557        if not in_props and not self._match(TokenType.L_PAREN, advance=False):
3558            return self.expression(exp.PrimaryKeyColumnConstraint, desc=desc)
3559
3560        expressions = self._parse_wrapped_csv(self._parse_field, optional=wrapped_optional)
3561        options = self._parse_key_constraint_options()
3562        return self.expression(exp.PrimaryKey, expressions=expressions, options=options)
3563
3564    def _parse_bracket(self, this: t.Optional[exp.Expression]) -> t.Optional[exp.Expression]:
3565        if not self._match_set((TokenType.L_BRACKET, TokenType.L_BRACE)):
3566            return this
3567
3568        bracket_kind = self._prev.token_type
3569
3570        if self._match(TokenType.COLON):
3571            expressions: t.List[t.Optional[exp.Expression]] = [
3572                self.expression(exp.Slice, expression=self._parse_conjunction())
3573            ]
3574        else:
3575            expressions = self._parse_csv(lambda: self._parse_slice(self._parse_conjunction()))
3576
3577        # https://duckdb.org/docs/sql/data_types/struct.html#creating-structs
3578        if bracket_kind == TokenType.L_BRACE:
3579            this = self.expression(exp.Struct, expressions=expressions)
3580        elif not this or this.name.upper() == "ARRAY":
3581            this = self.expression(exp.Array, expressions=expressions)
3582        else:
3583            expressions = apply_index_offset(this, expressions, -self.INDEX_OFFSET)
3584            this = self.expression(exp.Bracket, this=this, expressions=expressions)
3585
3586        if not self._match(TokenType.R_BRACKET) and bracket_kind == TokenType.L_BRACKET:
3587            self.raise_error("Expected ]")
3588        elif not self._match(TokenType.R_BRACE) and bracket_kind == TokenType.L_BRACE:
3589            self.raise_error("Expected }")
3590
3591        self._add_comments(this)
3592        return self._parse_bracket(this)
3593
3594    def _parse_slice(self, this: t.Optional[exp.Expression]) -> t.Optional[exp.Expression]:
3595        if self._match(TokenType.COLON):
3596            return self.expression(exp.Slice, this=this, expression=self._parse_conjunction())
3597        return this
3598
3599    def _parse_case(self) -> t.Optional[exp.Expression]:
3600        ifs = []
3601        default = None
3602
3603        expression = self._parse_conjunction()
3604
3605        while self._match(TokenType.WHEN):
3606            this = self._parse_conjunction()
3607            self._match(TokenType.THEN)
3608            then = self._parse_conjunction()
3609            ifs.append(self.expression(exp.If, this=this, true=then))
3610
3611        if self._match(TokenType.ELSE):
3612            default = self._parse_conjunction()
3613
3614        if not self._match(TokenType.END):
3615            self.raise_error("Expected END after CASE", self._prev)
3616
3617        return self._parse_window(
3618            self.expression(exp.Case, this=expression, ifs=ifs, default=default)
3619        )
3620
3621    def _parse_if(self) -> t.Optional[exp.Expression]:
3622        if self._match(TokenType.L_PAREN):
3623            args = self._parse_csv(self._parse_conjunction)
3624            this = self.validate_expression(exp.If.from_arg_list(args), args)
3625            self._match_r_paren()
3626        else:
3627            index = self._index - 1
3628            condition = self._parse_conjunction()
3629
3630            if not condition:
3631                self._retreat(index)
3632                return None
3633
3634            self._match(TokenType.THEN)
3635            true = self._parse_conjunction()
3636            false = self._parse_conjunction() if self._match(TokenType.ELSE) else None
3637            self._match(TokenType.END)
3638            this = self.expression(exp.If, this=condition, true=true, false=false)
3639
3640        return self._parse_window(this)
3641
3642    def _parse_extract(self) -> exp.Extract:
3643        this = self._parse_function() or self._parse_var() or self._parse_type()
3644
3645        if self._match(TokenType.FROM):
3646            return self.expression(exp.Extract, this=this, expression=self._parse_bitwise())
3647
3648        if not self._match(TokenType.COMMA):
3649            self.raise_error("Expected FROM or comma after EXTRACT", self._prev)
3650
3651        return self.expression(exp.Extract, this=this, expression=self._parse_bitwise())
3652
3653    def _parse_cast(self, strict: bool) -> exp.Expression:
3654        this = self._parse_conjunction()
3655
3656        if not self._match(TokenType.ALIAS):
3657            if self._match(TokenType.COMMA):
3658                return self.expression(
3659                    exp.CastToStrType, this=this, expression=self._parse_string()
3660                )
3661            else:
3662                self.raise_error("Expected AS after CAST")
3663
3664        to = self._parse_types()
3665
3666        if not to:
3667            self.raise_error("Expected TYPE after CAST")
3668        elif to.this == exp.DataType.Type.CHAR:
3669            if self._match(TokenType.CHARACTER_SET):
3670                to = self.expression(exp.CharacterSet, this=self._parse_var_or_string())
3671        elif to.this in exp.DataType.TEMPORAL_TYPES and self._match(TokenType.FORMAT):
3672            fmt = self._parse_string()
3673
3674            return self.expression(
3675                exp.StrToDate if to.this == exp.DataType.Type.DATE else exp.StrToTime,
3676                this=this,
3677                format=exp.Literal.string(
3678                    format_time(
3679                        fmt.this if fmt else "",
3680                        self.FORMAT_MAPPING or self.TIME_MAPPING,
3681                        self.FORMAT_TRIE or self.TIME_TRIE,
3682                    )
3683                ),
3684            )
3685
3686        return self.expression(exp.Cast if strict else exp.TryCast, this=this, to=to)
3687
3688    def _parse_concat(self) -> t.Optional[exp.Expression]:
3689        args = self._parse_csv(self._parse_conjunction)
3690        if self.CONCAT_NULL_OUTPUTS_STRING:
3691            args = [
3692                exp.func("COALESCE", exp.cast(arg, "text"), exp.Literal.string(""))
3693                for arg in args
3694                if arg
3695            ]
3696
3697        # Some dialects (e.g. Trino) don't allow a single-argument CONCAT call, so when
3698        # we find such a call we replace it with its argument.
3699        if len(args) == 1:
3700            return args[0]
3701
3702        return self.expression(
3703            exp.Concat if self.STRICT_STRING_CONCAT else exp.SafeConcat, expressions=args
3704        )
3705
3706    def _parse_string_agg(self) -> exp.Expression:
3707        expression: t.Optional[exp.Expression]
3708
3709        if self._match(TokenType.DISTINCT):
3710            args = self._parse_csv(self._parse_conjunction)
3711            expression = self.expression(exp.Distinct, expressions=[seq_get(args, 0)])
3712        else:
3713            args = self._parse_csv(self._parse_conjunction)
3714            expression = seq_get(args, 0)
3715
3716        index = self._index
3717        if not self._match(TokenType.R_PAREN):
3718            # postgres: STRING_AGG([DISTINCT] expression, separator [ORDER BY expression1 {ASC | DESC} [, ...]])
3719            order = self._parse_order(this=expression)
3720            return self.expression(exp.GroupConcat, this=order, separator=seq_get(args, 1))
3721
3722        # Checks if we can parse an order clause: WITHIN GROUP (ORDER BY <order_by_expression_list> [ASC | DESC]).
3723        # This is done "manually", instead of letting _parse_window parse it into an exp.WithinGroup node, so that
3724        # the STRING_AGG call is parsed like in MySQL / SQLite and can thus be transpiled more easily to them.
3725        if not self._match_text_seq("WITHIN", "GROUP"):
3726            self._retreat(index)
3727            return self.validate_expression(exp.GroupConcat.from_arg_list(args), args)
3728
3729        self._match_l_paren()  # The corresponding match_r_paren will be called in parse_function (caller)
3730        order = self._parse_order(this=expression)
3731        return self.expression(exp.GroupConcat, this=order, separator=seq_get(args, 1))
3732
3733    def _parse_convert(self, strict: bool) -> t.Optional[exp.Expression]:
3734        to: t.Optional[exp.Expression]
3735        this = self._parse_bitwise()
3736
3737        if self._match(TokenType.USING):
3738            to = self.expression(exp.CharacterSet, this=self._parse_var())
3739        elif self._match(TokenType.COMMA):
3740            to = self._parse_bitwise()
3741        else:
3742            to = None
3743
3744        # Swap the argument order if needed to produce the correct AST
3745        if self.CONVERT_TYPE_FIRST:
3746            this, to = to, this
3747
3748        return self.expression(exp.Cast if strict else exp.TryCast, this=this, to=to)
3749
3750    def _parse_decode(self) -> t.Optional[exp.Decode | exp.Case]:
3751        """
3752        There are generally two variants of the DECODE function:
3753
3754        - DECODE(bin, charset)
3755        - DECODE(expression, search, result [, search, result] ... [, default])
3756
3757        The second variant will always be parsed into a CASE expression. Note that NULL
3758        needs special treatment, since we need to explicitly check for it with `IS NULL`,
3759        instead of relying on pattern matching.
3760        """
3761        args = self._parse_csv(self._parse_conjunction)
3762
3763        if len(args) < 3:
3764            return self.expression(exp.Decode, this=seq_get(args, 0), charset=seq_get(args, 1))
3765
3766        expression, *expressions = args
3767        if not expression:
3768            return None
3769
3770        ifs = []
3771        for search, result in zip(expressions[::2], expressions[1::2]):
3772            if not search or not result:
3773                return None
3774
3775            if isinstance(search, exp.Literal):
3776                ifs.append(
3777                    exp.If(this=exp.EQ(this=expression.copy(), expression=search), true=result)
3778                )
3779            elif isinstance(search, exp.Null):
3780                ifs.append(
3781                    exp.If(this=exp.Is(this=expression.copy(), expression=exp.Null()), true=result)
3782                )
3783            else:
3784                cond = exp.or_(
3785                    exp.EQ(this=expression.copy(), expression=search),
3786                    exp.and_(
3787                        exp.Is(this=expression.copy(), expression=exp.Null()),
3788                        exp.Is(this=search.copy(), expression=exp.Null()),
3789                        copy=False,
3790                    ),
3791                    copy=False,
3792                )
3793                ifs.append(exp.If(this=cond, true=result))
3794
3795        return exp.Case(ifs=ifs, default=expressions[-1] if len(expressions) % 2 == 1 else None)
3796
3797    def _parse_json_key_value(self) -> t.Optional[exp.JSONKeyValue]:
3798        self._match_text_seq("KEY")
3799        key = self._parse_field()
3800        self._match(TokenType.COLON)
3801        self._match_text_seq("VALUE")
3802        value = self._parse_field()
3803
3804        if not key and not value:
3805            return None
3806        return self.expression(exp.JSONKeyValue, this=key, expression=value)
3807
3808    def _parse_json_object(self) -> exp.JSONObject:
3809        star = self._parse_star()
3810        expressions = [star] if star else self._parse_csv(self._parse_json_key_value)
3811
3812        null_handling = None
3813        if self._match_text_seq("NULL", "ON", "NULL"):
3814            null_handling = "NULL ON NULL"
3815        elif self._match_text_seq("ABSENT", "ON", "NULL"):
3816            null_handling = "ABSENT ON NULL"
3817
3818        unique_keys = None
3819        if self._match_text_seq("WITH", "UNIQUE"):
3820            unique_keys = True
3821        elif self._match_text_seq("WITHOUT", "UNIQUE"):
3822            unique_keys = False
3823
3824        self._match_text_seq("KEYS")
3825
3826        return_type = self._match_text_seq("RETURNING") and self._parse_type()
3827        format_json = self._match_text_seq("FORMAT", "JSON")
3828        encoding = self._match_text_seq("ENCODING") and self._parse_var()
3829
3830        return self.expression(
3831            exp.JSONObject,
3832            expressions=expressions,
3833            null_handling=null_handling,
3834            unique_keys=unique_keys,
3835            return_type=return_type,
3836            format_json=format_json,
3837            encoding=encoding,
3838        )
3839
3840    def _parse_logarithm(self) -> exp.Func:
3841        # Default argument order is base, expression
3842        args = self._parse_csv(self._parse_range)
3843
3844        if len(args) > 1:
3845            if not self.LOG_BASE_FIRST:
3846                args.reverse()
3847            return exp.Log.from_arg_list(args)
3848
3849        return self.expression(
3850            exp.Ln if self.LOG_DEFAULTS_TO_LN else exp.Log, this=seq_get(args, 0)
3851        )
3852
3853    def _parse_match_against(self) -> exp.MatchAgainst:
3854        expressions = self._parse_csv(self._parse_column)
3855
3856        self._match_text_seq(")", "AGAINST", "(")
3857
3858        this = self._parse_string()
3859
3860        if self._match_text_seq("IN", "NATURAL", "LANGUAGE", "MODE"):
3861            modifier = "IN NATURAL LANGUAGE MODE"
3862            if self._match_text_seq("WITH", "QUERY", "EXPANSION"):
3863                modifier = f"{modifier} WITH QUERY EXPANSION"
3864        elif self._match_text_seq("IN", "BOOLEAN", "MODE"):
3865            modifier = "IN BOOLEAN MODE"
3866        elif self._match_text_seq("WITH", "QUERY", "EXPANSION"):
3867            modifier = "WITH QUERY EXPANSION"
3868        else:
3869            modifier = None
3870
3871        return self.expression(
3872            exp.MatchAgainst, this=this, expressions=expressions, modifier=modifier
3873        )
3874
3875    # https://learn.microsoft.com/en-us/sql/t-sql/functions/openjson-transact-sql?view=sql-server-ver16
3876    def _parse_open_json(self) -> exp.OpenJSON:
3877        this = self._parse_bitwise()
3878        path = self._match(TokenType.COMMA) and self._parse_string()
3879
3880        def _parse_open_json_column_def() -> exp.OpenJSONColumnDef:
3881            this = self._parse_field(any_token=True)
3882            kind = self._parse_types()
3883            path = self._parse_string()
3884            as_json = self._match_pair(TokenType.ALIAS, TokenType.JSON)
3885
3886            return self.expression(
3887                exp.OpenJSONColumnDef, this=this, kind=kind, path=path, as_json=as_json
3888            )
3889
3890        expressions = None
3891        if self._match_pair(TokenType.R_PAREN, TokenType.WITH):
3892            self._match_l_paren()
3893            expressions = self._parse_csv(_parse_open_json_column_def)
3894
3895        return self.expression(exp.OpenJSON, this=this, path=path, expressions=expressions)
3896
3897    def _parse_position(self, haystack_first: bool = False) -> exp.StrPosition:
3898        args = self._parse_csv(self._parse_bitwise)
3899
3900        if self._match(TokenType.IN):
3901            return self.expression(
3902                exp.StrPosition, this=self._parse_bitwise(), substr=seq_get(args, 0)
3903            )
3904
3905        if haystack_first:
3906            haystack = seq_get(args, 0)
3907            needle = seq_get(args, 1)
3908        else:
3909            needle = seq_get(args, 0)
3910            haystack = seq_get(args, 1)
3911
3912        return self.expression(
3913            exp.StrPosition, this=haystack, substr=needle, position=seq_get(args, 2)
3914        )
3915
3916    def _parse_join_hint(self, func_name: str) -> exp.JoinHint:
3917        args = self._parse_csv(self._parse_table)
3918        return exp.JoinHint(this=func_name.upper(), expressions=args)
3919
3920    def _parse_substring(self) -> exp.Substring:
3921        # Postgres supports the form: substring(string [from int] [for int])
3922        # https://www.postgresql.org/docs/9.1/functions-string.html @ Table 9-6
3923
3924        args = self._parse_csv(self._parse_bitwise)
3925
3926        if self._match(TokenType.FROM):
3927            args.append(self._parse_bitwise())
3928            if self._match(TokenType.FOR):
3929                args.append(self._parse_bitwise())
3930
3931        return self.validate_expression(exp.Substring.from_arg_list(args), args)
3932
3933    def _parse_trim(self) -> exp.Trim:
3934        # https://www.w3resource.com/sql/character-functions/trim.php
3935        # https://docs.oracle.com/javadb/10.8.3.0/ref/rreftrimfunc.html
3936
3937        position = None
3938        collation = None
3939
3940        if self._match_texts(self.TRIM_TYPES):
3941            position = self._prev.text.upper()
3942
3943        expression = self._parse_bitwise()
3944        if self._match_set((TokenType.FROM, TokenType.COMMA)):
3945            this = self._parse_bitwise()
3946        else:
3947            this = expression
3948            expression = None
3949
3950        if self._match(TokenType.COLLATE):
3951            collation = self._parse_bitwise()
3952
3953        return self.expression(
3954            exp.Trim, this=this, position=position, expression=expression, collation=collation
3955        )
3956
3957    def _parse_window_clause(self) -> t.Optional[t.List[t.Optional[exp.Expression]]]:
3958        return self._match(TokenType.WINDOW) and self._parse_csv(self._parse_named_window)
3959
3960    def _parse_named_window(self) -> t.Optional[exp.Expression]:
3961        return self._parse_window(self._parse_id_var(), alias=True)
3962
3963    def _parse_respect_or_ignore_nulls(
3964        self, this: t.Optional[exp.Expression]
3965    ) -> t.Optional[exp.Expression]:
3966        if self._match_text_seq("IGNORE", "NULLS"):
3967            return self.expression(exp.IgnoreNulls, this=this)
3968        if self._match_text_seq("RESPECT", "NULLS"):
3969            return self.expression(exp.RespectNulls, this=this)
3970        return this
3971
3972    def _parse_window(
3973        self, this: t.Optional[exp.Expression], alias: bool = False
3974    ) -> t.Optional[exp.Expression]:
3975        if self._match_pair(TokenType.FILTER, TokenType.L_PAREN):
3976            this = self.expression(exp.Filter, this=this, expression=self._parse_where())
3977            self._match_r_paren()
3978
3979        # T-SQL allows the OVER (...) syntax after WITHIN GROUP.
3980        # https://learn.microsoft.com/en-us/sql/t-sql/functions/percentile-disc-transact-sql?view=sql-server-ver16
3981        if self._match_text_seq("WITHIN", "GROUP"):
3982            order = self._parse_wrapped(self._parse_order)
3983            this = self.expression(exp.WithinGroup, this=this, expression=order)
3984
3985        # SQL spec defines an optional [ { IGNORE | RESPECT } NULLS ] OVER
3986        # Some dialects choose to implement and some do not.
3987        # https://dev.mysql.com/doc/refman/8.0/en/window-function-descriptions.html
3988
3989        # There is some code above in _parse_lambda that handles
3990        #   SELECT FIRST_VALUE(TABLE.COLUMN IGNORE|RESPECT NULLS) OVER ...
3991
3992        # The below changes handle
3993        #   SELECT FIRST_VALUE(TABLE.COLUMN) IGNORE|RESPECT NULLS OVER ...
3994
3995        # Oracle allows both formats
3996        #   (https://docs.oracle.com/en/database/oracle/oracle-database/19/sqlrf/img_text/first_value.html)
3997        #   and Snowflake chose to do the same for familiarity
3998        #   https://docs.snowflake.com/en/sql-reference/functions/first_value.html#usage-notes
3999        this = self._parse_respect_or_ignore_nulls(this)
4000
4001        # bigquery select from window x AS (partition by ...)
4002        if alias:
4003            over = None
4004            self._match(TokenType.ALIAS)
4005        elif not self._match_set(self.WINDOW_BEFORE_PAREN_TOKENS):
4006            return this
4007        else:
4008            over = self._prev.text.upper()
4009
4010        if not self._match(TokenType.L_PAREN):
4011            return self.expression(
4012                exp.Window, this=this, alias=self._parse_id_var(False), over=over
4013            )
4014
4015        window_alias = self._parse_id_var(any_token=False, tokens=self.WINDOW_ALIAS_TOKENS)
4016
4017        first = self._match(TokenType.FIRST)
4018        if self._match_text_seq("LAST"):
4019            first = False
4020
4021        partition = self._parse_partition_by()
4022        order = self._parse_order()
4023        kind = self._match_set((TokenType.ROWS, TokenType.RANGE)) and self._prev.text
4024
4025        if kind:
4026            self._match(TokenType.BETWEEN)
4027            start = self._parse_window_spec()
4028            self._match(TokenType.AND)
4029            end = self._parse_window_spec()
4030
4031            spec = self.expression(
4032                exp.WindowSpec,
4033                kind=kind,
4034                start=start["value"],
4035                start_side=start["side"],
4036                end=end["value"],
4037                end_side=end["side"],
4038            )
4039        else:
4040            spec = None
4041
4042        self._match_r_paren()
4043
4044        return self.expression(
4045            exp.Window,
4046            this=this,
4047            partition_by=partition,
4048            order=order,
4049            spec=spec,
4050            alias=window_alias,
4051            over=over,
4052            first=first,
4053        )
4054
4055    def _parse_window_spec(self) -> t.Dict[str, t.Optional[str | exp.Expression]]:
4056        self._match(TokenType.BETWEEN)
4057
4058        return {
4059            "value": (
4060                (self._match_text_seq("UNBOUNDED") and "UNBOUNDED")
4061                or (self._match_text_seq("CURRENT", "ROW") and "CURRENT ROW")
4062                or self._parse_bitwise()
4063            ),
4064            "side": self._match_texts(self.WINDOW_SIDES) and self._prev.text,
4065        }
4066
4067    def _parse_alias(
4068        self, this: t.Optional[exp.Expression], explicit: bool = False
4069    ) -> t.Optional[exp.Expression]:
4070        any_token = self._match(TokenType.ALIAS)
4071
4072        if explicit and not any_token:
4073            return this
4074
4075        if self._match(TokenType.L_PAREN):
4076            aliases = self.expression(
4077                exp.Aliases,
4078                this=this,
4079                expressions=self._parse_csv(lambda: self._parse_id_var(any_token)),
4080            )
4081            self._match_r_paren(aliases)
4082            return aliases
4083
4084        alias = self._parse_id_var(any_token)
4085
4086        if alias:
4087            return self.expression(exp.Alias, this=this, alias=alias)
4088
4089        return this
4090
4091    def _parse_id_var(
4092        self,
4093        any_token: bool = True,
4094        tokens: t.Optional[t.Collection[TokenType]] = None,
4095    ) -> t.Optional[exp.Expression]:
4096        identifier = self._parse_identifier()
4097
4098        if identifier:
4099            return identifier
4100
4101        if (any_token and self._advance_any()) or self._match_set(tokens or self.ID_VAR_TOKENS):
4102            quoted = self._prev.token_type == TokenType.STRING
4103            return exp.Identifier(this=self._prev.text, quoted=quoted)
4104
4105        return None
4106
4107    def _parse_string(self) -> t.Optional[exp.Expression]:
4108        if self._match(TokenType.STRING):
4109            return self.PRIMARY_PARSERS[TokenType.STRING](self, self._prev)
4110        return self._parse_placeholder()
4111
4112    def _parse_string_as_identifier(self) -> t.Optional[exp.Identifier]:
4113        return exp.to_identifier(self._match(TokenType.STRING) and self._prev.text, quoted=True)
4114
4115    def _parse_number(self) -> t.Optional[exp.Expression]:
4116        if self._match(TokenType.NUMBER):
4117            return self.PRIMARY_PARSERS[TokenType.NUMBER](self, self._prev)
4118        return self._parse_placeholder()
4119
4120    def _parse_identifier(self) -> t.Optional[exp.Expression]:
4121        if self._match(TokenType.IDENTIFIER):
4122            return self.expression(exp.Identifier, this=self._prev.text, quoted=True)
4123        return self._parse_placeholder()
4124
4125    def _parse_var(
4126        self, any_token: bool = False, tokens: t.Optional[t.Collection[TokenType]] = None
4127    ) -> t.Optional[exp.Expression]:
4128        if (
4129            (any_token and self._advance_any())
4130            or self._match(TokenType.VAR)
4131            or (self._match_set(tokens) if tokens else False)
4132        ):
4133            return self.expression(exp.Var, this=self._prev.text)
4134        return self._parse_placeholder()
4135
4136    def _advance_any(self) -> t.Optional[Token]:
4137        if self._curr and self._curr.token_type not in self.RESERVED_KEYWORDS:
4138            self._advance()
4139            return self._prev
4140        return None
4141
4142    def _parse_var_or_string(self) -> t.Optional[exp.Expression]:
4143        return self._parse_var() or self._parse_string()
4144
4145    def _parse_null(self) -> t.Optional[exp.Expression]:
4146        if self._match(TokenType.NULL):
4147            return self.PRIMARY_PARSERS[TokenType.NULL](self, self._prev)
4148        return None
4149
4150    def _parse_boolean(self) -> t.Optional[exp.Expression]:
4151        if self._match(TokenType.TRUE):
4152            return self.PRIMARY_PARSERS[TokenType.TRUE](self, self._prev)
4153        if self._match(TokenType.FALSE):
4154            return self.PRIMARY_PARSERS[TokenType.FALSE](self, self._prev)
4155        return None
4156
4157    def _parse_star(self) -> t.Optional[exp.Expression]:
4158        if self._match(TokenType.STAR):
4159            return self.PRIMARY_PARSERS[TokenType.STAR](self, self._prev)
4160        return None
4161
4162    def _parse_parameter(self) -> exp.Parameter:
4163        wrapped = self._match(TokenType.L_BRACE)
4164        this = self._parse_var() or self._parse_identifier() or self._parse_primary()
4165        self._match(TokenType.R_BRACE)
4166        return self.expression(exp.Parameter, this=this, wrapped=wrapped)
4167
4168    def _parse_placeholder(self) -> t.Optional[exp.Expression]:
4169        if self._match_set(self.PLACEHOLDER_PARSERS):
4170            placeholder = self.PLACEHOLDER_PARSERS[self._prev.token_type](self)
4171            if placeholder:
4172                return placeholder
4173            self._advance(-1)
4174        return None
4175
4176    def _parse_except(self) -> t.Optional[t.List[t.Optional[exp.Expression]]]:
4177        if not self._match(TokenType.EXCEPT):
4178            return None
4179        if self._match(TokenType.L_PAREN, advance=False):
4180            return self._parse_wrapped_csv(self._parse_column)
4181        return self._parse_csv(self._parse_column)
4182
4183    def _parse_replace(self) -> t.Optional[t.List[t.Optional[exp.Expression]]]:
4184        if not self._match(TokenType.REPLACE):
4185            return None
4186        if self._match(TokenType.L_PAREN, advance=False):
4187            return self._parse_wrapped_csv(self._parse_expression)
4188        return self._parse_csv(self._parse_expression)
4189
4190    def _parse_csv(
4191        self, parse_method: t.Callable, sep: TokenType = TokenType.COMMA
4192    ) -> t.List[t.Optional[exp.Expression]]:
4193        parse_result = parse_method()
4194        items = [parse_result] if parse_result is not None else []
4195
4196        while self._match(sep):
4197            self._add_comments(parse_result)
4198            parse_result = parse_method()
4199            if parse_result is not None:
4200                items.append(parse_result)
4201
4202        return items
4203
4204    def _parse_tokens(
4205        self, parse_method: t.Callable, expressions: t.Dict
4206    ) -> t.Optional[exp.Expression]:
4207        this = parse_method()
4208
4209        while self._match_set(expressions):
4210            this = self.expression(
4211                expressions[self._prev.token_type],
4212                this=this,
4213                comments=self._prev_comments,
4214                expression=parse_method(),
4215            )
4216
4217        return this
4218
4219    def _parse_wrapped_id_vars(self, optional: bool = False) -> t.List[t.Optional[exp.Expression]]:
4220        return self._parse_wrapped_csv(self._parse_id_var, optional=optional)
4221
4222    def _parse_wrapped_csv(
4223        self, parse_method: t.Callable, sep: TokenType = TokenType.COMMA, optional: bool = False
4224    ) -> t.List[t.Optional[exp.Expression]]:
4225        return self._parse_wrapped(
4226            lambda: self._parse_csv(parse_method, sep=sep), optional=optional
4227        )
4228
4229    def _parse_wrapped(self, parse_method: t.Callable, optional: bool = False) -> t.Any:
4230        wrapped = self._match(TokenType.L_PAREN)
4231        if not wrapped and not optional:
4232            self.raise_error("Expecting (")
4233        parse_result = parse_method()
4234        if wrapped:
4235            self._match_r_paren()
4236        return parse_result
4237
4238    def _parse_select_or_expression(self, alias: bool = False) -> t.Optional[exp.Expression]:
4239        return self._parse_select() or self._parse_set_operations(
4240            self._parse_expression() if alias else self._parse_conjunction()
4241        )
4242
4243    def _parse_ddl_select(self) -> t.Optional[exp.Expression]:
4244        return self._parse_query_modifiers(
4245            self._parse_set_operations(self._parse_select(nested=True, parse_subquery_alias=False))
4246        )
4247
4248    def _parse_transaction(self) -> exp.Transaction:
4249        this = None
4250        if self._match_texts(self.TRANSACTION_KIND):
4251            this = self._prev.text
4252
4253        self._match_texts({"TRANSACTION", "WORK"})
4254
4255        modes = []
4256        while True:
4257            mode = []
4258            while self._match(TokenType.VAR):
4259                mode.append(self._prev.text)
4260
4261            if mode:
4262                modes.append(" ".join(mode))
4263            if not self._match(TokenType.COMMA):
4264                break
4265
4266        return self.expression(exp.Transaction, this=this, modes=modes)
4267
4268    def _parse_commit_or_rollback(self) -> exp.Commit | exp.Rollback:
4269        chain = None
4270        savepoint = None
4271        is_rollback = self._prev.token_type == TokenType.ROLLBACK
4272
4273        self._match_texts({"TRANSACTION", "WORK"})
4274
4275        if self._match_text_seq("TO"):
4276            self._match_text_seq("SAVEPOINT")
4277            savepoint = self._parse_id_var()
4278
4279        if self._match(TokenType.AND):
4280            chain = not self._match_text_seq("NO")
4281            self._match_text_seq("CHAIN")
4282
4283        if is_rollback:
4284            return self.expression(exp.Rollback, savepoint=savepoint)
4285
4286        return self.expression(exp.Commit, chain=chain)
4287
4288    def _parse_add_column(self) -> t.Optional[exp.Expression]:
4289        if not self._match_text_seq("ADD"):
4290            return None
4291
4292        self._match(TokenType.COLUMN)
4293        exists_column = self._parse_exists(not_=True)
4294        expression = self._parse_column_def(self._parse_field(any_token=True))
4295
4296        if expression:
4297            expression.set("exists", exists_column)
4298
4299            # https://docs.databricks.com/delta/update-schema.html#explicitly-update-schema-to-add-columns
4300            if self._match_texts(("FIRST", "AFTER")):
4301                position = self._prev.text
4302                column_position = self.expression(
4303                    exp.ColumnPosition, this=self._parse_column(), position=position
4304                )
4305                expression.set("position", column_position)
4306
4307        return expression
4308
4309    def _parse_drop_column(self) -> t.Optional[exp.Drop | exp.Command]:
4310        drop = self._match(TokenType.DROP) and self._parse_drop()
4311        if drop and not isinstance(drop, exp.Command):
4312            drop.set("kind", drop.args.get("kind", "COLUMN"))
4313        return drop
4314
4315    # https://docs.aws.amazon.com/athena/latest/ug/alter-table-drop-partition.html
4316    def _parse_drop_partition(self, exists: t.Optional[bool] = None) -> exp.DropPartition:
4317        return self.expression(
4318            exp.DropPartition, expressions=self._parse_csv(self._parse_partition), exists=exists
4319        )
4320
4321    def _parse_add_constraint(self) -> exp.AddConstraint:
4322        this = None
4323        kind = self._prev.token_type
4324
4325        if kind == TokenType.CONSTRAINT:
4326            this = self._parse_id_var()
4327
4328            if self._match_text_seq("CHECK"):
4329                expression = self._parse_wrapped(self._parse_conjunction)
4330                enforced = self._match_text_seq("ENFORCED")
4331
4332                return self.expression(
4333                    exp.AddConstraint, this=this, expression=expression, enforced=enforced
4334                )
4335
4336        if kind == TokenType.FOREIGN_KEY or self._match(TokenType.FOREIGN_KEY):
4337            expression = self._parse_foreign_key()
4338        elif kind == TokenType.PRIMARY_KEY or self._match(TokenType.PRIMARY_KEY):
4339            expression = self._parse_primary_key()
4340        else:
4341            expression = None
4342
4343        return self.expression(exp.AddConstraint, this=this, expression=expression)
4344
4345    def _parse_alter_table_add(self) -> t.List[t.Optional[exp.Expression]]:
4346        index = self._index - 1
4347
4348        if self._match_set(self.ADD_CONSTRAINT_TOKENS):
4349            return self._parse_csv(self._parse_add_constraint)
4350
4351        self._retreat(index)
4352        return self._parse_csv(self._parse_add_column)
4353
4354    def _parse_alter_table_alter(self) -> exp.AlterColumn:
4355        self._match(TokenType.COLUMN)
4356        column = self._parse_field(any_token=True)
4357
4358        if self._match_pair(TokenType.DROP, TokenType.DEFAULT):
4359            return self.expression(exp.AlterColumn, this=column, drop=True)
4360        if self._match_pair(TokenType.SET, TokenType.DEFAULT):
4361            return self.expression(exp.AlterColumn, this=column, default=self._parse_conjunction())
4362
4363        self._match_text_seq("SET", "DATA")
4364        return self.expression(
4365            exp.AlterColumn,
4366            this=column,
4367            dtype=self._match_text_seq("TYPE") and self._parse_types(),
4368            collate=self._match(TokenType.COLLATE) and self._parse_term(),
4369            using=self._match(TokenType.USING) and self._parse_conjunction(),
4370        )
4371
4372    def _parse_alter_table_drop(self) -> t.List[t.Optional[exp.Expression]]:
4373        index = self._index - 1
4374
4375        partition_exists = self._parse_exists()
4376        if self._match(TokenType.PARTITION, advance=False):
4377            return self._parse_csv(lambda: self._parse_drop_partition(exists=partition_exists))
4378
4379        self._retreat(index)
4380        return self._parse_csv(self._parse_drop_column)
4381
4382    def _parse_alter_table_rename(self) -> exp.RenameTable:
4383        self._match_text_seq("TO")
4384        return self.expression(exp.RenameTable, this=self._parse_table(schema=True))
4385
4386    def _parse_alter(self) -> exp.AlterTable | exp.Command:
4387        start = self._prev
4388
4389        if not self._match(TokenType.TABLE):
4390            return self._parse_as_command(start)
4391
4392        exists = self._parse_exists()
4393        this = self._parse_table(schema=True)
4394
4395        if self._next:
4396            self._advance()
4397        parser = self.ALTER_PARSERS.get(self._prev.text.upper()) if self._prev else None
4398
4399        if parser:
4400            actions = ensure_list(parser(self))
4401
4402            if not self._curr:
4403                return self.expression(
4404                    exp.AlterTable,
4405                    this=this,
4406                    exists=exists,
4407                    actions=actions,
4408                )
4409        return self._parse_as_command(start)
4410
4411    def _parse_merge(self) -> exp.Merge:
4412        self._match(TokenType.INTO)
4413        target = self._parse_table()
4414
4415        self._match(TokenType.USING)
4416        using = self._parse_table()
4417
4418        self._match(TokenType.ON)
4419        on = self._parse_conjunction()
4420
4421        whens = []
4422        while self._match(TokenType.WHEN):
4423            matched = not self._match(TokenType.NOT)
4424            self._match_text_seq("MATCHED")
4425            source = (
4426                False
4427                if self._match_text_seq("BY", "TARGET")
4428                else self._match_text_seq("BY", "SOURCE")
4429            )
4430            condition = self._parse_conjunction() if self._match(TokenType.AND) else None
4431
4432            self._match(TokenType.THEN)
4433
4434            if self._match(TokenType.INSERT):
4435                _this = self._parse_star()
4436                if _this:
4437                    then: t.Optional[exp.Expression] = self.expression(exp.Insert, this=_this)
4438                else:
4439                    then = self.expression(
4440                        exp.Insert,
4441                        this=self._parse_value(),
4442                        expression=self._match(TokenType.VALUES) and self._parse_value(),
4443                    )
4444            elif self._match(TokenType.UPDATE):
4445                expressions = self._parse_star()
4446                if expressions:
4447                    then = self.expression(exp.Update, expressions=expressions)
4448                else:
4449                    then = self.expression(
4450                        exp.Update,
4451                        expressions=self._match(TokenType.SET)
4452                        and self._parse_csv(self._parse_equality),
4453                    )
4454            elif self._match(TokenType.DELETE):
4455                then = self.expression(exp.Var, this=self._prev.text)
4456            else:
4457                then = None
4458
4459            whens.append(
4460                self.expression(
4461                    exp.When,
4462                    matched=matched,
4463                    source=source,
4464                    condition=condition,
4465                    then=then,
4466                )
4467            )
4468
4469        return self.expression(
4470            exp.Merge,
4471            this=target,
4472            using=using,
4473            on=on,
4474            expressions=whens,
4475        )
4476
4477    def _parse_show(self) -> t.Optional[exp.Expression]:
4478        parser = self._find_parser(self.SHOW_PARSERS, self.SHOW_TRIE)
4479        if parser:
4480            return parser(self)
4481        self._advance()
4482        return self.expression(exp.Show, this=self._prev.text.upper())
4483
4484    def _parse_set_item_assignment(
4485        self, kind: t.Optional[str] = None
4486    ) -> t.Optional[exp.Expression]:
4487        index = self._index
4488
4489        if kind in {"GLOBAL", "SESSION"} and self._match_text_seq("TRANSACTION"):
4490            return self._parse_set_transaction(global_=kind == "GLOBAL")
4491
4492        left = self._parse_primary() or self._parse_id_var()
4493
4494        if not self._match_texts(("=", "TO")):
4495            self._retreat(index)
4496            return None
4497
4498        right = self._parse_statement() or self._parse_id_var()
4499        this = self.expression(exp.EQ, this=left, expression=right)
4500
4501        return self.expression(exp.SetItem, this=this, kind=kind)
4502
4503    def _parse_set_transaction(self, global_: bool = False) -> exp.Expression:
4504        self._match_text_seq("TRANSACTION")
4505        characteristics = self._parse_csv(
4506            lambda: self._parse_var_from_options(self.TRANSACTION_CHARACTERISTICS)
4507        )
4508        return self.expression(
4509            exp.SetItem,
4510            expressions=characteristics,
4511            kind="TRANSACTION",
4512            **{"global": global_},  # type: ignore
4513        )
4514
4515    def _parse_set_item(self) -> t.Optional[exp.Expression]:
4516        parser = self._find_parser(self.SET_PARSERS, self.SET_TRIE)
4517        return parser(self) if parser else self._parse_set_item_assignment(kind=None)
4518
4519    def _parse_set(self) -> exp.Set | exp.Command:
4520        index = self._index
4521        set_ = self.expression(exp.Set, expressions=self._parse_csv(self._parse_set_item))
4522
4523        if self._curr:
4524            self._retreat(index)
4525            return self._parse_as_command(self._prev)
4526
4527        return set_
4528
4529    def _parse_var_from_options(self, options: t.Collection[str]) -> t.Optional[exp.Var]:
4530        for option in options:
4531            if self._match_text_seq(*option.split(" ")):
4532                return exp.var(option)
4533        return None
4534
4535    def _parse_as_command(self, start: Token) -> exp.Command:
4536        while self._curr:
4537            self._advance()
4538        text = self._find_sql(start, self._prev)
4539        size = len(start.text)
4540        return exp.Command(this=text[:size], expression=text[size:])
4541
4542    def _parse_dict_property(self, this: str) -> exp.DictProperty:
4543        settings = []
4544
4545        self._match_l_paren()
4546        kind = self._parse_id_var()
4547
4548        if self._match(TokenType.L_PAREN):
4549            while True:
4550                key = self._parse_id_var()
4551                value = self._parse_primary()
4552
4553                if not key and value is None:
4554                    break
4555                settings.append(self.expression(exp.DictSubProperty, this=key, value=value))
4556            self._match(TokenType.R_PAREN)
4557
4558        self._match_r_paren()
4559
4560        return self.expression(
4561            exp.DictProperty,
4562            this=this,
4563            kind=kind.this if kind else None,
4564            settings=settings,
4565        )
4566
4567    def _parse_dict_range(self, this: str) -> exp.DictRange:
4568        self._match_l_paren()
4569        has_min = self._match_text_seq("MIN")
4570        if has_min:
4571            min = self._parse_var() or self._parse_primary()
4572            self._match_text_seq("MAX")
4573            max = self._parse_var() or self._parse_primary()
4574        else:
4575            max = self._parse_var() or self._parse_primary()
4576            min = exp.Literal.number(0)
4577        self._match_r_paren()
4578        return self.expression(exp.DictRange, this=this, min=min, max=max)
4579
4580    def _find_parser(
4581        self, parsers: t.Dict[str, t.Callable], trie: t.Dict
4582    ) -> t.Optional[t.Callable]:
4583        if not self._curr:
4584            return None
4585
4586        index = self._index
4587        this = []
4588        while True:
4589            # The current token might be multiple words
4590            curr = self._curr.text.upper()
4591            key = curr.split(" ")
4592            this.append(curr)
4593
4594            self._advance()
4595            result, trie = in_trie(trie, key)
4596            if result == TrieResult.FAILED:
4597                break
4598
4599            if result == TrieResult.EXISTS:
4600                subparser = parsers[" ".join(this)]
4601                return subparser
4602
4603        self._retreat(index)
4604        return None
4605
4606    def _match(self, token_type, advance=True, expression=None):
4607        if not self._curr:
4608            return None
4609
4610        if self._curr.token_type == token_type:
4611            if advance:
4612                self._advance()
4613            self._add_comments(expression)
4614            return True
4615
4616        return None
4617
4618    def _match_set(self, types, advance=True):
4619        if not self._curr:
4620            return None
4621
4622        if self._curr.token_type in types:
4623            if advance:
4624                self._advance()
4625            return True
4626
4627        return None
4628
4629    def _match_pair(self, token_type_a, token_type_b, advance=True):
4630        if not self._curr or not self._next:
4631            return None
4632
4633        if self._curr.token_type == token_type_a and self._next.token_type == token_type_b:
4634            if advance:
4635                self._advance(2)
4636            return True
4637
4638        return None
4639
4640    def _match_l_paren(self, expression: t.Optional[exp.Expression] = None) -> None:
4641        if not self._match(TokenType.L_PAREN, expression=expression):
4642            self.raise_error("Expecting (")
4643
4644    def _match_r_paren(self, expression: t.Optional[exp.Expression] = None) -> None:
4645        if not self._match(TokenType.R_PAREN, expression=expression):
4646            self.raise_error("Expecting )")
4647
4648    def _match_texts(self, texts, advance=True):
4649        if self._curr and self._curr.text.upper() in texts:
4650            if advance:
4651                self._advance()
4652            return True
4653        return False
4654
4655    def _match_text_seq(self, *texts, advance=True):
4656        index = self._index
4657        for text in texts:
4658            if self._curr and self._curr.text.upper() == text:
4659                self._advance()
4660            else:
4661                self._retreat(index)
4662                return False
4663
4664        if not advance:
4665            self._retreat(index)
4666
4667        return True
4668
4669    @t.overload
4670    def _replace_columns_with_dots(self, this: exp.Expression) -> exp.Expression:
4671        ...
4672
4673    @t.overload
4674    def _replace_columns_with_dots(
4675        self, this: t.Optional[exp.Expression]
4676    ) -> t.Optional[exp.Expression]:
4677        ...
4678
4679    def _replace_columns_with_dots(self, this):
4680        if isinstance(this, exp.Dot):
4681            exp.replace_children(this, self._replace_columns_with_dots)
4682        elif isinstance(this, exp.Column):
4683            exp.replace_children(this, self._replace_columns_with_dots)
4684            table = this.args.get("table")
4685            this = (
4686                self.expression(exp.Dot, this=table, expression=this.this)
4687                if table
4688                else self.expression(exp.Var, this=this.name)
4689            )
4690        elif isinstance(this, exp.Identifier):
4691            this = self.expression(exp.Var, this=this.name)
4692
4693        return this
4694
4695    def _replace_lambda(
4696        self, node: t.Optional[exp.Expression], lambda_variables: t.Set[str]
4697    ) -> t.Optional[exp.Expression]:
4698        if not node:
4699            return node
4700
4701        for column in node.find_all(exp.Column):
4702            if column.parts[0].name in lambda_variables:
4703                dot_or_id = column.to_dot() if column.table else column.this
4704                parent = column.parent
4705
4706                while isinstance(parent, exp.Dot):
4707                    if not isinstance(parent.parent, exp.Dot):
4708                        parent.replace(dot_or_id)
4709                        break
4710                    parent = parent.parent
4711                else:
4712                    if column is node:
4713                        node = dot_or_id
4714                    else:
4715                        column.replace(dot_or_id)
4716        return node
logger = <Logger sqlglot (WARNING)>
def parse_var_map(args: List) -> sqlglot.expressions.StarMap | sqlglot.expressions.VarMap:
21def parse_var_map(args: t.List) -> exp.StarMap | exp.VarMap:
22    if len(args) == 1 and args[0].is_star:
23        return exp.StarMap(this=args[0])
24
25    keys = []
26    values = []
27    for i in range(0, len(args), 2):
28        keys.append(args[i])
29        values.append(args[i + 1])
30
31    return exp.VarMap(
32        keys=exp.Array(expressions=keys),
33        values=exp.Array(expressions=values),
34    )
def parse_like(args: List) -> sqlglot.expressions.Escape | sqlglot.expressions.Like:
37def parse_like(args: t.List) -> exp.Escape | exp.Like:
38    like = exp.Like(this=seq_get(args, 1), expression=seq_get(args, 0))
39    return exp.Escape(this=like, expression=seq_get(args, 2)) if len(args) > 2 else like
def binary_range_parser( expr_type: Type[sqlglot.expressions.Expression]) -> Callable[[sqlglot.parser.Parser, Optional[sqlglot.expressions.Expression]], Optional[sqlglot.expressions.Expression]]:
42def binary_range_parser(
43    expr_type: t.Type[exp.Expression],
44) -> t.Callable[[Parser, t.Optional[exp.Expression]], t.Optional[exp.Expression]]:
45    return lambda self, this: self._parse_escape(
46        self.expression(expr_type, this=this, expression=self._parse_bitwise())
47    )
class Parser:
  60class Parser(metaclass=_Parser):
  61    """
  62    Parser consumes a list of tokens produced by the Tokenizer and produces a parsed syntax tree.
  63
  64    Args:
  65        error_level: The desired error level.
  66            Default: ErrorLevel.IMMEDIATE
  67        error_message_context: Determines the amount of context to capture from a
  68            query string when displaying the error message (in number of characters).
  69            Default: 100
  70        max_errors: Maximum number of error messages to include in a raised ParseError.
  71            This is only relevant if error_level is ErrorLevel.RAISE.
  72            Default: 3
  73    """
  74
  75    FUNCTIONS: t.Dict[str, t.Callable] = {
  76        **{name: f.from_arg_list for f in exp.ALL_FUNCTIONS for name in f.sql_names()},
  77        "DATE_TO_DATE_STR": lambda args: exp.Cast(
  78            this=seq_get(args, 0),
  79            to=exp.DataType(this=exp.DataType.Type.TEXT),
  80        ),
  81        "GLOB": lambda args: exp.Glob(this=seq_get(args, 1), expression=seq_get(args, 0)),
  82        "LIKE": parse_like,
  83        "TIME_TO_TIME_STR": lambda args: exp.Cast(
  84            this=seq_get(args, 0),
  85            to=exp.DataType(this=exp.DataType.Type.TEXT),
  86        ),
  87        "TS_OR_DS_TO_DATE_STR": lambda args: exp.Substring(
  88            this=exp.Cast(
  89                this=seq_get(args, 0),
  90                to=exp.DataType(this=exp.DataType.Type.TEXT),
  91            ),
  92            start=exp.Literal.number(1),
  93            length=exp.Literal.number(10),
  94        ),
  95        "VAR_MAP": parse_var_map,
  96    }
  97
  98    NO_PAREN_FUNCTIONS = {
  99        TokenType.CURRENT_DATE: exp.CurrentDate,
 100        TokenType.CURRENT_DATETIME: exp.CurrentDate,
 101        TokenType.CURRENT_TIME: exp.CurrentTime,
 102        TokenType.CURRENT_TIMESTAMP: exp.CurrentTimestamp,
 103        TokenType.CURRENT_USER: exp.CurrentUser,
 104    }
 105
 106    NESTED_TYPE_TOKENS = {
 107        TokenType.ARRAY,
 108        TokenType.MAP,
 109        TokenType.NULLABLE,
 110        TokenType.STRUCT,
 111    }
 112
 113    ENUM_TYPE_TOKENS = {
 114        TokenType.ENUM,
 115    }
 116
 117    TYPE_TOKENS = {
 118        TokenType.BIT,
 119        TokenType.BOOLEAN,
 120        TokenType.TINYINT,
 121        TokenType.UTINYINT,
 122        TokenType.SMALLINT,
 123        TokenType.USMALLINT,
 124        TokenType.INT,
 125        TokenType.UINT,
 126        TokenType.BIGINT,
 127        TokenType.UBIGINT,
 128        TokenType.INT128,
 129        TokenType.UINT128,
 130        TokenType.INT256,
 131        TokenType.UINT256,
 132        TokenType.FLOAT,
 133        TokenType.DOUBLE,
 134        TokenType.CHAR,
 135        TokenType.NCHAR,
 136        TokenType.VARCHAR,
 137        TokenType.NVARCHAR,
 138        TokenType.TEXT,
 139        TokenType.MEDIUMTEXT,
 140        TokenType.LONGTEXT,
 141        TokenType.MEDIUMBLOB,
 142        TokenType.LONGBLOB,
 143        TokenType.BINARY,
 144        TokenType.VARBINARY,
 145        TokenType.JSON,
 146        TokenType.JSONB,
 147        TokenType.INTERVAL,
 148        TokenType.TIME,
 149        TokenType.TIMESTAMP,
 150        TokenType.TIMESTAMPTZ,
 151        TokenType.TIMESTAMPLTZ,
 152        TokenType.DATETIME,
 153        TokenType.DATETIME64,
 154        TokenType.DATE,
 155        TokenType.INT4RANGE,
 156        TokenType.INT4MULTIRANGE,
 157        TokenType.INT8RANGE,
 158        TokenType.INT8MULTIRANGE,
 159        TokenType.NUMRANGE,
 160        TokenType.NUMMULTIRANGE,
 161        TokenType.TSRANGE,
 162        TokenType.TSMULTIRANGE,
 163        TokenType.TSTZRANGE,
 164        TokenType.TSTZMULTIRANGE,
 165        TokenType.DATERANGE,
 166        TokenType.DATEMULTIRANGE,
 167        TokenType.DECIMAL,
 168        TokenType.BIGDECIMAL,
 169        TokenType.UUID,
 170        TokenType.GEOGRAPHY,
 171        TokenType.GEOMETRY,
 172        TokenType.HLLSKETCH,
 173        TokenType.HSTORE,
 174        TokenType.PSEUDO_TYPE,
 175        TokenType.SUPER,
 176        TokenType.SERIAL,
 177        TokenType.SMALLSERIAL,
 178        TokenType.BIGSERIAL,
 179        TokenType.XML,
 180        TokenType.UNIQUEIDENTIFIER,
 181        TokenType.USERDEFINED,
 182        TokenType.MONEY,
 183        TokenType.SMALLMONEY,
 184        TokenType.ROWVERSION,
 185        TokenType.IMAGE,
 186        TokenType.VARIANT,
 187        TokenType.OBJECT,
 188        TokenType.INET,
 189        TokenType.ENUM,
 190        *NESTED_TYPE_TOKENS,
 191    }
 192
 193    SUBQUERY_PREDICATES = {
 194        TokenType.ANY: exp.Any,
 195        TokenType.ALL: exp.All,
 196        TokenType.EXISTS: exp.Exists,
 197        TokenType.SOME: exp.Any,
 198    }
 199
 200    RESERVED_KEYWORDS = {
 201        *Tokenizer.SINGLE_TOKENS.values(),
 202        TokenType.SELECT,
 203    }
 204
 205    DB_CREATABLES = {
 206        TokenType.DATABASE,
 207        TokenType.SCHEMA,
 208        TokenType.TABLE,
 209        TokenType.VIEW,
 210        TokenType.DICTIONARY,
 211    }
 212
 213    CREATABLES = {
 214        TokenType.COLUMN,
 215        TokenType.FUNCTION,
 216        TokenType.INDEX,
 217        TokenType.PROCEDURE,
 218        *DB_CREATABLES,
 219    }
 220
 221    # Tokens that can represent identifiers
 222    ID_VAR_TOKENS = {
 223        TokenType.VAR,
 224        TokenType.ANTI,
 225        TokenType.APPLY,
 226        TokenType.ASC,
 227        TokenType.AUTO_INCREMENT,
 228        TokenType.BEGIN,
 229        TokenType.CACHE,
 230        TokenType.CASE,
 231        TokenType.COLLATE,
 232        TokenType.COMMAND,
 233        TokenType.COMMENT,
 234        TokenType.COMMIT,
 235        TokenType.CONSTRAINT,
 236        TokenType.DEFAULT,
 237        TokenType.DELETE,
 238        TokenType.DESC,
 239        TokenType.DESCRIBE,
 240        TokenType.DICTIONARY,
 241        TokenType.DIV,
 242        TokenType.END,
 243        TokenType.EXECUTE,
 244        TokenType.ESCAPE,
 245        TokenType.FALSE,
 246        TokenType.FIRST,
 247        TokenType.FILTER,
 248        TokenType.FORMAT,
 249        TokenType.FULL,
 250        TokenType.IF,
 251        TokenType.IS,
 252        TokenType.ISNULL,
 253        TokenType.INTERVAL,
 254        TokenType.KEEP,
 255        TokenType.LEFT,
 256        TokenType.LOAD,
 257        TokenType.MERGE,
 258        TokenType.NATURAL,
 259        TokenType.NEXT,
 260        TokenType.OFFSET,
 261        TokenType.ORDINALITY,
 262        TokenType.OVERWRITE,
 263        TokenType.PARTITION,
 264        TokenType.PERCENT,
 265        TokenType.PIVOT,
 266        TokenType.PRAGMA,
 267        TokenType.RANGE,
 268        TokenType.REFERENCES,
 269        TokenType.RIGHT,
 270        TokenType.ROW,
 271        TokenType.ROWS,
 272        TokenType.SEMI,
 273        TokenType.SET,
 274        TokenType.SETTINGS,
 275        TokenType.SHOW,
 276        TokenType.TEMPORARY,
 277        TokenType.TOP,
 278        TokenType.TRUE,
 279        TokenType.UNIQUE,
 280        TokenType.UNPIVOT,
 281        TokenType.UPDATE,
 282        TokenType.VOLATILE,
 283        TokenType.WINDOW,
 284        *CREATABLES,
 285        *SUBQUERY_PREDICATES,
 286        *TYPE_TOKENS,
 287        *NO_PAREN_FUNCTIONS,
 288    }
 289
 290    INTERVAL_VARS = ID_VAR_TOKENS - {TokenType.END}
 291
 292    TABLE_ALIAS_TOKENS = ID_VAR_TOKENS - {
 293        TokenType.APPLY,
 294        TokenType.ASOF,
 295        TokenType.FULL,
 296        TokenType.LEFT,
 297        TokenType.LOCK,
 298        TokenType.NATURAL,
 299        TokenType.OFFSET,
 300        TokenType.RIGHT,
 301        TokenType.WINDOW,
 302    }
 303
 304    COMMENT_TABLE_ALIAS_TOKENS = TABLE_ALIAS_TOKENS - {TokenType.IS}
 305
 306    UPDATE_ALIAS_TOKENS = TABLE_ALIAS_TOKENS - {TokenType.SET}
 307
 308    TRIM_TYPES = {"LEADING", "TRAILING", "BOTH"}
 309
 310    FUNC_TOKENS = {
 311        TokenType.COMMAND,
 312        TokenType.CURRENT_DATE,
 313        TokenType.CURRENT_DATETIME,
 314        TokenType.CURRENT_TIMESTAMP,
 315        TokenType.CURRENT_TIME,
 316        TokenType.CURRENT_USER,
 317        TokenType.FILTER,
 318        TokenType.FIRST,
 319        TokenType.FORMAT,
 320        TokenType.GLOB,
 321        TokenType.IDENTIFIER,
 322        TokenType.INDEX,
 323        TokenType.ISNULL,
 324        TokenType.ILIKE,
 325        TokenType.LIKE,
 326        TokenType.MERGE,
 327        TokenType.OFFSET,
 328        TokenType.PRIMARY_KEY,
 329        TokenType.RANGE,
 330        TokenType.REPLACE,
 331        TokenType.ROW,
 332        TokenType.UNNEST,
 333        TokenType.VAR,
 334        TokenType.LEFT,
 335        TokenType.RIGHT,
 336        TokenType.DATE,
 337        TokenType.DATETIME,
 338        TokenType.TABLE,
 339        TokenType.TIMESTAMP,
 340        TokenType.TIMESTAMPTZ,
 341        TokenType.WINDOW,
 342        *TYPE_TOKENS,
 343        *SUBQUERY_PREDICATES,
 344    }
 345
 346    CONJUNCTION = {
 347        TokenType.AND: exp.And,
 348        TokenType.OR: exp.Or,
 349    }
 350
 351    EQUALITY = {
 352        TokenType.EQ: exp.EQ,
 353        TokenType.NEQ: exp.NEQ,
 354        TokenType.NULLSAFE_EQ: exp.NullSafeEQ,
 355    }
 356
 357    COMPARISON = {
 358        TokenType.GT: exp.GT,
 359        TokenType.GTE: exp.GTE,
 360        TokenType.LT: exp.LT,
 361        TokenType.LTE: exp.LTE,
 362    }
 363
 364    BITWISE = {
 365        TokenType.AMP: exp.BitwiseAnd,
 366        TokenType.CARET: exp.BitwiseXor,
 367        TokenType.PIPE: exp.BitwiseOr,
 368        TokenType.DPIPE: exp.DPipe,
 369    }
 370
 371    TERM = {
 372        TokenType.DASH: exp.Sub,
 373        TokenType.PLUS: exp.Add,
 374        TokenType.MOD: exp.Mod,
 375        TokenType.COLLATE: exp.Collate,
 376    }
 377
 378    FACTOR = {
 379        TokenType.DIV: exp.IntDiv,
 380        TokenType.LR_ARROW: exp.Distance,
 381        TokenType.SLASH: exp.Div,
 382        TokenType.STAR: exp.Mul,
 383    }
 384
 385    TIMESTAMPS = {
 386        TokenType.TIME,
 387        TokenType.TIMESTAMP,
 388        TokenType.TIMESTAMPTZ,
 389        TokenType.TIMESTAMPLTZ,
 390    }
 391
 392    SET_OPERATIONS = {
 393        TokenType.UNION,
 394        TokenType.INTERSECT,
 395        TokenType.EXCEPT,
 396    }
 397
 398    JOIN_METHODS = {
 399        TokenType.NATURAL,
 400        TokenType.ASOF,
 401    }
 402
 403    JOIN_SIDES = {
 404        TokenType.LEFT,
 405        TokenType.RIGHT,
 406        TokenType.FULL,
 407    }
 408
 409    JOIN_KINDS = {
 410        TokenType.INNER,
 411        TokenType.OUTER,
 412        TokenType.CROSS,
 413        TokenType.SEMI,
 414        TokenType.ANTI,
 415    }
 416
 417    JOIN_HINTS: t.Set[str] = set()
 418
 419    LAMBDAS = {
 420        TokenType.ARROW: lambda self, expressions: self.expression(
 421            exp.Lambda,
 422            this=self._replace_lambda(
 423                self._parse_conjunction(),
 424                {node.name for node in expressions},
 425            ),
 426            expressions=expressions,
 427        ),
 428        TokenType.FARROW: lambda self, expressions: self.expression(
 429            exp.Kwarg,
 430            this=exp.var(expressions[0].name),
 431            expression=self._parse_conjunction(),
 432        ),
 433    }
 434
 435    COLUMN_OPERATORS = {
 436        TokenType.DOT: None,
 437        TokenType.DCOLON: lambda self, this, to: self.expression(
 438            exp.Cast if self.STRICT_CAST else exp.TryCast,
 439            this=this,
 440            to=to,
 441        ),
 442        TokenType.ARROW: lambda self, this, path: self.expression(
 443            exp.JSONExtract,
 444            this=this,
 445            expression=path,
 446        ),
 447        TokenType.DARROW: lambda self, this, path: self.expression(
 448            exp.JSONExtractScalar,
 449            this=this,
 450            expression=path,
 451        ),
 452        TokenType.HASH_ARROW: lambda self, this, path: self.expression(
 453            exp.JSONBExtract,
 454            this=this,
 455            expression=path,
 456        ),
 457        TokenType.DHASH_ARROW: lambda self, this, path: self.expression(
 458            exp.JSONBExtractScalar,
 459            this=this,
 460            expression=path,
 461        ),
 462        TokenType.PLACEHOLDER: lambda self, this, key: self.expression(
 463            exp.JSONBContains,
 464            this=this,
 465            expression=key,
 466        ),
 467    }
 468
 469    EXPRESSION_PARSERS = {
 470        exp.Cluster: lambda self: self._parse_sort(exp.Cluster, TokenType.CLUSTER_BY),
 471        exp.Column: lambda self: self._parse_column(),
 472        exp.Condition: lambda self: self._parse_conjunction(),
 473        exp.DataType: lambda self: self._parse_types(),
 474        exp.Expression: lambda self: self._parse_statement(),
 475        exp.From: lambda self: self._parse_from(),
 476        exp.Group: lambda self: self._parse_group(),
 477        exp.Having: lambda self: self._parse_having(),
 478        exp.Identifier: lambda self: self._parse_id_var(),
 479        exp.Join: lambda self: self._parse_join(),
 480        exp.Lambda: lambda self: self._parse_lambda(),
 481        exp.Lateral: lambda self: self._parse_lateral(),
 482        exp.Limit: lambda self: self._parse_limit(),
 483        exp.Offset: lambda self: self._parse_offset(),
 484        exp.Order: lambda self: self._parse_order(),
 485        exp.Ordered: lambda self: self._parse_ordered(),
 486        exp.Properties: lambda self: self._parse_properties(),
 487        exp.Qualify: lambda self: self._parse_qualify(),
 488        exp.Returning: lambda self: self._parse_returning(),
 489        exp.Sort: lambda self: self._parse_sort(exp.Sort, TokenType.SORT_BY),
 490        exp.Table: lambda self: self._parse_table_parts(),
 491        exp.TableAlias: lambda self: self._parse_table_alias(),
 492        exp.Where: lambda self: self._parse_where(),
 493        exp.Window: lambda self: self._parse_named_window(),
 494        exp.With: lambda self: self._parse_with(),
 495        "JOIN_TYPE": lambda self: self._parse_join_parts(),
 496    }
 497
 498    STATEMENT_PARSERS = {
 499        TokenType.ALTER: lambda self: self._parse_alter(),
 500        TokenType.BEGIN: lambda self: self._parse_transaction(),
 501        TokenType.CACHE: lambda self: self._parse_cache(),
 502        TokenType.COMMIT: lambda self: self._parse_commit_or_rollback(),
 503        TokenType.COMMENT: lambda self: self._parse_comment(),
 504        TokenType.CREATE: lambda self: self._parse_create(),
 505        TokenType.DELETE: lambda self: self._parse_delete(),
 506        TokenType.DESC: lambda self: self._parse_describe(),
 507        TokenType.DESCRIBE: lambda self: self._parse_describe(),
 508        TokenType.DROP: lambda self: self._parse_drop(),
 509        TokenType.END: lambda self: self._parse_commit_or_rollback(),
 510        TokenType.FROM: lambda self: exp.select("*").from_(
 511            t.cast(exp.From, self._parse_from(skip_from_token=True))
 512        ),
 513        TokenType.INSERT: lambda self: self._parse_insert(),
 514        TokenType.LOAD: lambda self: self._parse_load(),
 515        TokenType.MERGE: lambda self: self._parse_merge(),
 516        TokenType.PIVOT: lambda self: self._parse_simplified_pivot(),
 517        TokenType.PRAGMA: lambda self: self.expression(exp.Pragma, this=self._parse_expression()),
 518        TokenType.ROLLBACK: lambda self: self._parse_commit_or_rollback(),
 519        TokenType.SET: lambda self: self._parse_set(),
 520        TokenType.UNCACHE: lambda self: self._parse_uncache(),
 521        TokenType.UPDATE: lambda self: self._parse_update(),
 522        TokenType.USE: lambda self: self.expression(
 523            exp.Use,
 524            kind=self._match_texts(("ROLE", "WAREHOUSE", "DATABASE", "SCHEMA"))
 525            and exp.var(self._prev.text),
 526            this=self._parse_table(schema=False),
 527        ),
 528    }
 529
 530    UNARY_PARSERS = {
 531        TokenType.PLUS: lambda self: self._parse_unary(),  # Unary + is handled as a no-op
 532        TokenType.NOT: lambda self: self.expression(exp.Not, this=self._parse_equality()),
 533        TokenType.TILDA: lambda self: self.expression(exp.BitwiseNot, this=self._parse_unary()),
 534        TokenType.DASH: lambda self: self.expression(exp.Neg, this=self._parse_unary()),
 535    }
 536
 537    PRIMARY_PARSERS = {
 538        TokenType.STRING: lambda self, token: self.expression(
 539            exp.Literal, this=token.text, is_string=True
 540        ),
 541        TokenType.NUMBER: lambda self, token: self.expression(
 542            exp.Literal, this=token.text, is_string=False
 543        ),
 544        TokenType.STAR: lambda self, _: self.expression(
 545            exp.Star, **{"except": self._parse_except(), "replace": self._parse_replace()}
 546        ),
 547        TokenType.NULL: lambda self, _: self.expression(exp.Null),
 548        TokenType.TRUE: lambda self, _: self.expression(exp.Boolean, this=True),
 549        TokenType.FALSE: lambda self, _: self.expression(exp.Boolean, this=False),
 550        TokenType.BIT_STRING: lambda self, token: self.expression(exp.BitString, this=token.text),
 551        TokenType.HEX_STRING: lambda self, token: self.expression(exp.HexString, this=token.text),
 552        TokenType.BYTE_STRING: lambda self, token: self.expression(exp.ByteString, this=token.text),
 553        TokenType.INTRODUCER: lambda self, token: self._parse_introducer(token),
 554        TokenType.NATIONAL_STRING: lambda self, token: self.expression(
 555            exp.National, this=token.text
 556        ),
 557        TokenType.RAW_STRING: lambda self, token: self.expression(exp.RawString, this=token.text),
 558        TokenType.SESSION_PARAMETER: lambda self, _: self._parse_session_parameter(),
 559    }
 560
 561    PLACEHOLDER_PARSERS = {
 562        TokenType.PLACEHOLDER: lambda self: self.expression(exp.Placeholder),
 563        TokenType.PARAMETER: lambda self: self._parse_parameter(),
 564        TokenType.COLON: lambda self: self.expression(exp.Placeholder, this=self._prev.text)
 565        if self._match_set((TokenType.NUMBER, TokenType.VAR))
 566        else None,
 567    }
 568
 569    RANGE_PARSERS = {
 570        TokenType.BETWEEN: lambda self, this: self._parse_between(this),
 571        TokenType.GLOB: binary_range_parser(exp.Glob),
 572        TokenType.ILIKE: binary_range_parser(exp.ILike),
 573        TokenType.IN: lambda self, this: self._parse_in(this),
 574        TokenType.IRLIKE: binary_range_parser(exp.RegexpILike),
 575        TokenType.IS: lambda self, this: self._parse_is(this),
 576        TokenType.LIKE: binary_range_parser(exp.Like),
 577        TokenType.OVERLAPS: binary_range_parser(exp.Overlaps),
 578        TokenType.RLIKE: binary_range_parser(exp.RegexpLike),
 579        TokenType.SIMILAR_TO: binary_range_parser(exp.SimilarTo),
 580    }
 581
 582    PROPERTY_PARSERS: t.Dict[str, t.Callable] = {
 583        "ALGORITHM": lambda self: self._parse_property_assignment(exp.AlgorithmProperty),
 584        "AUTO_INCREMENT": lambda self: self._parse_property_assignment(exp.AutoIncrementProperty),
 585        "BLOCKCOMPRESSION": lambda self: self._parse_blockcompression(),
 586        "CHARACTER SET": lambda self: self._parse_character_set(),
 587        "CHECKSUM": lambda self: self._parse_checksum(),
 588        "CLUSTER BY": lambda self: self._parse_cluster(),
 589        "COLLATE": lambda self: self._parse_property_assignment(exp.CollateProperty),
 590        "COMMENT": lambda self: self._parse_property_assignment(exp.SchemaCommentProperty),
 591        "COPY": lambda self: self._parse_copy_property(),
 592        "DATABLOCKSIZE": lambda self, **kwargs: self._parse_datablocksize(**kwargs),
 593        "DEFINER": lambda self: self._parse_definer(),
 594        "DETERMINISTIC": lambda self: self.expression(
 595            exp.StabilityProperty, this=exp.Literal.string("IMMUTABLE")
 596        ),
 597        "DISTKEY": lambda self: self._parse_distkey(),
 598        "DISTSTYLE": lambda self: self._parse_property_assignment(exp.DistStyleProperty),
 599        "ENGINE": lambda self: self._parse_property_assignment(exp.EngineProperty),
 600        "EXECUTE": lambda self: self._parse_property_assignment(exp.ExecuteAsProperty),
 601        "EXTERNAL": lambda self: self.expression(exp.ExternalProperty),
 602        "FALLBACK": lambda self, **kwargs: self._parse_fallback(**kwargs),
 603        "FORMAT": lambda self: self._parse_property_assignment(exp.FileFormatProperty),
 604        "FREESPACE": lambda self: self._parse_freespace(),
 605        "IMMUTABLE": lambda self: self.expression(
 606            exp.StabilityProperty, this=exp.Literal.string("IMMUTABLE")
 607        ),
 608        "JOURNAL": lambda self, **kwargs: self._parse_journal(**kwargs),
 609        "LANGUAGE": lambda self: self._parse_property_assignment(exp.LanguageProperty),
 610        "LAYOUT": lambda self: self._parse_dict_property(this="LAYOUT"),
 611        "LIFETIME": lambda self: self._parse_dict_range(this="LIFETIME"),
 612        "LIKE": lambda self: self._parse_create_like(),
 613        "LOCATION": lambda self: self._parse_property_assignment(exp.LocationProperty),
 614        "LOCK": lambda self: self._parse_locking(),
 615        "LOCKING": lambda self: self._parse_locking(),
 616        "LOG": lambda self, **kwargs: self._parse_log(**kwargs),
 617        "MATERIALIZED": lambda self: self.expression(exp.MaterializedProperty),
 618        "MERGEBLOCKRATIO": lambda self, **kwargs: self._parse_mergeblockratio(**kwargs),
 619        "MULTISET": lambda self: self.expression(exp.SetProperty, multi=True),
 620        "NO": lambda self: self._parse_no_property(),
 621        "ON": lambda self: self._parse_on_property(),
 622        "ORDER BY": lambda self: self._parse_order(skip_order_token=True),
 623        "PARTITION BY": lambda self: self._parse_partitioned_by(),
 624        "PARTITIONED BY": lambda self: self._parse_partitioned_by(),
 625        "PARTITIONED_BY": lambda self: self._parse_partitioned_by(),
 626        "PRIMARY KEY": lambda self: self._parse_primary_key(in_props=True),
 627        "RANGE": lambda self: self._parse_dict_range(this="RANGE"),
 628        "RETURNS": lambda self: self._parse_returns(),
 629        "ROW": lambda self: self._parse_row(),
 630        "ROW_FORMAT": lambda self: self._parse_property_assignment(exp.RowFormatProperty),
 631        "SET": lambda self: self.expression(exp.SetProperty, multi=False),
 632        "SETTINGS": lambda self: self.expression(
 633            exp.SettingsProperty, expressions=self._parse_csv(self._parse_set_item)
 634        ),
 635        "SORTKEY": lambda self: self._parse_sortkey(),
 636        "SOURCE": lambda self: self._parse_dict_property(this="SOURCE"),
 637        "STABLE": lambda self: self.expression(
 638            exp.StabilityProperty, this=exp.Literal.string("STABLE")
 639        ),
 640        "STORED": lambda self: self._parse_stored(),
 641        "TBLPROPERTIES": lambda self: self._parse_wrapped_csv(self._parse_property),
 642        "TEMP": lambda self: self.expression(exp.TemporaryProperty),
 643        "TEMPORARY": lambda self: self.expression(exp.TemporaryProperty),
 644        "TO": lambda self: self._parse_to_table(),
 645        "TRANSIENT": lambda self: self.expression(exp.TransientProperty),
 646        "TTL": lambda self: self._parse_ttl(),
 647        "USING": lambda self: self._parse_property_assignment(exp.FileFormatProperty),
 648        "VOLATILE": lambda self: self._parse_volatile_property(),
 649        "WITH": lambda self: self._parse_with_property(),
 650    }
 651
 652    CONSTRAINT_PARSERS = {
 653        "AUTOINCREMENT": lambda self: self._parse_auto_increment(),
 654        "AUTO_INCREMENT": lambda self: self._parse_auto_increment(),
 655        "CASESPECIFIC": lambda self: self.expression(exp.CaseSpecificColumnConstraint, not_=False),
 656        "CHARACTER SET": lambda self: self.expression(
 657            exp.CharacterSetColumnConstraint, this=self._parse_var_or_string()
 658        ),
 659        "CHECK": lambda self: self.expression(
 660            exp.CheckColumnConstraint, this=self._parse_wrapped(self._parse_conjunction)
 661        ),
 662        "COLLATE": lambda self: self.expression(
 663            exp.CollateColumnConstraint, this=self._parse_var()
 664        ),
 665        "COMMENT": lambda self: self.expression(
 666            exp.CommentColumnConstraint, this=self._parse_string()
 667        ),
 668        "COMPRESS": lambda self: self._parse_compress(),
 669        "DEFAULT": lambda self: self.expression(
 670            exp.DefaultColumnConstraint, this=self._parse_bitwise()
 671        ),
 672        "ENCODE": lambda self: self.expression(exp.EncodeColumnConstraint, this=self._parse_var()),
 673        "FOREIGN KEY": lambda self: self._parse_foreign_key(),
 674        "FORMAT": lambda self: self.expression(
 675            exp.DateFormatColumnConstraint, this=self._parse_var_or_string()
 676        ),
 677        "GENERATED": lambda self: self._parse_generated_as_identity(),
 678        "IDENTITY": lambda self: self._parse_auto_increment(),
 679        "INLINE": lambda self: self._parse_inline(),
 680        "LIKE": lambda self: self._parse_create_like(),
 681        "NOT": lambda self: self._parse_not_constraint(),
 682        "NULL": lambda self: self.expression(exp.NotNullColumnConstraint, allow_null=True),
 683        "ON": lambda self: self._match(TokenType.UPDATE)
 684        and self.expression(exp.OnUpdateColumnConstraint, this=self._parse_function()),
 685        "PATH": lambda self: self.expression(exp.PathColumnConstraint, this=self._parse_string()),
 686        "PRIMARY KEY": lambda self: self._parse_primary_key(),
 687        "REFERENCES": lambda self: self._parse_references(match=False),
 688        "TITLE": lambda self: self.expression(
 689            exp.TitleColumnConstraint, this=self._parse_var_or_string()
 690        ),
 691        "TTL": lambda self: self.expression(exp.MergeTreeTTL, expressions=[self._parse_bitwise()]),
 692        "UNIQUE": lambda self: self._parse_unique(),
 693        "UPPERCASE": lambda self: self.expression(exp.UppercaseColumnConstraint),
 694    }
 695
 696    ALTER_PARSERS = {
 697        "ADD": lambda self: self._parse_alter_table_add(),
 698        "ALTER": lambda self: self._parse_alter_table_alter(),
 699        "DELETE": lambda self: self.expression(exp.Delete, where=self._parse_where()),
 700        "DROP": lambda self: self._parse_alter_table_drop(),
 701        "RENAME": lambda self: self._parse_alter_table_rename(),
 702    }
 703
 704    SCHEMA_UNNAMED_CONSTRAINTS = {"CHECK", "FOREIGN KEY", "LIKE", "PRIMARY KEY", "UNIQUE"}
 705
 706    NO_PAREN_FUNCTION_PARSERS = {
 707        TokenType.ANY: lambda self: self.expression(exp.Any, this=self._parse_bitwise()),
 708        TokenType.CASE: lambda self: self._parse_case(),
 709        TokenType.IF: lambda self: self._parse_if(),
 710        TokenType.NEXT_VALUE_FOR: lambda self: self.expression(
 711            exp.NextValueFor,
 712            this=self._parse_column(),
 713            order=self._match(TokenType.OVER) and self._parse_wrapped(self._parse_order),
 714        ),
 715    }
 716
 717    FUNCTIONS_WITH_ALIASED_ARGS = {"STRUCT"}
 718
 719    FUNCTION_PARSERS: t.Dict[str, t.Callable] = {
 720        "CAST": lambda self: self._parse_cast(self.STRICT_CAST),
 721        "CONCAT": lambda self: self._parse_concat(),
 722        "CONVERT": lambda self: self._parse_convert(self.STRICT_CAST),
 723        "DECODE": lambda self: self._parse_decode(),
 724        "EXTRACT": lambda self: self._parse_extract(),
 725        "JSON_OBJECT": lambda self: self._parse_json_object(),
 726        "LOG": lambda self: self._parse_logarithm(),
 727        "MATCH": lambda self: self._parse_match_against(),
 728        "OPENJSON": lambda self: self._parse_open_json(),
 729        "POSITION": lambda self: self._parse_position(),
 730        "SAFE_CAST": lambda self: self._parse_cast(False),
 731        "STRING_AGG": lambda self: self._parse_string_agg(),
 732        "SUBSTRING": lambda self: self._parse_substring(),
 733        "TRIM": lambda self: self._parse_trim(),
 734        "TRY_CAST": lambda self: self._parse_cast(False),
 735        "TRY_CONVERT": lambda self: self._parse_convert(False),
 736    }
 737
 738    QUERY_MODIFIER_PARSERS = {
 739        "joins": lambda self: list(iter(self._parse_join, None)),
 740        "laterals": lambda self: list(iter(self._parse_lateral, None)),
 741        "match": lambda self: self._parse_match_recognize(),
 742        "where": lambda self: self._parse_where(),
 743        "group": lambda self: self._parse_group(),
 744        "having": lambda self: self._parse_having(),
 745        "qualify": lambda self: self._parse_qualify(),
 746        "windows": lambda self: self._parse_window_clause(),
 747        "order": lambda self: self._parse_order(),
 748        "limit": lambda self: self._parse_limit(),
 749        "offset": lambda self: self._parse_offset(),
 750        "locks": lambda self: self._parse_locks(),
 751        "sample": lambda self: self._parse_table_sample(as_modifier=True),
 752    }
 753
 754    SET_PARSERS = {
 755        "GLOBAL": lambda self: self._parse_set_item_assignment("GLOBAL"),
 756        "LOCAL": lambda self: self._parse_set_item_assignment("LOCAL"),
 757        "SESSION": lambda self: self._parse_set_item_assignment("SESSION"),
 758        "TRANSACTION": lambda self: self._parse_set_transaction(),
 759    }
 760
 761    SHOW_PARSERS: t.Dict[str, t.Callable] = {}
 762
 763    TYPE_LITERAL_PARSERS: t.Dict[exp.DataType.Type, t.Callable] = {}
 764
 765    MODIFIABLES = (exp.Subquery, exp.Subqueryable, exp.Table)
 766
 767    DDL_SELECT_TOKENS = {TokenType.SELECT, TokenType.WITH, TokenType.L_PAREN}
 768
 769    PRE_VOLATILE_TOKENS = {TokenType.CREATE, TokenType.REPLACE, TokenType.UNIQUE}
 770
 771    TRANSACTION_KIND = {"DEFERRED", "IMMEDIATE", "EXCLUSIVE"}
 772    TRANSACTION_CHARACTERISTICS = {
 773        "ISOLATION LEVEL REPEATABLE READ",
 774        "ISOLATION LEVEL READ COMMITTED",
 775        "ISOLATION LEVEL READ UNCOMMITTED",
 776        "ISOLATION LEVEL SERIALIZABLE",
 777        "READ WRITE",
 778        "READ ONLY",
 779    }
 780
 781    INSERT_ALTERNATIVES = {"ABORT", "FAIL", "IGNORE", "REPLACE", "ROLLBACK"}
 782
 783    CLONE_KINDS = {"TIMESTAMP", "OFFSET", "STATEMENT"}
 784
 785    TABLE_INDEX_HINT_TOKENS = {TokenType.FORCE, TokenType.IGNORE, TokenType.USE}
 786
 787    WINDOW_ALIAS_TOKENS = ID_VAR_TOKENS - {TokenType.ROWS}
 788    WINDOW_BEFORE_PAREN_TOKENS = {TokenType.OVER}
 789    WINDOW_SIDES = {"FOLLOWING", "PRECEDING"}
 790
 791    ADD_CONSTRAINT_TOKENS = {TokenType.CONSTRAINT, TokenType.PRIMARY_KEY, TokenType.FOREIGN_KEY}
 792
 793    STRICT_CAST = True
 794
 795    # A NULL arg in CONCAT yields NULL by default
 796    CONCAT_NULL_OUTPUTS_STRING = False
 797
 798    CONVERT_TYPE_FIRST = False
 799
 800    PREFIXED_PIVOT_COLUMNS = False
 801    IDENTIFY_PIVOT_STRINGS = False
 802
 803    LOG_BASE_FIRST = True
 804    LOG_DEFAULTS_TO_LN = False
 805
 806    __slots__ = (
 807        "error_level",
 808        "error_message_context",
 809        "max_errors",
 810        "sql",
 811        "errors",
 812        "_tokens",
 813        "_index",
 814        "_curr",
 815        "_next",
 816        "_prev",
 817        "_prev_comments",
 818    )
 819
 820    # Autofilled
 821    INDEX_OFFSET: int = 0
 822    UNNEST_COLUMN_ONLY: bool = False
 823    ALIAS_POST_TABLESAMPLE: bool = False
 824    STRICT_STRING_CONCAT = False
 825    NULL_ORDERING: str = "nulls_are_small"
 826    SHOW_TRIE: t.Dict = {}
 827    SET_TRIE: t.Dict = {}
 828    FORMAT_MAPPING: t.Dict[str, str] = {}
 829    FORMAT_TRIE: t.Dict = {}
 830    TIME_MAPPING: t.Dict[str, str] = {}
 831    TIME_TRIE: t.Dict = {}
 832
 833    def __init__(
 834        self,
 835        error_level: t.Optional[ErrorLevel] = None,
 836        error_message_context: int = 100,
 837        max_errors: int = 3,
 838    ):
 839        self.error_level = error_level or ErrorLevel.IMMEDIATE
 840        self.error_message_context = error_message_context
 841        self.max_errors = max_errors
 842        self.reset()
 843
 844    def reset(self):
 845        self.sql = ""
 846        self.errors = []
 847        self._tokens = []
 848        self._index = 0
 849        self._curr = None
 850        self._next = None
 851        self._prev = None
 852        self._prev_comments = None
 853
 854    def parse(
 855        self, raw_tokens: t.List[Token], sql: t.Optional[str] = None
 856    ) -> t.List[t.Optional[exp.Expression]]:
 857        """
 858        Parses a list of tokens and returns a list of syntax trees, one tree
 859        per parsed SQL statement.
 860
 861        Args:
 862            raw_tokens: The list of tokens.
 863            sql: The original SQL string, used to produce helpful debug messages.
 864
 865        Returns:
 866            The list of the produced syntax trees.
 867        """
 868        return self._parse(
 869            parse_method=self.__class__._parse_statement, raw_tokens=raw_tokens, sql=sql
 870        )
 871
 872    def parse_into(
 873        self,
 874        expression_types: exp.IntoType,
 875        raw_tokens: t.List[Token],
 876        sql: t.Optional[str] = None,
 877    ) -> t.List[t.Optional[exp.Expression]]:
 878        """
 879        Parses a list of tokens into a given Expression type. If a collection of Expression
 880        types is given instead, this method will try to parse the token list into each one
 881        of them, stopping at the first for which the parsing succeeds.
 882
 883        Args:
 884            expression_types: The expression type(s) to try and parse the token list into.
 885            raw_tokens: The list of tokens.
 886            sql: The original SQL string, used to produce helpful debug messages.
 887
 888        Returns:
 889            The target Expression.
 890        """
 891        errors = []
 892        for expression_type in ensure_list(expression_types):
 893            parser = self.EXPRESSION_PARSERS.get(expression_type)
 894            if not parser:
 895                raise TypeError(f"No parser registered for {expression_type}")
 896
 897            try:
 898                return self._parse(parser, raw_tokens, sql)
 899            except ParseError as e:
 900                e.errors[0]["into_expression"] = expression_type
 901                errors.append(e)
 902
 903        raise ParseError(
 904            f"Failed to parse '{sql or raw_tokens}' into {expression_types}",
 905            errors=merge_errors(errors),
 906        ) from errors[-1]
 907
 908    def _parse(
 909        self,
 910        parse_method: t.Callable[[Parser], t.Optional[exp.Expression]],
 911        raw_tokens: t.List[Token],
 912        sql: t.Optional[str] = None,
 913    ) -> t.List[t.Optional[exp.Expression]]:
 914        self.reset()
 915        self.sql = sql or ""
 916
 917        total = len(raw_tokens)
 918        chunks: t.List[t.List[Token]] = [[]]
 919
 920        for i, token in enumerate(raw_tokens):
 921            if token.token_type == TokenType.SEMICOLON:
 922                if i < total - 1:
 923                    chunks.append([])
 924            else:
 925                chunks[-1].append(token)
 926
 927        expressions = []
 928
 929        for tokens in chunks:
 930            self._index = -1
 931            self._tokens = tokens
 932            self._advance()
 933
 934            expressions.append(parse_method(self))
 935
 936            if self._index < len(self._tokens):
 937                self.raise_error("Invalid expression / Unexpected token")
 938
 939            self.check_errors()
 940
 941        return expressions
 942
 943    def check_errors(self) -> None:
 944        """Logs or raises any found errors, depending on the chosen error level setting."""
 945        if self.error_level == ErrorLevel.WARN:
 946            for error in self.errors:
 947                logger.error(str(error))
 948        elif self.error_level == ErrorLevel.RAISE and self.errors:
 949            raise ParseError(
 950                concat_messages(self.errors, self.max_errors),
 951                errors=merge_errors(self.errors),
 952            )
 953
 954    def raise_error(self, message: str, token: t.Optional[Token] = None) -> None:
 955        """
 956        Appends an error in the list of recorded errors or raises it, depending on the chosen
 957        error level setting.
 958        """
 959        token = token or self._curr or self._prev or Token.string("")
 960        start = token.start
 961        end = token.end + 1
 962        start_context = self.sql[max(start - self.error_message_context, 0) : start]
 963        highlight = self.sql[start:end]
 964        end_context = self.sql[end : end + self.error_message_context]
 965
 966        error = ParseError.new(
 967            f"{message}. Line {token.line}, Col: {token.col}.\n"
 968            f"  {start_context}\033[4m{highlight}\033[0m{end_context}",
 969            description=message,
 970            line=token.line,
 971            col=token.col,
 972            start_context=start_context,
 973            highlight=highlight,
 974            end_context=end_context,
 975        )
 976
 977        if self.error_level == ErrorLevel.IMMEDIATE:
 978            raise error
 979
 980        self.errors.append(error)
 981
 982    def expression(
 983        self, exp_class: t.Type[E], comments: t.Optional[t.List[str]] = None, **kwargs
 984    ) -> E:
 985        """
 986        Creates a new, validated Expression.
 987
 988        Args:
 989            exp_class: The expression class to instantiate.
 990            comments: An optional list of comments to attach to the expression.
 991            kwargs: The arguments to set for the expression along with their respective values.
 992
 993        Returns:
 994            The target expression.
 995        """
 996        instance = exp_class(**kwargs)
 997        instance.add_comments(comments) if comments else self._add_comments(instance)
 998        return self.validate_expression(instance)
 999
1000    def _add_comments(self, expression: t.Optional[exp.Expression]) -> None:
1001        if expression and self._prev_comments:
1002            expression.add_comments(self._prev_comments)
1003            self._prev_comments = None
1004
1005    def validate_expression(self, expression: E, args: t.Optional[t.List] = None) -> E:
1006        """
1007        Validates an Expression, making sure that all its mandatory arguments are set.
1008
1009        Args:
1010            expression: The expression to validate.
1011            args: An optional list of items that was used to instantiate the expression, if it's a Func.
1012
1013        Returns:
1014            The validated expression.
1015        """
1016        if self.error_level != ErrorLevel.IGNORE:
1017            for error_message in expression.error_messages(args):
1018                self.raise_error(error_message)
1019
1020        return expression
1021
1022    def _find_sql(self, start: Token, end: Token) -> str:
1023        return self.sql[start.start : end.end + 1]
1024
1025    def _advance(self, times: int = 1) -> None:
1026        self._index += times
1027        self._curr = seq_get(self._tokens, self._index)
1028        self._next = seq_get(self._tokens, self._index + 1)
1029
1030        if self._index > 0:
1031            self._prev = self._tokens[self._index - 1]
1032            self._prev_comments = self._prev.comments
1033        else:
1034            self._prev = None
1035            self._prev_comments = None
1036
1037    def _retreat(self, index: int) -> None:
1038        if index != self._index:
1039            self._advance(index - self._index)
1040
1041    def _parse_command(self) -> exp.Command:
1042        return self.expression(exp.Command, this=self._prev.text, expression=self._parse_string())
1043
1044    def _parse_comment(self, allow_exists: bool = True) -> exp.Expression:
1045        start = self._prev
1046        exists = self._parse_exists() if allow_exists else None
1047
1048        self._match(TokenType.ON)
1049
1050        kind = self._match_set(self.CREATABLES) and self._prev
1051        if not kind:
1052            return self._parse_as_command(start)
1053
1054        if kind.token_type in (TokenType.FUNCTION, TokenType.PROCEDURE):
1055            this = self._parse_user_defined_function(kind=kind.token_type)
1056        elif kind.token_type == TokenType.TABLE:
1057            this = self._parse_table(alias_tokens=self.COMMENT_TABLE_ALIAS_TOKENS)
1058        elif kind.token_type == TokenType.COLUMN:
1059            this = self._parse_column()
1060        else:
1061            this = self._parse_id_var()
1062
1063        self._match(TokenType.IS)
1064
1065        return self.expression(
1066            exp.Comment, this=this, kind=kind.text, expression=self._parse_string(), exists=exists
1067        )
1068
1069    def _parse_to_table(
1070        self,
1071    ) -> exp.ToTableProperty:
1072        table = self._parse_table_parts(schema=True)
1073        return self.expression(exp.ToTableProperty, this=table)
1074
1075    # https://clickhouse.com/docs/en/engines/table-engines/mergetree-family/mergetree#mergetree-table-ttl
1076    def _parse_ttl(self) -> exp.Expression:
1077        def _parse_ttl_action() -> t.Optional[exp.Expression]:
1078            this = self._parse_bitwise()
1079
1080            if self._match_text_seq("DELETE"):
1081                return self.expression(exp.MergeTreeTTLAction, this=this, delete=True)
1082            if self._match_text_seq("RECOMPRESS"):
1083                return self.expression(
1084                    exp.MergeTreeTTLAction, this=this, recompress=self._parse_bitwise()
1085                )
1086            if self._match_text_seq("TO", "DISK"):
1087                return self.expression(
1088                    exp.MergeTreeTTLAction, this=this, to_disk=self._parse_string()
1089                )
1090            if self._match_text_seq("TO", "VOLUME"):
1091                return self.expression(
1092                    exp.MergeTreeTTLAction, this=this, to_volume=self._parse_string()
1093                )
1094
1095            return this
1096
1097        expressions = self._parse_csv(_parse_ttl_action)
1098        where = self._parse_where()
1099        group = self._parse_group()
1100
1101        aggregates = None
1102        if group and self._match(TokenType.SET):
1103            aggregates = self._parse_csv(self._parse_set_item)
1104
1105        return self.expression(
1106            exp.MergeTreeTTL,
1107            expressions=expressions,
1108            where=where,
1109            group=group,
1110            aggregates=aggregates,
1111        )
1112
1113    def _parse_statement(self) -> t.Optional[exp.Expression]:
1114        if self._curr is None:
1115            return None
1116
1117        if self._match_set(self.STATEMENT_PARSERS):
1118            return self.STATEMENT_PARSERS[self._prev.token_type](self)
1119
1120        if self._match_set(Tokenizer.COMMANDS):
1121            return self._parse_command()
1122
1123        expression = self._parse_expression()
1124        expression = self._parse_set_operations(expression) if expression else self._parse_select()
1125        return self._parse_query_modifiers(expression)
1126
1127    def _parse_drop(self) -> exp.Drop | exp.Command:
1128        start = self._prev
1129        temporary = self._match(TokenType.TEMPORARY)
1130        materialized = self._match_text_seq("MATERIALIZED")
1131
1132        kind = self._match_set(self.CREATABLES) and self._prev.text
1133        if not kind:
1134            return self._parse_as_command(start)
1135
1136        return self.expression(
1137            exp.Drop,
1138            exists=self._parse_exists(),
1139            this=self._parse_table(schema=True),
1140            kind=kind,
1141            temporary=temporary,
1142            materialized=materialized,
1143            cascade=self._match_text_seq("CASCADE"),
1144            constraints=self._match_text_seq("CONSTRAINTS"),
1145            purge=self._match_text_seq("PURGE"),
1146        )
1147
1148    def _parse_exists(self, not_: bool = False) -> t.Optional[bool]:
1149        return (
1150            self._match(TokenType.IF)
1151            and (not not_ or self._match(TokenType.NOT))
1152            and self._match(TokenType.EXISTS)
1153        )
1154
1155    def _parse_create(self) -> exp.Create | exp.Command:
1156        # Note: this can't be None because we've matched a statement parser
1157        start = self._prev
1158        replace = start.text.upper() == "REPLACE" or self._match_pair(
1159            TokenType.OR, TokenType.REPLACE
1160        )
1161        unique = self._match(TokenType.UNIQUE)
1162
1163        if self._match_pair(TokenType.TABLE, TokenType.FUNCTION, advance=False):
1164            self._advance()
1165
1166        properties = None
1167        create_token = self._match_set(self.CREATABLES) and self._prev
1168
1169        if not create_token:
1170            # exp.Properties.Location.POST_CREATE
1171            properties = self._parse_properties()
1172            create_token = self._match_set(self.CREATABLES) and self._prev
1173
1174            if not properties or not create_token:
1175                return self._parse_as_command(start)
1176
1177        exists = self._parse_exists(not_=True)
1178        this = None
1179        expression = None
1180        indexes = None
1181        no_schema_binding = None
1182        begin = None
1183        clone = None
1184
1185        def extend_props(temp_props: t.Optional[exp.Properties]) -> None:
1186            nonlocal properties
1187            if properties and temp_props:
1188                properties.expressions.extend(temp_props.expressions)
1189            elif temp_props:
1190                properties = temp_props
1191
1192        if create_token.token_type in (TokenType.FUNCTION, TokenType.PROCEDURE):
1193            this = self._parse_user_defined_function(kind=create_token.token_type)
1194
1195            # exp.Properties.Location.POST_SCHEMA ("schema" here is the UDF's type signature)
1196            extend_props(self._parse_properties())
1197
1198            self._match(TokenType.ALIAS)
1199            begin = self._match(TokenType.BEGIN)
1200            return_ = self._match_text_seq("RETURN")
1201            expression = self._parse_statement()
1202
1203            if return_:
1204                expression = self.expression(exp.Return, this=expression)
1205        elif create_token.token_type == TokenType.INDEX:
1206            this = self._parse_index(index=self._parse_id_var())
1207        elif create_token.token_type in self.DB_CREATABLES:
1208            table_parts = self._parse_table_parts(schema=True)
1209
1210            # exp.Properties.Location.POST_NAME
1211            self._match(TokenType.COMMA)
1212            extend_props(self._parse_properties(before=True))
1213
1214            this = self._parse_schema(this=table_parts)
1215
1216            # exp.Properties.Location.POST_SCHEMA and POST_WITH
1217            extend_props(self._parse_properties())
1218
1219            self._match(TokenType.ALIAS)
1220            if not self._match_set(self.DDL_SELECT_TOKENS, advance=False):
1221                # exp.Properties.Location.POST_ALIAS
1222                extend_props(self._parse_properties())
1223
1224            expression = self._parse_ddl_select()
1225
1226            if create_token.token_type == TokenType.TABLE:
1227                indexes = []
1228                while True:
1229                    index = self._parse_index()
1230
1231                    # exp.Properties.Location.POST_EXPRESSION and POST_INDEX
1232                    extend_props(self._parse_properties())
1233
1234                    if not index:
1235                        break
1236                    else:
1237                        self._match(TokenType.COMMA)
1238                        indexes.append(index)
1239            elif create_token.token_type == TokenType.VIEW:
1240                if self._match_text_seq("WITH", "NO", "SCHEMA", "BINDING"):
1241                    no_schema_binding = True
1242
1243            if self._match_text_seq("CLONE"):
1244                clone = self._parse_table(schema=True)
1245                when = self._match_texts({"AT", "BEFORE"}) and self._prev.text.upper()
1246                clone_kind = (
1247                    self._match(TokenType.L_PAREN)
1248                    and self._match_texts(self.CLONE_KINDS)
1249                    and self._prev.text.upper()
1250                )
1251                clone_expression = self._match(TokenType.FARROW) and self._parse_bitwise()
1252                self._match(TokenType.R_PAREN)
1253                clone = self.expression(
1254                    exp.Clone, this=clone, when=when, kind=clone_kind, expression=clone_expression
1255                )
1256
1257        return self.expression(
1258            exp.Create,
1259            this=this,
1260            kind=create_token.text,
1261            replace=replace,
1262            unique=unique,
1263            expression=expression,
1264            exists=exists,
1265            properties=properties,
1266            indexes=indexes,
1267            no_schema_binding=no_schema_binding,
1268            begin=begin,
1269            clone=clone,
1270        )
1271
1272    def _parse_property_before(self) -> t.Optional[exp.Expression]:
1273        # only used for teradata currently
1274        self._match(TokenType.COMMA)
1275
1276        kwargs = {
1277            "no": self._match_text_seq("NO"),
1278            "dual": self._match_text_seq("DUAL"),
1279            "before": self._match_text_seq("BEFORE"),
1280            "default": self._match_text_seq("DEFAULT"),
1281            "local": (self._match_text_seq("LOCAL") and "LOCAL")
1282            or (self._match_text_seq("NOT", "LOCAL") and "NOT LOCAL"),
1283            "after": self._match_text_seq("AFTER"),
1284            "minimum": self._match_texts(("MIN", "MINIMUM")),
1285            "maximum": self._match_texts(("MAX", "MAXIMUM")),
1286        }
1287
1288        if self._match_texts(self.PROPERTY_PARSERS):
1289            parser = self.PROPERTY_PARSERS[self._prev.text.upper()]
1290            try:
1291                return parser(self, **{k: v for k, v in kwargs.items() if v})
1292            except TypeError:
1293                self.raise_error(f"Cannot parse property '{self._prev.text}'")
1294
1295        return None
1296
1297    def _parse_property(self) -> t.Optional[exp.Expression]:
1298        if self._match_texts(self.PROPERTY_PARSERS):
1299            return self.PROPERTY_PARSERS[self._prev.text.upper()](self)
1300
1301        if self._match_pair(TokenType.DEFAULT, TokenType.CHARACTER_SET):
1302            return self._parse_character_set(default=True)
1303
1304        if self._match_text_seq("COMPOUND", "SORTKEY"):
1305            return self._parse_sortkey(compound=True)
1306
1307        if self._match_text_seq("SQL", "SECURITY"):
1308            return self.expression(exp.SqlSecurityProperty, definer=self._match_text_seq("DEFINER"))
1309
1310        assignment = self._match_pair(
1311            TokenType.VAR, TokenType.EQ, advance=False
1312        ) or self._match_pair(TokenType.STRING, TokenType.EQ, advance=False)
1313
1314        if assignment:
1315            key = self._parse_var_or_string()
1316            self._match(TokenType.EQ)
1317            return self.expression(exp.Property, this=key, value=self._parse_column())
1318
1319        return None
1320
1321    def _parse_stored(self) -> exp.FileFormatProperty:
1322        self._match(TokenType.ALIAS)
1323
1324        input_format = self._parse_string() if self._match_text_seq("INPUTFORMAT") else None
1325        output_format = self._parse_string() if self._match_text_seq("OUTPUTFORMAT") else None
1326
1327        return self.expression(
1328            exp.FileFormatProperty,
1329            this=self.expression(
1330                exp.InputOutputFormat, input_format=input_format, output_format=output_format
1331            )
1332            if input_format or output_format
1333            else self._parse_var_or_string() or self._parse_number() or self._parse_id_var(),
1334        )
1335
1336    def _parse_property_assignment(self, exp_class: t.Type[E]) -> E:
1337        self._match(TokenType.EQ)
1338        self._match(TokenType.ALIAS)
1339        return self.expression(exp_class, this=self._parse_field())
1340
1341    def _parse_properties(self, before: t.Optional[bool] = None) -> t.Optional[exp.Properties]:
1342        properties = []
1343        while True:
1344            if before:
1345                prop = self._parse_property_before()
1346            else:
1347                prop = self._parse_property()
1348
1349            if not prop:
1350                break
1351            for p in ensure_list(prop):
1352                properties.append(p)
1353
1354        if properties:
1355            return self.expression(exp.Properties, expressions=properties)
1356
1357        return None
1358
1359    def _parse_fallback(self, no: bool = False) -> exp.FallbackProperty:
1360        return self.expression(
1361            exp.FallbackProperty, no=no, protection=self._match_text_seq("PROTECTION")
1362        )
1363
1364    def _parse_volatile_property(self) -> exp.VolatileProperty | exp.StabilityProperty:
1365        if self._index >= 2:
1366            pre_volatile_token = self._tokens[self._index - 2]
1367        else:
1368            pre_volatile_token = None
1369
1370        if pre_volatile_token and pre_volatile_token.token_type in self.PRE_VOLATILE_TOKENS:
1371            return exp.VolatileProperty()
1372
1373        return self.expression(exp.StabilityProperty, this=exp.Literal.string("VOLATILE"))
1374
1375    def _parse_with_property(
1376        self,
1377    ) -> t.Optional[exp.Expression] | t.List[t.Optional[exp.Expression]]:
1378        self._match(TokenType.WITH)
1379        if self._match(TokenType.L_PAREN, advance=False):
1380            return self._parse_wrapped_csv(self._parse_property)
1381
1382        if self._match_text_seq("JOURNAL"):
1383            return self._parse_withjournaltable()
1384
1385        if self._match_text_seq("DATA"):
1386            return self._parse_withdata(no=False)
1387        elif self._match_text_seq("NO", "DATA"):
1388            return self._parse_withdata(no=True)
1389
1390        if not self._next:
1391            return None
1392
1393        return self._parse_withisolatedloading()
1394
1395    # https://dev.mysql.com/doc/refman/8.0/en/create-view.html
1396    def _parse_definer(self) -> t.Optional[exp.DefinerProperty]:
1397        self._match(TokenType.EQ)
1398
1399        user = self._parse_id_var()
1400        self._match(TokenType.PARAMETER)
1401        host = self._parse_id_var() or (self._match(TokenType.MOD) and self._prev.text)
1402
1403        if not user or not host:
1404            return None
1405
1406        return exp.DefinerProperty(this=f"{user}@{host}")
1407
1408    def _parse_withjournaltable(self) -> exp.WithJournalTableProperty:
1409        self._match(TokenType.TABLE)
1410        self._match(TokenType.EQ)
1411        return self.expression(exp.WithJournalTableProperty, this=self._parse_table_parts())
1412
1413    def _parse_log(self, no: bool = False) -> exp.LogProperty:
1414        return self.expression(exp.LogProperty, no=no)
1415
1416    def _parse_journal(self, **kwargs) -> exp.JournalProperty:
1417        return self.expression(exp.JournalProperty, **kwargs)
1418
1419    def _parse_checksum(self) -> exp.ChecksumProperty:
1420        self._match(TokenType.EQ)
1421
1422        on = None
1423        if self._match(TokenType.ON):
1424            on = True
1425        elif self._match_text_seq("OFF"):
1426            on = False
1427
1428        return self.expression(exp.ChecksumProperty, on=on, default=self._match(TokenType.DEFAULT))
1429
1430    def _parse_cluster(self) -> t.Optional[exp.Cluster]:
1431        return self.expression(exp.Cluster, expressions=self._parse_csv(self._parse_ordered))
1432
1433    def _parse_copy_property(self) -> t.Optional[exp.CopyGrantsProperty]:
1434        if not self._match_text_seq("GRANTS"):
1435            self._retreat(self._index - 1)
1436            return None
1437
1438        return self.expression(exp.CopyGrantsProperty)
1439
1440    def _parse_freespace(self) -> exp.FreespaceProperty:
1441        self._match(TokenType.EQ)
1442        return self.expression(
1443            exp.FreespaceProperty, this=self._parse_number(), percent=self._match(TokenType.PERCENT)
1444        )
1445
1446    def _parse_mergeblockratio(
1447        self, no: bool = False, default: bool = False
1448    ) -> exp.MergeBlockRatioProperty:
1449        if self._match(TokenType.EQ):
1450            return self.expression(
1451                exp.MergeBlockRatioProperty,
1452                this=self._parse_number(),
1453                percent=self._match(TokenType.PERCENT),
1454            )
1455
1456        return self.expression(exp.MergeBlockRatioProperty, no=no, default=default)
1457
1458    def _parse_datablocksize(
1459        self,
1460        default: t.Optional[bool] = None,
1461        minimum: t.Optional[bool] = None,
1462        maximum: t.Optional[bool] = None,
1463    ) -> exp.DataBlocksizeProperty:
1464        self._match(TokenType.EQ)
1465        size = self._parse_number()
1466
1467        units = None
1468        if self._match_texts(("BYTES", "KBYTES", "KILOBYTES")):
1469            units = self._prev.text
1470
1471        return self.expression(
1472            exp.DataBlocksizeProperty,
1473            size=size,
1474            units=units,
1475            default=default,
1476            minimum=minimum,
1477            maximum=maximum,
1478        )
1479
1480    def _parse_blockcompression(self) -> exp.BlockCompressionProperty:
1481        self._match(TokenType.EQ)
1482        always = self._match_text_seq("ALWAYS")
1483        manual = self._match_text_seq("MANUAL")
1484        never = self._match_text_seq("NEVER")
1485        default = self._match_text_seq("DEFAULT")
1486
1487        autotemp = None
1488        if self._match_text_seq("AUTOTEMP"):
1489            autotemp = self._parse_schema()
1490
1491        return self.expression(
1492            exp.BlockCompressionProperty,
1493            always=always,
1494            manual=manual,
1495            never=never,
1496            default=default,
1497            autotemp=autotemp,
1498        )
1499
1500    def _parse_withisolatedloading(self) -> exp.IsolatedLoadingProperty:
1501        no = self._match_text_seq("NO")
1502        concurrent = self._match_text_seq("CONCURRENT")
1503        self._match_text_seq("ISOLATED", "LOADING")
1504        for_all = self._match_text_seq("FOR", "ALL")
1505        for_insert = self._match_text_seq("FOR", "INSERT")
1506        for_none = self._match_text_seq("FOR", "NONE")
1507        return self.expression(
1508            exp.IsolatedLoadingProperty,
1509            no=no,
1510            concurrent=concurrent,
1511            for_all=for_all,
1512            for_insert=for_insert,
1513            for_none=for_none,
1514        )
1515
1516    def _parse_locking(self) -> exp.LockingProperty:
1517        if self._match(TokenType.TABLE):
1518            kind = "TABLE"
1519        elif self._match(TokenType.VIEW):
1520            kind = "VIEW"
1521        elif self._match(TokenType.ROW):
1522            kind = "ROW"
1523        elif self._match_text_seq("DATABASE"):
1524            kind = "DATABASE"
1525        else:
1526            kind = None
1527
1528        if kind in ("DATABASE", "TABLE", "VIEW"):
1529            this = self._parse_table_parts()
1530        else:
1531            this = None
1532
1533        if self._match(TokenType.FOR):
1534            for_or_in = "FOR"
1535        elif self._match(TokenType.IN):
1536            for_or_in = "IN"
1537        else:
1538            for_or_in = None
1539
1540        if self._match_text_seq("ACCESS"):
1541            lock_type = "ACCESS"
1542        elif self._match_texts(("EXCL", "EXCLUSIVE")):
1543            lock_type = "EXCLUSIVE"
1544        elif self._match_text_seq("SHARE"):
1545            lock_type = "SHARE"
1546        elif self._match_text_seq("READ"):
1547            lock_type = "READ"
1548        elif self._match_text_seq("WRITE"):
1549            lock_type = "WRITE"
1550        elif self._match_text_seq("CHECKSUM"):
1551            lock_type = "CHECKSUM"
1552        else:
1553            lock_type = None
1554
1555        override = self._match_text_seq("OVERRIDE")
1556
1557        return self.expression(
1558            exp.LockingProperty,
1559            this=this,
1560            kind=kind,
1561            for_or_in=for_or_in,
1562            lock_type=lock_type,
1563            override=override,
1564        )
1565
1566    def _parse_partition_by(self) -> t.List[t.Optional[exp.Expression]]:
1567        if self._match(TokenType.PARTITION_BY):
1568            return self._parse_csv(self._parse_conjunction)
1569        return []
1570
1571    def _parse_partitioned_by(self) -> exp.PartitionedByProperty:
1572        self._match(TokenType.EQ)
1573        return self.expression(
1574            exp.PartitionedByProperty,
1575            this=self._parse_schema() or self._parse_bracket(self._parse_field()),
1576        )
1577
1578    def _parse_withdata(self, no: bool = False) -> exp.WithDataProperty:
1579        if self._match_text_seq("AND", "STATISTICS"):
1580            statistics = True
1581        elif self._match_text_seq("AND", "NO", "STATISTICS"):
1582            statistics = False
1583        else:
1584            statistics = None
1585
1586        return self.expression(exp.WithDataProperty, no=no, statistics=statistics)
1587
1588    def _parse_no_property(self) -> t.Optional[exp.NoPrimaryIndexProperty]:
1589        if self._match_text_seq("PRIMARY", "INDEX"):
1590            return exp.NoPrimaryIndexProperty()
1591        return None
1592
1593    def _parse_on_property(self) -> t.Optional[exp.Expression]:
1594        if self._match_text_seq("COMMIT", "PRESERVE", "ROWS"):
1595            return exp.OnCommitProperty()
1596        elif self._match_text_seq("COMMIT", "DELETE", "ROWS"):
1597            return exp.OnCommitProperty(delete=True)
1598        return None
1599
1600    def _parse_distkey(self) -> exp.DistKeyProperty:
1601        return self.expression(exp.DistKeyProperty, this=self._parse_wrapped(self._parse_id_var))
1602
1603    def _parse_create_like(self) -> t.Optional[exp.LikeProperty]:
1604        table = self._parse_table(schema=True)
1605
1606        options = []
1607        while self._match_texts(("INCLUDING", "EXCLUDING")):
1608            this = self._prev.text.upper()
1609
1610            id_var = self._parse_id_var()
1611            if not id_var:
1612                return None
1613
1614            options.append(
1615                self.expression(exp.Property, this=this, value=exp.var(id_var.this.upper()))
1616            )
1617
1618        return self.expression(exp.LikeProperty, this=table, expressions=options)
1619
1620    def _parse_sortkey(self, compound: bool = False) -> exp.SortKeyProperty:
1621        return self.expression(
1622            exp.SortKeyProperty, this=self._parse_wrapped_id_vars(), compound=compound
1623        )
1624
1625    def _parse_character_set(self, default: bool = False) -> exp.CharacterSetProperty:
1626        self._match(TokenType.EQ)
1627        return self.expression(
1628            exp.CharacterSetProperty, this=self._parse_var_or_string(), default=default
1629        )
1630
1631    def _parse_returns(self) -> exp.ReturnsProperty:
1632        value: t.Optional[exp.Expression]
1633        is_table = self._match(TokenType.TABLE)
1634
1635        if is_table:
1636            if self._match(TokenType.LT):
1637                value = self.expression(
1638                    exp.Schema,
1639                    this="TABLE",
1640                    expressions=self._parse_csv(self._parse_struct_types),
1641                )
1642                if not self._match(TokenType.GT):
1643                    self.raise_error("Expecting >")
1644            else:
1645                value = self._parse_schema(exp.var("TABLE"))
1646        else:
1647            value = self._parse_types()
1648
1649        return self.expression(exp.ReturnsProperty, this=value, is_table=is_table)
1650
1651    def _parse_describe(self) -> exp.Describe:
1652        kind = self._match_set(self.CREATABLES) and self._prev.text
1653        this = self._parse_table()
1654        return self.expression(exp.Describe, this=this, kind=kind)
1655
1656    def _parse_insert(self) -> exp.Insert:
1657        overwrite = self._match(TokenType.OVERWRITE)
1658        local = self._match_text_seq("LOCAL")
1659        alternative = None
1660
1661        if self._match_text_seq("DIRECTORY"):
1662            this: t.Optional[exp.Expression] = self.expression(
1663                exp.Directory,
1664                this=self._parse_var_or_string(),
1665                local=local,
1666                row_format=self._parse_row_format(match_row=True),
1667            )
1668        else:
1669            if self._match(TokenType.OR):
1670                alternative = self._match_texts(self.INSERT_ALTERNATIVES) and self._prev.text
1671
1672            self._match(TokenType.INTO)
1673            self._match(TokenType.TABLE)
1674            this = self._parse_table(schema=True)
1675
1676        return self.expression(
1677            exp.Insert,
1678            this=this,
1679            exists=self._parse_exists(),
1680            partition=self._parse_partition(),
1681            where=self._match_pair(TokenType.REPLACE, TokenType.WHERE)
1682            and self._parse_conjunction(),
1683            expression=self._parse_ddl_select(),
1684            conflict=self._parse_on_conflict(),
1685            returning=self._parse_returning(),
1686            overwrite=overwrite,
1687            alternative=alternative,
1688        )
1689
1690    def _parse_on_conflict(self) -> t.Optional[exp.OnConflict]:
1691        conflict = self._match_text_seq("ON", "CONFLICT")
1692        duplicate = self._match_text_seq("ON", "DUPLICATE", "KEY")
1693
1694        if not conflict and not duplicate:
1695            return None
1696
1697        nothing = None
1698        expressions = None
1699        key = None
1700        constraint = None
1701
1702        if conflict:
1703            if self._match_text_seq("ON", "CONSTRAINT"):
1704                constraint = self._parse_id_var()
1705            else:
1706                key = self._parse_csv(self._parse_value)
1707
1708        self._match_text_seq("DO")
1709        if self._match_text_seq("NOTHING"):
1710            nothing = True
1711        else:
1712            self._match(TokenType.UPDATE)
1713            expressions = self._match(TokenType.SET) and self._parse_csv(self._parse_equality)
1714
1715        return self.expression(
1716            exp.OnConflict,
1717            duplicate=duplicate,
1718            expressions=expressions,
1719            nothing=nothing,
1720            key=key,
1721            constraint=constraint,
1722        )
1723
1724    def _parse_returning(self) -> t.Optional[exp.Returning]:
1725        if not self._match(TokenType.RETURNING):
1726            return None
1727
1728        return self.expression(exp.Returning, expressions=self._parse_csv(self._parse_column))
1729
1730    def _parse_row(self) -> t.Optional[exp.RowFormatSerdeProperty | exp.RowFormatDelimitedProperty]:
1731        if not self._match(TokenType.FORMAT):
1732            return None
1733        return self._parse_row_format()
1734
1735    def _parse_row_format(
1736        self, match_row: bool = False
1737    ) -> t.Optional[exp.RowFormatSerdeProperty | exp.RowFormatDelimitedProperty]:
1738        if match_row and not self._match_pair(TokenType.ROW, TokenType.FORMAT):
1739            return None
1740
1741        if self._match_text_seq("SERDE"):
1742            return self.expression(exp.RowFormatSerdeProperty, this=self._parse_string())
1743
1744        self._match_text_seq("DELIMITED")
1745
1746        kwargs = {}
1747
1748        if self._match_text_seq("FIELDS", "TERMINATED", "BY"):
1749            kwargs["fields"] = self._parse_string()
1750            if self._match_text_seq("ESCAPED", "BY"):
1751                kwargs["escaped"] = self._parse_string()
1752        if self._match_text_seq("COLLECTION", "ITEMS", "TERMINATED", "BY"):
1753            kwargs["collection_items"] = self._parse_string()
1754        if self._match_text_seq("MAP", "KEYS", "TERMINATED", "BY"):
1755            kwargs["map_keys"] = self._parse_string()
1756        if self._match_text_seq("LINES", "TERMINATED", "BY"):
1757            kwargs["lines"] = self._parse_string()
1758        if self._match_text_seq("NULL", "DEFINED", "AS"):
1759            kwargs["null"] = self._parse_string()
1760
1761        return self.expression(exp.RowFormatDelimitedProperty, **kwargs)  # type: ignore
1762
1763    def _parse_load(self) -> exp.LoadData | exp.Command:
1764        if self._match_text_seq("DATA"):
1765            local = self._match_text_seq("LOCAL")
1766            self._match_text_seq("INPATH")
1767            inpath = self._parse_string()
1768            overwrite = self._match(TokenType.OVERWRITE)
1769            self._match_pair(TokenType.INTO, TokenType.TABLE)
1770
1771            return self.expression(
1772                exp.LoadData,
1773                this=self._parse_table(schema=True),
1774                local=local,
1775                overwrite=overwrite,
1776                inpath=inpath,
1777                partition=self._parse_partition(),
1778                input_format=self._match_text_seq("INPUTFORMAT") and self._parse_string(),
1779                serde=self._match_text_seq("SERDE") and self._parse_string(),
1780            )
1781        return self._parse_as_command(self._prev)
1782
1783    def _parse_delete(self) -> exp.Delete:
1784        self._match(TokenType.FROM)
1785
1786        return self.expression(
1787            exp.Delete,
1788            this=self._parse_table(),
1789            using=self._parse_csv(lambda: self._match(TokenType.USING) and self._parse_table()),
1790            where=self._parse_where(),
1791            returning=self._parse_returning(),
1792            limit=self._parse_limit(),
1793        )
1794
1795    def _parse_update(self) -> exp.Update:
1796        return self.expression(
1797            exp.Update,
1798            **{  # type: ignore
1799                "this": self._parse_table(alias_tokens=self.UPDATE_ALIAS_TOKENS),
1800                "expressions": self._match(TokenType.SET) and self._parse_csv(self._parse_equality),
1801                "from": self._parse_from(modifiers=True),
1802                "where": self._parse_where(),
1803                "returning": self._parse_returning(),
1804                "limit": self._parse_limit(),
1805            },
1806        )
1807
1808    def _parse_uncache(self) -> exp.Uncache:
1809        if not self._match(TokenType.TABLE):
1810            self.raise_error("Expecting TABLE after UNCACHE")
1811
1812        return self.expression(
1813            exp.Uncache, exists=self._parse_exists(), this=self._parse_table(schema=True)
1814        )
1815
1816    def _parse_cache(self) -> exp.Cache:
1817        lazy = self._match_text_seq("LAZY")
1818        self._match(TokenType.TABLE)
1819        table = self._parse_table(schema=True)
1820
1821        options = []
1822        if self._match_text_seq("OPTIONS"):
1823            self._match_l_paren()
1824            k = self._parse_string()
1825            self._match(TokenType.EQ)
1826            v = self._parse_string()
1827            options = [k, v]
1828            self._match_r_paren()
1829
1830        self._match(TokenType.ALIAS)
1831        return self.expression(
1832            exp.Cache,
1833            this=table,
1834            lazy=lazy,
1835            options=options,
1836            expression=self._parse_select(nested=True),
1837        )
1838
1839    def _parse_partition(self) -> t.Optional[exp.Partition]:
1840        if not self._match(TokenType.PARTITION):
1841            return None
1842
1843        return self.expression(
1844            exp.Partition, expressions=self._parse_wrapped_csv(self._parse_conjunction)
1845        )
1846
1847    def _parse_value(self) -> exp.Tuple:
1848        if self._match(TokenType.L_PAREN):
1849            expressions = self._parse_csv(self._parse_conjunction)
1850            self._match_r_paren()
1851            return self.expression(exp.Tuple, expressions=expressions)
1852
1853        # In presto we can have VALUES 1, 2 which results in 1 column & 2 rows.
1854        # Source: https://prestodb.io/docs/current/sql/values.html
1855        return self.expression(exp.Tuple, expressions=[self._parse_conjunction()])
1856
1857    def _parse_select(
1858        self, nested: bool = False, table: bool = False, parse_subquery_alias: bool = True
1859    ) -> t.Optional[exp.Expression]:
1860        cte = self._parse_with()
1861        if cte:
1862            this = self._parse_statement()
1863
1864            if not this:
1865                self.raise_error("Failed to parse any statement following CTE")
1866                return cte
1867
1868            if "with" in this.arg_types:
1869                this.set("with", cte)
1870            else:
1871                self.raise_error(f"{this.key} does not support CTE")
1872                this = cte
1873        elif self._match(TokenType.SELECT):
1874            comments = self._prev_comments
1875
1876            hint = self._parse_hint()
1877            all_ = self._match(TokenType.ALL)
1878            distinct = self._match(TokenType.DISTINCT)
1879
1880            kind = (
1881                self._match(TokenType.ALIAS)
1882                and self._match_texts(("STRUCT", "VALUE"))
1883                and self._prev.text
1884            )
1885
1886            if distinct:
1887                distinct = self.expression(
1888                    exp.Distinct,
1889                    on=self._parse_value() if self._match(TokenType.ON) else None,
1890                )
1891
1892            if all_ and distinct:
1893                self.raise_error("Cannot specify both ALL and DISTINCT after SELECT")
1894
1895            limit = self._parse_limit(top=True)
1896            expressions = self._parse_csv(self._parse_expression)
1897
1898            this = self.expression(
1899                exp.Select,
1900                kind=kind,
1901                hint=hint,
1902                distinct=distinct,
1903                expressions=expressions,
1904                limit=limit,
1905            )
1906            this.comments = comments
1907
1908            into = self._parse_into()
1909            if into:
1910                this.set("into", into)
1911
1912            from_ = self._parse_from()
1913            if from_:
1914                this.set("from", from_)
1915
1916            this = self._parse_query_modifiers(this)
1917        elif (table or nested) and self._match(TokenType.L_PAREN):
1918            if self._match(TokenType.PIVOT):
1919                this = self._parse_simplified_pivot()
1920            elif self._match(TokenType.FROM):
1921                this = exp.select("*").from_(
1922                    t.cast(exp.From, self._parse_from(skip_from_token=True))
1923                )
1924            else:
1925                this = self._parse_table() if table else self._parse_select(nested=True)
1926                this = self._parse_set_operations(self._parse_query_modifiers(this))
1927
1928            self._match_r_paren()
1929
1930            # early return so that subquery unions aren't parsed again
1931            # SELECT * FROM (SELECT 1) UNION ALL SELECT 1
1932            # Union ALL should be a property of the top select node, not the subquery
1933            return self._parse_subquery(this, parse_alias=parse_subquery_alias)
1934        elif self._match(TokenType.VALUES):
1935            this = self.expression(
1936                exp.Values,
1937                expressions=self._parse_csv(self._parse_value),
1938                alias=self._parse_table_alias(),
1939            )
1940        else:
1941            this = None
1942
1943        return self._parse_set_operations(this)
1944
1945    def _parse_with(self, skip_with_token: bool = False) -> t.Optional[exp.With]:
1946        if not skip_with_token and not self._match(TokenType.WITH):
1947            return None
1948
1949        comments = self._prev_comments
1950        recursive = self._match(TokenType.RECURSIVE)
1951
1952        expressions = []
1953        while True:
1954            expressions.append(self._parse_cte())
1955
1956            if not self._match(TokenType.COMMA) and not self._match(TokenType.WITH):
1957                break
1958            else:
1959                self._match(TokenType.WITH)
1960
1961        return self.expression(
1962            exp.With, comments=comments, expressions=expressions, recursive=recursive
1963        )
1964
1965    def _parse_cte(self) -> exp.CTE:
1966        alias = self._parse_table_alias()
1967        if not alias or not alias.this:
1968            self.raise_error("Expected CTE to have alias")
1969
1970        self._match(TokenType.ALIAS)
1971        return self.expression(
1972            exp.CTE, this=self._parse_wrapped(self._parse_statement), alias=alias
1973        )
1974
1975    def _parse_table_alias(
1976        self, alias_tokens: t.Optional[t.Collection[TokenType]] = None
1977    ) -> t.Optional[exp.TableAlias]:
1978        any_token = self._match(TokenType.ALIAS)
1979        alias = (
1980            self._parse_id_var(any_token=any_token, tokens=alias_tokens or self.TABLE_ALIAS_TOKENS)
1981            or self._parse_string_as_identifier()
1982        )
1983
1984        index = self._index
1985        if self._match(TokenType.L_PAREN):
1986            columns = self._parse_csv(self._parse_function_parameter)
1987            self._match_r_paren() if columns else self._retreat(index)
1988        else:
1989            columns = None
1990
1991        if not alias and not columns:
1992            return None
1993
1994        return self.expression(exp.TableAlias, this=alias, columns=columns)
1995
1996    def _parse_subquery(
1997        self, this: t.Optional[exp.Expression], parse_alias: bool = True
1998    ) -> t.Optional[exp.Subquery]:
1999        if not this:
2000            return None
2001
2002        return self.expression(
2003            exp.Subquery,
2004            this=this,
2005            pivots=self._parse_pivots(),
2006            alias=self._parse_table_alias() if parse_alias else None,
2007        )
2008
2009    def _parse_query_modifiers(
2010        self, this: t.Optional[exp.Expression]
2011    ) -> t.Optional[exp.Expression]:
2012        if isinstance(this, self.MODIFIABLES):
2013            for key, parser in self.QUERY_MODIFIER_PARSERS.items():
2014                expression = parser(self)
2015
2016                if expression:
2017                    if key == "limit":
2018                        offset = expression.args.pop("offset", None)
2019                        if offset:
2020                            this.set("offset", exp.Offset(expression=offset))
2021                    this.set(key, expression)
2022        return this
2023
2024    def _parse_hint(self) -> t.Optional[exp.Hint]:
2025        if self._match(TokenType.HINT):
2026            hints = self._parse_csv(self._parse_function)
2027
2028            if not self._match_pair(TokenType.STAR, TokenType.SLASH):
2029                self.raise_error("Expected */ after HINT")
2030
2031            return self.expression(exp.Hint, expressions=hints)
2032
2033        return None
2034
2035    def _parse_into(self) -> t.Optional[exp.Into]:
2036        if not self._match(TokenType.INTO):
2037            return None
2038
2039        temp = self._match(TokenType.TEMPORARY)
2040        unlogged = self._match_text_seq("UNLOGGED")
2041        self._match(TokenType.TABLE)
2042
2043        return self.expression(
2044            exp.Into, this=self._parse_table(schema=True), temporary=temp, unlogged=unlogged
2045        )
2046
2047    def _parse_from(
2048        self, modifiers: bool = False, skip_from_token: bool = False
2049    ) -> t.Optional[exp.From]:
2050        if not skip_from_token and not self._match(TokenType.FROM):
2051            return None
2052
2053        comments = self._prev_comments
2054        this = self._parse_table()
2055
2056        return self.expression(
2057            exp.From,
2058            comments=comments,
2059            this=self._parse_query_modifiers(this) if modifiers else this,
2060        )
2061
2062    def _parse_match_recognize(self) -> t.Optional[exp.MatchRecognize]:
2063        if not self._match(TokenType.MATCH_RECOGNIZE):
2064            return None
2065
2066        self._match_l_paren()
2067
2068        partition = self._parse_partition_by()
2069        order = self._parse_order()
2070        measures = (
2071            self._parse_csv(self._parse_expression) if self._match_text_seq("MEASURES") else None
2072        )
2073
2074        if self._match_text_seq("ONE", "ROW", "PER", "MATCH"):
2075            rows = exp.var("ONE ROW PER MATCH")
2076        elif self._match_text_seq("ALL", "ROWS", "PER", "MATCH"):
2077            text = "ALL ROWS PER MATCH"
2078            if self._match_text_seq("SHOW", "EMPTY", "MATCHES"):
2079                text += f" SHOW EMPTY MATCHES"
2080            elif self._match_text_seq("OMIT", "EMPTY", "MATCHES"):
2081                text += f" OMIT EMPTY MATCHES"
2082            elif self._match_text_seq("WITH", "UNMATCHED", "ROWS"):
2083                text += f" WITH UNMATCHED ROWS"
2084            rows = exp.var(text)
2085        else:
2086            rows = None
2087
2088        if self._match_text_seq("AFTER", "MATCH", "SKIP"):
2089            text = "AFTER MATCH SKIP"
2090            if self._match_text_seq("PAST", "LAST", "ROW"):
2091                text += f" PAST LAST ROW"
2092            elif self._match_text_seq("TO", "NEXT", "ROW"):
2093                text += f" TO NEXT ROW"
2094            elif self._match_text_seq("TO", "FIRST"):
2095                text += f" TO FIRST {self._advance_any().text}"  # type: ignore
2096            elif self._match_text_seq("TO", "LAST"):
2097                text += f" TO LAST {self._advance_any().text}"  # type: ignore
2098            after = exp.var(text)
2099        else:
2100            after = None
2101
2102        if self._match_text_seq("PATTERN"):
2103            self._match_l_paren()
2104
2105            if not self._curr:
2106                self.raise_error("Expecting )", self._curr)
2107
2108            paren = 1
2109            start = self._curr
2110
2111            while self._curr and paren > 0:
2112                if self._curr.token_type == TokenType.L_PAREN:
2113                    paren += 1
2114                if self._curr.token_type == TokenType.R_PAREN:
2115                    paren -= 1
2116
2117                end = self._prev
2118                self._advance()
2119
2120            if paren > 0:
2121                self.raise_error("Expecting )", self._curr)
2122
2123            pattern = exp.var(self._find_sql(start, end))
2124        else:
2125            pattern = None
2126
2127        define = (
2128            self._parse_csv(
2129                lambda: self.expression(
2130                    exp.Alias,
2131                    alias=self._parse_id_var(any_token=True),
2132                    this=self._match(TokenType.ALIAS) and self._parse_conjunction(),
2133                )
2134            )
2135            if self._match_text_seq("DEFINE")
2136            else None
2137        )
2138
2139        self._match_r_paren()
2140
2141        return self.expression(
2142            exp.MatchRecognize,
2143            partition_by=partition,
2144            order=order,
2145            measures=measures,
2146            rows=rows,
2147            after=after,
2148            pattern=pattern,
2149            define=define,
2150            alias=self._parse_table_alias(),
2151        )
2152
2153    def _parse_lateral(self) -> t.Optional[exp.Lateral]:
2154        outer_apply = self._match_pair(TokenType.OUTER, TokenType.APPLY)
2155        cross_apply = self._match_pair(TokenType.CROSS, TokenType.APPLY)
2156
2157        if outer_apply or cross_apply:
2158            this = self._parse_select(table=True)
2159            view = None
2160            outer = not cross_apply
2161        elif self._match(TokenType.LATERAL):
2162            this = self._parse_select(table=True)
2163            view = self._match(TokenType.VIEW)
2164            outer = self._match(TokenType.OUTER)
2165        else:
2166            return None
2167
2168        if not this:
2169            this = self._parse_function() or self._parse_id_var(any_token=False)
2170            while self._match(TokenType.DOT):
2171                this = exp.Dot(
2172                    this=this,
2173                    expression=self._parse_function() or self._parse_id_var(any_token=False),
2174                )
2175
2176        if view:
2177            table = self._parse_id_var(any_token=False)
2178            columns = self._parse_csv(self._parse_id_var) if self._match(TokenType.ALIAS) else []
2179            table_alias: t.Optional[exp.TableAlias] = self.expression(
2180                exp.TableAlias, this=table, columns=columns
2181            )
2182        elif isinstance(this, exp.Subquery) and this.alias:
2183            # Ensures parity between the Subquery's and the Lateral's "alias" args
2184            table_alias = this.args["alias"].copy()
2185        else:
2186            table_alias = self._parse_table_alias()
2187
2188        return self.expression(exp.Lateral, this=this, view=view, outer=outer, alias=table_alias)
2189
2190    def _parse_join_parts(
2191        self,
2192    ) -> t.Tuple[t.Optional[Token], t.Optional[Token], t.Optional[Token]]:
2193        return (
2194            self._match_set(self.JOIN_METHODS) and self._prev,
2195            self._match_set(self.JOIN_SIDES) and self._prev,
2196            self._match_set(self.JOIN_KINDS) and self._prev,
2197        )
2198
2199    def _parse_join(self, skip_join_token: bool = False) -> t.Optional[exp.Join]:
2200        if self._match(TokenType.COMMA):
2201            return self.expression(exp.Join, this=self._parse_table())
2202
2203        index = self._index
2204        method, side, kind = self._parse_join_parts()
2205        hint = self._prev.text if self._match_texts(self.JOIN_HINTS) else None
2206        join = self._match(TokenType.JOIN)
2207
2208        if not skip_join_token and not join:
2209            self._retreat(index)
2210            kind = None
2211            method = None
2212            side = None
2213
2214        outer_apply = self._match_pair(TokenType.OUTER, TokenType.APPLY, False)
2215        cross_apply = self._match_pair(TokenType.CROSS, TokenType.APPLY, False)
2216
2217        if not skip_join_token and not join and not outer_apply and not cross_apply:
2218            return None
2219
2220        if outer_apply:
2221            side = Token(TokenType.LEFT, "LEFT")
2222
2223        kwargs: t.Dict[str, t.Any] = {"this": self._parse_table()}
2224
2225        if method:
2226            kwargs["method"] = method.text
2227        if side:
2228            kwargs["side"] = side.text
2229        if kind:
2230            kwargs["kind"] = kind.text
2231        if hint:
2232            kwargs["hint"] = hint
2233
2234        if self._match(TokenType.ON):
2235            kwargs["on"] = self._parse_conjunction()
2236        elif self._match(TokenType.USING):
2237            kwargs["using"] = self._parse_wrapped_id_vars()
2238
2239        return self.expression(exp.Join, **kwargs)
2240
2241    def _parse_index(
2242        self,
2243        index: t.Optional[exp.Expression] = None,
2244    ) -> t.Optional[exp.Index]:
2245        if index:
2246            unique = None
2247            primary = None
2248            amp = None
2249
2250            self._match(TokenType.ON)
2251            self._match(TokenType.TABLE)  # hive
2252            table = self._parse_table_parts(schema=True)
2253        else:
2254            unique = self._match(TokenType.UNIQUE)
2255            primary = self._match_text_seq("PRIMARY")
2256            amp = self._match_text_seq("AMP")
2257
2258            if not self._match(TokenType.INDEX):
2259                return None
2260
2261            index = self._parse_id_var()
2262            table = None
2263
2264        using = self._parse_field() if self._match(TokenType.USING) else None
2265
2266        if self._match(TokenType.L_PAREN, advance=False):
2267            columns = self._parse_wrapped_csv(self._parse_ordered)
2268        else:
2269            columns = None
2270
2271        return self.expression(
2272            exp.Index,
2273            this=index,
2274            table=table,
2275            using=using,
2276            columns=columns,
2277            unique=unique,
2278            primary=primary,
2279            amp=amp,
2280            partition_by=self._parse_partition_by(),
2281        )
2282
2283    def _parse_table_hints(self) -> t.Optional[t.List[exp.Expression]]:
2284        hints: t.List[exp.Expression] = []
2285        if self._match_pair(TokenType.WITH, TokenType.L_PAREN):
2286            # https://learn.microsoft.com/en-us/sql/t-sql/queries/hints-transact-sql-table?view=sql-server-ver16
2287            hints.append(
2288                self.expression(
2289                    exp.WithTableHint,
2290                    expressions=self._parse_csv(
2291                        lambda: self._parse_function() or self._parse_var(any_token=True)
2292                    ),
2293                )
2294            )
2295            self._match_r_paren()
2296        else:
2297            # https://dev.mysql.com/doc/refman/8.0/en/index-hints.html
2298            while self._match_set(self.TABLE_INDEX_HINT_TOKENS):
2299                hint = exp.IndexTableHint(this=self._prev.text.upper())
2300
2301                self._match_texts({"INDEX", "KEY"})
2302                if self._match(TokenType.FOR):
2303                    hint.set("target", self._advance_any() and self._prev.text.upper())
2304
2305                hint.set("expressions", self._parse_wrapped_id_vars())
2306                hints.append(hint)
2307
2308        return hints or None
2309
2310    def _parse_table_part(self, schema: bool = False) -> t.Optional[exp.Expression]:
2311        return (
2312            (not schema and self._parse_function(optional_parens=False))
2313            or self._parse_id_var(any_token=False)
2314            or self._parse_string_as_identifier()
2315            or self._parse_placeholder()
2316        )
2317
2318    def _parse_table_parts(self, schema: bool = False) -> exp.Table:
2319        catalog = None
2320        db = None
2321        table = self._parse_table_part(schema=schema)
2322
2323        while self._match(TokenType.DOT):
2324            if catalog:
2325                # This allows nesting the table in arbitrarily many dot expressions if needed
2326                table = self.expression(
2327                    exp.Dot, this=table, expression=self._parse_table_part(schema=schema)
2328                )
2329            else:
2330                catalog = db
2331                db = table
2332                table = self._parse_table_part(schema=schema)
2333
2334        if not table:
2335            self.raise_error(f"Expected table name but got {self._curr}")
2336
2337        return self.expression(
2338            exp.Table, this=table, db=db, catalog=catalog, pivots=self._parse_pivots()
2339        )
2340
2341    def _parse_table(
2342        self, schema: bool = False, alias_tokens: t.Optional[t.Collection[TokenType]] = None
2343    ) -> t.Optional[exp.Expression]:
2344        lateral = self._parse_lateral()
2345        if lateral:
2346            return lateral
2347
2348        unnest = self._parse_unnest()
2349        if unnest:
2350            return unnest
2351
2352        values = self._parse_derived_table_values()
2353        if values:
2354            return values
2355
2356        subquery = self._parse_select(table=True)
2357        if subquery:
2358            if not subquery.args.get("pivots"):
2359                subquery.set("pivots", self._parse_pivots())
2360            return subquery
2361
2362        this: exp.Expression = self._parse_table_parts(schema=schema)
2363
2364        if schema:
2365            return self._parse_schema(this=this)
2366
2367        if self.ALIAS_POST_TABLESAMPLE:
2368            table_sample = self._parse_table_sample()
2369
2370        alias = self._parse_table_alias(alias_tokens=alias_tokens or self.TABLE_ALIAS_TOKENS)
2371        if alias:
2372            this.set("alias", alias)
2373
2374        if not this.args.get("pivots"):
2375            this.set("pivots", self._parse_pivots())
2376
2377        this.set("hints", self._parse_table_hints())
2378
2379        if not self.ALIAS_POST_TABLESAMPLE:
2380            table_sample = self._parse_table_sample()
2381
2382        if table_sample:
2383            table_sample.set("this", this)
2384            this = table_sample
2385
2386        return this
2387
2388    def _parse_unnest(self, with_alias: bool = True) -> t.Optional[exp.Unnest]:
2389        if not self._match(TokenType.UNNEST):
2390            return None
2391
2392        expressions = self._parse_wrapped_csv(self._parse_type)
2393        ordinality = self._match_pair(TokenType.WITH, TokenType.ORDINALITY)
2394
2395        alias = self._parse_table_alias() if with_alias else None
2396
2397        if alias and self.UNNEST_COLUMN_ONLY:
2398            if alias.args.get("columns"):
2399                self.raise_error("Unexpected extra column alias in unnest.")
2400
2401            alias.set("columns", [alias.this])
2402            alias.set("this", None)
2403
2404        offset = None
2405        if self._match_pair(TokenType.WITH, TokenType.OFFSET):
2406            self._match(TokenType.ALIAS)
2407            offset = self._parse_id_var() or exp.to_identifier("offset")
2408
2409        return self.expression(
2410            exp.Unnest, expressions=expressions, ordinality=ordinality, alias=alias, offset=offset
2411        )
2412
2413    def _parse_derived_table_values(self) -> t.Optional[exp.Values]:
2414        is_derived = self._match_pair(TokenType.L_PAREN, TokenType.VALUES)
2415        if not is_derived and not self._match(TokenType.VALUES):
2416            return None
2417
2418        expressions = self._parse_csv(self._parse_value)
2419        alias = self._parse_table_alias()
2420
2421        if is_derived:
2422            self._match_r_paren()
2423
2424        return self.expression(
2425            exp.Values, expressions=expressions, alias=alias or self._parse_table_alias()
2426        )
2427
2428    def _parse_table_sample(self, as_modifier: bool = False) -> t.Optional[exp.TableSample]:
2429        if not self._match(TokenType.TABLE_SAMPLE) and not (
2430            as_modifier and self._match_text_seq("USING", "SAMPLE")
2431        ):
2432            return None
2433
2434        bucket_numerator = None
2435        bucket_denominator = None
2436        bucket_field = None
2437        percent = None
2438        rows = None
2439        size = None
2440        seed = None
2441
2442        kind = (
2443            self._prev.text if self._prev.token_type == TokenType.TABLE_SAMPLE else "USING SAMPLE"
2444        )
2445        method = self._parse_var(tokens=(TokenType.ROW,))
2446
2447        self._match(TokenType.L_PAREN)
2448
2449        num = self._parse_number()
2450
2451        if self._match_text_seq("BUCKET"):
2452            bucket_numerator = self._parse_number()
2453            self._match_text_seq("OUT", "OF")
2454            bucket_denominator = bucket_denominator = self._parse_number()
2455            self._match(TokenType.ON)
2456            bucket_field = self._parse_field()
2457        elif self._match_set((TokenType.PERCENT, TokenType.MOD)):
2458            percent = num
2459        elif self._match(TokenType.ROWS):
2460            rows = num
2461        else:
2462            size = num
2463
2464        self._match(TokenType.R_PAREN)
2465
2466        if self._match(TokenType.L_PAREN):
2467            method = self._parse_var()
2468            seed = self._match(TokenType.COMMA) and self._parse_number()
2469            self._match_r_paren()
2470        elif self._match_texts(("SEED", "REPEATABLE")):
2471            seed = self._parse_wrapped(self._parse_number)
2472
2473        return self.expression(
2474            exp.TableSample,
2475            method=method,
2476            bucket_numerator=bucket_numerator,
2477            bucket_denominator=bucket_denominator,
2478            bucket_field=bucket_field,
2479            percent=percent,
2480            rows=rows,
2481            size=size,
2482            seed=seed,
2483            kind=kind,
2484        )
2485
2486    def _parse_pivots(self) -> t.List[t.Optional[exp.Expression]]:
2487        return list(iter(self._parse_pivot, None))
2488
2489    # https://duckdb.org/docs/sql/statements/pivot
2490    def _parse_simplified_pivot(self) -> exp.Pivot:
2491        def _parse_on() -> t.Optional[exp.Expression]:
2492            this = self._parse_bitwise()
2493            return self._parse_in(this) if self._match(TokenType.IN) else this
2494
2495        this = self._parse_table()
2496        expressions = self._match(TokenType.ON) and self._parse_csv(_parse_on)
2497        using = self._match(TokenType.USING) and self._parse_csv(
2498            lambda: self._parse_alias(self._parse_function())
2499        )
2500        group = self._parse_group()
2501        return self.expression(
2502            exp.Pivot, this=this, expressions=expressions, using=using, group=group
2503        )
2504
2505    def _parse_pivot(self) -> t.Optional[exp.Pivot]:
2506        index = self._index
2507
2508        if self._match(TokenType.PIVOT):
2509            unpivot = False
2510        elif self._match(TokenType.UNPIVOT):
2511            unpivot = True
2512        else:
2513            return None
2514
2515        expressions = []
2516        field = None
2517
2518        if not self._match(TokenType.L_PAREN):
2519            self._retreat(index)
2520            return None
2521
2522        if unpivot:
2523            expressions = self._parse_csv(self._parse_column)
2524        else:
2525            expressions = self._parse_csv(lambda: self._parse_alias(self._parse_function()))
2526
2527        if not expressions:
2528            self.raise_error("Failed to parse PIVOT's aggregation list")
2529
2530        if not self._match(TokenType.FOR):
2531            self.raise_error("Expecting FOR")
2532
2533        value = self._parse_column()
2534
2535        if not self._match(TokenType.IN):
2536            self.raise_error("Expecting IN")
2537
2538        field = self._parse_in(value, alias=True)
2539
2540        self._match_r_paren()
2541
2542        pivot = self.expression(exp.Pivot, expressions=expressions, field=field, unpivot=unpivot)
2543
2544        if not self._match_set((TokenType.PIVOT, TokenType.UNPIVOT), advance=False):
2545            pivot.set("alias", self._parse_table_alias())
2546
2547        if not unpivot:
2548            names = self._pivot_column_names(t.cast(t.List[exp.Expression], expressions))
2549
2550            columns: t.List[exp.Expression] = []
2551            for fld in pivot.args["field"].expressions:
2552                field_name = fld.sql() if self.IDENTIFY_PIVOT_STRINGS else fld.alias_or_name
2553                for name in names:
2554                    if self.PREFIXED_PIVOT_COLUMNS:
2555                        name = f"{name}_{field_name}" if name else field_name
2556                    else:
2557                        name = f"{field_name}_{name}" if name else field_name
2558
2559                    columns.append(exp.to_identifier(name))
2560
2561            pivot.set("columns", columns)
2562
2563        return pivot
2564
2565    def _pivot_column_names(self, aggregations: t.List[exp.Expression]) -> t.List[str]:
2566        return [agg.alias for agg in aggregations]
2567
2568    def _parse_where(self, skip_where_token: bool = False) -> t.Optional[exp.Where]:
2569        if not skip_where_token and not self._match(TokenType.WHERE):
2570            return None
2571
2572        return self.expression(
2573            exp.Where, comments=self._prev_comments, this=self._parse_conjunction()
2574        )
2575
2576    def _parse_group(self, skip_group_by_token: bool = False) -> t.Optional[exp.Group]:
2577        if not skip_group_by_token and not self._match(TokenType.GROUP_BY):
2578            return None
2579
2580        elements = defaultdict(list)
2581
2582        while True:
2583            expressions = self._parse_csv(self._parse_conjunction)
2584            if expressions:
2585                elements["expressions"].extend(expressions)
2586
2587            grouping_sets = self._parse_grouping_sets()
2588            if grouping_sets:
2589                elements["grouping_sets"].extend(grouping_sets)
2590
2591            rollup = None
2592            cube = None
2593            totals = None
2594
2595            with_ = self._match(TokenType.WITH)
2596            if self._match(TokenType.ROLLUP):
2597                rollup = with_ or self._parse_wrapped_csv(self._parse_column)
2598                elements["rollup"].extend(ensure_list(rollup))
2599
2600            if self._match(TokenType.CUBE):
2601                cube = with_ or self._parse_wrapped_csv(self._parse_column)
2602                elements["cube"].extend(ensure_list(cube))
2603
2604            if self._match_text_seq("TOTALS"):
2605                totals = True
2606                elements["totals"] = True  # type: ignore
2607
2608            if not (grouping_sets or rollup or cube or totals):
2609                break
2610
2611        return self.expression(exp.Group, **elements)  # type: ignore
2612
2613    def _parse_grouping_sets(self) -> t.Optional[t.List[t.Optional[exp.Expression]]]:
2614        if not self._match(TokenType.GROUPING_SETS):
2615            return None
2616
2617        return self._parse_wrapped_csv(self._parse_grouping_set)
2618
2619    def _parse_grouping_set(self) -> t.Optional[exp.Expression]:
2620        if self._match(TokenType.L_PAREN):
2621            grouping_set = self._parse_csv(self._parse_column)
2622            self._match_r_paren()
2623            return self.expression(exp.Tuple, expressions=grouping_set)
2624
2625        return self._parse_column()
2626
2627    def _parse_having(self, skip_having_token: bool = False) -> t.Optional[exp.Having]:
2628        if not skip_having_token and not self._match(TokenType.HAVING):
2629            return None
2630        return self.expression(exp.Having, this=self._parse_conjunction())
2631
2632    def _parse_qualify(self) -> t.Optional[exp.Qualify]:
2633        if not self._match(TokenType.QUALIFY):
2634            return None
2635        return self.expression(exp.Qualify, this=self._parse_conjunction())
2636
2637    def _parse_order(
2638        self, this: t.Optional[exp.Expression] = None, skip_order_token: bool = False
2639    ) -> t.Optional[exp.Expression]:
2640        if not skip_order_token and not self._match(TokenType.ORDER_BY):
2641            return this
2642
2643        return self.expression(
2644            exp.Order, this=this, expressions=self._parse_csv(self._parse_ordered)
2645        )
2646
2647    def _parse_sort(self, exp_class: t.Type[E], token: TokenType) -> t.Optional[E]:
2648        if not self._match(token):
2649            return None
2650        return self.expression(exp_class, expressions=self._parse_csv(self._parse_ordered))
2651
2652    def _parse_ordered(self) -> exp.Ordered:
2653        this = self._parse_conjunction()
2654        self._match(TokenType.ASC)
2655
2656        is_desc = self._match(TokenType.DESC)
2657        is_nulls_first = self._match_text_seq("NULLS", "FIRST")
2658        is_nulls_last = self._match_text_seq("NULLS", "LAST")
2659        desc = is_desc or False
2660        asc = not desc
2661        nulls_first = is_nulls_first or False
2662        explicitly_null_ordered = is_nulls_first or is_nulls_last
2663
2664        if (
2665            not explicitly_null_ordered
2666            and (
2667                (asc and self.NULL_ORDERING == "nulls_are_small")
2668                or (desc and self.NULL_ORDERING != "nulls_are_small")
2669            )
2670            and self.NULL_ORDERING != "nulls_are_last"
2671        ):
2672            nulls_first = True
2673
2674        return self.expression(exp.Ordered, this=this, desc=desc, nulls_first=nulls_first)
2675
2676    def _parse_limit(
2677        self, this: t.Optional[exp.Expression] = None, top: bool = False
2678    ) -> t.Optional[exp.Expression]:
2679        if self._match(TokenType.TOP if top else TokenType.LIMIT):
2680            limit_paren = self._match(TokenType.L_PAREN)
2681            expression = self._parse_number() if top else self._parse_term()
2682
2683            if self._match(TokenType.COMMA):
2684                offset = expression
2685                expression = self._parse_term()
2686            else:
2687                offset = None
2688
2689            limit_exp = self.expression(exp.Limit, this=this, expression=expression, offset=offset)
2690
2691            if limit_paren:
2692                self._match_r_paren()
2693
2694            return limit_exp
2695
2696        if self._match(TokenType.FETCH):
2697            direction = self._match_set((TokenType.FIRST, TokenType.NEXT))
2698            direction = self._prev.text if direction else "FIRST"
2699
2700            count = self._parse_number()
2701            percent = self._match(TokenType.PERCENT)
2702
2703            self._match_set((TokenType.ROW, TokenType.ROWS))
2704
2705            only = self._match_text_seq("ONLY")
2706            with_ties = self._match_text_seq("WITH", "TIES")
2707
2708            if only and with_ties:
2709                self.raise_error("Cannot specify both ONLY and WITH TIES in FETCH clause")
2710
2711            return self.expression(
2712                exp.Fetch,
2713                direction=direction,
2714                count=count,
2715                percent=percent,
2716                with_ties=with_ties,
2717            )
2718
2719        return this
2720
2721    def _parse_offset(self, this: t.Optional[exp.Expression] = None) -> t.Optional[exp.Expression]:
2722        if not self._match(TokenType.OFFSET):
2723            return this
2724
2725        count = self._parse_number()
2726        self._match_set((TokenType.ROW, TokenType.ROWS))
2727        return self.expression(exp.Offset, this=this, expression=count)
2728
2729    def _parse_locks(self) -> t.List[exp.Lock]:
2730        locks = []
2731        while True:
2732            if self._match_text_seq("FOR", "UPDATE"):
2733                update = True
2734            elif self._match_text_seq("FOR", "SHARE") or self._match_text_seq(
2735                "LOCK", "IN", "SHARE", "MODE"
2736            ):
2737                update = False
2738            else:
2739                break
2740
2741            expressions = None
2742            if self._match_text_seq("OF"):
2743                expressions = self._parse_csv(lambda: self._parse_table(schema=True))
2744
2745            wait: t.Optional[bool | exp.Expression] = None
2746            if self._match_text_seq("NOWAIT"):
2747                wait = True
2748            elif self._match_text_seq("WAIT"):
2749                wait = self._parse_primary()
2750            elif self._match_text_seq("SKIP", "LOCKED"):
2751                wait = False
2752
2753            locks.append(
2754                self.expression(exp.Lock, update=update, expressions=expressions, wait=wait)
2755            )
2756
2757        return locks
2758
2759    def _parse_set_operations(self, this: t.Optional[exp.Expression]) -> t.Optional[exp.Expression]:
2760        if not self._match_set(self.SET_OPERATIONS):
2761            return this
2762
2763        token_type = self._prev.token_type
2764
2765        if token_type == TokenType.UNION:
2766            expression = exp.Union
2767        elif token_type == TokenType.EXCEPT:
2768            expression = exp.Except
2769        else:
2770            expression = exp.Intersect
2771
2772        return self.expression(
2773            expression,
2774            this=this,
2775            distinct=self._match(TokenType.DISTINCT) or not self._match(TokenType.ALL),
2776            expression=self._parse_set_operations(self._parse_select(nested=True)),
2777        )
2778
2779    def _parse_expression(self) -> t.Optional[exp.Expression]:
2780        return self._parse_alias(self._parse_conjunction())
2781
2782    def _parse_conjunction(self) -> t.Optional[exp.Expression]:
2783        return self._parse_tokens(self._parse_equality, self.CONJUNCTION)
2784
2785    def _parse_equality(self) -> t.Optional[exp.Expression]:
2786        return self._parse_tokens(self._parse_comparison, self.EQUALITY)
2787
2788    def _parse_comparison(self) -> t.Optional[exp.Expression]:
2789        return self._parse_tokens(self._parse_range, self.COMPARISON)
2790
2791    def _parse_range(self) -> t.Optional[exp.Expression]:
2792        this = self._parse_bitwise()
2793        negate = self._match(TokenType.NOT)
2794
2795        if self._match_set(self.RANGE_PARSERS):
2796            expression = self.RANGE_PARSERS[self._prev.token_type](self, this)
2797            if not expression:
2798                return this
2799
2800            this = expression
2801        elif self._match(TokenType.ISNULL):
2802            this = self.expression(exp.Is, this=this, expression=exp.Null())
2803
2804        # Postgres supports ISNULL and NOTNULL for conditions.
2805        # https://blog.andreiavram.ro/postgresql-null-composite-type/
2806        if self._match(TokenType.NOTNULL):
2807            this = self.expression(exp.Is, this=this, expression=exp.Null())
2808            this = self.expression(exp.Not, this=this)
2809
2810        if negate:
2811            this = self.expression(exp.Not, this=this)
2812
2813        if self._match(TokenType.IS):
2814            this = self._parse_is(this)
2815
2816        return this
2817
2818    def _parse_is(self, this: t.Optional[exp.Expression]) -> t.Optional[exp.Expression]:
2819        index = self._index - 1
2820        negate = self._match(TokenType.NOT)
2821
2822        if self._match_text_seq("DISTINCT", "FROM"):
2823            klass = exp.NullSafeEQ if negate else exp.NullSafeNEQ
2824            return self.expression(klass, this=this, expression=self._parse_expression())
2825
2826        expression = self._parse_null() or self._parse_boolean()
2827        if not expression:
2828            self._retreat(index)
2829            return None
2830
2831        this = self.expression(exp.Is, this=this, expression=expression)
2832        return self.expression(exp.Not, this=this) if negate else this
2833
2834    def _parse_in(self, this: t.Optional[exp.Expression], alias: bool = False) -> exp.In:
2835        unnest = self._parse_unnest(with_alias=False)
2836        if unnest:
2837            this = self.expression(exp.In, this=this, unnest=unnest)
2838        elif self._match(TokenType.L_PAREN):
2839            expressions = self._parse_csv(lambda: self._parse_select_or_expression(alias=alias))
2840
2841            if len(expressions) == 1 and isinstance(expressions[0], exp.Subqueryable):
2842                this = self.expression(exp.In, this=this, query=expressions[0])
2843            else:
2844                this = self.expression(exp.In, this=this, expressions=expressions)
2845
2846            self._match_r_paren(this)
2847        else:
2848            this = self.expression(exp.In, this=this, field=self._parse_field())
2849
2850        return this
2851
2852    def _parse_between(self, this: exp.Expression) -> exp.Between:
2853        low = self._parse_bitwise()
2854        self._match(TokenType.AND)
2855        high = self._parse_bitwise()
2856        return self.expression(exp.Between, this=this, low=low, high=high)
2857
2858    def _parse_escape(self, this: t.Optional[exp.Expression]) -> t.Optional[exp.Expression]:
2859        if not self._match(TokenType.ESCAPE):
2860            return this
2861        return self.expression(exp.Escape, this=this, expression=self._parse_string())
2862
2863    def _parse_interval(self) -> t.Optional[exp.Interval]:
2864        if not self._match(TokenType.INTERVAL):
2865            return None
2866
2867        this = self._parse_primary() or self._parse_term()
2868        unit = self._parse_function() or self._parse_var()
2869
2870        # Most dialects support, e.g., the form INTERVAL '5' day, thus we try to parse
2871        # each INTERVAL expression into this canonical form so it's easy to transpile
2872        if this and this.is_number:
2873            this = exp.Literal.string(this.name)
2874        elif this and this.is_string:
2875            parts = this.name.split()
2876
2877            if len(parts) == 2:
2878                if unit:
2879                    # this is not actually a unit, it's something else
2880                    unit = None
2881                    self._retreat(self._index - 1)
2882                else:
2883                    this = exp.Literal.string(parts[0])
2884                    unit = self.expression(exp.Var, this=parts[1])
2885
2886        return self.expression(exp.Interval, this=this, unit=unit)
2887
2888    def _parse_bitwise(self) -> t.Optional[exp.Expression]:
2889        this = self._parse_term()
2890
2891        while True:
2892            if self._match_set(self.BITWISE):
2893                this = self.expression(
2894                    self.BITWISE[self._prev.token_type], this=this, expression=self._parse_term()
2895                )
2896            elif self._match_pair(TokenType.LT, TokenType.LT):
2897                this = self.expression(
2898                    exp.BitwiseLeftShift, this=this, expression=self._parse_term()
2899                )
2900            elif self._match_pair(TokenType.GT, TokenType.GT):
2901                this = self.expression(
2902                    exp.BitwiseRightShift, this=this, expression=self._parse_term()
2903                )
2904            else:
2905                break
2906
2907        return this
2908
2909    def _parse_term(self) -> t.Optional[exp.Expression]:
2910        return self._parse_tokens(self._parse_factor, self.TERM)
2911
2912    def _parse_factor(self) -> t.Optional[exp.Expression]:
2913        return self._parse_tokens(self._parse_unary, self.FACTOR)
2914
2915    def _parse_unary(self) -> t.Optional[exp.Expression]:
2916        if self._match_set(self.UNARY_PARSERS):
2917            return self.UNARY_PARSERS[self._prev.token_type](self)
2918        return self._parse_at_time_zone(self._parse_type())
2919
2920    def _parse_type(self) -> t.Optional[exp.Expression]:
2921        interval = self._parse_interval()
2922        if interval:
2923            return interval
2924
2925        index = self._index
2926        data_type = self._parse_types(check_func=True)
2927        this = self._parse_column()
2928
2929        if data_type:
2930            if isinstance(this, exp.Literal):
2931                parser = self.TYPE_LITERAL_PARSERS.get(data_type.this)
2932                if parser:
2933                    return parser(self, this, data_type)
2934                return self.expression(exp.Cast, this=this, to=data_type)
2935            if not data_type.expressions:
2936                self._retreat(index)
2937                return self._parse_column()
2938            return self._parse_column_ops(data_type)
2939
2940        return this
2941
2942    def _parse_type_size(self) -> t.Optional[exp.DataTypeSize]:
2943        this = self._parse_type()
2944        if not this:
2945            return None
2946
2947        return self.expression(
2948            exp.DataTypeSize, this=this, expression=self._parse_var(any_token=True)
2949        )
2950
2951    def _parse_types(
2952        self, check_func: bool = False, schema: bool = False
2953    ) -> t.Optional[exp.Expression]:
2954        index = self._index
2955
2956        prefix = self._match_text_seq("SYSUDTLIB", ".")
2957
2958        if not self._match_set(self.TYPE_TOKENS):
2959            return None
2960
2961        type_token = self._prev.token_type
2962
2963        if type_token == TokenType.PSEUDO_TYPE:
2964            return self.expression(exp.PseudoType, this=self._prev.text)
2965
2966        nested = type_token in self.NESTED_TYPE_TOKENS
2967        is_struct = type_token == TokenType.STRUCT
2968        expressions = None
2969        maybe_func = False
2970
2971        if self._match(TokenType.L_PAREN):
2972            if is_struct:
2973                expressions = self._parse_csv(self._parse_struct_types)
2974            elif nested:
2975                expressions = self._parse_csv(
2976                    lambda: self._parse_types(check_func=check_func, schema=schema)
2977                )
2978            elif type_token in self.ENUM_TYPE_TOKENS:
2979                expressions = self._parse_csv(self._parse_primary)
2980            else:
2981                expressions = self._parse_csv(self._parse_type_size)
2982
2983            if not expressions or not self._match(TokenType.R_PAREN):
2984                self._retreat(index)
2985                return None
2986
2987            maybe_func = True
2988
2989        if self._match_pair(TokenType.L_BRACKET, TokenType.R_BRACKET):
2990            this = exp.DataType(
2991                this=exp.DataType.Type.ARRAY,
2992                expressions=[exp.DataType.build(type_token.value, expressions=expressions)],
2993                nested=True,
2994            )
2995
2996            while self._match_pair(TokenType.L_BRACKET, TokenType.R_BRACKET):
2997                this = exp.DataType(this=exp.DataType.Type.ARRAY, expressions=[this], nested=True)
2998
2999            return this
3000
3001        if self._match(TokenType.L_BRACKET):
3002            self._retreat(index)
3003            return None
3004
3005        values: t.Optional[t.List[t.Optional[exp.Expression]]] = None
3006        if nested and self._match(TokenType.LT):
3007            if is_struct:
3008                expressions = self._parse_csv(self._parse_struct_types)
3009            else:
3010                expressions = self._parse_csv(
3011                    lambda: self._parse_types(check_func=check_func, schema=schema)
3012                )
3013
3014            if not self._match(TokenType.GT):
3015                self.raise_error("Expecting >")
3016
3017            if self._match_set((TokenType.L_BRACKET, TokenType.L_PAREN)):
3018                values = self._parse_csv(self._parse_conjunction)
3019                self._match_set((TokenType.R_BRACKET, TokenType.R_PAREN))
3020
3021        value: t.Optional[exp.Expression] = None
3022        if type_token in self.TIMESTAMPS:
3023            if self._match_text_seq("WITH", "TIME", "ZONE"):
3024                maybe_func = False
3025                value = exp.DataType(this=exp.DataType.Type.TIMESTAMPTZ, expressions=expressions)
3026            elif self._match_text_seq("WITH", "LOCAL", "TIME", "ZONE"):
3027                maybe_func = False
3028                value = exp.DataType(this=exp.DataType.Type.TIMESTAMPLTZ, expressions=expressions)
3029            elif self._match_text_seq("WITHOUT", "TIME", "ZONE"):
3030                maybe_func = False
3031        elif type_token == TokenType.INTERVAL:
3032            unit = self._parse_var()
3033
3034            if not unit:
3035                value = self.expression(exp.DataType, this=exp.DataType.Type.INTERVAL)
3036            else:
3037                value = self.expression(exp.Interval, unit=unit)
3038
3039        if maybe_func and check_func:
3040            index2 = self._index
3041            peek = self._parse_string()
3042
3043            if not peek:
3044                self._retreat(index)
3045                return None
3046
3047            self._retreat(index2)
3048
3049        if value:
3050            return value
3051
3052        return exp.DataType(
3053            this=exp.DataType.Type[type_token.value.upper()],
3054            expressions=expressions,
3055            nested=nested,
3056            values=values,
3057            prefix=prefix,
3058        )
3059
3060    def _parse_struct_types(self) -> t.Optional[exp.Expression]:
3061        this = self._parse_type() or self._parse_id_var()
3062        self._match(TokenType.COLON)
3063        return self._parse_column_def(this)
3064
3065    def _parse_at_time_zone(self, this: t.Optional[exp.Expression]) -> t.Optional[exp.Expression]:
3066        if not self._match_text_seq("AT", "TIME", "ZONE"):
3067            return this
3068        return self.expression(exp.AtTimeZone, this=this, zone=self._parse_unary())
3069
3070    def _parse_column(self) -> t.Optional[exp.Expression]:
3071        this = self._parse_field()
3072        if isinstance(this, exp.Identifier):
3073            this = self.expression(exp.Column, this=this)
3074        elif not this:
3075            return self._parse_bracket(this)
3076        return self._parse_column_ops(this)
3077
3078    def _parse_column_ops(self, this: t.Optional[exp.Expression]) -> t.Optional[exp.Expression]:
3079        this = self._parse_bracket(this)
3080
3081        while self._match_set(self.COLUMN_OPERATORS):
3082            op_token = self._prev.token_type
3083            op = self.COLUMN_OPERATORS.get(op_token)
3084
3085            if op_token == TokenType.DCOLON:
3086                field = self._parse_types()
3087                if not field:
3088                    self.raise_error("Expected type")
3089            elif op and self._curr:
3090                self._advance()
3091                value = self._prev.text
3092                field = (
3093                    exp.Literal.number(value)
3094                    if self._prev.token_type == TokenType.NUMBER
3095                    else exp.Literal.string(value)
3096                )
3097            else:
3098                field = self._parse_field(anonymous_func=True, any_token=True)
3099
3100            if isinstance(field, exp.Func):
3101                # bigquery allows function calls like x.y.count(...)
3102                # SAFE.SUBSTR(...)
3103                # https://cloud.google.com/bigquery/docs/reference/standard-sql/functions-reference#function_call_rules
3104                this = self._replace_columns_with_dots(this)
3105
3106            if op:
3107                this = op(self, this, field)
3108            elif isinstance(this, exp.Column) and not this.args.get("catalog"):
3109                this = self.expression(
3110                    exp.Column,
3111                    this=field,
3112                    table=this.this,
3113                    db=this.args.get("table"),
3114                    catalog=this.args.get("db"),
3115                )
3116            else:
3117                this = self.expression(exp.Dot, this=this, expression=field)
3118            this = self._parse_bracket(this)
3119        return this
3120
3121    def _parse_primary(self) -> t.Optional[exp.Expression]:
3122        if self._match_set(self.PRIMARY_PARSERS):
3123            token_type = self._prev.token_type
3124            primary = self.PRIMARY_PARSERS[token_type](self, self._prev)
3125
3126            if token_type == TokenType.STRING:
3127                expressions = [primary]
3128                while self._match(TokenType.STRING):
3129                    expressions.append(exp.Literal.string(self._prev.text))
3130
3131                if len(expressions) > 1:
3132                    return self.expression(exp.Concat, expressions=expressions)
3133
3134            return primary
3135
3136        if self._match_pair(TokenType.DOT, TokenType.NUMBER):
3137            return exp.Literal.number(f"0.{self._prev.text}")
3138
3139        if self._match(TokenType.L_PAREN):
3140            comments = self._prev_comments
3141            query = self._parse_select()
3142
3143            if query:
3144                expressions = [query]
3145            else:
3146                expressions = self._parse_csv(self._parse_expression)
3147
3148            this = self._parse_query_modifiers(seq_get(expressions, 0))
3149
3150            if isinstance(this, exp.Subqueryable):
3151                this = self._parse_set_operations(
3152                    self._parse_subquery(this=this, parse_alias=False)
3153                )
3154            elif len(expressions) > 1:
3155                this = self.expression(exp.Tuple, expressions=expressions)
3156            else:
3157                this = self.expression(exp.Paren, this=self._parse_set_operations(this))
3158
3159            if this:
3160                this.add_comments(comments)
3161
3162            self._match_r_paren(expression=this)
3163            return this
3164
3165        return None
3166
3167    def _parse_field(
3168        self,
3169        any_token: bool = False,
3170        tokens: t.Optional[t.Collection[TokenType]] = None,
3171        anonymous_func: bool = False,
3172    ) -> t.Optional[exp.Expression]:
3173        return (
3174            self._parse_primary()
3175            or self._parse_function(anonymous=anonymous_func)
3176            or self._parse_id_var(any_token=any_token, tokens=tokens)
3177        )
3178
3179    def _parse_function(
3180        self,
3181        functions: t.Optional[t.Dict[str, t.Callable]] = None,
3182        anonymous: bool = False,
3183        optional_parens: bool = True,
3184    ) -> t.Optional[exp.Expression]:
3185        if not self._curr:
3186            return None
3187
3188        token_type = self._curr.token_type
3189
3190        if optional_parens and self._match_set(self.NO_PAREN_FUNCTION_PARSERS):
3191            return self.NO_PAREN_FUNCTION_PARSERS[token_type](self)
3192
3193        if not self._next or self._next.token_type != TokenType.L_PAREN:
3194            if optional_parens and token_type in self.NO_PAREN_FUNCTIONS:
3195                self._advance()
3196                return self.expression(self.NO_PAREN_FUNCTIONS[token_type])
3197
3198            return None
3199
3200        if token_type not in self.FUNC_TOKENS:
3201            return None
3202
3203        this = self._curr.text
3204        upper = this.upper()
3205        self._advance(2)
3206
3207        parser = self.FUNCTION_PARSERS.get(upper)
3208
3209        if parser and not anonymous:
3210            this = parser(self)
3211        else:
3212            subquery_predicate = self.SUBQUERY_PREDICATES.get(token_type)
3213
3214            if subquery_predicate and self._curr.token_type in (TokenType.SELECT, TokenType.WITH):
3215                this = self.expression(subquery_predicate, this=self._parse_select())
3216                self._match_r_paren()
3217                return this
3218
3219            if functions is None:
3220                functions = self.FUNCTIONS
3221
3222            function = functions.get(upper)
3223
3224            alias = upper in self.FUNCTIONS_WITH_ALIASED_ARGS
3225            args = self._parse_csv(lambda: self._parse_lambda(alias=alias))
3226
3227            if function and not anonymous:
3228                this = self.validate_expression(function(args), args)
3229            else:
3230                this = self.expression(exp.Anonymous, this=this, expressions=args)
3231
3232        self._match_r_paren(this)
3233        return self._parse_window(this)
3234
3235    def _parse_function_parameter(self) -> t.Optional[exp.Expression]:
3236        return self._parse_column_def(self._parse_id_var())
3237
3238    def _parse_user_defined_function(
3239        self, kind: t.Optional[TokenType] = None
3240    ) -> t.Optional[exp.Expression]:
3241        this = self._parse_id_var()
3242
3243        while self._match(TokenType.DOT):
3244            this = self.expression(exp.Dot, this=this, expression=self._parse_id_var())
3245
3246        if not self._match(TokenType.L_PAREN):
3247            return this
3248
3249        expressions = self._parse_csv(self._parse_function_parameter)
3250        self._match_r_paren()
3251        return self.expression(
3252            exp.UserDefinedFunction, this=this, expressions=expressions, wrapped=True
3253        )
3254
3255    def _parse_introducer(self, token: Token) -> exp.Introducer | exp.Identifier:
3256        literal = self._parse_primary()
3257        if literal:
3258            return self.expression(exp.Introducer, this=token.text, expression=literal)
3259
3260        return self.expression(exp.Identifier, this=token.text)
3261
3262    def _parse_session_parameter(self) -> exp.SessionParameter:
3263        kind = None
3264        this = self._parse_id_var() or self._parse_primary()
3265
3266        if this and self._match(TokenType.DOT):
3267            kind = this.name
3268            this = self._parse_var() or self._parse_primary()
3269
3270        return self.expression(exp.SessionParameter, this=this, kind=kind)
3271
3272    def _parse_lambda(self, alias: bool = False) -> t.Optional[exp.Expression]:
3273        index = self._index
3274
3275        if self._match(TokenType.L_PAREN):
3276            expressions = self._parse_csv(self._parse_id_var)
3277
3278            if not self._match(TokenType.R_PAREN):
3279                self._retreat(index)
3280        else:
3281            expressions = [self._parse_id_var()]
3282
3283        if self._match_set(self.LAMBDAS):
3284            return self.LAMBDAS[self._prev.token_type](self, expressions)
3285
3286        self._retreat(index)
3287
3288        this: t.Optional[exp.Expression]
3289
3290        if self._match(TokenType.DISTINCT):
3291            this = self.expression(
3292                exp.Distinct, expressions=self._parse_csv(self._parse_conjunction)
3293            )
3294        else:
3295            this = self._parse_select_or_expression(alias=alias)
3296
3297            if isinstance(this, exp.EQ):
3298                left = this.this
3299                if isinstance(left, exp.Column):
3300                    left.replace(exp.var(left.text("this")))
3301
3302        return self._parse_limit(self._parse_order(self._parse_respect_or_ignore_nulls(this)))
3303
3304    def _parse_schema(self, this: t.Optional[exp.Expression] = None) -> t.Optional[exp.Expression]:
3305        index = self._index
3306
3307        if not self.errors:
3308            try:
3309                if self._parse_select(nested=True):
3310                    return this
3311            except ParseError:
3312                pass
3313            finally:
3314                self.errors.clear()
3315                self._retreat(index)
3316
3317        if not self._match(TokenType.L_PAREN):
3318            return this
3319
3320        args = self._parse_csv(
3321            lambda: self._parse_constraint()
3322            or self._parse_column_def(self._parse_field(any_token=True))
3323        )
3324
3325        self._match_r_paren()
3326        return self.expression(exp.Schema, this=this, expressions=args)
3327
3328    def _parse_column_def(self, this: t.Optional[exp.Expression]) -> t.Optional[exp.Expression]:
3329        # column defs are not really columns, they're identifiers
3330        if isinstance(this, exp.Column):
3331            this = this.this
3332
3333        kind = self._parse_types(schema=True)
3334
3335        if self._match_text_seq("FOR", "ORDINALITY"):
3336            return self.expression(exp.ColumnDef, this=this, ordinality=True)
3337
3338        constraints = []
3339        while True:
3340            constraint = self._parse_column_constraint()
3341            if not constraint:
3342                break
3343            constraints.append(constraint)
3344
3345        if not kind and not constraints:
3346            return this
3347
3348        return self.expression(exp.ColumnDef, this=this, kind=kind, constraints=constraints)
3349
3350    def _parse_auto_increment(
3351        self,
3352    ) -> exp.GeneratedAsIdentityColumnConstraint | exp.AutoIncrementColumnConstraint:
3353        start = None
3354        increment = None
3355
3356        if self._match(TokenType.L_PAREN, advance=False):
3357            args = self._parse_wrapped_csv(self._parse_bitwise)
3358            start = seq_get(args, 0)
3359            increment = seq_get(args, 1)
3360        elif self._match_text_seq("START"):
3361            start = self._parse_bitwise()
3362            self._match_text_seq("INCREMENT")
3363            increment = self._parse_bitwise()
3364
3365        if start and increment:
3366            return exp.GeneratedAsIdentityColumnConstraint(start=start, increment=increment)
3367
3368        return exp.AutoIncrementColumnConstraint()
3369
3370    def _parse_compress(self) -> exp.CompressColumnConstraint:
3371        if self._match(TokenType.L_PAREN, advance=False):
3372            return self.expression(
3373                exp.CompressColumnConstraint, this=self._parse_wrapped_csv(self._parse_bitwise)
3374            )
3375
3376        return self.expression(exp.CompressColumnConstraint, this=self._parse_bitwise())
3377
3378    def _parse_generated_as_identity(self) -> exp.GeneratedAsIdentityColumnConstraint:
3379        if self._match_text_seq("BY", "DEFAULT"):
3380            on_null = self._match_pair(TokenType.ON, TokenType.NULL)
3381            this = self.expression(
3382                exp.GeneratedAsIdentityColumnConstraint, this=False, on_null=on_null
3383            )
3384        else:
3385            self._match_text_seq("ALWAYS")
3386            this = self.expression(exp.GeneratedAsIdentityColumnConstraint, this=True)
3387
3388        self._match(TokenType.ALIAS)
3389        identity = self._match_text_seq("IDENTITY")
3390
3391        if self._match(TokenType.L_PAREN):
3392            if self._match_text_seq("START", "WITH"):
3393                this.set("start", self._parse_bitwise())
3394            if self._match_text_seq("INCREMENT", "BY"):
3395                this.set("increment", self._parse_bitwise())
3396            if self._match_text_seq("MINVALUE"):
3397                this.set("minvalue", self._parse_bitwise())
3398            if self._match_text_seq("MAXVALUE"):
3399                this.set("maxvalue", self._parse_bitwise())
3400
3401            if self._match_text_seq("CYCLE"):
3402                this.set("cycle", True)
3403            elif self._match_text_seq("NO", "CYCLE"):
3404                this.set("cycle", False)
3405
3406            if not identity:
3407                this.set("expression", self._parse_bitwise())
3408
3409            self._match_r_paren()
3410
3411        return this
3412
3413    def _parse_inline(self) -> exp.InlineLengthColumnConstraint:
3414        self._match_text_seq("LENGTH")
3415        return self.expression(exp.InlineLengthColumnConstraint, this=self._parse_bitwise())
3416
3417    def _parse_not_constraint(
3418        self,
3419    ) -> t.Optional[exp.NotNullColumnConstraint | exp.CaseSpecificColumnConstraint]:
3420        if self._match_text_seq("NULL"):
3421            return self.expression(exp.NotNullColumnConstraint)
3422        if self._match_text_seq("CASESPECIFIC"):
3423            return self.expression(exp.CaseSpecificColumnConstraint, not_=True)
3424        return None
3425
3426    def _parse_column_constraint(self) -> t.Optional[exp.Expression]:
3427        if self._match(TokenType.CONSTRAINT):
3428            this = self._parse_id_var()
3429        else:
3430            this = None
3431
3432        if self._match_texts(self.CONSTRAINT_PARSERS):
3433            return self.expression(
3434                exp.ColumnConstraint,
3435                this=this,
3436                kind=self.CONSTRAINT_PARSERS[self._prev.text.upper()](self),
3437            )
3438
3439        return this
3440
3441    def _parse_constraint(self) -> t.Optional[exp.Expression]:
3442        if not self._match(TokenType.CONSTRAINT):
3443            return self._parse_unnamed_constraint(constraints=self.SCHEMA_UNNAMED_CONSTRAINTS)
3444
3445        this = self._parse_id_var()
3446        expressions = []
3447
3448        while True:
3449            constraint = self._parse_unnamed_constraint() or self._parse_function()
3450            if not constraint:
3451                break
3452            expressions.append(constraint)
3453
3454        return self.expression(exp.Constraint, this=this, expressions=expressions)
3455
3456    def _parse_unnamed_constraint(
3457        self, constraints: t.Optional[t.Collection[str]] = None
3458    ) -> t.Optional[exp.Expression]:
3459        if not self._match_texts(constraints or self.CONSTRAINT_PARSERS):
3460            return None
3461
3462        constraint = self._prev.text.upper()
3463        if constraint not in self.CONSTRAINT_PARSERS:
3464            self.raise_error(f"No parser found for schema constraint {constraint}.")
3465
3466        return self.CONSTRAINT_PARSERS[constraint](self)
3467
3468    def _parse_unique(self) -> exp.UniqueColumnConstraint:
3469        self._match_text_seq("KEY")
3470        return self.expression(
3471            exp.UniqueColumnConstraint, this=self._parse_schema(self._parse_id_var(any_token=False))
3472        )
3473
3474    def _parse_key_constraint_options(self) -> t.List[str]:
3475        options = []
3476        while True:
3477            if not self._curr:
3478                break
3479
3480            if self._match(TokenType.ON):
3481                action = None
3482                on = self._advance_any() and self._prev.text
3483
3484                if self._match_text_seq("NO", "ACTION"):
3485                    action = "NO ACTION"
3486                elif self._match_text_seq("CASCADE"):
3487                    action = "CASCADE"
3488                elif self._match_pair(TokenType.SET, TokenType.NULL):
3489                    action = "SET NULL"
3490                elif self._match_pair(TokenType.SET, TokenType.DEFAULT):
3491                    action = "SET DEFAULT"
3492                else:
3493                    self.raise_error("Invalid key constraint")
3494
3495                options.append(f"ON {on} {action}")
3496            elif self._match_text_seq("NOT", "ENFORCED"):
3497                options.append("NOT ENFORCED")
3498            elif self._match_text_seq("DEFERRABLE"):
3499                options.append("DEFERRABLE")
3500            elif self._match_text_seq("INITIALLY", "DEFERRED"):
3501                options.append("INITIALLY DEFERRED")
3502            elif self._match_text_seq("NORELY"):
3503                options.append("NORELY")
3504            elif self._match_text_seq("MATCH", "FULL"):
3505                options.append("MATCH FULL")
3506            else:
3507                break
3508
3509        return options
3510
3511    def _parse_references(self, match: bool = True) -> t.Optional[exp.Reference]:
3512        if match and not self._match(TokenType.REFERENCES):
3513            return None
3514
3515        expressions = None
3516        this = self._parse_id_var()
3517
3518        if self._match(TokenType.L_PAREN, advance=False):
3519            expressions = self._parse_wrapped_id_vars()
3520
3521        options = self._parse_key_constraint_options()
3522        return self.expression(exp.Reference, this=this, expressions=expressions, options=options)
3523
3524    def _parse_foreign_key(self) -> exp.ForeignKey:
3525        expressions = self._parse_wrapped_id_vars()
3526        reference = self._parse_references()
3527        options = {}
3528
3529        while self._match(TokenType.ON):
3530            if not self._match_set((TokenType.DELETE, TokenType.UPDATE)):
3531                self.raise_error("Expected DELETE or UPDATE")
3532
3533            kind = self._prev.text.lower()
3534
3535            if self._match_text_seq("NO", "ACTION"):
3536                action = "NO ACTION"
3537            elif self._match(TokenType.SET):
3538                self._match_set((TokenType.NULL, TokenType.DEFAULT))
3539                action = "SET " + self._prev.text.upper()
3540            else:
3541                self._advance()
3542                action = self._prev.text.upper()
3543
3544            options[kind] = action
3545
3546        return self.expression(
3547            exp.ForeignKey, expressions=expressions, reference=reference, **options  # type: ignore
3548        )
3549
3550    def _parse_primary_key(
3551        self, wrapped_optional: bool = False, in_props: bool = False
3552    ) -> exp.PrimaryKeyColumnConstraint | exp.PrimaryKey:
3553        desc = (
3554            self._match_set((TokenType.ASC, TokenType.DESC))
3555            and self._prev.token_type == TokenType.DESC
3556        )
3557
3558        if not in_props and not self._match(TokenType.L_PAREN, advance=False):
3559            return self.expression(exp.PrimaryKeyColumnConstraint, desc=desc)
3560
3561        expressions = self._parse_wrapped_csv(self._parse_field, optional=wrapped_optional)
3562        options = self._parse_key_constraint_options()
3563        return self.expression(exp.PrimaryKey, expressions=expressions, options=options)
3564
3565    def _parse_bracket(self, this: t.Optional[exp.Expression]) -> t.Optional[exp.Expression]:
3566        if not self._match_set((TokenType.L_BRACKET, TokenType.L_BRACE)):
3567            return this
3568
3569        bracket_kind = self._prev.token_type
3570
3571        if self._match(TokenType.COLON):
3572            expressions: t.List[t.Optional[exp.Expression]] = [
3573                self.expression(exp.Slice, expression=self._parse_conjunction())
3574            ]
3575        else:
3576            expressions = self._parse_csv(lambda: self._parse_slice(self._parse_conjunction()))
3577
3578        # https://duckdb.org/docs/sql/data_types/struct.html#creating-structs
3579        if bracket_kind == TokenType.L_BRACE:
3580            this = self.expression(exp.Struct, expressions=expressions)
3581        elif not this or this.name.upper() == "ARRAY":
3582            this = self.expression(exp.Array, expressions=expressions)
3583        else:
3584            expressions = apply_index_offset(this, expressions, -self.INDEX_OFFSET)
3585            this = self.expression(exp.Bracket, this=this, expressions=expressions)
3586
3587        if not self._match(TokenType.R_BRACKET) and bracket_kind == TokenType.L_BRACKET:
3588            self.raise_error("Expected ]")
3589        elif not self._match(TokenType.R_BRACE) and bracket_kind == TokenType.L_BRACE:
3590            self.raise_error("Expected }")
3591
3592        self._add_comments(this)
3593        return self._parse_bracket(this)
3594
3595    def _parse_slice(self, this: t.Optional[exp.Expression]) -> t.Optional[exp.Expression]:
3596        if self._match(TokenType.COLON):
3597            return self.expression(exp.Slice, this=this, expression=self._parse_conjunction())
3598        return this
3599
3600    def _parse_case(self) -> t.Optional[exp.Expression]:
3601        ifs = []
3602        default = None
3603
3604        expression = self._parse_conjunction()
3605
3606        while self._match(TokenType.WHEN):
3607            this = self._parse_conjunction()
3608            self._match(TokenType.THEN)
3609            then = self._parse_conjunction()
3610            ifs.append(self.expression(exp.If, this=this, true=then))
3611
3612        if self._match(TokenType.ELSE):
3613            default = self._parse_conjunction()
3614
3615        if not self._match(TokenType.END):
3616            self.raise_error("Expected END after CASE", self._prev)
3617
3618        return self._parse_window(
3619            self.expression(exp.Case, this=expression, ifs=ifs, default=default)
3620        )
3621
3622    def _parse_if(self) -> t.Optional[exp.Expression]:
3623        if self._match(TokenType.L_PAREN):
3624            args = self._parse_csv(self._parse_conjunction)
3625            this = self.validate_expression(exp.If.from_arg_list(args), args)
3626            self._match_r_paren()
3627        else:
3628            index = self._index - 1
3629            condition = self._parse_conjunction()
3630
3631            if not condition:
3632                self._retreat(index)
3633                return None
3634
3635            self._match(TokenType.THEN)
3636            true = self._parse_conjunction()
3637            false = self._parse_conjunction() if self._match(TokenType.ELSE) else None
3638            self._match(TokenType.END)
3639            this = self.expression(exp.If, this=condition, true=true, false=false)
3640
3641        return self._parse_window(this)
3642
3643    def _parse_extract(self) -> exp.Extract:
3644        this = self._parse_function() or self._parse_var() or self._parse_type()
3645
3646        if self._match(TokenType.FROM):
3647            return self.expression(exp.Extract, this=this, expression=self._parse_bitwise())
3648
3649        if not self._match(TokenType.COMMA):
3650            self.raise_error("Expected FROM or comma after EXTRACT", self._prev)
3651
3652        return self.expression(exp.Extract, this=this, expression=self._parse_bitwise())
3653
3654    def _parse_cast(self, strict: bool) -> exp.Expression:
3655        this = self._parse_conjunction()
3656
3657        if not self._match(TokenType.ALIAS):
3658            if self._match(TokenType.COMMA):
3659                return self.expression(
3660                    exp.CastToStrType, this=this, expression=self._parse_string()
3661                )
3662            else:
3663                self.raise_error("Expected AS after CAST")
3664
3665        to = self._parse_types()
3666
3667        if not to:
3668            self.raise_error("Expected TYPE after CAST")
3669        elif to.this == exp.DataType.Type.CHAR:
3670            if self._match(TokenType.CHARACTER_SET):
3671                to = self.expression(exp.CharacterSet, this=self._parse_var_or_string())
3672        elif to.this in exp.DataType.TEMPORAL_TYPES and self._match(TokenType.FORMAT):
3673            fmt = self._parse_string()
3674
3675            return self.expression(
3676                exp.StrToDate if to.this == exp.DataType.Type.DATE else exp.StrToTime,
3677                this=this,
3678                format=exp.Literal.string(
3679                    format_time(
3680                        fmt.this if fmt else "",
3681                        self.FORMAT_MAPPING or self.TIME_MAPPING,
3682                        self.FORMAT_TRIE or self.TIME_TRIE,
3683                    )
3684                ),
3685            )
3686
3687        return self.expression(exp.Cast if strict else exp.TryCast, this=this, to=to)
3688
3689    def _parse_concat(self) -> t.Optional[exp.Expression]:
3690        args = self._parse_csv(self._parse_conjunction)
3691        if self.CONCAT_NULL_OUTPUTS_STRING:
3692            args = [
3693                exp.func("COALESCE", exp.cast(arg, "text"), exp.Literal.string(""))
3694                for arg in args
3695                if arg
3696            ]
3697
3698        # Some dialects (e.g. Trino) don't allow a single-argument CONCAT call, so when
3699        # we find such a call we replace it with its argument.
3700        if len(args) == 1:
3701            return args[0]
3702
3703        return self.expression(
3704            exp.Concat if self.STRICT_STRING_CONCAT else exp.SafeConcat, expressions=args
3705        )
3706
3707    def _parse_string_agg(self) -> exp.Expression:
3708        expression: t.Optional[exp.Expression]
3709
3710        if self._match(TokenType.DISTINCT):
3711            args = self._parse_csv(self._parse_conjunction)
3712            expression = self.expression(exp.Distinct, expressions=[seq_get(args, 0)])
3713        else:
3714            args = self._parse_csv(self._parse_conjunction)
3715            expression = seq_get(args, 0)
3716
3717        index = self._index
3718        if not self._match(TokenType.R_PAREN):
3719            # postgres: STRING_AGG([DISTINCT] expression, separator [ORDER BY expression1 {ASC | DESC} [, ...]])
3720            order = self._parse_order(this=expression)
3721            return self.expression(exp.GroupConcat, this=order, separator=seq_get(args, 1))
3722
3723        # Checks if we can parse an order clause: WITHIN GROUP (ORDER BY <order_by_expression_list> [ASC | DESC]).
3724        # This is done "manually", instead of letting _parse_window parse it into an exp.WithinGroup node, so that
3725        # the STRING_AGG call is parsed like in MySQL / SQLite and can thus be transpiled more easily to them.
3726        if not self._match_text_seq("WITHIN", "GROUP"):
3727            self._retreat(index)
3728            return self.validate_expression(exp.GroupConcat.from_arg_list(args), args)
3729
3730        self._match_l_paren()  # The corresponding match_r_paren will be called in parse_function (caller)
3731        order = self._parse_order(this=expression)
3732        return self.expression(exp.GroupConcat, this=order, separator=seq_get(args, 1))
3733
3734    def _parse_convert(self, strict: bool) -> t.Optional[exp.Expression]:
3735        to: t.Optional[exp.Expression]
3736        this = self._parse_bitwise()
3737
3738        if self._match(TokenType.USING):
3739            to = self.expression(exp.CharacterSet, this=self._parse_var())
3740        elif self._match(TokenType.COMMA):
3741            to = self._parse_bitwise()
3742        else:
3743            to = None
3744
3745        # Swap the argument order if needed to produce the correct AST
3746        if self.CONVERT_TYPE_FIRST:
3747            this, to = to, this
3748
3749        return self.expression(exp.Cast if strict else exp.TryCast, this=this, to=to)
3750
3751    def _parse_decode(self) -> t.Optional[exp.Decode | exp.Case]:
3752        """
3753        There are generally two variants of the DECODE function:
3754
3755        - DECODE(bin, charset)
3756        - DECODE(expression, search, result [, search, result] ... [, default])
3757
3758        The second variant will always be parsed into a CASE expression. Note that NULL
3759        needs special treatment, since we need to explicitly check for it with `IS NULL`,
3760        instead of relying on pattern matching.
3761        """
3762        args = self._parse_csv(self._parse_conjunction)
3763
3764        if len(args) < 3:
3765            return self.expression(exp.Decode, this=seq_get(args, 0), charset=seq_get(args, 1))
3766
3767        expression, *expressions = args
3768        if not expression:
3769            return None
3770
3771        ifs = []
3772        for search, result in zip(expressions[::2], expressions[1::2]):
3773            if not search or not result:
3774                return None
3775
3776            if isinstance(search, exp.Literal):
3777                ifs.append(
3778                    exp.If(this=exp.EQ(this=expression.copy(), expression=search), true=result)
3779                )
3780            elif isinstance(search, exp.Null):
3781                ifs.append(
3782                    exp.If(this=exp.Is(this=expression.copy(), expression=exp.Null()), true=result)
3783                )
3784            else:
3785                cond = exp.or_(
3786                    exp.EQ(this=expression.copy(), expression=search),
3787                    exp.and_(
3788                        exp.Is(this=expression.copy(), expression=exp.Null()),
3789                        exp.Is(this=search.copy(), expression=exp.Null()),
3790                        copy=False,
3791                    ),
3792                    copy=False,
3793                )
3794                ifs.append(exp.If(this=cond, true=result))
3795
3796        return exp.Case(ifs=ifs, default=expressions[-1] if len(expressions) % 2 == 1 else None)
3797
3798    def _parse_json_key_value(self) -> t.Optional[exp.JSONKeyValue]:
3799        self._match_text_seq("KEY")
3800        key = self._parse_field()
3801        self._match(TokenType.COLON)
3802        self._match_text_seq("VALUE")
3803        value = self._parse_field()
3804
3805        if not key and not value:
3806            return None
3807        return self.expression(exp.JSONKeyValue, this=key, expression=value)
3808
3809    def _parse_json_object(self) -> exp.JSONObject:
3810        star = self._parse_star()
3811        expressions = [star] if star else self._parse_csv(self._parse_json_key_value)
3812
3813        null_handling = None
3814        if self._match_text_seq("NULL", "ON", "NULL"):
3815            null_handling = "NULL ON NULL"
3816        elif self._match_text_seq("ABSENT", "ON", "NULL"):
3817            null_handling = "ABSENT ON NULL"
3818
3819        unique_keys = None
3820        if self._match_text_seq("WITH", "UNIQUE"):
3821            unique_keys = True
3822        elif self._match_text_seq("WITHOUT", "UNIQUE"):
3823            unique_keys = False
3824
3825        self._match_text_seq("KEYS")
3826
3827        return_type = self._match_text_seq("RETURNING") and self._parse_type()
3828        format_json = self._match_text_seq("FORMAT", "JSON")
3829        encoding = self._match_text_seq("ENCODING") and self._parse_var()
3830
3831        return self.expression(
3832            exp.JSONObject,
3833            expressions=expressions,
3834            null_handling=null_handling,
3835            unique_keys=unique_keys,
3836            return_type=return_type,
3837            format_json=format_json,
3838            encoding=encoding,
3839        )
3840
3841    def _parse_logarithm(self) -> exp.Func:
3842        # Default argument order is base, expression
3843        args = self._parse_csv(self._parse_range)
3844
3845        if len(args) > 1:
3846            if not self.LOG_BASE_FIRST:
3847                args.reverse()
3848            return exp.Log.from_arg_list(args)
3849
3850        return self.expression(
3851            exp.Ln if self.LOG_DEFAULTS_TO_LN else exp.Log, this=seq_get(args, 0)
3852        )
3853
3854    def _parse_match_against(self) -> exp.MatchAgainst:
3855        expressions = self._parse_csv(self._parse_column)
3856
3857        self._match_text_seq(")", "AGAINST", "(")
3858
3859        this = self._parse_string()
3860
3861        if self._match_text_seq("IN", "NATURAL", "LANGUAGE", "MODE"):
3862            modifier = "IN NATURAL LANGUAGE MODE"
3863            if self._match_text_seq("WITH", "QUERY", "EXPANSION"):
3864                modifier = f"{modifier} WITH QUERY EXPANSION"
3865        elif self._match_text_seq("IN", "BOOLEAN", "MODE"):
3866            modifier = "IN BOOLEAN MODE"
3867        elif self._match_text_seq("WITH", "QUERY", "EXPANSION"):
3868            modifier = "WITH QUERY EXPANSION"
3869        else:
3870            modifier = None
3871
3872        return self.expression(
3873            exp.MatchAgainst, this=this, expressions=expressions, modifier=modifier
3874        )
3875
3876    # https://learn.microsoft.com/en-us/sql/t-sql/functions/openjson-transact-sql?view=sql-server-ver16
3877    def _parse_open_json(self) -> exp.OpenJSON:
3878        this = self._parse_bitwise()
3879        path = self._match(TokenType.COMMA) and self._parse_string()
3880
3881        def _parse_open_json_column_def() -> exp.OpenJSONColumnDef:
3882            this = self._parse_field(any_token=True)
3883            kind = self._parse_types()
3884            path = self._parse_string()
3885            as_json = self._match_pair(TokenType.ALIAS, TokenType.JSON)
3886
3887            return self.expression(
3888                exp.OpenJSONColumnDef, this=this, kind=kind, path=path, as_json=as_json
3889            )
3890
3891        expressions = None
3892        if self._match_pair(TokenType.R_PAREN, TokenType.WITH):
3893            self._match_l_paren()
3894            expressions = self._parse_csv(_parse_open_json_column_def)
3895
3896        return self.expression(exp.OpenJSON, this=this, path=path, expressions=expressions)
3897
3898    def _parse_position(self, haystack_first: bool = False) -> exp.StrPosition:
3899        args = self._parse_csv(self._parse_bitwise)
3900
3901        if self._match(TokenType.IN):
3902            return self.expression(
3903                exp.StrPosition, this=self._parse_bitwise(), substr=seq_get(args, 0)
3904            )
3905
3906        if haystack_first:
3907            haystack = seq_get(args, 0)
3908            needle = seq_get(args, 1)
3909        else:
3910            needle = seq_get(args, 0)
3911            haystack = seq_get(args, 1)
3912
3913        return self.expression(
3914            exp.StrPosition, this=haystack, substr=needle, position=seq_get(args, 2)
3915        )
3916
3917    def _parse_join_hint(self, func_name: str) -> exp.JoinHint:
3918        args = self._parse_csv(self._parse_table)
3919        return exp.JoinHint(this=func_name.upper(), expressions=args)
3920
3921    def _parse_substring(self) -> exp.Substring:
3922        # Postgres supports the form: substring(string [from int] [for int])
3923        # https://www.postgresql.org/docs/9.1/functions-string.html @ Table 9-6
3924
3925        args = self._parse_csv(self._parse_bitwise)
3926
3927        if self._match(TokenType.FROM):
3928            args.append(self._parse_bitwise())
3929            if self._match(TokenType.FOR):
3930                args.append(self._parse_bitwise())
3931
3932        return self.validate_expression(exp.Substring.from_arg_list(args), args)
3933
3934    def _parse_trim(self) -> exp.Trim:
3935        # https://www.w3resource.com/sql/character-functions/trim.php
3936        # https://docs.oracle.com/javadb/10.8.3.0/ref/rreftrimfunc.html
3937
3938        position = None
3939        collation = None
3940
3941        if self._match_texts(self.TRIM_TYPES):
3942            position = self._prev.text.upper()
3943
3944        expression = self._parse_bitwise()
3945        if self._match_set((TokenType.FROM, TokenType.COMMA)):
3946            this = self._parse_bitwise()
3947        else:
3948            this = expression
3949            expression = None
3950
3951        if self._match(TokenType.COLLATE):
3952            collation = self._parse_bitwise()
3953
3954        return self.expression(
3955            exp.Trim, this=this, position=position, expression=expression, collation=collation
3956        )
3957
3958    def _parse_window_clause(self) -> t.Optional[t.List[t.Optional[exp.Expression]]]:
3959        return self._match(TokenType.WINDOW) and self._parse_csv(self._parse_named_window)
3960
3961    def _parse_named_window(self) -> t.Optional[exp.Expression]:
3962        return self._parse_window(self._parse_id_var(), alias=True)
3963
3964    def _parse_respect_or_ignore_nulls(
3965        self, this: t.Optional[exp.Expression]
3966    ) -> t.Optional[exp.Expression]:
3967        if self._match_text_seq("IGNORE", "NULLS"):
3968            return self.expression(exp.IgnoreNulls, this=this)
3969        if self._match_text_seq("RESPECT", "NULLS"):
3970            return self.expression(exp.RespectNulls, this=this)
3971        return this
3972
3973    def _parse_window(
3974        self, this: t.Optional[exp.Expression], alias: bool = False
3975    ) -> t.Optional[exp.Expression]:
3976        if self._match_pair(TokenType.FILTER, TokenType.L_PAREN):
3977            this = self.expression(exp.Filter, this=this, expression=self._parse_where())
3978            self._match_r_paren()
3979
3980        # T-SQL allows the OVER (...) syntax after WITHIN GROUP.
3981        # https://learn.microsoft.com/en-us/sql/t-sql/functions/percentile-disc-transact-sql?view=sql-server-ver16
3982        if self._match_text_seq("WITHIN", "GROUP"):
3983            order = self._parse_wrapped(self._parse_order)
3984            this = self.expression(exp.WithinGroup, this=this, expression=order)
3985
3986        # SQL spec defines an optional [ { IGNORE | RESPECT } NULLS ] OVER
3987        # Some dialects choose to implement and some do not.
3988        # https://dev.mysql.com/doc/refman/8.0/en/window-function-descriptions.html
3989
3990        # There is some code above in _parse_lambda that handles
3991        #   SELECT FIRST_VALUE(TABLE.COLUMN IGNORE|RESPECT NULLS) OVER ...
3992
3993        # The below changes handle
3994        #   SELECT FIRST_VALUE(TABLE.COLUMN) IGNORE|RESPECT NULLS OVER ...
3995
3996        # Oracle allows both formats
3997        #   (https://docs.oracle.com/en/database/oracle/oracle-database/19/sqlrf/img_text/first_value.html)
3998        #   and Snowflake chose to do the same for familiarity
3999        #   https://docs.snowflake.com/en/sql-reference/functions/first_value.html#usage-notes
4000        this = self._parse_respect_or_ignore_nulls(this)
4001
4002        # bigquery select from window x AS (partition by ...)
4003        if alias:
4004            over = None
4005            self._match(TokenType.ALIAS)
4006        elif not self._match_set(self.WINDOW_BEFORE_PAREN_TOKENS):
4007            return this
4008        else:
4009            over = self._prev.text.upper()
4010
4011        if not self._match(TokenType.L_PAREN):
4012            return self.expression(
4013                exp.Window, this=this, alias=self._parse_id_var(False), over=over
4014            )
4015
4016        window_alias = self._parse_id_var(any_token=False, tokens=self.WINDOW_ALIAS_TOKENS)
4017
4018        first = self._match(TokenType.FIRST)
4019        if self._match_text_seq("LAST"):
4020            first = False
4021
4022        partition = self._parse_partition_by()
4023        order = self._parse_order()
4024        kind = self._match_set((TokenType.ROWS, TokenType.RANGE)) and self._prev.text
4025
4026        if kind:
4027            self._match(TokenType.BETWEEN)
4028            start = self._parse_window_spec()
4029            self._match(TokenType.AND)
4030            end = self._parse_window_spec()
4031
4032            spec = self.expression(
4033                exp.WindowSpec,
4034                kind=kind,
4035                start=start["value"],
4036                start_side=start["side"],
4037                end=end["value"],
4038                end_side=end["side"],
4039            )
4040        else:
4041            spec = None
4042
4043        self._match_r_paren()
4044
4045        return self.expression(
4046            exp.Window,
4047            this=this,
4048            partition_by=partition,
4049            order=order,
4050            spec=spec,
4051            alias=window_alias,
4052            over=over,
4053            first=first,
4054        )
4055
4056    def _parse_window_spec(self) -> t.Dict[str, t.Optional[str | exp.Expression]]:
4057        self._match(TokenType.BETWEEN)
4058
4059        return {
4060            "value": (
4061                (self._match_text_seq("UNBOUNDED") and "UNBOUNDED")
4062                or (self._match_text_seq("CURRENT", "ROW") and "CURRENT ROW")
4063                or self._parse_bitwise()
4064            ),
4065            "side": self._match_texts(self.WINDOW_SIDES) and self._prev.text,
4066        }
4067
4068    def _parse_alias(
4069        self, this: t.Optional[exp.Expression], explicit: bool = False
4070    ) -> t.Optional[exp.Expression]:
4071        any_token = self._match(TokenType.ALIAS)
4072
4073        if explicit and not any_token:
4074            return this
4075
4076        if self._match(TokenType.L_PAREN):
4077            aliases = self.expression(
4078                exp.Aliases,
4079                this=this,
4080                expressions=self._parse_csv(lambda: self._parse_id_var(any_token)),
4081            )
4082            self._match_r_paren(aliases)
4083            return aliases
4084
4085        alias = self._parse_id_var(any_token)
4086
4087        if alias:
4088            return self.expression(exp.Alias, this=this, alias=alias)
4089
4090        return this
4091
4092    def _parse_id_var(
4093        self,
4094        any_token: bool = True,
4095        tokens: t.Optional[t.Collection[TokenType]] = None,
4096    ) -> t.Optional[exp.Expression]:
4097        identifier = self._parse_identifier()
4098
4099        if identifier:
4100            return identifier
4101
4102        if (any_token and self._advance_any()) or self._match_set(tokens or self.ID_VAR_TOKENS):
4103            quoted = self._prev.token_type == TokenType.STRING
4104            return exp.Identifier(this=self._prev.text, quoted=quoted)
4105
4106        return None
4107
4108    def _parse_string(self) -> t.Optional[exp.Expression]:
4109        if self._match(TokenType.STRING):
4110            return self.PRIMARY_PARSERS[TokenType.STRING](self, self._prev)
4111        return self._parse_placeholder()
4112
4113    def _parse_string_as_identifier(self) -> t.Optional[exp.Identifier]:
4114        return exp.to_identifier(self._match(TokenType.STRING) and self._prev.text, quoted=True)
4115
4116    def _parse_number(self) -> t.Optional[exp.Expression]:
4117        if self._match(TokenType.NUMBER):
4118            return self.PRIMARY_PARSERS[TokenType.NUMBER](self, self._prev)
4119        return self._parse_placeholder()
4120
4121    def _parse_identifier(self) -> t.Optional[exp.Expression]:
4122        if self._match(TokenType.IDENTIFIER):
4123            return self.expression(exp.Identifier, this=self._prev.text, quoted=True)
4124        return self._parse_placeholder()
4125
4126    def _parse_var(
4127        self, any_token: bool = False, tokens: t.Optional[t.Collection[TokenType]] = None
4128    ) -> t.Optional[exp.Expression]:
4129        if (
4130            (any_token and self._advance_any())
4131            or self._match(TokenType.VAR)
4132            or (self._match_set(tokens) if tokens else False)
4133        ):
4134            return self.expression(exp.Var, this=self._prev.text)
4135        return self._parse_placeholder()
4136
4137    def _advance_any(self) -> t.Optional[Token]:
4138        if self._curr and self._curr.token_type not in self.RESERVED_KEYWORDS:
4139            self._advance()
4140            return self._prev
4141        return None
4142
4143    def _parse_var_or_string(self) -> t.Optional[exp.Expression]:
4144        return self._parse_var() or self._parse_string()
4145
4146    def _parse_null(self) -> t.Optional[exp.Expression]:
4147        if self._match(TokenType.NULL):
4148            return self.PRIMARY_PARSERS[TokenType.NULL](self, self._prev)
4149        return None
4150
4151    def _parse_boolean(self) -> t.Optional[exp.Expression]:
4152        if self._match(TokenType.TRUE):
4153            return self.PRIMARY_PARSERS[TokenType.TRUE](self, self._prev)
4154        if self._match(TokenType.FALSE):
4155            return self.PRIMARY_PARSERS[TokenType.FALSE](self, self._prev)
4156        return None
4157
4158    def _parse_star(self) -> t.Optional[exp.Expression]:
4159        if self._match(TokenType.STAR):
4160            return self.PRIMARY_PARSERS[TokenType.STAR](self, self._prev)
4161        return None
4162
4163    def _parse_parameter(self) -> exp.Parameter:
4164        wrapped = self._match(TokenType.L_BRACE)
4165        this = self._parse_var() or self._parse_identifier() or self._parse_primary()
4166        self._match(TokenType.R_BRACE)
4167        return self.expression(exp.Parameter, this=this, wrapped=wrapped)
4168
4169    def _parse_placeholder(self) -> t.Optional[exp.Expression]:
4170        if self._match_set(self.PLACEHOLDER_PARSERS):
4171            placeholder = self.PLACEHOLDER_PARSERS[self._prev.token_type](self)
4172            if placeholder:
4173                return placeholder
4174            self._advance(-1)
4175        return None
4176
4177    def _parse_except(self) -> t.Optional[t.List[t.Optional[exp.Expression]]]:
4178        if not self._match(TokenType.EXCEPT):
4179            return None
4180        if self._match(TokenType.L_PAREN, advance=False):
4181            return self._parse_wrapped_csv(self._parse_column)
4182        return self._parse_csv(self._parse_column)
4183
4184    def _parse_replace(self) -> t.Optional[t.List[t.Optional[exp.Expression]]]:
4185        if not self._match(TokenType.REPLACE):
4186            return None
4187        if self._match(TokenType.L_PAREN, advance=False):
4188            return self._parse_wrapped_csv(self._parse_expression)
4189        return self._parse_csv(self._parse_expression)
4190
4191    def _parse_csv(
4192        self, parse_method: t.Callable, sep: TokenType = TokenType.COMMA
4193    ) -> t.List[t.Optional[exp.Expression]]:
4194        parse_result = parse_method()
4195        items = [parse_result] if parse_result is not None else []
4196
4197        while self._match(sep):
4198            self._add_comments(parse_result)
4199            parse_result = parse_method()
4200            if parse_result is not None:
4201                items.append(parse_result)
4202
4203        return items
4204
4205    def _parse_tokens(
4206        self, parse_method: t.Callable, expressions: t.Dict
4207    ) -> t.Optional[exp.Expression]:
4208        this = parse_method()
4209
4210        while self._match_set(expressions):
4211            this = self.expression(
4212                expressions[self._prev.token_type],
4213                this=this,
4214                comments=self._prev_comments,
4215                expression=parse_method(),
4216            )
4217
4218        return this
4219
4220    def _parse_wrapped_id_vars(self, optional: bool = False) -> t.List[t.Optional[exp.Expression]]:
4221        return self._parse_wrapped_csv(self._parse_id_var, optional=optional)
4222
4223    def _parse_wrapped_csv(
4224        self, parse_method: t.Callable, sep: TokenType = TokenType.COMMA, optional: bool = False
4225    ) -> t.List[t.Optional[exp.Expression]]:
4226        return self._parse_wrapped(
4227            lambda: self._parse_csv(parse_method, sep=sep), optional=optional
4228        )
4229
4230    def _parse_wrapped(self, parse_method: t.Callable, optional: bool = False) -> t.Any:
4231        wrapped = self._match(TokenType.L_PAREN)
4232        if not wrapped and not optional:
4233            self.raise_error("Expecting (")
4234        parse_result = parse_method()
4235        if wrapped:
4236            self._match_r_paren()
4237        return parse_result
4238
4239    def _parse_select_or_expression(self, alias: bool = False) -> t.Optional[exp.Expression]:
4240        return self._parse_select() or self._parse_set_operations(
4241            self._parse_expression() if alias else self._parse_conjunction()
4242        )
4243
4244    def _parse_ddl_select(self) -> t.Optional[exp.Expression]:
4245        return self._parse_query_modifiers(
4246            self._parse_set_operations(self._parse_select(nested=True, parse_subquery_alias=False))
4247        )
4248
4249    def _parse_transaction(self) -> exp.Transaction:
4250        this = None
4251        if self._match_texts(self.TRANSACTION_KIND):
4252            this = self._prev.text
4253
4254        self._match_texts({"TRANSACTION", "WORK"})
4255
4256        modes = []
4257        while True:
4258            mode = []
4259            while self._match(TokenType.VAR):
4260                mode.append(self._prev.text)
4261
4262            if mode:
4263                modes.append(" ".join(mode))
4264            if not self._match(TokenType.COMMA):
4265                break
4266
4267        return self.expression(exp.Transaction, this=this, modes=modes)
4268
4269    def _parse_commit_or_rollback(self) -> exp.Commit | exp.Rollback:
4270        chain = None
4271        savepoint = None
4272        is_rollback = self._prev.token_type == TokenType.ROLLBACK
4273
4274        self._match_texts({"TRANSACTION", "WORK"})
4275
4276        if self._match_text_seq("TO"):
4277            self._match_text_seq("SAVEPOINT")
4278            savepoint = self._parse_id_var()
4279
4280        if self._match(TokenType.AND):
4281            chain = not self._match_text_seq("NO")
4282            self._match_text_seq("CHAIN")
4283
4284        if is_rollback:
4285            return self.expression(exp.Rollback, savepoint=savepoint)
4286
4287        return self.expression(exp.Commit, chain=chain)
4288
4289    def _parse_add_column(self) -> t.Optional[exp.Expression]:
4290        if not self._match_text_seq("ADD"):
4291            return None
4292
4293        self._match(TokenType.COLUMN)
4294        exists_column = self._parse_exists(not_=True)
4295        expression = self._parse_column_def(self._parse_field(any_token=True))
4296
4297        if expression:
4298            expression.set("exists", exists_column)
4299
4300            # https://docs.databricks.com/delta/update-schema.html#explicitly-update-schema-to-add-columns
4301            if self._match_texts(("FIRST", "AFTER")):
4302                position = self._prev.text
4303                column_position = self.expression(
4304                    exp.ColumnPosition, this=self._parse_column(), position=position
4305                )
4306                expression.set("position", column_position)
4307
4308        return expression
4309
4310    def _parse_drop_column(self) -> t.Optional[exp.Drop | exp.Command]:
4311        drop = self._match(TokenType.DROP) and self._parse_drop()
4312        if drop and not isinstance(drop, exp.Command):
4313            drop.set("kind", drop.args.get("kind", "COLUMN"))
4314        return drop
4315
4316    # https://docs.aws.amazon.com/athena/latest/ug/alter-table-drop-partition.html
4317    def _parse_drop_partition(self, exists: t.Optional[bool] = None) -> exp.DropPartition:
4318        return self.expression(
4319            exp.DropPartition, expressions=self._parse_csv(self._parse_partition), exists=exists
4320        )
4321
4322    def _parse_add_constraint(self) -> exp.AddConstraint:
4323        this = None
4324        kind = self._prev.token_type
4325
4326        if kind == TokenType.CONSTRAINT:
4327            this = self._parse_id_var()
4328
4329            if self._match_text_seq("CHECK"):
4330                expression = self._parse_wrapped(self._parse_conjunction)
4331                enforced = self._match_text_seq("ENFORCED")
4332
4333                return self.expression(
4334                    exp.AddConstraint, this=this, expression=expression, enforced=enforced
4335                )
4336
4337        if kind == TokenType.FOREIGN_KEY or self._match(TokenType.FOREIGN_KEY):
4338            expression = self._parse_foreign_key()
4339        elif kind == TokenType.PRIMARY_KEY or self._match(TokenType.PRIMARY_KEY):
4340            expression = self._parse_primary_key()
4341        else:
4342            expression = None
4343
4344        return self.expression(exp.AddConstraint, this=this, expression=expression)
4345
4346    def _parse_alter_table_add(self) -> t.List[t.Optional[exp.Expression]]:
4347        index = self._index - 1
4348
4349        if self._match_set(self.ADD_CONSTRAINT_TOKENS):
4350            return self._parse_csv(self._parse_add_constraint)
4351
4352        self._retreat(index)
4353        return self._parse_csv(self._parse_add_column)
4354
4355    def _parse_alter_table_alter(self) -> exp.AlterColumn:
4356        self._match(TokenType.COLUMN)
4357        column = self._parse_field(any_token=True)
4358
4359        if self._match_pair(TokenType.DROP, TokenType.DEFAULT):
4360            return self.expression(exp.AlterColumn, this=column, drop=True)
4361        if self._match_pair(TokenType.SET, TokenType.DEFAULT):
4362            return self.expression(exp.AlterColumn, this=column, default=self._parse_conjunction())
4363
4364        self._match_text_seq("SET", "DATA")
4365        return self.expression(
4366            exp.AlterColumn,
4367            this=column,
4368            dtype=self._match_text_seq("TYPE") and self._parse_types(),
4369            collate=self._match(TokenType.COLLATE) and self._parse_term(),
4370            using=self._match(TokenType.USING) and self._parse_conjunction(),
4371        )
4372
4373    def _parse_alter_table_drop(self) -> t.List[t.Optional[exp.Expression]]:
4374        index = self._index - 1
4375
4376        partition_exists = self._parse_exists()
4377        if self._match(TokenType.PARTITION, advance=False):
4378            return self._parse_csv(lambda: self._parse_drop_partition(exists=partition_exists))
4379
4380        self._retreat(index)
4381        return self._parse_csv(self._parse_drop_column)
4382
4383    def _parse_alter_table_rename(self) -> exp.RenameTable:
4384        self._match_text_seq("TO")
4385        return self.expression(exp.RenameTable, this=self._parse_table(schema=True))
4386
4387    def _parse_alter(self) -> exp.AlterTable | exp.Command:
4388        start = self._prev
4389
4390        if not self._match(TokenType.TABLE):
4391            return self._parse_as_command(start)
4392
4393        exists = self._parse_exists()
4394        this = self._parse_table(schema=True)
4395
4396        if self._next:
4397            self._advance()
4398        parser = self.ALTER_PARSERS.get(self._prev.text.upper()) if self._prev else None
4399
4400        if parser:
4401            actions = ensure_list(parser(self))
4402
4403            if not self._curr:
4404                return self.expression(
4405                    exp.AlterTable,
4406                    this=this,
4407                    exists=exists,
4408                    actions=actions,
4409                )
4410        return self._parse_as_command(start)
4411
4412    def _parse_merge(self) -> exp.Merge:
4413        self._match(TokenType.INTO)
4414        target = self._parse_table()
4415
4416        self._match(TokenType.USING)
4417        using = self._parse_table()
4418
4419        self._match(TokenType.ON)
4420        on = self._parse_conjunction()
4421
4422        whens = []
4423        while self._match(TokenType.WHEN):
4424            matched = not self._match(TokenType.NOT)
4425            self._match_text_seq("MATCHED")
4426            source = (
4427                False
4428                if self._match_text_seq("BY", "TARGET")
4429                else self._match_text_seq("BY", "SOURCE")
4430            )
4431            condition = self._parse_conjunction() if self._match(TokenType.AND) else None
4432
4433            self._match(TokenType.THEN)
4434
4435            if self._match(TokenType.INSERT):
4436                _this = self._parse_star()
4437                if _this:
4438                    then: t.Optional[exp.Expression] = self.expression(exp.Insert, this=_this)
4439                else:
4440                    then = self.expression(
4441                        exp.Insert,
4442                        this=self._parse_value(),
4443                        expression=self._match(TokenType.VALUES) and self._parse_value(),
4444                    )
4445            elif self._match(TokenType.UPDATE):
4446                expressions = self._parse_star()
4447                if expressions:
4448                    then = self.expression(exp.Update, expressions=expressions)
4449                else:
4450                    then = self.expression(
4451                        exp.Update,
4452                        expressions=self._match(TokenType.SET)
4453                        and self._parse_csv(self._parse_equality),
4454                    )
4455            elif self._match(TokenType.DELETE):
4456                then = self.expression(exp.Var, this=self._prev.text)
4457            else:
4458                then = None
4459
4460            whens.append(
4461                self.expression(
4462                    exp.When,
4463                    matched=matched,
4464                    source=source,
4465                    condition=condition,
4466                    then=then,
4467                )
4468            )
4469
4470        return self.expression(
4471            exp.Merge,
4472            this=target,
4473            using=using,
4474            on=on,
4475            expressions=whens,
4476        )
4477
4478    def _parse_show(self) -> t.Optional[exp.Expression]:
4479        parser = self._find_parser(self.SHOW_PARSERS, self.SHOW_TRIE)
4480        if parser:
4481            return parser(self)
4482        self._advance()
4483        return self.expression(exp.Show, this=self._prev.text.upper())
4484
4485    def _parse_set_item_assignment(
4486        self, kind: t.Optional[str] = None
4487    ) -> t.Optional[exp.Expression]:
4488        index = self._index
4489
4490        if kind in {"GLOBAL", "SESSION"} and self._match_text_seq("TRANSACTION"):
4491            return self._parse_set_transaction(global_=kind == "GLOBAL")
4492
4493        left = self._parse_primary() or self._parse_id_var()
4494
4495        if not self._match_texts(("=", "TO")):
4496            self._retreat(index)
4497            return None
4498
4499        right = self._parse_statement() or self._parse_id_var()
4500        this = self.expression(exp.EQ, this=left, expression=right)
4501
4502        return self.expression(exp.SetItem, this=this, kind=kind)
4503
4504    def _parse_set_transaction(self, global_: bool = False) -> exp.Expression:
4505        self._match_text_seq("TRANSACTION")
4506        characteristics = self._parse_csv(
4507            lambda: self._parse_var_from_options(self.TRANSACTION_CHARACTERISTICS)
4508        )
4509        return self.expression(
4510            exp.SetItem,
4511            expressions=characteristics,
4512            kind="TRANSACTION",
4513            **{"global": global_},  # type: ignore
4514        )
4515
4516    def _parse_set_item(self) -> t.Optional[exp.Expression]:
4517        parser = self._find_parser(self.SET_PARSERS, self.SET_TRIE)
4518        return parser(self) if parser else self._parse_set_item_assignment(kind=None)
4519
4520    def _parse_set(self) -> exp.Set | exp.Command:
4521        index = self._index
4522        set_ = self.expression(exp.Set, expressions=self._parse_csv(self._parse_set_item))
4523
4524        if self._curr:
4525            self._retreat(index)
4526            return self._parse_as_command(self._prev)
4527
4528        return set_
4529
4530    def _parse_var_from_options(self, options: t.Collection[str]) -> t.Optional[exp.Var]:
4531        for option in options:
4532            if self._match_text_seq(*option.split(" ")):
4533                return exp.var(option)
4534        return None
4535
4536    def _parse_as_command(self, start: Token) -> exp.Command:
4537        while self._curr:
4538            self._advance()
4539        text = self._find_sql(start, self._prev)
4540        size = len(start.text)
4541        return exp.Command(this=text[:size], expression=text[size:])
4542
4543    def _parse_dict_property(self, this: str) -> exp.DictProperty:
4544        settings = []
4545
4546        self._match_l_paren()
4547        kind = self._parse_id_var()
4548
4549        if self._match(TokenType.L_PAREN):
4550            while True:
4551                key = self._parse_id_var()
4552                value = self._parse_primary()
4553
4554                if not key and value is None:
4555                    break
4556                settings.append(self.expression(exp.DictSubProperty, this=key, value=value))
4557            self._match(TokenType.R_PAREN)
4558
4559        self._match_r_paren()
4560
4561        return self.expression(
4562            exp.DictProperty,
4563            this=this,
4564            kind=kind.this if kind else None,
4565            settings=settings,
4566        )
4567
4568    def _parse_dict_range(self, this: str) -> exp.DictRange:
4569        self._match_l_paren()
4570        has_min = self._match_text_seq("MIN")
4571        if has_min:
4572            min = self._parse_var() or self._parse_primary()
4573            self._match_text_seq("MAX")
4574            max = self._parse_var() or self._parse_primary()
4575        else:
4576            max = self._parse_var() or self._parse_primary()
4577            min = exp.Literal.number(0)
4578        self._match_r_paren()
4579        return self.expression(exp.DictRange, this=this, min=min, max=max)
4580
4581    def _find_parser(
4582        self, parsers: t.Dict[str, t.Callable], trie: t.Dict
4583    ) -> t.Optional[t.Callable]:
4584        if not self._curr:
4585            return None
4586
4587        index = self._index
4588        this = []
4589        while True:
4590            # The current token might be multiple words
4591            curr = self._curr.text.upper()
4592            key = curr.split(" ")
4593            this.append(curr)
4594
4595            self._advance()
4596            result, trie = in_trie(trie, key)
4597            if result == TrieResult.FAILED:
4598                break
4599
4600            if result == TrieResult.EXISTS:
4601                subparser = parsers[" ".join(this)]
4602                return subparser
4603
4604        self._retreat(index)
4605        return None
4606
4607    def _match(self, token_type, advance=True, expression=None):
4608        if not self._curr:
4609            return None
4610
4611        if self._curr.token_type == token_type:
4612            if advance:
4613                self._advance()
4614            self._add_comments(expression)
4615            return True
4616
4617        return None
4618
4619    def _match_set(self, types, advance=True):
4620        if not self._curr:
4621            return None
4622
4623        if self._curr.token_type in types:
4624            if advance:
4625                self._advance()
4626            return True
4627
4628        return None
4629
4630    def _match_pair(self, token_type_a, token_type_b, advance=True):
4631        if not self._curr or not self._next:
4632            return None
4633
4634        if self._curr.token_type == token_type_a and self._next.token_type == token_type_b:
4635            if advance:
4636                self._advance(2)
4637            return True
4638
4639        return None
4640
4641    def _match_l_paren(self, expression: t.Optional[exp.Expression] = None) -> None:
4642        if not self._match(TokenType.L_PAREN, expression=expression):
4643            self.raise_error("Expecting (")
4644
4645    def _match_r_paren(self, expression: t.Optional[exp.Expression] = None) -> None:
4646        if not self._match(TokenType.R_PAREN, expression=expression):
4647            self.raise_error("Expecting )")
4648
4649    def _match_texts(self, texts, advance=True):
4650        if self._curr and self._curr.text.upper() in texts:
4651            if advance:
4652                self._advance()
4653            return True
4654        return False
4655
4656    def _match_text_seq(self, *texts, advance=True):
4657        index = self._index
4658        for text in texts:
4659            if self._curr and self._curr.text.upper() == text:
4660                self._advance()
4661            else:
4662                self._retreat(index)
4663                return False
4664
4665        if not advance:
4666            self._retreat(index)
4667
4668        return True
4669
4670    @t.overload
4671    def _replace_columns_with_dots(self, this: exp.Expression) -> exp.Expression:
4672        ...
4673
4674    @t.overload
4675    def _replace_columns_with_dots(
4676        self, this: t.Optional[exp.Expression]
4677    ) -> t.Optional[exp.Expression]:
4678        ...
4679
4680    def _replace_columns_with_dots(self, this):
4681        if isinstance(this, exp.Dot):
4682            exp.replace_children(this, self._replace_columns_with_dots)
4683        elif isinstance(this, exp.Column):
4684            exp.replace_children(this, self._replace_columns_with_dots)
4685            table = this.args.get("table")
4686            this = (
4687                self.expression(exp.Dot, this=table, expression=this.this)
4688                if table
4689                else self.expression(exp.Var, this=this.name)
4690            )
4691        elif isinstance(this, exp.Identifier):
4692            this = self.expression(exp.Var, this=this.name)
4693
4694        return this
4695
4696    def _replace_lambda(
4697        self, node: t.Optional[exp.Expression], lambda_variables: t.Set[str]
4698    ) -> t.Optional[exp.Expression]:
4699        if not node:
4700            return node
4701
4702        for column in node.find_all(exp.Column):
4703            if column.parts[0].name in lambda_variables:
4704                dot_or_id = column.to_dot() if column.table else column.this
4705                parent = column.parent
4706
4707                while isinstance(parent, exp.Dot):
4708                    if not isinstance(parent.parent, exp.Dot):
4709                        parent.replace(dot_or_id)
4710                        break
4711                    parent = parent.parent
4712                else:
4713                    if column is node:
4714                        node = dot_or_id
4715                    else:
4716                        column.replace(dot_or_id)
4717        return node

Parser consumes a list of tokens produced by the Tokenizer and produces a parsed syntax tree.

Arguments:
  • error_level: The desired error level. Default: ErrorLevel.IMMEDIATE
  • error_message_context: Determines the amount of context to capture from a query string when displaying the error message (in number of characters). Default: 100
  • max_errors: Maximum number of error messages to include in a raised ParseError. This is only relevant if error_level is ErrorLevel.RAISE. Default: 3
Parser( error_level: Optional[sqlglot.errors.ErrorLevel] = None, error_message_context: int = 100, max_errors: int = 3)
833    def __init__(
834        self,
835        error_level: t.Optional[ErrorLevel] = None,
836        error_message_context: int = 100,
837        max_errors: int = 3,
838    ):
839        self.error_level = error_level or ErrorLevel.IMMEDIATE
840        self.error_message_context = error_message_context
841        self.max_errors = max_errors
842        self.reset()
FUNCTIONS: Dict[str, Callable] = {'ABS': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Abs'>>, 'ANY_VALUE': <bound method Func.from_arg_list of <class 'sqlglot.expressions.AnyValue'>>, 'APPROX_DISTINCT': <bound method Func.from_arg_list of <class 'sqlglot.expressions.ApproxDistinct'>>, 'APPROX_COUNT_DISTINCT': <bound method Func.from_arg_list of <class 'sqlglot.expressions.ApproxDistinct'>>, 'APPROX_QUANTILE': <bound method Func.from_arg_list of <class 'sqlglot.expressions.ApproxQuantile'>>, 'ARRAY': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Array'>>, 'ARRAY_AGG': <bound method Func.from_arg_list of <class 'sqlglot.expressions.ArrayAgg'>>, 'ARRAY_ALL': <bound method Func.from_arg_list of <class 'sqlglot.expressions.ArrayAll'>>, 'ARRAY_ANY': <bound method Func.from_arg_list of <class 'sqlglot.expressions.ArrayAny'>>, 'ARRAY_CONCAT': <bound method Func.from_arg_list of <class 'sqlglot.expressions.ArrayConcat'>>, 'ARRAY_CONTAINS': <bound method Func.from_arg_list of <class 'sqlglot.expressions.ArrayContains'>>, 'FILTER': <bound method Func.from_arg_list of <class 'sqlglot.expressions.ArrayFilter'>>, 'ARRAY_FILTER': <bound method Func.from_arg_list of <class 'sqlglot.expressions.ArrayFilter'>>, 'ARRAY_JOIN': <bound method Func.from_arg_list of <class 'sqlglot.expressions.ArrayJoin'>>, 'ARRAY_SIZE': <bound method Func.from_arg_list of <class 'sqlglot.expressions.ArraySize'>>, 'ARRAY_SORT': <bound method Func.from_arg_list of <class 'sqlglot.expressions.ArraySort'>>, 'ARRAY_SUM': <bound method Func.from_arg_list of <class 'sqlglot.expressions.ArraySum'>>, 'ARRAY_UNION_AGG': <bound method Func.from_arg_list of <class 'sqlglot.expressions.ArrayUnionAgg'>>, 'AVG': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Avg'>>, 'CASE': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Case'>>, 'CAST': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Cast'>>, 'CAST_TO_STR_TYPE': <bound method Func.from_arg_list of <class 'sqlglot.expressions.CastToStrType'>>, 'CEIL': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Ceil'>>, 'CEILING': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Ceil'>>, 'COALESCE': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Coalesce'>>, 'IFNULL': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Coalesce'>>, 'NVL': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Coalesce'>>, 'CONCAT': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Concat'>>, 'CONCAT_WS': <bound method Func.from_arg_list of <class 'sqlglot.expressions.ConcatWs'>>, 'COUNT': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Count'>>, 'COUNT_IF': <bound method Func.from_arg_list of <class 'sqlglot.expressions.CountIf'>>, 'CURRENT_DATE': <bound method Func.from_arg_list of <class 'sqlglot.expressions.CurrentDate'>>, 'CURRENT_DATETIME': <bound method Func.from_arg_list of <class 'sqlglot.expressions.CurrentDatetime'>>, 'CURRENT_TIME': <bound method Func.from_arg_list of <class 'sqlglot.expressions.CurrentTime'>>, 'CURRENT_TIMESTAMP': <bound method Func.from_arg_list of <class 'sqlglot.expressions.CurrentTimestamp'>>, 'CURRENT_USER': <bound method Func.from_arg_list of <class 'sqlglot.expressions.CurrentUser'>>, 'DATE': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Date'>>, 'DATE_ADD': <bound method Func.from_arg_list of <class 'sqlglot.expressions.DateAdd'>>, 'DATEDIFF': <bound method Func.from_arg_list of <class 'sqlglot.expressions.DateDiff'>>, 'DATE_DIFF': <bound method Func.from_arg_list of <class 'sqlglot.expressions.DateDiff'>>, 'DATEFROMPARTS': <bound method Func.from_arg_list of <class 'sqlglot.expressions.DateFromParts'>>, 'DATE_STR_TO_DATE': <bound method Func.from_arg_list of <class 'sqlglot.expressions.DateStrToDate'>>, 'DATE_SUB': <bound method Func.from_arg_list of <class 'sqlglot.expressions.DateSub'>>, 'DATE_TO_DATE_STR': <function Parser.<lambda>>, 'DATE_TO_DI': <bound method Func.from_arg_list of <class 'sqlglot.expressions.DateToDi'>>, 'DATE_TRUNC': <bound method Func.from_arg_list of <class 'sqlglot.expressions.DateTrunc'>>, 'DATETIME_ADD': <bound method Func.from_arg_list of <class 'sqlglot.expressions.DatetimeAdd'>>, 'DATETIME_DIFF': <bound method Func.from_arg_list of <class 'sqlglot.expressions.DatetimeDiff'>>, 'DATETIME_SUB': <bound method Func.from_arg_list of <class 'sqlglot.expressions.DatetimeSub'>>, 'DATETIME_TRUNC': <bound method Func.from_arg_list of <class 'sqlglot.expressions.DatetimeTrunc'>>, 'DAY': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Day'>>, 'DAY_OF_MONTH': <bound method Func.from_arg_list of <class 'sqlglot.expressions.DayOfMonth'>>, 'DAYOFMONTH': <bound method Func.from_arg_list of <class 'sqlglot.expressions.DayOfMonth'>>, 'DAY_OF_WEEK': <bound method Func.from_arg_list of <class 'sqlglot.expressions.DayOfWeek'>>, 'DAYOFWEEK': <bound method Func.from_arg_list of <class 'sqlglot.expressions.DayOfWeek'>>, 'DAY_OF_YEAR': <bound method Func.from_arg_list of <class 'sqlglot.expressions.DayOfYear'>>, 'DAYOFYEAR': <bound method Func.from_arg_list of <class 'sqlglot.expressions.DayOfYear'>>, 'DECODE': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Decode'>>, 'DI_TO_DATE': <bound method Func.from_arg_list of <class 'sqlglot.expressions.DiToDate'>>, 'ENCODE': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Encode'>>, 'EXP': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Exp'>>, 'EXPLODE': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Explode'>>, 'EXTRACT': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Extract'>>, 'FLOOR': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Floor'>>, 'FROM_BASE': <bound method Func.from_arg_list of <class 'sqlglot.expressions.FromBase'>>, 'FROM_BASE64': <bound method Func.from_arg_list of <class 'sqlglot.expressions.FromBase64'>>, 'GENERATE_SERIES': <bound method Func.from_arg_list of <class 'sqlglot.expressions.GenerateSeries'>>, 'GREATEST': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Greatest'>>, 'GROUP_CONCAT': <bound method Func.from_arg_list of <class 'sqlglot.expressions.GroupConcat'>>, 'HEX': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Hex'>>, 'HLL': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Hll'>>, 'IF': <bound method Func.from_arg_list of <class 'sqlglot.expressions.If'>>, 'INITCAP': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Initcap'>>, 'JSONB_EXTRACT': <bound method Func.from_arg_list of <class 'sqlglot.expressions.JSONBExtract'>>, 'JSONB_EXTRACT_SCALAR': <bound method Func.from_arg_list of <class 'sqlglot.expressions.JSONBExtractScalar'>>, 'JSON_EXTRACT': <bound method Func.from_arg_list of <class 'sqlglot.expressions.JSONExtract'>>, 'JSON_EXTRACT_SCALAR': <bound method Func.from_arg_list of <class 'sqlglot.expressions.JSONExtractScalar'>>, 'JSON_FORMAT': <bound method Func.from_arg_list of <class 'sqlglot.expressions.JSONFormat'>>, 'J_S_O_N_OBJECT': <bound method Func.from_arg_list of <class 'sqlglot.expressions.JSONObject'>>, 'LAST_DATE_OF_MONTH': <bound method Func.from_arg_list of <class 'sqlglot.expressions.LastDateOfMonth'>>, 'LEAST': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Least'>>, 'LEFT': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Left'>>, 'LENGTH': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Length'>>, 'LEN': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Length'>>, 'LEVENSHTEIN': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Levenshtein'>>, 'LN': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Ln'>>, 'LOG': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Log'>>, 'LOG10': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Log10'>>, 'LOG2': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Log2'>>, 'LOGICAL_AND': <bound method Func.from_arg_list of <class 'sqlglot.expressions.LogicalAnd'>>, 'BOOL_AND': <bound method Func.from_arg_list of <class 'sqlglot.expressions.LogicalAnd'>>, 'BOOLAND_AGG': <bound method Func.from_arg_list of <class 'sqlglot.expressions.LogicalAnd'>>, 'LOGICAL_OR': <bound method Func.from_arg_list of <class 'sqlglot.expressions.LogicalOr'>>, 'BOOL_OR': <bound method Func.from_arg_list of <class 'sqlglot.expressions.LogicalOr'>>, 'BOOLOR_AGG': <bound method Func.from_arg_list of <class 'sqlglot.expressions.LogicalOr'>>, 'LOWER': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Lower'>>, 'LCASE': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Lower'>>, 'MD5': <bound method Func.from_arg_list of <class 'sqlglot.expressions.MD5'>>, 'MAP': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Map'>>, 'MATCH_AGAINST': <bound method Func.from_arg_list of <class 'sqlglot.expressions.MatchAgainst'>>, 'MAX': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Max'>>, 'MIN': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Min'>>, 'MONTH': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Month'>>, 'NEXT_VALUE_FOR': <bound method Func.from_arg_list of <class 'sqlglot.expressions.NextValueFor'>>, 'NUMBER_TO_STR': <bound method Func.from_arg_list of <class 'sqlglot.expressions.NumberToStr'>>, 'NVL2': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Nvl2'>>, 'OPEN_J_S_O_N': <bound method Func.from_arg_list of <class 'sqlglot.expressions.OpenJSON'>>, 'PARAMETERIZED_AGG': <bound method Func.from_arg_list of <class 'sqlglot.expressions.ParameterizedAgg'>>, 'PERCENTILE_CONT': <bound method Func.from_arg_list of <class 'sqlglot.expressions.PercentileCont'>>, 'PERCENTILE_DISC': <bound method Func.from_arg_list of <class 'sqlglot.expressions.PercentileDisc'>>, 'POSEXPLODE': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Posexplode'>>, 'POWER': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Pow'>>, 'POW': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Pow'>>, 'QUANTILE': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Quantile'>>, 'RANGE_N': <bound method Func.from_arg_list of <class 'sqlglot.expressions.RangeN'>>, 'READ_CSV': <bound method Func.from_arg_list of <class 'sqlglot.expressions.ReadCSV'>>, 'REDUCE': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Reduce'>>, 'REGEXP_EXTRACT': <bound method Func.from_arg_list of <class 'sqlglot.expressions.RegexpExtract'>>, 'REGEXP_I_LIKE': <bound method Func.from_arg_list of <class 'sqlglot.expressions.RegexpILike'>>, 'REGEXP_LIKE': <bound method Func.from_arg_list of <class 'sqlglot.expressions.RegexpLike'>>, 'REGEXP_SPLIT': <bound method Func.from_arg_list of <class 'sqlglot.expressions.RegexpSplit'>>, 'REPEAT': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Repeat'>>, 'RIGHT': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Right'>>, 'ROUND': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Round'>>, 'ROW_NUMBER': <bound method Func.from_arg_list of <class 'sqlglot.expressions.RowNumber'>>, 'SHA': <bound method Func.from_arg_list of <class 'sqlglot.expressions.SHA'>>, 'SHA1': <bound method Func.from_arg_list of <class 'sqlglot.expressions.SHA'>>, 'SHA2': <bound method Func.from_arg_list of <class 'sqlglot.expressions.SHA2'>>, 'SAFE_CONCAT': <bound method Func.from_arg_list of <class 'sqlglot.expressions.SafeConcat'>>, 'SAFE_DIVIDE': <bound method Func.from_arg_list of <class 'sqlglot.expressions.SafeDivide'>>, 'SET_AGG': <bound method Func.from_arg_list of <class 'sqlglot.expressions.SetAgg'>>, 'SORT_ARRAY': <bound method Func.from_arg_list of <class 'sqlglot.expressions.SortArray'>>, 'SPLIT': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Split'>>, 'SQRT': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Sqrt'>>, 'STANDARD_HASH': <bound method Func.from_arg_list of <class 'sqlglot.expressions.StandardHash'>>, 'STAR_MAP': <bound method Func.from_arg_list of <class 'sqlglot.expressions.StarMap'>>, 'STDDEV': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Stddev'>>, 'STDDEV_POP': <bound method Func.from_arg_list of <class 'sqlglot.expressions.StddevPop'>>, 'STDDEV_SAMP': <bound method Func.from_arg_list of <class 'sqlglot.expressions.StddevSamp'>>, 'STR_POSITION': <bound method Func.from_arg_list of <class 'sqlglot.expressions.StrPosition'>>, 'STR_TO_DATE': <bound method Func.from_arg_list of <class 'sqlglot.expressions.StrToDate'>>, 'STR_TO_TIME': <bound method Func.from_arg_list of <class 'sqlglot.expressions.StrToTime'>>, 'STR_TO_UNIX': <bound method Func.from_arg_list of <class 'sqlglot.expressions.StrToUnix'>>, 'STRUCT': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Struct'>>, 'STRUCT_EXTRACT': <bound method Func.from_arg_list of <class 'sqlglot.expressions.StructExtract'>>, 'SUBSTRING': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Substring'>>, 'SUM': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Sum'>>, 'TIME_ADD': <bound method Func.from_arg_list of <class 'sqlglot.expressions.TimeAdd'>>, 'TIME_DIFF': <bound method Func.from_arg_list of <class 'sqlglot.expressions.TimeDiff'>>, 'TIME_STR_TO_DATE': <bound method Func.from_arg_list of <class 'sqlglot.expressions.TimeStrToDate'>>, 'TIME_STR_TO_TIME': <bound method Func.from_arg_list of <class 'sqlglot.expressions.TimeStrToTime'>>, 'TIME_STR_TO_UNIX': <bound method Func.from_arg_list of <class 'sqlglot.expressions.TimeStrToUnix'>>, 'TIME_SUB': <bound method Func.from_arg_list of <class 'sqlglot.expressions.TimeSub'>>, 'TIME_TO_STR': <bound method Func.from_arg_list of <class 'sqlglot.expressions.TimeToStr'>>, 'TIME_TO_TIME_STR': <function Parser.<lambda>>, 'TIME_TO_UNIX': <bound method Func.from_arg_list of <class 'sqlglot.expressions.TimeToUnix'>>, 'TIME_TRUNC': <bound method Func.from_arg_list of <class 'sqlglot.expressions.TimeTrunc'>>, 'TIMESTAMP_ADD': <bound method Func.from_arg_list of <class 'sqlglot.expressions.TimestampAdd'>>, 'TIMESTAMP_DIFF': <bound method Func.from_arg_list of <class 'sqlglot.expressions.TimestampDiff'>>, 'TIMESTAMP_SUB': <bound method Func.from_arg_list of <class 'sqlglot.expressions.TimestampSub'>>, 'TIMESTAMP_TRUNC': <bound method Func.from_arg_list of <class 'sqlglot.expressions.TimestampTrunc'>>, 'TO_BASE64': <bound method Func.from_arg_list of <class 'sqlglot.expressions.ToBase64'>>, 'TO_CHAR': <bound method Func.from_arg_list of <class 'sqlglot.expressions.ToChar'>>, 'TRIM': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Trim'>>, 'TRY_CAST': <bound method Func.from_arg_list of <class 'sqlglot.expressions.TryCast'>>, 'TS_OR_DI_TO_DI': <bound method Func.from_arg_list of <class 'sqlglot.expressions.TsOrDiToDi'>>, 'TS_OR_DS_ADD': <bound method Func.from_arg_list of <class 'sqlglot.expressions.TsOrDsAdd'>>, 'TS_OR_DS_TO_DATE': <bound method Func.from_arg_list of <class 'sqlglot.expressions.TsOrDsToDate'>>, 'TS_OR_DS_TO_DATE_STR': <function Parser.<lambda>>, 'UNHEX': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Unhex'>>, 'UNIX_TO_STR': <bound method Func.from_arg_list of <class 'sqlglot.expressions.UnixToStr'>>, 'UNIX_TO_TIME': <bound method Func.from_arg_list of <class 'sqlglot.expressions.UnixToTime'>>, 'UNIX_TO_TIME_STR': <bound method Func.from_arg_list of <class 'sqlglot.expressions.UnixToTimeStr'>>, 'UPPER': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Upper'>>, 'UCASE': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Upper'>>, 'VAR_MAP': <function parse_var_map>, 'VARIANCE': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Variance'>>, 'VARIANCE_SAMP': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Variance'>>, 'VAR_SAMP': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Variance'>>, 'VARIANCE_POP': <bound method Func.from_arg_list of <class 'sqlglot.expressions.VariancePop'>>, 'VAR_POP': <bound method Func.from_arg_list of <class 'sqlglot.expressions.VariancePop'>>, 'WEEK': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Week'>>, 'WEEK_OF_YEAR': <bound method Func.from_arg_list of <class 'sqlglot.expressions.WeekOfYear'>>, 'WEEKOFYEAR': <bound method Func.from_arg_list of <class 'sqlglot.expressions.WeekOfYear'>>, 'WHEN': <bound method Func.from_arg_list of <class 'sqlglot.expressions.When'>>, 'X_M_L_TABLE': <bound method Func.from_arg_list of <class 'sqlglot.expressions.XMLTable'>>, 'YEAR': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Year'>>, 'GLOB': <function Parser.<lambda>>, 'LIKE': <function parse_like>}
NO_PAREN_FUNCTIONS = {<TokenType.CURRENT_DATE: 'CURRENT_DATE'>: <class 'sqlglot.expressions.CurrentDate'>, <TokenType.CURRENT_DATETIME: 'CURRENT_DATETIME'>: <class 'sqlglot.expressions.CurrentDate'>, <TokenType.CURRENT_TIME: 'CURRENT_TIME'>: <class 'sqlglot.expressions.CurrentTime'>, <TokenType.CURRENT_TIMESTAMP: 'CURRENT_TIMESTAMP'>: <class 'sqlglot.expressions.CurrentTimestamp'>, <TokenType.CURRENT_USER: 'CURRENT_USER'>: <class 'sqlglot.expressions.CurrentUser'>}
NESTED_TYPE_TOKENS = {<TokenType.STRUCT: 'STRUCT'>, <TokenType.NULLABLE: 'NULLABLE'>, <TokenType.ARRAY: 'ARRAY'>, <TokenType.MAP: 'MAP'>}
ENUM_TYPE_TOKENS = {<TokenType.ENUM: 'ENUM'>}
TYPE_TOKENS = {<TokenType.MEDIUMBLOB: 'MEDIUMBLOB'>, <TokenType.GEOMETRY: 'GEOMETRY'>, <TokenType.INT8RANGE: 'INT8RANGE'>, <TokenType.SERIAL: 'SERIAL'>, <TokenType.MONEY: 'MONEY'>, <TokenType.BIT: 'BIT'>, <TokenType.INT128: 'INT128'>, <TokenType.LONGBLOB: 'LONGBLOB'>, <TokenType.TEXT: 'TEXT'>, <TokenType.TIMESTAMPTZ: 'TIMESTAMPTZ'>, <TokenType.TSMULTIRANGE: 'TSMULTIRANGE'>, <TokenType.BIGSERIAL: 'BIGSERIAL'>, <TokenType.UINT128: 'UINT128'>, <TokenType.UNIQUEIDENTIFIER: 'UNIQUEIDENTIFIER'>, <TokenType.FLOAT: 'FLOAT'>, <TokenType.TIMESTAMPLTZ: 'TIMESTAMPLTZ'>, <TokenType.MEDIUMTEXT: 'MEDIUMTEXT'>, <TokenType.HLLSKETCH: 'HLLSKETCH'>, <TokenType.PSEUDO_TYPE: 'PSEUDO_TYPE'>, <TokenType.STRUCT: 'STRUCT'>, <TokenType.UINT256: 'UINT256'>, <TokenType.INT: 'INT'>, <TokenType.DATETIME64: 'DATETIME64'>, <TokenType.VARCHAR: 'VARCHAR'>, <TokenType.SUPER: 'SUPER'>, <TokenType.JSON: 'JSON'>, <TokenType.TSTZRANGE: 'TSTZRANGE'>, <TokenType.SMALLMONEY: 'SMALLMONEY'>, <TokenType.NVARCHAR: 'NVARCHAR'>, <TokenType.NUMMULTIRANGE: 'NUMMULTIRANGE'>, <TokenType.TSRANGE: 'TSRANGE'>, <TokenType.VARBINARY: 'VARBINARY'>, <TokenType.BIGINT: 'BIGINT'>, <TokenType.UUID: 'UUID'>, <TokenType.DATETIME: 'DATETIME'>, <TokenType.DOUBLE: 'DOUBLE'>, <TokenType.CHAR: 'CHAR'>, <TokenType.DATE: 'DATE'>, <TokenType.GEOGRAPHY: 'GEOGRAPHY'>, <TokenType.USERDEFINED: 'USERDEFINED'>, <TokenType.IMAGE: 'IMAGE'>, <TokenType.USMALLINT: 'USMALLINT'>, <TokenType.NUMRANGE: 'NUMRANGE'>, <TokenType.SMALLINT: 'SMALLINT'>, <TokenType.INET: 'INET'>, <TokenType.NULLABLE: 'NULLABLE'>, <TokenType.SMALLSERIAL: 'SMALLSERIAL'>, <TokenType.ROWVERSION: 'ROWVERSION'>, <TokenType.JSONB: 'JSONB'>, <TokenType.LONGTEXT: 'LONGTEXT'>, <TokenType.ARRAY: 'ARRAY'>, <TokenType.TIMESTAMP: 'TIMESTAMP'>, <TokenType.OBJECT: 'OBJECT'>, <TokenType.VARIANT: 'VARIANT'>, <TokenType.DATEMULTIRANGE: 'DATEMULTIRANGE'>, <TokenType.BIGDECIMAL: 'BIGDECIMAL'>, <TokenType.TINYINT: 'TINYINT'>, <TokenType.UBIGINT: 'UBIGINT'>, <TokenType.TSTZMULTIRANGE: 'TSTZMULTIRANGE'>, <TokenType.XML: 'XML'>, <TokenType.INT256: 'INT256'>, <TokenType.INT4MULTIRANGE: 'INT4MULTIRANGE'>, <TokenType.INTERVAL: 'INTERVAL'>, <TokenType.NCHAR: 'NCHAR'>, <TokenType.HSTORE: 'HSTORE'>, <TokenType.UTINYINT: 'UTINYINT'>, <TokenType.BINARY: 'BINARY'>, <TokenType.ENUM: 'ENUM'>, <TokenType.UINT: 'UINT'>, <TokenType.BOOLEAN: 'BOOLEAN'>, <TokenType.DATERANGE: 'DATERANGE'>, <TokenType.TIME: 'TIME'>, <TokenType.INT8MULTIRANGE: 'INT8MULTIRANGE'>, <TokenType.INT4RANGE: 'INT4RANGE'>, <TokenType.MAP: 'MAP'>, <TokenType.DECIMAL: 'DECIMAL'>}
SUBQUERY_PREDICATES = {<TokenType.ANY: 'ANY'>: <class 'sqlglot.expressions.Any'>, <TokenType.ALL: 'ALL'>: <class 'sqlglot.expressions.All'>, <TokenType.EXISTS: 'EXISTS'>: <class 'sqlglot.expressions.Exists'>, <TokenType.SOME: 'SOME'>: <class 'sqlglot.expressions.Any'>}
RESERVED_KEYWORDS = {<TokenType.R_BRACE: 'R_BRACE'>, <TokenType.L_BRACE: 'L_BRACE'>, <TokenType.HASH: 'HASH'>, <TokenType.EQ: 'EQ'>, <TokenType.IDENTIFIER: 'IDENTIFIER'>, <TokenType.LT: 'LT'>, <TokenType.STAR: 'STAR'>, <TokenType.SEMICOLON: 'SEMICOLON'>, <TokenType.QUOTE: 'QUOTE'>, <TokenType.BACKSLASH: 'BACKSLASH'>, <TokenType.DASH: 'DASH'>, <TokenType.NOT: 'NOT'>, <TokenType.SELECT: 'SELECT'>, <TokenType.L_BRACKET: 'L_BRACKET'>, <TokenType.COLON: 'COLON'>, <TokenType.PIPE: 'PIPE'>, <TokenType.R_PAREN: 'R_PAREN'>, <TokenType.COMMA: 'COMMA'>, <TokenType.PLUS: 'PLUS'>, <TokenType.MOD: 'MOD'>, <TokenType.L_PAREN: 'L_PAREN'>, <TokenType.CARET: 'CARET'>, <TokenType.TILDA: 'TILDA'>, <TokenType.PARAMETER: 'PARAMETER'>, <TokenType.SLASH: 'SLASH'>, <TokenType.AMP: 'AMP'>, <TokenType.DOT: 'DOT'>, <TokenType.PLACEHOLDER: 'PLACEHOLDER'>, <TokenType.R_BRACKET: 'R_BRACKET'>, <TokenType.GT: 'GT'>}
DB_CREATABLES = {<TokenType.VIEW: 'VIEW'>, <TokenType.DATABASE: 'DATABASE'>, <TokenType.DICTIONARY: 'DICTIONARY'>, <TokenType.TABLE: 'TABLE'>, <TokenType.SCHEMA: 'SCHEMA'>}
CREATABLES = {<TokenType.PROCEDURE: 'PROCEDURE'>, <TokenType.VIEW: 'VIEW'>, <TokenType.DATABASE: 'DATABASE'>, <TokenType.DICTIONARY: 'DICTIONARY'>, <TokenType.TABLE: 'TABLE'>, <TokenType.COLUMN: 'COLUMN'>, <TokenType.SCHEMA: 'SCHEMA'>, <TokenType.FUNCTION: 'FUNCTION'>, <TokenType.INDEX: 'INDEX'>}
ID_VAR_TOKENS = {<TokenType.SHOW: 'SHOW'>, <TokenType.MEDIUMBLOB: 'MEDIUMBLOB'>, <TokenType.GEOMETRY: 'GEOMETRY'>, <TokenType.ASC: 'ASC'>, <TokenType.MONEY: 'MONEY'>, <TokenType.SETTINGS: 'SETTINGS'>, <TokenType.SCHEMA: 'SCHEMA'>, <TokenType.RANGE: 'RANGE'>, <TokenType.FLOAT: 'FLOAT'>, <TokenType.STRUCT: 'STRUCT'>, <TokenType.MEDIUMTEXT: 'MEDIUMTEXT'>, <TokenType.HLLSKETCH: 'HLLSKETCH'>, <TokenType.CURRENT_DATE: 'CURRENT_DATE'>, <TokenType.INT: 'INT'>, <TokenType.NATURAL: 'NATURAL'>, <TokenType.TOP: 'TOP'>, <TokenType.CURRENT_USER: 'CURRENT_USER'>, <TokenType.SEMI: 'SEMI'>, <TokenType.CURRENT_DATETIME: 'CURRENT_DATETIME'>, <TokenType.FORMAT: 'FORMAT'>, <TokenType.PIVOT: 'PIVOT'>, <TokenType.NVARCHAR: 'NVARCHAR'>, <TokenType.NUMMULTIRANGE: 'NUMMULTIRANGE'>, <TokenType.INDEX: 'INDEX'>, <TokenType.TSRANGE: 'TSRANGE'>, <TokenType.ORDINALITY: 'ORDINALITY'>, <TokenType.USERDEFINED: 'USERDEFINED'>, <TokenType.CURRENT_TIME: 'CURRENT_TIME'>, <TokenType.DATABASE: 'DATABASE'>, <TokenType.LOAD: 'LOAD'>, <TokenType.TABLE: 'TABLE'>, <TokenType.USMALLINT: 'USMALLINT'>, <TokenType.SMALLSERIAL: 'SMALLSERIAL'>, <TokenType.ROWVERSION: 'ROWVERSION'>, <TokenType.JSONB: 'JSONB'>, <TokenType.LONGTEXT: 'LONGTEXT'>, <TokenType.ARRAY: 'ARRAY'>, <TokenType.VIEW: 'VIEW'>, <TokenType.FILTER: 'FILTER'>, <TokenType.BIGDECIMAL: 'BIGDECIMAL'>, <TokenType.UBIGINT: 'UBIGINT'>, <TokenType.TSTZMULTIRANGE: 'TSTZMULTIRANGE'>, <TokenType.CONSTRAINT: 'CONSTRAINT'>, <TokenType.NCHAR: 'NCHAR'>, <TokenType.REFERENCES: 'REFERENCES'>, <TokenType.WINDOW: 'WINDOW'>, <TokenType.DECIMAL: 'DECIMAL'>, <TokenType.SET: 'SET'>, <TokenType.DELETE: 'DELETE'>, <TokenType.COMMAND: 'COMMAND'>, <TokenType.CURRENT_TIMESTAMP: 'CURRENT_TIMESTAMP'>, <TokenType.ANTI: 'ANTI'>, <TokenType.DESCRIBE: 'DESCRIBE'>, <TokenType.DIV: 'DIV'>, <TokenType.TSMULTIRANGE: 'TSMULTIRANGE'>, <TokenType.UINT128: 'UINT128'>, <TokenType.PERCENT: 'PERCENT'>, <TokenType.COLLATE: 'COLLATE'>, <TokenType.AUTO_INCREMENT: 'AUTO_INCREMENT'>, <TokenType.CACHE: 'CACHE'>, <TokenType.VARBINARY: 'VARBINARY'>, <TokenType.DOUBLE: 'DOUBLE'>, <TokenType.DATE: 'DATE'>, <TokenType.NUMRANGE: 'NUMRANGE'>, <TokenType.NULLABLE: 'NULLABLE'>, <TokenType.SOME: 'SOME'>, <TokenType.DATEMULTIRANGE: 'DATEMULTIRANGE'>, <TokenType.EXECUTE: 'EXECUTE'>, <TokenType.UNPIVOT: 'UNPIVOT'>, <TokenType.APPLY: 'APPLY'>, <TokenType.INT256: 'INT256'>, <TokenType.INT4MULTIRANGE: 'INT4MULTIRANGE'>, <TokenType.UTINYINT: 'UTINYINT'>, <TokenType.ENUM: 'ENUM'>, <TokenType.DESC: 'DESC'>, <TokenType.VOLATILE: 'VOLATILE'>, <TokenType.BOOLEAN: 'BOOLEAN'>, <TokenType.INT4RANGE: 'INT4RANGE'>, <TokenType.CASE: 'CASE'>, <TokenType.RIGHT: 'RIGHT'>, <TokenType.INT8RANGE: 'INT8RANGE'>, <TokenType.OFFSET: 'OFFSET'>, <TokenType.LONGBLOB: 'LONGBLOB'>, <TokenType.INT128: 'INT128'>, <TokenType.UNIQUE: 'UNIQUE'>, <TokenType.TIMESTAMPTZ: 'TIMESTAMPTZ'>, <TokenType.TEMPORARY: 'TEMPORARY'>, <TokenType.BIGSERIAL: 'BIGSERIAL'>, <TokenType.UNIQUEIDENTIFIER: 'UNIQUEIDENTIFIER'>, <TokenType.TIMESTAMPLTZ: 'TIMESTAMPLTZ'>, <TokenType.BEGIN: 'BEGIN'>, <TokenType.PROCEDURE: 'PROCEDURE'>, <TokenType.FULL: 'FULL'>, <TokenType.ROWS: 'ROWS'>, <TokenType.DATETIME64: 'DATETIME64'>, <TokenType.VARCHAR: 'VARCHAR'>, <TokenType.NEXT: 'NEXT'>, <TokenType.TSTZRANGE: 'TSTZRANGE'>, <TokenType.FUNCTION: 'FUNCTION'>, <TokenType.END: 'END'>, <TokenType.SMALLMONEY: 'SMALLMONEY'>, <TokenType.BIGINT: 'BIGINT'>, <TokenType.GEOGRAPHY: 'GEOGRAPHY'>, <TokenType.CHAR: 'CHAR'>, <TokenType.ISNULL: 'ISNULL'>, <TokenType.IMAGE: 'IMAGE'>, <TokenType.SMALLINT: 'SMALLINT'>, <TokenType.VAR: 'VAR'>, <TokenType.FALSE: 'FALSE'>, <TokenType.MERGE: 'MERGE'>, <TokenType.TIMESTAMP: 'TIMESTAMP'>, <TokenType.VARIANT: 'VARIANT'>, <TokenType.XML: 'XML'>, <TokenType.OVERWRITE: 'OVERWRITE'>, <TokenType.IS: 'IS'>, <TokenType.INTERVAL: 'INTERVAL'>, <TokenType.FIRST: 'FIRST'>, <TokenType.COLUMN: 'COLUMN'>, <TokenType.BINARY: 'BINARY'>, <TokenType.KEEP: 'KEEP'>, <TokenType.DATERANGE: 'DATERANGE'>, <TokenType.MAP: 'MAP'>, <TokenType.TIME: 'TIME'>, <TokenType.DICTIONARY: 'DICTIONARY'>, <TokenType.SERIAL: 'SERIAL'>, <TokenType.ALL: 'ALL'>, <TokenType.BIT: 'BIT'>, <TokenType.UPDATE: 'UPDATE'>, <TokenType.TEXT: 'TEXT'>, <TokenType.COMMENT: 'COMMENT'>, <TokenType.ANY: 'ANY'>, <TokenType.PSEUDO_TYPE: 'PSEUDO_TYPE'>, <TokenType.ESCAPE: 'ESCAPE'>, <TokenType.UINT256: 'UINT256'>, <TokenType.SUPER: 'SUPER'>, <TokenType.JSON: 'JSON'>, <TokenType.LEFT: 'LEFT'>, <TokenType.IF: 'IF'>, <TokenType.TRUE: 'TRUE'>, <TokenType.UUID: 'UUID'>, <TokenType.HSTORE: 'HSTORE'>, <TokenType.EXISTS: 'EXISTS'>, <TokenType.DATETIME: 'DATETIME'>, <TokenType.PRAGMA: 'PRAGMA'>, <TokenType.INET: 'INET'>, <TokenType.COMMIT: 'COMMIT'>, <TokenType.OBJECT: 'OBJECT'>, <TokenType.PARTITION: 'PARTITION'>, <TokenType.TINYINT: 'TINYINT'>, <TokenType.ROW: 'ROW'>, <TokenType.DEFAULT: 'DEFAULT'>, <TokenType.UINT: 'UINT'>, <TokenType.INT8MULTIRANGE: 'INT8MULTIRANGE'>}
INTERVAL_VARS = {<TokenType.SHOW: 'SHOW'>, <TokenType.MEDIUMBLOB: 'MEDIUMBLOB'>, <TokenType.GEOMETRY: 'GEOMETRY'>, <TokenType.ASC: 'ASC'>, <TokenType.MONEY: 'MONEY'>, <TokenType.SETTINGS: 'SETTINGS'>, <TokenType.SCHEMA: 'SCHEMA'>, <TokenType.RANGE: 'RANGE'>, <TokenType.FLOAT: 'FLOAT'>, <TokenType.STRUCT: 'STRUCT'>, <TokenType.MEDIUMTEXT: 'MEDIUMTEXT'>, <TokenType.HLLSKETCH: 'HLLSKETCH'>, <TokenType.CURRENT_DATE: 'CURRENT_DATE'>, <TokenType.INT: 'INT'>, <TokenType.NATURAL: 'NATURAL'>, <TokenType.TOP: 'TOP'>, <TokenType.CURRENT_USER: 'CURRENT_USER'>, <TokenType.SEMI: 'SEMI'>, <TokenType.CURRENT_DATETIME: 'CURRENT_DATETIME'>, <TokenType.FORMAT: 'FORMAT'>, <TokenType.PIVOT: 'PIVOT'>, <TokenType.NVARCHAR: 'NVARCHAR'>, <TokenType.NUMMULTIRANGE: 'NUMMULTIRANGE'>, <TokenType.INDEX: 'INDEX'>, <TokenType.TSRANGE: 'TSRANGE'>, <TokenType.ORDINALITY: 'ORDINALITY'>, <TokenType.USERDEFINED: 'USERDEFINED'>, <TokenType.CURRENT_TIME: 'CURRENT_TIME'>, <TokenType.DATABASE: 'DATABASE'>, <TokenType.LOAD: 'LOAD'>, <TokenType.TABLE: 'TABLE'>, <TokenType.USMALLINT: 'USMALLINT'>, <TokenType.SMALLSERIAL: 'SMALLSERIAL'>, <TokenType.ROWVERSION: 'ROWVERSION'>, <TokenType.JSONB: 'JSONB'>, <TokenType.LONGTEXT: 'LONGTEXT'>, <TokenType.ARRAY: 'ARRAY'>, <TokenType.VIEW: 'VIEW'>, <TokenType.FILTER: 'FILTER'>, <TokenType.BIGDECIMAL: 'BIGDECIMAL'>, <TokenType.UBIGINT: 'UBIGINT'>, <TokenType.TSTZMULTIRANGE: 'TSTZMULTIRANGE'>, <TokenType.CONSTRAINT: 'CONSTRAINT'>, <TokenType.NCHAR: 'NCHAR'>, <TokenType.REFERENCES: 'REFERENCES'>, <TokenType.WINDOW: 'WINDOW'>, <TokenType.DECIMAL: 'DECIMAL'>, <TokenType.SET: 'SET'>, <TokenType.DELETE: 'DELETE'>, <TokenType.COMMAND: 'COMMAND'>, <TokenType.CURRENT_TIMESTAMP: 'CURRENT_TIMESTAMP'>, <TokenType.ANTI: 'ANTI'>, <TokenType.DESCRIBE: 'DESCRIBE'>, <TokenType.DIV: 'DIV'>, <TokenType.TSMULTIRANGE: 'TSMULTIRANGE'>, <TokenType.UINT128: 'UINT128'>, <TokenType.PERCENT: 'PERCENT'>, <TokenType.COLLATE: 'COLLATE'>, <TokenType.AUTO_INCREMENT: 'AUTO_INCREMENT'>, <TokenType.CACHE: 'CACHE'>, <TokenType.VARBINARY: 'VARBINARY'>, <TokenType.DOUBLE: 'DOUBLE'>, <TokenType.DATE: 'DATE'>, <TokenType.NUMRANGE: 'NUMRANGE'>, <TokenType.NULLABLE: 'NULLABLE'>, <TokenType.SOME: 'SOME'>, <TokenType.DATEMULTIRANGE: 'DATEMULTIRANGE'>, <TokenType.EXECUTE: 'EXECUTE'>, <TokenType.UNPIVOT: 'UNPIVOT'>, <TokenType.APPLY: 'APPLY'>, <TokenType.INT256: 'INT256'>, <TokenType.INT4MULTIRANGE: 'INT4MULTIRANGE'>, <TokenType.UTINYINT: 'UTINYINT'>, <TokenType.ENUM: 'ENUM'>, <TokenType.DESC: 'DESC'>, <TokenType.VOLATILE: 'VOLATILE'>, <TokenType.BOOLEAN: 'BOOLEAN'>, <TokenType.INT4RANGE: 'INT4RANGE'>, <TokenType.CASE: 'CASE'>, <TokenType.RIGHT: 'RIGHT'>, <TokenType.INT8RANGE: 'INT8RANGE'>, <TokenType.OFFSET: 'OFFSET'>, <TokenType.LONGBLOB: 'LONGBLOB'>, <TokenType.INT128: 'INT128'>, <TokenType.UNIQUE: 'UNIQUE'>, <TokenType.TIMESTAMPTZ: 'TIMESTAMPTZ'>, <TokenType.TEMPORARY: 'TEMPORARY'>, <TokenType.BIGSERIAL: 'BIGSERIAL'>, <TokenType.UNIQUEIDENTIFIER: 'UNIQUEIDENTIFIER'>, <TokenType.TIMESTAMPLTZ: 'TIMESTAMPLTZ'>, <TokenType.BEGIN: 'BEGIN'>, <TokenType.PROCEDURE: 'PROCEDURE'>, <TokenType.FULL: 'FULL'>, <TokenType.ROWS: 'ROWS'>, <TokenType.DATETIME64: 'DATETIME64'>, <TokenType.VARCHAR: 'VARCHAR'>, <TokenType.NEXT: 'NEXT'>, <TokenType.TSTZRANGE: 'TSTZRANGE'>, <TokenType.FUNCTION: 'FUNCTION'>, <TokenType.SMALLMONEY: 'SMALLMONEY'>, <TokenType.BIGINT: 'BIGINT'>, <TokenType.GEOGRAPHY: 'GEOGRAPHY'>, <TokenType.CHAR: 'CHAR'>, <TokenType.ISNULL: 'ISNULL'>, <TokenType.IMAGE: 'IMAGE'>, <TokenType.SMALLINT: 'SMALLINT'>, <TokenType.VAR: 'VAR'>, <TokenType.FALSE: 'FALSE'>, <TokenType.MERGE: 'MERGE'>, <TokenType.TIMESTAMP: 'TIMESTAMP'>, <TokenType.VARIANT: 'VARIANT'>, <TokenType.XML: 'XML'>, <TokenType.OVERWRITE: 'OVERWRITE'>, <TokenType.IS: 'IS'>, <TokenType.INTERVAL: 'INTERVAL'>, <TokenType.FIRST: 'FIRST'>, <TokenType.COLUMN: 'COLUMN'>, <TokenType.BINARY: 'BINARY'>, <TokenType.KEEP: 'KEEP'>, <TokenType.DATERANGE: 'DATERANGE'>, <TokenType.MAP: 'MAP'>, <TokenType.TIME: 'TIME'>, <TokenType.DICTIONARY: 'DICTIONARY'>, <TokenType.SERIAL: 'SERIAL'>, <TokenType.ALL: 'ALL'>, <TokenType.BIT: 'BIT'>, <TokenType.UPDATE: 'UPDATE'>, <TokenType.TEXT: 'TEXT'>, <TokenType.COMMENT: 'COMMENT'>, <TokenType.ANY: 'ANY'>, <TokenType.PSEUDO_TYPE: 'PSEUDO_TYPE'>, <TokenType.ESCAPE: 'ESCAPE'>, <TokenType.UINT256: 'UINT256'>, <TokenType.SUPER: 'SUPER'>, <TokenType.JSON: 'JSON'>, <TokenType.LEFT: 'LEFT'>, <TokenType.IF: 'IF'>, <TokenType.TRUE: 'TRUE'>, <TokenType.UUID: 'UUID'>, <TokenType.HSTORE: 'HSTORE'>, <TokenType.EXISTS: 'EXISTS'>, <TokenType.DATETIME: 'DATETIME'>, <TokenType.PRAGMA: 'PRAGMA'>, <TokenType.INET: 'INET'>, <TokenType.COMMIT: 'COMMIT'>, <TokenType.OBJECT: 'OBJECT'>, <TokenType.PARTITION: 'PARTITION'>, <TokenType.TINYINT: 'TINYINT'>, <TokenType.ROW: 'ROW'>, <TokenType.DEFAULT: 'DEFAULT'>, <TokenType.UINT: 'UINT'>, <TokenType.INT8MULTIRANGE: 'INT8MULTIRANGE'>}
TABLE_ALIAS_TOKENS = {<TokenType.SHOW: 'SHOW'>, <TokenType.MEDIUMBLOB: 'MEDIUMBLOB'>, <TokenType.GEOMETRY: 'GEOMETRY'>, <TokenType.ASC: 'ASC'>, <TokenType.MONEY: 'MONEY'>, <TokenType.SETTINGS: 'SETTINGS'>, <TokenType.SCHEMA: 'SCHEMA'>, <TokenType.RANGE: 'RANGE'>, <TokenType.FLOAT: 'FLOAT'>, <TokenType.STRUCT: 'STRUCT'>, <TokenType.MEDIUMTEXT: 'MEDIUMTEXT'>, <TokenType.HLLSKETCH: 'HLLSKETCH'>, <TokenType.CURRENT_DATE: 'CURRENT_DATE'>, <TokenType.INT: 'INT'>, <TokenType.TOP: 'TOP'>, <TokenType.CURRENT_USER: 'CURRENT_USER'>, <TokenType.SEMI: 'SEMI'>, <TokenType.CURRENT_DATETIME: 'CURRENT_DATETIME'>, <TokenType.FORMAT: 'FORMAT'>, <TokenType.PIVOT: 'PIVOT'>, <TokenType.NVARCHAR: 'NVARCHAR'>, <TokenType.NUMMULTIRANGE: 'NUMMULTIRANGE'>, <TokenType.INDEX: 'INDEX'>, <TokenType.TSRANGE: 'TSRANGE'>, <TokenType.ORDINALITY: 'ORDINALITY'>, <TokenType.USERDEFINED: 'USERDEFINED'>, <TokenType.CURRENT_TIME: 'CURRENT_TIME'>, <TokenType.DATABASE: 'DATABASE'>, <TokenType.LOAD: 'LOAD'>, <TokenType.TABLE: 'TABLE'>, <TokenType.USMALLINT: 'USMALLINT'>, <TokenType.SMALLSERIAL: 'SMALLSERIAL'>, <TokenType.ROWVERSION: 'ROWVERSION'>, <TokenType.JSONB: 'JSONB'>, <TokenType.LONGTEXT: 'LONGTEXT'>, <TokenType.ARRAY: 'ARRAY'>, <TokenType.VIEW: 'VIEW'>, <TokenType.FILTER: 'FILTER'>, <TokenType.BIGDECIMAL: 'BIGDECIMAL'>, <TokenType.UBIGINT: 'UBIGINT'>, <TokenType.TSTZMULTIRANGE: 'TSTZMULTIRANGE'>, <TokenType.CONSTRAINT: 'CONSTRAINT'>, <TokenType.NCHAR: 'NCHAR'>, <TokenType.REFERENCES: 'REFERENCES'>, <TokenType.DECIMAL: 'DECIMAL'>, <TokenType.SET: 'SET'>, <TokenType.DELETE: 'DELETE'>, <TokenType.COMMAND: 'COMMAND'>, <TokenType.CURRENT_TIMESTAMP: 'CURRENT_TIMESTAMP'>, <TokenType.ANTI: 'ANTI'>, <TokenType.DESCRIBE: 'DESCRIBE'>, <TokenType.DIV: 'DIV'>, <TokenType.TSMULTIRANGE: 'TSMULTIRANGE'>, <TokenType.UINT128: 'UINT128'>, <TokenType.PERCENT: 'PERCENT'>, <TokenType.COLLATE: 'COLLATE'>, <TokenType.AUTO_INCREMENT: 'AUTO_INCREMENT'>, <TokenType.CACHE: 'CACHE'>, <TokenType.VARBINARY: 'VARBINARY'>, <TokenType.DOUBLE: 'DOUBLE'>, <TokenType.DATE: 'DATE'>, <TokenType.NUMRANGE: 'NUMRANGE'>, <TokenType.NULLABLE: 'NULLABLE'>, <TokenType.SOME: 'SOME'>, <TokenType.DATEMULTIRANGE: 'DATEMULTIRANGE'>, <TokenType.EXECUTE: 'EXECUTE'>, <TokenType.UNPIVOT: 'UNPIVOT'>, <TokenType.INT256: 'INT256'>, <TokenType.INT4MULTIRANGE: 'INT4MULTIRANGE'>, <TokenType.UTINYINT: 'UTINYINT'>, <TokenType.ENUM: 'ENUM'>, <TokenType.DESC: 'DESC'>, <TokenType.VOLATILE: 'VOLATILE'>, <TokenType.BOOLEAN: 'BOOLEAN'>, <TokenType.INT4RANGE: 'INT4RANGE'>, <TokenType.CASE: 'CASE'>, <TokenType.INT8RANGE: 'INT8RANGE'>, <TokenType.LONGBLOB: 'LONGBLOB'>, <TokenType.INT128: 'INT128'>, <TokenType.UNIQUE: 'UNIQUE'>, <TokenType.TIMESTAMPTZ: 'TIMESTAMPTZ'>, <TokenType.TEMPORARY: 'TEMPORARY'>, <TokenType.BIGSERIAL: 'BIGSERIAL'>, <TokenType.UNIQUEIDENTIFIER: 'UNIQUEIDENTIFIER'>, <TokenType.TIMESTAMPLTZ: 'TIMESTAMPLTZ'>, <TokenType.BEGIN: 'BEGIN'>, <TokenType.PROCEDURE: 'PROCEDURE'>, <TokenType.ROWS: 'ROWS'>, <TokenType.DATETIME64: 'DATETIME64'>, <TokenType.VARCHAR: 'VARCHAR'>, <TokenType.NEXT: 'NEXT'>, <TokenType.TSTZRANGE: 'TSTZRANGE'>, <TokenType.FUNCTION: 'FUNCTION'>, <TokenType.END: 'END'>, <TokenType.SMALLMONEY: 'SMALLMONEY'>, <TokenType.BIGINT: 'BIGINT'>, <TokenType.GEOGRAPHY: 'GEOGRAPHY'>, <TokenType.CHAR: 'CHAR'>, <TokenType.ISNULL: 'ISNULL'>, <TokenType.IMAGE: 'IMAGE'>, <TokenType.SMALLINT: 'SMALLINT'>, <TokenType.VAR: 'VAR'>, <TokenType.FALSE: 'FALSE'>, <TokenType.MERGE: 'MERGE'>, <TokenType.TIMESTAMP: 'TIMESTAMP'>, <TokenType.VARIANT: 'VARIANT'>, <TokenType.XML: 'XML'>, <TokenType.OVERWRITE: 'OVERWRITE'>, <TokenType.IS: 'IS'>, <TokenType.INTERVAL: 'INTERVAL'>, <TokenType.FIRST: 'FIRST'>, <TokenType.COLUMN: 'COLUMN'>, <TokenType.BINARY: 'BINARY'>, <TokenType.KEEP: 'KEEP'>, <TokenType.DATERANGE: 'DATERANGE'>, <TokenType.MAP: 'MAP'>, <TokenType.TIME: 'TIME'>, <TokenType.DICTIONARY: 'DICTIONARY'>, <TokenType.SERIAL: 'SERIAL'>, <TokenType.ALL: 'ALL'>, <TokenType.BIT: 'BIT'>, <TokenType.UPDATE: 'UPDATE'>, <TokenType.TEXT: 'TEXT'>, <TokenType.COMMENT: 'COMMENT'>, <TokenType.ANY: 'ANY'>, <TokenType.PSEUDO_TYPE: 'PSEUDO_TYPE'>, <TokenType.ESCAPE: 'ESCAPE'>, <TokenType.UINT256: 'UINT256'>, <TokenType.SUPER: 'SUPER'>, <TokenType.JSON: 'JSON'>, <TokenType.IF: 'IF'>, <TokenType.TRUE: 'TRUE'>, <TokenType.UUID: 'UUID'>, <TokenType.HSTORE: 'HSTORE'>, <TokenType.EXISTS: 'EXISTS'>, <TokenType.DATETIME: 'DATETIME'>, <TokenType.PRAGMA: 'PRAGMA'>, <TokenType.INET: 'INET'>, <TokenType.COMMIT: 'COMMIT'>, <TokenType.OBJECT: 'OBJECT'>, <TokenType.PARTITION: 'PARTITION'>, <TokenType.TINYINT: 'TINYINT'>, <TokenType.ROW: 'ROW'>, <TokenType.DEFAULT: 'DEFAULT'>, <TokenType.UINT: 'UINT'>, <TokenType.INT8MULTIRANGE: 'INT8MULTIRANGE'>}
COMMENT_TABLE_ALIAS_TOKENS = {<TokenType.SHOW: 'SHOW'>, <TokenType.MEDIUMBLOB: 'MEDIUMBLOB'>, <TokenType.GEOMETRY: 'GEOMETRY'>, <TokenType.ASC: 'ASC'>, <TokenType.MONEY: 'MONEY'>, <TokenType.SETTINGS: 'SETTINGS'>, <TokenType.SCHEMA: 'SCHEMA'>, <TokenType.RANGE: 'RANGE'>, <TokenType.FLOAT: 'FLOAT'>, <TokenType.STRUCT: 'STRUCT'>, <TokenType.MEDIUMTEXT: 'MEDIUMTEXT'>, <TokenType.HLLSKETCH: 'HLLSKETCH'>, <TokenType.CURRENT_DATE: 'CURRENT_DATE'>, <TokenType.INT: 'INT'>, <TokenType.TOP: 'TOP'>, <TokenType.CURRENT_USER: 'CURRENT_USER'>, <TokenType.SEMI: 'SEMI'>, <TokenType.CURRENT_DATETIME: 'CURRENT_DATETIME'>, <TokenType.FORMAT: 'FORMAT'>, <TokenType.PIVOT: 'PIVOT'>, <TokenType.NVARCHAR: 'NVARCHAR'>, <TokenType.NUMMULTIRANGE: 'NUMMULTIRANGE'>, <TokenType.INDEX: 'INDEX'>, <TokenType.TSRANGE: 'TSRANGE'>, <TokenType.ORDINALITY: 'ORDINALITY'>, <TokenType.USERDEFINED: 'USERDEFINED'>, <TokenType.CURRENT_TIME: 'CURRENT_TIME'>, <TokenType.DATABASE: 'DATABASE'>, <TokenType.LOAD: 'LOAD'>, <TokenType.TABLE: 'TABLE'>, <TokenType.USMALLINT: 'USMALLINT'>, <TokenType.SMALLSERIAL: 'SMALLSERIAL'>, <TokenType.ROWVERSION: 'ROWVERSION'>, <TokenType.JSONB: 'JSONB'>, <TokenType.LONGTEXT: 'LONGTEXT'>, <TokenType.ARRAY: 'ARRAY'>, <TokenType.VIEW: 'VIEW'>, <TokenType.FILTER: 'FILTER'>, <TokenType.BIGDECIMAL: 'BIGDECIMAL'>, <TokenType.UBIGINT: 'UBIGINT'>, <TokenType.TSTZMULTIRANGE: 'TSTZMULTIRANGE'>, <TokenType.CONSTRAINT: 'CONSTRAINT'>, <TokenType.NCHAR: 'NCHAR'>, <TokenType.REFERENCES: 'REFERENCES'>, <TokenType.DECIMAL: 'DECIMAL'>, <TokenType.SET: 'SET'>, <TokenType.DELETE: 'DELETE'>, <TokenType.COMMAND: 'COMMAND'>, <TokenType.CURRENT_TIMESTAMP: 'CURRENT_TIMESTAMP'>, <TokenType.ANTI: 'ANTI'>, <TokenType.DESCRIBE: 'DESCRIBE'>, <TokenType.DIV: 'DIV'>, <TokenType.TSMULTIRANGE: 'TSMULTIRANGE'>, <TokenType.UINT128: 'UINT128'>, <TokenType.PERCENT: 'PERCENT'>, <TokenType.COLLATE: 'COLLATE'>, <TokenType.AUTO_INCREMENT: 'AUTO_INCREMENT'>, <TokenType.CACHE: 'CACHE'>, <TokenType.VARBINARY: 'VARBINARY'>, <TokenType.DOUBLE: 'DOUBLE'>, <TokenType.DATE: 'DATE'>, <TokenType.NUMRANGE: 'NUMRANGE'>, <TokenType.NULLABLE: 'NULLABLE'>, <TokenType.SOME: 'SOME'>, <TokenType.DATEMULTIRANGE: 'DATEMULTIRANGE'>, <TokenType.EXECUTE: 'EXECUTE'>, <TokenType.UNPIVOT: 'UNPIVOT'>, <TokenType.INT256: 'INT256'>, <TokenType.INT4MULTIRANGE: 'INT4MULTIRANGE'>, <TokenType.UTINYINT: 'UTINYINT'>, <TokenType.ENUM: 'ENUM'>, <TokenType.DESC: 'DESC'>, <TokenType.VOLATILE: 'VOLATILE'>, <TokenType.BOOLEAN: 'BOOLEAN'>, <TokenType.INT4RANGE: 'INT4RANGE'>, <TokenType.CASE: 'CASE'>, <TokenType.INT8RANGE: 'INT8RANGE'>, <TokenType.LONGBLOB: 'LONGBLOB'>, <TokenType.INT128: 'INT128'>, <TokenType.UNIQUE: 'UNIQUE'>, <TokenType.TIMESTAMPTZ: 'TIMESTAMPTZ'>, <TokenType.TEMPORARY: 'TEMPORARY'>, <TokenType.BIGSERIAL: 'BIGSERIAL'>, <TokenType.UNIQUEIDENTIFIER: 'UNIQUEIDENTIFIER'>, <TokenType.TIMESTAMPLTZ: 'TIMESTAMPLTZ'>, <TokenType.BEGIN: 'BEGIN'>, <TokenType.PROCEDURE: 'PROCEDURE'>, <TokenType.ROWS: 'ROWS'>, <TokenType.DATETIME64: 'DATETIME64'>, <TokenType.VARCHAR: 'VARCHAR'>, <TokenType.NEXT: 'NEXT'>, <TokenType.TSTZRANGE: 'TSTZRANGE'>, <TokenType.FUNCTION: 'FUNCTION'>, <TokenType.END: 'END'>, <TokenType.SMALLMONEY: 'SMALLMONEY'>, <TokenType.BIGINT: 'BIGINT'>, <TokenType.GEOGRAPHY: 'GEOGRAPHY'>, <TokenType.CHAR: 'CHAR'>, <TokenType.ISNULL: 'ISNULL'>, <TokenType.IMAGE: 'IMAGE'>, <TokenType.SMALLINT: 'SMALLINT'>, <TokenType.VAR: 'VAR'>, <TokenType.FALSE: 'FALSE'>, <TokenType.MERGE: 'MERGE'>, <TokenType.TIMESTAMP: 'TIMESTAMP'>, <TokenType.VARIANT: 'VARIANT'>, <TokenType.XML: 'XML'>, <TokenType.OVERWRITE: 'OVERWRITE'>, <TokenType.INTERVAL: 'INTERVAL'>, <TokenType.FIRST: 'FIRST'>, <TokenType.COLUMN: 'COLUMN'>, <TokenType.BINARY: 'BINARY'>, <TokenType.KEEP: 'KEEP'>, <TokenType.DATERANGE: 'DATERANGE'>, <TokenType.MAP: 'MAP'>, <TokenType.TIME: 'TIME'>, <TokenType.DICTIONARY: 'DICTIONARY'>, <TokenType.SERIAL: 'SERIAL'>, <TokenType.ALL: 'ALL'>, <TokenType.BIT: 'BIT'>, <TokenType.UPDATE: 'UPDATE'>, <TokenType.TEXT: 'TEXT'>, <TokenType.COMMENT: 'COMMENT'>, <TokenType.ANY: 'ANY'>, <TokenType.PSEUDO_TYPE: 'PSEUDO_TYPE'>, <TokenType.ESCAPE: 'ESCAPE'>, <TokenType.UINT256: 'UINT256'>, <TokenType.SUPER: 'SUPER'>, <TokenType.JSON: 'JSON'>, <TokenType.IF: 'IF'>, <TokenType.TRUE: 'TRUE'>, <TokenType.UUID: 'UUID'>, <TokenType.HSTORE: 'HSTORE'>, <TokenType.EXISTS: 'EXISTS'>, <TokenType.DATETIME: 'DATETIME'>, <TokenType.PRAGMA: 'PRAGMA'>, <TokenType.INET: 'INET'>, <TokenType.COMMIT: 'COMMIT'>, <TokenType.OBJECT: 'OBJECT'>, <TokenType.PARTITION: 'PARTITION'>, <TokenType.TINYINT: 'TINYINT'>, <TokenType.ROW: 'ROW'>, <TokenType.DEFAULT: 'DEFAULT'>, <TokenType.UINT: 'UINT'>, <TokenType.INT8MULTIRANGE: 'INT8MULTIRANGE'>}
UPDATE_ALIAS_TOKENS = {<TokenType.SHOW: 'SHOW'>, <TokenType.MEDIUMBLOB: 'MEDIUMBLOB'>, <TokenType.GEOMETRY: 'GEOMETRY'>, <TokenType.ASC: 'ASC'>, <TokenType.MONEY: 'MONEY'>, <TokenType.SETTINGS: 'SETTINGS'>, <TokenType.SCHEMA: 'SCHEMA'>, <TokenType.RANGE: 'RANGE'>, <TokenType.FLOAT: 'FLOAT'>, <TokenType.STRUCT: 'STRUCT'>, <TokenType.MEDIUMTEXT: 'MEDIUMTEXT'>, <TokenType.HLLSKETCH: 'HLLSKETCH'>, <TokenType.CURRENT_DATE: 'CURRENT_DATE'>, <TokenType.INT: 'INT'>, <TokenType.TOP: 'TOP'>, <TokenType.CURRENT_USER: 'CURRENT_USER'>, <TokenType.SEMI: 'SEMI'>, <TokenType.CURRENT_DATETIME: 'CURRENT_DATETIME'>, <TokenType.FORMAT: 'FORMAT'>, <TokenType.PIVOT: 'PIVOT'>, <TokenType.NVARCHAR: 'NVARCHAR'>, <TokenType.NUMMULTIRANGE: 'NUMMULTIRANGE'>, <TokenType.INDEX: 'INDEX'>, <TokenType.TSRANGE: 'TSRANGE'>, <TokenType.ORDINALITY: 'ORDINALITY'>, <TokenType.USERDEFINED: 'USERDEFINED'>, <TokenType.CURRENT_TIME: 'CURRENT_TIME'>, <TokenType.DATABASE: 'DATABASE'>, <TokenType.LOAD: 'LOAD'>, <TokenType.TABLE: 'TABLE'>, <TokenType.USMALLINT: 'USMALLINT'>, <TokenType.SMALLSERIAL: 'SMALLSERIAL'>, <TokenType.ROWVERSION: 'ROWVERSION'>, <TokenType.JSONB: 'JSONB'>, <TokenType.LONGTEXT: 'LONGTEXT'>, <TokenType.ARRAY: 'ARRAY'>, <TokenType.VIEW: 'VIEW'>, <TokenType.FILTER: 'FILTER'>, <TokenType.BIGDECIMAL: 'BIGDECIMAL'>, <TokenType.UBIGINT: 'UBIGINT'>, <TokenType.TSTZMULTIRANGE: 'TSTZMULTIRANGE'>, <TokenType.CONSTRAINT: 'CONSTRAINT'>, <TokenType.NCHAR: 'NCHAR'>, <TokenType.REFERENCES: 'REFERENCES'>, <TokenType.DECIMAL: 'DECIMAL'>, <TokenType.DELETE: 'DELETE'>, <TokenType.COMMAND: 'COMMAND'>, <TokenType.CURRENT_TIMESTAMP: 'CURRENT_TIMESTAMP'>, <TokenType.ANTI: 'ANTI'>, <TokenType.DESCRIBE: 'DESCRIBE'>, <TokenType.DIV: 'DIV'>, <TokenType.TSMULTIRANGE: 'TSMULTIRANGE'>, <TokenType.UINT128: 'UINT128'>, <TokenType.PERCENT: 'PERCENT'>, <TokenType.COLLATE: 'COLLATE'>, <TokenType.AUTO_INCREMENT: 'AUTO_INCREMENT'>, <TokenType.CACHE: 'CACHE'>, <TokenType.VARBINARY: 'VARBINARY'>, <TokenType.DOUBLE: 'DOUBLE'>, <TokenType.DATE: 'DATE'>, <TokenType.NUMRANGE: 'NUMRANGE'>, <TokenType.NULLABLE: 'NULLABLE'>, <TokenType.SOME: 'SOME'>, <TokenType.DATEMULTIRANGE: 'DATEMULTIRANGE'>, <TokenType.EXECUTE: 'EXECUTE'>, <TokenType.UNPIVOT: 'UNPIVOT'>, <TokenType.INT256: 'INT256'>, <TokenType.INT4MULTIRANGE: 'INT4MULTIRANGE'>, <TokenType.UTINYINT: 'UTINYINT'>, <TokenType.ENUM: 'ENUM'>, <TokenType.DESC: 'DESC'>, <TokenType.VOLATILE: 'VOLATILE'>, <TokenType.BOOLEAN: 'BOOLEAN'>, <TokenType.INT4RANGE: 'INT4RANGE'>, <TokenType.CASE: 'CASE'>, <TokenType.INT8RANGE: 'INT8RANGE'>, <TokenType.LONGBLOB: 'LONGBLOB'>, <TokenType.INT128: 'INT128'>, <TokenType.UNIQUE: 'UNIQUE'>, <TokenType.TIMESTAMPTZ: 'TIMESTAMPTZ'>, <TokenType.TEMPORARY: 'TEMPORARY'>, <TokenType.BIGSERIAL: 'BIGSERIAL'>, <TokenType.UNIQUEIDENTIFIER: 'UNIQUEIDENTIFIER'>, <TokenType.TIMESTAMPLTZ: 'TIMESTAMPLTZ'>, <TokenType.BEGIN: 'BEGIN'>, <TokenType.PROCEDURE: 'PROCEDURE'>, <TokenType.ROWS: 'ROWS'>, <TokenType.DATETIME64: 'DATETIME64'>, <TokenType.VARCHAR: 'VARCHAR'>, <TokenType.NEXT: 'NEXT'>, <TokenType.TSTZRANGE: 'TSTZRANGE'>, <TokenType.FUNCTION: 'FUNCTION'>, <TokenType.END: 'END'>, <TokenType.SMALLMONEY: 'SMALLMONEY'>, <TokenType.BIGINT: 'BIGINT'>, <TokenType.GEOGRAPHY: 'GEOGRAPHY'>, <TokenType.CHAR: 'CHAR'>, <TokenType.ISNULL: 'ISNULL'>, <TokenType.IMAGE: 'IMAGE'>, <TokenType.SMALLINT: 'SMALLINT'>, <TokenType.VAR: 'VAR'>, <TokenType.FALSE: 'FALSE'>, <TokenType.MERGE: 'MERGE'>, <TokenType.TIMESTAMP: 'TIMESTAMP'>, <TokenType.VARIANT: 'VARIANT'>, <TokenType.XML: 'XML'>, <TokenType.OVERWRITE: 'OVERWRITE'>, <TokenType.IS: 'IS'>, <TokenType.INTERVAL: 'INTERVAL'>, <TokenType.FIRST: 'FIRST'>, <TokenType.COLUMN: 'COLUMN'>, <TokenType.BINARY: 'BINARY'>, <TokenType.KEEP: 'KEEP'>, <TokenType.DATERANGE: 'DATERANGE'>, <TokenType.MAP: 'MAP'>, <TokenType.TIME: 'TIME'>, <TokenType.DICTIONARY: 'DICTIONARY'>, <TokenType.SERIAL: 'SERIAL'>, <TokenType.ALL: 'ALL'>, <TokenType.BIT: 'BIT'>, <TokenType.UPDATE: 'UPDATE'>, <TokenType.TEXT: 'TEXT'>, <TokenType.COMMENT: 'COMMENT'>, <TokenType.ANY: 'ANY'>, <TokenType.PSEUDO_TYPE: 'PSEUDO_TYPE'>, <TokenType.ESCAPE: 'ESCAPE'>, <TokenType.UINT256: 'UINT256'>, <TokenType.SUPER: 'SUPER'>, <TokenType.JSON: 'JSON'>, <TokenType.IF: 'IF'>, <TokenType.TRUE: 'TRUE'>, <TokenType.UUID: 'UUID'>, <TokenType.HSTORE: 'HSTORE'>, <TokenType.EXISTS: 'EXISTS'>, <TokenType.DATETIME: 'DATETIME'>, <TokenType.PRAGMA: 'PRAGMA'>, <TokenType.INET: 'INET'>, <TokenType.COMMIT: 'COMMIT'>, <TokenType.OBJECT: 'OBJECT'>, <TokenType.PARTITION: 'PARTITION'>, <TokenType.TINYINT: 'TINYINT'>, <TokenType.ROW: 'ROW'>, <TokenType.DEFAULT: 'DEFAULT'>, <TokenType.UINT: 'UINT'>, <TokenType.INT8MULTIRANGE: 'INT8MULTIRANGE'>}
TRIM_TYPES = {'BOTH', 'LEADING', 'TRAILING'}
FUNC_TOKENS = {<TokenType.MEDIUMBLOB: 'MEDIUMBLOB'>, <TokenType.GEOMETRY: 'GEOMETRY'>, <TokenType.INT8RANGE: 'INT8RANGE'>, <TokenType.MONEY: 'MONEY'>, <TokenType.OFFSET: 'OFFSET'>, <TokenType.LONGBLOB: 'LONGBLOB'>, <TokenType.INT128: 'INT128'>, <TokenType.IDENTIFIER: 'IDENTIFIER'>, <TokenType.TIMESTAMPTZ: 'TIMESTAMPTZ'>, <TokenType.BIGSERIAL: 'BIGSERIAL'>, <TokenType.RANGE: 'RANGE'>, <TokenType.UNIQUEIDENTIFIER: 'UNIQUEIDENTIFIER'>, <TokenType.FLOAT: 'FLOAT'>, <TokenType.TIMESTAMPLTZ: 'TIMESTAMPLTZ'>, <TokenType.CURRENT_DATE: 'CURRENT_DATE'>, <TokenType.REPLACE: 'REPLACE'>, <TokenType.MEDIUMTEXT: 'MEDIUMTEXT'>, <TokenType.HLLSKETCH: 'HLLSKETCH'>, <TokenType.STRUCT: 'STRUCT'>, <TokenType.PRIMARY_KEY: 'PRIMARY_KEY'>, <TokenType.INT: 'INT'>, <TokenType.DATETIME64: 'DATETIME64'>, <TokenType.VARCHAR: 'VARCHAR'>, <TokenType.CURRENT_USER: 'CURRENT_USER'>, <TokenType.TSTZRANGE: 'TSTZRANGE'>, <TokenType.CURRENT_DATETIME: 'CURRENT_DATETIME'>, <TokenType.FORMAT: 'FORMAT'>, <TokenType.SMALLMONEY: 'SMALLMONEY'>, <TokenType.NVARCHAR: 'NVARCHAR'>, <TokenType.NUMMULTIRANGE: 'NUMMULTIRANGE'>, <TokenType.INDEX: 'INDEX'>, <TokenType.TSRANGE: 'TSRANGE'>, <TokenType.BIGINT: 'BIGINT'>, <TokenType.CURRENT_TIME: 'CURRENT_TIME'>, <TokenType.GEOGRAPHY: 'GEOGRAPHY'>, <TokenType.CHAR: 'CHAR'>, <TokenType.USERDEFINED: 'USERDEFINED'>, <TokenType.ISNULL: 'ISNULL'>, <TokenType.IMAGE: 'IMAGE'>, <TokenType.LIKE: 'LIKE'>, <TokenType.TABLE: 'TABLE'>, <TokenType.USMALLINT: 'USMALLINT'>, <TokenType.SMALLINT: 'SMALLINT'>, <TokenType.VAR: 'VAR'>, <TokenType.SMALLSERIAL: 'SMALLSERIAL'>, <TokenType.MERGE: 'MERGE'>, <TokenType.ROWVERSION: 'ROWVERSION'>, <TokenType.JSONB: 'JSONB'>, <TokenType.LONGTEXT: 'LONGTEXT'>, <TokenType.ARRAY: 'ARRAY'>, <TokenType.TIMESTAMP: 'TIMESTAMP'>, <TokenType.VARIANT: 'VARIANT'>, <TokenType.FILTER: 'FILTER'>, <TokenType.BIGDECIMAL: 'BIGDECIMAL'>, <TokenType.UBIGINT: 'UBIGINT'>, <TokenType.TSTZMULTIRANGE: 'TSTZMULTIRANGE'>, <TokenType.XML: 'XML'>, <TokenType.UNNEST: 'UNNEST'>, <TokenType.INTERVAL: 'INTERVAL'>, <TokenType.NCHAR: 'NCHAR'>, <TokenType.FIRST: 'FIRST'>, <TokenType.WINDOW: 'WINDOW'>, <TokenType.BINARY: 'BINARY'>, <TokenType.DATERANGE: 'DATERANGE'>, <TokenType.MAP: 'MAP'>, <TokenType.TIME: 'TIME'>, <TokenType.CURRENT_TIMESTAMP: 'CURRENT_TIMESTAMP'>, <TokenType.DECIMAL: 'DECIMAL'>, <TokenType.COMMAND: 'COMMAND'>, <TokenType.GLOB: 'GLOB'>, <TokenType.SERIAL: 'SERIAL'>, <TokenType.ALL: 'ALL'>, <TokenType.BIT: 'BIT'>, <TokenType.TEXT: 'TEXT'>, <TokenType.TSMULTIRANGE: 'TSMULTIRANGE'>, <TokenType.ANY: 'ANY'>, <TokenType.UINT128: 'UINT128'>, <TokenType.PSEUDO_TYPE: 'PSEUDO_TYPE'>, <TokenType.UINT256: 'UINT256'>, <TokenType.SUPER: 'SUPER'>, <TokenType.JSON: 'JSON'>, <TokenType.ILIKE: 'ILIKE'>, <TokenType.LEFT: 'LEFT'>, <TokenType.UUID: 'UUID'>, <TokenType.HSTORE: 'HSTORE'>, <TokenType.VARBINARY: 'VARBINARY'>, <TokenType.EXISTS: 'EXISTS'>, <TokenType.DATETIME: 'DATETIME'>, <TokenType.DOUBLE: 'DOUBLE'>, <TokenType.DATE: 'DATE'>, <TokenType.NUMRANGE: 'NUMRANGE'>, <TokenType.INET: 'INET'>, <TokenType.NULLABLE: 'NULLABLE'>, <TokenType.SOME: 'SOME'>, <TokenType.OBJECT: 'OBJECT'>, <TokenType.DATEMULTIRANGE: 'DATEMULTIRANGE'>, <TokenType.TINYINT: 'TINYINT'>, <TokenType.ROW: 'ROW'>, <TokenType.INT256: 'INT256'>, <TokenType.INT4MULTIRANGE: 'INT4MULTIRANGE'>, <TokenType.UTINYINT: 'UTINYINT'>, <TokenType.ENUM: 'ENUM'>, <TokenType.UINT: 'UINT'>, <TokenType.BOOLEAN: 'BOOLEAN'>, <TokenType.INT8MULTIRANGE: 'INT8MULTIRANGE'>, <TokenType.INT4RANGE: 'INT4RANGE'>, <TokenType.RIGHT: 'RIGHT'>}
CONJUNCTION = {<TokenType.AND: 'AND'>: <class 'sqlglot.expressions.And'>, <TokenType.OR: 'OR'>: <class 'sqlglot.expressions.Or'>}
EQUALITY = {<TokenType.EQ: 'EQ'>: <class 'sqlglot.expressions.EQ'>, <TokenType.NEQ: 'NEQ'>: <class 'sqlglot.expressions.NEQ'>, <TokenType.NULLSAFE_EQ: 'NULLSAFE_EQ'>: <class 'sqlglot.expressions.NullSafeEQ'>}
COMPARISON = {<TokenType.GT: 'GT'>: <class 'sqlglot.expressions.GT'>, <TokenType.GTE: 'GTE'>: <class 'sqlglot.expressions.GTE'>, <TokenType.LT: 'LT'>: <class 'sqlglot.expressions.LT'>, <TokenType.LTE: 'LTE'>: <class 'sqlglot.expressions.LTE'>}
BITWISE = {<TokenType.AMP: 'AMP'>: <class 'sqlglot.expressions.BitwiseAnd'>, <TokenType.CARET: 'CARET'>: <class 'sqlglot.expressions.BitwiseXor'>, <TokenType.PIPE: 'PIPE'>: <class 'sqlglot.expressions.BitwiseOr'>, <TokenType.DPIPE: 'DPIPE'>: <class 'sqlglot.expressions.SafeDPipe'>}
TERM = {<TokenType.DASH: 'DASH'>: <class 'sqlglot.expressions.Sub'>, <TokenType.PLUS: 'PLUS'>: <class 'sqlglot.expressions.Add'>, <TokenType.MOD: 'MOD'>: <class 'sqlglot.expressions.Mod'>, <TokenType.COLLATE: 'COLLATE'>: <class 'sqlglot.expressions.Collate'>}
FACTOR = {<TokenType.DIV: 'DIV'>: <class 'sqlglot.expressions.IntDiv'>, <TokenType.LR_ARROW: 'LR_ARROW'>: <class 'sqlglot.expressions.Distance'>, <TokenType.SLASH: 'SLASH'>: <class 'sqlglot.expressions.Div'>, <TokenType.STAR: 'STAR'>: <class 'sqlglot.expressions.Mul'>}
TIMESTAMPS = {<TokenType.TIMESTAMPLTZ: 'TIMESTAMPLTZ'>, <TokenType.TIMESTAMPTZ: 'TIMESTAMPTZ'>, <TokenType.TIMESTAMP: 'TIMESTAMP'>, <TokenType.TIME: 'TIME'>}
SET_OPERATIONS = {<TokenType.EXCEPT: 'EXCEPT'>, <TokenType.UNION: 'UNION'>, <TokenType.INTERSECT: 'INTERSECT'>}
JOIN_METHODS = {<TokenType.NATURAL: 'NATURAL'>, <TokenType.ASOF: 'ASOF'>}
JOIN_SIDES = {<TokenType.LEFT: 'LEFT'>, <TokenType.FULL: 'FULL'>, <TokenType.RIGHT: 'RIGHT'>}
JOIN_KINDS = {<TokenType.CROSS: 'CROSS'>, <TokenType.ANTI: 'ANTI'>, <TokenType.INNER: 'INNER'>, <TokenType.OUTER: 'OUTER'>, <TokenType.SEMI: 'SEMI'>}
JOIN_HINTS: Set[str] = set()
LAMBDAS = {<TokenType.ARROW: 'ARROW'>: <function Parser.<lambda>>, <TokenType.FARROW: 'FARROW'>: <function Parser.<lambda>>}
COLUMN_OPERATORS = {<TokenType.DOT: 'DOT'>: None, <TokenType.DCOLON: 'DCOLON'>: <function Parser.<lambda>>, <TokenType.ARROW: 'ARROW'>: <function Parser.<lambda>>, <TokenType.DARROW: 'DARROW'>: <function Parser.<lambda>>, <TokenType.HASH_ARROW: 'HASH_ARROW'>: <function Parser.<lambda>>, <TokenType.DHASH_ARROW: 'DHASH_ARROW'>: <function Parser.<lambda>>, <TokenType.PLACEHOLDER: 'PLACEHOLDER'>: <function Parser.<lambda>>}
EXPRESSION_PARSERS = {<class 'sqlglot.expressions.Cluster'>: <function Parser.<lambda>>, <class 'sqlglot.expressions.Column'>: <function Parser.<lambda>>, <class 'sqlglot.expressions.Condition'>: <function Parser.<lambda>>, <class 'sqlglot.expressions.DataType'>: <function Parser.<lambda>>, <class 'sqlglot.expressions.Expression'>: <function Parser.<lambda>>, <class 'sqlglot.expressions.From'>: <function Parser.<lambda>>, <class 'sqlglot.expressions.Group'>: <function Parser.<lambda>>, <class 'sqlglot.expressions.Having'>: <function Parser.<lambda>>, <class 'sqlglot.expressions.Identifier'>: <function Parser.<lambda>>, <class 'sqlglot.expressions.Join'>: <function Parser.<lambda>>, <class 'sqlglot.expressions.Lambda'>: <function Parser.<lambda>>, <class 'sqlglot.expressions.Lateral'>: <function Parser.<lambda>>, <class 'sqlglot.expressions.Limit'>: <function Parser.<lambda>>, <class 'sqlglot.expressions.Offset'>: <function Parser.<lambda>>, <class 'sqlglot.expressions.Order'>: <function Parser.<lambda>>, <class 'sqlglot.expressions.Ordered'>: <function Parser.<lambda>>, <class 'sqlglot.expressions.Properties'>: <function Parser.<lambda>>, <class 'sqlglot.expressions.Qualify'>: <function Parser.<lambda>>, <class 'sqlglot.expressions.Returning'>: <function Parser.<lambda>>, <class 'sqlglot.expressions.Sort'>: <function Parser.<lambda>>, <class 'sqlglot.expressions.Table'>: <function Parser.<lambda>>, <class 'sqlglot.expressions.TableAlias'>: <function Parser.<lambda>>, <class 'sqlglot.expressions.Where'>: <function Parser.<lambda>>, <class 'sqlglot.expressions.Window'>: <function Parser.<lambda>>, <class 'sqlglot.expressions.With'>: <function Parser.<lambda>>, 'JOIN_TYPE': <function Parser.<lambda>>}
STATEMENT_PARSERS = {<TokenType.ALTER: 'ALTER'>: <function Parser.<lambda>>, <TokenType.BEGIN: 'BEGIN'>: <function Parser.<lambda>>, <TokenType.CACHE: 'CACHE'>: <function Parser.<lambda>>, <TokenType.COMMIT: 'COMMIT'>: <function Parser.<lambda>>, <TokenType.COMMENT: 'COMMENT'>: <function Parser.<lambda>>, <TokenType.CREATE: 'CREATE'>: <function Parser.<lambda>>, <TokenType.DELETE: 'DELETE'>: <function Parser.<lambda>>, <TokenType.DESC: 'DESC'>: <function Parser.<lambda>>, <TokenType.DESCRIBE: 'DESCRIBE'>: <function Parser.<lambda>>, <TokenType.DROP: 'DROP'>: <function Parser.<lambda>>, <TokenType.END: 'END'>: <function Parser.<lambda>>, <TokenType.FROM: 'FROM'>: <function Parser.<lambda>>, <TokenType.INSERT: 'INSERT'>: <function Parser.<lambda>>, <TokenType.LOAD: 'LOAD'>: <function Parser.<lambda>>, <TokenType.MERGE: 'MERGE'>: <function Parser.<lambda>>, <TokenType.PIVOT: 'PIVOT'>: <function Parser.<lambda>>, <TokenType.PRAGMA: 'PRAGMA'>: <function Parser.<lambda>>, <TokenType.ROLLBACK: 'ROLLBACK'>: <function Parser.<lambda>>, <TokenType.SET: 'SET'>: <function Parser.<lambda>>, <TokenType.UNCACHE: 'UNCACHE'>: <function Parser.<lambda>>, <TokenType.UPDATE: 'UPDATE'>: <function Parser.<lambda>>, <TokenType.USE: 'USE'>: <function Parser.<lambda>>}
UNARY_PARSERS = {<TokenType.PLUS: 'PLUS'>: <function Parser.<lambda>>, <TokenType.NOT: 'NOT'>: <function Parser.<lambda>>, <TokenType.TILDA: 'TILDA'>: <function Parser.<lambda>>, <TokenType.DASH: 'DASH'>: <function Parser.<lambda>>}
PRIMARY_PARSERS = {<TokenType.STRING: 'STRING'>: <function Parser.<lambda>>, <TokenType.NUMBER: 'NUMBER'>: <function Parser.<lambda>>, <TokenType.STAR: 'STAR'>: <function Parser.<lambda>>, <TokenType.NULL: 'NULL'>: <function Parser.<lambda>>, <TokenType.TRUE: 'TRUE'>: <function Parser.<lambda>>, <TokenType.FALSE: 'FALSE'>: <function Parser.<lambda>>, <TokenType.BIT_STRING: 'BIT_STRING'>: <function Parser.<lambda>>, <TokenType.HEX_STRING: 'HEX_STRING'>: <function Parser.<lambda>>, <TokenType.BYTE_STRING: 'BYTE_STRING'>: <function Parser.<lambda>>, <TokenType.INTRODUCER: 'INTRODUCER'>: <function Parser.<lambda>>, <TokenType.NATIONAL_STRING: 'NATIONAL_STRING'>: <function Parser.<lambda>>, <TokenType.RAW_STRING: 'RAW_STRING'>: <function Parser.<lambda>>, <TokenType.SESSION_PARAMETER: 'SESSION_PARAMETER'>: <function Parser.<lambda>>}
PLACEHOLDER_PARSERS = {<TokenType.PLACEHOLDER: 'PLACEHOLDER'>: <function Parser.<lambda>>, <TokenType.PARAMETER: 'PARAMETER'>: <function Parser.<lambda>>, <TokenType.COLON: 'COLON'>: <function Parser.<lambda>>}
RANGE_PARSERS = {<TokenType.BETWEEN: 'BETWEEN'>: <function Parser.<lambda>>, <TokenType.GLOB: 'GLOB'>: <function binary_range_parser.<locals>.<lambda>>, <TokenType.ILIKE: 'ILIKE'>: <function binary_range_parser.<locals>.<lambda>>, <TokenType.IN: 'IN'>: <function Parser.<lambda>>, <TokenType.IRLIKE: 'IRLIKE'>: <function binary_range_parser.<locals>.<lambda>>, <TokenType.IS: 'IS'>: <function Parser.<lambda>>, <TokenType.LIKE: 'LIKE'>: <function binary_range_parser.<locals>.<lambda>>, <TokenType.OVERLAPS: 'OVERLAPS'>: <function binary_range_parser.<locals>.<lambda>>, <TokenType.RLIKE: 'RLIKE'>: <function binary_range_parser.<locals>.<lambda>>, <TokenType.SIMILAR_TO: 'SIMILAR_TO'>: <function binary_range_parser.<locals>.<lambda>>}
PROPERTY_PARSERS: Dict[str, Callable] = {'ALGORITHM': <function Parser.<lambda>>, 'AUTO_INCREMENT': <function Parser.<lambda>>, 'BLOCKCOMPRESSION': <function Parser.<lambda>>, 'CHARACTER SET': <function Parser.<lambda>>, 'CHECKSUM': <function Parser.<lambda>>, 'CLUSTER BY': <function Parser.<lambda>>, 'COLLATE': <function Parser.<lambda>>, 'COMMENT': <function Parser.<lambda>>, 'COPY': <function Parser.<lambda>>, 'DATABLOCKSIZE': <function Parser.<lambda>>, 'DEFINER': <function Parser.<lambda>>, 'DETERMINISTIC': <function Parser.<lambda>>, 'DISTKEY': <function Parser.<lambda>>, 'DISTSTYLE': <function Parser.<lambda>>, 'ENGINE': <function Parser.<lambda>>, 'EXECUTE': <function Parser.<lambda>>, 'EXTERNAL': <function Parser.<lambda>>, 'FALLBACK': <function Parser.<lambda>>, 'FORMAT': <function Parser.<lambda>>, 'FREESPACE': <function Parser.<lambda>>, 'IMMUTABLE': <function Parser.<lambda>>, 'JOURNAL': <function Parser.<lambda>>, 'LANGUAGE': <function Parser.<lambda>>, 'LAYOUT': <function Parser.<lambda>>, 'LIFETIME': <function Parser.<lambda>>, 'LIKE': <function Parser.<lambda>>, 'LOCATION': <function Parser.<lambda>>, 'LOCK': <function Parser.<lambda>>, 'LOCKING': <function Parser.<lambda>>, 'LOG': <function Parser.<lambda>>, 'MATERIALIZED': <function Parser.<lambda>>, 'MERGEBLOCKRATIO': <function Parser.<lambda>>, 'MULTISET': <function Parser.<lambda>>, 'NO': <function Parser.<lambda>>, 'ON': <function Parser.<lambda>>, 'ORDER BY': <function Parser.<lambda>>, 'PARTITION BY': <function Parser.<lambda>>, 'PARTITIONED BY': <function Parser.<lambda>>, 'PARTITIONED_BY': <function Parser.<lambda>>, 'PRIMARY KEY': <function Parser.<lambda>>, 'RANGE': <function Parser.<lambda>>, 'RETURNS': <function Parser.<lambda>>, 'ROW': <function Parser.<lambda>>, 'ROW_FORMAT': <function Parser.<lambda>>, 'SET': <function Parser.<lambda>>, 'SETTINGS': <function Parser.<lambda>>, 'SORTKEY': <function Parser.<lambda>>, 'SOURCE': <function Parser.<lambda>>, 'STABLE': <function Parser.<lambda>>, 'STORED': <function Parser.<lambda>>, 'TBLPROPERTIES': <function Parser.<lambda>>, 'TEMP': <function Parser.<lambda>>, 'TEMPORARY': <function Parser.<lambda>>, 'TO': <function Parser.<lambda>>, 'TRANSIENT': <function Parser.<lambda>>, 'TTL': <function Parser.<lambda>>, 'USING': <function Parser.<lambda>>, 'VOLATILE': <function Parser.<lambda>>, 'WITH': <function Parser.<lambda>>}
CONSTRAINT_PARSERS = {'AUTOINCREMENT': <function Parser.<lambda>>, 'AUTO_INCREMENT': <function Parser.<lambda>>, 'CASESPECIFIC': <function Parser.<lambda>>, 'CHARACTER SET': <function Parser.<lambda>>, 'CHECK': <function Parser.<lambda>>, 'COLLATE': <function Parser.<lambda>>, 'COMMENT': <function Parser.<lambda>>, 'COMPRESS': <function Parser.<lambda>>, 'DEFAULT': <function Parser.<lambda>>, 'ENCODE': <function Parser.<lambda>>, 'FOREIGN KEY': <function Parser.<lambda>>, 'FORMAT': <function Parser.<lambda>>, 'GENERATED': <function Parser.<lambda>>, 'IDENTITY': <function Parser.<lambda>>, 'INLINE': <function Parser.<lambda>>, 'LIKE': <function Parser.<lambda>>, 'NOT': <function Parser.<lambda>>, 'NULL': <function Parser.<lambda>>, 'ON': <function Parser.<lambda>>, 'PATH': <function Parser.<lambda>>, 'PRIMARY KEY': <function Parser.<lambda>>, 'REFERENCES': <function Parser.<lambda>>, 'TITLE': <function Parser.<lambda>>, 'TTL': <function Parser.<lambda>>, 'UNIQUE': <function Parser.<lambda>>, 'UPPERCASE': <function Parser.<lambda>>}
ALTER_PARSERS = {'ADD': <function Parser.<lambda>>, 'ALTER': <function Parser.<lambda>>, 'DELETE': <function Parser.<lambda>>, 'DROP': <function Parser.<lambda>>, 'RENAME': <function Parser.<lambda>>}
SCHEMA_UNNAMED_CONSTRAINTS = {'FOREIGN KEY', 'UNIQUE', 'CHECK', 'PRIMARY KEY', 'LIKE'}
NO_PAREN_FUNCTION_PARSERS = {<TokenType.ANY: 'ANY'>: <function Parser.<lambda>>, <TokenType.CASE: 'CASE'>: <function Parser.<lambda>>, <TokenType.IF: 'IF'>: <function Parser.<lambda>>, <TokenType.NEXT_VALUE_FOR: 'NEXT_VALUE_FOR'>: <function Parser.<lambda>>}
FUNCTIONS_WITH_ALIASED_ARGS = {'STRUCT'}
FUNCTION_PARSERS: Dict[str, Callable] = {'CAST': <function Parser.<lambda>>, 'CONCAT': <function Parser.<lambda>>, 'CONVERT': <function Parser.<lambda>>, 'DECODE': <function Parser.<lambda>>, 'EXTRACT': <function Parser.<lambda>>, 'JSON_OBJECT': <function Parser.<lambda>>, 'LOG': <function Parser.<lambda>>, 'MATCH': <function Parser.<lambda>>, 'OPENJSON': <function Parser.<lambda>>, 'POSITION': <function Parser.<lambda>>, 'SAFE_CAST': <function Parser.<lambda>>, 'STRING_AGG': <function Parser.<lambda>>, 'SUBSTRING': <function Parser.<lambda>>, 'TRIM': <function Parser.<lambda>>, 'TRY_CAST': <function Parser.<lambda>>, 'TRY_CONVERT': <function Parser.<lambda>>}
QUERY_MODIFIER_PARSERS = {'joins': <function Parser.<lambda>>, 'laterals': <function Parser.<lambda>>, 'match': <function Parser.<lambda>>, 'where': <function Parser.<lambda>>, 'group': <function Parser.<lambda>>, 'having': <function Parser.<lambda>>, 'qualify': <function Parser.<lambda>>, 'windows': <function Parser.<lambda>>, 'order': <function Parser.<lambda>>, 'limit': <function Parser.<lambda>>, 'offset': <function Parser.<lambda>>, 'locks': <function Parser.<lambda>>, 'sample': <function Parser.<lambda>>}
SET_PARSERS = {'GLOBAL': <function Parser.<lambda>>, 'LOCAL': <function Parser.<lambda>>, 'SESSION': <function Parser.<lambda>>, 'TRANSACTION': <function Parser.<lambda>>}
SHOW_PARSERS: Dict[str, Callable] = {}
TYPE_LITERAL_PARSERS: Dict[sqlglot.expressions.DataType.Type, Callable] = {}
DDL_SELECT_TOKENS = {<TokenType.L_PAREN: 'L_PAREN'>, <TokenType.WITH: 'WITH'>, <TokenType.SELECT: 'SELECT'>}
PRE_VOLATILE_TOKENS = {<TokenType.CREATE: 'CREATE'>, <TokenType.UNIQUE: 'UNIQUE'>, <TokenType.REPLACE: 'REPLACE'>}
TRANSACTION_KIND = {'IMMEDIATE', 'DEFERRED', 'EXCLUSIVE'}
TRANSACTION_CHARACTERISTICS = {'ISOLATION LEVEL REPEATABLE READ', 'ISOLATION LEVEL READ COMMITTED', 'ISOLATION LEVEL READ UNCOMMITTED', 'READ WRITE', 'ISOLATION LEVEL SERIALIZABLE', 'READ ONLY'}
INSERT_ALTERNATIVES = {'IGNORE', 'ROLLBACK', 'ABORT', 'REPLACE', 'FAIL'}
CLONE_KINDS = {'STATEMENT', 'TIMESTAMP', 'OFFSET'}
TABLE_INDEX_HINT_TOKENS = {<TokenType.IGNORE: 'IGNORE'>, <TokenType.USE: 'USE'>, <TokenType.FORCE: 'FORCE'>}
WINDOW_ALIAS_TOKENS = {<TokenType.SHOW: 'SHOW'>, <TokenType.MEDIUMBLOB: 'MEDIUMBLOB'>, <TokenType.GEOMETRY: 'GEOMETRY'>, <TokenType.ASC: 'ASC'>, <TokenType.MONEY: 'MONEY'>, <TokenType.SETTINGS: 'SETTINGS'>, <TokenType.SCHEMA: 'SCHEMA'>, <TokenType.RANGE: 'RANGE'>, <TokenType.FLOAT: 'FLOAT'>, <TokenType.STRUCT: 'STRUCT'>, <TokenType.MEDIUMTEXT: 'MEDIUMTEXT'>, <TokenType.HLLSKETCH: 'HLLSKETCH'>, <TokenType.CURRENT_DATE: 'CURRENT_DATE'>, <TokenType.INT: 'INT'>, <TokenType.NATURAL: 'NATURAL'>, <TokenType.TOP: 'TOP'>, <TokenType.CURRENT_USER: 'CURRENT_USER'>, <TokenType.SEMI: 'SEMI'>, <TokenType.CURRENT_DATETIME: 'CURRENT_DATETIME'>, <TokenType.FORMAT: 'FORMAT'>, <TokenType.PIVOT: 'PIVOT'>, <TokenType.NVARCHAR: 'NVARCHAR'>, <TokenType.NUMMULTIRANGE: 'NUMMULTIRANGE'>, <TokenType.INDEX: 'INDEX'>, <TokenType.TSRANGE: 'TSRANGE'>, <TokenType.ORDINALITY: 'ORDINALITY'>, <TokenType.USERDEFINED: 'USERDEFINED'>, <TokenType.CURRENT_TIME: 'CURRENT_TIME'>, <TokenType.DATABASE: 'DATABASE'>, <TokenType.LOAD: 'LOAD'>, <TokenType.TABLE: 'TABLE'>, <TokenType.USMALLINT: 'USMALLINT'>, <TokenType.SMALLSERIAL: 'SMALLSERIAL'>, <TokenType.ROWVERSION: 'ROWVERSION'>, <TokenType.JSONB: 'JSONB'>, <TokenType.LONGTEXT: 'LONGTEXT'>, <TokenType.ARRAY: 'ARRAY'>, <TokenType.VIEW: 'VIEW'>, <TokenType.FILTER: 'FILTER'>, <TokenType.BIGDECIMAL: 'BIGDECIMAL'>, <TokenType.UBIGINT: 'UBIGINT'>, <TokenType.TSTZMULTIRANGE: 'TSTZMULTIRANGE'>, <TokenType.CONSTRAINT: 'CONSTRAINT'>, <TokenType.NCHAR: 'NCHAR'>, <TokenType.REFERENCES: 'REFERENCES'>, <TokenType.WINDOW: 'WINDOW'>, <TokenType.DECIMAL: 'DECIMAL'>, <TokenType.SET: 'SET'>, <TokenType.DELETE: 'DELETE'>, <TokenType.COMMAND: 'COMMAND'>, <TokenType.CURRENT_TIMESTAMP: 'CURRENT_TIMESTAMP'>, <TokenType.ANTI: 'ANTI'>, <TokenType.DESCRIBE: 'DESCRIBE'>, <TokenType.DIV: 'DIV'>, <TokenType.TSMULTIRANGE: 'TSMULTIRANGE'>, <TokenType.UINT128: 'UINT128'>, <TokenType.PERCENT: 'PERCENT'>, <TokenType.COLLATE: 'COLLATE'>, <TokenType.AUTO_INCREMENT: 'AUTO_INCREMENT'>, <TokenType.CACHE: 'CACHE'>, <TokenType.VARBINARY: 'VARBINARY'>, <TokenType.DOUBLE: 'DOUBLE'>, <TokenType.DATE: 'DATE'>, <TokenType.NUMRANGE: 'NUMRANGE'>, <TokenType.NULLABLE: 'NULLABLE'>, <TokenType.SOME: 'SOME'>, <TokenType.DATEMULTIRANGE: 'DATEMULTIRANGE'>, <TokenType.EXECUTE: 'EXECUTE'>, <TokenType.UNPIVOT: 'UNPIVOT'>, <TokenType.APPLY: 'APPLY'>, <TokenType.INT256: 'INT256'>, <TokenType.INT4MULTIRANGE: 'INT4MULTIRANGE'>, <TokenType.UTINYINT: 'UTINYINT'>, <TokenType.ENUM: 'ENUM'>, <TokenType.DESC: 'DESC'>, <TokenType.VOLATILE: 'VOLATILE'>, <TokenType.BOOLEAN: 'BOOLEAN'>, <TokenType.INT4RANGE: 'INT4RANGE'>, <TokenType.CASE: 'CASE'>, <TokenType.RIGHT: 'RIGHT'>, <TokenType.INT8RANGE: 'INT8RANGE'>, <TokenType.OFFSET: 'OFFSET'>, <TokenType.LONGBLOB: 'LONGBLOB'>, <TokenType.INT128: 'INT128'>, <TokenType.UNIQUE: 'UNIQUE'>, <TokenType.TIMESTAMPTZ: 'TIMESTAMPTZ'>, <TokenType.TEMPORARY: 'TEMPORARY'>, <TokenType.BIGSERIAL: 'BIGSERIAL'>, <TokenType.UNIQUEIDENTIFIER: 'UNIQUEIDENTIFIER'>, <TokenType.TIMESTAMPLTZ: 'TIMESTAMPLTZ'>, <TokenType.BEGIN: 'BEGIN'>, <TokenType.PROCEDURE: 'PROCEDURE'>, <TokenType.FULL: 'FULL'>, <TokenType.DATETIME64: 'DATETIME64'>, <TokenType.VARCHAR: 'VARCHAR'>, <TokenType.NEXT: 'NEXT'>, <TokenType.TSTZRANGE: 'TSTZRANGE'>, <TokenType.FUNCTION: 'FUNCTION'>, <TokenType.END: 'END'>, <TokenType.SMALLMONEY: 'SMALLMONEY'>, <TokenType.BIGINT: 'BIGINT'>, <TokenType.GEOGRAPHY: 'GEOGRAPHY'>, <TokenType.CHAR: 'CHAR'>, <TokenType.ISNULL: 'ISNULL'>, <TokenType.IMAGE: 'IMAGE'>, <TokenType.SMALLINT: 'SMALLINT'>, <TokenType.VAR: 'VAR'>, <TokenType.FALSE: 'FALSE'>, <TokenType.MERGE: 'MERGE'>, <TokenType.TIMESTAMP: 'TIMESTAMP'>, <TokenType.VARIANT: 'VARIANT'>, <TokenType.XML: 'XML'>, <TokenType.OVERWRITE: 'OVERWRITE'>, <TokenType.IS: 'IS'>, <TokenType.INTERVAL: 'INTERVAL'>, <TokenType.FIRST: 'FIRST'>, <TokenType.COLUMN: 'COLUMN'>, <TokenType.BINARY: 'BINARY'>, <TokenType.KEEP: 'KEEP'>, <TokenType.DATERANGE: 'DATERANGE'>, <TokenType.MAP: 'MAP'>, <TokenType.TIME: 'TIME'>, <TokenType.DICTIONARY: 'DICTIONARY'>, <TokenType.SERIAL: 'SERIAL'>, <TokenType.ALL: 'ALL'>, <TokenType.BIT: 'BIT'>, <TokenType.UPDATE: 'UPDATE'>, <TokenType.TEXT: 'TEXT'>, <TokenType.COMMENT: 'COMMENT'>, <TokenType.ANY: 'ANY'>, <TokenType.PSEUDO_TYPE: 'PSEUDO_TYPE'>, <TokenType.ESCAPE: 'ESCAPE'>, <TokenType.UINT256: 'UINT256'>, <TokenType.SUPER: 'SUPER'>, <TokenType.JSON: 'JSON'>, <TokenType.LEFT: 'LEFT'>, <TokenType.IF: 'IF'>, <TokenType.TRUE: 'TRUE'>, <TokenType.UUID: 'UUID'>, <TokenType.HSTORE: 'HSTORE'>, <TokenType.EXISTS: 'EXISTS'>, <TokenType.DATETIME: 'DATETIME'>, <TokenType.PRAGMA: 'PRAGMA'>, <TokenType.INET: 'INET'>, <TokenType.COMMIT: 'COMMIT'>, <TokenType.OBJECT: 'OBJECT'>, <TokenType.PARTITION: 'PARTITION'>, <TokenType.TINYINT: 'TINYINT'>, <TokenType.ROW: 'ROW'>, <TokenType.DEFAULT: 'DEFAULT'>, <TokenType.UINT: 'UINT'>, <TokenType.INT8MULTIRANGE: 'INT8MULTIRANGE'>}
WINDOW_BEFORE_PAREN_TOKENS = {<TokenType.OVER: 'OVER'>}
WINDOW_SIDES = {'FOLLOWING', 'PRECEDING'}
ADD_CONSTRAINT_TOKENS = {<TokenType.CONSTRAINT: 'CONSTRAINT'>, <TokenType.FOREIGN_KEY: 'FOREIGN_KEY'>, <TokenType.PRIMARY_KEY: 'PRIMARY_KEY'>}
STRICT_CAST = True
CONCAT_NULL_OUTPUTS_STRING = False
CONVERT_TYPE_FIRST = False
PREFIXED_PIVOT_COLUMNS = False
IDENTIFY_PIVOT_STRINGS = False
LOG_BASE_FIRST = True
LOG_DEFAULTS_TO_LN = False
INDEX_OFFSET: int = 0
UNNEST_COLUMN_ONLY: bool = False
ALIAS_POST_TABLESAMPLE: bool = False
STRICT_STRING_CONCAT = False
NULL_ORDERING: str = 'nulls_are_small'
SHOW_TRIE: Dict = {}
SET_TRIE: Dict = {'GLOBAL': {0: True}, 'LOCAL': {0: True}, 'SESSION': {0: True}, 'TRANSACTION': {0: True}}
FORMAT_MAPPING: Dict[str, str] = {}
FORMAT_TRIE: Dict = {}
TIME_MAPPING: Dict[str, str] = {}
TIME_TRIE: Dict = {}
error_level
error_message_context
max_errors
def reset(self):
844    def reset(self):
845        self.sql = ""
846        self.errors = []
847        self._tokens = []
848        self._index = 0
849        self._curr = None
850        self._next = None
851        self._prev = None
852        self._prev_comments = None
def parse( self, raw_tokens: List[sqlglot.tokens.Token], sql: Optional[str] = None) -> List[Optional[sqlglot.expressions.Expression]]:
854    def parse(
855        self, raw_tokens: t.List[Token], sql: t.Optional[str] = None
856    ) -> t.List[t.Optional[exp.Expression]]:
857        """
858        Parses a list of tokens and returns a list of syntax trees, one tree
859        per parsed SQL statement.
860
861        Args:
862            raw_tokens: The list of tokens.
863            sql: The original SQL string, used to produce helpful debug messages.
864
865        Returns:
866            The list of the produced syntax trees.
867        """
868        return self._parse(
869            parse_method=self.__class__._parse_statement, raw_tokens=raw_tokens, sql=sql
870        )

Parses a list of tokens and returns a list of syntax trees, one tree per parsed SQL statement.

Arguments:
  • raw_tokens: The list of tokens.
  • sql: The original SQL string, used to produce helpful debug messages.
Returns:

The list of the produced syntax trees.

def parse_into( self, expression_types: Union[str, Type[sqlglot.expressions.Expression], Collection[Union[str, Type[sqlglot.expressions.Expression]]]], raw_tokens: List[sqlglot.tokens.Token], sql: Optional[str] = None) -> List[Optional[sqlglot.expressions.Expression]]:
872    def parse_into(
873        self,
874        expression_types: exp.IntoType,
875        raw_tokens: t.List[Token],
876        sql: t.Optional[str] = None,
877    ) -> t.List[t.Optional[exp.Expression]]:
878        """
879        Parses a list of tokens into a given Expression type. If a collection of Expression
880        types is given instead, this method will try to parse the token list into each one
881        of them, stopping at the first for which the parsing succeeds.
882
883        Args:
884            expression_types: The expression type(s) to try and parse the token list into.
885            raw_tokens: The list of tokens.
886            sql: The original SQL string, used to produce helpful debug messages.
887
888        Returns:
889            The target Expression.
890        """
891        errors = []
892        for expression_type in ensure_list(expression_types):
893            parser = self.EXPRESSION_PARSERS.get(expression_type)
894            if not parser:
895                raise TypeError(f"No parser registered for {expression_type}")
896
897            try:
898                return self._parse(parser, raw_tokens, sql)
899            except ParseError as e:
900                e.errors[0]["into_expression"] = expression_type
901                errors.append(e)
902
903        raise ParseError(
904            f"Failed to parse '{sql or raw_tokens}' into {expression_types}",
905            errors=merge_errors(errors),
906        ) from errors[-1]

Parses a list of tokens into a given Expression type. If a collection of Expression types is given instead, this method will try to parse the token list into each one of them, stopping at the first for which the parsing succeeds.

Arguments:
  • expression_types: The expression type(s) to try and parse the token list into.
  • raw_tokens: The list of tokens.
  • sql: The original SQL string, used to produce helpful debug messages.
Returns:

The target Expression.

def check_errors(self) -> None:
943    def check_errors(self) -> None:
944        """Logs or raises any found errors, depending on the chosen error level setting."""
945        if self.error_level == ErrorLevel.WARN:
946            for error in self.errors:
947                logger.error(str(error))
948        elif self.error_level == ErrorLevel.RAISE and self.errors:
949            raise ParseError(
950                concat_messages(self.errors, self.max_errors),
951                errors=merge_errors(self.errors),
952            )

Logs or raises any found errors, depending on the chosen error level setting.

def raise_error(self, message: str, token: Optional[sqlglot.tokens.Token] = None) -> None:
954    def raise_error(self, message: str, token: t.Optional[Token] = None) -> None:
955        """
956        Appends an error in the list of recorded errors or raises it, depending on the chosen
957        error level setting.
958        """
959        token = token or self._curr or self._prev or Token.string("")
960        start = token.start
961        end = token.end + 1
962        start_context = self.sql[max(start - self.error_message_context, 0) : start]
963        highlight = self.sql[start:end]
964        end_context = self.sql[end : end + self.error_message_context]
965
966        error = ParseError.new(
967            f"{message}. Line {token.line}, Col: {token.col}.\n"
968            f"  {start_context}\033[4m{highlight}\033[0m{end_context}",
969            description=message,
970            line=token.line,
971            col=token.col,
972            start_context=start_context,
973            highlight=highlight,
974            end_context=end_context,
975        )
976
977        if self.error_level == ErrorLevel.IMMEDIATE:
978            raise error
979
980        self.errors.append(error)

Appends an error in the list of recorded errors or raises it, depending on the chosen error level setting.

def expression( self, exp_class: Type[~E], comments: Optional[List[str]] = None, **kwargs) -> ~E:
982    def expression(
983        self, exp_class: t.Type[E], comments: t.Optional[t.List[str]] = None, **kwargs
984    ) -> E:
985        """
986        Creates a new, validated Expression.
987
988        Args:
989            exp_class: The expression class to instantiate.
990            comments: An optional list of comments to attach to the expression.
991            kwargs: The arguments to set for the expression along with their respective values.
992
993        Returns:
994            The target expression.
995        """
996        instance = exp_class(**kwargs)
997        instance.add_comments(comments) if comments else self._add_comments(instance)
998        return self.validate_expression(instance)

Creates a new, validated Expression.

Arguments:
  • exp_class: The expression class to instantiate.
  • comments: An optional list of comments to attach to the expression.
  • kwargs: The arguments to set for the expression along with their respective values.
Returns:

The target expression.

def validate_expression(self, expression: ~E, args: Optional[List] = None) -> ~E:
1005    def validate_expression(self, expression: E, args: t.Optional[t.List] = None) -> E:
1006        """
1007        Validates an Expression, making sure that all its mandatory arguments are set.
1008
1009        Args:
1010            expression: The expression to validate.
1011            args: An optional list of items that was used to instantiate the expression, if it's a Func.
1012
1013        Returns:
1014            The validated expression.
1015        """
1016        if self.error_level != ErrorLevel.IGNORE:
1017            for error_message in expression.error_messages(args):
1018                self.raise_error(error_message)
1019
1020        return expression

Validates an Expression, making sure that all its mandatory arguments are set.

Arguments:
  • expression: The expression to validate.
  • args: An optional list of items that was used to instantiate the expression, if it's a Func.
Returns:

The validated expression.

errors
sql