Edit on GitHub

sqlglot.dialects.postgres

   1from __future__ import annotations
   2
   3import typing as t
   4
   5from sqlglot import exp, generator, parser, tokens, transforms
   6from sqlglot.dialects.dialect import (
   7    DATE_ADD_OR_SUB,
   8    Dialect,
   9    JSON_EXTRACT_TYPE,
  10    any_value_to_max_sql,
  11    array_append_sql,
  12    array_concat_sql,
  13    binary_from_function,
  14    bool_xor_sql,
  15    datestrtodate_sql,
  16    build_formatted_time,
  17    filter_array_using_unnest,
  18    getbit_sql,
  19    inline_array_sql,
  20    json_extract_segments,
  21    json_path_key_only_name,
  22    max_or_greatest,
  23    merge_without_target_sql,
  24    min_or_least,
  25    no_last_day_sql,
  26    no_map_from_entries_sql,
  27    no_paren_current_date_sql,
  28    no_pivot_sql,
  29    no_trycast_sql,
  30    build_json_extract_path,
  31    build_timestamp_trunc,
  32    rename_func,
  33    sha256_sql,
  34    struct_extract_sql,
  35    timestamptrunc_sql,
  36    timestrtotime_sql,
  37    trim_sql,
  38    ts_or_ds_add_cast,
  39    strposition_sql,
  40    count_if_to_sum,
  41    groupconcat_sql,
  42    regexp_replace_global_modifier,
  43    sha2_digest_sql,
  44)
  45from sqlglot.generator import unsupported_args
  46from sqlglot.helper import is_int, seq_get
  47from sqlglot.parser import binary_range_parser
  48from sqlglot.tokens import TokenType
  49
  50if t.TYPE_CHECKING:
  51    from sqlglot.dialects.dialect import DialectType
  52
  53
  54DATE_DIFF_FACTOR = {
  55    "MICROSECOND": " * 1000000",
  56    "MILLISECOND": " * 1000",
  57    "SECOND": "",
  58    "MINUTE": " / 60",
  59    "HOUR": " / 3600",
  60    "DAY": " / 86400",
  61}
  62
  63
  64def _date_add_sql(kind: str) -> t.Callable[[Postgres.Generator, DATE_ADD_OR_SUB], str]:
  65    def func(self: Postgres.Generator, expression: DATE_ADD_OR_SUB) -> str:
  66        if isinstance(expression, exp.TsOrDsAdd):
  67            expression = ts_or_ds_add_cast(expression)
  68
  69        this = self.sql(expression, "this")
  70        unit = expression.args.get("unit")
  71
  72        e = self._simplify_unless_literal(expression.expression)
  73        if isinstance(e, exp.Literal):
  74            e.set("is_string", True)
  75        elif e.is_number:
  76            e = exp.Literal.string(e.to_py())
  77        else:
  78            self.unsupported("Cannot add non literal")
  79
  80        return f"{this} {kind} {self.sql(exp.Interval(this=e, unit=unit))}"
  81
  82    return func
  83
  84
  85def _date_diff_sql(self: Postgres.Generator, expression: exp.DateDiff) -> str:
  86    unit = expression.text("unit").upper()
  87    factor = DATE_DIFF_FACTOR.get(unit)
  88
  89    end = f"CAST({self.sql(expression, 'this')} AS TIMESTAMP)"
  90    start = f"CAST({self.sql(expression, 'expression')} AS TIMESTAMP)"
  91
  92    if factor is not None:
  93        return f"CAST(EXTRACT(epoch FROM {end} - {start}){factor} AS BIGINT)"
  94
  95    age = f"AGE({end}, {start})"
  96
  97    if unit == "WEEK":
  98        unit = f"EXTRACT(days FROM ({end} - {start})) / 7"
  99    elif unit == "MONTH":
 100        unit = f"EXTRACT(year FROM {age}) * 12 + EXTRACT(month FROM {age})"
 101    elif unit == "QUARTER":
 102        unit = f"EXTRACT(year FROM {age}) * 4 + EXTRACT(month FROM {age}) / 3"
 103    elif unit == "YEAR":
 104        unit = f"EXTRACT(year FROM {age})"
 105    else:
 106        unit = age
 107
 108    return f"CAST({unit} AS BIGINT)"
 109
 110
 111def _substring_sql(self: Postgres.Generator, expression: exp.Substring) -> str:
 112    this = self.sql(expression, "this")
 113    start = self.sql(expression, "start")
 114    length = self.sql(expression, "length")
 115
 116    from_part = f" FROM {start}" if start else ""
 117    for_part = f" FOR {length}" if length else ""
 118
 119    return f"SUBSTRING({this}{from_part}{for_part})"
 120
 121
 122def _auto_increment_to_serial(expression: exp.Expression) -> exp.Expression:
 123    auto = expression.find(exp.AutoIncrementColumnConstraint)
 124
 125    if auto:
 126        expression.args["constraints"].remove(auto.parent)
 127        kind = expression.args["kind"]
 128
 129        if kind.this == exp.DataType.Type.INT:
 130            kind.replace(exp.DataType(this=exp.DataType.Type.SERIAL))
 131        elif kind.this == exp.DataType.Type.SMALLINT:
 132            kind.replace(exp.DataType(this=exp.DataType.Type.SMALLSERIAL))
 133        elif kind.this == exp.DataType.Type.BIGINT:
 134            kind.replace(exp.DataType(this=exp.DataType.Type.BIGSERIAL))
 135
 136    return expression
 137
 138
 139def _serial_to_generated(expression: exp.Expression) -> exp.Expression:
 140    if not isinstance(expression, exp.ColumnDef):
 141        return expression
 142    kind = expression.kind
 143    if not kind:
 144        return expression
 145
 146    if kind.this == exp.DataType.Type.SERIAL:
 147        data_type = exp.DataType(this=exp.DataType.Type.INT)
 148    elif kind.this == exp.DataType.Type.SMALLSERIAL:
 149        data_type = exp.DataType(this=exp.DataType.Type.SMALLINT)
 150    elif kind.this == exp.DataType.Type.BIGSERIAL:
 151        data_type = exp.DataType(this=exp.DataType.Type.BIGINT)
 152    else:
 153        data_type = None
 154
 155    if data_type:
 156        expression.args["kind"].replace(data_type)
 157        constraints = expression.args["constraints"]
 158        generated = exp.ColumnConstraint(kind=exp.GeneratedAsIdentityColumnConstraint(this=False))
 159        notnull = exp.ColumnConstraint(kind=exp.NotNullColumnConstraint())
 160
 161        if notnull not in constraints:
 162            constraints.insert(0, notnull)
 163        if generated not in constraints:
 164            constraints.insert(0, generated)
 165
 166    return expression
 167
 168
 169def _build_generate_series(args: t.List) -> exp.ExplodingGenerateSeries:
 170    # The goal is to convert step values like '1 day' or INTERVAL '1 day' into INTERVAL '1' day
 171    # Note: postgres allows calls with just two arguments -- the "step" argument defaults to 1
 172    step = seq_get(args, 2)
 173    if step is not None:
 174        if step.is_string:
 175            args[2] = exp.to_interval(step.this)
 176        elif isinstance(step, exp.Interval) and not step.args.get("unit"):
 177            args[2] = exp.to_interval(step.this.this)
 178
 179    return exp.ExplodingGenerateSeries.from_arg_list(args)
 180
 181
 182def _build_to_timestamp(args: t.List) -> exp.UnixToTime | exp.StrToTime:
 183    # TO_TIMESTAMP accepts either a single double argument or (text, text)
 184    if len(args) == 1:
 185        # https://www.postgresql.org/docs/current/functions-datetime.html#FUNCTIONS-DATETIME-TABLE
 186        return exp.UnixToTime.from_arg_list(args)
 187
 188    # https://www.postgresql.org/docs/current/functions-formatting.html
 189    return build_formatted_time(exp.StrToTime, "postgres")(args)
 190
 191
 192def _json_extract_sql(
 193    name: str, op: str
 194) -> t.Callable[[Postgres.Generator, JSON_EXTRACT_TYPE], str]:
 195    def _generate(self: Postgres.Generator, expression: JSON_EXTRACT_TYPE) -> str:
 196        if expression.args.get("only_json_types"):
 197            return json_extract_segments(name, quoted_index=False, op=op)(self, expression)
 198        return json_extract_segments(name)(self, expression)
 199
 200    return _generate
 201
 202
 203def _build_regexp_replace(args: t.List, dialect: DialectType = None) -> exp.RegexpReplace:
 204    # The signature of REGEXP_REPLACE is:
 205    # regexp_replace(source, pattern, replacement [, start [, N ]] [, flags ])
 206    #
 207    # Any one of `start`, `N` and `flags` can be column references, meaning that
 208    # unless we can statically see that the last argument is a non-integer string
 209    # (eg. not '0'), then it's not possible to construct the correct AST
 210    regexp_replace = None
 211    if len(args) > 3:
 212        last = args[-1]
 213        if not is_int(last.name):
 214            if not last.type or last.is_type(exp.DataType.Type.UNKNOWN, exp.DataType.Type.NULL):
 215                from sqlglot.optimizer.annotate_types import annotate_types
 216
 217                last = annotate_types(last, dialect=dialect)
 218
 219            if last.is_type(*exp.DataType.TEXT_TYPES):
 220                regexp_replace = exp.RegexpReplace.from_arg_list(args[:-1])
 221                regexp_replace.set("modifiers", last)
 222
 223    regexp_replace = regexp_replace or exp.RegexpReplace.from_arg_list(args)
 224    regexp_replace.set("single_replace", True)
 225    return regexp_replace
 226
 227
 228def _unix_to_time_sql(self: Postgres.Generator, expression: exp.UnixToTime) -> str:
 229    scale = expression.args.get("scale")
 230    timestamp = expression.this
 231
 232    if scale in (None, exp.UnixToTime.SECONDS):
 233        return self.func("TO_TIMESTAMP", timestamp, self.format_time(expression))
 234
 235    return self.func(
 236        "TO_TIMESTAMP",
 237        exp.Div(this=timestamp, expression=exp.func("POW", 10, scale)),
 238        self.format_time(expression),
 239    )
 240
 241
 242def _build_levenshtein_less_equal(args: t.List) -> exp.Levenshtein:
 243    # Postgres has two signatures for levenshtein_less_equal function, but in both cases
 244    # max_dist is the last argument
 245    # levenshtein_less_equal(source, target, ins_cost, del_cost, sub_cost, max_d)
 246    # levenshtein_less_equal(source, target, max_d)
 247    max_dist = args.pop()
 248
 249    return exp.Levenshtein(
 250        this=seq_get(args, 0),
 251        expression=seq_get(args, 1),
 252        ins_cost=seq_get(args, 2),
 253        del_cost=seq_get(args, 3),
 254        sub_cost=seq_get(args, 4),
 255        max_dist=max_dist,
 256    )
 257
 258
 259def _levenshtein_sql(self: Postgres.Generator, expression: exp.Levenshtein) -> str:
 260    name = "LEVENSHTEIN_LESS_EQUAL" if expression.args.get("max_dist") else "LEVENSHTEIN"
 261
 262    return rename_func(name)(self, expression)
 263
 264
 265def _versioned_anyvalue_sql(self: Postgres.Generator, expression: exp.AnyValue) -> str:
 266    # https://www.postgresql.org/docs/16/functions-aggregate.html
 267    # https://www.postgresql.org/about/featurematrix/
 268    if self.dialect.version < (16,):
 269        return any_value_to_max_sql(self, expression)
 270
 271    return rename_func("ANY_VALUE")(self, expression)
 272
 273
 274def _round_sql(self: Postgres.Generator, expression: exp.Round) -> str:
 275    this = self.sql(expression, "this")
 276    decimals = self.sql(expression, "decimals")
 277
 278    if not decimals:
 279        return self.func("ROUND", this)
 280
 281    if not expression.type:
 282        from sqlglot.optimizer.annotate_types import annotate_types
 283
 284        expression = annotate_types(expression, dialect=self.dialect)
 285
 286    # ROUND(double precision, integer) is not permitted in Postgres
 287    # so it's necessary to cast to decimal before rounding.
 288    if expression.this.is_type(exp.DataType.Type.DOUBLE):
 289        decimal_type = exp.DataType.build(
 290            exp.DataType.Type.DECIMAL, expressions=expression.expressions
 291        )
 292        this = self.sql(exp.Cast(this=this, to=decimal_type))
 293
 294    return self.func("ROUND", this, decimals)
 295
 296
 297class Postgres(Dialect):
 298    INDEX_OFFSET = 1
 299    TYPED_DIVISION = True
 300    CONCAT_COALESCE = True
 301    NULL_ORDERING = "nulls_are_large"
 302    TIME_FORMAT = "'YYYY-MM-DD HH24:MI:SS'"
 303    TABLESAMPLE_SIZE_IS_PERCENT = True
 304    TABLES_REFERENCEABLE_AS_COLUMNS = True
 305
 306    DEFAULT_FUNCTIONS_COLUMN_NAMES = {
 307        exp.ExplodingGenerateSeries: "generate_series",
 308    }
 309
 310    TIME_MAPPING = {
 311        "d": "%u",  # 1-based day of week
 312        "D": "%u",  # 1-based day of week
 313        "dd": "%d",  # day of month
 314        "DD": "%d",  # day of month
 315        "ddd": "%j",  # zero padded day of year
 316        "DDD": "%j",  # zero padded day of year
 317        "FMDD": "%-d",  # - is no leading zero for Python; same for FM in postgres
 318        "FMDDD": "%-j",  # day of year
 319        "FMHH12": "%-I",  # 9
 320        "FMHH24": "%-H",  # 9
 321        "FMMI": "%-M",  # Minute
 322        "FMMM": "%-m",  # 1
 323        "FMSS": "%-S",  # Second
 324        "HH12": "%I",  # 09
 325        "HH24": "%H",  # 09
 326        "mi": "%M",  # zero padded minute
 327        "MI": "%M",  # zero padded minute
 328        "mm": "%m",  # 01
 329        "MM": "%m",  # 01
 330        "OF": "%z",  # utc offset
 331        "ss": "%S",  # zero padded second
 332        "SS": "%S",  # zero padded second
 333        "TMDay": "%A",  # TM is locale dependent
 334        "TMDy": "%a",
 335        "TMMon": "%b",  # Sep
 336        "TMMonth": "%B",  # September
 337        "TZ": "%Z",  # uppercase timezone name
 338        "US": "%f",  # zero padded microsecond
 339        "ww": "%U",  # 1-based week of year
 340        "WW": "%U",  # 1-based week of year
 341        "yy": "%y",  # 15
 342        "YY": "%y",  # 15
 343        "yyyy": "%Y",  # 2015
 344        "YYYY": "%Y",  # 2015
 345    }
 346
 347    class Tokenizer(tokens.Tokenizer):
 348        BIT_STRINGS = [("b'", "'"), ("B'", "'")]
 349        HEX_STRINGS = [("x'", "'"), ("X'", "'")]
 350        BYTE_STRINGS = [("e'", "'"), ("E'", "'")]
 351        BYTE_STRING_ESCAPES = ["'", "\\"]
 352        HEREDOC_STRINGS = ["$"]
 353
 354        HEREDOC_TAG_IS_IDENTIFIER = True
 355        HEREDOC_STRING_ALTERNATIVE = TokenType.PARAMETER
 356
 357        KEYWORDS = {
 358            **tokens.Tokenizer.KEYWORDS,
 359            "~": TokenType.RLIKE,
 360            "@@": TokenType.DAT,
 361            "@>": TokenType.AT_GT,
 362            "<@": TokenType.LT_AT,
 363            "?&": TokenType.QMARK_AMP,
 364            "?|": TokenType.QMARK_PIPE,
 365            "#-": TokenType.HASH_DASH,
 366            "|/": TokenType.PIPE_SLASH,
 367            "||/": TokenType.DPIPE_SLASH,
 368            "BEGIN": TokenType.BEGIN,
 369            "BIGSERIAL": TokenType.BIGSERIAL,
 370            "CONSTRAINT TRIGGER": TokenType.COMMAND,
 371            "CSTRING": TokenType.PSEUDO_TYPE,
 372            "DECLARE": TokenType.COMMAND,
 373            "DO": TokenType.COMMAND,
 374            "EXEC": TokenType.COMMAND,
 375            "HSTORE": TokenType.HSTORE,
 376            "INT8": TokenType.BIGINT,
 377            "MONEY": TokenType.MONEY,
 378            "NAME": TokenType.NAME,
 379            "OID": TokenType.OBJECT_IDENTIFIER,
 380            "ONLY": TokenType.ONLY,
 381            "POINT": TokenType.POINT,
 382            "REFRESH": TokenType.COMMAND,
 383            "REINDEX": TokenType.COMMAND,
 384            "RESET": TokenType.COMMAND,
 385            "SERIAL": TokenType.SERIAL,
 386            "SMALLSERIAL": TokenType.SMALLSERIAL,
 387            "TEMP": TokenType.TEMPORARY,
 388            "REGCLASS": TokenType.OBJECT_IDENTIFIER,
 389            "REGCOLLATION": TokenType.OBJECT_IDENTIFIER,
 390            "REGCONFIG": TokenType.OBJECT_IDENTIFIER,
 391            "REGDICTIONARY": TokenType.OBJECT_IDENTIFIER,
 392            "REGNAMESPACE": TokenType.OBJECT_IDENTIFIER,
 393            "REGOPER": TokenType.OBJECT_IDENTIFIER,
 394            "REGOPERATOR": TokenType.OBJECT_IDENTIFIER,
 395            "REGPROC": TokenType.OBJECT_IDENTIFIER,
 396            "REGPROCEDURE": TokenType.OBJECT_IDENTIFIER,
 397            "REGROLE": TokenType.OBJECT_IDENTIFIER,
 398            "REGTYPE": TokenType.OBJECT_IDENTIFIER,
 399            "FLOAT": TokenType.DOUBLE,
 400            "XML": TokenType.XML,
 401            "VARIADIC": TokenType.VARIADIC,
 402            "INOUT": TokenType.INOUT,
 403        }
 404        KEYWORDS.pop("/*+")
 405        KEYWORDS.pop("DIV")
 406
 407        SINGLE_TOKENS = {
 408            **tokens.Tokenizer.SINGLE_TOKENS,
 409            "$": TokenType.HEREDOC_STRING,
 410        }
 411
 412        VAR_SINGLE_TOKENS = {"$"}
 413
 414    class Parser(parser.Parser):
 415        SUPPORTS_OMITTED_INTERVAL_SPAN_UNIT = True
 416
 417        PROPERTY_PARSERS = {
 418            **parser.Parser.PROPERTY_PARSERS,
 419            "SET": lambda self: self.expression(exp.SetConfigProperty, this=self._parse_set()),
 420        }
 421        PROPERTY_PARSERS.pop("INPUT")
 422
 423        PLACEHOLDER_PARSERS = {
 424            **parser.Parser.PLACEHOLDER_PARSERS,
 425            TokenType.PLACEHOLDER: lambda self: self.expression(exp.Placeholder, jdbc=True),
 426            TokenType.MOD: lambda self: self._parse_query_parameter(),
 427        }
 428
 429        FUNCTIONS = {
 430            **parser.Parser.FUNCTIONS,
 431            "ARRAY_PREPEND": lambda args: exp.ArrayPrepend(
 432                this=seq_get(args, 1), expression=seq_get(args, 0)
 433            ),
 434            "BIT_AND": exp.BitwiseAndAgg.from_arg_list,
 435            "BIT_OR": exp.BitwiseOrAgg.from_arg_list,
 436            "BIT_XOR": exp.BitwiseXorAgg.from_arg_list,
 437            "DATE_TRUNC": build_timestamp_trunc,
 438            "DIV": lambda args: exp.cast(
 439                binary_from_function(exp.IntDiv)(args), exp.DataType.Type.DECIMAL
 440            ),
 441            "GENERATE_SERIES": _build_generate_series,
 442            "GET_BIT": lambda args: exp.Getbit(
 443                this=seq_get(args, 0), expression=seq_get(args, 1), zero_is_msb=True
 444            ),
 445            "JSON_EXTRACT_PATH": build_json_extract_path(exp.JSONExtract),
 446            "JSON_EXTRACT_PATH_TEXT": build_json_extract_path(exp.JSONExtractScalar),
 447            "LENGTH": lambda args: exp.Length(this=seq_get(args, 0), encoding=seq_get(args, 1)),
 448            "MAKE_TIME": exp.TimeFromParts.from_arg_list,
 449            "MAKE_TIMESTAMP": exp.TimestampFromParts.from_arg_list,
 450            "NOW": exp.CurrentTimestamp.from_arg_list,
 451            "REGEXP_REPLACE": _build_regexp_replace,
 452            "TO_CHAR": build_formatted_time(exp.TimeToStr, "postgres"),
 453            "TO_DATE": build_formatted_time(exp.StrToDate, "postgres"),
 454            "TO_TIMESTAMP": _build_to_timestamp,
 455            "UNNEST": exp.Explode.from_arg_list,
 456            "SHA256": lambda args: exp.SHA2(this=seq_get(args, 0), length=exp.Literal.number(256)),
 457            "SHA384": lambda args: exp.SHA2(this=seq_get(args, 0), length=exp.Literal.number(384)),
 458            "SHA512": lambda args: exp.SHA2(this=seq_get(args, 0), length=exp.Literal.number(512)),
 459            "LEVENSHTEIN_LESS_EQUAL": _build_levenshtein_less_equal,
 460            "JSON_OBJECT_AGG": lambda args: exp.JSONObjectAgg(expressions=args),
 461            "JSONB_OBJECT_AGG": exp.JSONBObjectAgg.from_arg_list,
 462            "WIDTH_BUCKET": lambda args: exp.WidthBucket(
 463                this=seq_get(args, 0), threshold=seq_get(args, 1)
 464            )
 465            if len(args) == 2
 466            else exp.WidthBucket.from_arg_list(args),
 467        }
 468
 469        NO_PAREN_FUNCTION_PARSERS = {
 470            **parser.Parser.NO_PAREN_FUNCTION_PARSERS,
 471            "VARIADIC": lambda self: self.expression(exp.Variadic, this=self._parse_bitwise()),
 472        }
 473
 474        NO_PAREN_FUNCTIONS = {
 475            **parser.Parser.NO_PAREN_FUNCTIONS,
 476            TokenType.CURRENT_SCHEMA: exp.CurrentSchema,
 477        }
 478
 479        FUNCTION_PARSERS = {
 480            **parser.Parser.FUNCTION_PARSERS,
 481            "DATE_PART": lambda self: self._parse_date_part(),
 482            "JSON_AGG": lambda self: self.expression(
 483                exp.JSONArrayAgg,
 484                this=self._parse_lambda(),
 485                order=self._parse_order(),
 486            ),
 487            "JSONB_EXISTS": lambda self: self._parse_jsonb_exists(),
 488        }
 489
 490        BITWISE = {
 491            **parser.Parser.BITWISE,
 492            TokenType.HASH: exp.BitwiseXor,
 493        }
 494
 495        EXPONENT = {
 496            TokenType.CARET: exp.Pow,
 497        }
 498
 499        RANGE_PARSERS = {
 500            **parser.Parser.RANGE_PARSERS,
 501            TokenType.DAMP: binary_range_parser(exp.ArrayOverlaps),
 502            TokenType.DAT: lambda self, this: self.expression(
 503                exp.MatchAgainst, this=self._parse_bitwise(), expressions=[this]
 504            ),
 505        }
 506
 507        STATEMENT_PARSERS = {
 508            **parser.Parser.STATEMENT_PARSERS,
 509            TokenType.END: lambda self: self._parse_commit_or_rollback(),
 510        }
 511
 512        UNARY_PARSERS = {
 513            **parser.Parser.UNARY_PARSERS,
 514            # The `~` token is remapped from TILDE to RLIKE in Postgres due to the binary REGEXP LIKE operator
 515            TokenType.RLIKE: lambda self: self.expression(exp.BitwiseNot, this=self._parse_unary()),
 516        }
 517
 518        JSON_ARROWS_REQUIRE_JSON_TYPE = True
 519
 520        COLUMN_OPERATORS = {
 521            **parser.Parser.COLUMN_OPERATORS,
 522            TokenType.ARROW: lambda self, this, path: self.validate_expression(
 523                build_json_extract_path(
 524                    exp.JSONExtract, arrow_req_json_type=self.JSON_ARROWS_REQUIRE_JSON_TYPE
 525                )([this, path])
 526            ),
 527            TokenType.DARROW: lambda self, this, path: self.validate_expression(
 528                build_json_extract_path(
 529                    exp.JSONExtractScalar, arrow_req_json_type=self.JSON_ARROWS_REQUIRE_JSON_TYPE
 530                )([this, path])
 531            ),
 532        }
 533
 534        ARG_MODE_TOKENS = {TokenType.IN, TokenType.OUT, TokenType.INOUT, TokenType.VARIADIC}
 535
 536        def _parse_parameter_mode(self) -> t.Optional[TokenType]:
 537            """
 538            Parse PostgreSQL function parameter mode (IN, OUT, INOUT, VARIADIC).
 539
 540            Disambiguates between mode keywords and identifiers with the same name:
 541            - MODE TYPE      → keyword is identifier (e.g., "out INT")
 542            - MODE NAME TYPE → keyword is mode (e.g., "OUT x INT")
 543
 544            Returns:
 545                Mode token type if current token is a mode keyword, None otherwise.
 546            """
 547            if not self._match_set(self.ARG_MODE_TOKENS, advance=False) or not self._next:
 548                return None
 549
 550            mode_token = self._curr
 551
 552            # Check Pattern 1: MODE TYPE
 553            # Try parsing next token as a built-in type (not UDT)
 554            # If successful, the keyword is an identifier, not a mode
 555            is_followed_by_builtin_type = self._try_parse(
 556                lambda: self._advance()  # type: ignore
 557                or self._parse_types(check_func=False, allow_identifiers=False),
 558                retreat=True,
 559            )
 560            if is_followed_by_builtin_type:
 561                return None  # Pattern: "out INT" → out is parameter name
 562
 563            # Check Pattern 2: MODE NAME TYPE
 564            # If next token is an identifier, check if there's a type after it
 565            # The type can be built-in or user-defined (allow_identifiers=True)
 566            if self._next.token_type not in self.ID_VAR_TOKENS:
 567                return None
 568
 569            is_followed_by_any_type = self._try_parse(
 570                lambda: self._advance(2)  # type: ignore
 571                or self._parse_types(check_func=False, allow_identifiers=True),
 572                retreat=True,
 573            )
 574
 575            if is_followed_by_any_type:
 576                return mode_token.token_type  # Pattern: "OUT x INT" → OUT is mode
 577
 578            return None
 579
 580        def _create_mode_constraint(self, param_mode: TokenType) -> exp.InOutColumnConstraint:
 581            """
 582            Create parameter mode constraint for function parameters.
 583
 584            Args:
 585                param_mode: The parameter mode token (IN, OUT, INOUT, or VARIADIC).
 586
 587            Returns:
 588                InOutColumnConstraint expression representing the parameter mode.
 589            """
 590            return self.expression(
 591                exp.InOutColumnConstraint,
 592                input_=(param_mode in {TokenType.IN, TokenType.INOUT}),
 593                output=(param_mode in {TokenType.OUT, TokenType.INOUT}),
 594                variadic=(param_mode == TokenType.VARIADIC),
 595            )
 596
 597        def _parse_function_parameter(self) -> t.Optional[exp.Expression]:
 598            param_mode = self._parse_parameter_mode()
 599
 600            if param_mode:
 601                self._advance()
 602
 603            # Parse parameter name and type
 604            param_name = self._parse_id_var()
 605            column_def = self._parse_column_def(this=param_name, computed_column=False)
 606
 607            # Attach mode as constraint
 608            if param_mode and column_def:
 609                constraint = self._create_mode_constraint(param_mode)
 610                if not column_def.args.get("constraints"):
 611                    column_def.set("constraints", [])
 612                column_def.args["constraints"].insert(0, constraint)
 613
 614            return column_def
 615
 616        def _parse_query_parameter(self) -> t.Optional[exp.Expression]:
 617            this = (
 618                self._parse_wrapped(self._parse_id_var)
 619                if self._match(TokenType.L_PAREN, advance=False)
 620                else None
 621            )
 622            self._match_text_seq("S")
 623            return self.expression(exp.Placeholder, this=this)
 624
 625        def _parse_date_part(self) -> exp.Expression:
 626            part = self._parse_type()
 627            self._match(TokenType.COMMA)
 628            value = self._parse_bitwise()
 629
 630            if part and isinstance(part, (exp.Column, exp.Literal)):
 631                part = exp.var(part.name)
 632
 633            return self.expression(exp.Extract, this=part, expression=value)
 634
 635        def _parse_unique_key(self) -> t.Optional[exp.Expression]:
 636            return None
 637
 638        def _parse_jsonb_exists(self) -> exp.JSONBExists:
 639            return self.expression(
 640                exp.JSONBExists,
 641                this=self._parse_bitwise(),
 642                path=self._match(TokenType.COMMA)
 643                and self.dialect.to_json_path(self._parse_bitwise()),
 644            )
 645
 646        def _parse_generated_as_identity(
 647            self,
 648        ) -> (
 649            exp.GeneratedAsIdentityColumnConstraint
 650            | exp.ComputedColumnConstraint
 651            | exp.GeneratedAsRowColumnConstraint
 652        ):
 653            this = super()._parse_generated_as_identity()
 654
 655            if self._match_text_seq("STORED"):
 656                this = self.expression(exp.ComputedColumnConstraint, this=this.expression)
 657
 658            return this
 659
 660        def _parse_user_defined_type(
 661            self, identifier: exp.Identifier
 662        ) -> t.Optional[exp.Expression]:
 663            udt_type: exp.Identifier | exp.Dot = identifier
 664
 665            while self._match(TokenType.DOT):
 666                part = self._parse_id_var()
 667                if part:
 668                    udt_type = exp.Dot(this=udt_type, expression=part)
 669
 670            return exp.DataType.build(udt_type, udt=True)
 671
 672    class Generator(generator.Generator):
 673        SINGLE_STRING_INTERVAL = True
 674        RENAME_TABLE_WITH_DB = False
 675        LOCKING_READS_SUPPORTED = True
 676        JOIN_HINTS = False
 677        TABLE_HINTS = False
 678        QUERY_HINTS = False
 679        NVL2_SUPPORTED = False
 680        PARAMETER_TOKEN = "$"
 681        NAMED_PLACEHOLDER_TOKEN = "%"
 682        TABLESAMPLE_SIZE_IS_ROWS = False
 683        TABLESAMPLE_SEED_KEYWORD = "REPEATABLE"
 684        SUPPORTS_SELECT_INTO = True
 685        JSON_TYPE_REQUIRED_FOR_EXTRACTION = True
 686        SUPPORTS_UNLOGGED_TABLES = True
 687        LIKE_PROPERTY_INSIDE_SCHEMA = True
 688        MULTI_ARG_DISTINCT = False
 689        CAN_IMPLEMENT_ARRAY_ANY = True
 690        SUPPORTS_WINDOW_EXCLUDE = True
 691        COPY_HAS_INTO_KEYWORD = False
 692        ARRAY_CONCAT_IS_VAR_LEN = False
 693        SUPPORTS_MEDIAN = False
 694        ARRAY_SIZE_DIM_REQUIRED = True
 695        SUPPORTS_BETWEEN_FLAGS = True
 696        INOUT_SEPARATOR = ""  # PostgreSQL uses "INOUT" (no space)
 697
 698        SUPPORTED_JSON_PATH_PARTS = {
 699            exp.JSONPathKey,
 700            exp.JSONPathRoot,
 701            exp.JSONPathSubscript,
 702        }
 703
 704        def lateral_sql(self, expression: exp.Lateral) -> str:
 705            sql = super().lateral_sql(expression)
 706
 707            if expression.args.get("cross_apply") is not None:
 708                sql = f"{sql} ON TRUE"
 709
 710            return sql
 711
 712        TYPE_MAPPING = {
 713            **generator.Generator.TYPE_MAPPING,
 714            exp.DataType.Type.TINYINT: "SMALLINT",
 715            exp.DataType.Type.FLOAT: "REAL",
 716            exp.DataType.Type.DOUBLE: "DOUBLE PRECISION",
 717            exp.DataType.Type.BINARY: "BYTEA",
 718            exp.DataType.Type.VARBINARY: "BYTEA",
 719            exp.DataType.Type.ROWVERSION: "BYTEA",
 720            exp.DataType.Type.DATETIME: "TIMESTAMP",
 721            exp.DataType.Type.TIMESTAMPNTZ: "TIMESTAMP",
 722            exp.DataType.Type.BLOB: "BYTEA",
 723        }
 724
 725        TRANSFORMS = {
 726            **generator.Generator.TRANSFORMS,
 727            exp.AnyValue: _versioned_anyvalue_sql,
 728            exp.ArrayConcat: array_concat_sql("ARRAY_CAT"),
 729            exp.ArrayFilter: filter_array_using_unnest,
 730            exp.ArrayAppend: array_append_sql("ARRAY_APPEND"),
 731            exp.ArrayPrepend: array_append_sql("ARRAY_PREPEND", swap_params=True),
 732            exp.BitwiseAndAgg: rename_func("BIT_AND"),
 733            exp.BitwiseOrAgg: rename_func("BIT_OR"),
 734            exp.BitwiseXor: lambda self, e: self.binary(e, "#"),
 735            exp.BitwiseXorAgg: rename_func("BIT_XOR"),
 736            exp.ColumnDef: transforms.preprocess([_auto_increment_to_serial, _serial_to_generated]),
 737            exp.CurrentDate: no_paren_current_date_sql,
 738            exp.CurrentTimestamp: lambda *_: "CURRENT_TIMESTAMP",
 739            exp.CurrentUser: lambda *_: "CURRENT_USER",
 740            exp.DateAdd: _date_add_sql("+"),
 741            exp.DateDiff: _date_diff_sql,
 742            exp.DateStrToDate: datestrtodate_sql,
 743            exp.DateSub: _date_add_sql("-"),
 744            exp.Explode: rename_func("UNNEST"),
 745            exp.ExplodingGenerateSeries: rename_func("GENERATE_SERIES"),
 746            exp.Getbit: getbit_sql,
 747            exp.GroupConcat: lambda self, e: groupconcat_sql(
 748                self, e, func_name="STRING_AGG", within_group=False
 749            ),
 750            exp.IntDiv: rename_func("DIV"),
 751            exp.JSONArrayAgg: lambda self, e: self.func(
 752                "JSON_AGG",
 753                self.sql(e, "this"),
 754                suffix=f"{self.sql(e, 'order')})",
 755            ),
 756            exp.JSONExtract: _json_extract_sql("JSON_EXTRACT_PATH", "->"),
 757            exp.JSONExtractScalar: _json_extract_sql("JSON_EXTRACT_PATH_TEXT", "->>"),
 758            exp.JSONBExtract: lambda self, e: self.binary(e, "#>"),
 759            exp.JSONBExtractScalar: lambda self, e: self.binary(e, "#>>"),
 760            exp.JSONBContains: lambda self, e: self.binary(e, "?"),
 761            exp.ParseJSON: lambda self, e: self.sql(exp.cast(e.this, exp.DataType.Type.JSON)),
 762            exp.JSONPathKey: json_path_key_only_name,
 763            exp.JSONPathRoot: lambda *_: "",
 764            exp.JSONPathSubscript: lambda self, e: self.json_path_part(e.this),
 765            exp.LastDay: no_last_day_sql,
 766            exp.LogicalOr: rename_func("BOOL_OR"),
 767            exp.LogicalAnd: rename_func("BOOL_AND"),
 768            exp.Max: max_or_greatest,
 769            exp.MapFromEntries: no_map_from_entries_sql,
 770            exp.Min: min_or_least,
 771            exp.Merge: merge_without_target_sql,
 772            exp.PartitionedByProperty: lambda self, e: f"PARTITION BY {self.sql(e, 'this')}",
 773            exp.PercentileCont: transforms.preprocess(
 774                [transforms.add_within_group_for_percentiles]
 775            ),
 776            exp.PercentileDisc: transforms.preprocess(
 777                [transforms.add_within_group_for_percentiles]
 778            ),
 779            exp.Pivot: no_pivot_sql,
 780            exp.Rand: rename_func("RANDOM"),
 781            exp.RegexpLike: lambda self, e: self.binary(e, "~"),
 782            exp.RegexpILike: lambda self, e: self.binary(e, "~*"),
 783            exp.RegexpReplace: lambda self, e: self.func(
 784                "REGEXP_REPLACE",
 785                e.this,
 786                e.expression,
 787                e.args.get("replacement"),
 788                e.args.get("position"),
 789                e.args.get("occurrence"),
 790                regexp_replace_global_modifier(e),
 791            ),
 792            exp.Round: _round_sql,
 793            exp.Select: transforms.preprocess(
 794                [
 795                    transforms.eliminate_semi_and_anti_joins,
 796                    transforms.eliminate_qualify,
 797                ]
 798            ),
 799            exp.SHA2: sha256_sql,
 800            exp.SHA2Digest: sha2_digest_sql,
 801            exp.StrPosition: lambda self, e: strposition_sql(self, e, func_name="POSITION"),
 802            exp.StrToDate: lambda self, e: self.func("TO_DATE", e.this, self.format_time(e)),
 803            exp.StrToTime: lambda self, e: self.func("TO_TIMESTAMP", e.this, self.format_time(e)),
 804            exp.StructExtract: struct_extract_sql,
 805            exp.Substring: _substring_sql,
 806            exp.TimeFromParts: rename_func("MAKE_TIME"),
 807            exp.TimestampFromParts: rename_func("MAKE_TIMESTAMP"),
 808            exp.TimestampTrunc: timestamptrunc_sql(zone=True),
 809            exp.TimeStrToTime: timestrtotime_sql,
 810            exp.TimeToStr: lambda self, e: self.func("TO_CHAR", e.this, self.format_time(e)),
 811            exp.ToChar: lambda self, e: self.function_fallback_sql(e)
 812            if e.args.get("format")
 813            else self.tochar_sql(e),
 814            exp.Trim: trim_sql,
 815            exp.TryCast: no_trycast_sql,
 816            exp.TsOrDsAdd: _date_add_sql("+"),
 817            exp.TsOrDsDiff: _date_diff_sql,
 818            exp.UnixToTime: lambda self, e: self.func("TO_TIMESTAMP", e.this),
 819            exp.Uuid: lambda *_: "GEN_RANDOM_UUID()",
 820            exp.TimeToUnix: lambda self, e: self.func(
 821                "DATE_PART", exp.Literal.string("epoch"), e.this
 822            ),
 823            exp.VariancePop: rename_func("VAR_POP"),
 824            exp.Variance: rename_func("VAR_SAMP"),
 825            exp.Xor: bool_xor_sql,
 826            exp.Unicode: rename_func("ASCII"),
 827            exp.UnixToTime: _unix_to_time_sql,
 828            exp.Levenshtein: _levenshtein_sql,
 829            exp.JSONObjectAgg: rename_func("JSON_OBJECT_AGG"),
 830            exp.JSONBObjectAgg: rename_func("JSONB_OBJECT_AGG"),
 831            exp.CountIf: count_if_to_sum,
 832        }
 833
 834        TRANSFORMS.pop(exp.CommentColumnConstraint)
 835
 836        PROPERTIES_LOCATION = {
 837            **generator.Generator.PROPERTIES_LOCATION,
 838            exp.PartitionedByProperty: exp.Properties.Location.POST_SCHEMA,
 839            exp.TransientProperty: exp.Properties.Location.UNSUPPORTED,
 840            exp.VolatileProperty: exp.Properties.Location.UNSUPPORTED,
 841        }
 842
 843        def schemacommentproperty_sql(self, expression: exp.SchemaCommentProperty) -> str:
 844            self.unsupported("Table comments are not supported in the CREATE statement")
 845            return ""
 846
 847        def commentcolumnconstraint_sql(self, expression: exp.CommentColumnConstraint) -> str:
 848            self.unsupported("Column comments are not supported in the CREATE statement")
 849            return ""
 850
 851        def columndef_sql(self, expression: exp.ColumnDef, sep: str = " ") -> str:
 852            # PostgreSQL places parameter modes BEFORE parameter name
 853            param_constraint = expression.find(exp.InOutColumnConstraint)
 854
 855            if param_constraint:
 856                mode_sql = self.sql(param_constraint)
 857                param_constraint.pop()  # Remove to prevent double-rendering
 858                base_sql = super().columndef_sql(expression, sep)
 859                return f"{mode_sql} {base_sql}"
 860
 861            return super().columndef_sql(expression, sep)
 862
 863        def unnest_sql(self, expression: exp.Unnest) -> str:
 864            if len(expression.expressions) == 1:
 865                arg = expression.expressions[0]
 866                if isinstance(arg, exp.GenerateDateArray):
 867                    generate_series: exp.Expression = exp.GenerateSeries(**arg.args)
 868                    if isinstance(expression.parent, (exp.From, exp.Join)):
 869                        generate_series = (
 870                            exp.select("value::date")
 871                            .from_(exp.Table(this=generate_series).as_("_t", table=["value"]))
 872                            .subquery(expression.args.get("alias") or "_unnested_generate_series")
 873                        )
 874                    return self.sql(generate_series)
 875
 876                from sqlglot.optimizer.annotate_types import annotate_types
 877
 878                this = annotate_types(arg, dialect=self.dialect)
 879                if this.is_type("array<json>"):
 880                    while isinstance(this, exp.Cast):
 881                        this = this.this
 882
 883                    arg_as_json = self.sql(exp.cast(this, exp.DataType.Type.JSON))
 884                    alias = self.sql(expression, "alias")
 885                    alias = f" AS {alias}" if alias else ""
 886
 887                    if expression.args.get("offset"):
 888                        self.unsupported("Unsupported JSON_ARRAY_ELEMENTS with offset")
 889
 890                    return f"JSON_ARRAY_ELEMENTS({arg_as_json}){alias}"
 891
 892            return super().unnest_sql(expression)
 893
 894        def bracket_sql(self, expression: exp.Bracket) -> str:
 895            """Forms like ARRAY[1, 2, 3][3] aren't allowed; we need to wrap the ARRAY."""
 896            if isinstance(expression.this, exp.Array):
 897                expression.set("this", exp.paren(expression.this, copy=False))
 898
 899            return super().bracket_sql(expression)
 900
 901        def matchagainst_sql(self, expression: exp.MatchAgainst) -> str:
 902            this = self.sql(expression, "this")
 903            expressions = [f"{self.sql(e)} @@ {this}" for e in expression.expressions]
 904            sql = " OR ".join(expressions)
 905            return f"({sql})" if len(expressions) > 1 else sql
 906
 907        def alterset_sql(self, expression: exp.AlterSet) -> str:
 908            exprs = self.expressions(expression, flat=True)
 909            exprs = f"({exprs})" if exprs else ""
 910
 911            access_method = self.sql(expression, "access_method")
 912            access_method = f"ACCESS METHOD {access_method}" if access_method else ""
 913            tablespace = self.sql(expression, "tablespace")
 914            tablespace = f"TABLESPACE {tablespace}" if tablespace else ""
 915            option = self.sql(expression, "option")
 916
 917            return f"SET {exprs}{access_method}{tablespace}{option}"
 918
 919        def datatype_sql(self, expression: exp.DataType) -> str:
 920            if expression.is_type(exp.DataType.Type.ARRAY):
 921                if expression.expressions:
 922                    values = self.expressions(expression, key="values", flat=True)
 923                    return f"{self.expressions(expression, flat=True)}[{values}]"
 924                return "ARRAY"
 925
 926            if (
 927                expression.is_type(exp.DataType.Type.DOUBLE, exp.DataType.Type.FLOAT)
 928                and expression.expressions
 929            ):
 930                # Postgres doesn't support precision for REAL and DOUBLE PRECISION types
 931                return f"FLOAT({self.expressions(expression, flat=True)})"
 932
 933            return super().datatype_sql(expression)
 934
 935        def cast_sql(self, expression: exp.Cast, safe_prefix: t.Optional[str] = None) -> str:
 936            this = expression.this
 937
 938            # Postgres casts DIV() to decimal for transpilation but when roundtripping it's superfluous
 939            if isinstance(this, exp.IntDiv) and expression.to == exp.DataType.build("decimal"):
 940                return self.sql(this)
 941
 942            return super().cast_sql(expression, safe_prefix=safe_prefix)
 943
 944        def array_sql(self, expression: exp.Array) -> str:
 945            exprs = expression.expressions
 946            func_name = self.normalize_func("ARRAY")
 947
 948            if isinstance(seq_get(exprs, 0), exp.Select):
 949                return f"{func_name}({self.sql(exprs[0])})"
 950
 951            return f"{func_name}{inline_array_sql(self, expression)}"
 952
 953        def computedcolumnconstraint_sql(self, expression: exp.ComputedColumnConstraint) -> str:
 954            return f"GENERATED ALWAYS AS ({self.sql(expression, 'this')}) STORED"
 955
 956        def isascii_sql(self, expression: exp.IsAscii) -> str:
 957            return f"({self.sql(expression.this)} ~ '^[[:ascii:]]*$')"
 958
 959        def ignorenulls_sql(self, expression: exp.IgnoreNulls) -> str:
 960            # https://www.postgresql.org/docs/current/functions-window.html
 961            self.unsupported("PostgreSQL does not support IGNORE NULLS.")
 962            return self.sql(expression.this)
 963
 964        def respectnulls_sql(self, expression: exp.RespectNulls) -> str:
 965            # https://www.postgresql.org/docs/current/functions-window.html
 966            self.unsupported("PostgreSQL does not support RESPECT NULLS.")
 967            return self.sql(expression.this)
 968
 969        @unsupported_args("this")
 970        def currentschema_sql(self, expression: exp.CurrentSchema) -> str:
 971            return "CURRENT_SCHEMA"
 972
 973        def interval_sql(self, expression: exp.Interval) -> str:
 974            unit = expression.text("unit").lower()
 975
 976            this = expression.this
 977            if unit.startswith("quarter") and isinstance(this, exp.Literal):
 978                this.replace(exp.Literal.string(int(this.to_py()) * 3))
 979                expression.args["unit"].replace(exp.var("MONTH"))
 980
 981            return super().interval_sql(expression)
 982
 983        def placeholder_sql(self, expression: exp.Placeholder) -> str:
 984            if expression.args.get("jdbc"):
 985                return "?"
 986
 987            this = f"({expression.name})" if expression.this else ""
 988            return f"{self.NAMED_PLACEHOLDER_TOKEN}{this}s"
 989
 990        def arraycontains_sql(self, expression: exp.ArrayContains) -> str:
 991            # Convert DuckDB's LIST_CONTAINS(array, value) to PostgreSQL
 992            # DuckDB behavior:
 993            #   - LIST_CONTAINS([1,2,3], 2) -> true
 994            #   - LIST_CONTAINS([1,2,3], 4) -> false
 995            #   - LIST_CONTAINS([1,2,NULL], 4) -> false (not NULL)
 996            #   - LIST_CONTAINS([1,2,3], NULL) -> NULL
 997            #
 998            # PostgreSQL equivalent: CASE WHEN value IS NULL THEN NULL
 999            #                            ELSE COALESCE(value = ANY(array), FALSE) END
1000            value = expression.expression
1001            array = expression.this
1002
1003            coalesce_expr = exp.Coalesce(
1004                this=value.eq(exp.Any(this=exp.paren(expression=array, copy=False))),
1005                expressions=[exp.false()],
1006            )
1007
1008            case_expr = (
1009                exp.Case()
1010                .when(exp.Is(this=value, expression=exp.null()), exp.null(), copy=False)
1011                .else_(coalesce_expr, copy=False)
1012            )
1013
1014            return self.sql(case_expr)
DATE_DIFF_FACTOR = {'MICROSECOND': ' * 1000000', 'MILLISECOND': ' * 1000', 'SECOND': '', 'MINUTE': ' / 60', 'HOUR': ' / 3600', 'DAY': ' / 86400'}
class Postgres(sqlglot.dialects.dialect.Dialect):
 298class Postgres(Dialect):
 299    INDEX_OFFSET = 1
 300    TYPED_DIVISION = True
 301    CONCAT_COALESCE = True
 302    NULL_ORDERING = "nulls_are_large"
 303    TIME_FORMAT = "'YYYY-MM-DD HH24:MI:SS'"
 304    TABLESAMPLE_SIZE_IS_PERCENT = True
 305    TABLES_REFERENCEABLE_AS_COLUMNS = True
 306
 307    DEFAULT_FUNCTIONS_COLUMN_NAMES = {
 308        exp.ExplodingGenerateSeries: "generate_series",
 309    }
 310
 311    TIME_MAPPING = {
 312        "d": "%u",  # 1-based day of week
 313        "D": "%u",  # 1-based day of week
 314        "dd": "%d",  # day of month
 315        "DD": "%d",  # day of month
 316        "ddd": "%j",  # zero padded day of year
 317        "DDD": "%j",  # zero padded day of year
 318        "FMDD": "%-d",  # - is no leading zero for Python; same for FM in postgres
 319        "FMDDD": "%-j",  # day of year
 320        "FMHH12": "%-I",  # 9
 321        "FMHH24": "%-H",  # 9
 322        "FMMI": "%-M",  # Minute
 323        "FMMM": "%-m",  # 1
 324        "FMSS": "%-S",  # Second
 325        "HH12": "%I",  # 09
 326        "HH24": "%H",  # 09
 327        "mi": "%M",  # zero padded minute
 328        "MI": "%M",  # zero padded minute
 329        "mm": "%m",  # 01
 330        "MM": "%m",  # 01
 331        "OF": "%z",  # utc offset
 332        "ss": "%S",  # zero padded second
 333        "SS": "%S",  # zero padded second
 334        "TMDay": "%A",  # TM is locale dependent
 335        "TMDy": "%a",
 336        "TMMon": "%b",  # Sep
 337        "TMMonth": "%B",  # September
 338        "TZ": "%Z",  # uppercase timezone name
 339        "US": "%f",  # zero padded microsecond
 340        "ww": "%U",  # 1-based week of year
 341        "WW": "%U",  # 1-based week of year
 342        "yy": "%y",  # 15
 343        "YY": "%y",  # 15
 344        "yyyy": "%Y",  # 2015
 345        "YYYY": "%Y",  # 2015
 346    }
 347
 348    class Tokenizer(tokens.Tokenizer):
 349        BIT_STRINGS = [("b'", "'"), ("B'", "'")]
 350        HEX_STRINGS = [("x'", "'"), ("X'", "'")]
 351        BYTE_STRINGS = [("e'", "'"), ("E'", "'")]
 352        BYTE_STRING_ESCAPES = ["'", "\\"]
 353        HEREDOC_STRINGS = ["$"]
 354
 355        HEREDOC_TAG_IS_IDENTIFIER = True
 356        HEREDOC_STRING_ALTERNATIVE = TokenType.PARAMETER
 357
 358        KEYWORDS = {
 359            **tokens.Tokenizer.KEYWORDS,
 360            "~": TokenType.RLIKE,
 361            "@@": TokenType.DAT,
 362            "@>": TokenType.AT_GT,
 363            "<@": TokenType.LT_AT,
 364            "?&": TokenType.QMARK_AMP,
 365            "?|": TokenType.QMARK_PIPE,
 366            "#-": TokenType.HASH_DASH,
 367            "|/": TokenType.PIPE_SLASH,
 368            "||/": TokenType.DPIPE_SLASH,
 369            "BEGIN": TokenType.BEGIN,
 370            "BIGSERIAL": TokenType.BIGSERIAL,
 371            "CONSTRAINT TRIGGER": TokenType.COMMAND,
 372            "CSTRING": TokenType.PSEUDO_TYPE,
 373            "DECLARE": TokenType.COMMAND,
 374            "DO": TokenType.COMMAND,
 375            "EXEC": TokenType.COMMAND,
 376            "HSTORE": TokenType.HSTORE,
 377            "INT8": TokenType.BIGINT,
 378            "MONEY": TokenType.MONEY,
 379            "NAME": TokenType.NAME,
 380            "OID": TokenType.OBJECT_IDENTIFIER,
 381            "ONLY": TokenType.ONLY,
 382            "POINT": TokenType.POINT,
 383            "REFRESH": TokenType.COMMAND,
 384            "REINDEX": TokenType.COMMAND,
 385            "RESET": TokenType.COMMAND,
 386            "SERIAL": TokenType.SERIAL,
 387            "SMALLSERIAL": TokenType.SMALLSERIAL,
 388            "TEMP": TokenType.TEMPORARY,
 389            "REGCLASS": TokenType.OBJECT_IDENTIFIER,
 390            "REGCOLLATION": TokenType.OBJECT_IDENTIFIER,
 391            "REGCONFIG": TokenType.OBJECT_IDENTIFIER,
 392            "REGDICTIONARY": TokenType.OBJECT_IDENTIFIER,
 393            "REGNAMESPACE": TokenType.OBJECT_IDENTIFIER,
 394            "REGOPER": TokenType.OBJECT_IDENTIFIER,
 395            "REGOPERATOR": TokenType.OBJECT_IDENTIFIER,
 396            "REGPROC": TokenType.OBJECT_IDENTIFIER,
 397            "REGPROCEDURE": TokenType.OBJECT_IDENTIFIER,
 398            "REGROLE": TokenType.OBJECT_IDENTIFIER,
 399            "REGTYPE": TokenType.OBJECT_IDENTIFIER,
 400            "FLOAT": TokenType.DOUBLE,
 401            "XML": TokenType.XML,
 402            "VARIADIC": TokenType.VARIADIC,
 403            "INOUT": TokenType.INOUT,
 404        }
 405        KEYWORDS.pop("/*+")
 406        KEYWORDS.pop("DIV")
 407
 408        SINGLE_TOKENS = {
 409            **tokens.Tokenizer.SINGLE_TOKENS,
 410            "$": TokenType.HEREDOC_STRING,
 411        }
 412
 413        VAR_SINGLE_TOKENS = {"$"}
 414
 415    class Parser(parser.Parser):
 416        SUPPORTS_OMITTED_INTERVAL_SPAN_UNIT = True
 417
 418        PROPERTY_PARSERS = {
 419            **parser.Parser.PROPERTY_PARSERS,
 420            "SET": lambda self: self.expression(exp.SetConfigProperty, this=self._parse_set()),
 421        }
 422        PROPERTY_PARSERS.pop("INPUT")
 423
 424        PLACEHOLDER_PARSERS = {
 425            **parser.Parser.PLACEHOLDER_PARSERS,
 426            TokenType.PLACEHOLDER: lambda self: self.expression(exp.Placeholder, jdbc=True),
 427            TokenType.MOD: lambda self: self._parse_query_parameter(),
 428        }
 429
 430        FUNCTIONS = {
 431            **parser.Parser.FUNCTIONS,
 432            "ARRAY_PREPEND": lambda args: exp.ArrayPrepend(
 433                this=seq_get(args, 1), expression=seq_get(args, 0)
 434            ),
 435            "BIT_AND": exp.BitwiseAndAgg.from_arg_list,
 436            "BIT_OR": exp.BitwiseOrAgg.from_arg_list,
 437            "BIT_XOR": exp.BitwiseXorAgg.from_arg_list,
 438            "DATE_TRUNC": build_timestamp_trunc,
 439            "DIV": lambda args: exp.cast(
 440                binary_from_function(exp.IntDiv)(args), exp.DataType.Type.DECIMAL
 441            ),
 442            "GENERATE_SERIES": _build_generate_series,
 443            "GET_BIT": lambda args: exp.Getbit(
 444                this=seq_get(args, 0), expression=seq_get(args, 1), zero_is_msb=True
 445            ),
 446            "JSON_EXTRACT_PATH": build_json_extract_path(exp.JSONExtract),
 447            "JSON_EXTRACT_PATH_TEXT": build_json_extract_path(exp.JSONExtractScalar),
 448            "LENGTH": lambda args: exp.Length(this=seq_get(args, 0), encoding=seq_get(args, 1)),
 449            "MAKE_TIME": exp.TimeFromParts.from_arg_list,
 450            "MAKE_TIMESTAMP": exp.TimestampFromParts.from_arg_list,
 451            "NOW": exp.CurrentTimestamp.from_arg_list,
 452            "REGEXP_REPLACE": _build_regexp_replace,
 453            "TO_CHAR": build_formatted_time(exp.TimeToStr, "postgres"),
 454            "TO_DATE": build_formatted_time(exp.StrToDate, "postgres"),
 455            "TO_TIMESTAMP": _build_to_timestamp,
 456            "UNNEST": exp.Explode.from_arg_list,
 457            "SHA256": lambda args: exp.SHA2(this=seq_get(args, 0), length=exp.Literal.number(256)),
 458            "SHA384": lambda args: exp.SHA2(this=seq_get(args, 0), length=exp.Literal.number(384)),
 459            "SHA512": lambda args: exp.SHA2(this=seq_get(args, 0), length=exp.Literal.number(512)),
 460            "LEVENSHTEIN_LESS_EQUAL": _build_levenshtein_less_equal,
 461            "JSON_OBJECT_AGG": lambda args: exp.JSONObjectAgg(expressions=args),
 462            "JSONB_OBJECT_AGG": exp.JSONBObjectAgg.from_arg_list,
 463            "WIDTH_BUCKET": lambda args: exp.WidthBucket(
 464                this=seq_get(args, 0), threshold=seq_get(args, 1)
 465            )
 466            if len(args) == 2
 467            else exp.WidthBucket.from_arg_list(args),
 468        }
 469
 470        NO_PAREN_FUNCTION_PARSERS = {
 471            **parser.Parser.NO_PAREN_FUNCTION_PARSERS,
 472            "VARIADIC": lambda self: self.expression(exp.Variadic, this=self._parse_bitwise()),
 473        }
 474
 475        NO_PAREN_FUNCTIONS = {
 476            **parser.Parser.NO_PAREN_FUNCTIONS,
 477            TokenType.CURRENT_SCHEMA: exp.CurrentSchema,
 478        }
 479
 480        FUNCTION_PARSERS = {
 481            **parser.Parser.FUNCTION_PARSERS,
 482            "DATE_PART": lambda self: self._parse_date_part(),
 483            "JSON_AGG": lambda self: self.expression(
 484                exp.JSONArrayAgg,
 485                this=self._parse_lambda(),
 486                order=self._parse_order(),
 487            ),
 488            "JSONB_EXISTS": lambda self: self._parse_jsonb_exists(),
 489        }
 490
 491        BITWISE = {
 492            **parser.Parser.BITWISE,
 493            TokenType.HASH: exp.BitwiseXor,
 494        }
 495
 496        EXPONENT = {
 497            TokenType.CARET: exp.Pow,
 498        }
 499
 500        RANGE_PARSERS = {
 501            **parser.Parser.RANGE_PARSERS,
 502            TokenType.DAMP: binary_range_parser(exp.ArrayOverlaps),
 503            TokenType.DAT: lambda self, this: self.expression(
 504                exp.MatchAgainst, this=self._parse_bitwise(), expressions=[this]
 505            ),
 506        }
 507
 508        STATEMENT_PARSERS = {
 509            **parser.Parser.STATEMENT_PARSERS,
 510            TokenType.END: lambda self: self._parse_commit_or_rollback(),
 511        }
 512
 513        UNARY_PARSERS = {
 514            **parser.Parser.UNARY_PARSERS,
 515            # The `~` token is remapped from TILDE to RLIKE in Postgres due to the binary REGEXP LIKE operator
 516            TokenType.RLIKE: lambda self: self.expression(exp.BitwiseNot, this=self._parse_unary()),
 517        }
 518
 519        JSON_ARROWS_REQUIRE_JSON_TYPE = True
 520
 521        COLUMN_OPERATORS = {
 522            **parser.Parser.COLUMN_OPERATORS,
 523            TokenType.ARROW: lambda self, this, path: self.validate_expression(
 524                build_json_extract_path(
 525                    exp.JSONExtract, arrow_req_json_type=self.JSON_ARROWS_REQUIRE_JSON_TYPE
 526                )([this, path])
 527            ),
 528            TokenType.DARROW: lambda self, this, path: self.validate_expression(
 529                build_json_extract_path(
 530                    exp.JSONExtractScalar, arrow_req_json_type=self.JSON_ARROWS_REQUIRE_JSON_TYPE
 531                )([this, path])
 532            ),
 533        }
 534
 535        ARG_MODE_TOKENS = {TokenType.IN, TokenType.OUT, TokenType.INOUT, TokenType.VARIADIC}
 536
 537        def _parse_parameter_mode(self) -> t.Optional[TokenType]:
 538            """
 539            Parse PostgreSQL function parameter mode (IN, OUT, INOUT, VARIADIC).
 540
 541            Disambiguates between mode keywords and identifiers with the same name:
 542            - MODE TYPE      → keyword is identifier (e.g., "out INT")
 543            - MODE NAME TYPE → keyword is mode (e.g., "OUT x INT")
 544
 545            Returns:
 546                Mode token type if current token is a mode keyword, None otherwise.
 547            """
 548            if not self._match_set(self.ARG_MODE_TOKENS, advance=False) or not self._next:
 549                return None
 550
 551            mode_token = self._curr
 552
 553            # Check Pattern 1: MODE TYPE
 554            # Try parsing next token as a built-in type (not UDT)
 555            # If successful, the keyword is an identifier, not a mode
 556            is_followed_by_builtin_type = self._try_parse(
 557                lambda: self._advance()  # type: ignore
 558                or self._parse_types(check_func=False, allow_identifiers=False),
 559                retreat=True,
 560            )
 561            if is_followed_by_builtin_type:
 562                return None  # Pattern: "out INT" → out is parameter name
 563
 564            # Check Pattern 2: MODE NAME TYPE
 565            # If next token is an identifier, check if there's a type after it
 566            # The type can be built-in or user-defined (allow_identifiers=True)
 567            if self._next.token_type not in self.ID_VAR_TOKENS:
 568                return None
 569
 570            is_followed_by_any_type = self._try_parse(
 571                lambda: self._advance(2)  # type: ignore
 572                or self._parse_types(check_func=False, allow_identifiers=True),
 573                retreat=True,
 574            )
 575
 576            if is_followed_by_any_type:
 577                return mode_token.token_type  # Pattern: "OUT x INT" → OUT is mode
 578
 579            return None
 580
 581        def _create_mode_constraint(self, param_mode: TokenType) -> exp.InOutColumnConstraint:
 582            """
 583            Create parameter mode constraint for function parameters.
 584
 585            Args:
 586                param_mode: The parameter mode token (IN, OUT, INOUT, or VARIADIC).
 587
 588            Returns:
 589                InOutColumnConstraint expression representing the parameter mode.
 590            """
 591            return self.expression(
 592                exp.InOutColumnConstraint,
 593                input_=(param_mode in {TokenType.IN, TokenType.INOUT}),
 594                output=(param_mode in {TokenType.OUT, TokenType.INOUT}),
 595                variadic=(param_mode == TokenType.VARIADIC),
 596            )
 597
 598        def _parse_function_parameter(self) -> t.Optional[exp.Expression]:
 599            param_mode = self._parse_parameter_mode()
 600
 601            if param_mode:
 602                self._advance()
 603
 604            # Parse parameter name and type
 605            param_name = self._parse_id_var()
 606            column_def = self._parse_column_def(this=param_name, computed_column=False)
 607
 608            # Attach mode as constraint
 609            if param_mode and column_def:
 610                constraint = self._create_mode_constraint(param_mode)
 611                if not column_def.args.get("constraints"):
 612                    column_def.set("constraints", [])
 613                column_def.args["constraints"].insert(0, constraint)
 614
 615            return column_def
 616
 617        def _parse_query_parameter(self) -> t.Optional[exp.Expression]:
 618            this = (
 619                self._parse_wrapped(self._parse_id_var)
 620                if self._match(TokenType.L_PAREN, advance=False)
 621                else None
 622            )
 623            self._match_text_seq("S")
 624            return self.expression(exp.Placeholder, this=this)
 625
 626        def _parse_date_part(self) -> exp.Expression:
 627            part = self._parse_type()
 628            self._match(TokenType.COMMA)
 629            value = self._parse_bitwise()
 630
 631            if part and isinstance(part, (exp.Column, exp.Literal)):
 632                part = exp.var(part.name)
 633
 634            return self.expression(exp.Extract, this=part, expression=value)
 635
 636        def _parse_unique_key(self) -> t.Optional[exp.Expression]:
 637            return None
 638
 639        def _parse_jsonb_exists(self) -> exp.JSONBExists:
 640            return self.expression(
 641                exp.JSONBExists,
 642                this=self._parse_bitwise(),
 643                path=self._match(TokenType.COMMA)
 644                and self.dialect.to_json_path(self._parse_bitwise()),
 645            )
 646
 647        def _parse_generated_as_identity(
 648            self,
 649        ) -> (
 650            exp.GeneratedAsIdentityColumnConstraint
 651            | exp.ComputedColumnConstraint
 652            | exp.GeneratedAsRowColumnConstraint
 653        ):
 654            this = super()._parse_generated_as_identity()
 655
 656            if self._match_text_seq("STORED"):
 657                this = self.expression(exp.ComputedColumnConstraint, this=this.expression)
 658
 659            return this
 660
 661        def _parse_user_defined_type(
 662            self, identifier: exp.Identifier
 663        ) -> t.Optional[exp.Expression]:
 664            udt_type: exp.Identifier | exp.Dot = identifier
 665
 666            while self._match(TokenType.DOT):
 667                part = self._parse_id_var()
 668                if part:
 669                    udt_type = exp.Dot(this=udt_type, expression=part)
 670
 671            return exp.DataType.build(udt_type, udt=True)
 672
 673    class Generator(generator.Generator):
 674        SINGLE_STRING_INTERVAL = True
 675        RENAME_TABLE_WITH_DB = False
 676        LOCKING_READS_SUPPORTED = True
 677        JOIN_HINTS = False
 678        TABLE_HINTS = False
 679        QUERY_HINTS = False
 680        NVL2_SUPPORTED = False
 681        PARAMETER_TOKEN = "$"
 682        NAMED_PLACEHOLDER_TOKEN = "%"
 683        TABLESAMPLE_SIZE_IS_ROWS = False
 684        TABLESAMPLE_SEED_KEYWORD = "REPEATABLE"
 685        SUPPORTS_SELECT_INTO = True
 686        JSON_TYPE_REQUIRED_FOR_EXTRACTION = True
 687        SUPPORTS_UNLOGGED_TABLES = True
 688        LIKE_PROPERTY_INSIDE_SCHEMA = True
 689        MULTI_ARG_DISTINCT = False
 690        CAN_IMPLEMENT_ARRAY_ANY = True
 691        SUPPORTS_WINDOW_EXCLUDE = True
 692        COPY_HAS_INTO_KEYWORD = False
 693        ARRAY_CONCAT_IS_VAR_LEN = False
 694        SUPPORTS_MEDIAN = False
 695        ARRAY_SIZE_DIM_REQUIRED = True
 696        SUPPORTS_BETWEEN_FLAGS = True
 697        INOUT_SEPARATOR = ""  # PostgreSQL uses "INOUT" (no space)
 698
 699        SUPPORTED_JSON_PATH_PARTS = {
 700            exp.JSONPathKey,
 701            exp.JSONPathRoot,
 702            exp.JSONPathSubscript,
 703        }
 704
 705        def lateral_sql(self, expression: exp.Lateral) -> str:
 706            sql = super().lateral_sql(expression)
 707
 708            if expression.args.get("cross_apply") is not None:
 709                sql = f"{sql} ON TRUE"
 710
 711            return sql
 712
 713        TYPE_MAPPING = {
 714            **generator.Generator.TYPE_MAPPING,
 715            exp.DataType.Type.TINYINT: "SMALLINT",
 716            exp.DataType.Type.FLOAT: "REAL",
 717            exp.DataType.Type.DOUBLE: "DOUBLE PRECISION",
 718            exp.DataType.Type.BINARY: "BYTEA",
 719            exp.DataType.Type.VARBINARY: "BYTEA",
 720            exp.DataType.Type.ROWVERSION: "BYTEA",
 721            exp.DataType.Type.DATETIME: "TIMESTAMP",
 722            exp.DataType.Type.TIMESTAMPNTZ: "TIMESTAMP",
 723            exp.DataType.Type.BLOB: "BYTEA",
 724        }
 725
 726        TRANSFORMS = {
 727            **generator.Generator.TRANSFORMS,
 728            exp.AnyValue: _versioned_anyvalue_sql,
 729            exp.ArrayConcat: array_concat_sql("ARRAY_CAT"),
 730            exp.ArrayFilter: filter_array_using_unnest,
 731            exp.ArrayAppend: array_append_sql("ARRAY_APPEND"),
 732            exp.ArrayPrepend: array_append_sql("ARRAY_PREPEND", swap_params=True),
 733            exp.BitwiseAndAgg: rename_func("BIT_AND"),
 734            exp.BitwiseOrAgg: rename_func("BIT_OR"),
 735            exp.BitwiseXor: lambda self, e: self.binary(e, "#"),
 736            exp.BitwiseXorAgg: rename_func("BIT_XOR"),
 737            exp.ColumnDef: transforms.preprocess([_auto_increment_to_serial, _serial_to_generated]),
 738            exp.CurrentDate: no_paren_current_date_sql,
 739            exp.CurrentTimestamp: lambda *_: "CURRENT_TIMESTAMP",
 740            exp.CurrentUser: lambda *_: "CURRENT_USER",
 741            exp.DateAdd: _date_add_sql("+"),
 742            exp.DateDiff: _date_diff_sql,
 743            exp.DateStrToDate: datestrtodate_sql,
 744            exp.DateSub: _date_add_sql("-"),
 745            exp.Explode: rename_func("UNNEST"),
 746            exp.ExplodingGenerateSeries: rename_func("GENERATE_SERIES"),
 747            exp.Getbit: getbit_sql,
 748            exp.GroupConcat: lambda self, e: groupconcat_sql(
 749                self, e, func_name="STRING_AGG", within_group=False
 750            ),
 751            exp.IntDiv: rename_func("DIV"),
 752            exp.JSONArrayAgg: lambda self, e: self.func(
 753                "JSON_AGG",
 754                self.sql(e, "this"),
 755                suffix=f"{self.sql(e, 'order')})",
 756            ),
 757            exp.JSONExtract: _json_extract_sql("JSON_EXTRACT_PATH", "->"),
 758            exp.JSONExtractScalar: _json_extract_sql("JSON_EXTRACT_PATH_TEXT", "->>"),
 759            exp.JSONBExtract: lambda self, e: self.binary(e, "#>"),
 760            exp.JSONBExtractScalar: lambda self, e: self.binary(e, "#>>"),
 761            exp.JSONBContains: lambda self, e: self.binary(e, "?"),
 762            exp.ParseJSON: lambda self, e: self.sql(exp.cast(e.this, exp.DataType.Type.JSON)),
 763            exp.JSONPathKey: json_path_key_only_name,
 764            exp.JSONPathRoot: lambda *_: "",
 765            exp.JSONPathSubscript: lambda self, e: self.json_path_part(e.this),
 766            exp.LastDay: no_last_day_sql,
 767            exp.LogicalOr: rename_func("BOOL_OR"),
 768            exp.LogicalAnd: rename_func("BOOL_AND"),
 769            exp.Max: max_or_greatest,
 770            exp.MapFromEntries: no_map_from_entries_sql,
 771            exp.Min: min_or_least,
 772            exp.Merge: merge_without_target_sql,
 773            exp.PartitionedByProperty: lambda self, e: f"PARTITION BY {self.sql(e, 'this')}",
 774            exp.PercentileCont: transforms.preprocess(
 775                [transforms.add_within_group_for_percentiles]
 776            ),
 777            exp.PercentileDisc: transforms.preprocess(
 778                [transforms.add_within_group_for_percentiles]
 779            ),
 780            exp.Pivot: no_pivot_sql,
 781            exp.Rand: rename_func("RANDOM"),
 782            exp.RegexpLike: lambda self, e: self.binary(e, "~"),
 783            exp.RegexpILike: lambda self, e: self.binary(e, "~*"),
 784            exp.RegexpReplace: lambda self, e: self.func(
 785                "REGEXP_REPLACE",
 786                e.this,
 787                e.expression,
 788                e.args.get("replacement"),
 789                e.args.get("position"),
 790                e.args.get("occurrence"),
 791                regexp_replace_global_modifier(e),
 792            ),
 793            exp.Round: _round_sql,
 794            exp.Select: transforms.preprocess(
 795                [
 796                    transforms.eliminate_semi_and_anti_joins,
 797                    transforms.eliminate_qualify,
 798                ]
 799            ),
 800            exp.SHA2: sha256_sql,
 801            exp.SHA2Digest: sha2_digest_sql,
 802            exp.StrPosition: lambda self, e: strposition_sql(self, e, func_name="POSITION"),
 803            exp.StrToDate: lambda self, e: self.func("TO_DATE", e.this, self.format_time(e)),
 804            exp.StrToTime: lambda self, e: self.func("TO_TIMESTAMP", e.this, self.format_time(e)),
 805            exp.StructExtract: struct_extract_sql,
 806            exp.Substring: _substring_sql,
 807            exp.TimeFromParts: rename_func("MAKE_TIME"),
 808            exp.TimestampFromParts: rename_func("MAKE_TIMESTAMP"),
 809            exp.TimestampTrunc: timestamptrunc_sql(zone=True),
 810            exp.TimeStrToTime: timestrtotime_sql,
 811            exp.TimeToStr: lambda self, e: self.func("TO_CHAR", e.this, self.format_time(e)),
 812            exp.ToChar: lambda self, e: self.function_fallback_sql(e)
 813            if e.args.get("format")
 814            else self.tochar_sql(e),
 815            exp.Trim: trim_sql,
 816            exp.TryCast: no_trycast_sql,
 817            exp.TsOrDsAdd: _date_add_sql("+"),
 818            exp.TsOrDsDiff: _date_diff_sql,
 819            exp.UnixToTime: lambda self, e: self.func("TO_TIMESTAMP", e.this),
 820            exp.Uuid: lambda *_: "GEN_RANDOM_UUID()",
 821            exp.TimeToUnix: lambda self, e: self.func(
 822                "DATE_PART", exp.Literal.string("epoch"), e.this
 823            ),
 824            exp.VariancePop: rename_func("VAR_POP"),
 825            exp.Variance: rename_func("VAR_SAMP"),
 826            exp.Xor: bool_xor_sql,
 827            exp.Unicode: rename_func("ASCII"),
 828            exp.UnixToTime: _unix_to_time_sql,
 829            exp.Levenshtein: _levenshtein_sql,
 830            exp.JSONObjectAgg: rename_func("JSON_OBJECT_AGG"),
 831            exp.JSONBObjectAgg: rename_func("JSONB_OBJECT_AGG"),
 832            exp.CountIf: count_if_to_sum,
 833        }
 834
 835        TRANSFORMS.pop(exp.CommentColumnConstraint)
 836
 837        PROPERTIES_LOCATION = {
 838            **generator.Generator.PROPERTIES_LOCATION,
 839            exp.PartitionedByProperty: exp.Properties.Location.POST_SCHEMA,
 840            exp.TransientProperty: exp.Properties.Location.UNSUPPORTED,
 841            exp.VolatileProperty: exp.Properties.Location.UNSUPPORTED,
 842        }
 843
 844        def schemacommentproperty_sql(self, expression: exp.SchemaCommentProperty) -> str:
 845            self.unsupported("Table comments are not supported in the CREATE statement")
 846            return ""
 847
 848        def commentcolumnconstraint_sql(self, expression: exp.CommentColumnConstraint) -> str:
 849            self.unsupported("Column comments are not supported in the CREATE statement")
 850            return ""
 851
 852        def columndef_sql(self, expression: exp.ColumnDef, sep: str = " ") -> str:
 853            # PostgreSQL places parameter modes BEFORE parameter name
 854            param_constraint = expression.find(exp.InOutColumnConstraint)
 855
 856            if param_constraint:
 857                mode_sql = self.sql(param_constraint)
 858                param_constraint.pop()  # Remove to prevent double-rendering
 859                base_sql = super().columndef_sql(expression, sep)
 860                return f"{mode_sql} {base_sql}"
 861
 862            return super().columndef_sql(expression, sep)
 863
 864        def unnest_sql(self, expression: exp.Unnest) -> str:
 865            if len(expression.expressions) == 1:
 866                arg = expression.expressions[0]
 867                if isinstance(arg, exp.GenerateDateArray):
 868                    generate_series: exp.Expression = exp.GenerateSeries(**arg.args)
 869                    if isinstance(expression.parent, (exp.From, exp.Join)):
 870                        generate_series = (
 871                            exp.select("value::date")
 872                            .from_(exp.Table(this=generate_series).as_("_t", table=["value"]))
 873                            .subquery(expression.args.get("alias") or "_unnested_generate_series")
 874                        )
 875                    return self.sql(generate_series)
 876
 877                from sqlglot.optimizer.annotate_types import annotate_types
 878
 879                this = annotate_types(arg, dialect=self.dialect)
 880                if this.is_type("array<json>"):
 881                    while isinstance(this, exp.Cast):
 882                        this = this.this
 883
 884                    arg_as_json = self.sql(exp.cast(this, exp.DataType.Type.JSON))
 885                    alias = self.sql(expression, "alias")
 886                    alias = f" AS {alias}" if alias else ""
 887
 888                    if expression.args.get("offset"):
 889                        self.unsupported("Unsupported JSON_ARRAY_ELEMENTS with offset")
 890
 891                    return f"JSON_ARRAY_ELEMENTS({arg_as_json}){alias}"
 892
 893            return super().unnest_sql(expression)
 894
 895        def bracket_sql(self, expression: exp.Bracket) -> str:
 896            """Forms like ARRAY[1, 2, 3][3] aren't allowed; we need to wrap the ARRAY."""
 897            if isinstance(expression.this, exp.Array):
 898                expression.set("this", exp.paren(expression.this, copy=False))
 899
 900            return super().bracket_sql(expression)
 901
 902        def matchagainst_sql(self, expression: exp.MatchAgainst) -> str:
 903            this = self.sql(expression, "this")
 904            expressions = [f"{self.sql(e)} @@ {this}" for e in expression.expressions]
 905            sql = " OR ".join(expressions)
 906            return f"({sql})" if len(expressions) > 1 else sql
 907
 908        def alterset_sql(self, expression: exp.AlterSet) -> str:
 909            exprs = self.expressions(expression, flat=True)
 910            exprs = f"({exprs})" if exprs else ""
 911
 912            access_method = self.sql(expression, "access_method")
 913            access_method = f"ACCESS METHOD {access_method}" if access_method else ""
 914            tablespace = self.sql(expression, "tablespace")
 915            tablespace = f"TABLESPACE {tablespace}" if tablespace else ""
 916            option = self.sql(expression, "option")
 917
 918            return f"SET {exprs}{access_method}{tablespace}{option}"
 919
 920        def datatype_sql(self, expression: exp.DataType) -> str:
 921            if expression.is_type(exp.DataType.Type.ARRAY):
 922                if expression.expressions:
 923                    values = self.expressions(expression, key="values", flat=True)
 924                    return f"{self.expressions(expression, flat=True)}[{values}]"
 925                return "ARRAY"
 926
 927            if (
 928                expression.is_type(exp.DataType.Type.DOUBLE, exp.DataType.Type.FLOAT)
 929                and expression.expressions
 930            ):
 931                # Postgres doesn't support precision for REAL and DOUBLE PRECISION types
 932                return f"FLOAT({self.expressions(expression, flat=True)})"
 933
 934            return super().datatype_sql(expression)
 935
 936        def cast_sql(self, expression: exp.Cast, safe_prefix: t.Optional[str] = None) -> str:
 937            this = expression.this
 938
 939            # Postgres casts DIV() to decimal for transpilation but when roundtripping it's superfluous
 940            if isinstance(this, exp.IntDiv) and expression.to == exp.DataType.build("decimal"):
 941                return self.sql(this)
 942
 943            return super().cast_sql(expression, safe_prefix=safe_prefix)
 944
 945        def array_sql(self, expression: exp.Array) -> str:
 946            exprs = expression.expressions
 947            func_name = self.normalize_func("ARRAY")
 948
 949            if isinstance(seq_get(exprs, 0), exp.Select):
 950                return f"{func_name}({self.sql(exprs[0])})"
 951
 952            return f"{func_name}{inline_array_sql(self, expression)}"
 953
 954        def computedcolumnconstraint_sql(self, expression: exp.ComputedColumnConstraint) -> str:
 955            return f"GENERATED ALWAYS AS ({self.sql(expression, 'this')}) STORED"
 956
 957        def isascii_sql(self, expression: exp.IsAscii) -> str:
 958            return f"({self.sql(expression.this)} ~ '^[[:ascii:]]*$')"
 959
 960        def ignorenulls_sql(self, expression: exp.IgnoreNulls) -> str:
 961            # https://www.postgresql.org/docs/current/functions-window.html
 962            self.unsupported("PostgreSQL does not support IGNORE NULLS.")
 963            return self.sql(expression.this)
 964
 965        def respectnulls_sql(self, expression: exp.RespectNulls) -> str:
 966            # https://www.postgresql.org/docs/current/functions-window.html
 967            self.unsupported("PostgreSQL does not support RESPECT NULLS.")
 968            return self.sql(expression.this)
 969
 970        @unsupported_args("this")
 971        def currentschema_sql(self, expression: exp.CurrentSchema) -> str:
 972            return "CURRENT_SCHEMA"
 973
 974        def interval_sql(self, expression: exp.Interval) -> str:
 975            unit = expression.text("unit").lower()
 976
 977            this = expression.this
 978            if unit.startswith("quarter") and isinstance(this, exp.Literal):
 979                this.replace(exp.Literal.string(int(this.to_py()) * 3))
 980                expression.args["unit"].replace(exp.var("MONTH"))
 981
 982            return super().interval_sql(expression)
 983
 984        def placeholder_sql(self, expression: exp.Placeholder) -> str:
 985            if expression.args.get("jdbc"):
 986                return "?"
 987
 988            this = f"({expression.name})" if expression.this else ""
 989            return f"{self.NAMED_PLACEHOLDER_TOKEN}{this}s"
 990
 991        def arraycontains_sql(self, expression: exp.ArrayContains) -> str:
 992            # Convert DuckDB's LIST_CONTAINS(array, value) to PostgreSQL
 993            # DuckDB behavior:
 994            #   - LIST_CONTAINS([1,2,3], 2) -> true
 995            #   - LIST_CONTAINS([1,2,3], 4) -> false
 996            #   - LIST_CONTAINS([1,2,NULL], 4) -> false (not NULL)
 997            #   - LIST_CONTAINS([1,2,3], NULL) -> NULL
 998            #
 999            # PostgreSQL equivalent: CASE WHEN value IS NULL THEN NULL
1000            #                            ELSE COALESCE(value = ANY(array), FALSE) END
1001            value = expression.expression
1002            array = expression.this
1003
1004            coalesce_expr = exp.Coalesce(
1005                this=value.eq(exp.Any(this=exp.paren(expression=array, copy=False))),
1006                expressions=[exp.false()],
1007            )
1008
1009            case_expr = (
1010                exp.Case()
1011                .when(exp.Is(this=value, expression=exp.null()), exp.null(), copy=False)
1012                .else_(coalesce_expr, copy=False)
1013            )
1014
1015            return self.sql(case_expr)
INDEX_OFFSET = 1

The base index offset for arrays.

TYPED_DIVISION = True

Whether the behavior of a / b depends on the types of a and b. False means a / b is always float division. True means a / b is integer division if both a and b are integers.

CONCAT_COALESCE = True

A NULL arg in CONCAT yields NULL by default, but in some dialects it yields an empty string.

NULL_ORDERING = 'nulls_are_large'

Default NULL ordering method to use if not explicitly set. Possible values: "nulls_are_small", "nulls_are_large", "nulls_are_last"

TIME_FORMAT = "'YYYY-MM-DD HH24:MI:SS'"
TABLESAMPLE_SIZE_IS_PERCENT = True

Whether a size in the table sample clause represents percentage.

TABLES_REFERENCEABLE_AS_COLUMNS = True

Whether table names can be referenced as columns (treated as structs).

BigQuery allows tables to be referenced as columns in queries, automatically treating them as struct values containing all the table's columns.

For example, in BigQuery: SELECT t FROM my_table AS t -- Returns entire row as a struct

DEFAULT_FUNCTIONS_COLUMN_NAMES: Dict[Type[sqlglot.expressions.Func], Union[str, Tuple[str, ...]]] = {<class 'sqlglot.expressions.ExplodingGenerateSeries'>: 'generate_series'}

Maps function expressions to their default output column name(s).

For example, in Postgres, generate_series function outputs a column named "generate_series" by default, so we map the ExplodingGenerateSeries expression to "generate_series" string.

TIME_MAPPING: Dict[str, str] = {'d': '%u', 'D': '%u', 'dd': '%d', 'DD': '%d', 'ddd': '%j', 'DDD': '%j', 'FMDD': '%-d', 'FMDDD': '%-j', 'FMHH12': '%-I', 'FMHH24': '%-H', 'FMMI': '%-M', 'FMMM': '%-m', 'FMSS': '%-S', 'HH12': '%I', 'HH24': '%H', 'mi': '%M', 'MI': '%M', 'mm': '%m', 'MM': '%m', 'OF': '%z', 'ss': '%S', 'SS': '%S', 'TMDay': '%A', 'TMDy': '%a', 'TMMon': '%b', 'TMMonth': '%B', 'TZ': '%Z', 'US': '%f', 'ww': '%U', 'WW': '%U', 'yy': '%y', 'YY': '%y', 'yyyy': '%Y', 'YYYY': '%Y'}

Associates this dialect's time formats with their equivalent Python strftime formats.

SUPPORTS_COLUMN_JOIN_MARKS = False

Whether the old-style outer join (+) syntax is supported.

UNESCAPED_SEQUENCES: Dict[str, str] = {'\\a': '\x07', '\\b': '\x08', '\\f': '\x0c', '\\n': '\n', '\\r': '\r', '\\t': '\t', '\\v': '\x0b', '\\\\': '\\'}

Mapping of an escaped sequence (\n) to its unescaped version ( ).

INITCAP_SUPPORTS_CUSTOM_DELIMITERS = False
tokenizer_class = <class 'Postgres.Tokenizer'>
jsonpath_tokenizer_class = <class 'sqlglot.tokens.JSONPathTokenizer'>
parser_class = <class 'Postgres.Parser'>
generator_class = <class 'Postgres.Generator'>
TIME_TRIE: Dict = {'d': {0: True, 'd': {0: True, 'd': {0: True}}}, 'D': {0: True, 'D': {0: True, 'D': {0: True}}}, 'F': {'M': {'D': {'D': {0: True, 'D': {0: True}}}, 'H': {'H': {'1': {'2': {0: True}}, '2': {'4': {0: True}}}}, 'M': {'I': {0: True}, 'M': {0: True}}, 'S': {'S': {0: True}}}}, 'H': {'H': {'1': {'2': {0: True}}, '2': {'4': {0: True}}}}, 'm': {'i': {0: True}, 'm': {0: True}}, 'M': {'I': {0: True}, 'M': {0: True}}, 'O': {'F': {0: True}}, 's': {'s': {0: True}}, 'S': {'S': {0: True}}, 'T': {'M': {'D': {'a': {'y': {0: True}}, 'y': {0: True}}, 'M': {'o': {'n': {0: True, 't': {'h': {0: True}}}}}}, 'Z': {0: True}}, 'U': {'S': {0: True}}, 'w': {'w': {0: True}}, 'W': {'W': {0: True}}, 'y': {'y': {0: True, 'y': {'y': {0: True}}}}, 'Y': {'Y': {0: True, 'Y': {'Y': {0: True}}}}}
FORMAT_TRIE: Dict = {'d': {0: True, 'd': {0: True, 'd': {0: True}}}, 'D': {0: True, 'D': {0: True, 'D': {0: True}}}, 'F': {'M': {'D': {'D': {0: True, 'D': {0: True}}}, 'H': {'H': {'1': {'2': {0: True}}, '2': {'4': {0: True}}}}, 'M': {'I': {0: True}, 'M': {0: True}}, 'S': {'S': {0: True}}}}, 'H': {'H': {'1': {'2': {0: True}}, '2': {'4': {0: True}}}}, 'm': {'i': {0: True}, 'm': {0: True}}, 'M': {'I': {0: True}, 'M': {0: True}}, 'O': {'F': {0: True}}, 's': {'s': {0: True}}, 'S': {'S': {0: True}}, 'T': {'M': {'D': {'a': {'y': {0: True}}, 'y': {0: True}}, 'M': {'o': {'n': {0: True, 't': {'h': {0: True}}}}}}, 'Z': {0: True}}, 'U': {'S': {0: True}}, 'w': {'w': {0: True}}, 'W': {'W': {0: True}}, 'y': {'y': {0: True, 'y': {'y': {0: True}}}}, 'Y': {'Y': {0: True, 'Y': {'Y': {0: True}}}}}
INVERSE_TIME_MAPPING: Dict[str, str] = {'%u': 'D', '%d': 'DD', '%j': 'DDD', '%-d': 'FMDD', '%-j': 'FMDDD', '%-I': 'FMHH12', '%-H': 'FMHH24', '%-M': 'FMMI', '%-m': 'FMMM', '%-S': 'FMSS', '%I': 'HH12', '%H': 'HH24', '%M': 'MI', '%m': 'MM', '%z': 'OF', '%S': 'SS', '%A': 'TMDay', '%a': 'TMDy', '%b': 'TMMon', '%B': 'TMMonth', '%Z': 'TZ', '%f': 'US', '%U': 'WW', '%y': 'YY', '%Y': 'YYYY'}
INVERSE_TIME_TRIE: Dict = {'%': {'u': {0: True}, 'd': {0: True}, 'j': {0: True}, '-': {'d': {0: True}, 'j': {0: True}, 'I': {0: True}, 'H': {0: True}, 'M': {0: True}, 'm': {0: True}, 'S': {0: True}}, 'I': {0: True}, 'H': {0: True}, 'M': {0: True}, 'm': {0: True}, 'z': {0: True}, 'S': {0: True}, 'A': {0: True}, 'a': {0: True}, 'b': {0: True}, 'B': {0: True}, 'Z': {0: True}, 'f': {0: True}, 'U': {0: True}, 'y': {0: True}, 'Y': {0: True}}}
INVERSE_FORMAT_MAPPING: Dict[str, str] = {}
INVERSE_FORMAT_TRIE: Dict = {}
INVERSE_CREATABLE_KIND_MAPPING: dict[str, str] = {}
ESCAPED_SEQUENCES: Dict[str, str] = {'\x07': '\\a', '\x08': '\\b', '\x0c': '\\f', '\n': '\\n', '\r': '\\r', '\t': '\\t', '\x0b': '\\v', '\\': '\\\\'}
QUOTE_START = "'"
QUOTE_END = "'"
IDENTIFIER_START = '"'
IDENTIFIER_END = '"'
VALID_INTERVAL_UNITS: Set[str] = {'MON', 'DAY OF YEAR', 'YEARS', 'EPOCH_NANOSECONDS', 'WEEKOFYEAR', 'M', 'MIL', 'DY', 'MINUTE', 'Y', 'MILS', 'MONS', 'NSEC', 'DOW', 'EPOCH_MICROSECONDS', 'YYYY', 'Q', 'DAY OF WEEK', 'HR', 'MILLISECONDS', 'DW_ISO', 'QTRS', 'W', 'NSECONDS', 'US', 'MINUTES', 'NANOSECS', 'NANOSECOND', 'MILLISECS', 'DECADES', 'EPOCH_SECONDS', 'MILLISECOND', 'C', 'DECS', 'DAYOFWEEK', 'DECADE', 'DAYS', 'CENTURY', 'YY', 'YR', 'SEC', 'QTR', 'MIN', 'WK', 'MM', 'DD', 'DW', 'YYY', 'TIMEZONE_HOUR', 'DOY', 'EPOCH_MILLISECONDS', 'TZH', 'DAYOFWEEK_ISO', 'MSEC', 'NANOSEC', 'CENTURIES', 'MICROSECS', 'MILLISECON', 'S', 'MI', 'WEEKDAY', 'EPOCH_NANOSECOND', 'WEEKOFYEARISO', 'MSECOND', 'HOURS', 'USECOND', 'EPOCH_SECOND', 'DAY', 'HH', 'SECS', 'NSECOND', 'EPOCH_MICROSECOND', 'MONTH', 'TZM', 'DOW_ISO', 'YEAR', 'D', 'MSECS', 'DAYOFMONTH', 'EPOCH_MILLISECOND', 'HOUR', 'YRS', 'WY', 'MICROSECONDS', 'DAYOFWEEKISO', 'WOY', 'WEEKDAY_ISO', 'H', 'MINS', 'MSECONDS', 'HRS', 'WEEK_ISO', 'TIMEZONE_MINUTE', 'MILLENNIUM', 'USECS', 'MILLISEC', 'MICROSECOND', 'WEEKOFYEAR_ISO', 'SECOND', 'USECONDS', 'WEEKISO', 'QUARTERS', 'MONTHS', 'MICROSEC', 'WEEK', 'DAYOFYEAR', 'QUARTER', 'CENTS', 'EPOCH', 'CENT', 'MILLENIA', 'DEC', 'NS', 'SECONDS', 'USEC', 'MS'}
BIT_START: Optional[str] = "b'"
BIT_END: Optional[str] = "'"
HEX_START: Optional[str] = "x'"
HEX_END: Optional[str] = "'"
BYTE_START: Optional[str] = "e'"
BYTE_END: Optional[str] = "'"
UNICODE_START: Optional[str] = None
UNICODE_END: Optional[str] = None
STRINGS_SUPPORT_ESCAPED_SEQUENCES = False
BYTE_STRINGS_SUPPORT_ESCAPED_SEQUENCES = True
class Postgres.Tokenizer(sqlglot.tokens.Tokenizer):
348    class Tokenizer(tokens.Tokenizer):
349        BIT_STRINGS = [("b'", "'"), ("B'", "'")]
350        HEX_STRINGS = [("x'", "'"), ("X'", "'")]
351        BYTE_STRINGS = [("e'", "'"), ("E'", "'")]
352        BYTE_STRING_ESCAPES = ["'", "\\"]
353        HEREDOC_STRINGS = ["$"]
354
355        HEREDOC_TAG_IS_IDENTIFIER = True
356        HEREDOC_STRING_ALTERNATIVE = TokenType.PARAMETER
357
358        KEYWORDS = {
359            **tokens.Tokenizer.KEYWORDS,
360            "~": TokenType.RLIKE,
361            "@@": TokenType.DAT,
362            "@>": TokenType.AT_GT,
363            "<@": TokenType.LT_AT,
364            "?&": TokenType.QMARK_AMP,
365            "?|": TokenType.QMARK_PIPE,
366            "#-": TokenType.HASH_DASH,
367            "|/": TokenType.PIPE_SLASH,
368            "||/": TokenType.DPIPE_SLASH,
369            "BEGIN": TokenType.BEGIN,
370            "BIGSERIAL": TokenType.BIGSERIAL,
371            "CONSTRAINT TRIGGER": TokenType.COMMAND,
372            "CSTRING": TokenType.PSEUDO_TYPE,
373            "DECLARE": TokenType.COMMAND,
374            "DO": TokenType.COMMAND,
375            "EXEC": TokenType.COMMAND,
376            "HSTORE": TokenType.HSTORE,
377            "INT8": TokenType.BIGINT,
378            "MONEY": TokenType.MONEY,
379            "NAME": TokenType.NAME,
380            "OID": TokenType.OBJECT_IDENTIFIER,
381            "ONLY": TokenType.ONLY,
382            "POINT": TokenType.POINT,
383            "REFRESH": TokenType.COMMAND,
384            "REINDEX": TokenType.COMMAND,
385            "RESET": TokenType.COMMAND,
386            "SERIAL": TokenType.SERIAL,
387            "SMALLSERIAL": TokenType.SMALLSERIAL,
388            "TEMP": TokenType.TEMPORARY,
389            "REGCLASS": TokenType.OBJECT_IDENTIFIER,
390            "REGCOLLATION": TokenType.OBJECT_IDENTIFIER,
391            "REGCONFIG": TokenType.OBJECT_IDENTIFIER,
392            "REGDICTIONARY": TokenType.OBJECT_IDENTIFIER,
393            "REGNAMESPACE": TokenType.OBJECT_IDENTIFIER,
394            "REGOPER": TokenType.OBJECT_IDENTIFIER,
395            "REGOPERATOR": TokenType.OBJECT_IDENTIFIER,
396            "REGPROC": TokenType.OBJECT_IDENTIFIER,
397            "REGPROCEDURE": TokenType.OBJECT_IDENTIFIER,
398            "REGROLE": TokenType.OBJECT_IDENTIFIER,
399            "REGTYPE": TokenType.OBJECT_IDENTIFIER,
400            "FLOAT": TokenType.DOUBLE,
401            "XML": TokenType.XML,
402            "VARIADIC": TokenType.VARIADIC,
403            "INOUT": TokenType.INOUT,
404        }
405        KEYWORDS.pop("/*+")
406        KEYWORDS.pop("DIV")
407
408        SINGLE_TOKENS = {
409            **tokens.Tokenizer.SINGLE_TOKENS,
410            "$": TokenType.HEREDOC_STRING,
411        }
412
413        VAR_SINGLE_TOKENS = {"$"}
BIT_STRINGS = [("b'", "'"), ("B'", "'")]
HEX_STRINGS = [("x'", "'"), ("X'", "'")]
BYTE_STRINGS = [("e'", "'"), ("E'", "'")]
BYTE_STRING_ESCAPES = ["'", '\\']
HEREDOC_STRINGS = ['$']
HEREDOC_TAG_IS_IDENTIFIER = True
HEREDOC_STRING_ALTERNATIVE = <TokenType.PARAMETER: 'PARAMETER'>
KEYWORDS = {'{%': <TokenType.BLOCK_START: 'BLOCK_START'>, '{%+': <TokenType.BLOCK_START: 'BLOCK_START'>, '{%-': <TokenType.BLOCK_START: 'BLOCK_START'>, '%}': <TokenType.BLOCK_END: 'BLOCK_END'>, '+%}': <TokenType.BLOCK_END: 'BLOCK_END'>, '-%}': <TokenType.BLOCK_END: 'BLOCK_END'>, '{{+': <TokenType.BLOCK_START: 'BLOCK_START'>, '{{-': <TokenType.BLOCK_START: 'BLOCK_START'>, '+}}': <TokenType.BLOCK_END: 'BLOCK_END'>, '-}}': <TokenType.BLOCK_END: 'BLOCK_END'>, '&<': <TokenType.AMP_LT: 'AMP_LT'>, '&>': <TokenType.AMP_GT: 'AMP_GT'>, '==': <TokenType.EQ: 'EQ'>, '::': <TokenType.DCOLON: 'DCOLON'>, '?::': <TokenType.QDCOLON: 'QDCOLON'>, '||': <TokenType.DPIPE: 'DPIPE'>, '|>': <TokenType.PIPE_GT: 'PIPE_GT'>, '>=': <TokenType.GTE: 'GTE'>, '<=': <TokenType.LTE: 'LTE'>, '<>': <TokenType.NEQ: 'NEQ'>, '!=': <TokenType.NEQ: 'NEQ'>, ':=': <TokenType.COLON_EQ: 'COLON_EQ'>, '<=>': <TokenType.NULLSAFE_EQ: 'NULLSAFE_EQ'>, '->': <TokenType.ARROW: 'ARROW'>, '->>': <TokenType.DARROW: 'DARROW'>, '=>': <TokenType.FARROW: 'FARROW'>, '#>': <TokenType.HASH_ARROW: 'HASH_ARROW'>, '#>>': <TokenType.DHASH_ARROW: 'DHASH_ARROW'>, '<->': <TokenType.LR_ARROW: 'LR_ARROW'>, '&&': <TokenType.DAMP: 'DAMP'>, '??': <TokenType.DQMARK: 'DQMARK'>, '~~~': <TokenType.GLOB: 'GLOB'>, '~~': <TokenType.LIKE: 'LIKE'>, '~~*': <TokenType.ILIKE: 'ILIKE'>, '~*': <TokenType.IRLIKE: 'IRLIKE'>, '-|-': <TokenType.ADJACENT: 'ADJACENT'>, 'ALL': <TokenType.ALL: 'ALL'>, 'AND': <TokenType.AND: 'AND'>, 'ANTI': <TokenType.ANTI: 'ANTI'>, 'ANY': <TokenType.ANY: 'ANY'>, 'ASC': <TokenType.ASC: 'ASC'>, 'AS': <TokenType.ALIAS: 'ALIAS'>, 'ASOF': <TokenType.ASOF: 'ASOF'>, 'AUTOINCREMENT': <TokenType.AUTO_INCREMENT: 'AUTO_INCREMENT'>, 'AUTO_INCREMENT': <TokenType.AUTO_INCREMENT: 'AUTO_INCREMENT'>, 'BEGIN': <TokenType.BEGIN: 'BEGIN'>, 'BETWEEN': <TokenType.BETWEEN: 'BETWEEN'>, 'CACHE': <TokenType.CACHE: 'CACHE'>, 'UNCACHE': <TokenType.UNCACHE: 'UNCACHE'>, 'CASE': <TokenType.CASE: 'CASE'>, 'CHARACTER SET': <TokenType.CHARACTER_SET: 'CHARACTER_SET'>, 'CLUSTER BY': <TokenType.CLUSTER_BY: 'CLUSTER_BY'>, 'COLLATE': <TokenType.COLLATE: 'COLLATE'>, 'COLUMN': <TokenType.COLUMN: 'COLUMN'>, 'COMMIT': <TokenType.COMMIT: 'COMMIT'>, 'CONNECT BY': <TokenType.CONNECT_BY: 'CONNECT_BY'>, 'CONSTRAINT': <TokenType.CONSTRAINT: 'CONSTRAINT'>, 'COPY': <TokenType.COPY: 'COPY'>, 'CREATE': <TokenType.CREATE: 'CREATE'>, 'CROSS': <TokenType.CROSS: 'CROSS'>, 'CUBE': <TokenType.CUBE: 'CUBE'>, 'CURRENT_DATE': <TokenType.CURRENT_DATE: 'CURRENT_DATE'>, 'CURRENT_SCHEMA': <TokenType.CURRENT_SCHEMA: 'CURRENT_SCHEMA'>, 'CURRENT_TIME': <TokenType.CURRENT_TIME: 'CURRENT_TIME'>, 'CURRENT_TIMESTAMP': <TokenType.CURRENT_TIMESTAMP: 'CURRENT_TIMESTAMP'>, 'CURRENT_USER': <TokenType.CURRENT_USER: 'CURRENT_USER'>, 'CURRENT_CATALOG': <TokenType.CURRENT_CATALOG: 'CURRENT_CATALOG'>, 'DATABASE': <TokenType.DATABASE: 'DATABASE'>, 'DEFAULT': <TokenType.DEFAULT: 'DEFAULT'>, 'DELETE': <TokenType.DELETE: 'DELETE'>, 'DESC': <TokenType.DESC: 'DESC'>, 'DESCRIBE': <TokenType.DESCRIBE: 'DESCRIBE'>, 'DISTINCT': <TokenType.DISTINCT: 'DISTINCT'>, 'DISTRIBUTE BY': <TokenType.DISTRIBUTE_BY: 'DISTRIBUTE_BY'>, 'DROP': <TokenType.DROP: 'DROP'>, 'ELSE': <TokenType.ELSE: 'ELSE'>, 'END': <TokenType.END: 'END'>, 'ENUM': <TokenType.ENUM: 'ENUM'>, 'ESCAPE': <TokenType.ESCAPE: 'ESCAPE'>, 'EXCEPT': <TokenType.EXCEPT: 'EXCEPT'>, 'EXECUTE': <TokenType.EXECUTE: 'EXECUTE'>, 'EXISTS': <TokenType.EXISTS: 'EXISTS'>, 'FALSE': <TokenType.FALSE: 'FALSE'>, 'FETCH': <TokenType.FETCH: 'FETCH'>, 'FILTER': <TokenType.FILTER: 'FILTER'>, 'FILE': <TokenType.FILE: 'FILE'>, 'FIRST': <TokenType.FIRST: 'FIRST'>, 'FULL': <TokenType.FULL: 'FULL'>, 'FUNCTION': <TokenType.FUNCTION: 'FUNCTION'>, 'FOR': <TokenType.FOR: 'FOR'>, 'FOREIGN KEY': <TokenType.FOREIGN_KEY: 'FOREIGN_KEY'>, 'FORMAT': <TokenType.FORMAT: 'FORMAT'>, 'FROM': <TokenType.FROM: 'FROM'>, 'GEOGRAPHY': <TokenType.GEOGRAPHY: 'GEOGRAPHY'>, 'GEOMETRY': <TokenType.GEOMETRY: 'GEOMETRY'>, 'GLOB': <TokenType.GLOB: 'GLOB'>, 'GROUP BY': <TokenType.GROUP_BY: 'GROUP_BY'>, 'GROUPING SETS': <TokenType.GROUPING_SETS: 'GROUPING_SETS'>, 'HAVING': <TokenType.HAVING: 'HAVING'>, 'ILIKE': <TokenType.ILIKE: 'ILIKE'>, 'IN': <TokenType.IN: 'IN'>, 'INDEX': <TokenType.INDEX: 'INDEX'>, 'INET': <TokenType.INET: 'INET'>, 'INNER': <TokenType.INNER: 'INNER'>, 'INSERT': <TokenType.INSERT: 'INSERT'>, 'INTERVAL': <TokenType.INTERVAL: 'INTERVAL'>, 'INTERSECT': <TokenType.INTERSECT: 'INTERSECT'>, 'INTO': <TokenType.INTO: 'INTO'>, 'IS': <TokenType.IS: 'IS'>, 'ISNULL': <TokenType.ISNULL: 'ISNULL'>, 'JOIN': <TokenType.JOIN: 'JOIN'>, 'KEEP': <TokenType.KEEP: 'KEEP'>, 'KILL': <TokenType.KILL: 'KILL'>, 'LATERAL': <TokenType.LATERAL: 'LATERAL'>, 'LEFT': <TokenType.LEFT: 'LEFT'>, 'LIKE': <TokenType.LIKE: 'LIKE'>, 'LIMIT': <TokenType.LIMIT: 'LIMIT'>, 'LOAD': <TokenType.LOAD: 'LOAD'>, 'LOCALTIME': <TokenType.LOCALTIME: 'LOCALTIME'>, 'LOCALTIMESTAMP': <TokenType.LOCALTIMESTAMP: 'LOCALTIMESTAMP'>, 'LOCK': <TokenType.LOCK: 'LOCK'>, 'MERGE': <TokenType.MERGE: 'MERGE'>, 'NAMESPACE': <TokenType.NAMESPACE: 'NAMESPACE'>, 'NATURAL': <TokenType.NATURAL: 'NATURAL'>, 'NEXT': <TokenType.NEXT: 'NEXT'>, 'NOT': <TokenType.NOT: 'NOT'>, 'NOTNULL': <TokenType.NOTNULL: 'NOTNULL'>, 'NULL': <TokenType.NULL: 'NULL'>, 'OBJECT': <TokenType.OBJECT: 'OBJECT'>, 'OFFSET': <TokenType.OFFSET: 'OFFSET'>, 'ON': <TokenType.ON: 'ON'>, 'OR': <TokenType.OR: 'OR'>, 'XOR': <TokenType.XOR: 'XOR'>, 'ORDER BY': <TokenType.ORDER_BY: 'ORDER_BY'>, 'ORDINALITY': <TokenType.ORDINALITY: 'ORDINALITY'>, 'OUT': <TokenType.OUT: 'OUT'>, 'OUTER': <TokenType.OUTER: 'OUTER'>, 'OVER': <TokenType.OVER: 'OVER'>, 'OVERLAPS': <TokenType.OVERLAPS: 'OVERLAPS'>, 'OVERWRITE': <TokenType.OVERWRITE: 'OVERWRITE'>, 'PARTITION': <TokenType.PARTITION: 'PARTITION'>, 'PARTITION BY': <TokenType.PARTITION_BY: 'PARTITION_BY'>, 'PARTITIONED BY': <TokenType.PARTITION_BY: 'PARTITION_BY'>, 'PARTITIONED_BY': <TokenType.PARTITION_BY: 'PARTITION_BY'>, 'PERCENT': <TokenType.PERCENT: 'PERCENT'>, 'PIVOT': <TokenType.PIVOT: 'PIVOT'>, 'PRAGMA': <TokenType.PRAGMA: 'PRAGMA'>, 'PRIMARY KEY': <TokenType.PRIMARY_KEY: 'PRIMARY_KEY'>, 'PROCEDURE': <TokenType.PROCEDURE: 'PROCEDURE'>, 'OPERATOR': <TokenType.OPERATOR: 'OPERATOR'>, 'QUALIFY': <TokenType.QUALIFY: 'QUALIFY'>, 'RANGE': <TokenType.RANGE: 'RANGE'>, 'RECURSIVE': <TokenType.RECURSIVE: 'RECURSIVE'>, 'REGEXP': <TokenType.RLIKE: 'RLIKE'>, 'RENAME': <TokenType.RENAME: 'RENAME'>, 'REPLACE': <TokenType.REPLACE: 'REPLACE'>, 'RETURNING': <TokenType.RETURNING: 'RETURNING'>, 'REFERENCES': <TokenType.REFERENCES: 'REFERENCES'>, 'RIGHT': <TokenType.RIGHT: 'RIGHT'>, 'RLIKE': <TokenType.RLIKE: 'RLIKE'>, 'ROLLBACK': <TokenType.ROLLBACK: 'ROLLBACK'>, 'ROLLUP': <TokenType.ROLLUP: 'ROLLUP'>, 'ROW': <TokenType.ROW: 'ROW'>, 'ROWS': <TokenType.ROWS: 'ROWS'>, 'SCHEMA': <TokenType.SCHEMA: 'SCHEMA'>, 'SELECT': <TokenType.SELECT: 'SELECT'>, 'SEMI': <TokenType.SEMI: 'SEMI'>, 'SESSION': <TokenType.SESSION: 'SESSION'>, 'SESSION_USER': <TokenType.SESSION_USER: 'SESSION_USER'>, 'SET': <TokenType.SET: 'SET'>, 'SETTINGS': <TokenType.SETTINGS: 'SETTINGS'>, 'SHOW': <TokenType.SHOW: 'SHOW'>, 'SIMILAR TO': <TokenType.SIMILAR_TO: 'SIMILAR_TO'>, 'SOME': <TokenType.SOME: 'SOME'>, 'SORT BY': <TokenType.SORT_BY: 'SORT_BY'>, 'START WITH': <TokenType.START_WITH: 'START_WITH'>, 'STRAIGHT_JOIN': <TokenType.STRAIGHT_JOIN: 'STRAIGHT_JOIN'>, 'TABLE': <TokenType.TABLE: 'TABLE'>, 'TABLESAMPLE': <TokenType.TABLE_SAMPLE: 'TABLE_SAMPLE'>, 'TEMP': <TokenType.TEMPORARY: 'TEMPORARY'>, 'TEMPORARY': <TokenType.TEMPORARY: 'TEMPORARY'>, 'THEN': <TokenType.THEN: 'THEN'>, 'TRUE': <TokenType.TRUE: 'TRUE'>, 'TRUNCATE': <TokenType.TRUNCATE: 'TRUNCATE'>, 'UNION': <TokenType.UNION: 'UNION'>, 'UNKNOWN': <TokenType.UNKNOWN: 'UNKNOWN'>, 'UNNEST': <TokenType.UNNEST: 'UNNEST'>, 'UNPIVOT': <TokenType.UNPIVOT: 'UNPIVOT'>, 'UPDATE': <TokenType.UPDATE: 'UPDATE'>, 'USE': <TokenType.USE: 'USE'>, 'USING': <TokenType.USING: 'USING'>, 'UUID': <TokenType.UUID: 'UUID'>, 'VALUES': <TokenType.VALUES: 'VALUES'>, 'VIEW': <TokenType.VIEW: 'VIEW'>, 'VOLATILE': <TokenType.VOLATILE: 'VOLATILE'>, 'WHEN': <TokenType.WHEN: 'WHEN'>, 'WHERE': <TokenType.WHERE: 'WHERE'>, 'WINDOW': <TokenType.WINDOW: 'WINDOW'>, 'WITH': <TokenType.WITH: 'WITH'>, 'APPLY': <TokenType.APPLY: 'APPLY'>, 'ARRAY': <TokenType.ARRAY: 'ARRAY'>, 'BIT': <TokenType.BIT: 'BIT'>, 'BOOL': <TokenType.BOOLEAN: 'BOOLEAN'>, 'BOOLEAN': <TokenType.BOOLEAN: 'BOOLEAN'>, 'BYTE': <TokenType.TINYINT: 'TINYINT'>, 'MEDIUMINT': <TokenType.MEDIUMINT: 'MEDIUMINT'>, 'INT1': <TokenType.TINYINT: 'TINYINT'>, 'TINYINT': <TokenType.TINYINT: 'TINYINT'>, 'INT16': <TokenType.SMALLINT: 'SMALLINT'>, 'SHORT': <TokenType.SMALLINT: 'SMALLINT'>, 'SMALLINT': <TokenType.SMALLINT: 'SMALLINT'>, 'HUGEINT': <TokenType.INT128: 'INT128'>, 'UHUGEINT': <TokenType.UINT128: 'UINT128'>, 'INT2': <TokenType.SMALLINT: 'SMALLINT'>, 'INTEGER': <TokenType.INT: 'INT'>, 'INT': <TokenType.INT: 'INT'>, 'INT4': <TokenType.INT: 'INT'>, 'INT32': <TokenType.INT: 'INT'>, 'INT64': <TokenType.BIGINT: 'BIGINT'>, 'INT128': <TokenType.INT128: 'INT128'>, 'INT256': <TokenType.INT256: 'INT256'>, 'LONG': <TokenType.BIGINT: 'BIGINT'>, 'BIGINT': <TokenType.BIGINT: 'BIGINT'>, 'INT8': <TokenType.BIGINT: 'BIGINT'>, 'UINT': <TokenType.UINT: 'UINT'>, 'UINT128': <TokenType.UINT128: 'UINT128'>, 'UINT256': <TokenType.UINT256: 'UINT256'>, 'DEC': <TokenType.DECIMAL: 'DECIMAL'>, 'DECIMAL': <TokenType.DECIMAL: 'DECIMAL'>, 'DECIMAL32': <TokenType.DECIMAL32: 'DECIMAL32'>, 'DECIMAL64': <TokenType.DECIMAL64: 'DECIMAL64'>, 'DECIMAL128': <TokenType.DECIMAL128: 'DECIMAL128'>, 'DECIMAL256': <TokenType.DECIMAL256: 'DECIMAL256'>, 'DECFLOAT': <TokenType.DECFLOAT: 'DECFLOAT'>, 'BIGDECIMAL': <TokenType.BIGDECIMAL: 'BIGDECIMAL'>, 'BIGNUMERIC': <TokenType.BIGDECIMAL: 'BIGDECIMAL'>, 'BIGNUM': <TokenType.BIGNUM: 'BIGNUM'>, 'LIST': <TokenType.LIST: 'LIST'>, 'MAP': <TokenType.MAP: 'MAP'>, 'NULLABLE': <TokenType.NULLABLE: 'NULLABLE'>, 'NUMBER': <TokenType.DECIMAL: 'DECIMAL'>, 'NUMERIC': <TokenType.DECIMAL: 'DECIMAL'>, 'FIXED': <TokenType.DECIMAL: 'DECIMAL'>, 'REAL': <TokenType.FLOAT: 'FLOAT'>, 'FLOAT': <TokenType.DOUBLE: 'DOUBLE'>, 'FLOAT4': <TokenType.FLOAT: 'FLOAT'>, 'FLOAT8': <TokenType.DOUBLE: 'DOUBLE'>, 'DOUBLE': <TokenType.DOUBLE: 'DOUBLE'>, 'DOUBLE PRECISION': <TokenType.DOUBLE: 'DOUBLE'>, 'JSON': <TokenType.JSON: 'JSON'>, 'JSONB': <TokenType.JSONB: 'JSONB'>, 'CHAR': <TokenType.CHAR: 'CHAR'>, 'CHARACTER': <TokenType.CHAR: 'CHAR'>, 'CHAR VARYING': <TokenType.VARCHAR: 'VARCHAR'>, 'CHARACTER VARYING': <TokenType.VARCHAR: 'VARCHAR'>, 'NCHAR': <TokenType.NCHAR: 'NCHAR'>, 'VARCHAR': <TokenType.VARCHAR: 'VARCHAR'>, 'VARCHAR2': <TokenType.VARCHAR: 'VARCHAR'>, 'NVARCHAR': <TokenType.NVARCHAR: 'NVARCHAR'>, 'NVARCHAR2': <TokenType.NVARCHAR: 'NVARCHAR'>, 'BPCHAR': <TokenType.BPCHAR: 'BPCHAR'>, 'STR': <TokenType.TEXT: 'TEXT'>, 'STRING': <TokenType.TEXT: 'TEXT'>, 'TEXT': <TokenType.TEXT: 'TEXT'>, 'LONGTEXT': <TokenType.LONGTEXT: 'LONGTEXT'>, 'MEDIUMTEXT': <TokenType.MEDIUMTEXT: 'MEDIUMTEXT'>, 'TINYTEXT': <TokenType.TINYTEXT: 'TINYTEXT'>, 'CLOB': <TokenType.TEXT: 'TEXT'>, 'LONGVARCHAR': <TokenType.TEXT: 'TEXT'>, 'BINARY': <TokenType.BINARY: 'BINARY'>, 'BLOB': <TokenType.VARBINARY: 'VARBINARY'>, 'LONGBLOB': <TokenType.LONGBLOB: 'LONGBLOB'>, 'MEDIUMBLOB': <TokenType.MEDIUMBLOB: 'MEDIUMBLOB'>, 'TINYBLOB': <TokenType.TINYBLOB: 'TINYBLOB'>, 'BYTEA': <TokenType.VARBINARY: 'VARBINARY'>, 'VARBINARY': <TokenType.VARBINARY: 'VARBINARY'>, 'TIME': <TokenType.TIME: 'TIME'>, 'TIMETZ': <TokenType.TIMETZ: 'TIMETZ'>, 'TIME_NS': <TokenType.TIME_NS: 'TIME_NS'>, 'TIMESTAMP': <TokenType.TIMESTAMP: 'TIMESTAMP'>, 'TIMESTAMPTZ': <TokenType.TIMESTAMPTZ: 'TIMESTAMPTZ'>, 'TIMESTAMPLTZ': <TokenType.TIMESTAMPLTZ: 'TIMESTAMPLTZ'>, 'TIMESTAMP_LTZ': <TokenType.TIMESTAMPLTZ: 'TIMESTAMPLTZ'>, 'TIMESTAMPNTZ': <TokenType.TIMESTAMPNTZ: 'TIMESTAMPNTZ'>, 'TIMESTAMP_NTZ': <TokenType.TIMESTAMPNTZ: 'TIMESTAMPNTZ'>, 'DATE': <TokenType.DATE: 'DATE'>, 'DATETIME': <TokenType.DATETIME: 'DATETIME'>, 'INT4RANGE': <TokenType.INT4RANGE: 'INT4RANGE'>, 'INT4MULTIRANGE': <TokenType.INT4MULTIRANGE: 'INT4MULTIRANGE'>, 'INT8RANGE': <TokenType.INT8RANGE: 'INT8RANGE'>, 'INT8MULTIRANGE': <TokenType.INT8MULTIRANGE: 'INT8MULTIRANGE'>, 'NUMRANGE': <TokenType.NUMRANGE: 'NUMRANGE'>, 'NUMMULTIRANGE': <TokenType.NUMMULTIRANGE: 'NUMMULTIRANGE'>, 'TSRANGE': <TokenType.TSRANGE: 'TSRANGE'>, 'TSMULTIRANGE': <TokenType.TSMULTIRANGE: 'TSMULTIRANGE'>, 'TSTZRANGE': <TokenType.TSTZRANGE: 'TSTZRANGE'>, 'TSTZMULTIRANGE': <TokenType.TSTZMULTIRANGE: 'TSTZMULTIRANGE'>, 'DATERANGE': <TokenType.DATERANGE: 'DATERANGE'>, 'DATEMULTIRANGE': <TokenType.DATEMULTIRANGE: 'DATEMULTIRANGE'>, 'UNIQUE': <TokenType.UNIQUE: 'UNIQUE'>, 'VECTOR': <TokenType.VECTOR: 'VECTOR'>, 'STRUCT': <TokenType.STRUCT: 'STRUCT'>, 'SEQUENCE': <TokenType.SEQUENCE: 'SEQUENCE'>, 'VARIANT': <TokenType.VARIANT: 'VARIANT'>, 'ALTER': <TokenType.ALTER: 'ALTER'>, 'ANALYZE': <TokenType.ANALYZE: 'ANALYZE'>, 'CALL': <TokenType.COMMAND: 'COMMAND'>, 'COMMENT': <TokenType.COMMENT: 'COMMENT'>, 'EXPLAIN': <TokenType.COMMAND: 'COMMAND'>, 'GRANT': <TokenType.GRANT: 'GRANT'>, 'REVOKE': <TokenType.REVOKE: 'REVOKE'>, 'OPTIMIZE': <TokenType.COMMAND: 'COMMAND'>, 'PREPARE': <TokenType.COMMAND: 'COMMAND'>, 'VACUUM': <TokenType.COMMAND: 'COMMAND'>, 'USER-DEFINED': <TokenType.USERDEFINED: 'USERDEFINED'>, 'FOR VERSION': <TokenType.VERSION_SNAPSHOT: 'VERSION_SNAPSHOT'>, 'FOR TIMESTAMP': <TokenType.TIMESTAMP_SNAPSHOT: 'TIMESTAMP_SNAPSHOT'>, '~': <TokenType.RLIKE: 'RLIKE'>, '@@': <TokenType.DAT: 'DAT'>, '@>': <TokenType.AT_GT: 'AT_GT'>, '<@': <TokenType.LT_AT: 'LT_AT'>, '?&': <TokenType.QMARK_AMP: 'QMARK_AMP'>, '?|': <TokenType.QMARK_PIPE: 'QMARK_PIPE'>, '#-': <TokenType.HASH_DASH: 'HASH_DASH'>, '|/': <TokenType.PIPE_SLASH: 'PIPE_SLASH'>, '||/': <TokenType.DPIPE_SLASH: 'DPIPE_SLASH'>, 'BIGSERIAL': <TokenType.BIGSERIAL: 'BIGSERIAL'>, 'CONSTRAINT TRIGGER': <TokenType.COMMAND: 'COMMAND'>, 'CSTRING': <TokenType.PSEUDO_TYPE: 'PSEUDO_TYPE'>, 'DECLARE': <TokenType.COMMAND: 'COMMAND'>, 'DO': <TokenType.COMMAND: 'COMMAND'>, 'EXEC': <TokenType.COMMAND: 'COMMAND'>, 'HSTORE': <TokenType.HSTORE: 'HSTORE'>, 'MONEY': <TokenType.MONEY: 'MONEY'>, 'NAME': <TokenType.NAME: 'NAME'>, 'OID': <TokenType.OBJECT_IDENTIFIER: 'OBJECT_IDENTIFIER'>, 'ONLY': <TokenType.ONLY: 'ONLY'>, 'POINT': <TokenType.POINT: 'POINT'>, 'REFRESH': <TokenType.COMMAND: 'COMMAND'>, 'REINDEX': <TokenType.COMMAND: 'COMMAND'>, 'RESET': <TokenType.COMMAND: 'COMMAND'>, 'SERIAL': <TokenType.SERIAL: 'SERIAL'>, 'SMALLSERIAL': <TokenType.SMALLSERIAL: 'SMALLSERIAL'>, 'REGCLASS': <TokenType.OBJECT_IDENTIFIER: 'OBJECT_IDENTIFIER'>, 'REGCOLLATION': <TokenType.OBJECT_IDENTIFIER: 'OBJECT_IDENTIFIER'>, 'REGCONFIG': <TokenType.OBJECT_IDENTIFIER: 'OBJECT_IDENTIFIER'>, 'REGDICTIONARY': <TokenType.OBJECT_IDENTIFIER: 'OBJECT_IDENTIFIER'>, 'REGNAMESPACE': <TokenType.OBJECT_IDENTIFIER: 'OBJECT_IDENTIFIER'>, 'REGOPER': <TokenType.OBJECT_IDENTIFIER: 'OBJECT_IDENTIFIER'>, 'REGOPERATOR': <TokenType.OBJECT_IDENTIFIER: 'OBJECT_IDENTIFIER'>, 'REGPROC': <TokenType.OBJECT_IDENTIFIER: 'OBJECT_IDENTIFIER'>, 'REGPROCEDURE': <TokenType.OBJECT_IDENTIFIER: 'OBJECT_IDENTIFIER'>, 'REGROLE': <TokenType.OBJECT_IDENTIFIER: 'OBJECT_IDENTIFIER'>, 'REGTYPE': <TokenType.OBJECT_IDENTIFIER: 'OBJECT_IDENTIFIER'>, 'XML': <TokenType.XML: 'XML'>, 'VARIADIC': <TokenType.VARIADIC: 'VARIADIC'>, 'INOUT': <TokenType.INOUT: 'INOUT'>}
SINGLE_TOKENS = {'(': <TokenType.L_PAREN: 'L_PAREN'>, ')': <TokenType.R_PAREN: 'R_PAREN'>, '[': <TokenType.L_BRACKET: 'L_BRACKET'>, ']': <TokenType.R_BRACKET: 'R_BRACKET'>, '{': <TokenType.L_BRACE: 'L_BRACE'>, '}': <TokenType.R_BRACE: 'R_BRACE'>, '&': <TokenType.AMP: 'AMP'>, '^': <TokenType.CARET: 'CARET'>, ':': <TokenType.COLON: 'COLON'>, ',': <TokenType.COMMA: 'COMMA'>, '.': <TokenType.DOT: 'DOT'>, '-': <TokenType.DASH: 'DASH'>, '=': <TokenType.EQ: 'EQ'>, '>': <TokenType.GT: 'GT'>, '<': <TokenType.LT: 'LT'>, '%': <TokenType.MOD: 'MOD'>, '!': <TokenType.NOT: 'NOT'>, '|': <TokenType.PIPE: 'PIPE'>, '+': <TokenType.PLUS: 'PLUS'>, ';': <TokenType.SEMICOLON: 'SEMICOLON'>, '/': <TokenType.SLASH: 'SLASH'>, '\\': <TokenType.BACKSLASH: 'BACKSLASH'>, '*': <TokenType.STAR: 'STAR'>, '~': <TokenType.TILDE: 'TILDE'>, '?': <TokenType.PLACEHOLDER: 'PLACEHOLDER'>, '@': <TokenType.PARAMETER: 'PARAMETER'>, '#': <TokenType.HASH: 'HASH'>, "'": <TokenType.UNKNOWN: 'UNKNOWN'>, '`': <TokenType.UNKNOWN: 'UNKNOWN'>, '"': <TokenType.UNKNOWN: 'UNKNOWN'>, '$': <TokenType.HEREDOC_STRING: 'HEREDOC_STRING'>}
VAR_SINGLE_TOKENS = {'$'}
class Postgres.Parser(sqlglot.parser.Parser):
415    class Parser(parser.Parser):
416        SUPPORTS_OMITTED_INTERVAL_SPAN_UNIT = True
417
418        PROPERTY_PARSERS = {
419            **parser.Parser.PROPERTY_PARSERS,
420            "SET": lambda self: self.expression(exp.SetConfigProperty, this=self._parse_set()),
421        }
422        PROPERTY_PARSERS.pop("INPUT")
423
424        PLACEHOLDER_PARSERS = {
425            **parser.Parser.PLACEHOLDER_PARSERS,
426            TokenType.PLACEHOLDER: lambda self: self.expression(exp.Placeholder, jdbc=True),
427            TokenType.MOD: lambda self: self._parse_query_parameter(),
428        }
429
430        FUNCTIONS = {
431            **parser.Parser.FUNCTIONS,
432            "ARRAY_PREPEND": lambda args: exp.ArrayPrepend(
433                this=seq_get(args, 1), expression=seq_get(args, 0)
434            ),
435            "BIT_AND": exp.BitwiseAndAgg.from_arg_list,
436            "BIT_OR": exp.BitwiseOrAgg.from_arg_list,
437            "BIT_XOR": exp.BitwiseXorAgg.from_arg_list,
438            "DATE_TRUNC": build_timestamp_trunc,
439            "DIV": lambda args: exp.cast(
440                binary_from_function(exp.IntDiv)(args), exp.DataType.Type.DECIMAL
441            ),
442            "GENERATE_SERIES": _build_generate_series,
443            "GET_BIT": lambda args: exp.Getbit(
444                this=seq_get(args, 0), expression=seq_get(args, 1), zero_is_msb=True
445            ),
446            "JSON_EXTRACT_PATH": build_json_extract_path(exp.JSONExtract),
447            "JSON_EXTRACT_PATH_TEXT": build_json_extract_path(exp.JSONExtractScalar),
448            "LENGTH": lambda args: exp.Length(this=seq_get(args, 0), encoding=seq_get(args, 1)),
449            "MAKE_TIME": exp.TimeFromParts.from_arg_list,
450            "MAKE_TIMESTAMP": exp.TimestampFromParts.from_arg_list,
451            "NOW": exp.CurrentTimestamp.from_arg_list,
452            "REGEXP_REPLACE": _build_regexp_replace,
453            "TO_CHAR": build_formatted_time(exp.TimeToStr, "postgres"),
454            "TO_DATE": build_formatted_time(exp.StrToDate, "postgres"),
455            "TO_TIMESTAMP": _build_to_timestamp,
456            "UNNEST": exp.Explode.from_arg_list,
457            "SHA256": lambda args: exp.SHA2(this=seq_get(args, 0), length=exp.Literal.number(256)),
458            "SHA384": lambda args: exp.SHA2(this=seq_get(args, 0), length=exp.Literal.number(384)),
459            "SHA512": lambda args: exp.SHA2(this=seq_get(args, 0), length=exp.Literal.number(512)),
460            "LEVENSHTEIN_LESS_EQUAL": _build_levenshtein_less_equal,
461            "JSON_OBJECT_AGG": lambda args: exp.JSONObjectAgg(expressions=args),
462            "JSONB_OBJECT_AGG": exp.JSONBObjectAgg.from_arg_list,
463            "WIDTH_BUCKET": lambda args: exp.WidthBucket(
464                this=seq_get(args, 0), threshold=seq_get(args, 1)
465            )
466            if len(args) == 2
467            else exp.WidthBucket.from_arg_list(args),
468        }
469
470        NO_PAREN_FUNCTION_PARSERS = {
471            **parser.Parser.NO_PAREN_FUNCTION_PARSERS,
472            "VARIADIC": lambda self: self.expression(exp.Variadic, this=self._parse_bitwise()),
473        }
474
475        NO_PAREN_FUNCTIONS = {
476            **parser.Parser.NO_PAREN_FUNCTIONS,
477            TokenType.CURRENT_SCHEMA: exp.CurrentSchema,
478        }
479
480        FUNCTION_PARSERS = {
481            **parser.Parser.FUNCTION_PARSERS,
482            "DATE_PART": lambda self: self._parse_date_part(),
483            "JSON_AGG": lambda self: self.expression(
484                exp.JSONArrayAgg,
485                this=self._parse_lambda(),
486                order=self._parse_order(),
487            ),
488            "JSONB_EXISTS": lambda self: self._parse_jsonb_exists(),
489        }
490
491        BITWISE = {
492            **parser.Parser.BITWISE,
493            TokenType.HASH: exp.BitwiseXor,
494        }
495
496        EXPONENT = {
497            TokenType.CARET: exp.Pow,
498        }
499
500        RANGE_PARSERS = {
501            **parser.Parser.RANGE_PARSERS,
502            TokenType.DAMP: binary_range_parser(exp.ArrayOverlaps),
503            TokenType.DAT: lambda self, this: self.expression(
504                exp.MatchAgainst, this=self._parse_bitwise(), expressions=[this]
505            ),
506        }
507
508        STATEMENT_PARSERS = {
509            **parser.Parser.STATEMENT_PARSERS,
510            TokenType.END: lambda self: self._parse_commit_or_rollback(),
511        }
512
513        UNARY_PARSERS = {
514            **parser.Parser.UNARY_PARSERS,
515            # The `~` token is remapped from TILDE to RLIKE in Postgres due to the binary REGEXP LIKE operator
516            TokenType.RLIKE: lambda self: self.expression(exp.BitwiseNot, this=self._parse_unary()),
517        }
518
519        JSON_ARROWS_REQUIRE_JSON_TYPE = True
520
521        COLUMN_OPERATORS = {
522            **parser.Parser.COLUMN_OPERATORS,
523            TokenType.ARROW: lambda self, this, path: self.validate_expression(
524                build_json_extract_path(
525                    exp.JSONExtract, arrow_req_json_type=self.JSON_ARROWS_REQUIRE_JSON_TYPE
526                )([this, path])
527            ),
528            TokenType.DARROW: lambda self, this, path: self.validate_expression(
529                build_json_extract_path(
530                    exp.JSONExtractScalar, arrow_req_json_type=self.JSON_ARROWS_REQUIRE_JSON_TYPE
531                )([this, path])
532            ),
533        }
534
535        ARG_MODE_TOKENS = {TokenType.IN, TokenType.OUT, TokenType.INOUT, TokenType.VARIADIC}
536
537        def _parse_parameter_mode(self) -> t.Optional[TokenType]:
538            """
539            Parse PostgreSQL function parameter mode (IN, OUT, INOUT, VARIADIC).
540
541            Disambiguates between mode keywords and identifiers with the same name:
542            - MODE TYPE      → keyword is identifier (e.g., "out INT")
543            - MODE NAME TYPE → keyword is mode (e.g., "OUT x INT")
544
545            Returns:
546                Mode token type if current token is a mode keyword, None otherwise.
547            """
548            if not self._match_set(self.ARG_MODE_TOKENS, advance=False) or not self._next:
549                return None
550
551            mode_token = self._curr
552
553            # Check Pattern 1: MODE TYPE
554            # Try parsing next token as a built-in type (not UDT)
555            # If successful, the keyword is an identifier, not a mode
556            is_followed_by_builtin_type = self._try_parse(
557                lambda: self._advance()  # type: ignore
558                or self._parse_types(check_func=False, allow_identifiers=False),
559                retreat=True,
560            )
561            if is_followed_by_builtin_type:
562                return None  # Pattern: "out INT" → out is parameter name
563
564            # Check Pattern 2: MODE NAME TYPE
565            # If next token is an identifier, check if there's a type after it
566            # The type can be built-in or user-defined (allow_identifiers=True)
567            if self._next.token_type not in self.ID_VAR_TOKENS:
568                return None
569
570            is_followed_by_any_type = self._try_parse(
571                lambda: self._advance(2)  # type: ignore
572                or self._parse_types(check_func=False, allow_identifiers=True),
573                retreat=True,
574            )
575
576            if is_followed_by_any_type:
577                return mode_token.token_type  # Pattern: "OUT x INT" → OUT is mode
578
579            return None
580
581        def _create_mode_constraint(self, param_mode: TokenType) -> exp.InOutColumnConstraint:
582            """
583            Create parameter mode constraint for function parameters.
584
585            Args:
586                param_mode: The parameter mode token (IN, OUT, INOUT, or VARIADIC).
587
588            Returns:
589                InOutColumnConstraint expression representing the parameter mode.
590            """
591            return self.expression(
592                exp.InOutColumnConstraint,
593                input_=(param_mode in {TokenType.IN, TokenType.INOUT}),
594                output=(param_mode in {TokenType.OUT, TokenType.INOUT}),
595                variadic=(param_mode == TokenType.VARIADIC),
596            )
597
598        def _parse_function_parameter(self) -> t.Optional[exp.Expression]:
599            param_mode = self._parse_parameter_mode()
600
601            if param_mode:
602                self._advance()
603
604            # Parse parameter name and type
605            param_name = self._parse_id_var()
606            column_def = self._parse_column_def(this=param_name, computed_column=False)
607
608            # Attach mode as constraint
609            if param_mode and column_def:
610                constraint = self._create_mode_constraint(param_mode)
611                if not column_def.args.get("constraints"):
612                    column_def.set("constraints", [])
613                column_def.args["constraints"].insert(0, constraint)
614
615            return column_def
616
617        def _parse_query_parameter(self) -> t.Optional[exp.Expression]:
618            this = (
619                self._parse_wrapped(self._parse_id_var)
620                if self._match(TokenType.L_PAREN, advance=False)
621                else None
622            )
623            self._match_text_seq("S")
624            return self.expression(exp.Placeholder, this=this)
625
626        def _parse_date_part(self) -> exp.Expression:
627            part = self._parse_type()
628            self._match(TokenType.COMMA)
629            value = self._parse_bitwise()
630
631            if part and isinstance(part, (exp.Column, exp.Literal)):
632                part = exp.var(part.name)
633
634            return self.expression(exp.Extract, this=part, expression=value)
635
636        def _parse_unique_key(self) -> t.Optional[exp.Expression]:
637            return None
638
639        def _parse_jsonb_exists(self) -> exp.JSONBExists:
640            return self.expression(
641                exp.JSONBExists,
642                this=self._parse_bitwise(),
643                path=self._match(TokenType.COMMA)
644                and self.dialect.to_json_path(self._parse_bitwise()),
645            )
646
647        def _parse_generated_as_identity(
648            self,
649        ) -> (
650            exp.GeneratedAsIdentityColumnConstraint
651            | exp.ComputedColumnConstraint
652            | exp.GeneratedAsRowColumnConstraint
653        ):
654            this = super()._parse_generated_as_identity()
655
656            if self._match_text_seq("STORED"):
657                this = self.expression(exp.ComputedColumnConstraint, this=this.expression)
658
659            return this
660
661        def _parse_user_defined_type(
662            self, identifier: exp.Identifier
663        ) -> t.Optional[exp.Expression]:
664            udt_type: exp.Identifier | exp.Dot = identifier
665
666            while self._match(TokenType.DOT):
667                part = self._parse_id_var()
668                if part:
669                    udt_type = exp.Dot(this=udt_type, expression=part)
670
671            return exp.DataType.build(udt_type, udt=True)

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: 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
SUPPORTS_OMITTED_INTERVAL_SPAN_UNIT = True
PROPERTY_PARSERS = {'ALLOWED_VALUES': <function Parser.<lambda>>, 'ALGORITHM': <function Parser.<lambda>>, 'AUTO': <function Parser.<lambda>>, 'AUTO_INCREMENT': <function Parser.<lambda>>, 'BACKUP': <function Parser.<lambda>>, 'BLOCKCOMPRESSION': <function Parser.<lambda>>, 'CHARSET': <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>>, 'CONTAINS': <function Parser.<lambda>>, 'COPY': <function Parser.<lambda>>, 'DATABLOCKSIZE': <function Parser.<lambda>>, 'DATA_DELETION': <function Parser.<lambda>>, 'DEFINER': <function Parser.<lambda>>, 'DETERMINISTIC': <function Parser.<lambda>>, 'DISTRIBUTED': <function Parser.<lambda>>, 'DUPLICATE': <function Parser.<lambda>>, 'DYNAMIC': <function Parser.<lambda>>, 'DISTKEY': <function Parser.<lambda>>, 'DISTSTYLE': <function Parser.<lambda>>, 'EMPTY': <function Parser.<lambda>>, 'ENGINE': <function Parser.<lambda>>, 'ENVIRONMENT': <function Parser.<lambda>>, 'EXECUTE': <function Parser.<lambda>>, 'EXTERNAL': <function Parser.<lambda>>, 'FALLBACK': <function Parser.<lambda>>, 'FORMAT': <function Parser.<lambda>>, 'FREESPACE': <function Parser.<lambda>>, 'GLOBAL': <function Parser.<lambda>>, 'HEAP': <function Parser.<lambda>>, 'ICEBERG': <function Parser.<lambda>>, 'IMMUTABLE': <function Parser.<lambda>>, 'INHERITS': <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>>, 'MODIFIES': <function Parser.<lambda>>, 'MULTISET': <function Parser.<lambda>>, 'NO': <function Parser.<lambda>>, 'ON': <function Parser.<lambda>>, 'ORDER BY': <function Parser.<lambda>>, 'OUTPUT': <function Parser.<lambda>>, 'PARTITION': <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>>, 'READS': <function Parser.<lambda>>, 'REMOTE': <function Parser.<lambda>>, 'RETURNS': <function Parser.<lambda>>, 'STRICT': <function Parser.<lambda>>, 'STREAMING': <function Parser.<lambda>>, 'ROW': <function Parser.<lambda>>, 'ROW_FORMAT': <function Parser.<lambda>>, 'SAMPLE': <function Parser.<lambda>>, 'SECURE': <function Parser.<lambda>>, 'SECURITY': <function Parser.<lambda>>, 'SET': <function Postgres.Parser.<lambda>>, 'SETTINGS': <function Parser.<lambda>>, 'SHARING': <function Parser.<lambda>>, 'SORTKEY': <function Parser.<lambda>>, 'SOURCE': <function Parser.<lambda>>, 'STABLE': <function Parser.<lambda>>, 'STORED': <function Parser.<lambda>>, 'SYSTEM_VERSIONING': <function Parser.<lambda>>, 'TBLPROPERTIES': <function Parser.<lambda>>, 'TEMP': <function Parser.<lambda>>, 'TEMPORARY': <function Parser.<lambda>>, 'TO': <function Parser.<lambda>>, 'TRANSIENT': <function Parser.<lambda>>, 'TRANSFORM': <function Parser.<lambda>>, 'TTL': <function Parser.<lambda>>, 'USING': <function Parser.<lambda>>, 'UNLOGGED': <function Parser.<lambda>>, 'VOLATILE': <function Parser.<lambda>>, 'WITH': <function Parser.<lambda>>}
PLACEHOLDER_PARSERS = {<TokenType.PLACEHOLDER: 'PLACEHOLDER'>: <function Postgres.Parser.<lambda>>, <TokenType.PARAMETER: 'PARAMETER'>: <function Parser.<lambda>>, <TokenType.COLON: 'COLON'>: <function Parser.<lambda>>, <TokenType.MOD: 'MOD'>: <function Postgres.Parser.<lambda>>}
FUNCTIONS = {'AI_AGG': <bound method Func.from_arg_list of <class 'sqlglot.expressions.AIAgg'>>, 'AI_CLASSIFY': <bound method Func.from_arg_list of <class 'sqlglot.expressions.AIClassify'>>, 'AI_SUMMARIZE_AGG': <bound method Func.from_arg_list of <class 'sqlglot.expressions.AISummarizeAgg'>>, 'ABS': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Abs'>>, 'ACOS': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Acos'>>, 'ACOSH': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Acosh'>>, 'ADD_MONTHS': <bound method Func.from_arg_list of <class 'sqlglot.expressions.AddMonths'>>, 'AND': <bound method Func.from_arg_list of <class 'sqlglot.expressions.And'>>, 'ANONYMOUS_AGG_FUNC': <bound method Func.from_arg_list of <class 'sqlglot.expressions.AnonymousAggFunc'>>, 'ANY_VALUE': <bound method Func.from_arg_list of <class 'sqlglot.expressions.AnyValue'>>, 'APPLY': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Apply'>>, '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_PERCENTILE_ACCUMULATE': <bound method Func.from_arg_list of <class 'sqlglot.expressions.ApproxPercentileAccumulate'>>, 'APPROX_PERCENTILE_COMBINE': <bound method Func.from_arg_list of <class 'sqlglot.expressions.ApproxPercentileCombine'>>, 'APPROX_PERCENTILE_ESTIMATE': <bound method Func.from_arg_list of <class 'sqlglot.expressions.ApproxPercentileEstimate'>>, 'APPROX_QUANTILE': <bound method Func.from_arg_list of <class 'sqlglot.expressions.ApproxQuantile'>>, 'APPROX_QUANTILES': <bound method Func.from_arg_list of <class 'sqlglot.expressions.ApproxQuantiles'>>, 'APPROX_TOP_K': <bound method Func.from_arg_list of <class 'sqlglot.expressions.ApproxTopK'>>, 'APPROX_TOP_K_ACCUMULATE': <bound method Func.from_arg_list of <class 'sqlglot.expressions.ApproxTopKAccumulate'>>, 'APPROX_TOP_K_COMBINE': <bound method Func.from_arg_list of <class 'sqlglot.expressions.ApproxTopKCombine'>>, 'APPROX_TOP_K_ESTIMATE': <bound method Func.from_arg_list of <class 'sqlglot.expressions.ApproxTopKEstimate'>>, 'APPROX_TOP_SUM': <bound method Func.from_arg_list of <class 'sqlglot.expressions.ApproxTopSum'>>, 'APPROXIMATE_SIMILARITY': <bound method Func.from_arg_list of <class 'sqlglot.expressions.ApproximateSimilarity'>>, 'APPROXIMATE_JACCARD_INDEX': <bound method Func.from_arg_list of <class 'sqlglot.expressions.ApproximateSimilarity'>>, 'ARG_MAX': <bound method Func.from_arg_list of <class 'sqlglot.expressions.ArgMax'>>, 'ARGMAX': <bound method Func.from_arg_list of <class 'sqlglot.expressions.ArgMax'>>, 'MAX_BY': <bound method Func.from_arg_list of <class 'sqlglot.expressions.ArgMax'>>, 'ARG_MIN': <bound method Func.from_arg_list of <class 'sqlglot.expressions.ArgMin'>>, 'ARGMIN': <bound method Func.from_arg_list of <class 'sqlglot.expressions.ArgMin'>>, 'MIN_BY': <bound method Func.from_arg_list of <class 'sqlglot.expressions.ArgMin'>>, 'ARRAY': <function Parser.<lambda>>, 'ARRAY_AGG': <function Parser.<lambda>>, '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_APPEND': <function build_array_append>, 'ARRAY_COMPACT': <bound method Func.from_arg_list of <class 'sqlglot.expressions.ArrayCompact'>>, 'ARRAY_CONCAT': <function build_array_concat>, 'ARRAY_CAT': <function build_array_concat>, 'ARRAY_CONCAT_AGG': <bound method Func.from_arg_list of <class 'sqlglot.expressions.ArrayConcatAgg'>>, 'ARRAY_CONSTRUCT_COMPACT': <bound method Func.from_arg_list of <class 'sqlglot.expressions.ArrayConstructCompact'>>, 'ARRAY_CONTAINS': <bound method Func.from_arg_list of <class 'sqlglot.expressions.ArrayContains'>>, 'ARRAY_HAS': <bound method Func.from_arg_list of <class 'sqlglot.expressions.ArrayContains'>>, 'ARRAY_CONTAINS_ALL': <bound method Func.from_arg_list of <class 'sqlglot.expressions.ArrayContainsAll'>>, 'ARRAY_HAS_ALL': <bound method Func.from_arg_list of <class 'sqlglot.expressions.ArrayContainsAll'>>, '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_FIRST': <bound method Func.from_arg_list of <class 'sqlglot.expressions.ArrayFirst'>>, 'ARRAY_INSERT': <bound method Func.from_arg_list of <class 'sqlglot.expressions.ArrayInsert'>>, 'ARRAY_INTERSECT': <bound method Func.from_arg_list of <class 'sqlglot.expressions.ArrayIntersect'>>, 'ARRAY_INTERSECTION': <bound method Func.from_arg_list of <class 'sqlglot.expressions.ArrayIntersect'>>, 'ARRAY_LAST': <bound method Func.from_arg_list of <class 'sqlglot.expressions.ArrayLast'>>, 'ARRAY_OVERLAPS': <bound method Func.from_arg_list of <class 'sqlglot.expressions.ArrayOverlaps'>>, 'ARRAY_PREPEND': <function Postgres.Parser.<lambda>>, 'ARRAY_REMOVE': <function build_array_remove>, 'ARRAY_REVERSE': <bound method Func.from_arg_list of <class 'sqlglot.expressions.ArrayReverse'>>, 'ARRAY_SIZE': <bound method Func.from_arg_list of <class 'sqlglot.expressions.ArraySize'>>, 'ARRAY_LENGTH': <bound method Func.from_arg_list of <class 'sqlglot.expressions.ArraySize'>>, 'ARRAY_SLICE': <bound method Func.from_arg_list of <class 'sqlglot.expressions.ArraySlice'>>, '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_TO_STRING': <bound method Func.from_arg_list of <class 'sqlglot.expressions.ArrayToString'>>, 'ARRAY_JOIN': <bound method Func.from_arg_list of <class 'sqlglot.expressions.ArrayToString'>>, 'ARRAY_UNION_AGG': <bound method Func.from_arg_list of <class 'sqlglot.expressions.ArrayUnionAgg'>>, 'ARRAY_UNIQUE_AGG': <bound method Func.from_arg_list of <class 'sqlglot.expressions.ArrayUniqueAgg'>>, 'ARRAYS_ZIP': <bound method Func.from_arg_list of <class 'sqlglot.expressions.ArraysZip'>>, 'ASCII': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Ascii'>>, 'ASIN': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Asin'>>, 'ASINH': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Asinh'>>, 'ATAN': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Atan'>>, 'ATAN2': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Atan2'>>, 'ATANH': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Atanh'>>, 'AVG': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Avg'>>, 'BASE64_DECODE_BINARY': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Base64DecodeBinary'>>, 'BASE64_DECODE_STRING': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Base64DecodeString'>>, 'BASE64_ENCODE': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Base64Encode'>>, 'BIT_LENGTH': <bound method Func.from_arg_list of <class 'sqlglot.expressions.BitLength'>>, 'BITMAP_BIT_POSITION': <bound method Func.from_arg_list of <class 'sqlglot.expressions.BitmapBitPosition'>>, 'BITMAP_BUCKET_NUMBER': <bound method Func.from_arg_list of <class 'sqlglot.expressions.BitmapBucketNumber'>>, 'BITMAP_CONSTRUCT_AGG': <bound method Func.from_arg_list of <class 'sqlglot.expressions.BitmapConstructAgg'>>, 'BITMAP_COUNT': <bound method Func.from_arg_list of <class 'sqlglot.expressions.BitmapCount'>>, 'BITMAP_OR_AGG': <bound method Func.from_arg_list of <class 'sqlglot.expressions.BitmapOrAgg'>>, 'BITWISE_AND_AGG': <bound method Func.from_arg_list of <class 'sqlglot.expressions.BitwiseAndAgg'>>, 'BITWISE_COUNT': <bound method Func.from_arg_list of <class 'sqlglot.expressions.BitwiseCount'>>, 'BITWISE_OR_AGG': <bound method Func.from_arg_list of <class 'sqlglot.expressions.BitwiseOrAgg'>>, 'BITWISE_XOR_AGG': <bound method Func.from_arg_list of <class 'sqlglot.expressions.BitwiseXorAgg'>>, 'BOOLAND': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Booland'>>, 'BOOLNOT': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Boolnot'>>, 'BOOLOR': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Boolor'>>, 'BOOLXOR_AGG': <bound method Func.from_arg_list of <class 'sqlglot.expressions.BoolxorAgg'>>, 'BYTE_LENGTH': <bound method Func.from_arg_list of <class 'sqlglot.expressions.ByteLength'>>, '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'>>, 'CBRT': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Cbrt'>>, 'CEIL': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Ceil'>>, 'CEILING': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Ceil'>>, 'CHECK_JSON': <bound method Func.from_arg_list of <class 'sqlglot.expressions.CheckJson'>>, 'CHECK_XML': <bound method Func.from_arg_list of <class 'sqlglot.expressions.CheckXml'>>, 'CHR': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Chr'>>, 'CHAR': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Chr'>>, 'COALESCE': <function build_coalesce>, 'IFNULL': <function build_coalesce>, 'NVL': <function build_coalesce>, 'CODE_POINTS_TO_BYTES': <bound method Func.from_arg_list of <class 'sqlglot.expressions.CodePointsToBytes'>>, 'CODE_POINTS_TO_STRING': <bound method Func.from_arg_list of <class 'sqlglot.expressions.CodePointsToString'>>, 'COLLATE': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Collate'>>, 'COLLATION': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Collation'>>, 'COLUMNS': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Columns'>>, 'COMBINED_AGG_FUNC': <bound method Func.from_arg_list of <class 'sqlglot.expressions.CombinedAggFunc'>>, 'COMBINED_PARAMETERIZED_AGG': <bound method Func.from_arg_list of <class 'sqlglot.expressions.CombinedParameterizedAgg'>>, 'COMPRESS': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Compress'>>, 'CONCAT': <function Parser.<lambda>>, 'CONCAT_WS': <function Parser.<lambda>>, 'CONNECT_BY_ROOT': <bound method Func.from_arg_list of <class 'sqlglot.expressions.ConnectByRoot'>>, 'CONTAINS': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Contains'>>, 'CONVERT': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Convert'>>, 'CONVERT_TIMEZONE': <function build_convert_timezone>, 'CONVERT_TO_CHARSET': <bound method Func.from_arg_list of <class 'sqlglot.expressions.ConvertToCharset'>>, 'CORR': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Corr'>>, 'COS': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Cos'>>, 'COSH': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Cosh'>>, 'COSINE_DISTANCE': <bound method Func.from_arg_list of <class 'sqlglot.expressions.CosineDistance'>>, 'COT': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Cot'>>, 'COTH': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Coth'>>, 'COUNT': <function Parser.<lambda>>, 'COUNT_IF': <bound method Func.from_arg_list of <class 'sqlglot.expressions.CountIf'>>, 'COUNTIF': <bound method Func.from_arg_list of <class 'sqlglot.expressions.CountIf'>>, 'COVAR_POP': <bound method Func.from_arg_list of <class 'sqlglot.expressions.CovarPop'>>, 'COVAR_SAMP': <bound method Func.from_arg_list of <class 'sqlglot.expressions.CovarSamp'>>, 'CSC': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Csc'>>, 'CSCH': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Csch'>>, 'CUME_DIST': <bound method Func.from_arg_list of <class 'sqlglot.expressions.CumeDist'>>, 'CURRENT_ACCOUNT': <bound method Func.from_arg_list of <class 'sqlglot.expressions.CurrentAccount'>>, 'CURRENT_ACCOUNT_NAME': <bound method Func.from_arg_list of <class 'sqlglot.expressions.CurrentAccountName'>>, 'CURRENT_AVAILABLE_ROLES': <bound method Func.from_arg_list of <class 'sqlglot.expressions.CurrentAvailableRoles'>>, 'CURRENT_CATALOG': <bound method Func.from_arg_list of <class 'sqlglot.expressions.CurrentCatalog'>>, 'CURRENT_CLIENT': <bound method Func.from_arg_list of <class 'sqlglot.expressions.CurrentClient'>>, 'CURRENT_DATABASE': <bound method Func.from_arg_list of <class 'sqlglot.expressions.CurrentDatabase'>>, '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_IP_ADDRESS': <bound method Func.from_arg_list of <class 'sqlglot.expressions.CurrentIpAddress'>>, 'CURRENT_ORGANIZATION_NAME': <bound method Func.from_arg_list of <class 'sqlglot.expressions.CurrentOrganizationName'>>, 'CURRENT_ORGANIZATION_USER': <bound method Func.from_arg_list of <class 'sqlglot.expressions.CurrentOrganizationUser'>>, 'CURRENT_REGION': <bound method Func.from_arg_list of <class 'sqlglot.expressions.CurrentRegion'>>, 'CURRENT_ROLE': <bound method Func.from_arg_list of <class 'sqlglot.expressions.CurrentRole'>>, 'CURRENT_ROLE_TYPE': <bound method Func.from_arg_list of <class 'sqlglot.expressions.CurrentRoleType'>>, 'CURRENT_SCHEMA': <bound method Func.from_arg_list of <class 'sqlglot.expressions.CurrentSchema'>>, 'CURRENT_SCHEMAS': <bound method Func.from_arg_list of <class 'sqlglot.expressions.CurrentSchemas'>>, 'CURRENT_SECONDARY_ROLES': <bound method Func.from_arg_list of <class 'sqlglot.expressions.CurrentSecondaryRoles'>>, 'CURRENT_SESSION': <bound method Func.from_arg_list of <class 'sqlglot.expressions.CurrentSession'>>, 'CURRENT_STATEMENT': <bound method Func.from_arg_list of <class 'sqlglot.expressions.CurrentStatement'>>, '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_TIMESTAMP_L_T_Z': <bound method Func.from_arg_list of <class 'sqlglot.expressions.CurrentTimestampLTZ'>>, 'CURRENT_TIMEZONE': <bound method Func.from_arg_list of <class 'sqlglot.expressions.CurrentTimezone'>>, 'CURRENT_TRANSACTION': <bound method Func.from_arg_list of <class 'sqlglot.expressions.CurrentTransaction'>>, 'CURRENT_USER': <bound method Func.from_arg_list of <class 'sqlglot.expressions.CurrentUser'>>, 'CURRENT_VERSION': <bound method Func.from_arg_list of <class 'sqlglot.expressions.CurrentVersion'>>, 'CURRENT_WAREHOUSE': <bound method Func.from_arg_list of <class 'sqlglot.expressions.CurrentWarehouse'>>, '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'>>, 'DATE_BIN': <bound method Func.from_arg_list of <class 'sqlglot.expressions.DateBin'>>, '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'>>, 'DATE_FROM_PARTS': <bound method Func.from_arg_list of <class 'sqlglot.expressions.DateFromParts'>>, 'DATEFROMPARTS': <bound method Func.from_arg_list of <class 'sqlglot.expressions.DateFromParts'>>, 'DATE_FROM_UNIX_DATE': <bound method Func.from_arg_list of <class 'sqlglot.expressions.DateFromUnixDate'>>, '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': <function build_timestamp_trunc>, 'DATETIME': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Datetime'>>, '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'>>, 'DAYOFWEEK_ISO': <bound method Func.from_arg_list of <class 'sqlglot.expressions.DayOfWeekIso'>>, 'ISODOW': <bound method Func.from_arg_list of <class 'sqlglot.expressions.DayOfWeekIso'>>, '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'>>, 'DAYNAME': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Dayname'>>, 'DECODE': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Decode'>>, 'DECODE_CASE': <bound method Func.from_arg_list of <class 'sqlglot.expressions.DecodeCase'>>, 'DECOMPRESS_BINARY': <bound method Func.from_arg_list of <class 'sqlglot.expressions.DecompressBinary'>>, 'DECOMPRESS_STRING': <bound method Func.from_arg_list of <class 'sqlglot.expressions.DecompressString'>>, 'DECRYPT': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Decrypt'>>, 'DECRYPT_RAW': <bound method Func.from_arg_list of <class 'sqlglot.expressions.DecryptRaw'>>, 'DEGREES': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Degrees'>>, 'DENSE_RANK': <bound method Func.from_arg_list of <class 'sqlglot.expressions.DenseRank'>>, 'DI_TO_DATE': <bound method Func.from_arg_list of <class 'sqlglot.expressions.DiToDate'>>, 'DOT_PRODUCT': <bound method Func.from_arg_list of <class 'sqlglot.expressions.DotProduct'>>, 'ELT': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Elt'>>, 'ENCODE': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Encode'>>, 'ENCRYPT': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Encrypt'>>, 'ENCRYPT_RAW': <bound method Func.from_arg_list of <class 'sqlglot.expressions.EncryptRaw'>>, 'ENDS_WITH': <bound method Func.from_arg_list of <class 'sqlglot.expressions.EndsWith'>>, 'ENDSWITH': <bound method Func.from_arg_list of <class 'sqlglot.expressions.EndsWith'>>, 'EQUAL_NULL': <bound method Func.from_arg_list of <class 'sqlglot.expressions.EqualNull'>>, 'EUCLIDEAN_DISTANCE': <bound method Func.from_arg_list of <class 'sqlglot.expressions.EuclideanDistance'>>, 'EXISTS': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Exists'>>, 'EXP': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Exp'>>, 'EXPLODE': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Explode'>>, 'EXPLODE_OUTER': <bound method Func.from_arg_list of <class 'sqlglot.expressions.ExplodeOuter'>>, 'EXPLODING_GENERATE_SERIES': <bound method Func.from_arg_list of <class 'sqlglot.expressions.ExplodingGenerateSeries'>>, 'EXTRACT': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Extract'>>, 'FACTORIAL': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Factorial'>>, 'FARM_FINGERPRINT': <bound method Func.from_arg_list of <class 'sqlglot.expressions.FarmFingerprint'>>, 'FARMFINGERPRINT64': <bound method Func.from_arg_list of <class 'sqlglot.expressions.FarmFingerprint'>>, 'FEATURES_AT_TIME': <bound method Func.from_arg_list of <class 'sqlglot.expressions.FeaturesAtTime'>>, 'FIRST': <bound method Func.from_arg_list of <class 'sqlglot.expressions.First'>>, 'FIRST_VALUE': <bound method Func.from_arg_list of <class 'sqlglot.expressions.FirstValue'>>, 'FLATTEN': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Flatten'>>, 'FLOAT64': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Float64'>>, 'FLOOR': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Floor'>>, 'FORMAT': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Format'>>, 'FROM_BASE': <bound method Func.from_arg_list of <class 'sqlglot.expressions.FromBase'>>, 'FROM_BASE32': <bound method Func.from_arg_list of <class 'sqlglot.expressions.FromBase32'>>, 'FROM_BASE64': <bound method Func.from_arg_list of <class 'sqlglot.expressions.FromBase64'>>, 'FROM_ISO8601_TIMESTAMP': <bound method Func.from_arg_list of <class 'sqlglot.expressions.FromISO8601Timestamp'>>, 'GAP_FILL': <bound method Func.from_arg_list of <class 'sqlglot.expressions.GapFill'>>, 'GENERATE_DATE_ARRAY': <function Parser.<lambda>>, 'GENERATE_EMBEDDING': <bound method Func.from_arg_list of <class 'sqlglot.expressions.GenerateEmbedding'>>, 'GENERATE_SERIES': <function _build_generate_series>, 'GENERATE_TIMESTAMP_ARRAY': <bound method Func.from_arg_list of <class 'sqlglot.expressions.GenerateTimestampArray'>>, 'GENERATOR': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Generator'>>, 'GET_EXTRACT': <bound method Func.from_arg_list of <class 'sqlglot.expressions.GetExtract'>>, 'GETBIT': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Getbit'>>, 'GET_BIT': <function Postgres.Parser.<lambda>>, 'GREATEST': <function Parser.<lambda>>, 'GROUP_CONCAT': <bound method Func.from_arg_list of <class 'sqlglot.expressions.GroupConcat'>>, 'GROUPING': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Grouping'>>, 'GROUPING_ID': <bound method Func.from_arg_list of <class 'sqlglot.expressions.GroupingId'>>, 'HASH_AGG': <bound method Func.from_arg_list of <class 'sqlglot.expressions.HashAgg'>>, 'HEX': <function build_hex>, 'HEX_DECODE_STRING': <bound method Func.from_arg_list of <class 'sqlglot.expressions.HexDecodeString'>>, 'HEX_ENCODE': <bound method Func.from_arg_list of <class 'sqlglot.expressions.HexEncode'>>, 'HLL': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Hll'>>, 'HOST': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Host'>>, 'HOUR': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Hour'>>, 'IF': <bound method Func.from_arg_list of <class 'sqlglot.expressions.If'>>, 'IIF': <bound method Func.from_arg_list of <class 'sqlglot.expressions.If'>>, 'INITCAP': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Initcap'>>, 'INLINE': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Inline'>>, 'INT64': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Int64'>>, 'IS_ARRAY': <bound method Func.from_arg_list of <class 'sqlglot.expressions.IsArray'>>, 'IS_ASCII': <bound method Func.from_arg_list of <class 'sqlglot.expressions.IsAscii'>>, 'IS_INF': <bound method Func.from_arg_list of <class 'sqlglot.expressions.IsInf'>>, 'ISINF': <bound method Func.from_arg_list of <class 'sqlglot.expressions.IsInf'>>, 'IS_NAN': <bound method Func.from_arg_list of <class 'sqlglot.expressions.IsNan'>>, 'ISNAN': <bound method Func.from_arg_list of <class 'sqlglot.expressions.IsNan'>>, 'IS_NULL_VALUE': <bound method Func.from_arg_list of <class 'sqlglot.expressions.IsNullValue'>>, 'J_S_O_N_ARRAY': <bound method Func.from_arg_list of <class 'sqlglot.expressions.JSONArray'>>, 'J_S_O_N_ARRAY_AGG': <bound method Func.from_arg_list of <class 'sqlglot.expressions.JSONArrayAgg'>>, 'JSON_ARRAY_APPEND': <bound method Func.from_arg_list of <class 'sqlglot.expressions.JSONArrayAppend'>>, 'JSON_ARRAY_CONTAINS': <bound method Func.from_arg_list of <class 'sqlglot.expressions.JSONArrayContains'>>, 'JSON_ARRAY_INSERT': <bound method Func.from_arg_list of <class 'sqlglot.expressions.JSONArrayInsert'>>, 'JSONB_CONTAINS': <bound method Func.from_arg_list of <class 'sqlglot.expressions.JSONBContains'>>, 'J_S_O_N_B_CONTAINS_ALL_TOP_KEYS': <bound method Func.from_arg_list of <class 'sqlglot.expressions.JSONBContainsAllTopKeys'>>, 'J_S_O_N_B_CONTAINS_ANY_TOP_KEYS': <bound method Func.from_arg_list of <class 'sqlglot.expressions.JSONBContainsAnyTopKeys'>>, 'J_S_O_N_B_DELETE_AT_PATH': <bound method Func.from_arg_list of <class 'sqlglot.expressions.JSONBDeleteAtPath'>>, 'JSONB_EXISTS': <bound method Func.from_arg_list of <class 'sqlglot.expressions.JSONBExists'>>, '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'>>, 'J_S_O_N_B_OBJECT_AGG': <bound method Func.from_arg_list of <class 'sqlglot.expressions.JSONBObjectAgg'>>, 'J_S_O_N_BOOL': <bound method Func.from_arg_list of <class 'sqlglot.expressions.JSONBool'>>, 'J_S_O_N_CAST': <bound method Func.from_arg_list of <class 'sqlglot.expressions.JSONCast'>>, 'J_S_O_N_EXISTS': <bound method Func.from_arg_list of <class 'sqlglot.expressions.JSONExists'>>, 'JSON_EXTRACT': <function build_extract_json_with_path.<locals>._builder>, 'JSON_EXTRACT_ARRAY': <bound method Func.from_arg_list of <class 'sqlglot.expressions.JSONExtractArray'>>, 'JSON_EXTRACT_SCALAR': <function build_extract_json_with_path.<locals>._builder>, 'JSON_FORMAT': <bound method Func.from_arg_list of <class 'sqlglot.expressions.JSONFormat'>>, 'JSON_KEYS': <function Parser.<lambda>>, 'J_S_O_N_KEYS_AT_DEPTH': <bound method Func.from_arg_list of <class 'sqlglot.expressions.JSONKeysAtDepth'>>, 'J_S_O_N_OBJECT': <bound method Func.from_arg_list of <class 'sqlglot.expressions.JSONObject'>>, 'J_S_O_N_OBJECT_AGG': <bound method Func.from_arg_list of <class 'sqlglot.expressions.JSONObjectAgg'>>, 'JSON_REMOVE': <bound method Func.from_arg_list of <class 'sqlglot.expressions.JSONRemove'>>, 'JSON_SET': <bound method Func.from_arg_list of <class 'sqlglot.expressions.JSONSet'>>, 'JSON_STRIP_NULLS': <bound method Func.from_arg_list of <class 'sqlglot.expressions.JSONStripNulls'>>, 'J_S_O_N_TABLE': <bound method Func.from_arg_list of <class 'sqlglot.expressions.JSONTable'>>, 'JSON_TYPE': <bound method Func.from_arg_list of <class 'sqlglot.expressions.JSONType'>>, 'J_S_O_N_VALUE_ARRAY': <bound method Func.from_arg_list of <class 'sqlglot.expressions.JSONValueArray'>>, 'JAROWINKLER_SIMILARITY': <bound method Func.from_arg_list of <class 'sqlglot.expressions.JarowinklerSimilarity'>>, 'JUSTIFY_DAYS': <bound method Func.from_arg_list of <class 'sqlglot.expressions.JustifyDays'>>, 'JUSTIFY_HOURS': <bound method Func.from_arg_list of <class 'sqlglot.expressions.JustifyHours'>>, 'JUSTIFY_INTERVAL': <bound method Func.from_arg_list of <class 'sqlglot.expressions.JustifyInterval'>>, 'KURTOSIS': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Kurtosis'>>, 'LAG': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Lag'>>, 'LAST': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Last'>>, 'LAST_DAY': <bound method Func.from_arg_list of <class 'sqlglot.expressions.LastDay'>>, 'LAST_DAY_OF_MONTH': <bound method Func.from_arg_list of <class 'sqlglot.expressions.LastDay'>>, 'LAST_VALUE': <bound method Func.from_arg_list of <class 'sqlglot.expressions.LastValue'>>, 'LAX_BOOL': <bound method Func.from_arg_list of <class 'sqlglot.expressions.LaxBool'>>, 'LAX_FLOAT64': <bound method Func.from_arg_list of <class 'sqlglot.expressions.LaxFloat64'>>, 'LAX_INT64': <bound method Func.from_arg_list of <class 'sqlglot.expressions.LaxInt64'>>, 'LAX_STRING': <bound method Func.from_arg_list of <class 'sqlglot.expressions.LaxString'>>, 'LEAD': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Lead'>>, 'LEAST': <function Parser.<lambda>>, 'LEFT': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Left'>>, 'LENGTH': <function Postgres.Parser.<lambda>>, 'LEN': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Length'>>, 'CHAR_LENGTH': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Length'>>, 'CHARACTER_LENGTH': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Length'>>, 'LEVENSHTEIN': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Levenshtein'>>, 'LIST': <bound method Func.from_arg_list of <class 'sqlglot.expressions.List'>>, 'LN': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Ln'>>, 'LOCALTIME': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Localtime'>>, 'LOCALTIMESTAMP': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Localtimestamp'>>, 'LOG': <function build_logarithm>, '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': <function build_lower>, 'LCASE': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Lower'>>, 'LOWER_HEX': <bound method Func.from_arg_list of <class 'sqlglot.expressions.LowerHex'>>, 'MD5': <bound method Func.from_arg_list of <class 'sqlglot.expressions.MD5'>>, 'MD5_DIGEST': <bound method Func.from_arg_list of <class 'sqlglot.expressions.MD5Digest'>>, 'M_D5_NUMBER_LOWER64': <bound method Func.from_arg_list of <class 'sqlglot.expressions.MD5NumberLower64'>>, 'M_D5_NUMBER_UPPER64': <bound method Func.from_arg_list of <class 'sqlglot.expressions.MD5NumberUpper64'>>, 'M_L_FORECAST': <bound method Func.from_arg_list of <class 'sqlglot.expressions.MLForecast'>>, 'M_L_TRANSLATE': <bound method Func.from_arg_list of <class 'sqlglot.expressions.MLTranslate'>>, 'MAKE_INTERVAL': <bound method Func.from_arg_list of <class 'sqlglot.expressions.MakeInterval'>>, 'MANHATTAN_DISTANCE': <bound method Func.from_arg_list of <class 'sqlglot.expressions.ManhattanDistance'>>, 'MAP': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Map'>>, 'MAP_CAT': <bound method Func.from_arg_list of <class 'sqlglot.expressions.MapCat'>>, 'MAP_CONTAINS_KEY': <bound method Func.from_arg_list of <class 'sqlglot.expressions.MapContainsKey'>>, 'MAP_DELETE': <bound method Func.from_arg_list of <class 'sqlglot.expressions.MapDelete'>>, 'MAP_FROM_ENTRIES': <bound method Func.from_arg_list of <class 'sqlglot.expressions.MapFromEntries'>>, 'MAP_INSERT': <bound method Func.from_arg_list of <class 'sqlglot.expressions.MapInsert'>>, 'MAP_KEYS': <bound method Func.from_arg_list of <class 'sqlglot.expressions.MapKeys'>>, 'MAP_PICK': <bound method Func.from_arg_list of <class 'sqlglot.expressions.MapPick'>>, 'MAP_SIZE': <bound method Func.from_arg_list of <class 'sqlglot.expressions.MapSize'>>, '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'>>, 'MEDIAN': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Median'>>, 'MIN': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Min'>>, 'MINHASH': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Minhash'>>, 'MINHASH_COMBINE': <bound method Func.from_arg_list of <class 'sqlglot.expressions.MinhashCombine'>>, 'MINUTE': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Minute'>>, 'MODE': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Mode'>>, 'MONTH': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Month'>>, 'MONTHNAME': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Monthname'>>, 'MONTHS_BETWEEN': <bound method Func.from_arg_list of <class 'sqlglot.expressions.MonthsBetween'>>, 'NET_FUNC': <bound method Func.from_arg_list of <class 'sqlglot.expressions.NetFunc'>>, 'NEXT_DAY': <bound method Func.from_arg_list of <class 'sqlglot.expressions.NextDay'>>, 'NEXT_VALUE_FOR': <bound method Func.from_arg_list of <class 'sqlglot.expressions.NextValueFor'>>, 'NORMAL': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Normal'>>, 'NORMALIZE': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Normalize'>>, 'NTH_VALUE': <bound method Func.from_arg_list of <class 'sqlglot.expressions.NthValue'>>, 'NTILE': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Ntile'>>, 'NULLIF': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Nullif'>>, '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'>>, 'OBJECT_AGG': <bound method Func.from_arg_list of <class 'sqlglot.expressions.ObjectAgg'>>, 'OBJECT_INSERT': <bound method Func.from_arg_list of <class 'sqlglot.expressions.ObjectInsert'>>, 'OPEN_J_S_O_N': <bound method Func.from_arg_list of <class 'sqlglot.expressions.OpenJSON'>>, 'OR': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Or'>>, 'OVERLAY': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Overlay'>>, 'PAD': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Pad'>>, 'PARAMETERIZED_AGG': <bound method Func.from_arg_list of <class 'sqlglot.expressions.ParameterizedAgg'>>, 'PARSE_BIGNUMERIC': <bound method Func.from_arg_list of <class 'sqlglot.expressions.ParseBignumeric'>>, 'PARSE_DATETIME': <bound method Func.from_arg_list of <class 'sqlglot.expressions.ParseDatetime'>>, 'PARSE_IP': <bound method Func.from_arg_list of <class 'sqlglot.expressions.ParseIp'>>, 'PARSE_JSON': <bound method Func.from_arg_list of <class 'sqlglot.expressions.ParseJSON'>>, 'JSON_PARSE': <bound method Func.from_arg_list of <class 'sqlglot.expressions.ParseJSON'>>, 'PARSE_NUMERIC': <bound method Func.from_arg_list of <class 'sqlglot.expressions.ParseNumeric'>>, 'PARSE_TIME': <bound method Func.from_arg_list of <class 'sqlglot.expressions.ParseTime'>>, 'PARSE_URL': <bound method Func.from_arg_list of <class 'sqlglot.expressions.ParseUrl'>>, 'PERCENT_RANK': <bound method Func.from_arg_list of <class 'sqlglot.expressions.PercentRank'>>, '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'>>, 'PI': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Pi'>>, 'POSEXPLODE': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Posexplode'>>, 'POSEXPLODE_OUTER': <bound method Func.from_arg_list of <class 'sqlglot.expressions.PosexplodeOuter'>>, 'POWER': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Pow'>>, 'POW': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Pow'>>, 'PREDICT': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Predict'>>, 'PREVIOUS_DAY': <bound method Func.from_arg_list of <class 'sqlglot.expressions.PreviousDay'>>, 'QUANTILE': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Quantile'>>, 'QUARTER': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Quarter'>>, 'RADIANS': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Radians'>>, 'RAND': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Rand'>>, 'RANDOM': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Rand'>>, 'RANDN': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Randn'>>, 'RANDSTR': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Randstr'>>, 'RANGE_BUCKET': <bound method Func.from_arg_list of <class 'sqlglot.expressions.RangeBucket'>>, 'RANGE_N': <bound method Func.from_arg_list of <class 'sqlglot.expressions.RangeN'>>, 'RANK': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Rank'>>, 'READ_CSV': <bound method Func.from_arg_list of <class 'sqlglot.expressions.ReadCSV'>>, 'READ_PARQUET': <bound method Func.from_arg_list of <class 'sqlglot.expressions.ReadParquet'>>, 'REDUCE': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Reduce'>>, 'REG_DOMAIN': <bound method Func.from_arg_list of <class 'sqlglot.expressions.RegDomain'>>, 'REGEXP_COUNT': <bound method Func.from_arg_list of <class 'sqlglot.expressions.RegexpCount'>>, 'REGEXP_EXTRACT': <bound method Func.from_arg_list of <class 'sqlglot.expressions.RegexpExtract'>>, 'REGEXP_EXTRACT_ALL': <bound method Func.from_arg_list of <class 'sqlglot.expressions.RegexpExtractAll'>>, 'REGEXP_FULL_MATCH': <bound method Func.from_arg_list of <class 'sqlglot.expressions.RegexpFullMatch'>>, 'REGEXP_I_LIKE': <bound method Func.from_arg_list of <class 'sqlglot.expressions.RegexpILike'>>, 'REGEXP_INSTR': <bound method Func.from_arg_list of <class 'sqlglot.expressions.RegexpInstr'>>, 'REGEXP_LIKE': <bound method Func.from_arg_list of <class 'sqlglot.expressions.RegexpLike'>>, 'REGEXP_REPLACE': <function _build_regexp_replace>, 'REGEXP_SPLIT': <bound method Func.from_arg_list of <class 'sqlglot.expressions.RegexpSplit'>>, 'REGR_AVGX': <bound method Func.from_arg_list of <class 'sqlglot.expressions.RegrAvgx'>>, 'REGR_AVGY': <bound method Func.from_arg_list of <class 'sqlglot.expressions.RegrAvgy'>>, 'REGR_COUNT': <bound method Func.from_arg_list of <class 'sqlglot.expressions.RegrCount'>>, 'REGR_INTERCEPT': <bound method Func.from_arg_list of <class 'sqlglot.expressions.RegrIntercept'>>, 'REGR_R2': <bound method Func.from_arg_list of <class 'sqlglot.expressions.RegrR2'>>, 'REGR_SLOPE': <bound method Func.from_arg_list of <class 'sqlglot.expressions.RegrSlope'>>, 'REGR_SXX': <bound method Func.from_arg_list of <class 'sqlglot.expressions.RegrSxx'>>, 'REGR_SXY': <bound method Func.from_arg_list of <class 'sqlglot.expressions.RegrSxy'>>, 'REGR_SYY': <bound method Func.from_arg_list of <class 'sqlglot.expressions.RegrSyy'>>, 'REGR_VALX': <bound method Func.from_arg_list of <class 'sqlglot.expressions.RegrValx'>>, 'REGR_VALY': <bound method Func.from_arg_list of <class 'sqlglot.expressions.RegrValy'>>, 'REPEAT': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Repeat'>>, 'REPLACE': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Replace'>>, 'REVERSE': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Reverse'>>, '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'>>, 'RTRIMMED_LENGTH': <bound method Func.from_arg_list of <class 'sqlglot.expressions.RtrimmedLength'>>, 'SHA': <bound method Func.from_arg_list of <class 'sqlglot.expressions.SHA'>>, 'SHA1': <bound method Func.from_arg_list of <class 'sqlglot.expressions.SHA'>>, 'S_H_A1_DIGEST': <bound method Func.from_arg_list of <class 'sqlglot.expressions.SHA1Digest'>>, 'SHA2': <bound method Func.from_arg_list of <class 'sqlglot.expressions.SHA2'>>, 'S_H_A2_DIGEST': <bound method Func.from_arg_list of <class 'sqlglot.expressions.SHA2Digest'>>, 'SAFE_ADD': <bound method Func.from_arg_list of <class 'sqlglot.expressions.SafeAdd'>>, 'SAFE_CONVERT_BYTES_TO_STRING': <bound method Func.from_arg_list of <class 'sqlglot.expressions.SafeConvertBytesToString'>>, 'SAFE_DIVIDE': <bound method Func.from_arg_list of <class 'sqlglot.expressions.SafeDivide'>>, 'SAFE_FUNC': <bound method Func.from_arg_list of <class 'sqlglot.expressions.SafeFunc'>>, 'SAFE_MULTIPLY': <bound method Func.from_arg_list of <class 'sqlglot.expressions.SafeMultiply'>>, 'SAFE_NEGATE': <bound method Func.from_arg_list of <class 'sqlglot.expressions.SafeNegate'>>, 'SAFE_SUBTRACT': <bound method Func.from_arg_list of <class 'sqlglot.expressions.SafeSubtract'>>, 'SEARCH': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Search'>>, 'SEARCH_IP': <bound method Func.from_arg_list of <class 'sqlglot.expressions.SearchIp'>>, 'SEC': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Sec'>>, 'SECH': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Sech'>>, 'SECOND': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Second'>>, 'SEQ1': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Seq1'>>, 'SEQ2': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Seq2'>>, 'SEQ4': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Seq4'>>, 'SEQ8': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Seq8'>>, 'SESSION_USER': <bound method Func.from_arg_list of <class 'sqlglot.expressions.SessionUser'>>, 'SIGN': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Sign'>>, 'SIGNUM': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Sign'>>, 'SIN': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Sin'>>, 'SINH': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Sinh'>>, 'SKEWNESS': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Skewness'>>, 'SORT_ARRAY': <bound method Func.from_arg_list of <class 'sqlglot.expressions.SortArray'>>, 'SOUNDEX': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Soundex'>>, 'SOUNDEX_P123': <bound method Func.from_arg_list of <class 'sqlglot.expressions.SoundexP123'>>, 'SPACE': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Space'>>, 'SPLIT': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Split'>>, 'SPLIT_PART': <bound method Func.from_arg_list of <class 'sqlglot.expressions.SplitPart'>>, 'SQRT': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Sqrt'>>, 'ST_DISTANCE': <bound method Func.from_arg_list of <class 'sqlglot.expressions.StDistance'>>, 'ST_POINT': <bound method Func.from_arg_list of <class 'sqlglot.expressions.StPoint'>>, 'ST_MAKEPOINT': <bound method Func.from_arg_list of <class 'sqlglot.expressions.StPoint'>>, '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'>>, 'STARTS_WITH': <bound method Func.from_arg_list of <class 'sqlglot.expressions.StartsWith'>>, 'STARTSWITH': <bound method Func.from_arg_list of <class 'sqlglot.expressions.StartsWith'>>, 'STDDEV': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Stddev'>>, 'STDEV': <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_MAP': <bound method Func.from_arg_list of <class 'sqlglot.expressions.StrToMap'>>, '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'>>, 'STRING': <bound method Func.from_arg_list of <class 'sqlglot.expressions.String'>>, 'STRING_TO_ARRAY': <bound method Func.from_arg_list of <class 'sqlglot.expressions.StringToArray'>>, 'SPLIT_BY_STRING': <bound method Func.from_arg_list of <class 'sqlglot.expressions.StringToArray'>>, 'STRTOK_TO_ARRAY': <bound method Func.from_arg_list of <class 'sqlglot.expressions.StringToArray'>>, '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'>>, 'STUFF': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Stuff'>>, 'INSERT': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Stuff'>>, 'SUBSTRING': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Substring'>>, 'SUBSTR': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Substring'>>, 'SUBSTRING_INDEX': <bound method Func.from_arg_list of <class 'sqlglot.expressions.SubstringIndex'>>, 'SUM': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Sum'>>, 'SYSTIMESTAMP': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Systimestamp'>>, 'TAN': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Tan'>>, 'TANH': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Tanh'>>, 'TIME': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Time'>>, '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_FROM_PARTS': <bound method Func.from_arg_list of <class 'sqlglot.expressions.TimeFromParts'>>, 'TIMEFROMPARTS': <bound method Func.from_arg_list of <class 'sqlglot.expressions.TimeFromParts'>>, 'TIME_SLICE': <bound method Func.from_arg_list of <class 'sqlglot.expressions.TimeSlice'>>, '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': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Timestamp'>>, 'TIMESTAMP_ADD': <bound method Func.from_arg_list of <class 'sqlglot.expressions.TimestampAdd'>>, 'TIMESTAMPDIFF': <bound method Func.from_arg_list of <class 'sqlglot.expressions.TimestampDiff'>>, 'TIMESTAMP_DIFF': <bound method Func.from_arg_list of <class 'sqlglot.expressions.TimestampDiff'>>, 'TIMESTAMP_FROM_PARTS': <bound method Func.from_arg_list of <class 'sqlglot.expressions.TimestampFromParts'>>, 'TIMESTAMPFROMPARTS': <bound method Func.from_arg_list of <class 'sqlglot.expressions.TimestampFromParts'>>, 'TIMESTAMP_LTZ_FROM_PARTS': <bound method Func.from_arg_list of <class 'sqlglot.expressions.TimestampLtzFromParts'>>, 'TIMESTAMPLTZFROMPARTS': <bound method Func.from_arg_list of <class 'sqlglot.expressions.TimestampLtzFromParts'>>, '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'>>, 'TIMESTAMP_TZ_FROM_PARTS': <bound method Func.from_arg_list of <class 'sqlglot.expressions.TimestampTzFromParts'>>, 'TIMESTAMPTZFROMPARTS': <bound method Func.from_arg_list of <class 'sqlglot.expressions.TimestampTzFromParts'>>, 'TO_ARRAY': <bound method Func.from_arg_list of <class 'sqlglot.expressions.ToArray'>>, 'TO_BASE32': <bound method Func.from_arg_list of <class 'sqlglot.expressions.ToBase32'>>, 'TO_BASE64': <bound method Func.from_arg_list of <class 'sqlglot.expressions.ToBase64'>>, 'TO_BINARY': <bound method Func.from_arg_list of <class 'sqlglot.expressions.ToBinary'>>, 'TO_BOOLEAN': <bound method Func.from_arg_list of <class 'sqlglot.expressions.ToBoolean'>>, 'TO_CHAR': <function build_formatted_time.<locals>._builder>, 'TO_CODE_POINTS': <bound method Func.from_arg_list of <class 'sqlglot.expressions.ToCodePoints'>>, 'TO_DAYS': <bound method Func.from_arg_list of <class 'sqlglot.expressions.ToDays'>>, 'TO_DECFLOAT': <bound method Func.from_arg_list of <class 'sqlglot.expressions.ToDecfloat'>>, 'TO_DOUBLE': <bound method Func.from_arg_list of <class 'sqlglot.expressions.ToDouble'>>, 'TO_FILE': <bound method Func.from_arg_list of <class 'sqlglot.expressions.ToFile'>>, 'TO_MAP': <bound method Func.from_arg_list of <class 'sqlglot.expressions.ToMap'>>, 'TO_NUMBER': <bound method Func.from_arg_list of <class 'sqlglot.expressions.ToNumber'>>, 'TRANSFORM': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Transform'>>, 'TRANSLATE': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Translate'>>, 'TRIM': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Trim'>>, 'TRY': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Try'>>, 'TRY_BASE64_DECODE_BINARY': <bound method Func.from_arg_list of <class 'sqlglot.expressions.TryBase64DecodeBinary'>>, 'TRY_BASE64_DECODE_STRING': <bound method Func.from_arg_list of <class 'sqlglot.expressions.TryBase64DecodeString'>>, 'TRY_CAST': <bound method Func.from_arg_list of <class 'sqlglot.expressions.TryCast'>>, 'TRY_HEX_DECODE_BINARY': <bound method Func.from_arg_list of <class 'sqlglot.expressions.TryHexDecodeBinary'>>, 'TRY_HEX_DECODE_STRING': <bound method Func.from_arg_list of <class 'sqlglot.expressions.TryHexDecodeString'>>, 'TRY_TO_DECFLOAT': <bound method Func.from_arg_list of <class 'sqlglot.expressions.TryToDecfloat'>>, '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_DIFF': <bound method Func.from_arg_list of <class 'sqlglot.expressions.TsOrDsDiff'>>, '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>>, 'TS_OR_DS_TO_DATETIME': <bound method Func.from_arg_list of <class 'sqlglot.expressions.TsOrDsToDatetime'>>, 'TS_OR_DS_TO_TIME': <bound method Func.from_arg_list of <class 'sqlglot.expressions.TsOrDsToTime'>>, 'TS_OR_DS_TO_TIMESTAMP': <bound method Func.from_arg_list of <class 'sqlglot.expressions.TsOrDsToTimestamp'>>, 'TYPEOF': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Typeof'>>, 'UNHEX': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Unhex'>>, 'UNICODE': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Unicode'>>, 'UNIFORM': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Uniform'>>, 'UNIX_DATE': <bound method Func.from_arg_list of <class 'sqlglot.expressions.UnixDate'>>, 'UNIX_MICROS': <bound method Func.from_arg_list of <class 'sqlglot.expressions.UnixMicros'>>, 'UNIX_MILLIS': <bound method Func.from_arg_list of <class 'sqlglot.expressions.UnixMillis'>>, 'UNIX_SECONDS': <bound method Func.from_arg_list of <class 'sqlglot.expressions.UnixSeconds'>>, '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'>>, 'UNNEST': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Explode'>>, 'UPPER': <function build_upper>, 'UCASE': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Upper'>>, 'UTC_DATE': <bound method Func.from_arg_list of <class 'sqlglot.expressions.UtcDate'>>, 'UTC_TIME': <bound method Func.from_arg_list of <class 'sqlglot.expressions.UtcTime'>>, 'UTC_TIMESTAMP': <bound method Func.from_arg_list of <class 'sqlglot.expressions.UtcTimestamp'>>, 'UUID': <function Parser.<lambda>>, 'GEN_RANDOM_UUID': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Uuid'>>, 'GENERATE_UUID': <function Parser.<lambda>>, 'UUID_STRING': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Uuid'>>, 'VAR_MAP': <function build_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'>>, 'VECTOR_SEARCH': <bound method Func.from_arg_list of <class 'sqlglot.expressions.VectorSearch'>>, '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'>>, 'WIDTH_BUCKET': <function Postgres.Parser.<lambda>>, 'XMLELEMENT': <bound method Func.from_arg_list of <class 'sqlglot.expressions.XMLElement'>>, 'XMLGET': <bound method Func.from_arg_list of <class 'sqlglot.expressions.XMLGet'>>, 'X_M_L_TABLE': <bound method Func.from_arg_list of <class 'sqlglot.expressions.XMLTable'>>, 'XOR': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Xor'>>, 'YEAR': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Year'>>, 'YEAR_OF_WEEK': <bound method Func.from_arg_list of <class 'sqlglot.expressions.YearOfWeek'>>, 'YEAROFWEEK': <bound method Func.from_arg_list of <class 'sqlglot.expressions.YearOfWeek'>>, 'YEAR_OF_WEEK_ISO': <bound method Func.from_arg_list of <class 'sqlglot.expressions.YearOfWeekIso'>>, 'YEAROFWEEKISO': <bound method Func.from_arg_list of <class 'sqlglot.expressions.YearOfWeekIso'>>, 'ZIPF': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Zipf'>>, 'ARRAYAGG': <function Parser.<lambda>>, 'GLOB': <function Parser.<lambda>>, 'JSON_EXTRACT_PATH_TEXT': <function build_json_extract_path.<locals>._builder>, 'LIKE': <function build_like>, 'LOG2': <function Parser.<lambda>>, 'LOG10': <function Parser.<lambda>>, 'LPAD': <function Parser.<lambda>>, 'LEFTPAD': <function Parser.<lambda>>, 'LTRIM': <function Parser.<lambda>>, 'MOD': <function build_mod>, 'RIGHTPAD': <function Parser.<lambda>>, 'RPAD': <function Parser.<lambda>>, 'RTRIM': <function Parser.<lambda>>, 'SCOPE_RESOLUTION': <function Parser.<lambda>>, 'STRPOS': <bound method Func.from_arg_list of <class 'sqlglot.expressions.StrPosition'>>, 'CHARINDEX': <function Parser.<lambda>>, 'INSTR': <bound method Func.from_arg_list of <class 'sqlglot.expressions.StrPosition'>>, 'LOCATE': <function Parser.<lambda>>, 'TO_HEX': <function build_hex>, 'BIT_AND': <bound method Func.from_arg_list of <class 'sqlglot.expressions.BitwiseAndAgg'>>, 'BIT_OR': <bound method Func.from_arg_list of <class 'sqlglot.expressions.BitwiseOrAgg'>>, 'BIT_XOR': <bound method Func.from_arg_list of <class 'sqlglot.expressions.BitwiseXorAgg'>>, 'DIV': <function Postgres.Parser.<lambda>>, 'JSON_EXTRACT_PATH': <function build_json_extract_path.<locals>._builder>, 'MAKE_TIME': <bound method Func.from_arg_list of <class 'sqlglot.expressions.TimeFromParts'>>, 'MAKE_TIMESTAMP': <bound method Func.from_arg_list of <class 'sqlglot.expressions.TimestampFromParts'>>, 'NOW': <bound method Func.from_arg_list of <class 'sqlglot.expressions.CurrentTimestamp'>>, 'TO_DATE': <function build_formatted_time.<locals>._builder>, 'TO_TIMESTAMP': <function _build_to_timestamp>, 'SHA256': <function Postgres.Parser.<lambda>>, 'SHA384': <function Postgres.Parser.<lambda>>, 'SHA512': <function Postgres.Parser.<lambda>>, 'LEVENSHTEIN_LESS_EQUAL': <function _build_levenshtein_less_equal>, 'JSON_OBJECT_AGG': <function Postgres.Parser.<lambda>>, 'JSONB_OBJECT_AGG': <bound method Func.from_arg_list of <class 'sqlglot.expressions.JSONBObjectAgg'>>}
NO_PAREN_FUNCTION_PARSERS = {'ANY': <function Parser.<lambda>>, 'CASE': <function Parser.<lambda>>, 'CONNECT_BY_ROOT': <function Parser.<lambda>>, 'IF': <function Parser.<lambda>>, 'VARIADIC': <function Postgres.Parser.<lambda>>}
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'>, <TokenType.LOCALTIME: 'LOCALTIME'>: <class 'sqlglot.expressions.Localtime'>, <TokenType.LOCALTIMESTAMP: 'LOCALTIMESTAMP'>: <class 'sqlglot.expressions.Localtimestamp'>, <TokenType.CURRENT_ROLE: 'CURRENT_ROLE'>: <class 'sqlglot.expressions.CurrentRole'>, <TokenType.CURRENT_SCHEMA: 'CURRENT_SCHEMA'>: <class 'sqlglot.expressions.CurrentSchema'>, <TokenType.CURRENT_CATALOG: 'CURRENT_CATALOG'>: <class 'sqlglot.expressions.CurrentCatalog'>, <TokenType.SESSION_USER: 'SESSION_USER'>: <class 'sqlglot.expressions.SessionUser'>}
FUNCTION_PARSERS = {'ARG_MAX': <function Parser.<dictcomp>.<lambda>>, 'ARGMAX': <function Parser.<dictcomp>.<lambda>>, 'MAX_BY': <function Parser.<dictcomp>.<lambda>>, 'ARG_MIN': <function Parser.<dictcomp>.<lambda>>, 'ARGMIN': <function Parser.<dictcomp>.<lambda>>, 'MIN_BY': <function Parser.<dictcomp>.<lambda>>, 'CAST': <function Parser.<lambda>>, 'CEIL': <function Parser.<lambda>>, 'CONVERT': <function Parser.<lambda>>, 'CHAR': <function Parser.<lambda>>, 'CHR': <function Parser.<lambda>>, 'DECODE': <function Parser.<lambda>>, 'EXTRACT': <function Parser.<lambda>>, 'FLOOR': <function Parser.<lambda>>, 'GAP_FILL': <function Parser.<lambda>>, 'INITCAP': <function Parser.<lambda>>, 'JSON_OBJECT': <function Parser.<lambda>>, 'JSON_OBJECTAGG': <function Parser.<lambda>>, 'JSON_TABLE': <function Parser.<lambda>>, 'MATCH': <function Parser.<lambda>>, 'NORMALIZE': <function Parser.<lambda>>, 'OPENJSON': <function Parser.<lambda>>, 'OVERLAY': <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>>, 'XMLELEMENT': <function Parser.<lambda>>, 'XMLTABLE': <function Parser.<lambda>>, 'DATE_PART': <function Postgres.Parser.<lambda>>, 'JSON_AGG': <function Postgres.Parser.<lambda>>, 'JSONB_EXISTS': <function Postgres.Parser.<lambda>>}
BITWISE = {<TokenType.AMP: 'AMP'>: <class 'sqlglot.expressions.BitwiseAnd'>, <TokenType.CARET: 'CARET'>: <class 'sqlglot.expressions.BitwiseXor'>, <TokenType.PIPE: 'PIPE'>: <class 'sqlglot.expressions.BitwiseOr'>, <TokenType.HASH: 'HASH'>: <class 'sqlglot.expressions.BitwiseXor'>}
EXPONENT = {<TokenType.CARET: 'CARET'>: <class 'sqlglot.expressions.Pow'>}
RANGE_PARSERS = {<TokenType.AT_GT: 'AT_GT'>: <function binary_range_parser.<locals>._parse_binary_range>, <TokenType.BETWEEN: 'BETWEEN'>: <function Parser.<lambda>>, <TokenType.GLOB: 'GLOB'>: <function binary_range_parser.<locals>._parse_binary_range>, <TokenType.ILIKE: 'ILIKE'>: <function binary_range_parser.<locals>._parse_binary_range>, <TokenType.IN: 'IN'>: <function Parser.<lambda>>, <TokenType.IRLIKE: 'IRLIKE'>: <function binary_range_parser.<locals>._parse_binary_range>, <TokenType.IS: 'IS'>: <function Parser.<lambda>>, <TokenType.LIKE: 'LIKE'>: <function binary_range_parser.<locals>._parse_binary_range>, <TokenType.LT_AT: 'LT_AT'>: <function binary_range_parser.<locals>._parse_binary_range>, <TokenType.OVERLAPS: 'OVERLAPS'>: <function binary_range_parser.<locals>._parse_binary_range>, <TokenType.RLIKE: 'RLIKE'>: <function binary_range_parser.<locals>._parse_binary_range>, <TokenType.SIMILAR_TO: 'SIMILAR_TO'>: <function binary_range_parser.<locals>._parse_binary_range>, <TokenType.FOR: 'FOR'>: <function Parser.<lambda>>, <TokenType.QMARK_AMP: 'QMARK_AMP'>: <function binary_range_parser.<locals>._parse_binary_range>, <TokenType.QMARK_PIPE: 'QMARK_PIPE'>: <function binary_range_parser.<locals>._parse_binary_range>, <TokenType.HASH_DASH: 'HASH_DASH'>: <function binary_range_parser.<locals>._parse_binary_range>, <TokenType.ADJACENT: 'ADJACENT'>: <function binary_range_parser.<locals>._parse_binary_range>, <TokenType.OPERATOR: 'OPERATOR'>: <function Parser.<lambda>>, <TokenType.AMP_LT: 'AMP_LT'>: <function binary_range_parser.<locals>._parse_binary_range>, <TokenType.AMP_GT: 'AMP_GT'>: <function binary_range_parser.<locals>._parse_binary_range>, <TokenType.DAMP: 'DAMP'>: <function binary_range_parser.<locals>._parse_binary_range>, <TokenType.DAT: 'DAT'>: <function Postgres.Parser.<lambda>>}
STATEMENT_PARSERS = {<TokenType.ALTER: 'ALTER'>: <function Parser.<lambda>>, <TokenType.ANALYZE: 'ANALYZE'>: <function Parser.<lambda>>, <TokenType.BEGIN: 'BEGIN'>: <function Parser.<lambda>>, <TokenType.CACHE: 'CACHE'>: <function Parser.<lambda>>, <TokenType.COMMENT: 'COMMENT'>: <function Parser.<lambda>>, <TokenType.COMMIT: 'COMMIT'>: <function Parser.<lambda>>, <TokenType.COPY: 'COPY'>: <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.GRANT: 'GRANT'>: <function Parser.<lambda>>, <TokenType.REVOKE: 'REVOKE'>: <function Parser.<lambda>>, <TokenType.INSERT: 'INSERT'>: <function Parser.<lambda>>, <TokenType.KILL: 'KILL'>: <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.REFRESH: 'REFRESH'>: <function Parser.<lambda>>, <TokenType.ROLLBACK: 'ROLLBACK'>: <function Parser.<lambda>>, <TokenType.SET: 'SET'>: <function Parser.<lambda>>, <TokenType.TRUNCATE: 'TRUNCATE'>: <function Parser.<lambda>>, <TokenType.UNCACHE: 'UNCACHE'>: <function Parser.<lambda>>, <TokenType.UNPIVOT: 'UNPIVOT'>: <function Parser.<lambda>>, <TokenType.UPDATE: 'UPDATE'>: <function Parser.<lambda>>, <TokenType.USE: 'USE'>: <function Parser.<lambda>>, <TokenType.SEMICOLON: 'SEMICOLON'>: <function Parser.<lambda>>, <TokenType.END: 'END'>: <function Postgres.Parser.<lambda>>}
UNARY_PARSERS = {<TokenType.PLUS: 'PLUS'>: <function Parser.<lambda>>, <TokenType.NOT: 'NOT'>: <function Parser.<lambda>>, <TokenType.TILDE: 'TILDE'>: <function Parser.<lambda>>, <TokenType.DASH: 'DASH'>: <function Parser.<lambda>>, <TokenType.PIPE_SLASH: 'PIPE_SLASH'>: <function Parser.<lambda>>, <TokenType.DPIPE_SLASH: 'DPIPE_SLASH'>: <function Parser.<lambda>>, <TokenType.RLIKE: 'RLIKE'>: <function Postgres.Parser.<lambda>>}
JSON_ARROWS_REQUIRE_JSON_TYPE = True
COLUMN_OPERATORS = {<TokenType.DOT: 'DOT'>: None, <TokenType.DOTCOLON: 'DOTCOLON'>: <function Parser.<lambda>>, <TokenType.DCOLON: 'DCOLON'>: <function Parser.<lambda>>, <TokenType.ARROW: 'ARROW'>: <function Postgres.Parser.<lambda>>, <TokenType.DARROW: 'DARROW'>: <function Postgres.Parser.<lambda>>, <TokenType.HASH_ARROW: 'HASH_ARROW'>: <function Parser.<lambda>>, <TokenType.DHASH_ARROW: 'DHASH_ARROW'>: <function Parser.<lambda>>, <TokenType.PLACEHOLDER: 'PLACEHOLDER'>: <function Parser.<lambda>>}
ARG_MODE_TOKENS = {<TokenType.VARIADIC: 'VARIADIC'>, <TokenType.INOUT: 'INOUT'>, <TokenType.IN: 'IN'>, <TokenType.OUT: 'OUT'>}
ID_VAR_TOKENS = {<TokenType.INT8RANGE: 'INT8RANGE'>, <TokenType.UDECIMAL: 'UDECIMAL'>, <TokenType.STRAIGHT_JOIN: 'STRAIGHT_JOIN'>, <TokenType.LOCK: 'LOCK'>, <TokenType.BPCHAR: 'BPCHAR'>, <TokenType.COLLATE: 'COLLATE'>, <TokenType.UDOUBLE: 'UDOUBLE'>, <TokenType.SHOW: 'SHOW'>, <TokenType.JSON: 'JSON'>, <TokenType.DATE32: 'DATE32'>, <TokenType.SETTINGS: 'SETTINGS'>, <TokenType.CURRENT_TIMESTAMP: 'CURRENT_TIMESTAMP'>, <TokenType.DECIMAL256: 'DECIMAL256'>, <TokenType.TRUNCATE: 'TRUNCATE'>, <TokenType.INT4RANGE: 'INT4RANGE'>, <TokenType.DIV: 'DIV'>, <TokenType.UINT256: 'UINT256'>, <TokenType.UNKNOWN: 'UNKNOWN'>, <TokenType.MEDIUMINT: 'MEDIUMINT'>, <TokenType.VARBINARY: 'VARBINARY'>, <TokenType.BIGDECIMAL: 'BIGDECIMAL'>, <TokenType.NAME: 'NAME'>, <TokenType.INTERVAL: 'INTERVAL'>, <TokenType.UTINYINT: 'UTINYINT'>, <TokenType.ESCAPE: 'ESCAPE'>, <TokenType.SMALLDATETIME: 'SMALLDATETIME'>, <TokenType.EXECUTE: 'EXECUTE'>, <TokenType.ISNULL: 'ISNULL'>, <TokenType.DESC: 'DESC'>, <TokenType.UNPIVOT: 'UNPIVOT'>, <TokenType.BOOLEAN: 'BOOLEAN'>, <TokenType.CURRENT_TIME: 'CURRENT_TIME'>, <TokenType.END: 'END'>, <TokenType.AUTO_INCREMENT: 'AUTO_INCREMENT'>, <TokenType.SEQUENCE: 'SEQUENCE'>, <TokenType.VAR: 'VAR'>, <TokenType.RENAME: 'RENAME'>, <TokenType.FIXEDSTRING: 'FIXEDSTRING'>, <TokenType.LIST: 'LIST'>, <TokenType.ATTACH: 'ATTACH'>, <TokenType.COMMENT: 'COMMENT'>, <TokenType.USMALLINT: 'USMALLINT'>, <TokenType.TIME_NS: 'TIME_NS'>, <TokenType.OPERATOR: 'OPERATOR'>, <TokenType.UINT: 'UINT'>, <TokenType.UUID: 'UUID'>, <TokenType.TIMESTAMP_NS: 'TIMESTAMP_NS'>, <TokenType.TIMESTAMPLTZ: 'TIMESTAMPLTZ'>, <TokenType.CURRENT_USER: 'CURRENT_USER'>, <TokenType.NCHAR: 'NCHAR'>, <TokenType.INT256: 'INT256'>, <TokenType.TOP: 'TOP'>, <TokenType.LOCALTIME: 'LOCALTIME'>, <TokenType.DYNAMIC: 'DYNAMIC'>, <TokenType.SEMI: 'SEMI'>, <TokenType.TEXT: 'TEXT'>, <TokenType.EXPORT: 'EXPORT'>, <TokenType.TSTZRANGE: 'TSTZRANGE'>, <TokenType.JSONB: 'JSONB'>, <TokenType.STREAMLIT: 'STREAMLIT'>, <TokenType.MEDIUMBLOB: 'MEDIUMBLOB'>, <TokenType.CURRENT_DATETIME: 'CURRENT_DATETIME'>, <TokenType.IS: 'IS'>, <TokenType.VIEW: 'VIEW'>, <TokenType.FORMAT: 'FORMAT'>, <TokenType.TIMETZ: 'TIMETZ'>, <TokenType.TSMULTIRANGE: 'TSMULTIRANGE'>, <TokenType.NOTHING: 'NOTHING'>, <TokenType.SMALLSERIAL: 'SMALLSERIAL'>, <TokenType.FOREIGN_KEY: 'FOREIGN_KEY'>, <TokenType.TIMESTAMPTZ: 'TIMESTAMPTZ'>, <TokenType.REFERENCES: 'REFERENCES'>, <TokenType.DETACH: 'DETACH'>, <TokenType.BIGNUM: 'BIGNUM'>, <TokenType.VECTOR: 'VECTOR'>, <TokenType.LOCALTIMESTAMP: 'LOCALTIMESTAMP'>, <TokenType.TAG: 'TAG'>, <TokenType.TRUE: 'TRUE'>, <TokenType.TIMESTAMP_S: 'TIMESTAMP_S'>, <TokenType.DICTIONARY: 'DICTIONARY'>, <TokenType.KILL: 'KILL'>, <TokenType.INDEX: 'INDEX'>, <TokenType.IPV4: 'IPV4'>, <TokenType.TSRANGE: 'TSRANGE'>, <TokenType.OFFSET: 'OFFSET'>, <TokenType.PIVOT: 'PIVOT'>, <TokenType.ANY: 'ANY'>, <TokenType.MONEY: 'MONEY'>, <TokenType.INOUT: 'INOUT'>, <TokenType.REPLACE: 'REPLACE'>, <TokenType.ENUM16: 'ENUM16'>, <TokenType.SET: 'SET'>, <TokenType.BLOB: 'BLOB'>, <TokenType.FULL: 'FULL'>, <TokenType.WAREHOUSE: 'WAREHOUSE'>, <TokenType.PROCEDURE: 'PROCEDURE'>, <TokenType.OBJECT: 'OBJECT'>, <TokenType.ARRAY: 'ARRAY'>, <TokenType.COPY: 'COPY'>, <TokenType.CUBE: 'CUBE'>, <TokenType.VARIANT: 'VARIANT'>, <TokenType.SINK: 'SINK'>, <TokenType.CHAR: 'CHAR'>, <TokenType.SOME: 'SOME'>, <TokenType.ANALYZE: 'ANALYZE'>, <TokenType.NAMESPACE: 'NAMESPACE'>, <TokenType.LEFT: 'LEFT'>, <TokenType.FLOAT: 'FLOAT'>, <TokenType.UNNEST: 'UNNEST'>, <TokenType.LONGTEXT: 'LONGTEXT'>, <TokenType.MULTILINESTRING: 'MULTILINESTRING'>, <TokenType.LOWCARDINALITY: 'LOWCARDINALITY'>, <TokenType.BIGSERIAL: 'BIGSERIAL'>, <TokenType.PERCENT: 'PERCENT'>, <TokenType.FILTER: 'FILTER'>, <TokenType.DATERANGE: 'DATERANGE'>, <TokenType.VARCHAR: 'VARCHAR'>, <TokenType.DESCRIBE: 'DESCRIBE'>, <TokenType.APPLY: 'APPLY'>, <TokenType.IDENTIFIER: 'IDENTIFIER'>, <TokenType.STORAGE_INTEGRATION: 'STORAGE_INTEGRATION'>, <TokenType.ROWVERSION: 'ROWVERSION'>, <TokenType.TIMESTAMP: 'TIMESTAMP'>, <TokenType.TINYTEXT: 'TINYTEXT'>, <TokenType.DATABASE: 'DATABASE'>, <TokenType.SIMPLEAGGREGATEFUNCTION: 'SIMPLEAGGREGATEFUNCTION'>, <TokenType.AGGREGATEFUNCTION: 'AGGREGATEFUNCTION'>, <TokenType.TABLE: 'TABLE'>, <TokenType.UMEDIUMINT: 'UMEDIUMINT'>, <TokenType.GEOGRAPHY: 'GEOGRAPHY'>, <TokenType.INT128: 'INT128'>, <TokenType.NUMMULTIRANGE: 'NUMMULTIRANGE'>, <TokenType.STAGE: 'STAGE'>, <TokenType.POINT: 'POINT'>, <TokenType.MATCH: 'MATCH'>, <TokenType.DATE: 'DATE'>, <TokenType.LONGBLOB: 'LONGBLOB'>, <TokenType.CURRENT_SCHEMA: 'CURRENT_SCHEMA'>, <TokenType.INET: 'INET'>, <TokenType.FALSE: 'FALSE'>, <TokenType.CASE: 'CASE'>, <TokenType.LIMIT: 'LIMIT'>, <TokenType.LOAD: 'LOAD'>, <TokenType.UINT128: 'UINT128'>, <TokenType.UBIGINT: 'UBIGINT'>, <TokenType.TEMPORARY: 'TEMPORARY'>, <TokenType.ROWS: 'ROWS'>, <TokenType.DECIMAL32: 'DECIMAL32'>, <TokenType.SCHEMA: 'SCHEMA'>, <TokenType.MEDIUMTEXT: 'MEDIUMTEXT'>, <TokenType.TIMESTAMPNTZ: 'TIMESTAMPNTZ'>, <TokenType.ENUM: 'ENUM'>, <TokenType.INT8MULTIRANGE: 'INT8MULTIRANGE'>, <TokenType.NULLABLE: 'NULLABLE'>, <TokenType.DATETIME2: 'DATETIME2'>, <TokenType.COMMIT: 'COMMIT'>, <TokenType.DELETE: 'DELETE'>, <TokenType.IMAGE: 'IMAGE'>, <TokenType.GET: 'GET'>, <TokenType.IPV6: 'IPV6'>, <TokenType.ROW: 'ROW'>, <TokenType.ENUM8: 'ENUM8'>, <TokenType.POLYGON: 'POLYGON'>, <TokenType.PARTITION: 'PARTITION'>, <TokenType.NEXT: 'NEXT'>, <TokenType.TINYINT: 'TINYINT'>, <TokenType.DECIMAL: 'DECIMAL'>, <TokenType.SMALLINT: 'SMALLINT'>, <TokenType.SMALLMONEY: 'SMALLMONEY'>, <TokenType.KEEP: 'KEEP'>, <TokenType.EXISTS: 'EXISTS'>, <TokenType.RANGE: 'RANGE'>, <TokenType.PSEUDO_TYPE: 'PSEUDO_TYPE'>, <TokenType.INT: 'INT'>, <TokenType.VOLATILE: 'VOLATILE'>, <TokenType.NVARCHAR: 'NVARCHAR'>, <TokenType.OVERWRITE: 'OVERWRITE'>, <TokenType.DOUBLE: 'DOUBLE'>, <TokenType.VOID: 'VOID'>, <TokenType.SOURCE: 'SOURCE'>, <TokenType.ORDINALITY: 'ORDINALITY'>, <TokenType.BIGINT: 'BIGINT'>, <TokenType.DECIMAL64: 'DECIMAL64'>, <TokenType.DATETIME64: 'DATETIME64'>, <TokenType.SUPER: 'SUPER'>, <TokenType.NUMRANGE: 'NUMRANGE'>, <TokenType.USERDEFINED: 'USERDEFINED'>, <TokenType.IPADDRESS: 'IPADDRESS'>, <TokenType.NULL: 'NULL'>, <TokenType.FILE: 'FILE'>, <TokenType.NESTED: 'NESTED'>, <TokenType.CONSTRAINT: 'CONSTRAINT'>, <TokenType.CURRENT_ROLE: 'CURRENT_ROLE'>, <TokenType.ASOF: 'ASOF'>, <TokenType.FIRST: 'FIRST'>, <TokenType.SESSION: 'SESSION'>, <TokenType.SEMANTIC_VIEW: 'SEMANTIC_VIEW'>, <TokenType.ROLLUP: 'ROLLUP'>, <TokenType.OVER: 'OVER'>, <TokenType.DATEMULTIRANGE: 'DATEMULTIRANGE'>, <TokenType.USE: 'USE'>, <TokenType.TDIGEST: 'TDIGEST'>, <TokenType.COLUMN: 'COLUMN'>, <TokenType.REFRESH: 'REFRESH'>, <TokenType.HLLSKETCH: 'HLLSKETCH'>, <TokenType.YEAR: 'YEAR'>, <TokenType.COMMAND: 'COMMAND'>, <TokenType.UNIQUE: 'UNIQUE'>, <TokenType.BEGIN: 'BEGIN'>, <TokenType.FUNCTION: 'FUNCTION'>, <TokenType.TIMESTAMP_MS: 'TIMESTAMP_MS'>, <TokenType.OVERLAPS: 'OVERLAPS'>, <TokenType.PRAGMA: 'PRAGMA'>, <TokenType.DECFLOAT: 'DECFLOAT'>, <TokenType.PUT: 'PUT'>, <TokenType.GEOGRAPHYPOINT: 'GEOGRAPHYPOINT'>, <TokenType.MODEL: 'MODEL'>, <TokenType.LINESTRING: 'LINESTRING'>, <TokenType.RING: 'RING'>, <TokenType.ASC: 'ASC'>, <TokenType.WINDOW: 'WINDOW'>, <TokenType.HSTORE: 'HSTORE'>, <TokenType.CACHE: 'CACHE'>, <TokenType.FINAL: 'FINAL'>, <TokenType.ALL: 'ALL'>, <TokenType.DEFAULT: 'DEFAULT'>, <TokenType.MULTIPOLYGON: 'MULTIPOLYGON'>, <TokenType.SERIAL: 'SERIAL'>, <TokenType.XML: 'XML'>, <TokenType.DECIMAL128: 'DECIMAL128'>, <TokenType.OBJECT_IDENTIFIER: 'OBJECT_IDENTIFIER'>, <TokenType.UPDATE: 'UPDATE'>, <TokenType.IPPREFIX: 'IPPREFIX'>, <TokenType.CURRENT_DATE: 'CURRENT_DATE'>, <TokenType.RIGHT: 'RIGHT'>, <TokenType.MAP: 'MAP'>, <TokenType.TINYBLOB: 'TINYBLOB'>, <TokenType.TIME: 'TIME'>, <TokenType.BIT: 'BIT'>, <TokenType.FILE_FORMAT: 'FILE_FORMAT'>, <TokenType.GEOMETRY: 'GEOMETRY'>, <TokenType.MERGE: 'MERGE'>, <TokenType.NATURAL: 'NATURAL'>, <TokenType.BINARY: 'BINARY'>, <TokenType.INT4MULTIRANGE: 'INT4MULTIRANGE'>, <TokenType.RECURSIVE: 'RECURSIVE'>, <TokenType.STRUCT: 'STRUCT'>, <TokenType.DATETIME: 'DATETIME'>, <TokenType.ANTI: 'ANTI'>, <TokenType.TSTZMULTIRANGE: 'TSTZMULTIRANGE'>}
TABLE_ALIAS_TOKENS = {<TokenType.INT8RANGE: 'INT8RANGE'>, <TokenType.UDECIMAL: 'UDECIMAL'>, <TokenType.STRAIGHT_JOIN: 'STRAIGHT_JOIN'>, <TokenType.BPCHAR: 'BPCHAR'>, <TokenType.COLLATE: 'COLLATE'>, <TokenType.UDOUBLE: 'UDOUBLE'>, <TokenType.SHOW: 'SHOW'>, <TokenType.JSON: 'JSON'>, <TokenType.DATE32: 'DATE32'>, <TokenType.SETTINGS: 'SETTINGS'>, <TokenType.CURRENT_TIMESTAMP: 'CURRENT_TIMESTAMP'>, <TokenType.DECIMAL256: 'DECIMAL256'>, <TokenType.TRUNCATE: 'TRUNCATE'>, <TokenType.TSTZMULTIRANGE: 'TSTZMULTIRANGE'>, <TokenType.INT4RANGE: 'INT4RANGE'>, <TokenType.DIV: 'DIV'>, <TokenType.UINT256: 'UINT256'>, <TokenType.UNKNOWN: 'UNKNOWN'>, <TokenType.MEDIUMINT: 'MEDIUMINT'>, <TokenType.VARBINARY: 'VARBINARY'>, <TokenType.BIGDECIMAL: 'BIGDECIMAL'>, <TokenType.NAME: 'NAME'>, <TokenType.INTERVAL: 'INTERVAL'>, <TokenType.UTINYINT: 'UTINYINT'>, <TokenType.ESCAPE: 'ESCAPE'>, <TokenType.SMALLDATETIME: 'SMALLDATETIME'>, <TokenType.EXECUTE: 'EXECUTE'>, <TokenType.ISNULL: 'ISNULL'>, <TokenType.DESC: 'DESC'>, <TokenType.UNPIVOT: 'UNPIVOT'>, <TokenType.BOOLEAN: 'BOOLEAN'>, <TokenType.CURRENT_TIME: 'CURRENT_TIME'>, <TokenType.END: 'END'>, <TokenType.AUTO_INCREMENT: 'AUTO_INCREMENT'>, <TokenType.SEQUENCE: 'SEQUENCE'>, <TokenType.VAR: 'VAR'>, <TokenType.RENAME: 'RENAME'>, <TokenType.FIXEDSTRING: 'FIXEDSTRING'>, <TokenType.LIST: 'LIST'>, <TokenType.ATTACH: 'ATTACH'>, <TokenType.COMMENT: 'COMMENT'>, <TokenType.USMALLINT: 'USMALLINT'>, <TokenType.TIME_NS: 'TIME_NS'>, <TokenType.OPERATOR: 'OPERATOR'>, <TokenType.UINT: 'UINT'>, <TokenType.UUID: 'UUID'>, <TokenType.TIMESTAMP_NS: 'TIMESTAMP_NS'>, <TokenType.TIMESTAMPLTZ: 'TIMESTAMPLTZ'>, <TokenType.CURRENT_USER: 'CURRENT_USER'>, <TokenType.NCHAR: 'NCHAR'>, <TokenType.INT256: 'INT256'>, <TokenType.TOP: 'TOP'>, <TokenType.LOCALTIME: 'LOCALTIME'>, <TokenType.DYNAMIC: 'DYNAMIC'>, <TokenType.TEXT: 'TEXT'>, <TokenType.EXPORT: 'EXPORT'>, <TokenType.TSTZRANGE: 'TSTZRANGE'>, <TokenType.JSONB: 'JSONB'>, <TokenType.STREAMLIT: 'STREAMLIT'>, <TokenType.MEDIUMBLOB: 'MEDIUMBLOB'>, <TokenType.CURRENT_DATETIME: 'CURRENT_DATETIME'>, <TokenType.IS: 'IS'>, <TokenType.VIEW: 'VIEW'>, <TokenType.FORMAT: 'FORMAT'>, <TokenType.TIMETZ: 'TIMETZ'>, <TokenType.TSMULTIRANGE: 'TSMULTIRANGE'>, <TokenType.NOTHING: 'NOTHING'>, <TokenType.SMALLSERIAL: 'SMALLSERIAL'>, <TokenType.FOREIGN_KEY: 'FOREIGN_KEY'>, <TokenType.TIMESTAMPTZ: 'TIMESTAMPTZ'>, <TokenType.REFERENCES: 'REFERENCES'>, <TokenType.DETACH: 'DETACH'>, <TokenType.BIGNUM: 'BIGNUM'>, <TokenType.VECTOR: 'VECTOR'>, <TokenType.LOCALTIMESTAMP: 'LOCALTIMESTAMP'>, <TokenType.TAG: 'TAG'>, <TokenType.TRUE: 'TRUE'>, <TokenType.TIMESTAMP_S: 'TIMESTAMP_S'>, <TokenType.DICTIONARY: 'DICTIONARY'>, <TokenType.KILL: 'KILL'>, <TokenType.INDEX: 'INDEX'>, <TokenType.IPV4: 'IPV4'>, <TokenType.TSRANGE: 'TSRANGE'>, <TokenType.OFFSET: 'OFFSET'>, <TokenType.PIVOT: 'PIVOT'>, <TokenType.ANY: 'ANY'>, <TokenType.MONEY: 'MONEY'>, <TokenType.INOUT: 'INOUT'>, <TokenType.REPLACE: 'REPLACE'>, <TokenType.ENUM16: 'ENUM16'>, <TokenType.SET: 'SET'>, <TokenType.BLOB: 'BLOB'>, <TokenType.WAREHOUSE: 'WAREHOUSE'>, <TokenType.PROCEDURE: 'PROCEDURE'>, <TokenType.OBJECT: 'OBJECT'>, <TokenType.ARRAY: 'ARRAY'>, <TokenType.COPY: 'COPY'>, <TokenType.CUBE: 'CUBE'>, <TokenType.VARIANT: 'VARIANT'>, <TokenType.SINK: 'SINK'>, <TokenType.CHAR: 'CHAR'>, <TokenType.SOME: 'SOME'>, <TokenType.ANALYZE: 'ANALYZE'>, <TokenType.NAMESPACE: 'NAMESPACE'>, <TokenType.FLOAT: 'FLOAT'>, <TokenType.UNNEST: 'UNNEST'>, <TokenType.LONGTEXT: 'LONGTEXT'>, <TokenType.MULTILINESTRING: 'MULTILINESTRING'>, <TokenType.LOWCARDINALITY: 'LOWCARDINALITY'>, <TokenType.BIGSERIAL: 'BIGSERIAL'>, <TokenType.STRUCT: 'STRUCT'>, <TokenType.PERCENT: 'PERCENT'>, <TokenType.FILTER: 'FILTER'>, <TokenType.DATERANGE: 'DATERANGE'>, <TokenType.VARCHAR: 'VARCHAR'>, <TokenType.DESCRIBE: 'DESCRIBE'>, <TokenType.APPLY: 'APPLY'>, <TokenType.IDENTIFIER: 'IDENTIFIER'>, <TokenType.STORAGE_INTEGRATION: 'STORAGE_INTEGRATION'>, <TokenType.ROWVERSION: 'ROWVERSION'>, <TokenType.TIMESTAMP: 'TIMESTAMP'>, <TokenType.TINYTEXT: 'TINYTEXT'>, <TokenType.DATABASE: 'DATABASE'>, <TokenType.SIMPLEAGGREGATEFUNCTION: 'SIMPLEAGGREGATEFUNCTION'>, <TokenType.AGGREGATEFUNCTION: 'AGGREGATEFUNCTION'>, <TokenType.TABLE: 'TABLE'>, <TokenType.UMEDIUMINT: 'UMEDIUMINT'>, <TokenType.GEOGRAPHY: 'GEOGRAPHY'>, <TokenType.INT128: 'INT128'>, <TokenType.NUMMULTIRANGE: 'NUMMULTIRANGE'>, <TokenType.STAGE: 'STAGE'>, <TokenType.POINT: 'POINT'>, <TokenType.MATCH: 'MATCH'>, <TokenType.DATE: 'DATE'>, <TokenType.LONGBLOB: 'LONGBLOB'>, <TokenType.CURRENT_SCHEMA: 'CURRENT_SCHEMA'>, <TokenType.INET: 'INET'>, <TokenType.FALSE: 'FALSE'>, <TokenType.CASE: 'CASE'>, <TokenType.LIMIT: 'LIMIT'>, <TokenType.LOAD: 'LOAD'>, <TokenType.UINT128: 'UINT128'>, <TokenType.UBIGINT: 'UBIGINT'>, <TokenType.TEMPORARY: 'TEMPORARY'>, <TokenType.ROWS: 'ROWS'>, <TokenType.DECIMAL32: 'DECIMAL32'>, <TokenType.SCHEMA: 'SCHEMA'>, <TokenType.MEDIUMTEXT: 'MEDIUMTEXT'>, <TokenType.TIMESTAMPNTZ: 'TIMESTAMPNTZ'>, <TokenType.ENUM: 'ENUM'>, <TokenType.INT8MULTIRANGE: 'INT8MULTIRANGE'>, <TokenType.NULLABLE: 'NULLABLE'>, <TokenType.DATETIME2: 'DATETIME2'>, <TokenType.COMMIT: 'COMMIT'>, <TokenType.DELETE: 'DELETE'>, <TokenType.IMAGE: 'IMAGE'>, <TokenType.GET: 'GET'>, <TokenType.IPV6: 'IPV6'>, <TokenType.ROW: 'ROW'>, <TokenType.ENUM8: 'ENUM8'>, <TokenType.POLYGON: 'POLYGON'>, <TokenType.PARTITION: 'PARTITION'>, <TokenType.NEXT: 'NEXT'>, <TokenType.TINYINT: 'TINYINT'>, <TokenType.DECIMAL: 'DECIMAL'>, <TokenType.SMALLINT: 'SMALLINT'>, <TokenType.SMALLMONEY: 'SMALLMONEY'>, <TokenType.KEEP: 'KEEP'>, <TokenType.EXISTS: 'EXISTS'>, <TokenType.PSEUDO_TYPE: 'PSEUDO_TYPE'>, <TokenType.INT: 'INT'>, <TokenType.VOLATILE: 'VOLATILE'>, <TokenType.NVARCHAR: 'NVARCHAR'>, <TokenType.OVERWRITE: 'OVERWRITE'>, <TokenType.DOUBLE: 'DOUBLE'>, <TokenType.VOID: 'VOID'>, <TokenType.SOURCE: 'SOURCE'>, <TokenType.ORDINALITY: 'ORDINALITY'>, <TokenType.BIGINT: 'BIGINT'>, <TokenType.DECIMAL64: 'DECIMAL64'>, <TokenType.DATETIME64: 'DATETIME64'>, <TokenType.SUPER: 'SUPER'>, <TokenType.NUMRANGE: 'NUMRANGE'>, <TokenType.USERDEFINED: 'USERDEFINED'>, <TokenType.IPADDRESS: 'IPADDRESS'>, <TokenType.NULL: 'NULL'>, <TokenType.FILE: 'FILE'>, <TokenType.NESTED: 'NESTED'>, <TokenType.CONSTRAINT: 'CONSTRAINT'>, <TokenType.CURRENT_ROLE: 'CURRENT_ROLE'>, <TokenType.FIRST: 'FIRST'>, <TokenType.SESSION: 'SESSION'>, <TokenType.SEMANTIC_VIEW: 'SEMANTIC_VIEW'>, <TokenType.ROLLUP: 'ROLLUP'>, <TokenType.OVER: 'OVER'>, <TokenType.DATEMULTIRANGE: 'DATEMULTIRANGE'>, <TokenType.USE: 'USE'>, <TokenType.TDIGEST: 'TDIGEST'>, <TokenType.COLUMN: 'COLUMN'>, <TokenType.REFRESH: 'REFRESH'>, <TokenType.HLLSKETCH: 'HLLSKETCH'>, <TokenType.YEAR: 'YEAR'>, <TokenType.COMMAND: 'COMMAND'>, <TokenType.UNIQUE: 'UNIQUE'>, <TokenType.BEGIN: 'BEGIN'>, <TokenType.FUNCTION: 'FUNCTION'>, <TokenType.TIMESTAMP_MS: 'TIMESTAMP_MS'>, <TokenType.OVERLAPS: 'OVERLAPS'>, <TokenType.PRAGMA: 'PRAGMA'>, <TokenType.GEOGRAPHYPOINT: 'GEOGRAPHYPOINT'>, <TokenType.MODEL: 'MODEL'>, <TokenType.LINESTRING: 'LINESTRING'>, <TokenType.RING: 'RING'>, <TokenType.ASC: 'ASC'>, <TokenType.HSTORE: 'HSTORE'>, <TokenType.CACHE: 'CACHE'>, <TokenType.FINAL: 'FINAL'>, <TokenType.ALL: 'ALL'>, <TokenType.DEFAULT: 'DEFAULT'>, <TokenType.MULTIPOLYGON: 'MULTIPOLYGON'>, <TokenType.SERIAL: 'SERIAL'>, <TokenType.XML: 'XML'>, <TokenType.DECIMAL128: 'DECIMAL128'>, <TokenType.OBJECT_IDENTIFIER: 'OBJECT_IDENTIFIER'>, <TokenType.UPDATE: 'UPDATE'>, <TokenType.IPPREFIX: 'IPPREFIX'>, <TokenType.CURRENT_DATE: 'CURRENT_DATE'>, <TokenType.MAP: 'MAP'>, <TokenType.TINYBLOB: 'TINYBLOB'>, <TokenType.TIME: 'TIME'>, <TokenType.BIT: 'BIT'>, <TokenType.FILE_FORMAT: 'FILE_FORMAT'>, <TokenType.GEOMETRY: 'GEOMETRY'>, <TokenType.MERGE: 'MERGE'>, <TokenType.BINARY: 'BINARY'>, <TokenType.INT4MULTIRANGE: 'INT4MULTIRANGE'>, <TokenType.RECURSIVE: 'RECURSIVE'>, <TokenType.RANGE: 'RANGE'>, <TokenType.DATETIME: 'DATETIME'>, <TokenType.PUT: 'PUT'>, <TokenType.DECFLOAT: 'DECFLOAT'>}
SHOW_TRIE: Dict = {}
SET_TRIE: Dict = {'GLOBAL': {0: True}, 'LOCAL': {0: True}, 'SESSION': {0: True}, 'TRANSACTION': {0: True}}
Inherited Members
sqlglot.parser.Parser
Parser
STRUCT_TYPE_TOKENS
NESTED_TYPE_TOKENS
ENUM_TYPE_TOKENS
AGGREGATE_TYPE_TOKENS
TYPE_TOKENS
SIGNED_TO_UNSIGNED_TYPE_TOKEN
SUBQUERY_PREDICATES
RESERVED_TOKENS
DB_CREATABLES
CREATABLES
ALTERABLES
ALIAS_TOKENS
COLON_PLACEHOLDER_TOKENS
ARRAY_CONSTRUCTORS
COMMENT_TABLE_ALIAS_TOKENS
UPDATE_ALIAS_TOKENS
TRIM_TYPES
FUNC_TOKENS
CONJUNCTION
ASSIGNMENT
DISJUNCTION
EQUALITY
COMPARISON
TERM
FACTOR
TIMES
TIMESTAMPS
SET_OPERATIONS
JOIN_METHODS
JOIN_SIDES
JOIN_KINDS
JOIN_HINTS
LAMBDAS
CAST_COLUMN_OPERATORS
EXPRESSION_PARSERS
STRING_PARSERS
NUMERIC_PARSERS
PRIMARY_PARSERS
PIPE_SYNTAX_TRANSFORM_PARSERS
CONSTRAINT_PARSERS
ALTER_PARSERS
ALTER_ALTER_PARSERS
SCHEMA_UNNAMED_CONSTRAINTS
INVALID_FUNC_NAME_TOKENS
FUNCTIONS_WITH_ALIASED_ARGS
KEY_VALUE_DEFINITIONS
QUERY_MODIFIER_PARSERS
QUERY_MODIFIER_TOKENS
SET_PARSERS
SHOW_PARSERS
TYPE_LITERAL_PARSERS
TYPE_CONVERTERS
DDL_SELECT_TOKENS
PRE_VOLATILE_TOKENS
TRANSACTION_KIND
TRANSACTION_CHARACTERISTICS
CONFLICT_ACTIONS
CREATE_SEQUENCE
ISOLATED_LOADING_OPTIONS
USABLES
CAST_ACTIONS
SCHEMA_BINDING_OPTIONS
PROCEDURE_OPTIONS
EXECUTE_AS_OPTIONS
KEY_CONSTRAINT_OPTIONS
WINDOW_EXCLUDE_OPTIONS
INSERT_ALTERNATIVES
CLONE_KEYWORDS
HISTORICAL_DATA_PREFIX
HISTORICAL_DATA_KIND
OPCLASS_FOLLOW_KEYWORDS
OPTYPE_FOLLOW_TOKENS
TABLE_INDEX_HINT_TOKENS
VIEW_ATTRIBUTES
WINDOW_ALIAS_TOKENS
WINDOW_BEFORE_PAREN_TOKENS
WINDOW_SIDES
JSON_KEY_VALUE_SEPARATOR_TOKENS
FETCH_TOKENS
ADD_CONSTRAINT_TOKENS
DISTINCT_TOKENS
UNNEST_OFFSET_ALIAS_TOKENS
SELECT_START_TOKENS
COPY_INTO_VARLEN_OPTIONS
IS_JSON_PREDICATE_KIND
ODBC_DATETIME_LITERALS
ON_CONDITION_TOKENS
PRIVILEGE_FOLLOW_TOKENS
DESCRIBE_STYLES
SET_ASSIGNMENT_DELIMITERS
ANALYZE_STYLES
ANALYZE_EXPRESSION_PARSERS
PARTITION_KEYWORDS
AMBIGUOUS_ALIAS_TOKENS
OPERATION_MODIFIERS
RECURSIVE_CTE_SEARCH_KIND
MODIFIABLES
STRICT_CAST
PREFIXED_PIVOT_COLUMNS
IDENTIFY_PIVOT_STRINGS
LOG_DEFAULTS_TO_LN
TABLESAMPLE_CSV
DEFAULT_SAMPLING_METHOD
SET_REQUIRES_ASSIGNMENT_DELIMITER
TRIM_PATTERN_FIRST
STRING_ALIASES
MODIFIERS_ATTACHED_TO_SET_OP
SET_OP_MODIFIERS
NO_PAREN_IF_COMMANDS
COLON_IS_VARIANT_EXTRACT
VALUES_FOLLOWED_BY_PAREN
SUPPORTS_IMPLICIT_UNNEST
INTERVAL_SPANS
SUPPORTS_PARTITION_SELECTION
WRAPPED_TRANSFORM_COLUMN_CONSTRAINT
OPTIONAL_ALIAS_TOKEN_CTE
ALTER_RENAME_REQUIRES_COLUMN
ALTER_TABLE_PARTITIONS
JOINS_HAVE_EQUAL_PRECEDENCE
ZONE_AWARE_TIMESTAMP_CONSTRUCTOR
MAP_KEYS_ARE_ARBITRARY_EXPRESSIONS
JSON_EXTRACT_REQUIRES_JSON_EXPRESSION
ADD_JOIN_ON_TRUE
error_level
error_message_context
max_errors
dialect
reset
parse
parse_into
check_errors
raise_error
expression
validate_expression
parse_set_operation
build_cast
errors
sql
class Postgres.Generator(sqlglot.generator.Generator):
 673    class Generator(generator.Generator):
 674        SINGLE_STRING_INTERVAL = True
 675        RENAME_TABLE_WITH_DB = False
 676        LOCKING_READS_SUPPORTED = True
 677        JOIN_HINTS = False
 678        TABLE_HINTS = False
 679        QUERY_HINTS = False
 680        NVL2_SUPPORTED = False
 681        PARAMETER_TOKEN = "$"
 682        NAMED_PLACEHOLDER_TOKEN = "%"
 683        TABLESAMPLE_SIZE_IS_ROWS = False
 684        TABLESAMPLE_SEED_KEYWORD = "REPEATABLE"
 685        SUPPORTS_SELECT_INTO = True
 686        JSON_TYPE_REQUIRED_FOR_EXTRACTION = True
 687        SUPPORTS_UNLOGGED_TABLES = True
 688        LIKE_PROPERTY_INSIDE_SCHEMA = True
 689        MULTI_ARG_DISTINCT = False
 690        CAN_IMPLEMENT_ARRAY_ANY = True
 691        SUPPORTS_WINDOW_EXCLUDE = True
 692        COPY_HAS_INTO_KEYWORD = False
 693        ARRAY_CONCAT_IS_VAR_LEN = False
 694        SUPPORTS_MEDIAN = False
 695        ARRAY_SIZE_DIM_REQUIRED = True
 696        SUPPORTS_BETWEEN_FLAGS = True
 697        INOUT_SEPARATOR = ""  # PostgreSQL uses "INOUT" (no space)
 698
 699        SUPPORTED_JSON_PATH_PARTS = {
 700            exp.JSONPathKey,
 701            exp.JSONPathRoot,
 702            exp.JSONPathSubscript,
 703        }
 704
 705        def lateral_sql(self, expression: exp.Lateral) -> str:
 706            sql = super().lateral_sql(expression)
 707
 708            if expression.args.get("cross_apply") is not None:
 709                sql = f"{sql} ON TRUE"
 710
 711            return sql
 712
 713        TYPE_MAPPING = {
 714            **generator.Generator.TYPE_MAPPING,
 715            exp.DataType.Type.TINYINT: "SMALLINT",
 716            exp.DataType.Type.FLOAT: "REAL",
 717            exp.DataType.Type.DOUBLE: "DOUBLE PRECISION",
 718            exp.DataType.Type.BINARY: "BYTEA",
 719            exp.DataType.Type.VARBINARY: "BYTEA",
 720            exp.DataType.Type.ROWVERSION: "BYTEA",
 721            exp.DataType.Type.DATETIME: "TIMESTAMP",
 722            exp.DataType.Type.TIMESTAMPNTZ: "TIMESTAMP",
 723            exp.DataType.Type.BLOB: "BYTEA",
 724        }
 725
 726        TRANSFORMS = {
 727            **generator.Generator.TRANSFORMS,
 728            exp.AnyValue: _versioned_anyvalue_sql,
 729            exp.ArrayConcat: array_concat_sql("ARRAY_CAT"),
 730            exp.ArrayFilter: filter_array_using_unnest,
 731            exp.ArrayAppend: array_append_sql("ARRAY_APPEND"),
 732            exp.ArrayPrepend: array_append_sql("ARRAY_PREPEND", swap_params=True),
 733            exp.BitwiseAndAgg: rename_func("BIT_AND"),
 734            exp.BitwiseOrAgg: rename_func("BIT_OR"),
 735            exp.BitwiseXor: lambda self, e: self.binary(e, "#"),
 736            exp.BitwiseXorAgg: rename_func("BIT_XOR"),
 737            exp.ColumnDef: transforms.preprocess([_auto_increment_to_serial, _serial_to_generated]),
 738            exp.CurrentDate: no_paren_current_date_sql,
 739            exp.CurrentTimestamp: lambda *_: "CURRENT_TIMESTAMP",
 740            exp.CurrentUser: lambda *_: "CURRENT_USER",
 741            exp.DateAdd: _date_add_sql("+"),
 742            exp.DateDiff: _date_diff_sql,
 743            exp.DateStrToDate: datestrtodate_sql,
 744            exp.DateSub: _date_add_sql("-"),
 745            exp.Explode: rename_func("UNNEST"),
 746            exp.ExplodingGenerateSeries: rename_func("GENERATE_SERIES"),
 747            exp.Getbit: getbit_sql,
 748            exp.GroupConcat: lambda self, e: groupconcat_sql(
 749                self, e, func_name="STRING_AGG", within_group=False
 750            ),
 751            exp.IntDiv: rename_func("DIV"),
 752            exp.JSONArrayAgg: lambda self, e: self.func(
 753                "JSON_AGG",
 754                self.sql(e, "this"),
 755                suffix=f"{self.sql(e, 'order')})",
 756            ),
 757            exp.JSONExtract: _json_extract_sql("JSON_EXTRACT_PATH", "->"),
 758            exp.JSONExtractScalar: _json_extract_sql("JSON_EXTRACT_PATH_TEXT", "->>"),
 759            exp.JSONBExtract: lambda self, e: self.binary(e, "#>"),
 760            exp.JSONBExtractScalar: lambda self, e: self.binary(e, "#>>"),
 761            exp.JSONBContains: lambda self, e: self.binary(e, "?"),
 762            exp.ParseJSON: lambda self, e: self.sql(exp.cast(e.this, exp.DataType.Type.JSON)),
 763            exp.JSONPathKey: json_path_key_only_name,
 764            exp.JSONPathRoot: lambda *_: "",
 765            exp.JSONPathSubscript: lambda self, e: self.json_path_part(e.this),
 766            exp.LastDay: no_last_day_sql,
 767            exp.LogicalOr: rename_func("BOOL_OR"),
 768            exp.LogicalAnd: rename_func("BOOL_AND"),
 769            exp.Max: max_or_greatest,
 770            exp.MapFromEntries: no_map_from_entries_sql,
 771            exp.Min: min_or_least,
 772            exp.Merge: merge_without_target_sql,
 773            exp.PartitionedByProperty: lambda self, e: f"PARTITION BY {self.sql(e, 'this')}",
 774            exp.PercentileCont: transforms.preprocess(
 775                [transforms.add_within_group_for_percentiles]
 776            ),
 777            exp.PercentileDisc: transforms.preprocess(
 778                [transforms.add_within_group_for_percentiles]
 779            ),
 780            exp.Pivot: no_pivot_sql,
 781            exp.Rand: rename_func("RANDOM"),
 782            exp.RegexpLike: lambda self, e: self.binary(e, "~"),
 783            exp.RegexpILike: lambda self, e: self.binary(e, "~*"),
 784            exp.RegexpReplace: lambda self, e: self.func(
 785                "REGEXP_REPLACE",
 786                e.this,
 787                e.expression,
 788                e.args.get("replacement"),
 789                e.args.get("position"),
 790                e.args.get("occurrence"),
 791                regexp_replace_global_modifier(e),
 792            ),
 793            exp.Round: _round_sql,
 794            exp.Select: transforms.preprocess(
 795                [
 796                    transforms.eliminate_semi_and_anti_joins,
 797                    transforms.eliminate_qualify,
 798                ]
 799            ),
 800            exp.SHA2: sha256_sql,
 801            exp.SHA2Digest: sha2_digest_sql,
 802            exp.StrPosition: lambda self, e: strposition_sql(self, e, func_name="POSITION"),
 803            exp.StrToDate: lambda self, e: self.func("TO_DATE", e.this, self.format_time(e)),
 804            exp.StrToTime: lambda self, e: self.func("TO_TIMESTAMP", e.this, self.format_time(e)),
 805            exp.StructExtract: struct_extract_sql,
 806            exp.Substring: _substring_sql,
 807            exp.TimeFromParts: rename_func("MAKE_TIME"),
 808            exp.TimestampFromParts: rename_func("MAKE_TIMESTAMP"),
 809            exp.TimestampTrunc: timestamptrunc_sql(zone=True),
 810            exp.TimeStrToTime: timestrtotime_sql,
 811            exp.TimeToStr: lambda self, e: self.func("TO_CHAR", e.this, self.format_time(e)),
 812            exp.ToChar: lambda self, e: self.function_fallback_sql(e)
 813            if e.args.get("format")
 814            else self.tochar_sql(e),
 815            exp.Trim: trim_sql,
 816            exp.TryCast: no_trycast_sql,
 817            exp.TsOrDsAdd: _date_add_sql("+"),
 818            exp.TsOrDsDiff: _date_diff_sql,
 819            exp.UnixToTime: lambda self, e: self.func("TO_TIMESTAMP", e.this),
 820            exp.Uuid: lambda *_: "GEN_RANDOM_UUID()",
 821            exp.TimeToUnix: lambda self, e: self.func(
 822                "DATE_PART", exp.Literal.string("epoch"), e.this
 823            ),
 824            exp.VariancePop: rename_func("VAR_POP"),
 825            exp.Variance: rename_func("VAR_SAMP"),
 826            exp.Xor: bool_xor_sql,
 827            exp.Unicode: rename_func("ASCII"),
 828            exp.UnixToTime: _unix_to_time_sql,
 829            exp.Levenshtein: _levenshtein_sql,
 830            exp.JSONObjectAgg: rename_func("JSON_OBJECT_AGG"),
 831            exp.JSONBObjectAgg: rename_func("JSONB_OBJECT_AGG"),
 832            exp.CountIf: count_if_to_sum,
 833        }
 834
 835        TRANSFORMS.pop(exp.CommentColumnConstraint)
 836
 837        PROPERTIES_LOCATION = {
 838            **generator.Generator.PROPERTIES_LOCATION,
 839            exp.PartitionedByProperty: exp.Properties.Location.POST_SCHEMA,
 840            exp.TransientProperty: exp.Properties.Location.UNSUPPORTED,
 841            exp.VolatileProperty: exp.Properties.Location.UNSUPPORTED,
 842        }
 843
 844        def schemacommentproperty_sql(self, expression: exp.SchemaCommentProperty) -> str:
 845            self.unsupported("Table comments are not supported in the CREATE statement")
 846            return ""
 847
 848        def commentcolumnconstraint_sql(self, expression: exp.CommentColumnConstraint) -> str:
 849            self.unsupported("Column comments are not supported in the CREATE statement")
 850            return ""
 851
 852        def columndef_sql(self, expression: exp.ColumnDef, sep: str = " ") -> str:
 853            # PostgreSQL places parameter modes BEFORE parameter name
 854            param_constraint = expression.find(exp.InOutColumnConstraint)
 855
 856            if param_constraint:
 857                mode_sql = self.sql(param_constraint)
 858                param_constraint.pop()  # Remove to prevent double-rendering
 859                base_sql = super().columndef_sql(expression, sep)
 860                return f"{mode_sql} {base_sql}"
 861
 862            return super().columndef_sql(expression, sep)
 863
 864        def unnest_sql(self, expression: exp.Unnest) -> str:
 865            if len(expression.expressions) == 1:
 866                arg = expression.expressions[0]
 867                if isinstance(arg, exp.GenerateDateArray):
 868                    generate_series: exp.Expression = exp.GenerateSeries(**arg.args)
 869                    if isinstance(expression.parent, (exp.From, exp.Join)):
 870                        generate_series = (
 871                            exp.select("value::date")
 872                            .from_(exp.Table(this=generate_series).as_("_t", table=["value"]))
 873                            .subquery(expression.args.get("alias") or "_unnested_generate_series")
 874                        )
 875                    return self.sql(generate_series)
 876
 877                from sqlglot.optimizer.annotate_types import annotate_types
 878
 879                this = annotate_types(arg, dialect=self.dialect)
 880                if this.is_type("array<json>"):
 881                    while isinstance(this, exp.Cast):
 882                        this = this.this
 883
 884                    arg_as_json = self.sql(exp.cast(this, exp.DataType.Type.JSON))
 885                    alias = self.sql(expression, "alias")
 886                    alias = f" AS {alias}" if alias else ""
 887
 888                    if expression.args.get("offset"):
 889                        self.unsupported("Unsupported JSON_ARRAY_ELEMENTS with offset")
 890
 891                    return f"JSON_ARRAY_ELEMENTS({arg_as_json}){alias}"
 892
 893            return super().unnest_sql(expression)
 894
 895        def bracket_sql(self, expression: exp.Bracket) -> str:
 896            """Forms like ARRAY[1, 2, 3][3] aren't allowed; we need to wrap the ARRAY."""
 897            if isinstance(expression.this, exp.Array):
 898                expression.set("this", exp.paren(expression.this, copy=False))
 899
 900            return super().bracket_sql(expression)
 901
 902        def matchagainst_sql(self, expression: exp.MatchAgainst) -> str:
 903            this = self.sql(expression, "this")
 904            expressions = [f"{self.sql(e)} @@ {this}" for e in expression.expressions]
 905            sql = " OR ".join(expressions)
 906            return f"({sql})" if len(expressions) > 1 else sql
 907
 908        def alterset_sql(self, expression: exp.AlterSet) -> str:
 909            exprs = self.expressions(expression, flat=True)
 910            exprs = f"({exprs})" if exprs else ""
 911
 912            access_method = self.sql(expression, "access_method")
 913            access_method = f"ACCESS METHOD {access_method}" if access_method else ""
 914            tablespace = self.sql(expression, "tablespace")
 915            tablespace = f"TABLESPACE {tablespace}" if tablespace else ""
 916            option = self.sql(expression, "option")
 917
 918            return f"SET {exprs}{access_method}{tablespace}{option}"
 919
 920        def datatype_sql(self, expression: exp.DataType) -> str:
 921            if expression.is_type(exp.DataType.Type.ARRAY):
 922                if expression.expressions:
 923                    values = self.expressions(expression, key="values", flat=True)
 924                    return f"{self.expressions(expression, flat=True)}[{values}]"
 925                return "ARRAY"
 926
 927            if (
 928                expression.is_type(exp.DataType.Type.DOUBLE, exp.DataType.Type.FLOAT)
 929                and expression.expressions
 930            ):
 931                # Postgres doesn't support precision for REAL and DOUBLE PRECISION types
 932                return f"FLOAT({self.expressions(expression, flat=True)})"
 933
 934            return super().datatype_sql(expression)
 935
 936        def cast_sql(self, expression: exp.Cast, safe_prefix: t.Optional[str] = None) -> str:
 937            this = expression.this
 938
 939            # Postgres casts DIV() to decimal for transpilation but when roundtripping it's superfluous
 940            if isinstance(this, exp.IntDiv) and expression.to == exp.DataType.build("decimal"):
 941                return self.sql(this)
 942
 943            return super().cast_sql(expression, safe_prefix=safe_prefix)
 944
 945        def array_sql(self, expression: exp.Array) -> str:
 946            exprs = expression.expressions
 947            func_name = self.normalize_func("ARRAY")
 948
 949            if isinstance(seq_get(exprs, 0), exp.Select):
 950                return f"{func_name}({self.sql(exprs[0])})"
 951
 952            return f"{func_name}{inline_array_sql(self, expression)}"
 953
 954        def computedcolumnconstraint_sql(self, expression: exp.ComputedColumnConstraint) -> str:
 955            return f"GENERATED ALWAYS AS ({self.sql(expression, 'this')}) STORED"
 956
 957        def isascii_sql(self, expression: exp.IsAscii) -> str:
 958            return f"({self.sql(expression.this)} ~ '^[[:ascii:]]*$')"
 959
 960        def ignorenulls_sql(self, expression: exp.IgnoreNulls) -> str:
 961            # https://www.postgresql.org/docs/current/functions-window.html
 962            self.unsupported("PostgreSQL does not support IGNORE NULLS.")
 963            return self.sql(expression.this)
 964
 965        def respectnulls_sql(self, expression: exp.RespectNulls) -> str:
 966            # https://www.postgresql.org/docs/current/functions-window.html
 967            self.unsupported("PostgreSQL does not support RESPECT NULLS.")
 968            return self.sql(expression.this)
 969
 970        @unsupported_args("this")
 971        def currentschema_sql(self, expression: exp.CurrentSchema) -> str:
 972            return "CURRENT_SCHEMA"
 973
 974        def interval_sql(self, expression: exp.Interval) -> str:
 975            unit = expression.text("unit").lower()
 976
 977            this = expression.this
 978            if unit.startswith("quarter") and isinstance(this, exp.Literal):
 979                this.replace(exp.Literal.string(int(this.to_py()) * 3))
 980                expression.args["unit"].replace(exp.var("MONTH"))
 981
 982            return super().interval_sql(expression)
 983
 984        def placeholder_sql(self, expression: exp.Placeholder) -> str:
 985            if expression.args.get("jdbc"):
 986                return "?"
 987
 988            this = f"({expression.name})" if expression.this else ""
 989            return f"{self.NAMED_PLACEHOLDER_TOKEN}{this}s"
 990
 991        def arraycontains_sql(self, expression: exp.ArrayContains) -> str:
 992            # Convert DuckDB's LIST_CONTAINS(array, value) to PostgreSQL
 993            # DuckDB behavior:
 994            #   - LIST_CONTAINS([1,2,3], 2) -> true
 995            #   - LIST_CONTAINS([1,2,3], 4) -> false
 996            #   - LIST_CONTAINS([1,2,NULL], 4) -> false (not NULL)
 997            #   - LIST_CONTAINS([1,2,3], NULL) -> NULL
 998            #
 999            # PostgreSQL equivalent: CASE WHEN value IS NULL THEN NULL
1000            #                            ELSE COALESCE(value = ANY(array), FALSE) END
1001            value = expression.expression
1002            array = expression.this
1003
1004            coalesce_expr = exp.Coalesce(
1005                this=value.eq(exp.Any(this=exp.paren(expression=array, copy=False))),
1006                expressions=[exp.false()],
1007            )
1008
1009            case_expr = (
1010                exp.Case()
1011                .when(exp.Is(this=value, expression=exp.null()), exp.null(), copy=False)
1012                .else_(coalesce_expr, copy=False)
1013            )
1014
1015            return self.sql(case_expr)

Generator converts a given syntax tree to the corresponding SQL string.

Arguments:
  • pretty: Whether to format the produced SQL string. Default: False.
  • identify: Determines when an identifier should be quoted. Possible values are: False (default): Never quote, except in cases where it's mandatory by the dialect. True: Always quote except for specials cases. 'safe': Only quote identifiers that are case insensitive.
  • normalize: Whether to normalize identifiers to lowercase. Default: False.
  • pad: The pad size in a formatted string. For example, this affects the indentation of a projection in a query, relative to its nesting level. Default: 2.
  • indent: The indentation size in a formatted string. For example, this affects the indentation of subqueries and filters under a WHERE clause. Default: 2.
  • normalize_functions: How to normalize function names. Possible values are: "upper" or True (default): Convert names to uppercase. "lower": Convert names to lowercase. False: Disables function name normalization.
  • unsupported_level: Determines the generator's behavior when it encounters unsupported expressions. Default ErrorLevel.WARN.
  • max_unsupported: Maximum number of unsupported messages to include in a raised UnsupportedError. This is only relevant if unsupported_level is ErrorLevel.RAISE. Default: 3
  • leading_comma: Whether the comma is leading or trailing in select expressions. This is only relevant when generating in pretty mode. Default: False
  • max_text_width: The max number of characters in a segment before creating new lines in pretty mode. The default is on the smaller end because the length only represents a segment and not the true line length. Default: 80
  • comments: Whether to preserve comments in the output SQL code. Default: True
SINGLE_STRING_INTERVAL = True
RENAME_TABLE_WITH_DB = False
LOCKING_READS_SUPPORTED = True
JOIN_HINTS = False
TABLE_HINTS = False
QUERY_HINTS = False
NVL2_SUPPORTED = False
PARAMETER_TOKEN = '$'
NAMED_PLACEHOLDER_TOKEN = '%'
TABLESAMPLE_SIZE_IS_ROWS = False
TABLESAMPLE_SEED_KEYWORD = 'REPEATABLE'
SUPPORTS_SELECT_INTO = True
JSON_TYPE_REQUIRED_FOR_EXTRACTION = True
SUPPORTS_UNLOGGED_TABLES = True
LIKE_PROPERTY_INSIDE_SCHEMA = True
MULTI_ARG_DISTINCT = False
CAN_IMPLEMENT_ARRAY_ANY = True
SUPPORTS_WINDOW_EXCLUDE = True
COPY_HAS_INTO_KEYWORD = False
ARRAY_CONCAT_IS_VAR_LEN = False
SUPPORTS_MEDIAN = False
ARRAY_SIZE_DIM_REQUIRED = True
SUPPORTS_BETWEEN_FLAGS = True
INOUT_SEPARATOR = ''
def lateral_sql(self, expression: sqlglot.expressions.Lateral) -> str:
705        def lateral_sql(self, expression: exp.Lateral) -> str:
706            sql = super().lateral_sql(expression)
707
708            if expression.args.get("cross_apply") is not None:
709                sql = f"{sql} ON TRUE"
710
711            return sql
TYPE_MAPPING = {<Type.DATETIME2: 'DATETIME2'>: 'TIMESTAMP', <Type.NCHAR: 'NCHAR'>: 'CHAR', <Type.NVARCHAR: 'NVARCHAR'>: 'VARCHAR', <Type.MEDIUMTEXT: 'MEDIUMTEXT'>: 'TEXT', <Type.LONGTEXT: 'LONGTEXT'>: 'TEXT', <Type.TINYTEXT: 'TINYTEXT'>: 'TEXT', <Type.BLOB: 'BLOB'>: 'BYTEA', <Type.MEDIUMBLOB: 'MEDIUMBLOB'>: 'BLOB', <Type.LONGBLOB: 'LONGBLOB'>: 'BLOB', <Type.TINYBLOB: 'TINYBLOB'>: 'BLOB', <Type.INET: 'INET'>: 'INET', <Type.ROWVERSION: 'ROWVERSION'>: 'BYTEA', <Type.SMALLDATETIME: 'SMALLDATETIME'>: 'TIMESTAMP', <Type.TINYINT: 'TINYINT'>: 'SMALLINT', <Type.FLOAT: 'FLOAT'>: 'REAL', <Type.DOUBLE: 'DOUBLE'>: 'DOUBLE PRECISION', <Type.BINARY: 'BINARY'>: 'BYTEA', <Type.VARBINARY: 'VARBINARY'>: 'BYTEA', <Type.DATETIME: 'DATETIME'>: 'TIMESTAMP', <Type.TIMESTAMPNTZ: 'TIMESTAMPNTZ'>: 'TIMESTAMP'}
TRANSFORMS = {<class 'sqlglot.expressions.JSONPathKey'>: <function json_path_key_only_name>, <class 'sqlglot.expressions.JSONPathRoot'>: <function Postgres.Generator.<lambda>>, <class 'sqlglot.expressions.JSONPathSubscript'>: <function Postgres.Generator.<lambda>>, <class 'sqlglot.expressions.Adjacent'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.AllowedValuesProperty'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.AnalyzeColumns'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.AnalyzeWith'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.ArrayContainsAll'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.ArrayOverlaps'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.AutoRefreshProperty'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.BackupProperty'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.CaseSpecificColumnConstraint'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.Ceil'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.CharacterSetColumnConstraint'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.CharacterSetProperty'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.ClusteredColumnConstraint'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.CollateColumnConstraint'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.ConnectByRoot'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.ConvertToCharset'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.CopyGrantsProperty'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.CredentialsProperty'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.CurrentCatalog'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.SessionUser'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.DateFormatColumnConstraint'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.DefaultColumnConstraint'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.DynamicProperty'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.EmptyProperty'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.EncodeColumnConstraint'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.EnviromentProperty'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.EphemeralColumnConstraint'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.ExcludeColumnConstraint'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.ExecuteAsProperty'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.Except'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.ExternalProperty'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.Floor'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.Get'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.GlobalProperty'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.HeapProperty'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.IcebergProperty'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.InheritsProperty'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.InlineLengthColumnConstraint'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.InputModelProperty'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.Intersect'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.IntervalSpan'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.Int64'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.JSONBContainsAnyTopKeys'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.JSONBContainsAllTopKeys'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.JSONBDeleteAtPath'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.LanguageProperty'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.LocationProperty'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.LogProperty'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.MaterializedProperty'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.NetFunc'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.NonClusteredColumnConstraint'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.NoPrimaryIndexProperty'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.NotForReplicationColumnConstraint'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.OnCommitProperty'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.OnProperty'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.OnUpdateColumnConstraint'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.Operator'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.OutputModelProperty'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.ExtendsLeft'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.ExtendsRight'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.PathColumnConstraint'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.PartitionedByBucket'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.PartitionByTruncate'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.PivotAny'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.PositionalColumn'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.ProjectionPolicyColumnConstraint'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.ZeroFillColumnConstraint'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.Put'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.RemoteWithConnectionModelProperty'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.ReturnsProperty'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.SafeFunc'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.SampleProperty'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.SecureProperty'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.SecurityProperty'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.SetConfigProperty'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.SetProperty'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.SettingsProperty'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.SharingProperty'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.SqlReadWriteProperty'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.SqlSecurityProperty'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.StabilityProperty'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.Stream'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.StreamingTableProperty'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.StrictProperty'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.SwapTable'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.TableColumn'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.Tags'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.TemporaryProperty'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.TitleColumnConstraint'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.ToMap'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.ToTableProperty'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.TransformModelProperty'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.TransientProperty'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.Union'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.UnloggedProperty'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.UsingTemplateProperty'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.UsingData'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.UppercaseColumnConstraint'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.UtcDate'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.UtcTime'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.UtcTimestamp'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.Variadic'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.VarMap'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.ViewAttributeProperty'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.VolatileProperty'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.WithJournalTableProperty'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.WithProcedureOptions'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.WithSchemaBindingProperty'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.WithOperator'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.ForceProperty'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.AnyValue'>: <function _versioned_anyvalue_sql>, <class 'sqlglot.expressions.ArrayConcat'>: <function array_concat_sql.<locals>._array_concat_sql>, <class 'sqlglot.expressions.ArrayFilter'>: <function filter_array_using_unnest>, <class 'sqlglot.expressions.ArrayAppend'>: <function array_append_sql.<locals>._array_append_sql>, <class 'sqlglot.expressions.ArrayPrepend'>: <function array_append_sql.<locals>._array_append_sql>, <class 'sqlglot.expressions.BitwiseAndAgg'>: <function rename_func.<locals>.<lambda>>, <class 'sqlglot.expressions.BitwiseOrAgg'>: <function rename_func.<locals>.<lambda>>, <class 'sqlglot.expressions.BitwiseXor'>: <function Postgres.Generator.<lambda>>, <class 'sqlglot.expressions.BitwiseXorAgg'>: <function rename_func.<locals>.<lambda>>, <class 'sqlglot.expressions.ColumnDef'>: <function preprocess.<locals>._to_sql>, <class 'sqlglot.expressions.CurrentDate'>: <function no_paren_current_date_sql>, <class 'sqlglot.expressions.CurrentTimestamp'>: <function Postgres.Generator.<lambda>>, <class 'sqlglot.expressions.CurrentUser'>: <function Postgres.Generator.<lambda>>, <class 'sqlglot.expressions.DateAdd'>: <function _date_add_sql.<locals>.func>, <class 'sqlglot.expressions.DateDiff'>: <function _date_diff_sql>, <class 'sqlglot.expressions.DateStrToDate'>: <function datestrtodate_sql>, <class 'sqlglot.expressions.DateSub'>: <function _date_add_sql.<locals>.func>, <class 'sqlglot.expressions.Explode'>: <function rename_func.<locals>.<lambda>>, <class 'sqlglot.expressions.ExplodingGenerateSeries'>: <function rename_func.<locals>.<lambda>>, <class 'sqlglot.expressions.Getbit'>: <function getbit_sql>, <class 'sqlglot.expressions.GroupConcat'>: <function Postgres.Generator.<lambda>>, <class 'sqlglot.expressions.IntDiv'>: <function rename_func.<locals>.<lambda>>, <class 'sqlglot.expressions.JSONArrayAgg'>: <function Postgres.Generator.<lambda>>, <class 'sqlglot.expressions.JSONExtract'>: <function _json_extract_sql.<locals>._generate>, <class 'sqlglot.expressions.JSONExtractScalar'>: <function _json_extract_sql.<locals>._generate>, <class 'sqlglot.expressions.JSONBExtract'>: <function Postgres.Generator.<lambda>>, <class 'sqlglot.expressions.JSONBExtractScalar'>: <function Postgres.Generator.<lambda>>, <class 'sqlglot.expressions.JSONBContains'>: <function Postgres.Generator.<lambda>>, <class 'sqlglot.expressions.ParseJSON'>: <function Postgres.Generator.<lambda>>, <class 'sqlglot.expressions.LastDay'>: <function no_last_day_sql>, <class 'sqlglot.expressions.LogicalOr'>: <function rename_func.<locals>.<lambda>>, <class 'sqlglot.expressions.LogicalAnd'>: <function rename_func.<locals>.<lambda>>, <class 'sqlglot.expressions.Max'>: <function max_or_greatest>, <class 'sqlglot.expressions.MapFromEntries'>: <function no_map_from_entries_sql>, <class 'sqlglot.expressions.Min'>: <function min_or_least>, <class 'sqlglot.expressions.Merge'>: <function merge_without_target_sql>, <class 'sqlglot.expressions.PartitionedByProperty'>: <function Postgres.Generator.<lambda>>, <class 'sqlglot.expressions.PercentileCont'>: <function preprocess.<locals>._to_sql>, <class 'sqlglot.expressions.PercentileDisc'>: <function preprocess.<locals>._to_sql>, <class 'sqlglot.expressions.Pivot'>: <function no_pivot_sql>, <class 'sqlglot.expressions.Rand'>: <function rename_func.<locals>.<lambda>>, <class 'sqlglot.expressions.RegexpLike'>: <function Postgres.Generator.<lambda>>, <class 'sqlglot.expressions.RegexpILike'>: <function Postgres.Generator.<lambda>>, <class 'sqlglot.expressions.RegexpReplace'>: <function Postgres.Generator.<lambda>>, <class 'sqlglot.expressions.Round'>: <function _round_sql>, <class 'sqlglot.expressions.Select'>: <function preprocess.<locals>._to_sql>, <class 'sqlglot.expressions.SHA2'>: <function sha256_sql>, <class 'sqlglot.expressions.SHA2Digest'>: <function sha2_digest_sql>, <class 'sqlglot.expressions.StrPosition'>: <function Postgres.Generator.<lambda>>, <class 'sqlglot.expressions.StrToDate'>: <function Postgres.Generator.<lambda>>, <class 'sqlglot.expressions.StrToTime'>: <function Postgres.Generator.<lambda>>, <class 'sqlglot.expressions.StructExtract'>: <function struct_extract_sql>, <class 'sqlglot.expressions.Substring'>: <function _substring_sql>, <class 'sqlglot.expressions.TimeFromParts'>: <function rename_func.<locals>.<lambda>>, <class 'sqlglot.expressions.TimestampFromParts'>: <function rename_func.<locals>.<lambda>>, <class 'sqlglot.expressions.TimestampTrunc'>: <function timestamptrunc_sql.<locals>._timestamptrunc_sql>, <class 'sqlglot.expressions.TimeStrToTime'>: <function timestrtotime_sql>, <class 'sqlglot.expressions.TimeToStr'>: <function Postgres.Generator.<lambda>>, <class 'sqlglot.expressions.ToChar'>: <function Postgres.Generator.<lambda>>, <class 'sqlglot.expressions.Trim'>: <function trim_sql>, <class 'sqlglot.expressions.TryCast'>: <function no_trycast_sql>, <class 'sqlglot.expressions.TsOrDsAdd'>: <function _date_add_sql.<locals>.func>, <class 'sqlglot.expressions.TsOrDsDiff'>: <function _date_diff_sql>, <class 'sqlglot.expressions.UnixToTime'>: <function _unix_to_time_sql>, <class 'sqlglot.expressions.Uuid'>: <function Postgres.Generator.<lambda>>, <class 'sqlglot.expressions.TimeToUnix'>: <function Postgres.Generator.<lambda>>, <class 'sqlglot.expressions.VariancePop'>: <function rename_func.<locals>.<lambda>>, <class 'sqlglot.expressions.Variance'>: <function rename_func.<locals>.<lambda>>, <class 'sqlglot.expressions.Xor'>: <function bool_xor_sql>, <class 'sqlglot.expressions.Unicode'>: <function rename_func.<locals>.<lambda>>, <class 'sqlglot.expressions.Levenshtein'>: <function _levenshtein_sql>, <class 'sqlglot.expressions.JSONObjectAgg'>: <function rename_func.<locals>.<lambda>>, <class 'sqlglot.expressions.JSONBObjectAgg'>: <function rename_func.<locals>.<lambda>>, <class 'sqlglot.expressions.CountIf'>: <function count_if_to_sum>}
PROPERTIES_LOCATION = {<class 'sqlglot.expressions.AllowedValuesProperty'>: <Location.POST_SCHEMA: 'POST_SCHEMA'>, <class 'sqlglot.expressions.AlgorithmProperty'>: <Location.POST_CREATE: 'POST_CREATE'>, <class 'sqlglot.expressions.AutoIncrementProperty'>: <Location.POST_SCHEMA: 'POST_SCHEMA'>, <class 'sqlglot.expressions.AutoRefreshProperty'>: <Location.POST_SCHEMA: 'POST_SCHEMA'>, <class 'sqlglot.expressions.BackupProperty'>: <Location.POST_SCHEMA: 'POST_SCHEMA'>, <class 'sqlglot.expressions.BlockCompressionProperty'>: <Location.POST_NAME: 'POST_NAME'>, <class 'sqlglot.expressions.CharacterSetProperty'>: <Location.POST_SCHEMA: 'POST_SCHEMA'>, <class 'sqlglot.expressions.ChecksumProperty'>: <Location.POST_NAME: 'POST_NAME'>, <class 'sqlglot.expressions.CollateProperty'>: <Location.POST_SCHEMA: 'POST_SCHEMA'>, <class 'sqlglot.expressions.CopyGrantsProperty'>: <Location.POST_SCHEMA: 'POST_SCHEMA'>, <class 'sqlglot.expressions.Cluster'>: <Location.POST_SCHEMA: 'POST_SCHEMA'>, <class 'sqlglot.expressions.ClusteredByProperty'>: <Location.POST_SCHEMA: 'POST_SCHEMA'>, <class 'sqlglot.expressions.DistributedByProperty'>: <Location.POST_SCHEMA: 'POST_SCHEMA'>, <class 'sqlglot.expressions.DuplicateKeyProperty'>: <Location.POST_SCHEMA: 'POST_SCHEMA'>, <class 'sqlglot.expressions.DataBlocksizeProperty'>: <Location.POST_NAME: 'POST_NAME'>, <class 'sqlglot.expressions.DataDeletionProperty'>: <Location.POST_SCHEMA: 'POST_SCHEMA'>, <class 'sqlglot.expressions.DefinerProperty'>: <Location.POST_CREATE: 'POST_CREATE'>, <class 'sqlglot.expressions.DictRange'>: <Location.POST_SCHEMA: 'POST_SCHEMA'>, <class 'sqlglot.expressions.DictProperty'>: <Location.POST_SCHEMA: 'POST_SCHEMA'>, <class 'sqlglot.expressions.DynamicProperty'>: <Location.POST_CREATE: 'POST_CREATE'>, <class 'sqlglot.expressions.DistKeyProperty'>: <Location.POST_SCHEMA: 'POST_SCHEMA'>, <class 'sqlglot.expressions.DistStyleProperty'>: <Location.POST_SCHEMA: 'POST_SCHEMA'>, <class 'sqlglot.expressions.EmptyProperty'>: <Location.POST_SCHEMA: 'POST_SCHEMA'>, <class 'sqlglot.expressions.EncodeProperty'>: <Location.POST_EXPRESSION: 'POST_EXPRESSION'>, <class 'sqlglot.expressions.EngineProperty'>: <Location.POST_SCHEMA: 'POST_SCHEMA'>, <class 'sqlglot.expressions.EnviromentProperty'>: <Location.POST_SCHEMA: 'POST_SCHEMA'>, <class 'sqlglot.expressions.ExecuteAsProperty'>: <Location.POST_SCHEMA: 'POST_SCHEMA'>, <class 'sqlglot.expressions.ExternalProperty'>: <Location.POST_CREATE: 'POST_CREATE'>, <class 'sqlglot.expressions.FallbackProperty'>: <Location.POST_NAME: 'POST_NAME'>, <class 'sqlglot.expressions.FileFormatProperty'>: <Location.POST_WITH: 'POST_WITH'>, <class 'sqlglot.expressions.FreespaceProperty'>: <Location.POST_NAME: 'POST_NAME'>, <class 'sqlglot.expressions.GlobalProperty'>: <Location.POST_CREATE: 'POST_CREATE'>, <class 'sqlglot.expressions.HeapProperty'>: <Location.POST_WITH: 'POST_WITH'>, <class 'sqlglot.expressions.InheritsProperty'>: <Location.POST_SCHEMA: 'POST_SCHEMA'>, <class 'sqlglot.expressions.IcebergProperty'>: <Location.POST_CREATE: 'POST_CREATE'>, <class 'sqlglot.expressions.IncludeProperty'>: <Location.POST_SCHEMA: 'POST_SCHEMA'>, <class 'sqlglot.expressions.InputModelProperty'>: <Location.POST_SCHEMA: 'POST_SCHEMA'>, <class 'sqlglot.expressions.IsolatedLoadingProperty'>: <Location.POST_NAME: 'POST_NAME'>, <class 'sqlglot.expressions.JournalProperty'>: <Location.POST_NAME: 'POST_NAME'>, <class 'sqlglot.expressions.LanguageProperty'>: <Location.POST_SCHEMA: 'POST_SCHEMA'>, <class 'sqlglot.expressions.LikeProperty'>: <Location.POST_SCHEMA: 'POST_SCHEMA'>, <class 'sqlglot.expressions.LocationProperty'>: <Location.POST_SCHEMA: 'POST_SCHEMA'>, <class 'sqlglot.expressions.LockProperty'>: <Location.POST_SCHEMA: 'POST_SCHEMA'>, <class 'sqlglot.expressions.LockingProperty'>: <Location.POST_ALIAS: 'POST_ALIAS'>, <class 'sqlglot.expressions.LogProperty'>: <Location.POST_NAME: 'POST_NAME'>, <class 'sqlglot.expressions.MaterializedProperty'>: <Location.POST_CREATE: 'POST_CREATE'>, <class 'sqlglot.expressions.MergeBlockRatioProperty'>: <Location.POST_NAME: 'POST_NAME'>, <class 'sqlglot.expressions.NoPrimaryIndexProperty'>: <Location.POST_EXPRESSION: 'POST_EXPRESSION'>, <class 'sqlglot.expressions.OnProperty'>: <Location.POST_SCHEMA: 'POST_SCHEMA'>, <class 'sqlglot.expressions.OnCommitProperty'>: <Location.POST_EXPRESSION: 'POST_EXPRESSION'>, <class 'sqlglot.expressions.Order'>: <Location.POST_SCHEMA: 'POST_SCHEMA'>, <class 'sqlglot.expressions.OutputModelProperty'>: <Location.POST_SCHEMA: 'POST_SCHEMA'>, <class 'sqlglot.expressions.PartitionedByProperty'>: <Location.POST_SCHEMA: 'POST_SCHEMA'>, <class 'sqlglot.expressions.PartitionedOfProperty'>: <Location.POST_SCHEMA: 'POST_SCHEMA'>, <class 'sqlglot.expressions.PrimaryKey'>: <Location.POST_SCHEMA: 'POST_SCHEMA'>, <class 'sqlglot.expressions.Property'>: <Location.POST_WITH: 'POST_WITH'>, <class 'sqlglot.expressions.RefreshTriggerProperty'>: <Location.POST_SCHEMA: 'POST_SCHEMA'>, <class 'sqlglot.expressions.RemoteWithConnectionModelProperty'>: <Location.POST_SCHEMA: 'POST_SCHEMA'>, <class 'sqlglot.expressions.ReturnsProperty'>: <Location.POST_SCHEMA: 'POST_SCHEMA'>, <class 'sqlglot.expressions.RollupProperty'>: <Location.UNSUPPORTED: 'UNSUPPORTED'>, <class 'sqlglot.expressions.RowFormatProperty'>: <Location.POST_SCHEMA: 'POST_SCHEMA'>, <class 'sqlglot.expressions.RowFormatDelimitedProperty'>: <Location.POST_SCHEMA: 'POST_SCHEMA'>, <class 'sqlglot.expressions.RowFormatSerdeProperty'>: <Location.POST_SCHEMA: 'POST_SCHEMA'>, <class 'sqlglot.expressions.SampleProperty'>: <Location.POST_SCHEMA: 'POST_SCHEMA'>, <class 'sqlglot.expressions.SchemaCommentProperty'>: <Location.POST_SCHEMA: 'POST_SCHEMA'>, <class 'sqlglot.expressions.SecureProperty'>: <Location.POST_CREATE: 'POST_CREATE'>, <class 'sqlglot.expressions.SecurityProperty'>: <Location.POST_SCHEMA: 'POST_SCHEMA'>, <class 'sqlglot.expressions.SerdeProperties'>: <Location.POST_SCHEMA: 'POST_SCHEMA'>, <class 'sqlglot.expressions.Set'>: <Location.POST_SCHEMA: 'POST_SCHEMA'>, <class 'sqlglot.expressions.SettingsProperty'>: <Location.POST_SCHEMA: 'POST_SCHEMA'>, <class 'sqlglot.expressions.SetProperty'>: <Location.POST_CREATE: 'POST_CREATE'>, <class 'sqlglot.expressions.SetConfigProperty'>: <Location.POST_SCHEMA: 'POST_SCHEMA'>, <class 'sqlglot.expressions.SharingProperty'>: <Location.POST_EXPRESSION: 'POST_EXPRESSION'>, <class 'sqlglot.expressions.SequenceProperties'>: <Location.POST_EXPRESSION: 'POST_EXPRESSION'>, <class 'sqlglot.expressions.SortKeyProperty'>: <Location.POST_SCHEMA: 'POST_SCHEMA'>, <class 'sqlglot.expressions.SqlReadWriteProperty'>: <Location.POST_SCHEMA: 'POST_SCHEMA'>, <class 'sqlglot.expressions.SqlSecurityProperty'>: <Location.POST_CREATE: 'POST_CREATE'>, <class 'sqlglot.expressions.StabilityProperty'>: <Location.POST_SCHEMA: 'POST_SCHEMA'>, <class 'sqlglot.expressions.StorageHandlerProperty'>: <Location.POST_SCHEMA: 'POST_SCHEMA'>, <class 'sqlglot.expressions.StreamingTableProperty'>: <Location.POST_CREATE: 'POST_CREATE'>, <class 'sqlglot.expressions.StrictProperty'>: <Location.POST_SCHEMA: 'POST_SCHEMA'>, <class 'sqlglot.expressions.Tags'>: <Location.POST_WITH: 'POST_WITH'>, <class 'sqlglot.expressions.TemporaryProperty'>: <Location.POST_CREATE: 'POST_CREATE'>, <class 'sqlglot.expressions.ToTableProperty'>: <Location.POST_SCHEMA: 'POST_SCHEMA'>, <class 'sqlglot.expressions.TransientProperty'>: <Location.UNSUPPORTED: 'UNSUPPORTED'>, <class 'sqlglot.expressions.TransformModelProperty'>: <Location.POST_SCHEMA: 'POST_SCHEMA'>, <class 'sqlglot.expressions.MergeTreeTTL'>: <Location.POST_SCHEMA: 'POST_SCHEMA'>, <class 'sqlglot.expressions.UnloggedProperty'>: <Location.POST_CREATE: 'POST_CREATE'>, <class 'sqlglot.expressions.UsingTemplateProperty'>: <Location.POST_SCHEMA: 'POST_SCHEMA'>, <class 'sqlglot.expressions.ViewAttributeProperty'>: <Location.POST_SCHEMA: 'POST_SCHEMA'>, <class 'sqlglot.expressions.VolatileProperty'>: <Location.UNSUPPORTED: 'UNSUPPORTED'>, <class 'sqlglot.expressions.WithDataProperty'>: <Location.POST_EXPRESSION: 'POST_EXPRESSION'>, <class 'sqlglot.expressions.WithJournalTableProperty'>: <Location.POST_NAME: 'POST_NAME'>, <class 'sqlglot.expressions.WithProcedureOptions'>: <Location.POST_SCHEMA: 'POST_SCHEMA'>, <class 'sqlglot.expressions.WithSchemaBindingProperty'>: <Location.POST_SCHEMA: 'POST_SCHEMA'>, <class 'sqlglot.expressions.WithSystemVersioningProperty'>: <Location.POST_SCHEMA: 'POST_SCHEMA'>, <class 'sqlglot.expressions.ForceProperty'>: <Location.POST_CREATE: 'POST_CREATE'>}
def schemacommentproperty_sql(self, expression: sqlglot.expressions.SchemaCommentProperty) -> str:
844        def schemacommentproperty_sql(self, expression: exp.SchemaCommentProperty) -> str:
845            self.unsupported("Table comments are not supported in the CREATE statement")
846            return ""
def commentcolumnconstraint_sql(self, expression: sqlglot.expressions.CommentColumnConstraint) -> str:
848        def commentcolumnconstraint_sql(self, expression: exp.CommentColumnConstraint) -> str:
849            self.unsupported("Column comments are not supported in the CREATE statement")
850            return ""
def columndef_sql(self, expression: sqlglot.expressions.ColumnDef, sep: str = ' ') -> str:
852        def columndef_sql(self, expression: exp.ColumnDef, sep: str = " ") -> str:
853            # PostgreSQL places parameter modes BEFORE parameter name
854            param_constraint = expression.find(exp.InOutColumnConstraint)
855
856            if param_constraint:
857                mode_sql = self.sql(param_constraint)
858                param_constraint.pop()  # Remove to prevent double-rendering
859                base_sql = super().columndef_sql(expression, sep)
860                return f"{mode_sql} {base_sql}"
861
862            return super().columndef_sql(expression, sep)
def unnest_sql(self, expression: sqlglot.expressions.Unnest) -> str:
864        def unnest_sql(self, expression: exp.Unnest) -> str:
865            if len(expression.expressions) == 1:
866                arg = expression.expressions[0]
867                if isinstance(arg, exp.GenerateDateArray):
868                    generate_series: exp.Expression = exp.GenerateSeries(**arg.args)
869                    if isinstance(expression.parent, (exp.From, exp.Join)):
870                        generate_series = (
871                            exp.select("value::date")
872                            .from_(exp.Table(this=generate_series).as_("_t", table=["value"]))
873                            .subquery(expression.args.get("alias") or "_unnested_generate_series")
874                        )
875                    return self.sql(generate_series)
876
877                from sqlglot.optimizer.annotate_types import annotate_types
878
879                this = annotate_types(arg, dialect=self.dialect)
880                if this.is_type("array<json>"):
881                    while isinstance(this, exp.Cast):
882                        this = this.this
883
884                    arg_as_json = self.sql(exp.cast(this, exp.DataType.Type.JSON))
885                    alias = self.sql(expression, "alias")
886                    alias = f" AS {alias}" if alias else ""
887
888                    if expression.args.get("offset"):
889                        self.unsupported("Unsupported JSON_ARRAY_ELEMENTS with offset")
890
891                    return f"JSON_ARRAY_ELEMENTS({arg_as_json}){alias}"
892
893            return super().unnest_sql(expression)
def bracket_sql(self, expression: sqlglot.expressions.Bracket) -> str:
895        def bracket_sql(self, expression: exp.Bracket) -> str:
896            """Forms like ARRAY[1, 2, 3][3] aren't allowed; we need to wrap the ARRAY."""
897            if isinstance(expression.this, exp.Array):
898                expression.set("this", exp.paren(expression.this, copy=False))
899
900            return super().bracket_sql(expression)

Forms like ARRAY[1, 2, 3][3] aren't allowed; we need to wrap the ARRAY.

def matchagainst_sql(self, expression: sqlglot.expressions.MatchAgainst) -> str:
902        def matchagainst_sql(self, expression: exp.MatchAgainst) -> str:
903            this = self.sql(expression, "this")
904            expressions = [f"{self.sql(e)} @@ {this}" for e in expression.expressions]
905            sql = " OR ".join(expressions)
906            return f"({sql})" if len(expressions) > 1 else sql
def alterset_sql(self, expression: sqlglot.expressions.AlterSet) -> str:
908        def alterset_sql(self, expression: exp.AlterSet) -> str:
909            exprs = self.expressions(expression, flat=True)
910            exprs = f"({exprs})" if exprs else ""
911
912            access_method = self.sql(expression, "access_method")
913            access_method = f"ACCESS METHOD {access_method}" if access_method else ""
914            tablespace = self.sql(expression, "tablespace")
915            tablespace = f"TABLESPACE {tablespace}" if tablespace else ""
916            option = self.sql(expression, "option")
917
918            return f"SET {exprs}{access_method}{tablespace}{option}"
def datatype_sql(self, expression: sqlglot.expressions.DataType) -> str:
920        def datatype_sql(self, expression: exp.DataType) -> str:
921            if expression.is_type(exp.DataType.Type.ARRAY):
922                if expression.expressions:
923                    values = self.expressions(expression, key="values", flat=True)
924                    return f"{self.expressions(expression, flat=True)}[{values}]"
925                return "ARRAY"
926
927            if (
928                expression.is_type(exp.DataType.Type.DOUBLE, exp.DataType.Type.FLOAT)
929                and expression.expressions
930            ):
931                # Postgres doesn't support precision for REAL and DOUBLE PRECISION types
932                return f"FLOAT({self.expressions(expression, flat=True)})"
933
934            return super().datatype_sql(expression)
def cast_sql( self, expression: sqlglot.expressions.Cast, safe_prefix: Optional[str] = None) -> str:
936        def cast_sql(self, expression: exp.Cast, safe_prefix: t.Optional[str] = None) -> str:
937            this = expression.this
938
939            # Postgres casts DIV() to decimal for transpilation but when roundtripping it's superfluous
940            if isinstance(this, exp.IntDiv) and expression.to == exp.DataType.build("decimal"):
941                return self.sql(this)
942
943            return super().cast_sql(expression, safe_prefix=safe_prefix)
def array_sql(self, expression: sqlglot.expressions.Array) -> str:
945        def array_sql(self, expression: exp.Array) -> str:
946            exprs = expression.expressions
947            func_name = self.normalize_func("ARRAY")
948
949            if isinstance(seq_get(exprs, 0), exp.Select):
950                return f"{func_name}({self.sql(exprs[0])})"
951
952            return f"{func_name}{inline_array_sql(self, expression)}"
def computedcolumnconstraint_sql(self, expression: sqlglot.expressions.ComputedColumnConstraint) -> str:
954        def computedcolumnconstraint_sql(self, expression: exp.ComputedColumnConstraint) -> str:
955            return f"GENERATED ALWAYS AS ({self.sql(expression, 'this')}) STORED"
def isascii_sql(self, expression: sqlglot.expressions.IsAscii) -> str:
957        def isascii_sql(self, expression: exp.IsAscii) -> str:
958            return f"({self.sql(expression.this)} ~ '^[[:ascii:]]*$')"
def ignorenulls_sql(self, expression: sqlglot.expressions.IgnoreNulls) -> str:
960        def ignorenulls_sql(self, expression: exp.IgnoreNulls) -> str:
961            # https://www.postgresql.org/docs/current/functions-window.html
962            self.unsupported("PostgreSQL does not support IGNORE NULLS.")
963            return self.sql(expression.this)
def respectnulls_sql(self, expression: sqlglot.expressions.RespectNulls) -> str:
965        def respectnulls_sql(self, expression: exp.RespectNulls) -> str:
966            # https://www.postgresql.org/docs/current/functions-window.html
967            self.unsupported("PostgreSQL does not support RESPECT NULLS.")
968            return self.sql(expression.this)
@unsupported_args('this')
def currentschema_sql(self, expression: sqlglot.expressions.CurrentSchema) -> str:
970        @unsupported_args("this")
971        def currentschema_sql(self, expression: exp.CurrentSchema) -> str:
972            return "CURRENT_SCHEMA"
def interval_sql(self, expression: sqlglot.expressions.Interval) -> str:
974        def interval_sql(self, expression: exp.Interval) -> str:
975            unit = expression.text("unit").lower()
976
977            this = expression.this
978            if unit.startswith("quarter") and isinstance(this, exp.Literal):
979                this.replace(exp.Literal.string(int(this.to_py()) * 3))
980                expression.args["unit"].replace(exp.var("MONTH"))
981
982            return super().interval_sql(expression)
def placeholder_sql(self, expression: sqlglot.expressions.Placeholder) -> str:
984        def placeholder_sql(self, expression: exp.Placeholder) -> str:
985            if expression.args.get("jdbc"):
986                return "?"
987
988            this = f"({expression.name})" if expression.this else ""
989            return f"{self.NAMED_PLACEHOLDER_TOKEN}{this}s"
def arraycontains_sql(self, expression: sqlglot.expressions.ArrayContains) -> str:
 991        def arraycontains_sql(self, expression: exp.ArrayContains) -> str:
 992            # Convert DuckDB's LIST_CONTAINS(array, value) to PostgreSQL
 993            # DuckDB behavior:
 994            #   - LIST_CONTAINS([1,2,3], 2) -> true
 995            #   - LIST_CONTAINS([1,2,3], 4) -> false
 996            #   - LIST_CONTAINS([1,2,NULL], 4) -> false (not NULL)
 997            #   - LIST_CONTAINS([1,2,3], NULL) -> NULL
 998            #
 999            # PostgreSQL equivalent: CASE WHEN value IS NULL THEN NULL
1000            #                            ELSE COALESCE(value = ANY(array), FALSE) END
1001            value = expression.expression
1002            array = expression.this
1003
1004            coalesce_expr = exp.Coalesce(
1005                this=value.eq(exp.Any(this=exp.paren(expression=array, copy=False))),
1006                expressions=[exp.false()],
1007            )
1008
1009            case_expr = (
1010                exp.Case()
1011                .when(exp.Is(this=value, expression=exp.null()), exp.null(), copy=False)
1012                .else_(coalesce_expr, copy=False)
1013            )
1014
1015            return self.sql(case_expr)
SELECT_KINDS: Tuple[str, ...] = ()
TRY_SUPPORTED = False
SUPPORTS_UESCAPE = False
SUPPORTS_DECODE_CASE = False
AFTER_HAVING_MODIFIER_TRANSFORMS = {'windows': <function Generator.<lambda>>, 'qualify': <function Generator.<lambda>>}
Inherited Members
sqlglot.generator.Generator
Generator
NULL_ORDERING_SUPPORTED
IGNORE_NULLS_IN_FUNC
EXCEPT_INTERSECT_SUPPORT_ALL_CLAUSE
WRAP_DERIVED_VALUES
CREATE_FUNCTION_RETURN_AS
MATCHED_BY_SOURCE
INTERVAL_ALLOWS_PLURAL_FORM
LIMIT_FETCH
LIMIT_ONLY_LITERALS
GROUPINGS_SEP
INDEX_ON
DIRECTED_JOINS
QUERY_HINT_SEP
IS_BOOL_ALLOWED
DUPLICATE_KEY_UPDATE_WITH_SET
LIMIT_IS_TOP
RETURNING_END
EXTRACT_ALLOWS_QUOTES
TZ_TO_WITH_TIME_ZONE
VALUES_AS_TABLE
ALTER_TABLE_INCLUDE_COLUMN_KEYWORD
UNNEST_WITH_ORDINALITY
AGGREGATE_FILTER_SUPPORTED
SEMI_ANTI_JOIN_WITH_SIDE
COMPUTED_COLUMN_WITH_TYPE
SUPPORTS_TABLE_COPY
TABLESAMPLE_REQUIRES_PARENS
TABLESAMPLE_KEYWORDS
TABLESAMPLE_WITH_METHOD
COLLATE_IS_FUNC
DATA_TYPE_SPECIFIERS_ALLOWED
ENSURE_BOOLS
CTE_RECURSIVE_KEYWORD_REQUIRED
SUPPORTS_SINGLE_ARG_CONCAT
LAST_DAY_SUPPORTS_DATE_PART
SUPPORTS_TABLE_ALIAS_COLUMNS
UNPIVOT_ALIASES_ARE_IDENTIFIERS
JSON_KEY_VALUE_PAIR_SEP
INSERT_OVERWRITE
SUPPORTS_CREATE_TABLE_LIKE
JSON_PATH_BRACKETED_KEY_SUPPORTED
JSON_PATH_SINGLE_QUOTE_ESCAPE
SUPPORTS_TO_NUMBER
SET_OP_MODIFIERS
COPY_PARAMS_ARE_WRAPPED
COPY_PARAMS_EQ_REQUIRED
UNICODE_SUBSTITUTE
STAR_EXCEPT
HEX_FUNC
WITH_PROPERTIES_PREFIX
QUOTE_JSON_PATH
PAD_FILL_PATTERN_IS_REQUIRED
SUPPORTS_EXPLODING_PROJECTIONS
SUPPORTS_CONVERT_TIMEZONE
SUPPORTS_UNIX_SECONDS
ALTER_SET_WRAPPED
NORMALIZE_EXTRACT_DATE_PARTS
PARSE_JSON_NAME
ARRAY_SIZE_NAME
ALTER_SET_TYPE
SUPPORTS_LIKE_QUANTIFIERS
MATCH_AGAINST_TABLE_PREFIX
SET_ASSIGNMENT_REQUIRES_VARIABLE_KEYWORD
UPDATE_STATEMENT_SUPPORTS_FROM
UNSUPPORTED_TYPES
TIME_PART_SINGULARS
TOKEN_MAPPING
STRUCT_DELIMITER
EXPRESSION_PRECEDES_PROPERTIES_CREATABLES
RESERVED_KEYWORDS
WITH_SEPARATED_COMMENTS
EXCLUDE_COMMENTS
UNWRAPPED_INTERVAL_VALUES
PARAMETERIZABLE_TEXT_TYPES
EXPRESSIONS_WITHOUT_NESTED_CTES
RESPECT_IGNORE_NULLS_UNSUPPORTED_EXPRESSIONS
SAFE_JSON_PATH_KEY_RE
SENTINEL_LINE_BREAK
pretty
identify
normalize
pad
unsupported_level
max_unsupported
leading_comma
max_text_width
comments
dialect
normalize_functions
unsupported_messages
generate
preprocess
unsupported
sep
seg
sanitize_comment
maybe_comment
wrap
no_identify
normalize_func
indent
sql
uncache_sql
cache_sql
characterset_sql
column_parts
column_sql
pseudocolumn_sql
columnposition_sql
columnconstraint_sql
autoincrementcolumnconstraint_sql
compresscolumnconstraint_sql
generatedasidentitycolumnconstraint_sql
generatedasrowcolumnconstraint_sql
periodforsystemtimeconstraint_sql
notnullcolumnconstraint_sql
primarykeycolumnconstraint_sql
uniquecolumnconstraint_sql
inoutcolumnconstraint_sql
createable_sql
create_sql
sequenceproperties_sql
clone_sql
describe_sql
heredoc_sql
prepend_ctes
with_sql
cte_sql
tablealias_sql
bitstring_sql
hexstring_sql
bytestring_sql
unicodestring_sql
rawstring_sql
datatypeparam_sql
directory_sql
delete_sql
drop_sql
set_operation
set_operations
fetch_sql
limitoptions_sql
filter_sql
hint_sql
indexparameters_sql
index_sql
identifier_sql
hex_sql
lowerhex_sql
inputoutputformat_sql
national_sql
partition_sql
properties_sql
root_properties
properties
with_properties
locate_properties
property_name
property_sql
likeproperty_sql
fallbackproperty_sql
journalproperty_sql
freespaceproperty_sql
checksumproperty_sql
mergeblockratioproperty_sql
datablocksizeproperty_sql
blockcompressionproperty_sql
isolatedloadingproperty_sql
partitionboundspec_sql
partitionedofproperty_sql
lockingproperty_sql
withdataproperty_sql
withsystemversioningproperty_sql
insert_sql
introducer_sql
kill_sql
pseudotype_sql
objectidentifier_sql
onconflict_sql
returning_sql
rowformatdelimitedproperty_sql
withtablehint_sql
indextablehint_sql
historicaldata_sql
table_parts
table_sql
tablefromrows_sql
tablesample_sql
pivot_sql
version_sql
tuple_sql
update_sql
values_sql
var_sql
into_sql
from_sql
groupingsets_sql
rollup_sql
rollupindex_sql
rollupproperty_sql
cube_sql
group_sql
having_sql
connect_sql
prior_sql
join_sql
lambda_sql
lateral_op
limit_sql
offset_sql
setitem_sql
set_sql
queryband_sql
pragma_sql
lock_sql
literal_sql
escape_str
loaddata_sql
null_sql
boolean_sql
booland_sql
boolor_sql
order_sql
withfill_sql
cluster_sql
distribute_sql
sort_sql
ordered_sql
matchrecognizemeasure_sql
matchrecognize_sql
query_modifiers
options_modifier
for_modifiers
queryoption_sql
offset_limit_modifiers
after_limit_modifiers
select_sql
schema_sql
schema_columns_sql
star_sql
parameter_sql
sessionparameter_sql
subquery_sql
qualify_sql
prewhere_sql
where_sql
window_sql
partition_by_sql
windowspec_sql
withingroup_sql
between_sql
bracket_offset_expressions
all_sql
any_sql
exists_sql
case_sql
constraint_sql
nextvaluefor_sql
extract_sql
trim_sql
convert_concat_args
concat_sql
concatws_sql
check_sql
foreignkey_sql
primarykey_sql
if_sql
jsonkeyvalue_sql
jsonpath_sql
json_path_part
formatjson_sql
formatphrase_sql
jsonobject_sql
jsonobjectagg_sql
jsonarray_sql
jsonarrayagg_sql
jsoncolumndef_sql
jsonschema_sql
jsontable_sql
openjsoncolumndef_sql
openjson_sql
in_sql
in_unnest_op
return_sql
reference_sql
anonymous_sql
paren_sql
neg_sql
not_sql
alias_sql
pivotalias_sql
aliases_sql
atindex_sql
attimezone_sql
fromtimezone_sql
add_sql
and_sql
or_sql
xor_sql
connector_sql
bitwiseand_sql
bitwiseleftshift_sql
bitwisenot_sql
bitwiseor_sql
bitwiserightshift_sql
bitwisexor_sql
strtotime_sql
currentdate_sql
collate_sql
command_sql
comment_sql
mergetreettlaction_sql
mergetreettl_sql
transaction_sql
commit_sql
rollback_sql
altercolumn_sql
alterindex_sql
alterdiststyle_sql
altersortkey_sql
alterrename_sql
renamecolumn_sql
alter_sql
altersession_sql
add_column_sql
droppartition_sql
addconstraint_sql
addpartition_sql
distinct_sql
havingmax_sql
intdiv_sql
dpipe_sql
div_sql
safedivide_sql
overlaps_sql
distance_sql
dot_sql
eq_sql
propertyeq_sql
escape_sql
glob_sql
gt_sql
gte_sql
is_sql
like_sql
ilike_sql
match_sql
similarto_sql
lt_sql
lte_sql
mod_sql
mul_sql
neq_sql
nullsafeeq_sql
nullsafeneq_sql
sub_sql
trycast_sql
jsoncast_sql
try_sql
log_sql
use_sql
binary
ceil_floor
function_fallback_sql
func
format_args
too_wide
format_time
expressions
op_expressions
naked_property
tag_sql
token_sql
userdefinedfunction_sql
joinhint_sql
kwarg_sql
when_sql
whens_sql
merge_sql
tochar_sql
tonumber_sql
dictproperty_sql
dictrange_sql
dictsubproperty_sql
duplicatekeyproperty_sql
uniquekeyproperty_sql
distributedbyproperty_sql
oncluster_sql
clusteredbyproperty_sql
anyvalue_sql
querytransform_sql
indexconstraintoption_sql
checkcolumnconstraint_sql
indexcolumnconstraint_sql
nvl2_sql
comprehension_sql
columnprefix_sql
opclass_sql
predict_sql
generateembedding_sql
mltranslate_sql
mlforecast_sql
featuresattime_sql
vectorsearch_sql
forin_sql
refresh_sql
toarray_sql
tsordstotime_sql
tsordstotimestamp_sql
tsordstodatetime_sql
tsordstodate_sql
unixdate_sql
lastday_sql
dateadd_sql
arrayany_sql
struct_sql
partitionrange_sql
truncatetable_sql
convert_sql
copyparameter_sql
credentials_sql
copy_sql
semicolon_sql
datadeletionproperty_sql
maskingpolicycolumnconstraint_sql
gapfill_sql
scope_resolution
scoperesolution_sql
parsejson_sql
rand_sql
changes_sql
pad_sql
summarize_sql
explodinggenerateseries_sql
converttimezone_sql
json_sql
jsonvalue_sql
conditionalinsert_sql
multitableinserts_sql
oncondition_sql
jsonextractquote_sql
jsonexists_sql
arrayagg_sql
slice_sql
apply_sql
grant_sql
revoke_sql
grantprivilege_sql
grantprincipal_sql
columns_sql
overlay_sql
todouble_sql
string_sql
median_sql
overflowtruncatebehavior_sql
unixseconds_sql
arraysize_sql
attach_sql
detach_sql
attachoption_sql
watermarkcolumnconstraint_sql
encodeproperty_sql
includeproperty_sql
xmlelement_sql
xmlkeyvalueoption_sql
partitionbyrangeproperty_sql
partitionbyrangepropertydynamic_sql
unpivotcolumns_sql
analyzesample_sql
analyzestatistics_sql
analyzehistogram_sql
analyzedelete_sql
analyzelistchainedrows_sql
analyzevalidate_sql
analyze_sql
xmltable_sql
xmlnamespace_sql
export_sql
declare_sql
declareitem_sql
recursivewithsearch_sql
parameterizedagg_sql
anonymousaggfunc_sql
combinedaggfunc_sql
combinedparameterizedagg_sql
show_sql
install_sql
get_put_sql
translatecharacters_sql
decodecase_sql
semanticview_sql
getextract_sql
datefromunixdate_sql
space_sql
buildproperty_sql
refreshtriggerproperty_sql
modelattribute_sql
directorystage_sql
uuid_sql
initcap_sql
localtime_sql
localtimestamp_sql
weekstart_sql
chr_sql