sqlglot.parser API documentation

Edit on GitHub

# sqlglot.parser

View Source

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

logger = <Logger sqlglot (WARNING)>
def parse_var_map(args: List) -> sqlglot.expressions.StarMap | sqlglot.expressions.VarMap: View Source

    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: View Source

    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]]: View Source

    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: View Source

      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        "CLUSTERED": lambda self: self._parse_clustered_by(),
     590        "COLLATE": lambda self: self._parse_property_assignment(exp.CollateProperty),
     591        "COMMENT": lambda self: self._parse_property_assignment(exp.SchemaCommentProperty),
     592        "COPY": lambda self: self._parse_copy_property(),
     593        "DATABLOCKSIZE": lambda self, **kwargs: self._parse_datablocksize(**kwargs),
     594        "DEFINER": lambda self: self._parse_definer(),
     595        "DETERMINISTIC": lambda self: self.expression(
     596            exp.StabilityProperty, this=exp.Literal.string("IMMUTABLE")
     597        ),
     598        "DISTKEY": lambda self: self._parse_distkey(),
     599        "DISTSTYLE": lambda self: self._parse_property_assignment(exp.DistStyleProperty),
     600        "ENGINE": lambda self: self._parse_property_assignment(exp.EngineProperty),
     601        "EXECUTE": lambda self: self._parse_property_assignment(exp.ExecuteAsProperty),
     602        "EXTERNAL": lambda self: self.expression(exp.ExternalProperty),
     603        "FALLBACK": lambda self, **kwargs: self._parse_fallback(**kwargs),
     604        "FORMAT": lambda self: self._parse_property_assignment(exp.FileFormatProperty),
     605        "FREESPACE": lambda self: self._parse_freespace(),
     606        "IMMUTABLE": lambda self: self.expression(
     607            exp.StabilityProperty, this=exp.Literal.string("IMMUTABLE")
     608        ),
     609        "JOURNAL": lambda self, **kwargs: self._parse_journal(**kwargs),
     610        "LANGUAGE": lambda self: self._parse_property_assignment(exp.LanguageProperty),
     611        "LAYOUT": lambda self: self._parse_dict_property(this="LAYOUT"),
     612        "LIFETIME": lambda self: self._parse_dict_range(this="LIFETIME"),
     613        "LIKE": lambda self: self._parse_create_like(),
     614        "LOCATION": lambda self: self._parse_property_assignment(exp.LocationProperty),
     615        "LOCK": lambda self: self._parse_locking(),
     616        "LOCKING": lambda self: self._parse_locking(),
     617        "LOG": lambda self, **kwargs: self._parse_log(**kwargs),
     618        "MATERIALIZED": lambda self: self.expression(exp.MaterializedProperty),
     619        "MERGEBLOCKRATIO": lambda self, **kwargs: self._parse_mergeblockratio(**kwargs),
     620        "MULTISET": lambda self: self.expression(exp.SetProperty, multi=True),
     621        "NO": lambda self: self._parse_no_property(),
     622        "ON": lambda self: self._parse_on_property(),
     623        "ORDER BY": lambda self: self._parse_order(skip_order_token=True),
     624        "PARTITION BY": lambda self: self._parse_partitioned_by(),
     625        "PARTITIONED BY": lambda self: self._parse_partitioned_by(),
     626        "PARTITIONED_BY": lambda self: self._parse_partitioned_by(),
     627        "PRIMARY KEY": lambda self: self._parse_primary_key(in_props=True),
     628        "RANGE": lambda self: self._parse_dict_range(this="RANGE"),
     629        "RETURNS": lambda self: self._parse_returns(),
     630        "ROW": lambda self: self._parse_row(),
     631        "ROW_FORMAT": lambda self: self._parse_property_assignment(exp.RowFormatProperty),
     632        "SET": lambda self: self.expression(exp.SetProperty, multi=False),
     633        "SETTINGS": lambda self: self.expression(
     634            exp.SettingsProperty, expressions=self._parse_csv(self._parse_set_item)
     635        ),
     636        "SORTKEY": lambda self: self._parse_sortkey(),
     637        "SOURCE": lambda self: self._parse_dict_property(this="SOURCE"),
     638        "STABLE": lambda self: self.expression(
     639            exp.StabilityProperty, this=exp.Literal.string("STABLE")
     640        ),
     641        "STORED": lambda self: self._parse_stored(),
     642        "TBLPROPERTIES": lambda self: self._parse_wrapped_csv(self._parse_property),
     643        "TEMP": lambda self: self.expression(exp.TemporaryProperty),
     644        "TEMPORARY": lambda self: self.expression(exp.TemporaryProperty),
     645        "TO": lambda self: self._parse_to_table(),
     646        "TRANSIENT": lambda self: self.expression(exp.TransientProperty),
     647        "TTL": lambda self: self._parse_ttl(),
     648        "USING": lambda self: self._parse_property_assignment(exp.FileFormatProperty),
     649        "VOLATILE": lambda self: self._parse_volatile_property(),
     650        "WITH": lambda self: self._parse_with_property(),
     651    }
     652
     653    CONSTRAINT_PARSERS = {
     654        "AUTOINCREMENT": lambda self: self._parse_auto_increment(),
     655        "AUTO_INCREMENT": lambda self: self._parse_auto_increment(),
     656        "CASESPECIFIC": lambda self: self.expression(exp.CaseSpecificColumnConstraint, not_=False),
     657        "CHARACTER SET": lambda self: self.expression(
     658            exp.CharacterSetColumnConstraint, this=self._parse_var_or_string()
     659        ),
     660        "CHECK": lambda self: self.expression(
     661            exp.CheckColumnConstraint, this=self._parse_wrapped(self._parse_conjunction)
     662        ),
     663        "COLLATE": lambda self: self.expression(
     664            exp.CollateColumnConstraint, this=self._parse_var()
     665        ),
     666        "COMMENT": lambda self: self.expression(
     667            exp.CommentColumnConstraint, this=self._parse_string()
     668        ),
     669        "COMPRESS": lambda self: self._parse_compress(),
     670        "DEFAULT": lambda self: self.expression(
     671            exp.DefaultColumnConstraint, this=self._parse_bitwise()
     672        ),
     673        "ENCODE": lambda self: self.expression(exp.EncodeColumnConstraint, this=self._parse_var()),
     674        "FOREIGN KEY": lambda self: self._parse_foreign_key(),
     675        "FORMAT": lambda self: self.expression(
     676            exp.DateFormatColumnConstraint, this=self._parse_var_or_string()
     677        ),
     678        "GENERATED": lambda self: self._parse_generated_as_identity(),
     679        "IDENTITY": lambda self: self._parse_auto_increment(),
     680        "INLINE": lambda self: self._parse_inline(),
     681        "LIKE": lambda self: self._parse_create_like(),
     682        "NOT": lambda self: self._parse_not_constraint(),
     683        "NULL": lambda self: self.expression(exp.NotNullColumnConstraint, allow_null=True),
     684        "ON": lambda self: self._match(TokenType.UPDATE)
     685        and self.expression(exp.OnUpdateColumnConstraint, this=self._parse_function()),
     686        "PATH": lambda self: self.expression(exp.PathColumnConstraint, this=self._parse_string()),
     687        "PRIMARY KEY": lambda self: self._parse_primary_key(),
     688        "REFERENCES": lambda self: self._parse_references(match=False),
     689        "TITLE": lambda self: self.expression(
     690            exp.TitleColumnConstraint, this=self._parse_var_or_string()
     691        ),
     692        "TTL": lambda self: self.expression(exp.MergeTreeTTL, expressions=[self._parse_bitwise()]),
     693        "UNIQUE": lambda self: self._parse_unique(),
     694        "UPPERCASE": lambda self: self.expression(exp.UppercaseColumnConstraint),
     695    }
     696
     697    ALTER_PARSERS = {
     698        "ADD": lambda self: self._parse_alter_table_add(),
     699        "ALTER": lambda self: self._parse_alter_table_alter(),
     700        "DELETE": lambda self: self.expression(exp.Delete, where=self._parse_where()),
     701        "DROP": lambda self: self._parse_alter_table_drop(),
     702        "RENAME": lambda self: self._parse_alter_table_rename(),
     703    }
     704
     705    SCHEMA_UNNAMED_CONSTRAINTS = {"CHECK", "FOREIGN KEY", "LIKE", "PRIMARY KEY", "UNIQUE"}
     706
     707    NO_PAREN_FUNCTION_PARSERS = {
     708        TokenType.ANY: lambda self: self.expression(exp.Any, this=self._parse_bitwise()),
     709        TokenType.CASE: lambda self: self._parse_case(),
     710        TokenType.IF: lambda self: self._parse_if(),
     711        TokenType.NEXT_VALUE_FOR: lambda self: self.expression(
     712            exp.NextValueFor,
     713            this=self._parse_column(),
     714            order=self._match(TokenType.OVER) and self._parse_wrapped(self._parse_order),
     715        ),
     716    }
     717
     718    FUNCTIONS_WITH_ALIASED_ARGS = {"STRUCT"}
     719
     720    FUNCTION_PARSERS: t.Dict[str, t.Callable] = {
     721        "CAST": lambda self: self._parse_cast(self.STRICT_CAST),
     722        "CONCAT": lambda self: self._parse_concat(),
     723        "CONVERT": lambda self: self._parse_convert(self.STRICT_CAST),
     724        "DECODE": lambda self: self._parse_decode(),
     725        "EXTRACT": lambda self: self._parse_extract(),
     726        "JSON_OBJECT": lambda self: self._parse_json_object(),
     727        "LOG": lambda self: self._parse_logarithm(),
     728        "MATCH": lambda self: self._parse_match_against(),
     729        "OPENJSON": lambda self: self._parse_open_json(),
     730        "POSITION": lambda self: self._parse_position(),
     731        "SAFE_CAST": lambda self: self._parse_cast(False),
     732        "STRING_AGG": lambda self: self._parse_string_agg(),
     733        "SUBSTRING": lambda self: self._parse_substring(),
     734        "TRIM": lambda self: self._parse_trim(),
     735        "TRY_CAST": lambda self: self._parse_cast(False),
     736        "TRY_CONVERT": lambda self: self._parse_convert(False),
     737    }
     738
     739    QUERY_MODIFIER_PARSERS = {
     740        "joins": lambda self: list(iter(self._parse_join, None)),
     741        "laterals": lambda self: list(iter(self._parse_lateral, None)),
     742        "match": lambda self: self._parse_match_recognize(),
     743        "where": lambda self: self._parse_where(),
     744        "group": lambda self: self._parse_group(),
     745        "having": lambda self: self._parse_having(),
     746        "qualify": lambda self: self._parse_qualify(),
     747        "windows": lambda self: self._parse_window_clause(),
     748        "order": lambda self: self._parse_order(),
     749        "limit": lambda self: self._parse_limit(),
     750        "offset": lambda self: self._parse_offset(),
     751        "locks": lambda self: self._parse_locks(),
     752        "sample": lambda self: self._parse_table_sample(as_modifier=True),
     753    }
     754
     755    SET_PARSERS = {
     756        "GLOBAL": lambda self: self._parse_set_item_assignment("GLOBAL"),
     757        "LOCAL": lambda self: self._parse_set_item_assignment("LOCAL"),
     758        "SESSION": lambda self: self._parse_set_item_assignment("SESSION"),
     759        "TRANSACTION": lambda self: self._parse_set_transaction(),
     760    }
     761
     762    SHOW_PARSERS: t.Dict[str, t.Callable] = {}
     763
     764    TYPE_LITERAL_PARSERS: t.Dict[exp.DataType.Type, t.Callable] = {}
     765
     766    MODIFIABLES = (exp.Subquery, exp.Subqueryable, exp.Table)
     767
     768    DDL_SELECT_TOKENS = {TokenType.SELECT, TokenType.WITH, TokenType.L_PAREN}
     769
     770    PRE_VOLATILE_TOKENS = {TokenType.CREATE, TokenType.REPLACE, TokenType.UNIQUE}
     771
     772    TRANSACTION_KIND = {"DEFERRED", "IMMEDIATE", "EXCLUSIVE"}
     773    TRANSACTION_CHARACTERISTICS = {
     774        "ISOLATION LEVEL REPEATABLE READ",
     775        "ISOLATION LEVEL READ COMMITTED",
     776        "ISOLATION LEVEL READ UNCOMMITTED",
     777        "ISOLATION LEVEL SERIALIZABLE",
     778        "READ WRITE",
     779        "READ ONLY",
     780    }
     781
     782    INSERT_ALTERNATIVES = {"ABORT", "FAIL", "IGNORE", "REPLACE", "ROLLBACK"}
     783
     784    CLONE_KINDS = {"TIMESTAMP", "OFFSET", "STATEMENT"}
     785
     786    TABLE_INDEX_HINT_TOKENS = {TokenType.FORCE, TokenType.IGNORE, TokenType.USE}
     787
     788    WINDOW_ALIAS_TOKENS = ID_VAR_TOKENS - {TokenType.ROWS}
     789    WINDOW_BEFORE_PAREN_TOKENS = {TokenType.OVER}
     790    WINDOW_SIDES = {"FOLLOWING", "PRECEDING"}
     791
     792    ADD_CONSTRAINT_TOKENS = {TokenType.CONSTRAINT, TokenType.PRIMARY_KEY, TokenType.FOREIGN_KEY}
     793
     794    STRICT_CAST = True
     795
     796    # A NULL arg in CONCAT yields NULL by default
     797    CONCAT_NULL_OUTPUTS_STRING = 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) -> exp.Cluster:
    1430        return self.expression(exp.Cluster, expressions=self._parse_csv(self._parse_ordered))
    1431
    1432    def _parse_clustered_by(self) -> exp.ClusteredByProperty:
    1433        self._match_text_seq("BY")
    1434
    1435        self._match_l_paren()
    1436        expressions = self._parse_csv(self._parse_column)
    1437        self._match_r_paren()
    1438
    1439        if self._match_text_seq("SORTED", "BY"):
    1440            self._match_l_paren()
    1441            sorted_by = self._parse_csv(self._parse_ordered)
    1442            self._match_r_paren()
    1443        else:
    1444            sorted_by = None
    1445
    1446        self._match(TokenType.INTO)
    1447        buckets = self._parse_number()
    1448        self._match_text_seq("BUCKETS")
    1449
    1450        return self.expression(
    1451            exp.ClusteredByProperty,
    1452            expressions=expressions,
    1453            sorted_by=sorted_by,
    1454            buckets=buckets,
    1455        )
    1456
    1457    def _parse_copy_property(self) -> t.Optional[exp.CopyGrantsProperty]:
    1458        if not self._match_text_seq("GRANTS"):
    1459            self._retreat(self._index - 1)
    1460            return None
    1461
    1462        return self.expression(exp.CopyGrantsProperty)
    1463
    1464    def _parse_freespace(self) -> exp.FreespaceProperty:
    1465        self._match(TokenType.EQ)
    1466        return self.expression(
    1467            exp.FreespaceProperty, this=self._parse_number(), percent=self._match(TokenType.PERCENT)
    1468        )
    1469
    1470    def _parse_mergeblockratio(
    1471        self, no: bool = False, default: bool = False
    1472    ) -> exp.MergeBlockRatioProperty:
    1473        if self._match(TokenType.EQ):
    1474            return self.expression(
    1475                exp.MergeBlockRatioProperty,
    1476                this=self._parse_number(),
    1477                percent=self._match(TokenType.PERCENT),
    1478            )
    1479
    1480        return self.expression(exp.MergeBlockRatioProperty, no=no, default=default)
    1481
    1482    def _parse_datablocksize(
    1483        self,
    1484        default: t.Optional[bool] = None,
    1485        minimum: t.Optional[bool] = None,
    1486        maximum: t.Optional[bool] = None,
    1487    ) -> exp.DataBlocksizeProperty:
    1488        self._match(TokenType.EQ)
    1489        size = self._parse_number()
    1490
    1491        units = None
    1492        if self._match_texts(("BYTES", "KBYTES", "KILOBYTES")):
    1493            units = self._prev.text
    1494
    1495        return self.expression(
    1496            exp.DataBlocksizeProperty,
    1497            size=size,
    1498            units=units,
    1499            default=default,
    1500            minimum=minimum,
    1501            maximum=maximum,
    1502        )
    1503
    1504    def _parse_blockcompression(self) -> exp.BlockCompressionProperty:
    1505        self._match(TokenType.EQ)
    1506        always = self._match_text_seq("ALWAYS")
    1507        manual = self._match_text_seq("MANUAL")
    1508        never = self._match_text_seq("NEVER")
    1509        default = self._match_text_seq("DEFAULT")
    1510
    1511        autotemp = None
    1512        if self._match_text_seq("AUTOTEMP"):
    1513            autotemp = self._parse_schema()
    1514
    1515        return self.expression(
    1516            exp.BlockCompressionProperty,
    1517            always=always,
    1518            manual=manual,
    1519            never=never,
    1520            default=default,
    1521            autotemp=autotemp,
    1522        )
    1523
    1524    def _parse_withisolatedloading(self) -> exp.IsolatedLoadingProperty:
    1525        no = self._match_text_seq("NO")
    1526        concurrent = self._match_text_seq("CONCURRENT")
    1527        self._match_text_seq("ISOLATED", "LOADING")
    1528        for_all = self._match_text_seq("FOR", "ALL")
    1529        for_insert = self._match_text_seq("FOR", "INSERT")
    1530        for_none = self._match_text_seq("FOR", "NONE")
    1531        return self.expression(
    1532            exp.IsolatedLoadingProperty,
    1533            no=no,
    1534            concurrent=concurrent,
    1535            for_all=for_all,
    1536            for_insert=for_insert,
    1537            for_none=for_none,
    1538        )
    1539
    1540    def _parse_locking(self) -> exp.LockingProperty:
    1541        if self._match(TokenType.TABLE):
    1542            kind = "TABLE"
    1543        elif self._match(TokenType.VIEW):
    1544            kind = "VIEW"
    1545        elif self._match(TokenType.ROW):
    1546            kind = "ROW"
    1547        elif self._match_text_seq("DATABASE"):
    1548            kind = "DATABASE"
    1549        else:
    1550            kind = None
    1551
    1552        if kind in ("DATABASE", "TABLE", "VIEW"):
    1553            this = self._parse_table_parts()
    1554        else:
    1555            this = None
    1556
    1557        if self._match(TokenType.FOR):
    1558            for_or_in = "FOR"
    1559        elif self._match(TokenType.IN):
    1560            for_or_in = "IN"
    1561        else:
    1562            for_or_in = None
    1563
    1564        if self._match_text_seq("ACCESS"):
    1565            lock_type = "ACCESS"
    1566        elif self._match_texts(("EXCL", "EXCLUSIVE")):
    1567            lock_type = "EXCLUSIVE"
    1568        elif self._match_text_seq("SHARE"):
    1569            lock_type = "SHARE"
    1570        elif self._match_text_seq("READ"):
    1571            lock_type = "READ"
    1572        elif self._match_text_seq("WRITE"):
    1573            lock_type = "WRITE"
    1574        elif self._match_text_seq("CHECKSUM"):
    1575            lock_type = "CHECKSUM"
    1576        else:
    1577            lock_type = None
    1578
    1579        override = self._match_text_seq("OVERRIDE")
    1580
    1581        return self.expression(
    1582            exp.LockingProperty,
    1583            this=this,
    1584            kind=kind,
    1585            for_or_in=for_or_in,
    1586            lock_type=lock_type,
    1587            override=override,
    1588        )
    1589
    1590    def _parse_partition_by(self) -> t.List[t.Optional[exp.Expression]]:
    1591        if self._match(TokenType.PARTITION_BY):
    1592            return self._parse_csv(self._parse_conjunction)
    1593        return []
    1594
    1595    def _parse_partitioned_by(self) -> exp.PartitionedByProperty:
    1596        self._match(TokenType.EQ)
    1597        return self.expression(
    1598            exp.PartitionedByProperty,
    1599            this=self._parse_schema() or self._parse_bracket(self._parse_field()),
    1600        )
    1601
    1602    def _parse_withdata(self, no: bool = False) -> exp.WithDataProperty:
    1603        if self._match_text_seq("AND", "STATISTICS"):
    1604            statistics = True
    1605        elif self._match_text_seq("AND", "NO", "STATISTICS"):
    1606            statistics = False
    1607        else:
    1608            statistics = None
    1609
    1610        return self.expression(exp.WithDataProperty, no=no, statistics=statistics)
    1611
    1612    def _parse_no_property(self) -> t.Optional[exp.NoPrimaryIndexProperty]:
    1613        if self._match_text_seq("PRIMARY", "INDEX"):
    1614            return exp.NoPrimaryIndexProperty()
    1615        return None
    1616
    1617    def _parse_on_property(self) -> t.Optional[exp.Expression]:
    1618        if self._match_text_seq("COMMIT", "PRESERVE", "ROWS"):
    1619            return exp.OnCommitProperty()
    1620        elif self._match_text_seq("COMMIT", "DELETE", "ROWS"):
    1621            return exp.OnCommitProperty(delete=True)
    1622        return None
    1623
    1624    def _parse_distkey(self) -> exp.DistKeyProperty:
    1625        return self.expression(exp.DistKeyProperty, this=self._parse_wrapped(self._parse_id_var))
    1626
    1627    def _parse_create_like(self) -> t.Optional[exp.LikeProperty]:
    1628        table = self._parse_table(schema=True)
    1629
    1630        options = []
    1631        while self._match_texts(("INCLUDING", "EXCLUDING")):
    1632            this = self._prev.text.upper()
    1633
    1634            id_var = self._parse_id_var()
    1635            if not id_var:
    1636                return None
    1637
    1638            options.append(
    1639                self.expression(exp.Property, this=this, value=exp.var(id_var.this.upper()))
    1640            )
    1641
    1642        return self.expression(exp.LikeProperty, this=table, expressions=options)
    1643
    1644    def _parse_sortkey(self, compound: bool = False) -> exp.SortKeyProperty:
    1645        return self.expression(
    1646            exp.SortKeyProperty, this=self._parse_wrapped_id_vars(), compound=compound
    1647        )
    1648
    1649    def _parse_character_set(self, default: bool = False) -> exp.CharacterSetProperty:
    1650        self._match(TokenType.EQ)
    1651        return self.expression(
    1652            exp.CharacterSetProperty, this=self._parse_var_or_string(), default=default
    1653        )
    1654
    1655    def _parse_returns(self) -> exp.ReturnsProperty:
    1656        value: t.Optional[exp.Expression]
    1657        is_table = self._match(TokenType.TABLE)
    1658
    1659        if is_table:
    1660            if self._match(TokenType.LT):
    1661                value = self.expression(
    1662                    exp.Schema,
    1663                    this="TABLE",
    1664                    expressions=self._parse_csv(self._parse_struct_types),
    1665                )
    1666                if not self._match(TokenType.GT):
    1667                    self.raise_error("Expecting >")
    1668            else:
    1669                value = self._parse_schema(exp.var("TABLE"))
    1670        else:
    1671            value = self._parse_types()
    1672
    1673        return self.expression(exp.ReturnsProperty, this=value, is_table=is_table)
    1674
    1675    def _parse_describe(self) -> exp.Describe:
    1676        kind = self._match_set(self.CREATABLES) and self._prev.text
    1677        this = self._parse_table()
    1678        return self.expression(exp.Describe, this=this, kind=kind)
    1679
    1680    def _parse_insert(self) -> exp.Insert:
    1681        overwrite = self._match(TokenType.OVERWRITE)
    1682        local = self._match_text_seq("LOCAL")
    1683        alternative = None
    1684
    1685        if self._match_text_seq("DIRECTORY"):
    1686            this: t.Optional[exp.Expression] = self.expression(
    1687                exp.Directory,
    1688                this=self._parse_var_or_string(),
    1689                local=local,
    1690                row_format=self._parse_row_format(match_row=True),
    1691            )
    1692        else:
    1693            if self._match(TokenType.OR):
    1694                alternative = self._match_texts(self.INSERT_ALTERNATIVES) and self._prev.text
    1695
    1696            self._match(TokenType.INTO)
    1697            self._match(TokenType.TABLE)
    1698            this = self._parse_table(schema=True)
    1699
    1700        return self.expression(
    1701            exp.Insert,
    1702            this=this,
    1703            exists=self._parse_exists(),
    1704            partition=self._parse_partition(),
    1705            where=self._match_pair(TokenType.REPLACE, TokenType.WHERE)
    1706            and self._parse_conjunction(),
    1707            expression=self._parse_ddl_select(),
    1708            conflict=self._parse_on_conflict(),
    1709            returning=self._parse_returning(),
    1710            overwrite=overwrite,
    1711            alternative=alternative,
    1712        )
    1713
    1714    def _parse_on_conflict(self) -> t.Optional[exp.OnConflict]:
    1715        conflict = self._match_text_seq("ON", "CONFLICT")
    1716        duplicate = self._match_text_seq("ON", "DUPLICATE", "KEY")
    1717
    1718        if not conflict and not duplicate:
    1719            return None
    1720
    1721        nothing = None
    1722        expressions = None
    1723        key = None
    1724        constraint = None
    1725
    1726        if conflict:
    1727            if self._match_text_seq("ON", "CONSTRAINT"):
    1728                constraint = self._parse_id_var()
    1729            else:
    1730                key = self._parse_csv(self._parse_value)
    1731
    1732        self._match_text_seq("DO")
    1733        if self._match_text_seq("NOTHING"):
    1734            nothing = True
    1735        else:
    1736            self._match(TokenType.UPDATE)
    1737            expressions = self._match(TokenType.SET) and self._parse_csv(self._parse_equality)
    1738
    1739        return self.expression(
    1740            exp.OnConflict,
    1741            duplicate=duplicate,
    1742            expressions=expressions,
    1743            nothing=nothing,
    1744            key=key,
    1745            constraint=constraint,
    1746        )
    1747
    1748    def _parse_returning(self) -> t.Optional[exp.Returning]:
    1749        if not self._match(TokenType.RETURNING):
    1750            return None
    1751
    1752        return self.expression(exp.Returning, expressions=self._parse_csv(self._parse_column))
    1753
    1754    def _parse_row(self) -> t.Optional[exp.RowFormatSerdeProperty | exp.RowFormatDelimitedProperty]:
    1755        if not self._match(TokenType.FORMAT):
    1756            return None
    1757        return self._parse_row_format()
    1758
    1759    def _parse_row_format(
    1760        self, match_row: bool = False
    1761    ) -> t.Optional[exp.RowFormatSerdeProperty | exp.RowFormatDelimitedProperty]:
    1762        if match_row and not self._match_pair(TokenType.ROW, TokenType.FORMAT):
    1763            return None
    1764
    1765        if self._match_text_seq("SERDE"):
    1766            return self.expression(exp.RowFormatSerdeProperty, this=self._parse_string())
    1767
    1768        self._match_text_seq("DELIMITED")
    1769
    1770        kwargs = {}
    1771
    1772        if self._match_text_seq("FIELDS", "TERMINATED", "BY"):
    1773            kwargs["fields"] = self._parse_string()
    1774            if self._match_text_seq("ESCAPED", "BY"):
    1775                kwargs["escaped"] = self._parse_string()
    1776        if self._match_text_seq("COLLECTION", "ITEMS", "TERMINATED", "BY"):
    1777            kwargs["collection_items"] = self._parse_string()
    1778        if self._match_text_seq("MAP", "KEYS", "TERMINATED", "BY"):
    1779            kwargs["map_keys"] = self._parse_string()
    1780        if self._match_text_seq("LINES", "TERMINATED", "BY"):
    1781            kwargs["lines"] = self._parse_string()
    1782        if self._match_text_seq("NULL", "DEFINED", "AS"):
    1783            kwargs["null"] = self._parse_string()
    1784
    1785        return self.expression(exp.RowFormatDelimitedProperty, **kwargs)  # type: ignore
    1786
    1787    def _parse_load(self) -> exp.LoadData | exp.Command:
    1788        if self._match_text_seq("DATA"):
    1789            local = self._match_text_seq("LOCAL")
    1790            self._match_text_seq("INPATH")
    1791            inpath = self._parse_string()
    1792            overwrite = self._match(TokenType.OVERWRITE)
    1793            self._match_pair(TokenType.INTO, TokenType.TABLE)
    1794
    1795            return self.expression(
    1796                exp.LoadData,
    1797                this=self._parse_table(schema=True),
    1798                local=local,
    1799                overwrite=overwrite,
    1800                inpath=inpath,
    1801                partition=self._parse_partition(),
    1802                input_format=self._match_text_seq("INPUTFORMAT") and self._parse_string(),
    1803                serde=self._match_text_seq("SERDE") and self._parse_string(),
    1804            )
    1805        return self._parse_as_command(self._prev)
    1806
    1807    def _parse_delete(self) -> exp.Delete:
    1808        self._match(TokenType.FROM)
    1809
    1810        return self.expression(
    1811            exp.Delete,
    1812            this=self._parse_table(),
    1813            using=self._parse_csv(lambda: self._match(TokenType.USING) and self._parse_table()),
    1814            where=self._parse_where(),
    1815            returning=self._parse_returning(),
    1816            limit=self._parse_limit(),
    1817        )
    1818
    1819    def _parse_update(self) -> exp.Update:
    1820        return self.expression(
    1821            exp.Update,
    1822            **{  # type: ignore
    1823                "this": self._parse_table(alias_tokens=self.UPDATE_ALIAS_TOKENS),
    1824                "expressions": self._match(TokenType.SET) and self._parse_csv(self._parse_equality),
    1825                "from": self._parse_from(modifiers=True),
    1826                "where": self._parse_where(),
    1827                "returning": self._parse_returning(),
    1828                "limit": self._parse_limit(),
    1829            },
    1830        )
    1831
    1832    def _parse_uncache(self) -> exp.Uncache:
    1833        if not self._match(TokenType.TABLE):
    1834            self.raise_error("Expecting TABLE after UNCACHE")
    1835
    1836        return self.expression(
    1837            exp.Uncache, exists=self._parse_exists(), this=self._parse_table(schema=True)
    1838        )
    1839
    1840    def _parse_cache(self) -> exp.Cache:
    1841        lazy = self._match_text_seq("LAZY")
    1842        self._match(TokenType.TABLE)
    1843        table = self._parse_table(schema=True)
    1844
    1845        options = []
    1846        if self._match_text_seq("OPTIONS"):
    1847            self._match_l_paren()
    1848            k = self._parse_string()
    1849            self._match(TokenType.EQ)
    1850            v = self._parse_string()
    1851            options = [k, v]
    1852            self._match_r_paren()
    1853
    1854        self._match(TokenType.ALIAS)
    1855        return self.expression(
    1856            exp.Cache,
    1857            this=table,
    1858            lazy=lazy,
    1859            options=options,
    1860            expression=self._parse_select(nested=True),
    1861        )
    1862
    1863    def _parse_partition(self) -> t.Optional[exp.Partition]:
    1864        if not self._match(TokenType.PARTITION):
    1865            return None
    1866
    1867        return self.expression(
    1868            exp.Partition, expressions=self._parse_wrapped_csv(self._parse_conjunction)
    1869        )
    1870
    1871    def _parse_value(self) -> exp.Tuple:
    1872        if self._match(TokenType.L_PAREN):
    1873            expressions = self._parse_csv(self._parse_conjunction)
    1874            self._match_r_paren()
    1875            return self.expression(exp.Tuple, expressions=expressions)
    1876
    1877        # In presto we can have VALUES 1, 2 which results in 1 column & 2 rows.
    1878        # Source: https://prestodb.io/docs/current/sql/values.html
    1879        return self.expression(exp.Tuple, expressions=[self._parse_conjunction()])
    1880
    1881    def _parse_select(
    1882        self, nested: bool = False, table: bool = False, parse_subquery_alias: bool = True
    1883    ) -> t.Optional[exp.Expression]:
    1884        cte = self._parse_with()
    1885        if cte:
    1886            this = self._parse_statement()
    1887
    1888            if not this:
    1889                self.raise_error("Failed to parse any statement following CTE")
    1890                return cte
    1891
    1892            if "with" in this.arg_types:
    1893                this.set("with", cte)
    1894            else:
    1895                self.raise_error(f"{this.key} does not support CTE")
    1896                this = cte
    1897        elif self._match(TokenType.SELECT):
    1898            comments = self._prev_comments
    1899
    1900            hint = self._parse_hint()
    1901            all_ = self._match(TokenType.ALL)
    1902            distinct = self._match(TokenType.DISTINCT)
    1903
    1904            kind = (
    1905                self._match(TokenType.ALIAS)
    1906                and self._match_texts(("STRUCT", "VALUE"))
    1907                and self._prev.text
    1908            )
    1909
    1910            if distinct:
    1911                distinct = self.expression(
    1912                    exp.Distinct,
    1913                    on=self._parse_value() if self._match(TokenType.ON) else None,
    1914                )
    1915
    1916            if all_ and distinct:
    1917                self.raise_error("Cannot specify both ALL and DISTINCT after SELECT")
    1918
    1919            limit = self._parse_limit(top=True)
    1920            expressions = self._parse_csv(self._parse_expression)
    1921
    1922            this = self.expression(
    1923                exp.Select,
    1924                kind=kind,
    1925                hint=hint,
    1926                distinct=distinct,
    1927                expressions=expressions,
    1928                limit=limit,
    1929            )
    1930            this.comments = comments
    1931
    1932            into = self._parse_into()
    1933            if into:
    1934                this.set("into", into)
    1935
    1936            from_ = self._parse_from()
    1937            if from_:
    1938                this.set("from", from_)
    1939
    1940            this = self._parse_query_modifiers(this)
    1941        elif (table or nested) and self._match(TokenType.L_PAREN):
    1942            if self._match(TokenType.PIVOT):
    1943                this = self._parse_simplified_pivot()
    1944            elif self._match(TokenType.FROM):
    1945                this = exp.select("*").from_(
    1946                    t.cast(exp.From, self._parse_from(skip_from_token=True))
    1947                )
    1948            else:
    1949                this = self._parse_table() if table else self._parse_select(nested=True)
    1950                this = self._parse_set_operations(self._parse_query_modifiers(this))
    1951
    1952            self._match_r_paren()
    1953
    1954            # early return so that subquery unions aren't parsed again
    1955            # SELECT * FROM (SELECT 1) UNION ALL SELECT 1
    1956            # Union ALL should be a property of the top select node, not the subquery
    1957            return self._parse_subquery(this, parse_alias=parse_subquery_alias)
    1958        elif self._match(TokenType.VALUES):
    1959            this = self.expression(
    1960                exp.Values,
    1961                expressions=self._parse_csv(self._parse_value),
    1962                alias=self._parse_table_alias(),
    1963            )
    1964        else:
    1965            this = None
    1966
    1967        return self._parse_set_operations(this)
    1968
    1969    def _parse_with(self, skip_with_token: bool = False) -> t.Optional[exp.With]:
    1970        if not skip_with_token and not self._match(TokenType.WITH):
    1971            return None
    1972
    1973        comments = self._prev_comments
    1974        recursive = self._match(TokenType.RECURSIVE)
    1975
    1976        expressions = []
    1977        while True:
    1978            expressions.append(self._parse_cte())
    1979
    1980            if not self._match(TokenType.COMMA) and not self._match(TokenType.WITH):
    1981                break
    1982            else:
    1983                self._match(TokenType.WITH)
    1984
    1985        return self.expression(
    1986            exp.With, comments=comments, expressions=expressions, recursive=recursive
    1987        )
    1988
    1989    def _parse_cte(self) -> exp.CTE:
    1990        alias = self._parse_table_alias()
    1991        if not alias or not alias.this:
    1992            self.raise_error("Expected CTE to have alias")
    1993
    1994        self._match(TokenType.ALIAS)
    1995        return self.expression(
    1996            exp.CTE, this=self._parse_wrapped(self._parse_statement), alias=alias
    1997        )
    1998
    1999    def _parse_table_alias(
    2000        self, alias_tokens: t.Optional[t.Collection[TokenType]] = None
    2001    ) -> t.Optional[exp.TableAlias]:
    2002        any_token = self._match(TokenType.ALIAS)
    2003        alias = (
    2004            self._parse_id_var(any_token=any_token, tokens=alias_tokens or self.TABLE_ALIAS_TOKENS)
    2005            or self._parse_string_as_identifier()
    2006        )
    2007
    2008        index = self._index
    2009        if self._match(TokenType.L_PAREN):
    2010            columns = self._parse_csv(self._parse_function_parameter)
    2011            self._match_r_paren() if columns else self._retreat(index)
    2012        else:
    2013            columns = None
    2014
    2015        if not alias and not columns:
    2016            return None
    2017
    2018        return self.expression(exp.TableAlias, this=alias, columns=columns)
    2019
    2020    def _parse_subquery(
    2021        self, this: t.Optional[exp.Expression], parse_alias: bool = True
    2022    ) -> t.Optional[exp.Subquery]:
    2023        if not this:
    2024            return None
    2025
    2026        return self.expression(
    2027            exp.Subquery,
    2028            this=this,
    2029            pivots=self._parse_pivots(),
    2030            alias=self._parse_table_alias() if parse_alias else None,
    2031        )
    2032
    2033    def _parse_query_modifiers(
    2034        self, this: t.Optional[exp.Expression]
    2035    ) -> t.Optional[exp.Expression]:
    2036        if isinstance(this, self.MODIFIABLES):
    2037            for key, parser in self.QUERY_MODIFIER_PARSERS.items():
    2038                expression = parser(self)
    2039
    2040                if expression:
    2041                    if key == "limit":
    2042                        offset = expression.args.pop("offset", None)
    2043                        if offset:
    2044                            this.set("offset", exp.Offset(expression=offset))
    2045                    this.set(key, expression)
    2046        return this
    2047
    2048    def _parse_hint(self) -> t.Optional[exp.Hint]:
    2049        if self._match(TokenType.HINT):
    2050            hints = self._parse_csv(self._parse_function)
    2051
    2052            if not self._match_pair(TokenType.STAR, TokenType.SLASH):
    2053                self.raise_error("Expected */ after HINT")
    2054
    2055            return self.expression(exp.Hint, expressions=hints)
    2056
    2057        return None
    2058
    2059    def _parse_into(self) -> t.Optional[exp.Into]:
    2060        if not self._match(TokenType.INTO):
    2061            return None
    2062
    2063        temp = self._match(TokenType.TEMPORARY)
    2064        unlogged = self._match_text_seq("UNLOGGED")
    2065        self._match(TokenType.TABLE)
    2066
    2067        return self.expression(
    2068            exp.Into, this=self._parse_table(schema=True), temporary=temp, unlogged=unlogged
    2069        )
    2070
    2071    def _parse_from(
    2072        self, modifiers: bool = False, skip_from_token: bool = False
    2073    ) -> t.Optional[exp.From]:
    2074        if not skip_from_token and not self._match(TokenType.FROM):
    2075            return None
    2076
    2077        comments = self._prev_comments
    2078        this = self._parse_table()
    2079
    2080        return self.expression(
    2081            exp.From,
    2082            comments=comments,
    2083            this=self._parse_query_modifiers(this) if modifiers else this,
    2084        )
    2085
    2086    def _parse_match_recognize(self) -> t.Optional[exp.MatchRecognize]:
    2087        if not self._match(TokenType.MATCH_RECOGNIZE):
    2088            return None
    2089
    2090        self._match_l_paren()
    2091
    2092        partition = self._parse_partition_by()
    2093        order = self._parse_order()
    2094        measures = (
    2095            self._parse_csv(self._parse_expression) if self._match_text_seq("MEASURES") else None
    2096        )
    2097
    2098        if self._match_text_seq("ONE", "ROW", "PER", "MATCH"):
    2099            rows = exp.var("ONE ROW PER MATCH")
    2100        elif self._match_text_seq("ALL", "ROWS", "PER", "MATCH"):
    2101            text = "ALL ROWS PER MATCH"
    2102            if self._match_text_seq("SHOW", "EMPTY", "MATCHES"):
    2103                text += f" SHOW EMPTY MATCHES"
    2104            elif self._match_text_seq("OMIT", "EMPTY", "MATCHES"):
    2105                text += f" OMIT EMPTY MATCHES"
    2106            elif self._match_text_seq("WITH", "UNMATCHED", "ROWS"):
    2107                text += f" WITH UNMATCHED ROWS"
    2108            rows = exp.var(text)
    2109        else:
    2110            rows = None
    2111
    2112        if self._match_text_seq("AFTER", "MATCH", "SKIP"):
    2113            text = "AFTER MATCH SKIP"
    2114            if self._match_text_seq("PAST", "LAST", "ROW"):
    2115                text += f" PAST LAST ROW"
    2116            elif self._match_text_seq("TO", "NEXT", "ROW"):
    2117                text += f" TO NEXT ROW"
    2118            elif self._match_text_seq("TO", "FIRST"):
    2119                text += f" TO FIRST {self._advance_any().text}"  # type: ignore
    2120            elif self._match_text_seq("TO", "LAST"):
    2121                text += f" TO LAST {self._advance_any().text}"  # type: ignore
    2122            after = exp.var(text)
    2123        else:
    2124            after = None
    2125
    2126        if self._match_text_seq("PATTERN"):
    2127            self._match_l_paren()
    2128
    2129            if not self._curr:
    2130                self.raise_error("Expecting )", self._curr)
    2131
    2132            paren = 1
    2133            start = self._curr
    2134
    2135            while self._curr and paren > 0:
    2136                if self._curr.token_type == TokenType.L_PAREN:
    2137                    paren += 1
    2138                if self._curr.token_type == TokenType.R_PAREN:
    2139                    paren -= 1
    2140
    2141                end = self._prev
    2142                self._advance()
    2143
    2144            if paren > 0:
    2145                self.raise_error("Expecting )", self._curr)
    2146
    2147            pattern = exp.var(self._find_sql(start, end))
    2148        else:
    2149            pattern = None
    2150
    2151        define = (
    2152            self._parse_csv(
    2153                lambda: self.expression(
    2154                    exp.Alias,
    2155                    alias=self._parse_id_var(any_token=True),
    2156                    this=self._match(TokenType.ALIAS) and self._parse_conjunction(),
    2157                )
    2158            )
    2159            if self._match_text_seq("DEFINE")
    2160            else None
    2161        )
    2162
    2163        self._match_r_paren()
    2164
    2165        return self.expression(
    2166            exp.MatchRecognize,
    2167            partition_by=partition,
    2168            order=order,
    2169            measures=measures,
    2170            rows=rows,
    2171            after=after,
    2172            pattern=pattern,
    2173            define=define,
    2174            alias=self._parse_table_alias(),
    2175        )
    2176
    2177    def _parse_lateral(self) -> t.Optional[exp.Lateral]:
    2178        outer_apply = self._match_pair(TokenType.OUTER, TokenType.APPLY)
    2179        cross_apply = self._match_pair(TokenType.CROSS, TokenType.APPLY)
    2180
    2181        if outer_apply or cross_apply:
    2182            this = self._parse_select(table=True)
    2183            view = None
    2184            outer = not cross_apply
    2185        elif self._match(TokenType.LATERAL):
    2186            this = self._parse_select(table=True)
    2187            view = self._match(TokenType.VIEW)
    2188            outer = self._match(TokenType.OUTER)
    2189        else:
    2190            return None
    2191
    2192        if not this:
    2193            this = self._parse_function() or self._parse_id_var(any_token=False)
    2194            while self._match(TokenType.DOT):
    2195                this = exp.Dot(
    2196                    this=this,
    2197                    expression=self._parse_function() or self._parse_id_var(any_token=False),
    2198                )
    2199
    2200        if view:
    2201            table = self._parse_id_var(any_token=False)
    2202            columns = self._parse_csv(self._parse_id_var) if self._match(TokenType.ALIAS) else []
    2203            table_alias: t.Optional[exp.TableAlias] = self.expression(
    2204                exp.TableAlias, this=table, columns=columns
    2205            )
    2206        elif isinstance(this, exp.Subquery) and this.alias:
    2207            # Ensures parity between the Subquery's and the Lateral's "alias" args
    2208            table_alias = this.args["alias"].copy()
    2209        else:
    2210            table_alias = self._parse_table_alias()
    2211
    2212        return self.expression(exp.Lateral, this=this, view=view, outer=outer, alias=table_alias)
    2213
    2214    def _parse_join_parts(
    2215        self,
    2216    ) -> t.Tuple[t.Optional[Token], t.Optional[Token], t.Optional[Token]]:
    2217        return (
    2218            self._match_set(self.JOIN_METHODS) and self._prev,
    2219            self._match_set(self.JOIN_SIDES) and self._prev,
    2220            self._match_set(self.JOIN_KINDS) and self._prev,
    2221        )
    2222
    2223    def _parse_join(self, skip_join_token: bool = False) -> t.Optional[exp.Join]:
    2224        if self._match(TokenType.COMMA):
    2225            return self.expression(exp.Join, this=self._parse_table())
    2226
    2227        index = self._index
    2228        method, side, kind = self._parse_join_parts()
    2229        hint = self._prev.text if self._match_texts(self.JOIN_HINTS) else None
    2230        join = self._match(TokenType.JOIN)
    2231
    2232        if not skip_join_token and not join:
    2233            self._retreat(index)
    2234            kind = None
    2235            method = None
    2236            side = None
    2237
    2238        outer_apply = self._match_pair(TokenType.OUTER, TokenType.APPLY, False)
    2239        cross_apply = self._match_pair(TokenType.CROSS, TokenType.APPLY, False)
    2240
    2241        if not skip_join_token and not join and not outer_apply and not cross_apply:
    2242            return None
    2243
    2244        if outer_apply:
    2245            side = Token(TokenType.LEFT, "LEFT")
    2246
    2247        kwargs: t.Dict[str, t.Any] = {"this": self._parse_table()}
    2248
    2249        if method:
    2250            kwargs["method"] = method.text
    2251        if side:
    2252            kwargs["side"] = side.text
    2253        if kind:
    2254            kwargs["kind"] = kind.text
    2255        if hint:
    2256            kwargs["hint"] = hint
    2257
    2258        if self._match(TokenType.ON):
    2259            kwargs["on"] = self._parse_conjunction()
    2260        elif self._match(TokenType.USING):
    2261            kwargs["using"] = self._parse_wrapped_id_vars()
    2262
    2263        return self.expression(exp.Join, **kwargs)
    2264
    2265    def _parse_index(
    2266        self,
    2267        index: t.Optional[exp.Expression] = None,
    2268    ) -> t.Optional[exp.Index]:
    2269        if index:
    2270            unique = None
    2271            primary = None
    2272            amp = None
    2273
    2274            self._match(TokenType.ON)
    2275            self._match(TokenType.TABLE)  # hive
    2276            table = self._parse_table_parts(schema=True)
    2277        else:
    2278            unique = self._match(TokenType.UNIQUE)
    2279            primary = self._match_text_seq("PRIMARY")
    2280            amp = self._match_text_seq("AMP")
    2281
    2282            if not self._match(TokenType.INDEX):
    2283                return None
    2284
    2285            index = self._parse_id_var()
    2286            table = None
    2287
    2288        using = self._parse_field() if self._match(TokenType.USING) else None
    2289
    2290        if self._match(TokenType.L_PAREN, advance=False):
    2291            columns = self._parse_wrapped_csv(self._parse_ordered)
    2292        else:
    2293            columns = None
    2294
    2295        return self.expression(
    2296            exp.Index,
    2297            this=index,
    2298            table=table,
    2299            using=using,
    2300            columns=columns,
    2301            unique=unique,
    2302            primary=primary,
    2303            amp=amp,
    2304            partition_by=self._parse_partition_by(),
    2305        )
    2306
    2307    def _parse_table_hints(self) -> t.Optional[t.List[exp.Expression]]:
    2308        hints: t.List[exp.Expression] = []
    2309        if self._match_pair(TokenType.WITH, TokenType.L_PAREN):
    2310            # https://learn.microsoft.com/en-us/sql/t-sql/queries/hints-transact-sql-table?view=sql-server-ver16
    2311            hints.append(
    2312                self.expression(
    2313                    exp.WithTableHint,
    2314                    expressions=self._parse_csv(
    2315                        lambda: self._parse_function() or self._parse_var(any_token=True)
    2316                    ),
    2317                )
    2318            )
    2319            self._match_r_paren()
    2320        else:
    2321            # https://dev.mysql.com/doc/refman/8.0/en/index-hints.html
    2322            while self._match_set(self.TABLE_INDEX_HINT_TOKENS):
    2323                hint = exp.IndexTableHint(this=self._prev.text.upper())
    2324
    2325                self._match_texts({"INDEX", "KEY"})
    2326                if self._match(TokenType.FOR):
    2327                    hint.set("target", self._advance_any() and self._prev.text.upper())
    2328
    2329                hint.set("expressions", self._parse_wrapped_id_vars())
    2330                hints.append(hint)
    2331
    2332        return hints or None
    2333
    2334    def _parse_table_part(self, schema: bool = False) -> t.Optional[exp.Expression]:
    2335        return (
    2336            (not schema and self._parse_function(optional_parens=False))
    2337            or self._parse_id_var(any_token=False)
    2338            or self._parse_string_as_identifier()
    2339            or self._parse_placeholder()
    2340        )
    2341
    2342    def _parse_table_parts(self, schema: bool = False) -> exp.Table:
    2343        catalog = None
    2344        db = None
    2345        table = self._parse_table_part(schema=schema)
    2346
    2347        while self._match(TokenType.DOT):
    2348            if catalog:
    2349                # This allows nesting the table in arbitrarily many dot expressions if needed
    2350                table = self.expression(
    2351                    exp.Dot, this=table, expression=self._parse_table_part(schema=schema)
    2352                )
    2353            else:
    2354                catalog = db
    2355                db = table
    2356                table = self._parse_table_part(schema=schema)
    2357
    2358        if not table:
    2359            self.raise_error(f"Expected table name but got {self._curr}")
    2360
    2361        return self.expression(
    2362            exp.Table, this=table, db=db, catalog=catalog, pivots=self._parse_pivots()
    2363        )
    2364
    2365    def _parse_table(
    2366        self, schema: bool = False, alias_tokens: t.Optional[t.Collection[TokenType]] = None
    2367    ) -> t.Optional[exp.Expression]:
    2368        lateral = self._parse_lateral()
    2369        if lateral:
    2370            return lateral
    2371
    2372        unnest = self._parse_unnest()
    2373        if unnest:
    2374            return unnest
    2375
    2376        values = self._parse_derived_table_values()
    2377        if values:
    2378            return values
    2379
    2380        subquery = self._parse_select(table=True)
    2381        if subquery:
    2382            if not subquery.args.get("pivots"):
    2383                subquery.set("pivots", self._parse_pivots())
    2384            return subquery
    2385
    2386        this: exp.Expression = self._parse_table_parts(schema=schema)
    2387
    2388        if schema:
    2389            return self._parse_schema(this=this)
    2390
    2391        if self.ALIAS_POST_TABLESAMPLE:
    2392            table_sample = self._parse_table_sample()
    2393
    2394        alias = self._parse_table_alias(alias_tokens=alias_tokens or self.TABLE_ALIAS_TOKENS)
    2395        if alias:
    2396            this.set("alias", alias)
    2397
    2398        if not this.args.get("pivots"):
    2399            this.set("pivots", self._parse_pivots())
    2400
    2401        this.set("hints", self._parse_table_hints())
    2402
    2403        if not self.ALIAS_POST_TABLESAMPLE:
    2404            table_sample = self._parse_table_sample()
    2405
    2406        if table_sample:
    2407            table_sample.set("this", this)
    2408            this = table_sample
    2409
    2410        return this
    2411
    2412    def _parse_unnest(self, with_alias: bool = True) -> t.Optional[exp.Unnest]:
    2413        if not self._match(TokenType.UNNEST):
    2414            return None
    2415
    2416        expressions = self._parse_wrapped_csv(self._parse_type)
    2417        ordinality = self._match_pair(TokenType.WITH, TokenType.ORDINALITY)
    2418
    2419        alias = self._parse_table_alias() if with_alias else None
    2420
    2421        if alias and self.UNNEST_COLUMN_ONLY:
    2422            if alias.args.get("columns"):
    2423                self.raise_error("Unexpected extra column alias in unnest.")
    2424
    2425            alias.set("columns", [alias.this])
    2426            alias.set("this", None)
    2427
    2428        offset = None
    2429        if self._match_pair(TokenType.WITH, TokenType.OFFSET):
    2430            self._match(TokenType.ALIAS)
    2431            offset = self._parse_id_var() or exp.to_identifier("offset")
    2432
    2433        return self.expression(
    2434            exp.Unnest, expressions=expressions, ordinality=ordinality, alias=alias, offset=offset
    2435        )
    2436
    2437    def _parse_derived_table_values(self) -> t.Optional[exp.Values]:
    2438        is_derived = self._match_pair(TokenType.L_PAREN, TokenType.VALUES)
    2439        if not is_derived and not self._match(TokenType.VALUES):
    2440            return None
    2441
    2442        expressions = self._parse_csv(self._parse_value)
    2443        alias = self._parse_table_alias()
    2444
    2445        if is_derived:
    2446            self._match_r_paren()
    2447
    2448        return self.expression(
    2449            exp.Values, expressions=expressions, alias=alias or self._parse_table_alias()
    2450        )
    2451
    2452    def _parse_table_sample(self, as_modifier: bool = False) -> t.Optional[exp.TableSample]:
    2453        if not self._match(TokenType.TABLE_SAMPLE) and not (
    2454            as_modifier and self._match_text_seq("USING", "SAMPLE")
    2455        ):
    2456            return None
    2457
    2458        bucket_numerator = None
    2459        bucket_denominator = None
    2460        bucket_field = None
    2461        percent = None
    2462        rows = None
    2463        size = None
    2464        seed = None
    2465
    2466        kind = (
    2467            self._prev.text if self._prev.token_type == TokenType.TABLE_SAMPLE else "USING SAMPLE"
    2468        )
    2469        method = self._parse_var(tokens=(TokenType.ROW,))
    2470
    2471        self._match(TokenType.L_PAREN)
    2472
    2473        num = self._parse_number()
    2474
    2475        if self._match_text_seq("BUCKET"):
    2476            bucket_numerator = self._parse_number()
    2477            self._match_text_seq("OUT", "OF")
    2478            bucket_denominator = bucket_denominator = self._parse_number()
    2479            self._match(TokenType.ON)
    2480            bucket_field = self._parse_field()
    2481        elif self._match_set((TokenType.PERCENT, TokenType.MOD)):
    2482            percent = num
    2483        elif self._match(TokenType.ROWS):
    2484            rows = num
    2485        else:
    2486            size = num
    2487
    2488        self._match(TokenType.R_PAREN)
    2489
    2490        if self._match(TokenType.L_PAREN):
    2491            method = self._parse_var()
    2492            seed = self._match(TokenType.COMMA) and self._parse_number()
    2493            self._match_r_paren()
    2494        elif self._match_texts(("SEED", "REPEATABLE")):
    2495            seed = self._parse_wrapped(self._parse_number)
    2496
    2497        return self.expression(
    2498            exp.TableSample,
    2499            method=method,
    2500            bucket_numerator=bucket_numerator,
    2501            bucket_denominator=bucket_denominator,
    2502            bucket_field=bucket_field,
    2503            percent=percent,
    2504            rows=rows,
    2505            size=size,
    2506            seed=seed,
    2507            kind=kind,
    2508        )
    2509
    2510    def _parse_pivots(self) -> t.List[t.Optional[exp.Expression]]:
    2511        return list(iter(self._parse_pivot, None))
    2512
    2513    # https://duckdb.org/docs/sql/statements/pivot
    2514    def _parse_simplified_pivot(self) -> exp.Pivot:
    2515        def _parse_on() -> t.Optional[exp.Expression]:
    2516            this = self._parse_bitwise()
    2517            return self._parse_in(this) if self._match(TokenType.IN) else this
    2518
    2519        this = self._parse_table()
    2520        expressions = self._match(TokenType.ON) and self._parse_csv(_parse_on)
    2521        using = self._match(TokenType.USING) and self._parse_csv(
    2522            lambda: self._parse_alias(self._parse_function())
    2523        )
    2524        group = self._parse_group()
    2525        return self.expression(
    2526            exp.Pivot, this=this, expressions=expressions, using=using, group=group
    2527        )
    2528
    2529    def _parse_pivot(self) -> t.Optional[exp.Pivot]:
    2530        index = self._index
    2531
    2532        if self._match(TokenType.PIVOT):
    2533            unpivot = False
    2534        elif self._match(TokenType.UNPIVOT):
    2535            unpivot = True
    2536        else:
    2537            return None
    2538
    2539        expressions = []
    2540        field = None
    2541
    2542        if not self._match(TokenType.L_PAREN):
    2543            self._retreat(index)
    2544            return None
    2545
    2546        if unpivot:
    2547            expressions = self._parse_csv(self._parse_column)
    2548        else:
    2549            expressions = self._parse_csv(lambda: self._parse_alias(self._parse_function()))
    2550
    2551        if not expressions:
    2552            self.raise_error("Failed to parse PIVOT's aggregation list")
    2553
    2554        if not self._match(TokenType.FOR):
    2555            self.raise_error("Expecting FOR")
    2556
    2557        value = self._parse_column()
    2558
    2559        if not self._match(TokenType.IN):
    2560            self.raise_error("Expecting IN")
    2561
    2562        field = self._parse_in(value, alias=True)
    2563
    2564        self._match_r_paren()
    2565
    2566        pivot = self.expression(exp.Pivot, expressions=expressions, field=field, unpivot=unpivot)
    2567
    2568        if not self._match_set((TokenType.PIVOT, TokenType.UNPIVOT), advance=False):
    2569            pivot.set("alias", self._parse_table_alias())
    2570
    2571        if not unpivot:
    2572            names = self._pivot_column_names(t.cast(t.List[exp.Expression], expressions))
    2573
    2574            columns: t.List[exp.Expression] = []
    2575            for fld in pivot.args["field"].expressions:
    2576                field_name = fld.sql() if self.IDENTIFY_PIVOT_STRINGS else fld.alias_or_name
    2577                for name in names:
    2578                    if self.PREFIXED_PIVOT_COLUMNS:
    2579                        name = f"{name}_{field_name}" if name else field_name
    2580                    else:
    2581                        name = f"{field_name}_{name}" if name else field_name
    2582
    2583                    columns.append(exp.to_identifier(name))
    2584
    2585            pivot.set("columns", columns)
    2586
    2587        return pivot
    2588
    2589    def _pivot_column_names(self, aggregations: t.List[exp.Expression]) -> t.List[str]:
    2590        return [agg.alias for agg in aggregations]
    2591
    2592    def _parse_where(self, skip_where_token: bool = False) -> t.Optional[exp.Where]:
    2593        if not skip_where_token and not self._match(TokenType.WHERE):
    2594            return None
    2595
    2596        return self.expression(
    2597            exp.Where, comments=self._prev_comments, this=self._parse_conjunction()
    2598        )
    2599
    2600    def _parse_group(self, skip_group_by_token: bool = False) -> t.Optional[exp.Group]:
    2601        if not skip_group_by_token and not self._match(TokenType.GROUP_BY):
    2602            return None
    2603
    2604        elements = defaultdict(list)
    2605
    2606        while True:
    2607            expressions = self._parse_csv(self._parse_conjunction)
    2608            if expressions:
    2609                elements["expressions"].extend(expressions)
    2610
    2611            grouping_sets = self._parse_grouping_sets()
    2612            if grouping_sets:
    2613                elements["grouping_sets"].extend(grouping_sets)
    2614
    2615            rollup = None
    2616            cube = None
    2617            totals = None
    2618
    2619            with_ = self._match(TokenType.WITH)
    2620            if self._match(TokenType.ROLLUP):
    2621                rollup = with_ or self._parse_wrapped_csv(self._parse_column)
    2622                elements["rollup"].extend(ensure_list(rollup))
    2623
    2624            if self._match(TokenType.CUBE):
    2625                cube = with_ or self._parse_wrapped_csv(self._parse_column)
    2626                elements["cube"].extend(ensure_list(cube))
    2627
    2628            if self._match_text_seq("TOTALS"):
    2629                totals = True
    2630                elements["totals"] = True  # type: ignore
    2631
    2632            if not (grouping_sets or rollup or cube or totals):
    2633                break
    2634
    2635        return self.expression(exp.Group, **elements)  # type: ignore
    2636
    2637    def _parse_grouping_sets(self) -> t.Optional[t.List[t.Optional[exp.Expression]]]:
    2638        if not self._match(TokenType.GROUPING_SETS):
    2639            return None
    2640
    2641        return self._parse_wrapped_csv(self._parse_grouping_set)
    2642
    2643    def _parse_grouping_set(self) -> t.Optional[exp.Expression]:
    2644        if self._match(TokenType.L_PAREN):
    2645            grouping_set = self._parse_csv(self._parse_column)
    2646            self._match_r_paren()
    2647            return self.expression(exp.Tuple, expressions=grouping_set)
    2648
    2649        return self._parse_column()
    2650
    2651    def _parse_having(self, skip_having_token: bool = False) -> t.Optional[exp.Having]:
    2652        if not skip_having_token and not self._match(TokenType.HAVING):
    2653            return None
    2654        return self.expression(exp.Having, this=self._parse_conjunction())
    2655
    2656    def _parse_qualify(self) -> t.Optional[exp.Qualify]:
    2657        if not self._match(TokenType.QUALIFY):
    2658            return None
    2659        return self.expression(exp.Qualify, this=self._parse_conjunction())
    2660
    2661    def _parse_order(
    2662        self, this: t.Optional[exp.Expression] = None, skip_order_token: bool = False
    2663    ) -> t.Optional[exp.Expression]:
    2664        if not skip_order_token and not self._match(TokenType.ORDER_BY):
    2665            return this
    2666
    2667        return self.expression(
    2668            exp.Order, this=this, expressions=self._parse_csv(self._parse_ordered)
    2669        )
    2670
    2671    def _parse_sort(self, exp_class: t.Type[E], token: TokenType) -> t.Optional[E]:
    2672        if not self._match(token):
    2673            return None
    2674        return self.expression(exp_class, expressions=self._parse_csv(self._parse_ordered))
    2675
    2676    def _parse_ordered(self) -> exp.Ordered:
    2677        this = self._parse_conjunction()
    2678        self._match(TokenType.ASC)
    2679
    2680        is_desc = self._match(TokenType.DESC)
    2681        is_nulls_first = self._match_text_seq("NULLS", "FIRST")
    2682        is_nulls_last = self._match_text_seq("NULLS", "LAST")
    2683        desc = is_desc or False
    2684        asc = not desc
    2685        nulls_first = is_nulls_first or False
    2686        explicitly_null_ordered = is_nulls_first or is_nulls_last
    2687
    2688        if (
    2689            not explicitly_null_ordered
    2690            and (
    2691                (asc and self.NULL_ORDERING == "nulls_are_small")
    2692                or (desc and self.NULL_ORDERING != "nulls_are_small")
    2693            )
    2694            and self.NULL_ORDERING != "nulls_are_last"
    2695        ):
    2696            nulls_first = True
    2697
    2698        return self.expression(exp.Ordered, this=this, desc=desc, nulls_first=nulls_first)
    2699
    2700    def _parse_limit(
    2701        self, this: t.Optional[exp.Expression] = None, top: bool = False
    2702    ) -> t.Optional[exp.Expression]:
    2703        if self._match(TokenType.TOP if top else TokenType.LIMIT):
    2704            limit_paren = self._match(TokenType.L_PAREN)
    2705            expression = self._parse_number() if top else self._parse_term()
    2706
    2707            if self._match(TokenType.COMMA):
    2708                offset = expression
    2709                expression = self._parse_term()
    2710            else:
    2711                offset = None
    2712
    2713            limit_exp = self.expression(exp.Limit, this=this, expression=expression, offset=offset)
    2714
    2715            if limit_paren:
    2716                self._match_r_paren()
    2717
    2718            return limit_exp
    2719
    2720        if self._match(TokenType.FETCH):
    2721            direction = self._match_set((TokenType.FIRST, TokenType.NEXT))
    2722            direction = self._prev.text if direction else "FIRST"
    2723
    2724            count = self._parse_number()
    2725            percent = self._match(TokenType.PERCENT)
    2726
    2727            self._match_set((TokenType.ROW, TokenType.ROWS))
    2728
    2729            only = self._match_text_seq("ONLY")
    2730            with_ties = self._match_text_seq("WITH", "TIES")
    2731
    2732            if only and with_ties:
    2733                self.raise_error("Cannot specify both ONLY and WITH TIES in FETCH clause")
    2734
    2735            return self.expression(
    2736                exp.Fetch,
    2737                direction=direction,
    2738                count=count,
    2739                percent=percent,
    2740                with_ties=with_ties,
    2741            )
    2742
    2743        return this
    2744
    2745    def _parse_offset(self, this: t.Optional[exp.Expression] = None) -> t.Optional[exp.Expression]:
    2746        if not self._match(TokenType.OFFSET):
    2747            return this
    2748
    2749        count = self._parse_number()
    2750        self._match_set((TokenType.ROW, TokenType.ROWS))
    2751        return self.expression(exp.Offset, this=this, expression=count)
    2752
    2753    def _parse_locks(self) -> t.List[exp.Lock]:
    2754        locks = []
    2755        while True:
    2756            if self._match_text_seq("FOR", "UPDATE"):
    2757                update = True
    2758            elif self._match_text_seq("FOR", "SHARE") or self._match_text_seq(
    2759                "LOCK", "IN", "SHARE", "MODE"
    2760            ):
    2761                update = False
    2762            else:
    2763                break
    2764
    2765            expressions = None
    2766            if self._match_text_seq("OF"):
    2767                expressions = self._parse_csv(lambda: self._parse_table(schema=True))
    2768
    2769            wait: t.Optional[bool | exp.Expression] = None
    2770            if self._match_text_seq("NOWAIT"):
    2771                wait = True
    2772            elif self._match_text_seq("WAIT"):
    2773                wait = self._parse_primary()
    2774            elif self._match_text_seq("SKIP", "LOCKED"):
    2775                wait = False
    2776
    2777            locks.append(
    2778                self.expression(exp.Lock, update=update, expressions=expressions, wait=wait)
    2779            )
    2780
    2781        return locks
    2782
    2783    def _parse_set_operations(self, this: t.Optional[exp.Expression]) -> t.Optional[exp.Expression]:
    2784        if not self._match_set(self.SET_OPERATIONS):
    2785            return this
    2786
    2787        token_type = self._prev.token_type
    2788
    2789        if token_type == TokenType.UNION:
    2790            expression = exp.Union
    2791        elif token_type == TokenType.EXCEPT:
    2792            expression = exp.Except
    2793        else:
    2794            expression = exp.Intersect
    2795
    2796        return self.expression(
    2797            expression,
    2798            this=this,
    2799            distinct=self._match(TokenType.DISTINCT) or not self._match(TokenType.ALL),
    2800            expression=self._parse_set_operations(self._parse_select(nested=True)),
    2801        )
    2802
    2803    def _parse_expression(self) -> t.Optional[exp.Expression]:
    2804        return self._parse_alias(self._parse_conjunction())
    2805
    2806    def _parse_conjunction(self) -> t.Optional[exp.Expression]:
    2807        return self._parse_tokens(self._parse_equality, self.CONJUNCTION)
    2808
    2809    def _parse_equality(self) -> t.Optional[exp.Expression]:
    2810        return self._parse_tokens(self._parse_comparison, self.EQUALITY)
    2811
    2812    def _parse_comparison(self) -> t.Optional[exp.Expression]:
    2813        return self._parse_tokens(self._parse_range, self.COMPARISON)
    2814
    2815    def _parse_range(self) -> t.Optional[exp.Expression]:
    2816        this = self._parse_bitwise()
    2817        negate = self._match(TokenType.NOT)
    2818
    2819        if self._match_set(self.RANGE_PARSERS):
    2820            expression = self.RANGE_PARSERS[self._prev.token_type](self, this)
    2821            if not expression:
    2822                return this
    2823
    2824            this = expression
    2825        elif self._match(TokenType.ISNULL):
    2826            this = self.expression(exp.Is, this=this, expression=exp.Null())
    2827
    2828        # Postgres supports ISNULL and NOTNULL for conditions.
    2829        # https://blog.andreiavram.ro/postgresql-null-composite-type/
    2830        if self._match(TokenType.NOTNULL):
    2831            this = self.expression(exp.Is, this=this, expression=exp.Null())
    2832            this = self.expression(exp.Not, this=this)
    2833
    2834        if negate:
    2835            this = self.expression(exp.Not, this=this)
    2836
    2837        if self._match(TokenType.IS):
    2838            this = self._parse_is(this)
    2839
    2840        return this
    2841
    2842    def _parse_is(self, this: t.Optional[exp.Expression]) -> t.Optional[exp.Expression]:
    2843        index = self._index - 1
    2844        negate = self._match(TokenType.NOT)
    2845
    2846        if self._match_text_seq("DISTINCT", "FROM"):
    2847            klass = exp.NullSafeEQ if negate else exp.NullSafeNEQ
    2848            return self.expression(klass, this=this, expression=self._parse_expression())
    2849
    2850        expression = self._parse_null() or self._parse_boolean()
    2851        if not expression:
    2852            self._retreat(index)
    2853            return None
    2854
    2855        this = self.expression(exp.Is, this=this, expression=expression)
    2856        return self.expression(exp.Not, this=this) if negate else this
    2857
    2858    def _parse_in(self, this: t.Optional[exp.Expression], alias: bool = False) -> exp.In:
    2859        unnest = self._parse_unnest(with_alias=False)
    2860        if unnest:
    2861            this = self.expression(exp.In, this=this, unnest=unnest)
    2862        elif self._match(TokenType.L_PAREN):
    2863            expressions = self._parse_csv(lambda: self._parse_select_or_expression(alias=alias))
    2864
    2865            if len(expressions) == 1 and isinstance(expressions[0], exp.Subqueryable):
    2866                this = self.expression(exp.In, this=this, query=expressions[0])
    2867            else:
    2868                this = self.expression(exp.In, this=this, expressions=expressions)
    2869
    2870            self._match_r_paren(this)
    2871        else:
    2872            this = self.expression(exp.In, this=this, field=self._parse_field())
    2873
    2874        return this
    2875
    2876    def _parse_between(self, this: exp.Expression) -> exp.Between:
    2877        low = self._parse_bitwise()
    2878        self._match(TokenType.AND)
    2879        high = self._parse_bitwise()
    2880        return self.expression(exp.Between, this=this, low=low, high=high)
    2881
    2882    def _parse_escape(self, this: t.Optional[exp.Expression]) -> t.Optional[exp.Expression]:
    2883        if not self._match(TokenType.ESCAPE):
    2884            return this
    2885        return self.expression(exp.Escape, this=this, expression=self._parse_string())
    2886
    2887    def _parse_interval(self) -> t.Optional[exp.Interval]:
    2888        if not self._match(TokenType.INTERVAL):
    2889            return None
    2890
    2891        if self._match(TokenType.STRING, advance=False):
    2892            this = self._parse_primary()
    2893        else:
    2894            this = self._parse_term()
    2895
    2896        unit = self._parse_function() or self._parse_var()
    2897
    2898        # Most dialects support, e.g., the form INTERVAL '5' day, thus we try to parse
    2899        # each INTERVAL expression into this canonical form so it's easy to transpile
    2900        if this and this.is_number:
    2901            this = exp.Literal.string(this.name)
    2902        elif this and this.is_string:
    2903            parts = this.name.split()
    2904
    2905            if len(parts) == 2:
    2906                if unit:
    2907                    # this is not actually a unit, it's something else
    2908                    unit = None
    2909                    self._retreat(self._index - 1)
    2910                else:
    2911                    this = exp.Literal.string(parts[0])
    2912                    unit = self.expression(exp.Var, this=parts[1])
    2913
    2914        return self.expression(exp.Interval, this=this, unit=unit)
    2915
    2916    def _parse_bitwise(self) -> t.Optional[exp.Expression]:
    2917        this = self._parse_term()
    2918
    2919        while True:
    2920            if self._match_set(self.BITWISE):
    2921                this = self.expression(
    2922                    self.BITWISE[self._prev.token_type], this=this, expression=self._parse_term()
    2923                )
    2924            elif self._match_pair(TokenType.LT, TokenType.LT):
    2925                this = self.expression(
    2926                    exp.BitwiseLeftShift, this=this, expression=self._parse_term()
    2927                )
    2928            elif self._match_pair(TokenType.GT, TokenType.GT):
    2929                this = self.expression(
    2930                    exp.BitwiseRightShift, this=this, expression=self._parse_term()
    2931                )
    2932            else:
    2933                break
    2934
    2935        return this
    2936
    2937    def _parse_term(self) -> t.Optional[exp.Expression]:
    2938        return self._parse_tokens(self._parse_factor, self.TERM)
    2939
    2940    def _parse_factor(self) -> t.Optional[exp.Expression]:
    2941        return self._parse_tokens(self._parse_unary, self.FACTOR)
    2942
    2943    def _parse_unary(self) -> t.Optional[exp.Expression]:
    2944        if self._match_set(self.UNARY_PARSERS):
    2945            return self.UNARY_PARSERS[self._prev.token_type](self)
    2946        return self._parse_at_time_zone(self._parse_type())
    2947
    2948    def _parse_type(self) -> t.Optional[exp.Expression]:
    2949        interval = self._parse_interval()
    2950        if interval:
    2951            return interval
    2952
    2953        index = self._index
    2954        data_type = self._parse_types(check_func=True)
    2955        this = self._parse_column()
    2956
    2957        if data_type:
    2958            if isinstance(this, exp.Literal):
    2959                parser = self.TYPE_LITERAL_PARSERS.get(data_type.this)
    2960                if parser:
    2961                    return parser(self, this, data_type)
    2962                return self.expression(exp.Cast, this=this, to=data_type)
    2963            if not data_type.expressions:
    2964                self._retreat(index)
    2965                return self._parse_column()
    2966            return self._parse_column_ops(data_type)
    2967
    2968        return this
    2969
    2970    def _parse_type_size(self) -> t.Optional[exp.DataTypeSize]:
    2971        this = self._parse_type()
    2972        if not this:
    2973            return None
    2974
    2975        return self.expression(
    2976            exp.DataTypeSize, this=this, expression=self._parse_var(any_token=True)
    2977        )
    2978
    2979    def _parse_types(
    2980        self, check_func: bool = False, schema: bool = False
    2981    ) -> t.Optional[exp.Expression]:
    2982        index = self._index
    2983
    2984        prefix = self._match_text_seq("SYSUDTLIB", ".")
    2985
    2986        if not self._match_set(self.TYPE_TOKENS):
    2987            return None
    2988
    2989        type_token = self._prev.token_type
    2990
    2991        if type_token == TokenType.PSEUDO_TYPE:
    2992            return self.expression(exp.PseudoType, this=self._prev.text)
    2993
    2994        nested = type_token in self.NESTED_TYPE_TOKENS
    2995        is_struct = type_token == TokenType.STRUCT
    2996        expressions = None
    2997        maybe_func = False
    2998
    2999        if self._match(TokenType.L_PAREN):
    3000            if is_struct:
    3001                expressions = self._parse_csv(self._parse_struct_types)
    3002            elif nested:
    3003                expressions = self._parse_csv(
    3004                    lambda: self._parse_types(check_func=check_func, schema=schema)
    3005                )
    3006            elif type_token in self.ENUM_TYPE_TOKENS:
    3007                expressions = self._parse_csv(self._parse_primary)
    3008            else:
    3009                expressions = self._parse_csv(self._parse_type_size)
    3010
    3011            if not expressions or not self._match(TokenType.R_PAREN):
    3012                self._retreat(index)
    3013                return None
    3014
    3015            maybe_func = True
    3016
    3017        if self._match_pair(TokenType.L_BRACKET, TokenType.R_BRACKET):
    3018            this = exp.DataType(
    3019                this=exp.DataType.Type.ARRAY,
    3020                expressions=[exp.DataType.build(type_token.value, expressions=expressions)],
    3021                nested=True,
    3022            )
    3023
    3024            while self._match_pair(TokenType.L_BRACKET, TokenType.R_BRACKET):
    3025                this = exp.DataType(this=exp.DataType.Type.ARRAY, expressions=[this], nested=True)
    3026
    3027            return this
    3028
    3029        if self._match(TokenType.L_BRACKET):
    3030            self._retreat(index)
    3031            return None
    3032
    3033        values: t.Optional[t.List[t.Optional[exp.Expression]]] = None
    3034        if nested and self._match(TokenType.LT):
    3035            if is_struct:
    3036                expressions = self._parse_csv(self._parse_struct_types)
    3037            else:
    3038                expressions = self._parse_csv(
    3039                    lambda: self._parse_types(check_func=check_func, schema=schema)
    3040                )
    3041
    3042            if not self._match(TokenType.GT):
    3043                self.raise_error("Expecting >")
    3044
    3045            if self._match_set((TokenType.L_BRACKET, TokenType.L_PAREN)):
    3046                values = self._parse_csv(self._parse_conjunction)
    3047                self._match_set((TokenType.R_BRACKET, TokenType.R_PAREN))
    3048
    3049        value: t.Optional[exp.Expression] = None
    3050        if type_token in self.TIMESTAMPS:
    3051            if self._match_text_seq("WITH", "TIME", "ZONE"):
    3052                maybe_func = False
    3053                value = exp.DataType(this=exp.DataType.Type.TIMESTAMPTZ, expressions=expressions)
    3054            elif self._match_text_seq("WITH", "LOCAL", "TIME", "ZONE"):
    3055                maybe_func = False
    3056                value = exp.DataType(this=exp.DataType.Type.TIMESTAMPLTZ, expressions=expressions)
    3057            elif self._match_text_seq("WITHOUT", "TIME", "ZONE"):
    3058                maybe_func = False
    3059        elif type_token == TokenType.INTERVAL:
    3060            unit = self._parse_var()
    3061
    3062            if not unit:
    3063                value = self.expression(exp.DataType, this=exp.DataType.Type.INTERVAL)
    3064            else:
    3065                value = self.expression(exp.Interval, unit=unit)
    3066
    3067        if maybe_func and check_func:
    3068            index2 = self._index
    3069            peek = self._parse_string()
    3070
    3071            if not peek:
    3072                self._retreat(index)
    3073                return None
    3074
    3075            self._retreat(index2)
    3076
    3077        if value:
    3078            return value
    3079
    3080        return exp.DataType(
    3081            this=exp.DataType.Type[type_token.value.upper()],
    3082            expressions=expressions,
    3083            nested=nested,
    3084            values=values,
    3085            prefix=prefix,
    3086        )
    3087
    3088    def _parse_struct_types(self) -> t.Optional[exp.Expression]:
    3089        this = self._parse_type() or self._parse_id_var()
    3090        self._match(TokenType.COLON)
    3091        return self._parse_column_def(this)
    3092
    3093    def _parse_at_time_zone(self, this: t.Optional[exp.Expression]) -> t.Optional[exp.Expression]:
    3094        if not self._match_text_seq("AT", "TIME", "ZONE"):
    3095            return this
    3096        return self.expression(exp.AtTimeZone, this=this, zone=self._parse_unary())
    3097
    3098    def _parse_column(self) -> t.Optional[exp.Expression]:
    3099        this = self._parse_field()
    3100        if isinstance(this, exp.Identifier):
    3101            this = self.expression(exp.Column, this=this)
    3102        elif not this:
    3103            return self._parse_bracket(this)
    3104        return self._parse_column_ops(this)
    3105
    3106    def _parse_column_ops(self, this: t.Optional[exp.Expression]) -> t.Optional[exp.Expression]:
    3107        this = self._parse_bracket(this)
    3108
    3109        while self._match_set(self.COLUMN_OPERATORS):
    3110            op_token = self._prev.token_type
    3111            op = self.COLUMN_OPERATORS.get(op_token)
    3112
    3113            if op_token == TokenType.DCOLON:
    3114                field = self._parse_types()
    3115                if not field:
    3116                    self.raise_error("Expected type")
    3117            elif op and self._curr:
    3118                self._advance()
    3119                value = self._prev.text
    3120                field = (
    3121                    exp.Literal.number(value)
    3122                    if self._prev.token_type == TokenType.NUMBER
    3123                    else exp.Literal.string(value)
    3124                )
    3125            else:
    3126                field = self._parse_field(anonymous_func=True, any_token=True)
    3127
    3128            if isinstance(field, exp.Func):
    3129                # bigquery allows function calls like x.y.count(...)
    3130                # SAFE.SUBSTR(...)
    3131                # https://cloud.google.com/bigquery/docs/reference/standard-sql/functions-reference#function_call_rules
    3132                this = self._replace_columns_with_dots(this)
    3133
    3134            if op:
    3135                this = op(self, this, field)
    3136            elif isinstance(this, exp.Column) and not this.args.get("catalog"):
    3137                this = self.expression(
    3138                    exp.Column,
    3139                    this=field,
    3140                    table=this.this,
    3141                    db=this.args.get("table"),
    3142                    catalog=this.args.get("db"),
    3143                )
    3144            else:
    3145                this = self.expression(exp.Dot, this=this, expression=field)
    3146            this = self._parse_bracket(this)
    3147        return this
    3148
    3149    def _parse_primary(self) -> t.Optional[exp.Expression]:
    3150        if self._match_set(self.PRIMARY_PARSERS):
    3151            token_type = self._prev.token_type
    3152            primary = self.PRIMARY_PARSERS[token_type](self, self._prev)
    3153
    3154            if token_type == TokenType.STRING:
    3155                expressions = [primary]
    3156                while self._match(TokenType.STRING):
    3157                    expressions.append(exp.Literal.string(self._prev.text))
    3158
    3159                if len(expressions) > 1:
    3160                    return self.expression(exp.Concat, expressions=expressions)
    3161
    3162            return primary
    3163
    3164        if self._match_pair(TokenType.DOT, TokenType.NUMBER):
    3165            return exp.Literal.number(f"0.{self._prev.text}")
    3166
    3167        if self._match(TokenType.L_PAREN):
    3168            comments = self._prev_comments
    3169            query = self._parse_select()
    3170
    3171            if query:
    3172                expressions = [query]
    3173            else:
    3174                expressions = self._parse_csv(self._parse_expression)
    3175
    3176            this = self._parse_query_modifiers(seq_get(expressions, 0))
    3177
    3178            if isinstance(this, exp.Subqueryable):
    3179                this = self._parse_set_operations(
    3180                    self._parse_subquery(this=this, parse_alias=False)
    3181                )
    3182            elif len(expressions) > 1:
    3183                this = self.expression(exp.Tuple, expressions=expressions)
    3184            else:
    3185                this = self.expression(exp.Paren, this=self._parse_set_operations(this))
    3186
    3187            if this:
    3188                this.add_comments(comments)
    3189
    3190            self._match_r_paren(expression=this)
    3191            return this
    3192
    3193        return None
    3194
    3195    def _parse_field(
    3196        self,
    3197        any_token: bool = False,
    3198        tokens: t.Optional[t.Collection[TokenType]] = None,
    3199        anonymous_func: bool = False,
    3200    ) -> t.Optional[exp.Expression]:
    3201        return (
    3202            self._parse_primary()
    3203            or self._parse_function(anonymous=anonymous_func)
    3204            or self._parse_id_var(any_token=any_token, tokens=tokens)
    3205        )
    3206
    3207    def _parse_function(
    3208        self,
    3209        functions: t.Optional[t.Dict[str, t.Callable]] = None,
    3210        anonymous: bool = False,
    3211        optional_parens: bool = True,
    3212    ) -> t.Optional[exp.Expression]:
    3213        if not self._curr:
    3214            return None
    3215
    3216        token_type = self._curr.token_type
    3217
    3218        if optional_parens and self._match_set(self.NO_PAREN_FUNCTION_PARSERS):
    3219            return self.NO_PAREN_FUNCTION_PARSERS[token_type](self)
    3220
    3221        if not self._next or self._next.token_type != TokenType.L_PAREN:
    3222            if optional_parens and token_type in self.NO_PAREN_FUNCTIONS:
    3223                self._advance()
    3224                return self.expression(self.NO_PAREN_FUNCTIONS[token_type])
    3225
    3226            return None
    3227
    3228        if token_type not in self.FUNC_TOKENS:
    3229            return None
    3230
    3231        this = self._curr.text
    3232        upper = this.upper()
    3233        self._advance(2)
    3234
    3235        parser = self.FUNCTION_PARSERS.get(upper)
    3236
    3237        if parser and not anonymous:
    3238            this = parser(self)
    3239        else:
    3240            subquery_predicate = self.SUBQUERY_PREDICATES.get(token_type)
    3241
    3242            if subquery_predicate and self._curr.token_type in (TokenType.SELECT, TokenType.WITH):
    3243                this = self.expression(subquery_predicate, this=self._parse_select())
    3244                self._match_r_paren()
    3245                return this
    3246
    3247            if functions is None:
    3248                functions = self.FUNCTIONS
    3249
    3250            function = functions.get(upper)
    3251
    3252            alias = upper in self.FUNCTIONS_WITH_ALIASED_ARGS
    3253            args = self._parse_csv(lambda: self._parse_lambda(alias=alias))
    3254
    3255            if function and not anonymous:
    3256                this = self.validate_expression(function(args), args)
    3257            else:
    3258                this = self.expression(exp.Anonymous, this=this, expressions=args)
    3259
    3260        self._match_r_paren(this)
    3261        return self._parse_window(this)
    3262
    3263    def _parse_function_parameter(self) -> t.Optional[exp.Expression]:
    3264        return self._parse_column_def(self._parse_id_var())
    3265
    3266    def _parse_user_defined_function(
    3267        self, kind: t.Optional[TokenType] = None
    3268    ) -> t.Optional[exp.Expression]:
    3269        this = self._parse_id_var()
    3270
    3271        while self._match(TokenType.DOT):
    3272            this = self.expression(exp.Dot, this=this, expression=self._parse_id_var())
    3273
    3274        if not self._match(TokenType.L_PAREN):
    3275            return this
    3276
    3277        expressions = self._parse_csv(self._parse_function_parameter)
    3278        self._match_r_paren()
    3279        return self.expression(
    3280            exp.UserDefinedFunction, this=this, expressions=expressions, wrapped=True
    3281        )
    3282
    3283    def _parse_introducer(self, token: Token) -> exp.Introducer | exp.Identifier:
    3284        literal = self._parse_primary()
    3285        if literal:
    3286            return self.expression(exp.Introducer, this=token.text, expression=literal)
    3287
    3288        return self.expression(exp.Identifier, this=token.text)
    3289
    3290    def _parse_session_parameter(self) -> exp.SessionParameter:
    3291        kind = None
    3292        this = self._parse_id_var() or self._parse_primary()
    3293
    3294        if this and self._match(TokenType.DOT):
    3295            kind = this.name
    3296            this = self._parse_var() or self._parse_primary()
    3297
    3298        return self.expression(exp.SessionParameter, this=this, kind=kind)
    3299
    3300    def _parse_lambda(self, alias: bool = False) -> t.Optional[exp.Expression]:
    3301        index = self._index
    3302
    3303        if self._match(TokenType.L_PAREN):
    3304            expressions = self._parse_csv(self._parse_id_var)
    3305
    3306            if not self._match(TokenType.R_PAREN):
    3307                self._retreat(index)
    3308        else:
    3309            expressions = [self._parse_id_var()]
    3310
    3311        if self._match_set(self.LAMBDAS):
    3312            return self.LAMBDAS[self._prev.token_type](self, expressions)
    3313
    3314        self._retreat(index)
    3315
    3316        this: t.Optional[exp.Expression]
    3317
    3318        if self._match(TokenType.DISTINCT):
    3319            this = self.expression(
    3320                exp.Distinct, expressions=self._parse_csv(self._parse_conjunction)
    3321            )
    3322        else:
    3323            this = self._parse_select_or_expression(alias=alias)
    3324
    3325            if isinstance(this, exp.EQ):
    3326                left = this.this
    3327                if isinstance(left, exp.Column):
    3328                    left.replace(exp.var(left.text("this")))
    3329
    3330        return self._parse_limit(self._parse_order(self._parse_respect_or_ignore_nulls(this)))
    3331
    3332    def _parse_schema(self, this: t.Optional[exp.Expression] = None) -> t.Optional[exp.Expression]:
    3333        index = self._index
    3334
    3335        if not self.errors:
    3336            try:
    3337                if self._parse_select(nested=True):
    3338                    return this
    3339            except ParseError:
    3340                pass
    3341            finally:
    3342                self.errors.clear()
    3343                self._retreat(index)
    3344
    3345        if not self._match(TokenType.L_PAREN):
    3346            return this
    3347
    3348        args = self._parse_csv(
    3349            lambda: self._parse_constraint()
    3350            or self._parse_column_def(self._parse_field(any_token=True))
    3351        )
    3352
    3353        self._match_r_paren()
    3354        return self.expression(exp.Schema, this=this, expressions=args)
    3355
    3356    def _parse_column_def(self, this: t.Optional[exp.Expression]) -> t.Optional[exp.Expression]:
    3357        # column defs are not really columns, they're identifiers
    3358        if isinstance(this, exp.Column):
    3359            this = this.this
    3360
    3361        kind = self._parse_types(schema=True)
    3362
    3363        if self._match_text_seq("FOR", "ORDINALITY"):
    3364            return self.expression(exp.ColumnDef, this=this, ordinality=True)
    3365
    3366        constraints = []
    3367        while True:
    3368            constraint = self._parse_column_constraint()
    3369            if not constraint:
    3370                break
    3371            constraints.append(constraint)
    3372
    3373        if not kind and not constraints:
    3374            return this
    3375
    3376        return self.expression(exp.ColumnDef, this=this, kind=kind, constraints=constraints)
    3377
    3378    def _parse_auto_increment(
    3379        self,
    3380    ) -> exp.GeneratedAsIdentityColumnConstraint | exp.AutoIncrementColumnConstraint:
    3381        start = None
    3382        increment = None
    3383
    3384        if self._match(TokenType.L_PAREN, advance=False):
    3385            args = self._parse_wrapped_csv(self._parse_bitwise)
    3386            start = seq_get(args, 0)
    3387            increment = seq_get(args, 1)
    3388        elif self._match_text_seq("START"):
    3389            start = self._parse_bitwise()
    3390            self._match_text_seq("INCREMENT")
    3391            increment = self._parse_bitwise()
    3392
    3393        if start and increment:
    3394            return exp.GeneratedAsIdentityColumnConstraint(start=start, increment=increment)
    3395
    3396        return exp.AutoIncrementColumnConstraint()
    3397
    3398    def _parse_compress(self) -> exp.CompressColumnConstraint:
    3399        if self._match(TokenType.L_PAREN, advance=False):
    3400            return self.expression(
    3401                exp.CompressColumnConstraint, this=self._parse_wrapped_csv(self._parse_bitwise)
    3402            )
    3403
    3404        return self.expression(exp.CompressColumnConstraint, this=self._parse_bitwise())
    3405
    3406    def _parse_generated_as_identity(self) -> exp.GeneratedAsIdentityColumnConstraint:
    3407        if self._match_text_seq("BY", "DEFAULT"):
    3408            on_null = self._match_pair(TokenType.ON, TokenType.NULL)
    3409            this = self.expression(
    3410                exp.GeneratedAsIdentityColumnConstraint, this=False, on_null=on_null
    3411            )
    3412        else:
    3413            self._match_text_seq("ALWAYS")
    3414            this = self.expression(exp.GeneratedAsIdentityColumnConstraint, this=True)
    3415
    3416        self._match(TokenType.ALIAS)
    3417        identity = self._match_text_seq("IDENTITY")
    3418
    3419        if self._match(TokenType.L_PAREN):
    3420            if self._match_text_seq("START", "WITH"):
    3421                this.set("start", self._parse_bitwise())
    3422            if self._match_text_seq("INCREMENT", "BY"):
    3423                this.set("increment", self._parse_bitwise())
    3424            if self._match_text_seq("MINVALUE"):
    3425                this.set("minvalue", self._parse_bitwise())
    3426            if self._match_text_seq("MAXVALUE"):
    3427                this.set("maxvalue", self._parse_bitwise())
    3428
    3429            if self._match_text_seq("CYCLE"):
    3430                this.set("cycle", True)
    3431            elif self._match_text_seq("NO", "CYCLE"):
    3432                this.set("cycle", False)
    3433
    3434            if not identity:
    3435                this.set("expression", self._parse_bitwise())
    3436
    3437            self._match_r_paren()
    3438
    3439        return this
    3440
    3441    def _parse_inline(self) -> exp.InlineLengthColumnConstraint:
    3442        self._match_text_seq("LENGTH")
    3443        return self.expression(exp.InlineLengthColumnConstraint, this=self._parse_bitwise())
    3444
    3445    def _parse_not_constraint(
    3446        self,
    3447    ) -> t.Optional[exp.NotNullColumnConstraint | exp.CaseSpecificColumnConstraint]:
    3448        if self._match_text_seq("NULL"):
    3449            return self.expression(exp.NotNullColumnConstraint)
    3450        if self._match_text_seq("CASESPECIFIC"):
    3451            return self.expression(exp.CaseSpecificColumnConstraint, not_=True)
    3452        return None
    3453
    3454    def _parse_column_constraint(self) -> t.Optional[exp.Expression]:
    3455        if self._match(TokenType.CONSTRAINT):
    3456            this = self._parse_id_var()
    3457        else:
    3458            this = None
    3459
    3460        if self._match_texts(self.CONSTRAINT_PARSERS):
    3461            return self.expression(
    3462                exp.ColumnConstraint,
    3463                this=this,
    3464                kind=self.CONSTRAINT_PARSERS[self._prev.text.upper()](self),
    3465            )
    3466
    3467        return this
    3468
    3469    def _parse_constraint(self) -> t.Optional[exp.Expression]:
    3470        if not self._match(TokenType.CONSTRAINT):
    3471            return self._parse_unnamed_constraint(constraints=self.SCHEMA_UNNAMED_CONSTRAINTS)
    3472
    3473        this = self._parse_id_var()
    3474        expressions = []
    3475
    3476        while True:
    3477            constraint = self._parse_unnamed_constraint() or self._parse_function()
    3478            if not constraint:
    3479                break
    3480            expressions.append(constraint)
    3481
    3482        return self.expression(exp.Constraint, this=this, expressions=expressions)
    3483
    3484    def _parse_unnamed_constraint(
    3485        self, constraints: t.Optional[t.Collection[str]] = None
    3486    ) -> t.Optional[exp.Expression]:
    3487        if not self._match_texts(constraints or self.CONSTRAINT_PARSERS):
    3488            return None
    3489
    3490        constraint = self._prev.text.upper()
    3491        if constraint not in self.CONSTRAINT_PARSERS:
    3492            self.raise_error(f"No parser found for schema constraint {constraint}.")
    3493
    3494        return self.CONSTRAINT_PARSERS[constraint](self)
    3495
    3496    def _parse_unique(self) -> exp.UniqueColumnConstraint:
    3497        self._match_text_seq("KEY")
    3498        return self.expression(
    3499            exp.UniqueColumnConstraint, this=self._parse_schema(self._parse_id_var(any_token=False))
    3500        )
    3501
    3502    def _parse_key_constraint_options(self) -> t.List[str]:
    3503        options = []
    3504        while True:
    3505            if not self._curr:
    3506                break
    3507
    3508            if self._match(TokenType.ON):
    3509                action = None
    3510                on = self._advance_any() and self._prev.text
    3511
    3512                if self._match_text_seq("NO", "ACTION"):
    3513                    action = "NO ACTION"
    3514                elif self._match_text_seq("CASCADE"):
    3515                    action = "CASCADE"
    3516                elif self._match_pair(TokenType.SET, TokenType.NULL):
    3517                    action = "SET NULL"
    3518                elif self._match_pair(TokenType.SET, TokenType.DEFAULT):
    3519                    action = "SET DEFAULT"
    3520                else:
    3521                    self.raise_error("Invalid key constraint")
    3522
    3523                options.append(f"ON {on} {action}")
    3524            elif self._match_text_seq("NOT", "ENFORCED"):
    3525                options.append("NOT ENFORCED")
    3526            elif self._match_text_seq("DEFERRABLE"):
    3527                options.append("DEFERRABLE")
    3528            elif self._match_text_seq("INITIALLY", "DEFERRED"):
    3529                options.append("INITIALLY DEFERRED")
    3530            elif self._match_text_seq("NORELY"):
    3531                options.append("NORELY")
    3532            elif self._match_text_seq("MATCH", "FULL"):
    3533                options.append("MATCH FULL")
    3534            else:
    3535                break
    3536
    3537        return options
    3538
    3539    def _parse_references(self, match: bool = True) -> t.Optional[exp.Reference]:
    3540        if match and not self._match(TokenType.REFERENCES):
    3541            return None
    3542
    3543        expressions = None
    3544        this = self._parse_id_var()
    3545
    3546        if self._match(TokenType.L_PAREN, advance=False):
    3547            expressions = self._parse_wrapped_id_vars()
    3548
    3549        options = self._parse_key_constraint_options()
    3550        return self.expression(exp.Reference, this=this, expressions=expressions, options=options)
    3551
    3552    def _parse_foreign_key(self) -> exp.ForeignKey:
    3553        expressions = self._parse_wrapped_id_vars()
    3554        reference = self._parse_references()
    3555        options = {}
    3556
    3557        while self._match(TokenType.ON):
    3558            if not self._match_set((TokenType.DELETE, TokenType.UPDATE)):
    3559                self.raise_error("Expected DELETE or UPDATE")
    3560
    3561            kind = self._prev.text.lower()
    3562
    3563            if self._match_text_seq("NO", "ACTION"):
    3564                action = "NO ACTION"
    3565            elif self._match(TokenType.SET):
    3566                self._match_set((TokenType.NULL, TokenType.DEFAULT))
    3567                action = "SET " + self._prev.text.upper()
    3568            else:
    3569                self._advance()
    3570                action = self._prev.text.upper()
    3571
    3572            options[kind] = action
    3573
    3574        return self.expression(
    3575            exp.ForeignKey, expressions=expressions, reference=reference, **options  # type: ignore
    3576        )
    3577
    3578    def _parse_primary_key(
    3579        self, wrapped_optional: bool = False, in_props: bool = False
    3580    ) -> exp.PrimaryKeyColumnConstraint | exp.PrimaryKey:
    3581        desc = (
    3582            self._match_set((TokenType.ASC, TokenType.DESC))
    3583            and self._prev.token_type == TokenType.DESC
    3584        )
    3585
    3586        if not in_props and not self._match(TokenType.L_PAREN, advance=False):
    3587            return self.expression(exp.PrimaryKeyColumnConstraint, desc=desc)
    3588
    3589        expressions = self._parse_wrapped_csv(self._parse_field, optional=wrapped_optional)
    3590        options = self._parse_key_constraint_options()
    3591        return self.expression(exp.PrimaryKey, expressions=expressions, options=options)
    3592
    3593    def _parse_bracket(self, this: t.Optional[exp.Expression]) -> t.Optional[exp.Expression]:
    3594        if not self._match_set((TokenType.L_BRACKET, TokenType.L_BRACE)):
    3595            return this
    3596
    3597        bracket_kind = self._prev.token_type
    3598
    3599        if self._match(TokenType.COLON):
    3600            expressions: t.List[t.Optional[exp.Expression]] = [
    3601                self.expression(exp.Slice, expression=self._parse_conjunction())
    3602            ]
    3603        else:
    3604            expressions = self._parse_csv(lambda: self._parse_slice(self._parse_conjunction()))
    3605
    3606        # https://duckdb.org/docs/sql/data_types/struct.html#creating-structs
    3607        if bracket_kind == TokenType.L_BRACE:
    3608            this = self.expression(exp.Struct, expressions=expressions)
    3609        elif not this or this.name.upper() == "ARRAY":
    3610            this = self.expression(exp.Array, expressions=expressions)
    3611        else:
    3612            expressions = apply_index_offset(this, expressions, -self.INDEX_OFFSET)
    3613            this = self.expression(exp.Bracket, this=this, expressions=expressions)
    3614
    3615        if not self._match(TokenType.R_BRACKET) and bracket_kind == TokenType.L_BRACKET:
    3616            self.raise_error("Expected ]")
    3617        elif not self._match(TokenType.R_BRACE) and bracket_kind == TokenType.L_BRACE:
    3618            self.raise_error("Expected }")
    3619
    3620        self._add_comments(this)
    3621        return self._parse_bracket(this)
    3622
    3623    def _parse_slice(self, this: t.Optional[exp.Expression]) -> t.Optional[exp.Expression]:
    3624        if self._match(TokenType.COLON):
    3625            return self.expression(exp.Slice, this=this, expression=self._parse_conjunction())
    3626        return this
    3627
    3628    def _parse_case(self) -> t.Optional[exp.Expression]:
    3629        ifs = []
    3630        default = None
    3631
    3632        expression = self._parse_conjunction()
    3633
    3634        while self._match(TokenType.WHEN):
    3635            this = self._parse_conjunction()
    3636            self._match(TokenType.THEN)
    3637            then = self._parse_conjunction()
    3638            ifs.append(self.expression(exp.If, this=this, true=then))
    3639
    3640        if self._match(TokenType.ELSE):
    3641            default = self._parse_conjunction()
    3642
    3643        if not self._match(TokenType.END):
    3644            self.raise_error("Expected END after CASE", self._prev)
    3645
    3646        return self._parse_window(
    3647            self.expression(exp.Case, this=expression, ifs=ifs, default=default)
    3648        )
    3649
    3650    def _parse_if(self) -> t.Optional[exp.Expression]:
    3651        if self._match(TokenType.L_PAREN):
    3652            args = self._parse_csv(self._parse_conjunction)
    3653            this = self.validate_expression(exp.If.from_arg_list(args), args)
    3654            self._match_r_paren()
    3655        else:
    3656            index = self._index - 1
    3657            condition = self._parse_conjunction()
    3658
    3659            if not condition:
    3660                self._retreat(index)
    3661                return None
    3662
    3663            self._match(TokenType.THEN)
    3664            true = self._parse_conjunction()
    3665            false = self._parse_conjunction() if self._match(TokenType.ELSE) else None
    3666            self._match(TokenType.END)
    3667            this = self.expression(exp.If, this=condition, true=true, false=false)
    3668
    3669        return self._parse_window(this)
    3670
    3671    def _parse_extract(self) -> exp.Extract:
    3672        this = self._parse_function() or self._parse_var() or self._parse_type()
    3673
    3674        if self._match(TokenType.FROM):
    3675            return self.expression(exp.Extract, this=this, expression=self._parse_bitwise())
    3676
    3677        if not self._match(TokenType.COMMA):
    3678            self.raise_error("Expected FROM or comma after EXTRACT", self._prev)
    3679
    3680        return self.expression(exp.Extract, this=this, expression=self._parse_bitwise())
    3681
    3682    def _parse_cast(self, strict: bool) -> exp.Expression:
    3683        this = self._parse_conjunction()
    3684
    3685        if not self._match(TokenType.ALIAS):
    3686            if self._match(TokenType.COMMA):
    3687                return self.expression(
    3688                    exp.CastToStrType, this=this, expression=self._parse_string()
    3689                )
    3690            else:
    3691                self.raise_error("Expected AS after CAST")
    3692
    3693        to = self._parse_types()
    3694
    3695        if not to:
    3696            self.raise_error("Expected TYPE after CAST")
    3697        elif to.this == exp.DataType.Type.CHAR:
    3698            if self._match(TokenType.CHARACTER_SET):
    3699                to = self.expression(exp.CharacterSet, this=self._parse_var_or_string())
    3700        elif to.this in exp.DataType.TEMPORAL_TYPES and self._match(TokenType.FORMAT):
    3701            fmt = self._parse_string()
    3702
    3703            return self.expression(
    3704                exp.StrToDate if to.this == exp.DataType.Type.DATE else exp.StrToTime,
    3705                this=this,
    3706                format=exp.Literal.string(
    3707                    format_time(
    3708                        fmt.this if fmt else "",
    3709                        self.FORMAT_MAPPING or self.TIME_MAPPING,
    3710                        self.FORMAT_TRIE or self.TIME_TRIE,
    3711                    )
    3712                ),
    3713            )
    3714
    3715        return self.expression(exp.Cast if strict else exp.TryCast, this=this, to=to)
    3716
    3717    def _parse_concat(self) -> t.Optional[exp.Expression]:
    3718        args = self._parse_csv(self._parse_conjunction)
    3719        if self.CONCAT_NULL_OUTPUTS_STRING:
    3720            args = [
    3721                exp.func("COALESCE", exp.cast(arg, "text"), exp.Literal.string(""))
    3722                for arg in args
    3723                if arg
    3724            ]
    3725
    3726        # Some dialects (e.g. Trino) don't allow a single-argument CONCAT call, so when
    3727        # we find such a call we replace it with its argument.
    3728        if len(args) == 1:
    3729            return args[0]
    3730
    3731        return self.expression(
    3732            exp.Concat if self.STRICT_STRING_CONCAT else exp.SafeConcat, expressions=args
    3733        )
    3734
    3735    def _parse_string_agg(self) -> exp.Expression:
    3736        if self._match(TokenType.DISTINCT):
    3737            args: t.List[t.Optional[exp.Expression]] = [
    3738                self.expression(exp.Distinct, expressions=[self._parse_conjunction()])
    3739            ]
    3740            if self._match(TokenType.COMMA):
    3741                args.extend(self._parse_csv(self._parse_conjunction))
    3742        else:
    3743            args = self._parse_csv(self._parse_conjunction)
    3744
    3745        index = self._index
    3746        if not self._match(TokenType.R_PAREN):
    3747            # postgres: STRING_AGG([DISTINCT] expression, separator [ORDER BY expression1 {ASC | DESC} [, ...]])
    3748            return self.expression(
    3749                exp.GroupConcat,
    3750                this=seq_get(args, 0),
    3751                separator=self._parse_order(this=seq_get(args, 1)),
    3752            )
    3753
    3754        # Checks if we can parse an order clause: WITHIN GROUP (ORDER BY <order_by_expression_list> [ASC | DESC]).
    3755        # This is done "manually", instead of letting _parse_window parse it into an exp.WithinGroup node, so that
    3756        # the STRING_AGG call is parsed like in MySQL / SQLite and can thus be transpiled more easily to them.
    3757        if not self._match_text_seq("WITHIN", "GROUP"):
    3758            self._retreat(index)
    3759            return self.validate_expression(exp.GroupConcat.from_arg_list(args), args)
    3760
    3761        self._match_l_paren()  # The corresponding match_r_paren will be called in parse_function (caller)
    3762        order = self._parse_order(this=seq_get(args, 0))
    3763        return self.expression(exp.GroupConcat, this=order, separator=seq_get(args, 1))
    3764
    3765    def _parse_convert(self, strict: bool) -> t.Optional[exp.Expression]:
    3766        this = self._parse_bitwise()
    3767
    3768        if self._match(TokenType.USING):
    3769            to: t.Optional[exp.Expression] = self.expression(
    3770                exp.CharacterSet, this=self._parse_var()
    3771            )
    3772        elif self._match(TokenType.COMMA):
    3773            to = self._parse_types()
    3774        else:
    3775            to = None
    3776
    3777        return self.expression(exp.Cast if strict else exp.TryCast, this=this, to=to)
    3778
    3779    def _parse_decode(self) -> t.Optional[exp.Decode | exp.Case]:
    3780        """
    3781        There are generally two variants of the DECODE function:
    3782
    3783        - DECODE(bin, charset)
    3784        - DECODE(expression, search, result [, search, result] ... [, default])
    3785
    3786        The second variant will always be parsed into a CASE expression. Note that NULL
    3787        needs special treatment, since we need to explicitly check for it with `IS NULL`,
    3788        instead of relying on pattern matching.
    3789        """
    3790        args = self._parse_csv(self._parse_conjunction)
    3791
    3792        if len(args) < 3:
    3793            return self.expression(exp.Decode, this=seq_get(args, 0), charset=seq_get(args, 1))
    3794
    3795        expression, *expressions = args
    3796        if not expression:
    3797            return None
    3798
    3799        ifs = []
    3800        for search, result in zip(expressions[::2], expressions[1::2]):
    3801            if not search or not result:
    3802                return None
    3803
    3804            if isinstance(search, exp.Literal):
    3805                ifs.append(
    3806                    exp.If(this=exp.EQ(this=expression.copy(), expression=search), true=result)
    3807                )
    3808            elif isinstance(search, exp.Null):
    3809                ifs.append(
    3810                    exp.If(this=exp.Is(this=expression.copy(), expression=exp.Null()), true=result)
    3811                )
    3812            else:
    3813                cond = exp.or_(
    3814                    exp.EQ(this=expression.copy(), expression=search),
    3815                    exp.and_(
    3816                        exp.Is(this=expression.copy(), expression=exp.Null()),
    3817                        exp.Is(this=search.copy(), expression=exp.Null()),
    3818                        copy=False,
    3819                    ),
    3820                    copy=False,
    3821                )
    3822                ifs.append(exp.If(this=cond, true=result))
    3823
    3824        return exp.Case(ifs=ifs, default=expressions[-1] if len(expressions) % 2 == 1 else None)
    3825
    3826    def _parse_json_key_value(self) -> t.Optional[exp.JSONKeyValue]:
    3827        self._match_text_seq("KEY")
    3828        key = self._parse_field()
    3829        self._match(TokenType.COLON)
    3830        self._match_text_seq("VALUE")
    3831        value = self._parse_field()
    3832
    3833        if not key and not value:
    3834            return None
    3835        return self.expression(exp.JSONKeyValue, this=key, expression=value)
    3836
    3837    def _parse_json_object(self) -> exp.JSONObject:
    3838        star = self._parse_star()
    3839        expressions = [star] if star else self._parse_csv(self._parse_json_key_value)
    3840
    3841        null_handling = None
    3842        if self._match_text_seq("NULL", "ON", "NULL"):
    3843            null_handling = "NULL ON NULL"
    3844        elif self._match_text_seq("ABSENT", "ON", "NULL"):
    3845            null_handling = "ABSENT ON NULL"
    3846
    3847        unique_keys = None
    3848        if self._match_text_seq("WITH", "UNIQUE"):
    3849            unique_keys = True
    3850        elif self._match_text_seq("WITHOUT", "UNIQUE"):
    3851            unique_keys = False
    3852
    3853        self._match_text_seq("KEYS")
    3854
    3855        return_type = self._match_text_seq("RETURNING") and self._parse_type()
    3856        format_json = self._match_text_seq("FORMAT", "JSON")
    3857        encoding = self._match_text_seq("ENCODING") and self._parse_var()
    3858
    3859        return self.expression(
    3860            exp.JSONObject,
    3861            expressions=expressions,
    3862            null_handling=null_handling,
    3863            unique_keys=unique_keys,
    3864            return_type=return_type,
    3865            format_json=format_json,
    3866            encoding=encoding,
    3867        )
    3868
    3869    def _parse_logarithm(self) -> exp.Func:
    3870        # Default argument order is base, expression
    3871        args = self._parse_csv(self._parse_range)
    3872
    3873        if len(args) > 1:
    3874            if not self.LOG_BASE_FIRST:
    3875                args.reverse()
    3876            return exp.Log.from_arg_list(args)
    3877
    3878        return self.expression(
    3879            exp.Ln if self.LOG_DEFAULTS_TO_LN else exp.Log, this=seq_get(args, 0)
    3880        )
    3881
    3882    def _parse_match_against(self) -> exp.MatchAgainst:
    3883        expressions = self._parse_csv(self._parse_column)
    3884
    3885        self._match_text_seq(")", "AGAINST", "(")
    3886
    3887        this = self._parse_string()
    3888
    3889        if self._match_text_seq("IN", "NATURAL", "LANGUAGE", "MODE"):
    3890            modifier = "IN NATURAL LANGUAGE MODE"
    3891            if self._match_text_seq("WITH", "QUERY", "EXPANSION"):
    3892                modifier = f"{modifier} WITH QUERY EXPANSION"
    3893        elif self._match_text_seq("IN", "BOOLEAN", "MODE"):
    3894            modifier = "IN BOOLEAN MODE"
    3895        elif self._match_text_seq("WITH", "QUERY", "EXPANSION"):
    3896            modifier = "WITH QUERY EXPANSION"
    3897        else:
    3898            modifier = None
    3899
    3900        return self.expression(
    3901            exp.MatchAgainst, this=this, expressions=expressions, modifier=modifier
    3902        )
    3903
    3904    # https://learn.microsoft.com/en-us/sql/t-sql/functions/openjson-transact-sql?view=sql-server-ver16
    3905    def _parse_open_json(self) -> exp.OpenJSON:
    3906        this = self._parse_bitwise()
    3907        path = self._match(TokenType.COMMA) and self._parse_string()
    3908
    3909        def _parse_open_json_column_def() -> exp.OpenJSONColumnDef:
    3910            this = self._parse_field(any_token=True)
    3911            kind = self._parse_types()
    3912            path = self._parse_string()
    3913            as_json = self._match_pair(TokenType.ALIAS, TokenType.JSON)
    3914
    3915            return self.expression(
    3916                exp.OpenJSONColumnDef, this=this, kind=kind, path=path, as_json=as_json
    3917            )
    3918
    3919        expressions = None
    3920        if self._match_pair(TokenType.R_PAREN, TokenType.WITH):
    3921            self._match_l_paren()
    3922            expressions = self._parse_csv(_parse_open_json_column_def)
    3923
    3924        return self.expression(exp.OpenJSON, this=this, path=path, expressions=expressions)
    3925
    3926    def _parse_position(self, haystack_first: bool = False) -> exp.StrPosition:
    3927        args = self._parse_csv(self._parse_bitwise)
    3928
    3929        if self._match(TokenType.IN):
    3930            return self.expression(
    3931                exp.StrPosition, this=self._parse_bitwise(), substr=seq_get(args, 0)
    3932            )
    3933
    3934        if haystack_first:
    3935            haystack = seq_get(args, 0)
    3936            needle = seq_get(args, 1)
    3937        else:
    3938            needle = seq_get(args, 0)
    3939            haystack = seq_get(args, 1)
    3940
    3941        return self.expression(
    3942            exp.StrPosition, this=haystack, substr=needle, position=seq_get(args, 2)
    3943        )
    3944
    3945    def _parse_join_hint(self, func_name: str) -> exp.JoinHint:
    3946        args = self._parse_csv(self._parse_table)
    3947        return exp.JoinHint(this=func_name.upper(), expressions=args)
    3948
    3949    def _parse_substring(self) -> exp.Substring:
    3950        # Postgres supports the form: substring(string [from int] [for int])
    3951        # https://www.postgresql.org/docs/9.1/functions-string.html @ Table 9-6
    3952
    3953        args = self._parse_csv(self._parse_bitwise)
    3954
    3955        if self._match(TokenType.FROM):
    3956            args.append(self._parse_bitwise())
    3957            if self._match(TokenType.FOR):
    3958                args.append(self._parse_bitwise())
    3959
    3960        return self.validate_expression(exp.Substring.from_arg_list(args), args)
    3961
    3962    def _parse_trim(self) -> exp.Trim:
    3963        # https://www.w3resource.com/sql/character-functions/trim.php
    3964        # https://docs.oracle.com/javadb/10.8.3.0/ref/rreftrimfunc.html
    3965
    3966        position = None
    3967        collation = None
    3968
    3969        if self._match_texts(self.TRIM_TYPES):
    3970            position = self._prev.text.upper()
    3971
    3972        expression = self._parse_bitwise()
    3973        if self._match_set((TokenType.FROM, TokenType.COMMA)):
    3974            this = self._parse_bitwise()
    3975        else:
    3976            this = expression
    3977            expression = None
    3978
    3979        if self._match(TokenType.COLLATE):
    3980            collation = self._parse_bitwise()
    3981
    3982        return self.expression(
    3983            exp.Trim, this=this, position=position, expression=expression, collation=collation
    3984        )
    3985
    3986    def _parse_window_clause(self) -> t.Optional[t.List[t.Optional[exp.Expression]]]:
    3987        return self._match(TokenType.WINDOW) and self._parse_csv(self._parse_named_window)
    3988
    3989    def _parse_named_window(self) -> t.Optional[exp.Expression]:
    3990        return self._parse_window(self._parse_id_var(), alias=True)
    3991
    3992    def _parse_respect_or_ignore_nulls(
    3993        self, this: t.Optional[exp.Expression]
    3994    ) -> t.Optional[exp.Expression]:
    3995        if self._match_text_seq("IGNORE", "NULLS"):
    3996            return self.expression(exp.IgnoreNulls, this=this)
    3997        if self._match_text_seq("RESPECT", "NULLS"):
    3998            return self.expression(exp.RespectNulls, this=this)
    3999        return this
    4000
    4001    def _parse_window(
    4002        self, this: t.Optional[exp.Expression], alias: bool = False
    4003    ) -> t.Optional[exp.Expression]:
    4004        if self._match_pair(TokenType.FILTER, TokenType.L_PAREN):
    4005            this = self.expression(exp.Filter, this=this, expression=self._parse_where())
    4006            self._match_r_paren()
    4007
    4008        # T-SQL allows the OVER (...) syntax after WITHIN GROUP.
    4009        # https://learn.microsoft.com/en-us/sql/t-sql/functions/percentile-disc-transact-sql?view=sql-server-ver16
    4010        if self._match_text_seq("WITHIN", "GROUP"):
    4011            order = self._parse_wrapped(self._parse_order)
    4012            this = self.expression(exp.WithinGroup, this=this, expression=order)
    4013
    4014        # SQL spec defines an optional [ { IGNORE | RESPECT } NULLS ] OVER
    4015        # Some dialects choose to implement and some do not.
    4016        # https://dev.mysql.com/doc/refman/8.0/en/window-function-descriptions.html
    4017
    4018        # There is some code above in _parse_lambda that handles
    4019        #   SELECT FIRST_VALUE(TABLE.COLUMN IGNORE|RESPECT NULLS) OVER ...
    4020
    4021        # The below changes handle
    4022        #   SELECT FIRST_VALUE(TABLE.COLUMN) IGNORE|RESPECT NULLS OVER ...
    4023
    4024        # Oracle allows both formats
    4025        #   (https://docs.oracle.com/en/database/oracle/oracle-database/19/sqlrf/img_text/first_value.html)
    4026        #   and Snowflake chose to do the same for familiarity
    4027        #   https://docs.snowflake.com/en/sql-reference/functions/first_value.html#usage-notes
    4028        this = self._parse_respect_or_ignore_nulls(this)
    4029
    4030        # bigquery select from window x AS (partition by ...)
    4031        if alias:
    4032            over = None
    4033            self._match(TokenType.ALIAS)
    4034        elif not self._match_set(self.WINDOW_BEFORE_PAREN_TOKENS):
    4035            return this
    4036        else:
    4037            over = self._prev.text.upper()
    4038
    4039        if not self._match(TokenType.L_PAREN):
    4040            return self.expression(
    4041                exp.Window, this=this, alias=self._parse_id_var(False), over=over
    4042            )
    4043
    4044        window_alias = self._parse_id_var(any_token=False, tokens=self.WINDOW_ALIAS_TOKENS)
    4045
    4046        first = self._match(TokenType.FIRST)
    4047        if self._match_text_seq("LAST"):
    4048            first = False
    4049
    4050        partition = self._parse_partition_by()
    4051        order = self._parse_order()
    4052        kind = self._match_set((TokenType.ROWS, TokenType.RANGE)) and self._prev.text
    4053
    4054        if kind:
    4055            self._match(TokenType.BETWEEN)
    4056            start = self._parse_window_spec()
    4057            self._match(TokenType.AND)
    4058            end = self._parse_window_spec()
    4059
    4060            spec = self.expression(
    4061                exp.WindowSpec,
    4062                kind=kind,
    4063                start=start["value"],
    4064                start_side=start["side"],
    4065                end=end["value"],
    4066                end_side=end["side"],
    4067            )
    4068        else:
    4069            spec = None
    4070
    4071        self._match_r_paren()
    4072
    4073        return self.expression(
    4074            exp.Window,
    4075            this=this,
    4076            partition_by=partition,
    4077            order=order,
    4078            spec=spec,
    4079            alias=window_alias,
    4080            over=over,
    4081            first=first,
    4082        )
    4083
    4084    def _parse_window_spec(self) -> t.Dict[str, t.Optional[str | exp.Expression]]:
    4085        self._match(TokenType.BETWEEN)
    4086
    4087        return {
    4088            "value": (
    4089                (self._match_text_seq("UNBOUNDED") and "UNBOUNDED")
    4090                or (self._match_text_seq("CURRENT", "ROW") and "CURRENT ROW")
    4091                or self._parse_bitwise()
    4092            ),
    4093            "side": self._match_texts(self.WINDOW_SIDES) and self._prev.text,
    4094        }
    4095
    4096    def _parse_alias(
    4097        self, this: t.Optional[exp.Expression], explicit: bool = False
    4098    ) -> t.Optional[exp.Expression]:
    4099        any_token = self._match(TokenType.ALIAS)
    4100
    4101        if explicit and not any_token:
    4102            return this
    4103
    4104        if self._match(TokenType.L_PAREN):
    4105            aliases = self.expression(
    4106                exp.Aliases,
    4107                this=this,
    4108                expressions=self._parse_csv(lambda: self._parse_id_var(any_token)),
    4109            )
    4110            self._match_r_paren(aliases)
    4111            return aliases
    4112
    4113        alias = self._parse_id_var(any_token)
    4114
    4115        if alias:
    4116            return self.expression(exp.Alias, this=this, alias=alias)
    4117
    4118        return this
    4119
    4120    def _parse_id_var(
    4121        self,
    4122        any_token: bool = True,
    4123        tokens: t.Optional[t.Collection[TokenType]] = None,
    4124    ) -> t.Optional[exp.Expression]:
    4125        identifier = self._parse_identifier()
    4126
    4127        if identifier:
    4128            return identifier
    4129
    4130        if (any_token and self._advance_any()) or self._match_set(tokens or self.ID_VAR_TOKENS):
    4131            quoted = self._prev.token_type == TokenType.STRING
    4132            return exp.Identifier(this=self._prev.text, quoted=quoted)
    4133
    4134        return None
    4135
    4136    def _parse_string(self) -> t.Optional[exp.Expression]:
    4137        if self._match(TokenType.STRING):
    4138            return self.PRIMARY_PARSERS[TokenType.STRING](self, self._prev)
    4139        return self._parse_placeholder()
    4140
    4141    def _parse_string_as_identifier(self) -> t.Optional[exp.Identifier]:
    4142        return exp.to_identifier(self._match(TokenType.STRING) and self._prev.text, quoted=True)
    4143
    4144    def _parse_number(self) -> t.Optional[exp.Expression]:
    4145        if self._match(TokenType.NUMBER):
    4146            return self.PRIMARY_PARSERS[TokenType.NUMBER](self, self._prev)
    4147        return self._parse_placeholder()
    4148
    4149    def _parse_identifier(self) -> t.Optional[exp.Expression]:
    4150        if self._match(TokenType.IDENTIFIER):
    4151            return self.expression(exp.Identifier, this=self._prev.text, quoted=True)
    4152        return self._parse_placeholder()
    4153
    4154    def _parse_var(
    4155        self, any_token: bool = False, tokens: t.Optional[t.Collection[TokenType]] = None
    4156    ) -> t.Optional[exp.Expression]:
    4157        if (
    4158            (any_token and self._advance_any())
    4159            or self._match(TokenType.VAR)
    4160            or (self._match_set(tokens) if tokens else False)
    4161        ):
    4162            return self.expression(exp.Var, this=self._prev.text)
    4163        return self._parse_placeholder()
    4164
    4165    def _advance_any(self) -> t.Optional[Token]:
    4166        if self._curr and self._curr.token_type not in self.RESERVED_KEYWORDS:
    4167            self._advance()
    4168            return self._prev
    4169        return None
    4170
    4171    def _parse_var_or_string(self) -> t.Optional[exp.Expression]:
    4172        return self._parse_var() or self._parse_string()
    4173
    4174    def _parse_null(self) -> t.Optional[exp.Expression]:
    4175        if self._match(TokenType.NULL):
    4176            return self.PRIMARY_PARSERS[TokenType.NULL](self, self._prev)
    4177        return None
    4178
    4179    def _parse_boolean(self) -> t.Optional[exp.Expression]:
    4180        if self._match(TokenType.TRUE):
    4181            return self.PRIMARY_PARSERS[TokenType.TRUE](self, self._prev)
    4182        if self._match(TokenType.FALSE):
    4183            return self.PRIMARY_PARSERS[TokenType.FALSE](self, self._prev)
    4184        return None
    4185
    4186    def _parse_star(self) -> t.Optional[exp.Expression]:
    4187        if self._match(TokenType.STAR):
    4188            return self.PRIMARY_PARSERS[TokenType.STAR](self, self._prev)
    4189        return None
    4190
    4191    def _parse_parameter(self) -> exp.Parameter:
    4192        wrapped = self._match(TokenType.L_BRACE)
    4193        this = self._parse_var() or self._parse_identifier() or self._parse_primary()
    4194        self._match(TokenType.R_BRACE)
    4195        return self.expression(exp.Parameter, this=this, wrapped=wrapped)
    4196
    4197    def _parse_placeholder(self) -> t.Optional[exp.Expression]:
    4198        if self._match_set(self.PLACEHOLDER_PARSERS):
    4199            placeholder = self.PLACEHOLDER_PARSERS[self._prev.token_type](self)
    4200            if placeholder:
    4201                return placeholder
    4202            self._advance(-1)
    4203        return None
    4204
    4205    def _parse_except(self) -> t.Optional[t.List[t.Optional[exp.Expression]]]:
    4206        if not self._match(TokenType.EXCEPT):
    4207            return None
    4208        if self._match(TokenType.L_PAREN, advance=False):
    4209            return self._parse_wrapped_csv(self._parse_column)
    4210        return self._parse_csv(self._parse_column)
    4211
    4212    def _parse_replace(self) -> t.Optional[t.List[t.Optional[exp.Expression]]]:
    4213        if not self._match(TokenType.REPLACE):
    4214            return None
    4215        if self._match(TokenType.L_PAREN, advance=False):
    4216            return self._parse_wrapped_csv(self._parse_expression)
    4217        return self._parse_csv(self._parse_expression)
    4218
    4219    def _parse_csv(
    4220        self, parse_method: t.Callable, sep: TokenType = TokenType.COMMA
    4221    ) -> t.List[t.Optional[exp.Expression]]:
    4222        parse_result = parse_method()
    4223        items = [parse_result] if parse_result is not None else []
    4224
    4225        while self._match(sep):
    4226            self._add_comments(parse_result)
    4227            parse_result = parse_method()
    4228            if parse_result is not None:
    4229                items.append(parse_result)
    4230
    4231        return items
    4232
    4233    def _parse_tokens(
    4234        self, parse_method: t.Callable, expressions: t.Dict
    4235    ) -> t.Optional[exp.Expression]:
    4236        this = parse_method()
    4237
    4238        while self._match_set(expressions):
    4239            this = self.expression(
    4240                expressions[self._prev.token_type],
    4241                this=this,
    4242                comments=self._prev_comments,
    4243                expression=parse_method(),
    4244            )
    4245
    4246        return this
    4247
    4248    def _parse_wrapped_id_vars(self, optional: bool = False) -> t.List[t.Optional[exp.Expression]]:
    4249        return self._parse_wrapped_csv(self._parse_id_var, optional=optional)
    4250
    4251    def _parse_wrapped_csv(
    4252        self, parse_method: t.Callable, sep: TokenType = TokenType.COMMA, optional: bool = False
    4253    ) -> t.List[t.Optional[exp.Expression]]:
    4254        return self._parse_wrapped(
    4255            lambda: self._parse_csv(parse_method, sep=sep), optional=optional
    4256        )
    4257
    4258    def _parse_wrapped(self, parse_method: t.Callable, optional: bool = False) -> t.Any:
    4259        wrapped = self._match(TokenType.L_PAREN)
    4260        if not wrapped and not optional:
    4261            self.raise_error("Expecting (")
    4262        parse_result = parse_method()
    4263        if wrapped:
    4264            self._match_r_paren()
    4265        return parse_result
    4266
    4267    def _parse_select_or_expression(self, alias: bool = False) -> t.Optional[exp.Expression]:
    4268        return self._parse_select() or self._parse_set_operations(
    4269            self._parse_expression() if alias else self._parse_conjunction()
    4270        )
    4271
    4272    def _parse_ddl_select(self) -> t.Optional[exp.Expression]:
    4273        return self._parse_query_modifiers(
    4274            self._parse_set_operations(self._parse_select(nested=True, parse_subquery_alias=False))
    4275        )
    4276
    4277    def _parse_transaction(self) -> exp.Transaction:
    4278        this = None
    4279        if self._match_texts(self.TRANSACTION_KIND):
    4280            this = self._prev.text
    4281
    4282        self._match_texts({"TRANSACTION", "WORK"})
    4283
    4284        modes = []
    4285        while True:
    4286            mode = []
    4287            while self._match(TokenType.VAR):
    4288                mode.append(self._prev.text)
    4289
    4290            if mode:
    4291                modes.append(" ".join(mode))
    4292            if not self._match(TokenType.COMMA):
    4293                break
    4294
    4295        return self.expression(exp.Transaction, this=this, modes=modes)
    4296
    4297    def _parse_commit_or_rollback(self) -> exp.Commit | exp.Rollback:
    4298        chain = None
    4299        savepoint = None
    4300        is_rollback = self._prev.token_type == TokenType.ROLLBACK
    4301
    4302        self._match_texts({"TRANSACTION", "WORK"})
    4303
    4304        if self._match_text_seq("TO"):
    4305            self._match_text_seq("SAVEPOINT")
    4306            savepoint = self._parse_id_var()
    4307
    4308        if self._match(TokenType.AND):
    4309            chain = not self._match_text_seq("NO")
    4310            self._match_text_seq("CHAIN")
    4311
    4312        if is_rollback:
    4313            return self.expression(exp.Rollback, savepoint=savepoint)
    4314
    4315        return self.expression(exp.Commit, chain=chain)
    4316
    4317    def _parse_add_column(self) -> t.Optional[exp.Expression]:
    4318        if not self._match_text_seq("ADD"):
    4319            return None
    4320
    4321        self._match(TokenType.COLUMN)
    4322        exists_column = self._parse_exists(not_=True)
    4323        expression = self._parse_column_def(self._parse_field(any_token=True))
    4324
    4325        if expression:
    4326            expression.set("exists", exists_column)
    4327
    4328            # https://docs.databricks.com/delta/update-schema.html#explicitly-update-schema-to-add-columns
    4329            if self._match_texts(("FIRST", "AFTER")):
    4330                position = self._prev.text
    4331                column_position = self.expression(
    4332                    exp.ColumnPosition, this=self._parse_column(), position=position
    4333                )
    4334                expression.set("position", column_position)
    4335
    4336        return expression
    4337
    4338    def _parse_drop_column(self) -> t.Optional[exp.Drop | exp.Command]:
    4339        drop = self._match(TokenType.DROP) and self._parse_drop()
    4340        if drop and not isinstance(drop, exp.Command):
    4341            drop.set("kind", drop.args.get("kind", "COLUMN"))
    4342        return drop
    4343
    4344    # https://docs.aws.amazon.com/athena/latest/ug/alter-table-drop-partition.html
    4345    def _parse_drop_partition(self, exists: t.Optional[bool] = None) -> exp.DropPartition:
    4346        return self.expression(
    4347            exp.DropPartition, expressions=self._parse_csv(self._parse_partition), exists=exists
    4348        )
    4349
    4350    def _parse_add_constraint(self) -> exp.AddConstraint:
    4351        this = None
    4352        kind = self._prev.token_type
    4353
    4354        if kind == TokenType.CONSTRAINT:
    4355            this = self._parse_id_var()
    4356
    4357            if self._match_text_seq("CHECK"):
    4358                expression = self._parse_wrapped(self._parse_conjunction)
    4359                enforced = self._match_text_seq("ENFORCED")
    4360
    4361                return self.expression(
    4362                    exp.AddConstraint, this=this, expression=expression, enforced=enforced
    4363                )
    4364
    4365        if kind == TokenType.FOREIGN_KEY or self._match(TokenType.FOREIGN_KEY):
    4366            expression = self._parse_foreign_key()
    4367        elif kind == TokenType.PRIMARY_KEY or self._match(TokenType.PRIMARY_KEY):
    4368            expression = self._parse_primary_key()
    4369        else:
    4370            expression = None
    4371
    4372        return self.expression(exp.AddConstraint, this=this, expression=expression)
    4373
    4374    def _parse_alter_table_add(self) -> t.List[t.Optional[exp.Expression]]:
    4375        index = self._index - 1
    4376
    4377        if self._match_set(self.ADD_CONSTRAINT_TOKENS):
    4378            return self._parse_csv(self._parse_add_constraint)
    4379
    4380        self._retreat(index)
    4381        return self._parse_csv(self._parse_add_column)
    4382
    4383    def _parse_alter_table_alter(self) -> exp.AlterColumn:
    4384        self._match(TokenType.COLUMN)
    4385        column = self._parse_field(any_token=True)
    4386
    4387        if self._match_pair(TokenType.DROP, TokenType.DEFAULT):
    4388            return self.expression(exp.AlterColumn, this=column, drop=True)
    4389        if self._match_pair(TokenType.SET, TokenType.DEFAULT):
    4390            return self.expression(exp.AlterColumn, this=column, default=self._parse_conjunction())
    4391
    4392        self._match_text_seq("SET", "DATA")
    4393        return self.expression(
    4394            exp.AlterColumn,
    4395            this=column,
    4396            dtype=self._match_text_seq("TYPE") and self._parse_types(),
    4397            collate=self._match(TokenType.COLLATE) and self._parse_term(),
    4398            using=self._match(TokenType.USING) and self._parse_conjunction(),
    4399        )
    4400
    4401    def _parse_alter_table_drop(self) -> t.List[t.Optional[exp.Expression]]:
    4402        index = self._index - 1
    4403
    4404        partition_exists = self._parse_exists()
    4405        if self._match(TokenType.PARTITION, advance=False):
    4406            return self._parse_csv(lambda: self._parse_drop_partition(exists=partition_exists))
    4407
    4408        self._retreat(index)
    4409        return self._parse_csv(self._parse_drop_column)
    4410
    4411    def _parse_alter_table_rename(self) -> exp.RenameTable:
    4412        self._match_text_seq("TO")
    4413        return self.expression(exp.RenameTable, this=self._parse_table(schema=True))
    4414
    4415    def _parse_alter(self) -> exp.AlterTable | exp.Command:
    4416        start = self._prev
    4417
    4418        if not self._match(TokenType.TABLE):
    4419            return self._parse_as_command(start)
    4420
    4421        exists = self._parse_exists()
    4422        this = self._parse_table(schema=True)
    4423
    4424        if self._next:
    4425            self._advance()
    4426
    4427        parser = self.ALTER_PARSERS.get(self._prev.text.upper()) if self._prev else None
    4428        if parser:
    4429            actions = ensure_list(parser(self))
    4430
    4431            if not self._curr:
    4432                return self.expression(
    4433                    exp.AlterTable,
    4434                    this=this,
    4435                    exists=exists,
    4436                    actions=actions,
    4437                )
    4438        return self._parse_as_command(start)
    4439
    4440    def _parse_merge(self) -> exp.Merge:
    4441        self._match(TokenType.INTO)
    4442        target = self._parse_table()
    4443
    4444        self._match(TokenType.USING)
    4445        using = self._parse_table()
    4446
    4447        self._match(TokenType.ON)
    4448        on = self._parse_conjunction()
    4449
    4450        whens = []
    4451        while self._match(TokenType.WHEN):
    4452            matched = not self._match(TokenType.NOT)
    4453            self._match_text_seq("MATCHED")
    4454            source = (
    4455                False
    4456                if self._match_text_seq("BY", "TARGET")
    4457                else self._match_text_seq("BY", "SOURCE")
    4458            )
    4459            condition = self._parse_conjunction() if self._match(TokenType.AND) else None
    4460
    4461            self._match(TokenType.THEN)
    4462
    4463            if self._match(TokenType.INSERT):
    4464                _this = self._parse_star()
    4465                if _this:
    4466                    then: t.Optional[exp.Expression] = self.expression(exp.Insert, this=_this)
    4467                else:
    4468                    then = self.expression(
    4469                        exp.Insert,
    4470                        this=self._parse_value(),
    4471                        expression=self._match(TokenType.VALUES) and self._parse_value(),
    4472                    )
    4473            elif self._match(TokenType.UPDATE):
    4474                expressions = self._parse_star()
    4475                if expressions:
    4476                    then = self.expression(exp.Update, expressions=expressions)
    4477                else:
    4478                    then = self.expression(
    4479                        exp.Update,
    4480                        expressions=self._match(TokenType.SET)
    4481                        and self._parse_csv(self._parse_equality),
    4482                    )
    4483            elif self._match(TokenType.DELETE):
    4484                then = self.expression(exp.Var, this=self._prev.text)
    4485            else:
    4486                then = None
    4487
    4488            whens.append(
    4489                self.expression(
    4490                    exp.When,
    4491                    matched=matched,
    4492                    source=source,
    4493                    condition=condition,
    4494                    then=then,
    4495                )
    4496            )
    4497
    4498        return self.expression(
    4499            exp.Merge,
    4500            this=target,
    4501            using=using,
    4502            on=on,
    4503            expressions=whens,
    4504        )
    4505
    4506    def _parse_show(self) -> t.Optional[exp.Expression]:
    4507        parser = self._find_parser(self.SHOW_PARSERS, self.SHOW_TRIE)
    4508        if parser:
    4509            return parser(self)
    4510        self._advance()
    4511        return self.expression(exp.Show, this=self._prev.text.upper())
    4512
    4513    def _parse_set_item_assignment(
    4514        self, kind: t.Optional[str] = None
    4515    ) -> t.Optional[exp.Expression]:
    4516        index = self._index
    4517
    4518        if kind in {"GLOBAL", "SESSION"} and self._match_text_seq("TRANSACTION"):
    4519            return self._parse_set_transaction(global_=kind == "GLOBAL")
    4520
    4521        left = self._parse_primary() or self._parse_id_var()
    4522
    4523        if not self._match_texts(("=", "TO")):
    4524            self._retreat(index)
    4525            return None
    4526
    4527        right = self._parse_statement() or self._parse_id_var()
    4528        this = self.expression(exp.EQ, this=left, expression=right)
    4529
    4530        return self.expression(exp.SetItem, this=this, kind=kind)
    4531
    4532    def _parse_set_transaction(self, global_: bool = False) -> exp.Expression:
    4533        self._match_text_seq("TRANSACTION")
    4534        characteristics = self._parse_csv(
    4535            lambda: self._parse_var_from_options(self.TRANSACTION_CHARACTERISTICS)
    4536        )
    4537        return self.expression(
    4538            exp.SetItem,
    4539            expressions=characteristics,
    4540            kind="TRANSACTION",
    4541            **{"global": global_},  # type: ignore
    4542        )
    4543
    4544    def _parse_set_item(self) -> t.Optional[exp.Expression]:
    4545        parser = self._find_parser(self.SET_PARSERS, self.SET_TRIE)
    4546        return parser(self) if parser else self._parse_set_item_assignment(kind=None)
    4547
    4548    def _parse_set(self, unset: bool = False, tag: bool = False) -> exp.Set | exp.Command:
    4549        index = self._index
    4550        set_ = self.expression(
    4551            exp.Set, expressions=self._parse_csv(self._parse_set_item), unset=unset, tag=tag
    4552        )
    4553
    4554        if self._curr:
    4555            self._retreat(index)
    4556            return self._parse_as_command(self._prev)
    4557
    4558        return set_
    4559
    4560    def _parse_var_from_options(self, options: t.Collection[str]) -> t.Optional[exp.Var]:
    4561        for option in options:
    4562            if self._match_text_seq(*option.split(" ")):
    4563                return exp.var(option)
    4564        return None
    4565
    4566    def _parse_as_command(self, start: Token) -> exp.Command:
    4567        while self._curr:
    4568            self._advance()
    4569        text = self._find_sql(start, self._prev)
    4570        size = len(start.text)
    4571        return exp.Command(this=text[:size], expression=text[size:])
    4572
    4573    def _parse_dict_property(self, this: str) -> exp.DictProperty:
    4574        settings = []
    4575
    4576        self._match_l_paren()
    4577        kind = self._parse_id_var()
    4578
    4579        if self._match(TokenType.L_PAREN):
    4580            while True:
    4581                key = self._parse_id_var()
    4582                value = self._parse_primary()
    4583
    4584                if not key and value is None:
    4585                    break
    4586                settings.append(self.expression(exp.DictSubProperty, this=key, value=value))
    4587            self._match(TokenType.R_PAREN)
    4588
    4589        self._match_r_paren()
    4590
    4591        return self.expression(
    4592            exp.DictProperty,
    4593            this=this,
    4594            kind=kind.this if kind else None,
    4595            settings=settings,
    4596        )
    4597
    4598    def _parse_dict_range(self, this: str) -> exp.DictRange:
    4599        self._match_l_paren()
    4600        has_min = self._match_text_seq("MIN")
    4601        if has_min:
    4602            min = self._parse_var() or self._parse_primary()
    4603            self._match_text_seq("MAX")
    4604            max = self._parse_var() or self._parse_primary()
    4605        else:
    4606            max = self._parse_var() or self._parse_primary()
    4607            min = exp.Literal.number(0)
    4608        self._match_r_paren()
    4609        return self.expression(exp.DictRange, this=this, min=min, max=max)
    4610
    4611    def _find_parser(
    4612        self, parsers: t.Dict[str, t.Callable], trie: t.Dict
    4613    ) -> t.Optional[t.Callable]:
    4614        if not self._curr:
    4615            return None
    4616
    4617        index = self._index
    4618        this = []
    4619        while True:
    4620            # The current token might be multiple words
    4621            curr = self._curr.text.upper()
    4622            key = curr.split(" ")
    4623            this.append(curr)
    4624
    4625            self._advance()
    4626            result, trie = in_trie(trie, key)
    4627            if result == TrieResult.FAILED:
    4628                break
    4629
    4630            if result == TrieResult.EXISTS:
    4631                subparser = parsers[" ".join(this)]
    4632                return subparser
    4633
    4634        self._retreat(index)
    4635        return None
    4636
    4637    def _match(self, token_type, advance=True, expression=None):
    4638        if not self._curr:
    4639            return None
    4640
    4641        if self._curr.token_type == token_type:
    4642            if advance:
    4643                self._advance()
    4644            self._add_comments(expression)
    4645            return True
    4646
    4647        return None
    4648
    4649    def _match_set(self, types, advance=True):
    4650        if not self._curr:
    4651            return None
    4652
    4653        if self._curr.token_type in types:
    4654            if advance:
    4655                self._advance()
    4656            return True
    4657
    4658        return None
    4659
    4660    def _match_pair(self, token_type_a, token_type_b, advance=True):
    4661        if not self._curr or not self._next:
    4662            return None
    4663
    4664        if self._curr.token_type == token_type_a and self._next.token_type == token_type_b:
    4665            if advance:
    4666                self._advance(2)
    4667            return True
    4668
    4669        return None
    4670
    4671    def _match_l_paren(self, expression: t.Optional[exp.Expression] = None) -> None:
    4672        if not self._match(TokenType.L_PAREN, expression=expression):
    4673            self.raise_error("Expecting (")
    4674
    4675    def _match_r_paren(self, expression: t.Optional[exp.Expression] = None) -> None:
    4676        if not self._match(TokenType.R_PAREN, expression=expression):
    4677            self.raise_error("Expecting )")
    4678
    4679    def _match_texts(self, texts, advance=True):
    4680        if self._curr and self._curr.text.upper() in texts:
    4681            if advance:
    4682                self._advance()
    4683            return True
    4684        return False
    4685
    4686    def _match_text_seq(self, *texts, advance=True):
    4687        index = self._index
    4688        for text in texts:
    4689            if self._curr and self._curr.text.upper() == text:
    4690                self._advance()
    4691            else:
    4692                self._retreat(index)
    4693                return False
    4694
    4695        if not advance:
    4696            self._retreat(index)
    4697
    4698        return True
    4699
    4700    @t.overload
    4701    def _replace_columns_with_dots(self, this: exp.Expression) -> exp.Expression:
    4702        ...
    4703
    4704    @t.overload
    4705    def _replace_columns_with_dots(
    4706        self, this: t.Optional[exp.Expression]
    4707    ) -> t.Optional[exp.Expression]:
    4708        ...
    4709
    4710    def _replace_columns_with_dots(self, this):
    4711        if isinstance(this, exp.Dot):
    4712            exp.replace_children(this, self._replace_columns_with_dots)
    4713        elif isinstance(this, exp.Column):
    4714            exp.replace_children(this, self._replace_columns_with_dots)
    4715            table = this.args.get("table")
    4716            this = (
    4717                self.expression(exp.Dot, this=table, expression=this.this)
    4718                if table
    4719                else self.expression(exp.Var, this=this.name)
    4720            )
    4721        elif isinstance(this, exp.Identifier):
    4722            this = self.expression(exp.Var, this=this.name)
    4723
    4724        return this
    4725
    4726    def _replace_lambda(
    4727        self, node: t.Optional[exp.Expression], lambda_variables: t.Set[str]
    4728    ) -> t.Optional[exp.Expression]:
    4729        if not node:
    4730            return node
    4731
    4732        for column in node.find_all(exp.Column):
    4733            if column.parts[0].name in lambda_variables:
    4734                dot_or_id = column.to_dot() if column.table else column.this
    4735                parent = column.parent
    4736
    4737                while isinstance(parent, exp.Dot):
    4738                    if not isinstance(parent.parent, exp.Dot):
    4739                        parent.replace(dot_or_id)
    4740                        break
    4741                    parent = parent.parent
    4742                else:
    4743                    if column is node:
    4744                        node = dot_or_id
    4745                    else:
    4746                        column.replace(dot_or_id)
    4747        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) View Source

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

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'>>, 'MAP_FROM_ENTRIES': <bound method Func.from_arg_list of <class 'sqlglot.expressions.MapFromEntries'>>, '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.LONGBLOB: 'LONGBLOB'>, <TokenType.TIMESTAMP: 'TIMESTAMP'>, <TokenType.TIMESTAMPLTZ: 'TIMESTAMPLTZ'>, <TokenType.TEXT: 'TEXT'>, <TokenType.NCHAR: 'NCHAR'>, <TokenType.MEDIUMTEXT: 'MEDIUMTEXT'>, <TokenType.UNIQUEIDENTIFIER: 'UNIQUEIDENTIFIER'>, <TokenType.BIT: 'BIT'>, <TokenType.TIMESTAMPTZ: 'TIMESTAMPTZ'>, <TokenType.MONEY: 'MONEY'>, <TokenType.SMALLINT: 'SMALLINT'>, <TokenType.HLLSKETCH: 'HLLSKETCH'>, <TokenType.VARBINARY: 'VARBINARY'>, <TokenType.INT4RANGE: 'INT4RANGE'>, <TokenType.SMALLSERIAL: 'SMALLSERIAL'>, <TokenType.NULLABLE: 'NULLABLE'>, <TokenType.VARCHAR: 'VARCHAR'>, <TokenType.UBIGINT: 'UBIGINT'>, <TokenType.GEOGRAPHY: 'GEOGRAPHY'>, <TokenType.DOUBLE: 'DOUBLE'>, <TokenType.XML: 'XML'>, <TokenType.USERDEFINED: 'USERDEFINED'>, <TokenType.IMAGE: 'IMAGE'>, <TokenType.FLOAT: 'FLOAT'>, <TokenType.TSRANGE: 'TSRANGE'>, <TokenType.MEDIUMBLOB: 'MEDIUMBLOB'>, <TokenType.UUID: 'UUID'>, <TokenType.DATE: 'DATE'>, <TokenType.HSTORE: 'HSTORE'>, <TokenType.SMALLMONEY: 'SMALLMONEY'>, <TokenType.DATERANGE: 'DATERANGE'>, <TokenType.INT8RANGE: 'INT8RANGE'>, <TokenType.SERIAL: 'SERIAL'>, <TokenType.NVARCHAR: 'NVARCHAR'>, <TokenType.BIGDECIMAL: 'BIGDECIMAL'>, <TokenType.TSTZMULTIRANGE: 'TSTZMULTIRANGE'>, <TokenType.UTINYINT: 'UTINYINT'>, <TokenType.TINYINT: 'TINYINT'>, <TokenType.JSONB: 'JSONB'>, <TokenType.NUMRANGE: 'NUMRANGE'>, <TokenType.VARIANT: 'VARIANT'>, <TokenType.INET: 'INET'>, <TokenType.TSMULTIRANGE: 'TSMULTIRANGE'>, <TokenType.ROWVERSION: 'ROWVERSION'>, <TokenType.CHAR: 'CHAR'>, <TokenType.JSON: 'JSON'>, <TokenType.SUPER: 'SUPER'>, <TokenType.BIGINT: 'BIGINT'>, <TokenType.INT128: 'INT128'>, <TokenType.INTERVAL: 'INTERVAL'>, <TokenType.NUMMULTIRANGE: 'NUMMULTIRANGE'>, <TokenType.ENUM: 'ENUM'>, <TokenType.INT: 'INT'>, <TokenType.LONGTEXT: 'LONGTEXT'>, <TokenType.INT256: 'INT256'>, <TokenType.DATEMULTIRANGE: 'DATEMULTIRANGE'>, <TokenType.PSEUDO_TYPE: 'PSEUDO_TYPE'>, <TokenType.UINT256: 'UINT256'>, <TokenType.UINT: 'UINT'>, <TokenType.USMALLINT: 'USMALLINT'>, <TokenType.UINT128: 'UINT128'>, <TokenType.TSTZRANGE: 'TSTZRANGE'>, <TokenType.DATETIME: 'DATETIME'>, <TokenType.INT8MULTIRANGE: 'INT8MULTIRANGE'>, <TokenType.BIGSERIAL: 'BIGSERIAL'>, <TokenType.TIME: 'TIME'>, <TokenType.BINARY: 'BINARY'>, <TokenType.BOOLEAN: 'BOOLEAN'>, <TokenType.MAP: 'MAP'>, <TokenType.DATETIME64: 'DATETIME64'>, <TokenType.GEOMETRY: 'GEOMETRY'>, <TokenType.ARRAY: 'ARRAY'>, <TokenType.INT4MULTIRANGE: 'INT4MULTIRANGE'>, <TokenType.OBJECT: 'OBJECT'>, <TokenType.STRUCT: 'STRUCT'>, <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_PAREN: 'R_PAREN'>, <TokenType.HASH: 'HASH'>, <TokenType.PLUS: 'PLUS'>, <TokenType.CARET: 'CARET'>, <TokenType.R_BRACKET: 'R_BRACKET'>, <TokenType.BACKSLASH: 'BACKSLASH'>, <TokenType.L_BRACKET: 'L_BRACKET'>, <TokenType.PIPE: 'PIPE'>, <TokenType.SELECT: 'SELECT'>, <TokenType.SLASH: 'SLASH'>, <TokenType.IDENTIFIER: 'IDENTIFIER'>, <TokenType.PARAMETER: 'PARAMETER'>, <TokenType.AMP: 'AMP'>, <TokenType.R_BRACE: 'R_BRACE'>, <TokenType.TILDA: 'TILDA'>, <TokenType.PLACEHOLDER: 'PLACEHOLDER'>, <TokenType.DASH: 'DASH'>, <TokenType.LT: 'LT'>, <TokenType.GT: 'GT'>, <TokenType.NOT: 'NOT'>, <TokenType.STAR: 'STAR'>, <TokenType.QUOTE: 'QUOTE'>, <TokenType.MOD: 'MOD'>, <TokenType.COMMA: 'COMMA'>, <TokenType.DOT: 'DOT'>, <TokenType.COLON: 'COLON'>, <TokenType.L_BRACE: 'L_BRACE'>, <TokenType.L_PAREN: 'L_PAREN'>, <TokenType.EQ: 'EQ'>, <TokenType.SEMICOLON: 'SEMICOLON'>}
DB_CREATABLES = {<TokenType.DATABASE: 'DATABASE'>, <TokenType.SCHEMA: 'SCHEMA'>, <TokenType.DICTIONARY: 'DICTIONARY'>, <TokenType.VIEW: 'VIEW'>, <TokenType.TABLE: 'TABLE'>}
CREATABLES = {<TokenType.INDEX: 'INDEX'>, <TokenType.COLUMN: 'COLUMN'>, <TokenType.PROCEDURE: 'PROCEDURE'>, <TokenType.DATABASE: 'DATABASE'>, <TokenType.SCHEMA: 'SCHEMA'>, <TokenType.FUNCTION: 'FUNCTION'>, <TokenType.DICTIONARY: 'DICTIONARY'>, <TokenType.VIEW: 'VIEW'>, <TokenType.TABLE: 'TABLE'>}
ID_VAR_TOKENS = {<TokenType.CURRENT_DATETIME: 'CURRENT_DATETIME'>, <TokenType.TIMESTAMP: 'TIMESTAMP'>, <TokenType.UNIQUEIDENTIFIER: 'UNIQUEIDENTIFIER'>, <TokenType.TEMPORARY: 'TEMPORARY'>, <TokenType.HLLSKETCH: 'HLLSKETCH'>, <TokenType.FALSE: 'FALSE'>, <TokenType.FIRST: 'FIRST'>, <TokenType.RIGHT: 'RIGHT'>, <TokenType.DOUBLE: 'DOUBLE'>, <TokenType.FORMAT: 'FORMAT'>, <TokenType.USERDEFINED: 'USERDEFINED'>, <TokenType.TSRANGE: 'TSRANGE'>, <TokenType.CASE: 'CASE'>, <TokenType.ANTI: 'ANTI'>, <TokenType.FULL: 'FULL'>, <TokenType.ALL: 'ALL'>, <TokenType.CURRENT_TIMESTAMP: 'CURRENT_TIMESTAMP'>, <TokenType.OVERWRITE: 'OVERWRITE'>, <TokenType.IF: 'IF'>, <TokenType.CHAR: 'CHAR'>, <TokenType.PERCENT: 'PERCENT'>, <TokenType.COMMIT: 'COMMIT'>, <TokenType.PRAGMA: 'PRAGMA'>, <TokenType.PSEUDO_TYPE: 'PSEUDO_TYPE'>, <TokenType.CONSTRAINT: 'CONSTRAINT'>, <TokenType.DIV: 'DIV'>, <TokenType.SET: 'SET'>, <TokenType.COMMENT: 'COMMENT'>, <TokenType.DATETIME: 'DATETIME'>, <TokenType.CACHE: 'CACHE'>, <TokenType.INT8MULTIRANGE: 'INT8MULTIRANGE'>, <TokenType.CURRENT_USER: 'CURRENT_USER'>, <TokenType.INT4MULTIRANGE: 'INT4MULTIRANGE'>, <TokenType.OBJECT: 'OBJECT'>, <TokenType.PIVOT: 'PIVOT'>, <TokenType.UPDATE: 'UPDATE'>, <TokenType.ROWS: 'ROWS'>, <TokenType.INDEX: 'INDEX'>, <TokenType.COLUMN: 'COLUMN'>, <TokenType.TEXT: 'TEXT'>, <TokenType.TIMESTAMPTZ: 'TIMESTAMPTZ'>, <TokenType.TABLE: 'TABLE'>, <TokenType.NULLABLE: 'NULLABLE'>, <TokenType.ESCAPE: 'ESCAPE'>, <TokenType.VARBINARY: 'VARBINARY'>, <TokenType.IMAGE: 'IMAGE'>, <TokenType.XML: 'XML'>, <TokenType.ASC: 'ASC'>, <TokenType.DATE: 'DATE'>, <TokenType.DESC: 'DESC'>, <TokenType.SERIAL: 'SERIAL'>, <TokenType.VARIANT: 'VARIANT'>, <TokenType.BIGDECIMAL: 'BIGDECIMAL'>, <TokenType.TINYINT: 'TINYINT'>, <TokenType.JSONB: 'JSONB'>, <TokenType.INET: 'INET'>, <TokenType.SUPER: 'SUPER'>, <TokenType.SOME: 'SOME'>, <TokenType.FILTER: 'FILTER'>, <TokenType.INT: 'INT'>, <TokenType.UINT128: 'UINT128'>, <TokenType.TSTZRANGE: 'TSTZRANGE'>, <TokenType.EXECUTE: 'EXECUTE'>, <TokenType.TIME: 'TIME'>, <TokenType.BINARY: 'BINARY'>, <TokenType.DATETIME64: 'DATETIME64'>, <TokenType.SHOW: 'SHOW'>, <TokenType.DATABASE: 'DATABASE'>, <TokenType.ARRAY: 'ARRAY'>, <TokenType.END: 'END'>, <TokenType.DECIMAL: 'DECIMAL'>, <TokenType.RANGE: 'RANGE'>, <TokenType.MEDIUMTEXT: 'MEDIUMTEXT'>, <TokenType.BIT: 'BIT'>, <TokenType.SEMI: 'SEMI'>, <TokenType.SETTINGS: 'SETTINGS'>, <TokenType.MONEY: 'MONEY'>, <TokenType.COLLATE: 'COLLATE'>, <TokenType.SMALLINT: 'SMALLINT'>, <TokenType.UNIQUE: 'UNIQUE'>, <TokenType.SMALLSERIAL: 'SMALLSERIAL'>, <TokenType.VARCHAR: 'VARCHAR'>, <TokenType.UBIGINT: 'UBIGINT'>, <TokenType.AUTO_INCREMENT: 'AUTO_INCREMENT'>, <TokenType.VAR: 'VAR'>, <TokenType.MEDIUMBLOB: 'MEDIUMBLOB'>, <TokenType.ISNULL: 'ISNULL'>, <TokenType.DATERANGE: 'DATERANGE'>, <TokenType.INT8RANGE: 'INT8RANGE'>, <TokenType.TSTZMULTIRANGE: 'TSTZMULTIRANGE'>, <TokenType.UTINYINT: 'UTINYINT'>, <TokenType.NUMRANGE: 'NUMRANGE'>, <TokenType.DELETE: 'DELETE'>, <TokenType.TSMULTIRANGE: 'TSMULTIRANGE'>, <TokenType.ROWVERSION: 'ROWVERSION'>, <TokenType.ANY: 'ANY'>, <TokenType.DEFAULT: 'DEFAULT'>, <TokenType.REFERENCES: 'REFERENCES'>, <TokenType.MERGE: 'MERGE'>, <TokenType.OFFSET: 'OFFSET'>, <TokenType.BIGINT: 'BIGINT'>, <TokenType.TOP: 'TOP'>, <TokenType.INT128: 'INT128'>, <TokenType.ENUM: 'ENUM'>, <TokenType.UNPIVOT: 'UNPIVOT'>, <TokenType.PARTITION: 'PARTITION'>, <TokenType.NATURAL: 'NATURAL'>, <TokenType.COMMAND: 'COMMAND'>, <TokenType.ORDINALITY: 'ORDINALITY'>, <TokenType.DESCRIBE: 'DESCRIBE'>, <TokenType.GEOMETRY: 'GEOMETRY'>, <TokenType.ROW: 'ROW'>, <TokenType.LONGBLOB: 'LONGBLOB'>, <TokenType.TIMESTAMPLTZ: 'TIMESTAMPLTZ'>, <TokenType.NCHAR: 'NCHAR'>, <TokenType.VIEW: 'VIEW'>, <TokenType.BEGIN: 'BEGIN'>, <TokenType.INT4RANGE: 'INT4RANGE'>, <TokenType.GEOGRAPHY: 'GEOGRAPHY'>, <TokenType.IS: 'IS'>, <TokenType.APPLY: 'APPLY'>, <TokenType.FLOAT: 'FLOAT'>, <TokenType.UUID: 'UUID'>, <TokenType.LEFT: 'LEFT'>, <TokenType.CURRENT_TIME: 'CURRENT_TIME'>, <TokenType.VOLATILE: 'VOLATILE'>, <TokenType.SMALLMONEY: 'SMALLMONEY'>, <TokenType.SCHEMA: 'SCHEMA'>, <TokenType.NVARCHAR: 'NVARCHAR'>, <TokenType.DICTIONARY: 'DICTIONARY'>, <TokenType.CURRENT_DATE: 'CURRENT_DATE'>, <TokenType.JSON: 'JSON'>, <TokenType.LOAD: 'LOAD'>, <TokenType.INTERVAL: 'INTERVAL'>, <TokenType.NUMMULTIRANGE: 'NUMMULTIRANGE'>, <TokenType.LONGTEXT: 'LONGTEXT'>, <TokenType.INT256: 'INT256'>, <TokenType.DATEMULTIRANGE: 'DATEMULTIRANGE'>, <TokenType.UINT256: 'UINT256'>, <TokenType.UINT: 'UINT'>, <TokenType.KEEP: 'KEEP'>, <TokenType.USMALLINT: 'USMALLINT'>, <TokenType.TRUE: 'TRUE'>, <TokenType.EXISTS: 'EXISTS'>, <TokenType.BIGSERIAL: 'BIGSERIAL'>, <TokenType.BOOLEAN: 'BOOLEAN'>, <TokenType.MAP: 'MAP'>, <TokenType.PROCEDURE: 'PROCEDURE'>, <TokenType.FUNCTION: 'FUNCTION'>, <TokenType.STRUCT: 'STRUCT'>, <TokenType.HSTORE: 'HSTORE'>, <TokenType.NEXT: 'NEXT'>, <TokenType.WINDOW: 'WINDOW'>}
INTERVAL_VARS = {<TokenType.CURRENT_DATETIME: 'CURRENT_DATETIME'>, <TokenType.TIMESTAMP: 'TIMESTAMP'>, <TokenType.UNIQUEIDENTIFIER: 'UNIQUEIDENTIFIER'>, <TokenType.TEMPORARY: 'TEMPORARY'>, <TokenType.HLLSKETCH: 'HLLSKETCH'>, <TokenType.FALSE: 'FALSE'>, <TokenType.FIRST: 'FIRST'>, <TokenType.RIGHT: 'RIGHT'>, <TokenType.DOUBLE: 'DOUBLE'>, <TokenType.FORMAT: 'FORMAT'>, <TokenType.USERDEFINED: 'USERDEFINED'>, <TokenType.TSRANGE: 'TSRANGE'>, <TokenType.CASE: 'CASE'>, <TokenType.ANTI: 'ANTI'>, <TokenType.FULL: 'FULL'>, <TokenType.ALL: 'ALL'>, <TokenType.CURRENT_TIMESTAMP: 'CURRENT_TIMESTAMP'>, <TokenType.OVERWRITE: 'OVERWRITE'>, <TokenType.IF: 'IF'>, <TokenType.CHAR: 'CHAR'>, <TokenType.PERCENT: 'PERCENT'>, <TokenType.COMMIT: 'COMMIT'>, <TokenType.PRAGMA: 'PRAGMA'>, <TokenType.PSEUDO_TYPE: 'PSEUDO_TYPE'>, <TokenType.CONSTRAINT: 'CONSTRAINT'>, <TokenType.DIV: 'DIV'>, <TokenType.SET: 'SET'>, <TokenType.COMMENT: 'COMMENT'>, <TokenType.DATETIME: 'DATETIME'>, <TokenType.CACHE: 'CACHE'>, <TokenType.INT8MULTIRANGE: 'INT8MULTIRANGE'>, <TokenType.CURRENT_USER: 'CURRENT_USER'>, <TokenType.INT4MULTIRANGE: 'INT4MULTIRANGE'>, <TokenType.OBJECT: 'OBJECT'>, <TokenType.PIVOT: 'PIVOT'>, <TokenType.UPDATE: 'UPDATE'>, <TokenType.ROWS: 'ROWS'>, <TokenType.INDEX: 'INDEX'>, <TokenType.COLUMN: 'COLUMN'>, <TokenType.TEXT: 'TEXT'>, <TokenType.TIMESTAMPTZ: 'TIMESTAMPTZ'>, <TokenType.TABLE: 'TABLE'>, <TokenType.NULLABLE: 'NULLABLE'>, <TokenType.ESCAPE: 'ESCAPE'>, <TokenType.VARBINARY: 'VARBINARY'>, <TokenType.IMAGE: 'IMAGE'>, <TokenType.XML: 'XML'>, <TokenType.ASC: 'ASC'>, <TokenType.DATE: 'DATE'>, <TokenType.DESC: 'DESC'>, <TokenType.SERIAL: 'SERIAL'>, <TokenType.VARIANT: 'VARIANT'>, <TokenType.BIGDECIMAL: 'BIGDECIMAL'>, <TokenType.TINYINT: 'TINYINT'>, <TokenType.JSONB: 'JSONB'>, <TokenType.INET: 'INET'>, <TokenType.SUPER: 'SUPER'>, <TokenType.SOME: 'SOME'>, <TokenType.FILTER: 'FILTER'>, <TokenType.INT: 'INT'>, <TokenType.UINT128: 'UINT128'>, <TokenType.TSTZRANGE: 'TSTZRANGE'>, <TokenType.EXECUTE: 'EXECUTE'>, <TokenType.TIME: 'TIME'>, <TokenType.BINARY: 'BINARY'>, <TokenType.DATETIME64: 'DATETIME64'>, <TokenType.SHOW: 'SHOW'>, <TokenType.DATABASE: 'DATABASE'>, <TokenType.ARRAY: 'ARRAY'>, <TokenType.DECIMAL: 'DECIMAL'>, <TokenType.RANGE: 'RANGE'>, <TokenType.MEDIUMTEXT: 'MEDIUMTEXT'>, <TokenType.BIT: 'BIT'>, <TokenType.SEMI: 'SEMI'>, <TokenType.SETTINGS: 'SETTINGS'>, <TokenType.MONEY: 'MONEY'>, <TokenType.COLLATE: 'COLLATE'>, <TokenType.SMALLINT: 'SMALLINT'>, <TokenType.UNIQUE: 'UNIQUE'>, <TokenType.SMALLSERIAL: 'SMALLSERIAL'>, <TokenType.VARCHAR: 'VARCHAR'>, <TokenType.UBIGINT: 'UBIGINT'>, <TokenType.AUTO_INCREMENT: 'AUTO_INCREMENT'>, <TokenType.VAR: 'VAR'>, <TokenType.MEDIUMBLOB: 'MEDIUMBLOB'>, <TokenType.ISNULL: 'ISNULL'>, <TokenType.DATERANGE: 'DATERANGE'>, <TokenType.INT8RANGE: 'INT8RANGE'>, <TokenType.TSTZMULTIRANGE: 'TSTZMULTIRANGE'>, <TokenType.UTINYINT: 'UTINYINT'>, <TokenType.NUMRANGE: 'NUMRANGE'>, <TokenType.DELETE: 'DELETE'>, <TokenType.TSMULTIRANGE: 'TSMULTIRANGE'>, <TokenType.ROWVERSION: 'ROWVERSION'>, <TokenType.ANY: 'ANY'>, <TokenType.DEFAULT: 'DEFAULT'>, <TokenType.REFERENCES: 'REFERENCES'>, <TokenType.MERGE: 'MERGE'>, <TokenType.OFFSET: 'OFFSET'>, <TokenType.BIGINT: 'BIGINT'>, <TokenType.TOP: 'TOP'>, <TokenType.INT128: 'INT128'>, <TokenType.ENUM: 'ENUM'>, <TokenType.UNPIVOT: 'UNPIVOT'>, <TokenType.PARTITION: 'PARTITION'>, <TokenType.NATURAL: 'NATURAL'>, <TokenType.COMMAND: 'COMMAND'>, <TokenType.ORDINALITY: 'ORDINALITY'>, <TokenType.DESCRIBE: 'DESCRIBE'>, <TokenType.GEOMETRY: 'GEOMETRY'>, <TokenType.ROW: 'ROW'>, <TokenType.LONGBLOB: 'LONGBLOB'>, <TokenType.TIMESTAMPLTZ: 'TIMESTAMPLTZ'>, <TokenType.NCHAR: 'NCHAR'>, <TokenType.VIEW: 'VIEW'>, <TokenType.BEGIN: 'BEGIN'>, <TokenType.INT4RANGE: 'INT4RANGE'>, <TokenType.GEOGRAPHY: 'GEOGRAPHY'>, <TokenType.IS: 'IS'>, <TokenType.APPLY: 'APPLY'>, <TokenType.FLOAT: 'FLOAT'>, <TokenType.UUID: 'UUID'>, <TokenType.LEFT: 'LEFT'>, <TokenType.CURRENT_TIME: 'CURRENT_TIME'>, <TokenType.VOLATILE: 'VOLATILE'>, <TokenType.SMALLMONEY: 'SMALLMONEY'>, <TokenType.SCHEMA: 'SCHEMA'>, <TokenType.NVARCHAR: 'NVARCHAR'>, <TokenType.DICTIONARY: 'DICTIONARY'>, <TokenType.CURRENT_DATE: 'CURRENT_DATE'>, <TokenType.JSON: 'JSON'>, <TokenType.LOAD: 'LOAD'>, <TokenType.INTERVAL: 'INTERVAL'>, <TokenType.NUMMULTIRANGE: 'NUMMULTIRANGE'>, <TokenType.LONGTEXT: 'LONGTEXT'>, <TokenType.INT256: 'INT256'>, <TokenType.DATEMULTIRANGE: 'DATEMULTIRANGE'>, <TokenType.UINT256: 'UINT256'>, <TokenType.UINT: 'UINT'>, <TokenType.KEEP: 'KEEP'>, <TokenType.USMALLINT: 'USMALLINT'>, <TokenType.TRUE: 'TRUE'>, <TokenType.EXISTS: 'EXISTS'>, <TokenType.BIGSERIAL: 'BIGSERIAL'>, <TokenType.BOOLEAN: 'BOOLEAN'>, <TokenType.MAP: 'MAP'>, <TokenType.PROCEDURE: 'PROCEDURE'>, <TokenType.FUNCTION: 'FUNCTION'>, <TokenType.STRUCT: 'STRUCT'>, <TokenType.HSTORE: 'HSTORE'>, <TokenType.NEXT: 'NEXT'>, <TokenType.WINDOW: 'WINDOW'>}
TABLE_ALIAS_TOKENS = {<TokenType.CURRENT_DATETIME: 'CURRENT_DATETIME'>, <TokenType.TIMESTAMP: 'TIMESTAMP'>, <TokenType.UNIQUEIDENTIFIER: 'UNIQUEIDENTIFIER'>, <TokenType.TEMPORARY: 'TEMPORARY'>, <TokenType.HLLSKETCH: 'HLLSKETCH'>, <TokenType.FALSE: 'FALSE'>, <TokenType.FIRST: 'FIRST'>, <TokenType.DOUBLE: 'DOUBLE'>, <TokenType.FORMAT: 'FORMAT'>, <TokenType.USERDEFINED: 'USERDEFINED'>, <TokenType.TSRANGE: 'TSRANGE'>, <TokenType.CASE: 'CASE'>, <TokenType.ANTI: 'ANTI'>, <TokenType.ALL: 'ALL'>, <TokenType.CURRENT_TIMESTAMP: 'CURRENT_TIMESTAMP'>, <TokenType.OVERWRITE: 'OVERWRITE'>, <TokenType.IF: 'IF'>, <TokenType.CHAR: 'CHAR'>, <TokenType.PERCENT: 'PERCENT'>, <TokenType.COMMIT: 'COMMIT'>, <TokenType.PRAGMA: 'PRAGMA'>, <TokenType.PSEUDO_TYPE: 'PSEUDO_TYPE'>, <TokenType.CONSTRAINT: 'CONSTRAINT'>, <TokenType.DIV: 'DIV'>, <TokenType.SET: 'SET'>, <TokenType.COMMENT: 'COMMENT'>, <TokenType.DATETIME: 'DATETIME'>, <TokenType.CACHE: 'CACHE'>, <TokenType.INT8MULTIRANGE: 'INT8MULTIRANGE'>, <TokenType.CURRENT_USER: 'CURRENT_USER'>, <TokenType.INT4MULTIRANGE: 'INT4MULTIRANGE'>, <TokenType.OBJECT: 'OBJECT'>, <TokenType.PIVOT: 'PIVOT'>, <TokenType.UPDATE: 'UPDATE'>, <TokenType.ROWS: 'ROWS'>, <TokenType.INDEX: 'INDEX'>, <TokenType.COLUMN: 'COLUMN'>, <TokenType.TEXT: 'TEXT'>, <TokenType.TIMESTAMPTZ: 'TIMESTAMPTZ'>, <TokenType.TABLE: 'TABLE'>, <TokenType.NULLABLE: 'NULLABLE'>, <TokenType.ESCAPE: 'ESCAPE'>, <TokenType.VARBINARY: 'VARBINARY'>, <TokenType.IMAGE: 'IMAGE'>, <TokenType.XML: 'XML'>, <TokenType.ASC: 'ASC'>, <TokenType.DATE: 'DATE'>, <TokenType.DESC: 'DESC'>, <TokenType.SERIAL: 'SERIAL'>, <TokenType.VARIANT: 'VARIANT'>, <TokenType.BIGDECIMAL: 'BIGDECIMAL'>, <TokenType.TINYINT: 'TINYINT'>, <TokenType.JSONB: 'JSONB'>, <TokenType.INET: 'INET'>, <TokenType.SUPER: 'SUPER'>, <TokenType.SOME: 'SOME'>, <TokenType.FILTER: 'FILTER'>, <TokenType.INT: 'INT'>, <TokenType.UINT128: 'UINT128'>, <TokenType.TSTZRANGE: 'TSTZRANGE'>, <TokenType.EXECUTE: 'EXECUTE'>, <TokenType.TIME: 'TIME'>, <TokenType.BINARY: 'BINARY'>, <TokenType.DATETIME64: 'DATETIME64'>, <TokenType.SHOW: 'SHOW'>, <TokenType.DATABASE: 'DATABASE'>, <TokenType.ARRAY: 'ARRAY'>, <TokenType.END: 'END'>, <TokenType.DECIMAL: 'DECIMAL'>, <TokenType.RANGE: 'RANGE'>, <TokenType.MEDIUMTEXT: 'MEDIUMTEXT'>, <TokenType.BIT: 'BIT'>, <TokenType.SEMI: 'SEMI'>, <TokenType.SETTINGS: 'SETTINGS'>, <TokenType.MONEY: 'MONEY'>, <TokenType.COLLATE: 'COLLATE'>, <TokenType.SMALLINT: 'SMALLINT'>, <TokenType.UNIQUE: 'UNIQUE'>, <TokenType.SMALLSERIAL: 'SMALLSERIAL'>, <TokenType.VARCHAR: 'VARCHAR'>, <TokenType.UBIGINT: 'UBIGINT'>, <TokenType.AUTO_INCREMENT: 'AUTO_INCREMENT'>, <TokenType.VAR: 'VAR'>, <TokenType.MEDIUMBLOB: 'MEDIUMBLOB'>, <TokenType.ISNULL: 'ISNULL'>, <TokenType.DATERANGE: 'DATERANGE'>, <TokenType.INT8RANGE: 'INT8RANGE'>, <TokenType.TSTZMULTIRANGE: 'TSTZMULTIRANGE'>, <TokenType.UTINYINT: 'UTINYINT'>, <TokenType.NUMRANGE: 'NUMRANGE'>, <TokenType.DELETE: 'DELETE'>, <TokenType.TSMULTIRANGE: 'TSMULTIRANGE'>, <TokenType.ROWVERSION: 'ROWVERSION'>, <TokenType.ANY: 'ANY'>, <TokenType.DEFAULT: 'DEFAULT'>, <TokenType.REFERENCES: 'REFERENCES'>, <TokenType.MERGE: 'MERGE'>, <TokenType.BIGINT: 'BIGINT'>, <TokenType.TOP: 'TOP'>, <TokenType.INT128: 'INT128'>, <TokenType.ENUM: 'ENUM'>, <TokenType.UNPIVOT: 'UNPIVOT'>, <TokenType.PARTITION: 'PARTITION'>, <TokenType.COMMAND: 'COMMAND'>, <TokenType.ORDINALITY: 'ORDINALITY'>, <TokenType.DESCRIBE: 'DESCRIBE'>, <TokenType.GEOMETRY: 'GEOMETRY'>, <TokenType.ROW: 'ROW'>, <TokenType.LONGBLOB: 'LONGBLOB'>, <TokenType.TIMESTAMPLTZ: 'TIMESTAMPLTZ'>, <TokenType.NCHAR: 'NCHAR'>, <TokenType.VIEW: 'VIEW'>, <TokenType.BEGIN: 'BEGIN'>, <TokenType.INT4RANGE: 'INT4RANGE'>, <TokenType.GEOGRAPHY: 'GEOGRAPHY'>, <TokenType.IS: 'IS'>, <TokenType.FLOAT: 'FLOAT'>, <TokenType.UUID: 'UUID'>, <TokenType.CURRENT_TIME: 'CURRENT_TIME'>, <TokenType.VOLATILE: 'VOLATILE'>, <TokenType.SMALLMONEY: 'SMALLMONEY'>, <TokenType.SCHEMA: 'SCHEMA'>, <TokenType.NVARCHAR: 'NVARCHAR'>, <TokenType.DICTIONARY: 'DICTIONARY'>, <TokenType.CURRENT_DATE: 'CURRENT_DATE'>, <TokenType.JSON: 'JSON'>, <TokenType.LOAD: 'LOAD'>, <TokenType.INTERVAL: 'INTERVAL'>, <TokenType.NUMMULTIRANGE: 'NUMMULTIRANGE'>, <TokenType.LONGTEXT: 'LONGTEXT'>, <TokenType.INT256: 'INT256'>, <TokenType.DATEMULTIRANGE: 'DATEMULTIRANGE'>, <TokenType.UINT256: 'UINT256'>, <TokenType.UINT: 'UINT'>, <TokenType.KEEP: 'KEEP'>, <TokenType.USMALLINT: 'USMALLINT'>, <TokenType.TRUE: 'TRUE'>, <TokenType.EXISTS: 'EXISTS'>, <TokenType.BIGSERIAL: 'BIGSERIAL'>, <TokenType.BOOLEAN: 'BOOLEAN'>, <TokenType.MAP: 'MAP'>, <TokenType.PROCEDURE: 'PROCEDURE'>, <TokenType.FUNCTION: 'FUNCTION'>, <TokenType.STRUCT: 'STRUCT'>, <TokenType.HSTORE: 'HSTORE'>, <TokenType.NEXT: 'NEXT'>}
COMMENT_TABLE_ALIAS_TOKENS = {<TokenType.CURRENT_DATETIME: 'CURRENT_DATETIME'>, <TokenType.TIMESTAMP: 'TIMESTAMP'>, <TokenType.UNIQUEIDENTIFIER: 'UNIQUEIDENTIFIER'>, <TokenType.TEMPORARY: 'TEMPORARY'>, <TokenType.HLLSKETCH: 'HLLSKETCH'>, <TokenType.FALSE: 'FALSE'>, <TokenType.FIRST: 'FIRST'>, <TokenType.DOUBLE: 'DOUBLE'>, <TokenType.FORMAT: 'FORMAT'>, <TokenType.USERDEFINED: 'USERDEFINED'>, <TokenType.TSRANGE: 'TSRANGE'>, <TokenType.CASE: 'CASE'>, <TokenType.ANTI: 'ANTI'>, <TokenType.ALL: 'ALL'>, <TokenType.CURRENT_TIMESTAMP: 'CURRENT_TIMESTAMP'>, <TokenType.OVERWRITE: 'OVERWRITE'>, <TokenType.IF: 'IF'>, <TokenType.CHAR: 'CHAR'>, <TokenType.PERCENT: 'PERCENT'>, <TokenType.COMMIT: 'COMMIT'>, <TokenType.PRAGMA: 'PRAGMA'>, <TokenType.PSEUDO_TYPE: 'PSEUDO_TYPE'>, <TokenType.CONSTRAINT: 'CONSTRAINT'>, <TokenType.DIV: 'DIV'>, <TokenType.SET: 'SET'>, <TokenType.COMMENT: 'COMMENT'>, <TokenType.DATETIME: 'DATETIME'>, <TokenType.CACHE: 'CACHE'>, <TokenType.INT8MULTIRANGE: 'INT8MULTIRANGE'>, <TokenType.CURRENT_USER: 'CURRENT_USER'>, <TokenType.INT4MULTIRANGE: 'INT4MULTIRANGE'>, <TokenType.OBJECT: 'OBJECT'>, <TokenType.PIVOT: 'PIVOT'>, <TokenType.UPDATE: 'UPDATE'>, <TokenType.ROWS: 'ROWS'>, <TokenType.INDEX: 'INDEX'>, <TokenType.COLUMN: 'COLUMN'>, <TokenType.TEXT: 'TEXT'>, <TokenType.TIMESTAMPTZ: 'TIMESTAMPTZ'>, <TokenType.TABLE: 'TABLE'>, <TokenType.NULLABLE: 'NULLABLE'>, <TokenType.ESCAPE: 'ESCAPE'>, <TokenType.VARBINARY: 'VARBINARY'>, <TokenType.IMAGE: 'IMAGE'>, <TokenType.XML: 'XML'>, <TokenType.ASC: 'ASC'>, <TokenType.DATE: 'DATE'>, <TokenType.DESC: 'DESC'>, <TokenType.SERIAL: 'SERIAL'>, <TokenType.VARIANT: 'VARIANT'>, <TokenType.BIGDECIMAL: 'BIGDECIMAL'>, <TokenType.TINYINT: 'TINYINT'>, <TokenType.JSONB: 'JSONB'>, <TokenType.INET: 'INET'>, <TokenType.SUPER: 'SUPER'>, <TokenType.SOME: 'SOME'>, <TokenType.FILTER: 'FILTER'>, <TokenType.INT: 'INT'>, <TokenType.UINT128: 'UINT128'>, <TokenType.TSTZRANGE: 'TSTZRANGE'>, <TokenType.EXECUTE: 'EXECUTE'>, <TokenType.TIME: 'TIME'>, <TokenType.BINARY: 'BINARY'>, <TokenType.DATETIME64: 'DATETIME64'>, <TokenType.SHOW: 'SHOW'>, <TokenType.DATABASE: 'DATABASE'>, <TokenType.ARRAY: 'ARRAY'>, <TokenType.END: 'END'>, <TokenType.DECIMAL: 'DECIMAL'>, <TokenType.RANGE: 'RANGE'>, <TokenType.MEDIUMTEXT: 'MEDIUMTEXT'>, <TokenType.BIT: 'BIT'>, <TokenType.SEMI: 'SEMI'>, <TokenType.SETTINGS: 'SETTINGS'>, <TokenType.MONEY: 'MONEY'>, <TokenType.COLLATE: 'COLLATE'>, <TokenType.SMALLINT: 'SMALLINT'>, <TokenType.UNIQUE: 'UNIQUE'>, <TokenType.SMALLSERIAL: 'SMALLSERIAL'>, <TokenType.VARCHAR: 'VARCHAR'>, <TokenType.UBIGINT: 'UBIGINT'>, <TokenType.AUTO_INCREMENT: 'AUTO_INCREMENT'>, <TokenType.VAR: 'VAR'>, <TokenType.MEDIUMBLOB: 'MEDIUMBLOB'>, <TokenType.ISNULL: 'ISNULL'>, <TokenType.DATERANGE: 'DATERANGE'>, <TokenType.INT8RANGE: 'INT8RANGE'>, <TokenType.TSTZMULTIRANGE: 'TSTZMULTIRANGE'>, <TokenType.UTINYINT: 'UTINYINT'>, <TokenType.NUMRANGE: 'NUMRANGE'>, <TokenType.DELETE: 'DELETE'>, <TokenType.TSMULTIRANGE: 'TSMULTIRANGE'>, <TokenType.ROWVERSION: 'ROWVERSION'>, <TokenType.ANY: 'ANY'>, <TokenType.DEFAULT: 'DEFAULT'>, <TokenType.REFERENCES: 'REFERENCES'>, <TokenType.MERGE: 'MERGE'>, <TokenType.BIGINT: 'BIGINT'>, <TokenType.INT128: 'INT128'>, <TokenType.TOP: 'TOP'>, <TokenType.ENUM: 'ENUM'>, <TokenType.UNPIVOT: 'UNPIVOT'>, <TokenType.PARTITION: 'PARTITION'>, <TokenType.COMMAND: 'COMMAND'>, <TokenType.ORDINALITY: 'ORDINALITY'>, <TokenType.DESCRIBE: 'DESCRIBE'>, <TokenType.GEOMETRY: 'GEOMETRY'>, <TokenType.ROW: 'ROW'>, <TokenType.LONGBLOB: 'LONGBLOB'>, <TokenType.TIMESTAMPLTZ: 'TIMESTAMPLTZ'>, <TokenType.NCHAR: 'NCHAR'>, <TokenType.VIEW: 'VIEW'>, <TokenType.BEGIN: 'BEGIN'>, <TokenType.INT4RANGE: 'INT4RANGE'>, <TokenType.GEOGRAPHY: 'GEOGRAPHY'>, <TokenType.FLOAT: 'FLOAT'>, <TokenType.UUID: 'UUID'>, <TokenType.CURRENT_TIME: 'CURRENT_TIME'>, <TokenType.VOLATILE: 'VOLATILE'>, <TokenType.SMALLMONEY: 'SMALLMONEY'>, <TokenType.SCHEMA: 'SCHEMA'>, <TokenType.NVARCHAR: 'NVARCHAR'>, <TokenType.DICTIONARY: 'DICTIONARY'>, <TokenType.CURRENT_DATE: 'CURRENT_DATE'>, <TokenType.JSON: 'JSON'>, <TokenType.LOAD: 'LOAD'>, <TokenType.INTERVAL: 'INTERVAL'>, <TokenType.NUMMULTIRANGE: 'NUMMULTIRANGE'>, <TokenType.LONGTEXT: 'LONGTEXT'>, <TokenType.INT256: 'INT256'>, <TokenType.DATEMULTIRANGE: 'DATEMULTIRANGE'>, <TokenType.UINT256: 'UINT256'>, <TokenType.UINT: 'UINT'>, <TokenType.KEEP: 'KEEP'>, <TokenType.USMALLINT: 'USMALLINT'>, <TokenType.TRUE: 'TRUE'>, <TokenType.EXISTS: 'EXISTS'>, <TokenType.BIGSERIAL: 'BIGSERIAL'>, <TokenType.BOOLEAN: 'BOOLEAN'>, <TokenType.MAP: 'MAP'>, <TokenType.PROCEDURE: 'PROCEDURE'>, <TokenType.FUNCTION: 'FUNCTION'>, <TokenType.STRUCT: 'STRUCT'>, <TokenType.HSTORE: 'HSTORE'>, <TokenType.NEXT: 'NEXT'>}
UPDATE_ALIAS_TOKENS = {<TokenType.CURRENT_DATETIME: 'CURRENT_DATETIME'>, <TokenType.TIMESTAMP: 'TIMESTAMP'>, <TokenType.UNIQUEIDENTIFIER: 'UNIQUEIDENTIFIER'>, <TokenType.TEMPORARY: 'TEMPORARY'>, <TokenType.HLLSKETCH: 'HLLSKETCH'>, <TokenType.FALSE: 'FALSE'>, <TokenType.FIRST: 'FIRST'>, <TokenType.DOUBLE: 'DOUBLE'>, <TokenType.FORMAT: 'FORMAT'>, <TokenType.USERDEFINED: 'USERDEFINED'>, <TokenType.TSRANGE: 'TSRANGE'>, <TokenType.CASE: 'CASE'>, <TokenType.ANTI: 'ANTI'>, <TokenType.ALL: 'ALL'>, <TokenType.CURRENT_TIMESTAMP: 'CURRENT_TIMESTAMP'>, <TokenType.OVERWRITE: 'OVERWRITE'>, <TokenType.IF: 'IF'>, <TokenType.CHAR: 'CHAR'>, <TokenType.PERCENT: 'PERCENT'>, <TokenType.COMMIT: 'COMMIT'>, <TokenType.PRAGMA: 'PRAGMA'>, <TokenType.PSEUDO_TYPE: 'PSEUDO_TYPE'>, <TokenType.CONSTRAINT: 'CONSTRAINT'>, <TokenType.DIV: 'DIV'>, <TokenType.COMMENT: 'COMMENT'>, <TokenType.DATETIME: 'DATETIME'>, <TokenType.CACHE: 'CACHE'>, <TokenType.INT8MULTIRANGE: 'INT8MULTIRANGE'>, <TokenType.CURRENT_USER: 'CURRENT_USER'>, <TokenType.INT4MULTIRANGE: 'INT4MULTIRANGE'>, <TokenType.OBJECT: 'OBJECT'>, <TokenType.PIVOT: 'PIVOT'>, <TokenType.UPDATE: 'UPDATE'>, <TokenType.ROWS: 'ROWS'>, <TokenType.INDEX: 'INDEX'>, <TokenType.COLUMN: 'COLUMN'>, <TokenType.TEXT: 'TEXT'>, <TokenType.TIMESTAMPTZ: 'TIMESTAMPTZ'>, <TokenType.TABLE: 'TABLE'>, <TokenType.NULLABLE: 'NULLABLE'>, <TokenType.ESCAPE: 'ESCAPE'>, <TokenType.VARBINARY: 'VARBINARY'>, <TokenType.IMAGE: 'IMAGE'>, <TokenType.XML: 'XML'>, <TokenType.ASC: 'ASC'>, <TokenType.DATE: 'DATE'>, <TokenType.DESC: 'DESC'>, <TokenType.SERIAL: 'SERIAL'>, <TokenType.VARIANT: 'VARIANT'>, <TokenType.BIGDECIMAL: 'BIGDECIMAL'>, <TokenType.TINYINT: 'TINYINT'>, <TokenType.JSONB: 'JSONB'>, <TokenType.INET: 'INET'>, <TokenType.SUPER: 'SUPER'>, <TokenType.SOME: 'SOME'>, <TokenType.FILTER: 'FILTER'>, <TokenType.INT: 'INT'>, <TokenType.UINT128: 'UINT128'>, <TokenType.TSTZRANGE: 'TSTZRANGE'>, <TokenType.EXECUTE: 'EXECUTE'>, <TokenType.TIME: 'TIME'>, <TokenType.BINARY: 'BINARY'>, <TokenType.DATETIME64: 'DATETIME64'>, <TokenType.SHOW: 'SHOW'>, <TokenType.DATABASE: 'DATABASE'>, <TokenType.ARRAY: 'ARRAY'>, <TokenType.END: 'END'>, <TokenType.DECIMAL: 'DECIMAL'>, <TokenType.RANGE: 'RANGE'>, <TokenType.MEDIUMTEXT: 'MEDIUMTEXT'>, <TokenType.BIT: 'BIT'>, <TokenType.SEMI: 'SEMI'>, <TokenType.SETTINGS: 'SETTINGS'>, <TokenType.MONEY: 'MONEY'>, <TokenType.COLLATE: 'COLLATE'>, <TokenType.SMALLINT: 'SMALLINT'>, <TokenType.UNIQUE: 'UNIQUE'>, <TokenType.SMALLSERIAL: 'SMALLSERIAL'>, <TokenType.VARCHAR: 'VARCHAR'>, <TokenType.UBIGINT: 'UBIGINT'>, <TokenType.AUTO_INCREMENT: 'AUTO_INCREMENT'>, <TokenType.VAR: 'VAR'>, <TokenType.MEDIUMBLOB: 'MEDIUMBLOB'>, <TokenType.ISNULL: 'ISNULL'>, <TokenType.DATERANGE: 'DATERANGE'>, <TokenType.INT8RANGE: 'INT8RANGE'>, <TokenType.TSTZMULTIRANGE: 'TSTZMULTIRANGE'>, <TokenType.UTINYINT: 'UTINYINT'>, <TokenType.NUMRANGE: 'NUMRANGE'>, <TokenType.DELETE: 'DELETE'>, <TokenType.TSMULTIRANGE: 'TSMULTIRANGE'>, <TokenType.ROWVERSION: 'ROWVERSION'>, <TokenType.ANY: 'ANY'>, <TokenType.DEFAULT: 'DEFAULT'>, <TokenType.REFERENCES: 'REFERENCES'>, <TokenType.MERGE: 'MERGE'>, <TokenType.BIGINT: 'BIGINT'>, <TokenType.INT128: 'INT128'>, <TokenType.TOP: 'TOP'>, <TokenType.ENUM: 'ENUM'>, <TokenType.UNPIVOT: 'UNPIVOT'>, <TokenType.PARTITION: 'PARTITION'>, <TokenType.COMMAND: 'COMMAND'>, <TokenType.ORDINALITY: 'ORDINALITY'>, <TokenType.DESCRIBE: 'DESCRIBE'>, <TokenType.GEOMETRY: 'GEOMETRY'>, <TokenType.ROW: 'ROW'>, <TokenType.LONGBLOB: 'LONGBLOB'>, <TokenType.TIMESTAMPLTZ: 'TIMESTAMPLTZ'>, <TokenType.NCHAR: 'NCHAR'>, <TokenType.VIEW: 'VIEW'>, <TokenType.BEGIN: 'BEGIN'>, <TokenType.INT4RANGE: 'INT4RANGE'>, <TokenType.GEOGRAPHY: 'GEOGRAPHY'>, <TokenType.IS: 'IS'>, <TokenType.FLOAT: 'FLOAT'>, <TokenType.UUID: 'UUID'>, <TokenType.CURRENT_TIME: 'CURRENT_TIME'>, <TokenType.VOLATILE: 'VOLATILE'>, <TokenType.SMALLMONEY: 'SMALLMONEY'>, <TokenType.SCHEMA: 'SCHEMA'>, <TokenType.NVARCHAR: 'NVARCHAR'>, <TokenType.DICTIONARY: 'DICTIONARY'>, <TokenType.CURRENT_DATE: 'CURRENT_DATE'>, <TokenType.JSON: 'JSON'>, <TokenType.LOAD: 'LOAD'>, <TokenType.INTERVAL: 'INTERVAL'>, <TokenType.NUMMULTIRANGE: 'NUMMULTIRANGE'>, <TokenType.LONGTEXT: 'LONGTEXT'>, <TokenType.INT256: 'INT256'>, <TokenType.DATEMULTIRANGE: 'DATEMULTIRANGE'>, <TokenType.UINT256: 'UINT256'>, <TokenType.UINT: 'UINT'>, <TokenType.KEEP: 'KEEP'>, <TokenType.USMALLINT: 'USMALLINT'>, <TokenType.TRUE: 'TRUE'>, <TokenType.EXISTS: 'EXISTS'>, <TokenType.BIGSERIAL: 'BIGSERIAL'>, <TokenType.BOOLEAN: 'BOOLEAN'>, <TokenType.MAP: 'MAP'>, <TokenType.PROCEDURE: 'PROCEDURE'>, <TokenType.FUNCTION: 'FUNCTION'>, <TokenType.STRUCT: 'STRUCT'>, <TokenType.HSTORE: 'HSTORE'>, <TokenType.NEXT: 'NEXT'>}
TRIM_TYPES = {'BOTH', 'TRAILING', 'LEADING'}
FUNC_TOKENS = {<TokenType.CURRENT_DATETIME: 'CURRENT_DATETIME'>, <TokenType.TIMESTAMP: 'TIMESTAMP'>, <TokenType.RANGE: 'RANGE'>, <TokenType.MEDIUMTEXT: 'MEDIUMTEXT'>, <TokenType.UNIQUEIDENTIFIER: 'UNIQUEIDENTIFIER'>, <TokenType.BIT: 'BIT'>, <TokenType.MONEY: 'MONEY'>, <TokenType.SMALLINT: 'SMALLINT'>, <TokenType.HLLSKETCH: 'HLLSKETCH'>, <TokenType.SMALLSERIAL: 'SMALLSERIAL'>, <TokenType.FIRST: 'FIRST'>, <TokenType.RIGHT: 'RIGHT'>, <TokenType.VARCHAR: 'VARCHAR'>, <TokenType.UBIGINT: 'UBIGINT'>, <TokenType.DOUBLE: 'DOUBLE'>, <TokenType.FORMAT: 'FORMAT'>, <TokenType.USERDEFINED: 'USERDEFINED'>, <TokenType.VAR: 'VAR'>, <TokenType.TSRANGE: 'TSRANGE'>, <TokenType.MEDIUMBLOB: 'MEDIUMBLOB'>, <TokenType.ISNULL: 'ISNULL'>, <TokenType.DATERANGE: 'DATERANGE'>, <TokenType.INT8RANGE: 'INT8RANGE'>, <TokenType.ALL: 'ALL'>, <TokenType.CURRENT_TIMESTAMP: 'CURRENT_TIMESTAMP'>, <TokenType.TSTZMULTIRANGE: 'TSTZMULTIRANGE'>, <TokenType.UTINYINT: 'UTINYINT'>, <TokenType.NUMRANGE: 'NUMRANGE'>, <TokenType.TSMULTIRANGE: 'TSMULTIRANGE'>, <TokenType.ROWVERSION: 'ROWVERSION'>, <TokenType.CHAR: 'CHAR'>, <TokenType.ANY: 'ANY'>, <TokenType.MERGE: 'MERGE'>, <TokenType.OFFSET: 'OFFSET'>, <TokenType.BIGINT: 'BIGINT'>, <TokenType.INT128: 'INT128'>, <TokenType.PRIMARY_KEY: 'PRIMARY_KEY'>, <TokenType.ENUM: 'ENUM'>, <TokenType.PSEUDO_TYPE: 'PSEUDO_TYPE'>, <TokenType.COMMAND: 'COMMAND'>, <TokenType.DATETIME: 'DATETIME'>, <TokenType.INT8MULTIRANGE: 'INT8MULTIRANGE'>, <TokenType.GEOMETRY: 'GEOMETRY'>, <TokenType.ROW: 'ROW'>, <TokenType.CURRENT_USER: 'CURRENT_USER'>, <TokenType.INT4MULTIRANGE: 'INT4MULTIRANGE'>, <TokenType.OBJECT: 'OBJECT'>, <TokenType.INDEX: 'INDEX'>, <TokenType.LONGBLOB: 'LONGBLOB'>, <TokenType.TIMESTAMPLTZ: 'TIMESTAMPLTZ'>, <TokenType.TEXT: 'TEXT'>, <TokenType.NCHAR: 'NCHAR'>, <TokenType.TIMESTAMPTZ: 'TIMESTAMPTZ'>, <TokenType.ILIKE: 'ILIKE'>, <TokenType.TABLE: 'TABLE'>, <TokenType.NULLABLE: 'NULLABLE'>, <TokenType.VARBINARY: 'VARBINARY'>, <TokenType.INT4RANGE: 'INT4RANGE'>, <TokenType.GEOGRAPHY: 'GEOGRAPHY'>, <TokenType.IMAGE: 'IMAGE'>, <TokenType.GLOB: 'GLOB'>, <TokenType.XML: 'XML'>, <TokenType.DECIMAL: 'DECIMAL'>, <TokenType.FLOAT: 'FLOAT'>, <TokenType.UNNEST: 'UNNEST'>, <TokenType.UUID: 'UUID'>, <TokenType.LEFT: 'LEFT'>, <TokenType.CURRENT_TIME: 'CURRENT_TIME'>, <TokenType.DATE: 'DATE'>, <TokenType.SMALLMONEY: 'SMALLMONEY'>, <TokenType.IDENTIFIER: 'IDENTIFIER'>, <TokenType.SERIAL: 'SERIAL'>, <TokenType.NVARCHAR: 'NVARCHAR'>, <TokenType.BIGDECIMAL: 'BIGDECIMAL'>, <TokenType.VARIANT: 'VARIANT'>, <TokenType.TINYINT: 'TINYINT'>, <TokenType.JSONB: 'JSONB'>, <TokenType.INET: 'INET'>, <TokenType.CURRENT_DATE: 'CURRENT_DATE'>, <TokenType.JSON: 'JSON'>, <TokenType.SUPER: 'SUPER'>, <TokenType.SOME: 'SOME'>, <TokenType.FILTER: 'FILTER'>, <TokenType.INTERVAL: 'INTERVAL'>, <TokenType.NUMMULTIRANGE: 'NUMMULTIRANGE'>, <TokenType.INT: 'INT'>, <TokenType.LONGTEXT: 'LONGTEXT'>, <TokenType.INT256: 'INT256'>, <TokenType.DATEMULTIRANGE: 'DATEMULTIRANGE'>, <TokenType.UINT256: 'UINT256'>, <TokenType.UINT: 'UINT'>, <TokenType.USMALLINT: 'USMALLINT'>, <TokenType.UINT128: 'UINT128'>, <TokenType.TSTZRANGE: 'TSTZRANGE'>, <TokenType.LIKE: 'LIKE'>, <TokenType.EXISTS: 'EXISTS'>, <TokenType.BIGSERIAL: 'BIGSERIAL'>, <TokenType.TIME: 'TIME'>, <TokenType.BINARY: 'BINARY'>, <TokenType.BOOLEAN: 'BOOLEAN'>, <TokenType.MAP: 'MAP'>, <TokenType.DATETIME64: 'DATETIME64'>, <TokenType.REPLACE: 'REPLACE'>, <TokenType.ARRAY: 'ARRAY'>, <TokenType.STRUCT: 'STRUCT'>, <TokenType.HSTORE: 'HSTORE'>, <TokenType.WINDOW: 'WINDOW'>}
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.TIME: 'TIME'>, <TokenType.TIMESTAMP: 'TIMESTAMP'>, <TokenType.TIMESTAMPLTZ: 'TIMESTAMPLTZ'>, <TokenType.TIMESTAMPTZ: 'TIMESTAMPTZ'>}
SET_OPERATIONS = {<TokenType.UNION: 'UNION'>, <TokenType.EXCEPT: 'EXCEPT'>, <TokenType.INTERSECT: 'INTERSECT'>}
JOIN_METHODS = {<TokenType.NATURAL: 'NATURAL'>, <TokenType.ASOF: 'ASOF'>}
JOIN_SIDES = {<TokenType.RIGHT: 'RIGHT'>, <TokenType.LEFT: 'LEFT'>, <TokenType.FULL: 'FULL'>}
JOIN_KINDS = {<TokenType.INNER: 'INNER'>, <TokenType.CROSS: 'CROSS'>, <TokenType.ANTI: 'ANTI'>, <TokenType.SEMI: 'SEMI'>, <TokenType.OUTER: 'OUTER'>}
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>>, 'CLUSTERED': <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 = {'PRIMARY KEY', 'UNIQUE', 'FOREIGN KEY', 'CHECK', '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] = {}
MODIFIABLES = (<class 'sqlglot.expressions.Subquery'>, <class 'sqlglot.expressions.Subqueryable'>, <class 'sqlglot.expressions.Table'>)
DDL_SELECT_TOKENS = {<TokenType.SELECT: 'SELECT'>, <TokenType.WITH: 'WITH'>, <TokenType.L_PAREN: 'L_PAREN'>}
PRE_VOLATILE_TOKENS = {<TokenType.REPLACE: 'REPLACE'>, <TokenType.UNIQUE: 'UNIQUE'>, <TokenType.CREATE: 'CREATE'>}
TRANSACTION_KIND = {'IMMEDIATE', 'EXCLUSIVE', 'DEFERRED'}
TRANSACTION_CHARACTERISTICS = {'ISOLATION LEVEL READ UNCOMMITTED', 'READ ONLY', 'ISOLATION LEVEL REPEATABLE READ', 'ISOLATION LEVEL SERIALIZABLE', 'READ WRITE', 'ISOLATION LEVEL READ COMMITTED'}
INSERT_ALTERNATIVES = {'ROLLBACK', 'FAIL', 'IGNORE', 'ABORT', 'REPLACE'}
CLONE_KINDS = {'TIMESTAMP', 'STATEMENT', 'OFFSET'}
TABLE_INDEX_HINT_TOKENS = {<TokenType.USE: 'USE'>, <TokenType.IGNORE: 'IGNORE'>, <TokenType.FORCE: 'FORCE'>}
WINDOW_ALIAS_TOKENS = {<TokenType.CURRENT_DATETIME: 'CURRENT_DATETIME'>, <TokenType.TIMESTAMP: 'TIMESTAMP'>, <TokenType.UNIQUEIDENTIFIER: 'UNIQUEIDENTIFIER'>, <TokenType.TEMPORARY: 'TEMPORARY'>, <TokenType.HLLSKETCH: 'HLLSKETCH'>, <TokenType.FALSE: 'FALSE'>, <TokenType.FIRST: 'FIRST'>, <TokenType.RIGHT: 'RIGHT'>, <TokenType.DOUBLE: 'DOUBLE'>, <TokenType.FORMAT: 'FORMAT'>, <TokenType.USERDEFINED: 'USERDEFINED'>, <TokenType.TSRANGE: 'TSRANGE'>, <TokenType.CASE: 'CASE'>, <TokenType.ANTI: 'ANTI'>, <TokenType.FULL: 'FULL'>, <TokenType.ALL: 'ALL'>, <TokenType.CURRENT_TIMESTAMP: 'CURRENT_TIMESTAMP'>, <TokenType.OVERWRITE: 'OVERWRITE'>, <TokenType.IF: 'IF'>, <TokenType.CHAR: 'CHAR'>, <TokenType.PERCENT: 'PERCENT'>, <TokenType.COMMIT: 'COMMIT'>, <TokenType.PRAGMA: 'PRAGMA'>, <TokenType.PSEUDO_TYPE: 'PSEUDO_TYPE'>, <TokenType.CONSTRAINT: 'CONSTRAINT'>, <TokenType.DIV: 'DIV'>, <TokenType.SET: 'SET'>, <TokenType.COMMENT: 'COMMENT'>, <TokenType.DATETIME: 'DATETIME'>, <TokenType.CACHE: 'CACHE'>, <TokenType.INT8MULTIRANGE: 'INT8MULTIRANGE'>, <TokenType.CURRENT_USER: 'CURRENT_USER'>, <TokenType.INT4MULTIRANGE: 'INT4MULTIRANGE'>, <TokenType.OBJECT: 'OBJECT'>, <TokenType.PIVOT: 'PIVOT'>, <TokenType.UPDATE: 'UPDATE'>, <TokenType.INDEX: 'INDEX'>, <TokenType.COLUMN: 'COLUMN'>, <TokenType.TEXT: 'TEXT'>, <TokenType.TIMESTAMPTZ: 'TIMESTAMPTZ'>, <TokenType.TABLE: 'TABLE'>, <TokenType.NULLABLE: 'NULLABLE'>, <TokenType.ESCAPE: 'ESCAPE'>, <TokenType.VARBINARY: 'VARBINARY'>, <TokenType.IMAGE: 'IMAGE'>, <TokenType.XML: 'XML'>, <TokenType.ASC: 'ASC'>, <TokenType.DATE: 'DATE'>, <TokenType.DESC: 'DESC'>, <TokenType.SERIAL: 'SERIAL'>, <TokenType.VARIANT: 'VARIANT'>, <TokenType.BIGDECIMAL: 'BIGDECIMAL'>, <TokenType.TINYINT: 'TINYINT'>, <TokenType.JSONB: 'JSONB'>, <TokenType.INET: 'INET'>, <TokenType.SUPER: 'SUPER'>, <TokenType.SOME: 'SOME'>, <TokenType.FILTER: 'FILTER'>, <TokenType.INT: 'INT'>, <TokenType.UINT128: 'UINT128'>, <TokenType.TSTZRANGE: 'TSTZRANGE'>, <TokenType.EXECUTE: 'EXECUTE'>, <TokenType.TIME: 'TIME'>, <TokenType.BINARY: 'BINARY'>, <TokenType.DATETIME64: 'DATETIME64'>, <TokenType.SHOW: 'SHOW'>, <TokenType.DATABASE: 'DATABASE'>, <TokenType.ARRAY: 'ARRAY'>, <TokenType.END: 'END'>, <TokenType.DECIMAL: 'DECIMAL'>, <TokenType.RANGE: 'RANGE'>, <TokenType.MEDIUMTEXT: 'MEDIUMTEXT'>, <TokenType.BIT: 'BIT'>, <TokenType.SEMI: 'SEMI'>, <TokenType.SETTINGS: 'SETTINGS'>, <TokenType.MONEY: 'MONEY'>, <TokenType.COLLATE: 'COLLATE'>, <TokenType.SMALLINT: 'SMALLINT'>, <TokenType.UNIQUE: 'UNIQUE'>, <TokenType.SMALLSERIAL: 'SMALLSERIAL'>, <TokenType.VARCHAR: 'VARCHAR'>, <TokenType.UBIGINT: 'UBIGINT'>, <TokenType.AUTO_INCREMENT: 'AUTO_INCREMENT'>, <TokenType.VAR: 'VAR'>, <TokenType.MEDIUMBLOB: 'MEDIUMBLOB'>, <TokenType.ISNULL: 'ISNULL'>, <TokenType.DATERANGE: 'DATERANGE'>, <TokenType.INT8RANGE: 'INT8RANGE'>, <TokenType.TSTZMULTIRANGE: 'TSTZMULTIRANGE'>, <TokenType.UTINYINT: 'UTINYINT'>, <TokenType.NUMRANGE: 'NUMRANGE'>, <TokenType.DELETE: 'DELETE'>, <TokenType.TSMULTIRANGE: 'TSMULTIRANGE'>, <TokenType.ROWVERSION: 'ROWVERSION'>, <TokenType.ANY: 'ANY'>, <TokenType.DEFAULT: 'DEFAULT'>, <TokenType.REFERENCES: 'REFERENCES'>, <TokenType.MERGE: 'MERGE'>, <TokenType.OFFSET: 'OFFSET'>, <TokenType.BIGINT: 'BIGINT'>, <TokenType.TOP: 'TOP'>, <TokenType.INT128: 'INT128'>, <TokenType.ENUM: 'ENUM'>, <TokenType.UNPIVOT: 'UNPIVOT'>, <TokenType.PARTITION: 'PARTITION'>, <TokenType.NATURAL: 'NATURAL'>, <TokenType.COMMAND: 'COMMAND'>, <TokenType.ORDINALITY: 'ORDINALITY'>, <TokenType.DESCRIBE: 'DESCRIBE'>, <TokenType.GEOMETRY: 'GEOMETRY'>, <TokenType.ROW: 'ROW'>, <TokenType.LONGBLOB: 'LONGBLOB'>, <TokenType.TIMESTAMPLTZ: 'TIMESTAMPLTZ'>, <TokenType.NCHAR: 'NCHAR'>, <TokenType.VIEW: 'VIEW'>, <TokenType.BEGIN: 'BEGIN'>, <TokenType.INT4RANGE: 'INT4RANGE'>, <TokenType.GEOGRAPHY: 'GEOGRAPHY'>, <TokenType.IS: 'IS'>, <TokenType.APPLY: 'APPLY'>, <TokenType.FLOAT: 'FLOAT'>, <TokenType.UUID: 'UUID'>, <TokenType.LEFT: 'LEFT'>, <TokenType.CURRENT_TIME: 'CURRENT_TIME'>, <TokenType.VOLATILE: 'VOLATILE'>, <TokenType.SMALLMONEY: 'SMALLMONEY'>, <TokenType.SCHEMA: 'SCHEMA'>, <TokenType.NVARCHAR: 'NVARCHAR'>, <TokenType.DICTIONARY: 'DICTIONARY'>, <TokenType.CURRENT_DATE: 'CURRENT_DATE'>, <TokenType.JSON: 'JSON'>, <TokenType.LOAD: 'LOAD'>, <TokenType.INTERVAL: 'INTERVAL'>, <TokenType.NUMMULTIRANGE: 'NUMMULTIRANGE'>, <TokenType.LONGTEXT: 'LONGTEXT'>, <TokenType.INT256: 'INT256'>, <TokenType.DATEMULTIRANGE: 'DATEMULTIRANGE'>, <TokenType.UINT256: 'UINT256'>, <TokenType.UINT: 'UINT'>, <TokenType.KEEP: 'KEEP'>, <TokenType.USMALLINT: 'USMALLINT'>, <TokenType.TRUE: 'TRUE'>, <TokenType.EXISTS: 'EXISTS'>, <TokenType.BIGSERIAL: 'BIGSERIAL'>, <TokenType.BOOLEAN: 'BOOLEAN'>, <TokenType.MAP: 'MAP'>, <TokenType.PROCEDURE: 'PROCEDURE'>, <TokenType.FUNCTION: 'FUNCTION'>, <TokenType.STRUCT: 'STRUCT'>, <TokenType.HSTORE: 'HSTORE'>, <TokenType.NEXT: 'NEXT'>, <TokenType.WINDOW: 'WINDOW'>}
WINDOW_BEFORE_PAREN_TOKENS = {<TokenType.OVER: 'OVER'>}
WINDOW_SIDES = {'PRECEDING', 'FOLLOWING'}
ADD_CONSTRAINT_TOKENS = {<TokenType.PRIMARY_KEY: 'PRIMARY_KEY'>, <TokenType.FOREIGN_KEY: 'FOREIGN_KEY'>, <TokenType.CONSTRAINT: 'CONSTRAINT'>}
STRICT_CAST = True
CONCAT_NULL_OUTPUTS_STRING = 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): View Source

    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

def parse( self, raw_tokens: List[sqlglot.tokens.Token], sql: Optional[str] = None) -> List[Optional[sqlglot.expressions.Expression]]: View Source

    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        )

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]]: View Source

    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]

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: View Source

    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            )

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: View Source

    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)

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: View Source

    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)

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: View Source

    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

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