sqlglot.dialects.bigquery API documentation

Edit on GitHub

# sqlglot.dialects.bigquery

View Source

      1from __future__ import annotations
      2
      3import logging
      4import re
      5import typing as t
      6
      7from sqlglot import exp, generator, parser, tokens, transforms
      8from sqlglot.dialects.dialect import (
      9    Dialect,
     10    NormalizationStrategy,
     11    arg_max_or_min_no_count,
     12    binary_from_function,
     13    date_add_interval_sql,
     14    datestrtodate_sql,
     15    build_formatted_time,
     16    filter_array_using_unnest,
     17    if_sql,
     18    inline_array_unless_query,
     19    max_or_greatest,
     20    min_or_least,
     21    no_ilike_sql,
     22    build_date_delta_with_interval,
     23    regexp_replace_sql,
     24    rename_func,
     25    sha256_sql,
     26    timestrtotime_sql,
     27    ts_or_ds_add_cast,
     28    unit_to_var,
     29)
     30from sqlglot.helper import seq_get, split_num_words
     31from sqlglot.tokens import TokenType
     32
     33if t.TYPE_CHECKING:
     34    from sqlglot._typing import E, Lit
     35
     36logger = logging.getLogger("sqlglot")
     37
     38
     39def _derived_table_values_to_unnest(self: BigQuery.Generator, expression: exp.Values) -> str:
     40    if not expression.find_ancestor(exp.From, exp.Join):
     41        return self.values_sql(expression)
     42
     43    structs = []
     44    alias = expression.args.get("alias")
     45    for tup in expression.find_all(exp.Tuple):
     46        field_aliases = (
     47            alias.columns
     48            if alias and alias.columns
     49            else (f"_c{i}" for i in range(len(tup.expressions)))
     50        )
     51        expressions = [
     52            exp.PropertyEQ(this=exp.to_identifier(name), expression=fld)
     53            for name, fld in zip(field_aliases, tup.expressions)
     54        ]
     55        structs.append(exp.Struct(expressions=expressions))
     56
     57    # Due to `UNNEST_COLUMN_ONLY`, it is expected that the table alias be contained in the columns expression
     58    alias_name_only = exp.TableAlias(columns=[alias.this]) if alias else None
     59    return self.unnest_sql(
     60        exp.Unnest(expressions=[exp.array(*structs, copy=False)], alias=alias_name_only)
     61    )
     62
     63
     64def _returnsproperty_sql(self: BigQuery.Generator, expression: exp.ReturnsProperty) -> str:
     65    this = expression.this
     66    if isinstance(this, exp.Schema):
     67        this = f"{self.sql(this, 'this')} <{self.expressions(this)}>"
     68    else:
     69        this = self.sql(this)
     70    return f"RETURNS {this}"
     71
     72
     73def _create_sql(self: BigQuery.Generator, expression: exp.Create) -> str:
     74    returns = expression.find(exp.ReturnsProperty)
     75    if expression.kind == "FUNCTION" and returns and returns.args.get("is_table"):
     76        expression.set("kind", "TABLE FUNCTION")
     77
     78        if isinstance(expression.expression, (exp.Subquery, exp.Literal)):
     79            expression.set("expression", expression.expression.this)
     80
     81    return self.create_sql(expression)
     82
     83
     84# https://issuetracker.google.com/issues/162294746
     85# workaround for bigquery bug when grouping by an expression and then ordering
     86# WITH x AS (SELECT 1 y)
     87# SELECT y + 1 z
     88# FROM x
     89# GROUP BY x + 1
     90# ORDER by z
     91def _alias_ordered_group(expression: exp.Expression) -> exp.Expression:
     92    if isinstance(expression, exp.Select):
     93        group = expression.args.get("group")
     94        order = expression.args.get("order")
     95
     96        if group and order:
     97            aliases = {
     98                select.this: select.args["alias"]
     99                for select in expression.selects
    100                if isinstance(select, exp.Alias)
    101            }
    102
    103            for grouped in group.expressions:
    104                if grouped.is_int:
    105                    continue
    106                alias = aliases.get(grouped)
    107                if alias:
    108                    grouped.replace(exp.column(alias))
    109
    110    return expression
    111
    112
    113def _pushdown_cte_column_names(expression: exp.Expression) -> exp.Expression:
    114    """BigQuery doesn't allow column names when defining a CTE, so we try to push them down."""
    115    if isinstance(expression, exp.CTE) and expression.alias_column_names:
    116        cte_query = expression.this
    117
    118        if cte_query.is_star:
    119            logger.warning(
    120                "Can't push down CTE column names for star queries. Run the query through"
    121                " the optimizer or use 'qualify' to expand the star projections first."
    122            )
    123            return expression
    124
    125        column_names = expression.alias_column_names
    126        expression.args["alias"].set("columns", None)
    127
    128        for name, select in zip(column_names, cte_query.selects):
    129            to_replace = select
    130
    131            if isinstance(select, exp.Alias):
    132                select = select.this
    133
    134            # Inner aliases are shadowed by the CTE column names
    135            to_replace.replace(exp.alias_(select, name))
    136
    137    return expression
    138
    139
    140def _build_parse_timestamp(args: t.List) -> exp.StrToTime:
    141    this = build_formatted_time(exp.StrToTime, "bigquery")([seq_get(args, 1), seq_get(args, 0)])
    142    this.set("zone", seq_get(args, 2))
    143    return this
    144
    145
    146def _build_timestamp(args: t.List) -> exp.Timestamp:
    147    timestamp = exp.Timestamp.from_arg_list(args)
    148    timestamp.set("with_tz", True)
    149    return timestamp
    150
    151
    152def _build_date(args: t.List) -> exp.Date | exp.DateFromParts:
    153    expr_type = exp.DateFromParts if len(args) == 3 else exp.Date
    154    return expr_type.from_arg_list(args)
    155
    156
    157def _build_to_hex(args: t.List) -> exp.Hex | exp.MD5:
    158    # TO_HEX(MD5(..)) is common in BigQuery, so it's parsed into MD5 to simplify its transpilation
    159    arg = seq_get(args, 0)
    160    return exp.MD5(this=arg.this) if isinstance(arg, exp.MD5Digest) else exp.LowerHex(this=arg)
    161
    162
    163def _array_contains_sql(self: BigQuery.Generator, expression: exp.ArrayContains) -> str:
    164    return self.sql(
    165        exp.Exists(
    166            this=exp.select("1")
    167            .from_(exp.Unnest(expressions=[expression.left]).as_("_unnest", table=["_col"]))
    168            .where(exp.column("_col").eq(expression.right))
    169        )
    170    )
    171
    172
    173def _ts_or_ds_add_sql(self: BigQuery.Generator, expression: exp.TsOrDsAdd) -> str:
    174    return date_add_interval_sql("DATE", "ADD")(self, ts_or_ds_add_cast(expression))
    175
    176
    177def _ts_or_ds_diff_sql(self: BigQuery.Generator, expression: exp.TsOrDsDiff) -> str:
    178    expression.this.replace(exp.cast(expression.this, exp.DataType.Type.TIMESTAMP))
    179    expression.expression.replace(exp.cast(expression.expression, exp.DataType.Type.TIMESTAMP))
    180    unit = unit_to_var(expression)
    181    return self.func("DATE_DIFF", expression.this, expression.expression, unit)
    182
    183
    184def _unix_to_time_sql(self: BigQuery.Generator, expression: exp.UnixToTime) -> str:
    185    scale = expression.args.get("scale")
    186    timestamp = expression.this
    187
    188    if scale in (None, exp.UnixToTime.SECONDS):
    189        return self.func("TIMESTAMP_SECONDS", timestamp)
    190    if scale == exp.UnixToTime.MILLIS:
    191        return self.func("TIMESTAMP_MILLIS", timestamp)
    192    if scale == exp.UnixToTime.MICROS:
    193        return self.func("TIMESTAMP_MICROS", timestamp)
    194
    195    unix_seconds = exp.cast(
    196        exp.Div(this=timestamp, expression=exp.func("POW", 10, scale)), exp.DataType.Type.BIGINT
    197    )
    198    return self.func("TIMESTAMP_SECONDS", unix_seconds)
    199
    200
    201def _build_time(args: t.List) -> exp.Func:
    202    if len(args) == 1:
    203        return exp.TsOrDsToTime(this=args[0])
    204    if len(args) == 2:
    205        return exp.Time.from_arg_list(args)
    206    return exp.TimeFromParts.from_arg_list(args)
    207
    208
    209def _build_datetime(args: t.List) -> exp.Func:
    210    if len(args) == 1:
    211        return exp.TsOrDsToTimestamp.from_arg_list(args)
    212    if len(args) == 2:
    213        return exp.Datetime.from_arg_list(args)
    214    return exp.TimestampFromParts.from_arg_list(args)
    215
    216
    217class BigQuery(Dialect):
    218    WEEK_OFFSET = -1
    219    UNNEST_COLUMN_ONLY = True
    220    SUPPORTS_USER_DEFINED_TYPES = False
    221    SUPPORTS_SEMI_ANTI_JOIN = False
    222    LOG_BASE_FIRST = False
    223    HEX_LOWERCASE = True
    224
    225    # https://cloud.google.com/bigquery/docs/reference/standard-sql/lexical#case_sensitivity
    226    NORMALIZATION_STRATEGY = NormalizationStrategy.CASE_INSENSITIVE
    227
    228    # bigquery udfs are case sensitive
    229    NORMALIZE_FUNCTIONS = False
    230
    231    # https://cloud.google.com/bigquery/docs/reference/standard-sql/format-elements#format_elements_date_time
    232    TIME_MAPPING = {
    233        "%D": "%m/%d/%y",
    234        "%E6S": "%S.%f",
    235    }
    236
    237    FORMAT_MAPPING = {
    238        "DD": "%d",
    239        "MM": "%m",
    240        "MON": "%b",
    241        "MONTH": "%B",
    242        "YYYY": "%Y",
    243        "YY": "%y",
    244        "HH": "%I",
    245        "HH12": "%I",
    246        "HH24": "%H",
    247        "MI": "%M",
    248        "SS": "%S",
    249        "SSSSS": "%f",
    250        "TZH": "%z",
    251    }
    252
    253    # The _PARTITIONTIME and _PARTITIONDATE pseudo-columns are not returned by a SELECT * statement
    254    # https://cloud.google.com/bigquery/docs/querying-partitioned-tables#query_an_ingestion-time_partitioned_table
    255    PSEUDOCOLUMNS = {"_PARTITIONTIME", "_PARTITIONDATE"}
    256
    257    def normalize_identifier(self, expression: E) -> E:
    258        if (
    259            isinstance(expression, exp.Identifier)
    260            and self.normalization_strategy is not NormalizationStrategy.CASE_SENSITIVE
    261        ):
    262            parent = expression.parent
    263            while isinstance(parent, exp.Dot):
    264                parent = parent.parent
    265
    266            # In BigQuery, CTEs are case-insensitive, but UDF and table names are case-sensitive
    267            # by default. The following check uses a heuristic to detect tables based on whether
    268            # they are qualified. This should generally be correct, because tables in BigQuery
    269            # must be qualified with at least a dataset, unless @@dataset_id is set.
    270            case_sensitive = (
    271                isinstance(parent, exp.UserDefinedFunction)
    272                or (
    273                    isinstance(parent, exp.Table)
    274                    and parent.db
    275                    and (parent.meta.get("quoted_table") or not parent.meta.get("maybe_column"))
    276                )
    277                or expression.meta.get("is_table")
    278            )
    279            if not case_sensitive:
    280                expression.set("this", expression.this.lower())
    281
    282        return expression
    283
    284    class Tokenizer(tokens.Tokenizer):
    285        QUOTES = ["'", '"', '"""', "'''"]
    286        COMMENTS = ["--", "#", ("/*", "*/")]
    287        IDENTIFIERS = ["`"]
    288        STRING_ESCAPES = ["\\"]
    289
    290        HEX_STRINGS = [("0x", ""), ("0X", "")]
    291
    292        BYTE_STRINGS = [
    293            (prefix + q, q) for q in t.cast(t.List[str], QUOTES) for prefix in ("b", "B")
    294        ]
    295
    296        RAW_STRINGS = [
    297            (prefix + q, q) for q in t.cast(t.List[str], QUOTES) for prefix in ("r", "R")
    298        ]
    299
    300        KEYWORDS = {
    301            **tokens.Tokenizer.KEYWORDS,
    302            "ANY TYPE": TokenType.VARIANT,
    303            "BEGIN": TokenType.COMMAND,
    304            "BEGIN TRANSACTION": TokenType.BEGIN,
    305            "BYTES": TokenType.BINARY,
    306            "CURRENT_DATETIME": TokenType.CURRENT_DATETIME,
    307            "DATETIME": TokenType.TIMESTAMP,
    308            "DECLARE": TokenType.COMMAND,
    309            "ELSEIF": TokenType.COMMAND,
    310            "EXCEPTION": TokenType.COMMAND,
    311            "FLOAT64": TokenType.DOUBLE,
    312            "FOR SYSTEM_TIME": TokenType.TIMESTAMP_SNAPSHOT,
    313            "MODEL": TokenType.MODEL,
    314            "NOT DETERMINISTIC": TokenType.VOLATILE,
    315            "RECORD": TokenType.STRUCT,
    316            "TIMESTAMP": TokenType.TIMESTAMPTZ,
    317        }
    318        KEYWORDS.pop("DIV")
    319        KEYWORDS.pop("VALUES")
    320
    321    class Parser(parser.Parser):
    322        PREFIXED_PIVOT_COLUMNS = True
    323        LOG_DEFAULTS_TO_LN = True
    324        SUPPORTS_IMPLICIT_UNNEST = True
    325
    326        FUNCTIONS = {
    327            **parser.Parser.FUNCTIONS,
    328            "DATE": _build_date,
    329            "DATE_ADD": build_date_delta_with_interval(exp.DateAdd),
    330            "DATE_SUB": build_date_delta_with_interval(exp.DateSub),
    331            "DATE_TRUNC": lambda args: exp.DateTrunc(
    332                unit=exp.Literal.string(str(seq_get(args, 1))),
    333                this=seq_get(args, 0),
    334            ),
    335            "DATETIME": _build_datetime,
    336            "DATETIME_ADD": build_date_delta_with_interval(exp.DatetimeAdd),
    337            "DATETIME_SUB": build_date_delta_with_interval(exp.DatetimeSub),
    338            "DIV": binary_from_function(exp.IntDiv),
    339            "FORMAT_DATE": lambda args: exp.TimeToStr(
    340                this=exp.TsOrDsToDate(this=seq_get(args, 1)), format=seq_get(args, 0)
    341            ),
    342            "GENERATE_ARRAY": exp.GenerateSeries.from_arg_list,
    343            "JSON_EXTRACT_SCALAR": lambda args: exp.JSONExtractScalar(
    344                this=seq_get(args, 0), expression=seq_get(args, 1) or exp.Literal.string("$")
    345            ),
    346            "MD5": exp.MD5Digest.from_arg_list,
    347            "TO_HEX": _build_to_hex,
    348            "PARSE_DATE": lambda args: build_formatted_time(exp.StrToDate, "bigquery")(
    349                [seq_get(args, 1), seq_get(args, 0)]
    350            ),
    351            "PARSE_TIMESTAMP": _build_parse_timestamp,
    352            "REGEXP_CONTAINS": exp.RegexpLike.from_arg_list,
    353            "REGEXP_EXTRACT": lambda args: exp.RegexpExtract(
    354                this=seq_get(args, 0),
    355                expression=seq_get(args, 1),
    356                position=seq_get(args, 2),
    357                occurrence=seq_get(args, 3),
    358                group=exp.Literal.number(1) if re.compile(args[1].name).groups == 1 else None,
    359            ),
    360            "SHA256": lambda args: exp.SHA2(this=seq_get(args, 0), length=exp.Literal.number(256)),
    361            "SHA512": lambda args: exp.SHA2(this=seq_get(args, 0), length=exp.Literal.number(512)),
    362            "SPLIT": lambda args: exp.Split(
    363                # https://cloud.google.com/bigquery/docs/reference/standard-sql/string_functions#split
    364                this=seq_get(args, 0),
    365                expression=seq_get(args, 1) or exp.Literal.string(","),
    366            ),
    367            "TIME": _build_time,
    368            "TIME_ADD": build_date_delta_with_interval(exp.TimeAdd),
    369            "TIME_SUB": build_date_delta_with_interval(exp.TimeSub),
    370            "TIMESTAMP": _build_timestamp,
    371            "TIMESTAMP_ADD": build_date_delta_with_interval(exp.TimestampAdd),
    372            "TIMESTAMP_SUB": build_date_delta_with_interval(exp.TimestampSub),
    373            "TIMESTAMP_MICROS": lambda args: exp.UnixToTime(
    374                this=seq_get(args, 0), scale=exp.UnixToTime.MICROS
    375            ),
    376            "TIMESTAMP_MILLIS": lambda args: exp.UnixToTime(
    377                this=seq_get(args, 0), scale=exp.UnixToTime.MILLIS
    378            ),
    379            "TIMESTAMP_SECONDS": lambda args: exp.UnixToTime(this=seq_get(args, 0)),
    380            "TO_JSON_STRING": exp.JSONFormat.from_arg_list,
    381        }
    382
    383        FUNCTION_PARSERS = {
    384            **parser.Parser.FUNCTION_PARSERS,
    385            "ARRAY": lambda self: self.expression(exp.Array, expressions=[self._parse_statement()]),
    386        }
    387        FUNCTION_PARSERS.pop("TRIM")
    388
    389        NO_PAREN_FUNCTIONS = {
    390            **parser.Parser.NO_PAREN_FUNCTIONS,
    391            TokenType.CURRENT_DATETIME: exp.CurrentDatetime,
    392        }
    393
    394        NESTED_TYPE_TOKENS = {
    395            *parser.Parser.NESTED_TYPE_TOKENS,
    396            TokenType.TABLE,
    397        }
    398
    399        PROPERTY_PARSERS = {
    400            **parser.Parser.PROPERTY_PARSERS,
    401            "NOT DETERMINISTIC": lambda self: self.expression(
    402                exp.StabilityProperty, this=exp.Literal.string("VOLATILE")
    403            ),
    404            "OPTIONS": lambda self: self._parse_with_property(),
    405        }
    406
    407        CONSTRAINT_PARSERS = {
    408            **parser.Parser.CONSTRAINT_PARSERS,
    409            "OPTIONS": lambda self: exp.Properties(expressions=self._parse_with_property()),
    410        }
    411
    412        RANGE_PARSERS = parser.Parser.RANGE_PARSERS.copy()
    413        RANGE_PARSERS.pop(TokenType.OVERLAPS)
    414
    415        NULL_TOKENS = {TokenType.NULL, TokenType.UNKNOWN}
    416
    417        STATEMENT_PARSERS = {
    418            **parser.Parser.STATEMENT_PARSERS,
    419            TokenType.ELSE: lambda self: self._parse_as_command(self._prev),
    420            TokenType.END: lambda self: self._parse_as_command(self._prev),
    421            TokenType.FOR: lambda self: self._parse_for_in(),
    422        }
    423
    424        BRACKET_OFFSETS = {
    425            "OFFSET": (0, False),
    426            "ORDINAL": (1, False),
    427            "SAFE_OFFSET": (0, True),
    428            "SAFE_ORDINAL": (1, True),
    429        }
    430
    431        def _parse_for_in(self) -> exp.ForIn:
    432            this = self._parse_range()
    433            self._match_text_seq("DO")
    434            return self.expression(exp.ForIn, this=this, expression=self._parse_statement())
    435
    436        def _parse_table_part(self, schema: bool = False) -> t.Optional[exp.Expression]:
    437            this = super()._parse_table_part(schema=schema) or self._parse_number()
    438
    439            # https://cloud.google.com/bigquery/docs/reference/standard-sql/lexical#table_names
    440            if isinstance(this, exp.Identifier):
    441                table_name = this.name
    442                while self._match(TokenType.DASH, advance=False) and self._next:
    443                    text = ""
    444                    while self._curr and self._curr.token_type != TokenType.DOT:
    445                        self._advance()
    446                        text += self._prev.text
    447                    table_name += text
    448
    449                this = exp.Identifier(this=table_name, quoted=this.args.get("quoted"))
    450            elif isinstance(this, exp.Literal):
    451                table_name = this.name
    452
    453                if self._is_connected() and self._parse_var(any_token=True):
    454                    table_name += self._prev.text
    455
    456                this = exp.Identifier(this=table_name, quoted=True)
    457
    458            return this
    459
    460        def _parse_table_parts(
    461            self, schema: bool = False, is_db_reference: bool = False, wildcard: bool = False
    462        ) -> exp.Table:
    463            table = super()._parse_table_parts(
    464                schema=schema, is_db_reference=is_db_reference, wildcard=True
    465            )
    466
    467            # proj-1.db.tbl -- `1.` is tokenized as a float so we need to unravel it here
    468            if not table.catalog:
    469                if table.db:
    470                    parts = table.db.split(".")
    471                    if len(parts) == 2 and not table.args["db"].quoted:
    472                        table.set("catalog", exp.Identifier(this=parts[0]))
    473                        table.set("db", exp.Identifier(this=parts[1]))
    474                else:
    475                    parts = table.name.split(".")
    476                    if len(parts) == 2 and not table.this.quoted:
    477                        table.set("db", exp.Identifier(this=parts[0]))
    478                        table.set("this", exp.Identifier(this=parts[1]))
    479
    480            if any("." in p.name for p in table.parts):
    481                catalog, db, this, *rest = (
    482                    exp.to_identifier(p, quoted=True)
    483                    for p in split_num_words(".".join(p.name for p in table.parts), ".", 3)
    484                )
    485
    486                if rest and this:
    487                    this = exp.Dot.build([this, *rest])  # type: ignore
    488
    489                table = exp.Table(
    490                    this=this, db=db, catalog=catalog, pivots=table.args.get("pivots")
    491                )
    492                table.meta["quoted_table"] = True
    493
    494            return table
    495
    496        def _parse_column(self) -> t.Optional[exp.Expression]:
    497            column = super()._parse_column()
    498            if isinstance(column, exp.Column):
    499                parts = column.parts
    500                if any("." in p.name for p in parts):
    501                    catalog, db, table, this, *rest = (
    502                        exp.to_identifier(p, quoted=True)
    503                        for p in split_num_words(".".join(p.name for p in parts), ".", 4)
    504                    )
    505
    506                    if rest and this:
    507                        this = exp.Dot.build([this, *rest])  # type: ignore
    508
    509                    column = exp.Column(this=this, table=table, db=db, catalog=catalog)
    510                    column.meta["quoted_column"] = True
    511
    512            return column
    513
    514        @t.overload
    515        def _parse_json_object(self, agg: Lit[False]) -> exp.JSONObject: ...
    516
    517        @t.overload
    518        def _parse_json_object(self, agg: Lit[True]) -> exp.JSONObjectAgg: ...
    519
    520        def _parse_json_object(self, agg=False):
    521            json_object = super()._parse_json_object()
    522            array_kv_pair = seq_get(json_object.expressions, 0)
    523
    524            # Converts BQ's "signature 2" of JSON_OBJECT into SQLGlot's canonical representation
    525            # https://cloud.google.com/bigquery/docs/reference/standard-sql/json_functions#json_object_signature2
    526            if (
    527                array_kv_pair
    528                and isinstance(array_kv_pair.this, exp.Array)
    529                and isinstance(array_kv_pair.expression, exp.Array)
    530            ):
    531                keys = array_kv_pair.this.expressions
    532                values = array_kv_pair.expression.expressions
    533
    534                json_object.set(
    535                    "expressions",
    536                    [exp.JSONKeyValue(this=k, expression=v) for k, v in zip(keys, values)],
    537                )
    538
    539            return json_object
    540
    541        def _parse_bracket(
    542            self, this: t.Optional[exp.Expression] = None
    543        ) -> t.Optional[exp.Expression]:
    544            bracket = super()._parse_bracket(this)
    545
    546            if this is bracket:
    547                return bracket
    548
    549            if isinstance(bracket, exp.Bracket):
    550                for expression in bracket.expressions:
    551                    name = expression.name.upper()
    552
    553                    if name not in self.BRACKET_OFFSETS:
    554                        break
    555
    556                    offset, safe = self.BRACKET_OFFSETS[name]
    557                    bracket.set("offset", offset)
    558                    bracket.set("safe", safe)
    559                    expression.replace(expression.expressions[0])
    560
    561            return bracket
    562
    563    class Generator(generator.Generator):
    564        EXPLICIT_SET_OP = True
    565        INTERVAL_ALLOWS_PLURAL_FORM = False
    566        JOIN_HINTS = False
    567        QUERY_HINTS = False
    568        TABLE_HINTS = False
    569        LIMIT_FETCH = "LIMIT"
    570        RENAME_TABLE_WITH_DB = False
    571        NVL2_SUPPORTED = False
    572        UNNEST_WITH_ORDINALITY = False
    573        COLLATE_IS_FUNC = True
    574        LIMIT_ONLY_LITERALS = True
    575        SUPPORTS_TABLE_ALIAS_COLUMNS = False
    576        UNPIVOT_ALIASES_ARE_IDENTIFIERS = False
    577        JSON_KEY_VALUE_PAIR_SEP = ","
    578        NULL_ORDERING_SUPPORTED = False
    579        IGNORE_NULLS_IN_FUNC = True
    580        JSON_PATH_SINGLE_QUOTE_ESCAPE = True
    581        CAN_IMPLEMENT_ARRAY_ANY = True
    582        SUPPORTS_TO_NUMBER = False
    583        NAMED_PLACEHOLDER_TOKEN = "@"
    584        HEX_FUNC = "TO_HEX"
    585        WITH_PROPERTIES_PREFIX = "OPTIONS"
    586
    587        TRANSFORMS = {
    588            **generator.Generator.TRANSFORMS,
    589            exp.ApproxDistinct: rename_func("APPROX_COUNT_DISTINCT"),
    590            exp.ArgMax: arg_max_or_min_no_count("MAX_BY"),
    591            exp.ArgMin: arg_max_or_min_no_count("MIN_BY"),
    592            exp.Array: inline_array_unless_query,
    593            exp.ArrayContains: _array_contains_sql,
    594            exp.ArrayFilter: filter_array_using_unnest,
    595            exp.ArraySize: rename_func("ARRAY_LENGTH"),
    596            exp.Cast: transforms.preprocess([transforms.remove_precision_parameterized_types]),
    597            exp.CollateProperty: lambda self, e: (
    598                f"DEFAULT COLLATE {self.sql(e, 'this')}"
    599                if e.args.get("default")
    600                else f"COLLATE {self.sql(e, 'this')}"
    601            ),
    602            exp.Commit: lambda *_: "COMMIT TRANSACTION",
    603            exp.CountIf: rename_func("COUNTIF"),
    604            exp.Create: _create_sql,
    605            exp.CTE: transforms.preprocess([_pushdown_cte_column_names]),
    606            exp.DateAdd: date_add_interval_sql("DATE", "ADD"),
    607            exp.DateDiff: lambda self, e: self.func(
    608                "DATE_DIFF", e.this, e.expression, unit_to_var(e)
    609            ),
    610            exp.DateFromParts: rename_func("DATE"),
    611            exp.DateStrToDate: datestrtodate_sql,
    612            exp.DateSub: date_add_interval_sql("DATE", "SUB"),
    613            exp.DatetimeAdd: date_add_interval_sql("DATETIME", "ADD"),
    614            exp.DatetimeSub: date_add_interval_sql("DATETIME", "SUB"),
    615            exp.DateTrunc: lambda self, e: self.func("DATE_TRUNC", e.this, e.text("unit")),
    616            exp.FromTimeZone: lambda self, e: self.func(
    617                "DATETIME", self.func("TIMESTAMP", e.this, e.args.get("zone")), "'UTC'"
    618            ),
    619            exp.GenerateSeries: rename_func("GENERATE_ARRAY"),
    620            exp.GroupConcat: rename_func("STRING_AGG"),
    621            exp.Hex: lambda self, e: self.func("UPPER", self.func("TO_HEX", self.sql(e, "this"))),
    622            exp.If: if_sql(false_value="NULL"),
    623            exp.ILike: no_ilike_sql,
    624            exp.IntDiv: rename_func("DIV"),
    625            exp.JSONFormat: rename_func("TO_JSON_STRING"),
    626            exp.Max: max_or_greatest,
    627            exp.MD5: lambda self, e: self.func("TO_HEX", self.func("MD5", e.this)),
    628            exp.MD5Digest: rename_func("MD5"),
    629            exp.Min: min_or_least,
    630            exp.PartitionedByProperty: lambda self, e: f"PARTITION BY {self.sql(e, 'this')}",
    631            exp.RegexpExtract: lambda self, e: self.func(
    632                "REGEXP_EXTRACT",
    633                e.this,
    634                e.expression,
    635                e.args.get("position"),
    636                e.args.get("occurrence"),
    637            ),
    638            exp.RegexpReplace: regexp_replace_sql,
    639            exp.RegexpLike: rename_func("REGEXP_CONTAINS"),
    640            exp.ReturnsProperty: _returnsproperty_sql,
    641            exp.Rollback: lambda *_: "ROLLBACK TRANSACTION",
    642            exp.Select: transforms.preprocess(
    643                [
    644                    transforms.explode_to_unnest(),
    645                    transforms.unqualify_unnest,
    646                    transforms.eliminate_distinct_on,
    647                    _alias_ordered_group,
    648                    transforms.eliminate_semi_and_anti_joins,
    649                ]
    650            ),
    651            exp.SHA: rename_func("SHA1"),
    652            exp.SHA2: sha256_sql,
    653            exp.StabilityProperty: lambda self, e: (
    654                "DETERMINISTIC" if e.name == "IMMUTABLE" else "NOT DETERMINISTIC"
    655            ),
    656            exp.StrToDate: lambda self, e: self.func("PARSE_DATE", self.format_time(e), e.this),
    657            exp.StrToTime: lambda self, e: self.func(
    658                "PARSE_TIMESTAMP", self.format_time(e), e.this, e.args.get("zone")
    659            ),
    660            exp.TimeAdd: date_add_interval_sql("TIME", "ADD"),
    661            exp.TimeFromParts: rename_func("TIME"),
    662            exp.TimestampFromParts: rename_func("DATETIME"),
    663            exp.TimeSub: date_add_interval_sql("TIME", "SUB"),
    664            exp.TimestampAdd: date_add_interval_sql("TIMESTAMP", "ADD"),
    665            exp.TimestampDiff: rename_func("TIMESTAMP_DIFF"),
    666            exp.TimestampSub: date_add_interval_sql("TIMESTAMP", "SUB"),
    667            exp.TimeStrToTime: timestrtotime_sql,
    668            exp.Transaction: lambda *_: "BEGIN TRANSACTION",
    669            exp.Trim: lambda self, e: self.func("TRIM", e.this, e.expression),
    670            exp.TsOrDsAdd: _ts_or_ds_add_sql,
    671            exp.TsOrDsDiff: _ts_or_ds_diff_sql,
    672            exp.TsOrDsToTime: rename_func("TIME"),
    673            exp.TsOrDsToTimestamp: rename_func("DATETIME"),
    674            exp.Unhex: rename_func("FROM_HEX"),
    675            exp.UnixDate: rename_func("UNIX_DATE"),
    676            exp.UnixToTime: _unix_to_time_sql,
    677            exp.Values: _derived_table_values_to_unnest,
    678            exp.VariancePop: rename_func("VAR_POP"),
    679        }
    680
    681        SUPPORTED_JSON_PATH_PARTS = {
    682            exp.JSONPathKey,
    683            exp.JSONPathRoot,
    684            exp.JSONPathSubscript,
    685        }
    686
    687        TYPE_MAPPING = {
    688            **generator.Generator.TYPE_MAPPING,
    689            exp.DataType.Type.BIGDECIMAL: "BIGNUMERIC",
    690            exp.DataType.Type.BIGINT: "INT64",
    691            exp.DataType.Type.BINARY: "BYTES",
    692            exp.DataType.Type.BOOLEAN: "BOOL",
    693            exp.DataType.Type.CHAR: "STRING",
    694            exp.DataType.Type.DECIMAL: "NUMERIC",
    695            exp.DataType.Type.DOUBLE: "FLOAT64",
    696            exp.DataType.Type.FLOAT: "FLOAT64",
    697            exp.DataType.Type.INT: "INT64",
    698            exp.DataType.Type.NCHAR: "STRING",
    699            exp.DataType.Type.NVARCHAR: "STRING",
    700            exp.DataType.Type.SMALLINT: "INT64",
    701            exp.DataType.Type.TEXT: "STRING",
    702            exp.DataType.Type.TIMESTAMP: "DATETIME",
    703            exp.DataType.Type.TIMESTAMPTZ: "TIMESTAMP",
    704            exp.DataType.Type.TIMESTAMPLTZ: "TIMESTAMP",
    705            exp.DataType.Type.TINYINT: "INT64",
    706            exp.DataType.Type.VARBINARY: "BYTES",
    707            exp.DataType.Type.ROWVERSION: "BYTES",
    708            exp.DataType.Type.VARCHAR: "STRING",
    709            exp.DataType.Type.VARIANT: "ANY TYPE",
    710        }
    711
    712        PROPERTIES_LOCATION = {
    713            **generator.Generator.PROPERTIES_LOCATION,
    714            exp.PartitionedByProperty: exp.Properties.Location.POST_SCHEMA,
    715            exp.VolatileProperty: exp.Properties.Location.UNSUPPORTED,
    716        }
    717
    718        # from: https://cloud.google.com/bigquery/docs/reference/standard-sql/lexical#reserved_keywords
    719        RESERVED_KEYWORDS = {
    720            "all",
    721            "and",
    722            "any",
    723            "array",
    724            "as",
    725            "asc",
    726            "assert_rows_modified",
    727            "at",
    728            "between",
    729            "by",
    730            "case",
    731            "cast",
    732            "collate",
    733            "contains",
    734            "create",
    735            "cross",
    736            "cube",
    737            "current",
    738            "default",
    739            "define",
    740            "desc",
    741            "distinct",
    742            "else",
    743            "end",
    744            "enum",
    745            "escape",
    746            "except",
    747            "exclude",
    748            "exists",
    749            "extract",
    750            "false",
    751            "fetch",
    752            "following",
    753            "for",
    754            "from",
    755            "full",
    756            "group",
    757            "grouping",
    758            "groups",
    759            "hash",
    760            "having",
    761            "if",
    762            "ignore",
    763            "in",
    764            "inner",
    765            "intersect",
    766            "interval",
    767            "into",
    768            "is",
    769            "join",
    770            "lateral",
    771            "left",
    772            "like",
    773            "limit",
    774            "lookup",
    775            "merge",
    776            "natural",
    777            "new",
    778            "no",
    779            "not",
    780            "null",
    781            "nulls",
    782            "of",
    783            "on",
    784            "or",
    785            "order",
    786            "outer",
    787            "over",
    788            "partition",
    789            "preceding",
    790            "proto",
    791            "qualify",
    792            "range",
    793            "recursive",
    794            "respect",
    795            "right",
    796            "rollup",
    797            "rows",
    798            "select",
    799            "set",
    800            "some",
    801            "struct",
    802            "tablesample",
    803            "then",
    804            "to",
    805            "treat",
    806            "true",
    807            "unbounded",
    808            "union",
    809            "unnest",
    810            "using",
    811            "when",
    812            "where",
    813            "window",
    814            "with",
    815            "within",
    816        }
    817
    818        def mod_sql(self, expression: exp.Mod) -> str:
    819            this = expression.this
    820            expr = expression.expression
    821            return self.func(
    822                "MOD",
    823                this.unnest() if isinstance(this, exp.Paren) else this,
    824                expr.unnest() if isinstance(expr, exp.Paren) else expr,
    825            )
    826
    827        def column_parts(self, expression: exp.Column) -> str:
    828            if expression.meta.get("quoted_column"):
    829                # If a column reference is of the form `dataset.table`.name, we need
    830                # to preserve the quoted table path, otherwise the reference breaks
    831                table_parts = ".".join(p.name for p in expression.parts[:-1])
    832                table_path = self.sql(exp.Identifier(this=table_parts, quoted=True))
    833                return f"{table_path}.{self.sql(expression, 'this')}"
    834
    835            return super().column_parts(expression)
    836
    837        def table_parts(self, expression: exp.Table) -> str:
    838            # Depending on the context, `x.y` may not resolve to the same data source as `x`.`y`, so
    839            # we need to make sure the correct quoting is used in each case.
    840            #
    841            # For example, if there is a CTE x that clashes with a schema name, then the former will
    842            # return the table y in that schema, whereas the latter will return the CTE's y column:
    843            #
    844            # - WITH x AS (SELECT [1, 2] AS y) SELECT * FROM x, `x.y`   -> cross join
    845            # - WITH x AS (SELECT [1, 2] AS y) SELECT * FROM x, `x`.`y` -> implicit unnest
    846            if expression.meta.get("quoted_table"):
    847                table_parts = ".".join(p.name for p in expression.parts)
    848                return self.sql(exp.Identifier(this=table_parts, quoted=True))
    849
    850            return super().table_parts(expression)
    851
    852        def timetostr_sql(self, expression: exp.TimeToStr) -> str:
    853            this = expression.this if isinstance(expression.this, exp.TsOrDsToDate) else expression
    854            return self.func("FORMAT_DATE", self.format_time(expression), this.this)
    855
    856        def eq_sql(self, expression: exp.EQ) -> str:
    857            # Operands of = cannot be NULL in BigQuery
    858            if isinstance(expression.left, exp.Null) or isinstance(expression.right, exp.Null):
    859                if not isinstance(expression.parent, exp.Update):
    860                    return "NULL"
    861
    862            return self.binary(expression, "=")
    863
    864        def attimezone_sql(self, expression: exp.AtTimeZone) -> str:
    865            parent = expression.parent
    866
    867            # BigQuery allows CAST(.. AS {STRING|TIMESTAMP} [FORMAT <fmt> [AT TIME ZONE <tz>]]).
    868            # Only the TIMESTAMP one should use the below conversion, when AT TIME ZONE is included.
    869            if not isinstance(parent, exp.Cast) or not parent.to.is_type("text"):
    870                return self.func(
    871                    "TIMESTAMP", self.func("DATETIME", expression.this, expression.args.get("zone"))
    872                )
    873
    874            return super().attimezone_sql(expression)
    875
    876        def trycast_sql(self, expression: exp.TryCast) -> str:
    877            return self.cast_sql(expression, safe_prefix="SAFE_")
    878
    879        def bracket_sql(self, expression: exp.Bracket) -> str:
    880            this = expression.this
    881            expressions = expression.expressions
    882
    883            if len(expressions) == 1 and this and this.is_type(exp.DataType.Type.STRUCT):
    884                arg = expressions[0]
    885                if arg.type is None:
    886                    from sqlglot.optimizer.annotate_types import annotate_types
    887
    888                    arg = annotate_types(arg)
    889
    890                if arg.type and arg.type.this in exp.DataType.TEXT_TYPES:
    891                    # BQ doesn't support bracket syntax with string values for structs
    892                    return f"{self.sql(this)}.{arg.name}"
    893
    894            expressions_sql = self.expressions(expression, flat=True)
    895            offset = expression.args.get("offset")
    896
    897            if offset == 0:
    898                expressions_sql = f"OFFSET({expressions_sql})"
    899            elif offset == 1:
    900                expressions_sql = f"ORDINAL({expressions_sql})"
    901            elif offset is not None:
    902                self.unsupported(f"Unsupported array offset: {offset}")
    903
    904            if expression.args.get("safe"):
    905                expressions_sql = f"SAFE_{expressions_sql}"
    906
    907            return f"{self.sql(this)}[{expressions_sql}]"
    908
    909        def in_unnest_op(self, expression: exp.Unnest) -> str:
    910            return self.sql(expression)
    911
    912        def except_op(self, expression: exp.Except) -> str:
    913            if not expression.args.get("distinct"):
    914                self.unsupported("EXCEPT without DISTINCT is not supported in BigQuery")
    915            return f"EXCEPT{' DISTINCT' if expression.args.get('distinct') else ' ALL'}"
    916
    917        def intersect_op(self, expression: exp.Intersect) -> str:
    918            if not expression.args.get("distinct"):
    919                self.unsupported("INTERSECT without DISTINCT is not supported in BigQuery")
    920            return f"INTERSECT{' DISTINCT' if expression.args.get('distinct') else ' ALL'}"
    921
    922        def version_sql(self, expression: exp.Version) -> str:
    923            if expression.name == "TIMESTAMP":
    924                expression.set("this", "SYSTEM_TIME")
    925            return super().version_sql(expression)

logger = <Logger sqlglot (WARNING)>
class BigQuery(sqlglot.dialects.dialect.Dialect): View Source

    218class BigQuery(Dialect):
    219    WEEK_OFFSET = -1
    220    UNNEST_COLUMN_ONLY = True
    221    SUPPORTS_USER_DEFINED_TYPES = False
    222    SUPPORTS_SEMI_ANTI_JOIN = False
    223    LOG_BASE_FIRST = False
    224    HEX_LOWERCASE = True
    225
    226    # https://cloud.google.com/bigquery/docs/reference/standard-sql/lexical#case_sensitivity
    227    NORMALIZATION_STRATEGY = NormalizationStrategy.CASE_INSENSITIVE
    228
    229    # bigquery udfs are case sensitive
    230    NORMALIZE_FUNCTIONS = False
    231
    232    # https://cloud.google.com/bigquery/docs/reference/standard-sql/format-elements#format_elements_date_time
    233    TIME_MAPPING = {
    234        "%D": "%m/%d/%y",
    235        "%E6S": "%S.%f",
    236    }
    237
    238    FORMAT_MAPPING = {
    239        "DD": "%d",
    240        "MM": "%m",
    241        "MON": "%b",
    242        "MONTH": "%B",
    243        "YYYY": "%Y",
    244        "YY": "%y",
    245        "HH": "%I",
    246        "HH12": "%I",
    247        "HH24": "%H",
    248        "MI": "%M",
    249        "SS": "%S",
    250        "SSSSS": "%f",
    251        "TZH": "%z",
    252    }
    253
    254    # The _PARTITIONTIME and _PARTITIONDATE pseudo-columns are not returned by a SELECT * statement
    255    # https://cloud.google.com/bigquery/docs/querying-partitioned-tables#query_an_ingestion-time_partitioned_table
    256    PSEUDOCOLUMNS = {"_PARTITIONTIME", "_PARTITIONDATE"}
    257
    258    def normalize_identifier(self, expression: E) -> E:
    259        if (
    260            isinstance(expression, exp.Identifier)
    261            and self.normalization_strategy is not NormalizationStrategy.CASE_SENSITIVE
    262        ):
    263            parent = expression.parent
    264            while isinstance(parent, exp.Dot):
    265                parent = parent.parent
    266
    267            # In BigQuery, CTEs are case-insensitive, but UDF and table names are case-sensitive
    268            # by default. The following check uses a heuristic to detect tables based on whether
    269            # they are qualified. This should generally be correct, because tables in BigQuery
    270            # must be qualified with at least a dataset, unless @@dataset_id is set.
    271            case_sensitive = (
    272                isinstance(parent, exp.UserDefinedFunction)
    273                or (
    274                    isinstance(parent, exp.Table)
    275                    and parent.db
    276                    and (parent.meta.get("quoted_table") or not parent.meta.get("maybe_column"))
    277                )
    278                or expression.meta.get("is_table")
    279            )
    280            if not case_sensitive:
    281                expression.set("this", expression.this.lower())
    282
    283        return expression
    284
    285    class Tokenizer(tokens.Tokenizer):
    286        QUOTES = ["'", '"', '"""', "'''"]
    287        COMMENTS = ["--", "#", ("/*", "*/")]
    288        IDENTIFIERS = ["`"]
    289        STRING_ESCAPES = ["\\"]
    290
    291        HEX_STRINGS = [("0x", ""), ("0X", "")]
    292
    293        BYTE_STRINGS = [
    294            (prefix + q, q) for q in t.cast(t.List[str], QUOTES) for prefix in ("b", "B")
    295        ]
    296
    297        RAW_STRINGS = [
    298            (prefix + q, q) for q in t.cast(t.List[str], QUOTES) for prefix in ("r", "R")
    299        ]
    300
    301        KEYWORDS = {
    302            **tokens.Tokenizer.KEYWORDS,
    303            "ANY TYPE": TokenType.VARIANT,
    304            "BEGIN": TokenType.COMMAND,
    305            "BEGIN TRANSACTION": TokenType.BEGIN,
    306            "BYTES": TokenType.BINARY,
    307            "CURRENT_DATETIME": TokenType.CURRENT_DATETIME,
    308            "DATETIME": TokenType.TIMESTAMP,
    309            "DECLARE": TokenType.COMMAND,
    310            "ELSEIF": TokenType.COMMAND,
    311            "EXCEPTION": TokenType.COMMAND,
    312            "FLOAT64": TokenType.DOUBLE,
    313            "FOR SYSTEM_TIME": TokenType.TIMESTAMP_SNAPSHOT,
    314            "MODEL": TokenType.MODEL,
    315            "NOT DETERMINISTIC": TokenType.VOLATILE,
    316            "RECORD": TokenType.STRUCT,
    317            "TIMESTAMP": TokenType.TIMESTAMPTZ,
    318        }
    319        KEYWORDS.pop("DIV")
    320        KEYWORDS.pop("VALUES")
    321
    322    class Parser(parser.Parser):
    323        PREFIXED_PIVOT_COLUMNS = True
    324        LOG_DEFAULTS_TO_LN = True
    325        SUPPORTS_IMPLICIT_UNNEST = True
    326
    327        FUNCTIONS = {
    328            **parser.Parser.FUNCTIONS,
    329            "DATE": _build_date,
    330            "DATE_ADD": build_date_delta_with_interval(exp.DateAdd),
    331            "DATE_SUB": build_date_delta_with_interval(exp.DateSub),
    332            "DATE_TRUNC": lambda args: exp.DateTrunc(
    333                unit=exp.Literal.string(str(seq_get(args, 1))),
    334                this=seq_get(args, 0),
    335            ),
    336            "DATETIME": _build_datetime,
    337            "DATETIME_ADD": build_date_delta_with_interval(exp.DatetimeAdd),
    338            "DATETIME_SUB": build_date_delta_with_interval(exp.DatetimeSub),
    339            "DIV": binary_from_function(exp.IntDiv),
    340            "FORMAT_DATE": lambda args: exp.TimeToStr(
    341                this=exp.TsOrDsToDate(this=seq_get(args, 1)), format=seq_get(args, 0)
    342            ),
    343            "GENERATE_ARRAY": exp.GenerateSeries.from_arg_list,
    344            "JSON_EXTRACT_SCALAR": lambda args: exp.JSONExtractScalar(
    345                this=seq_get(args, 0), expression=seq_get(args, 1) or exp.Literal.string("$")
    346            ),
    347            "MD5": exp.MD5Digest.from_arg_list,
    348            "TO_HEX": _build_to_hex,
    349            "PARSE_DATE": lambda args: build_formatted_time(exp.StrToDate, "bigquery")(
    350                [seq_get(args, 1), seq_get(args, 0)]
    351            ),
    352            "PARSE_TIMESTAMP": _build_parse_timestamp,
    353            "REGEXP_CONTAINS": exp.RegexpLike.from_arg_list,
    354            "REGEXP_EXTRACT": lambda args: exp.RegexpExtract(
    355                this=seq_get(args, 0),
    356                expression=seq_get(args, 1),
    357                position=seq_get(args, 2),
    358                occurrence=seq_get(args, 3),
    359                group=exp.Literal.number(1) if re.compile(args[1].name).groups == 1 else None,
    360            ),
    361            "SHA256": lambda args: exp.SHA2(this=seq_get(args, 0), length=exp.Literal.number(256)),
    362            "SHA512": lambda args: exp.SHA2(this=seq_get(args, 0), length=exp.Literal.number(512)),
    363            "SPLIT": lambda args: exp.Split(
    364                # https://cloud.google.com/bigquery/docs/reference/standard-sql/string_functions#split
    365                this=seq_get(args, 0),
    366                expression=seq_get(args, 1) or exp.Literal.string(","),
    367            ),
    368            "TIME": _build_time,
    369            "TIME_ADD": build_date_delta_with_interval(exp.TimeAdd),
    370            "TIME_SUB": build_date_delta_with_interval(exp.TimeSub),
    371            "TIMESTAMP": _build_timestamp,
    372            "TIMESTAMP_ADD": build_date_delta_with_interval(exp.TimestampAdd),
    373            "TIMESTAMP_SUB": build_date_delta_with_interval(exp.TimestampSub),
    374            "TIMESTAMP_MICROS": lambda args: exp.UnixToTime(
    375                this=seq_get(args, 0), scale=exp.UnixToTime.MICROS
    376            ),
    377            "TIMESTAMP_MILLIS": lambda args: exp.UnixToTime(
    378                this=seq_get(args, 0), scale=exp.UnixToTime.MILLIS
    379            ),
    380            "TIMESTAMP_SECONDS": lambda args: exp.UnixToTime(this=seq_get(args, 0)),
    381            "TO_JSON_STRING": exp.JSONFormat.from_arg_list,
    382        }
    383
    384        FUNCTION_PARSERS = {
    385            **parser.Parser.FUNCTION_PARSERS,
    386            "ARRAY": lambda self: self.expression(exp.Array, expressions=[self._parse_statement()]),
    387        }
    388        FUNCTION_PARSERS.pop("TRIM")
    389
    390        NO_PAREN_FUNCTIONS = {
    391            **parser.Parser.NO_PAREN_FUNCTIONS,
    392            TokenType.CURRENT_DATETIME: exp.CurrentDatetime,
    393        }
    394
    395        NESTED_TYPE_TOKENS = {
    396            *parser.Parser.NESTED_TYPE_TOKENS,
    397            TokenType.TABLE,
    398        }
    399
    400        PROPERTY_PARSERS = {
    401            **parser.Parser.PROPERTY_PARSERS,
    402            "NOT DETERMINISTIC": lambda self: self.expression(
    403                exp.StabilityProperty, this=exp.Literal.string("VOLATILE")
    404            ),
    405            "OPTIONS": lambda self: self._parse_with_property(),
    406        }
    407
    408        CONSTRAINT_PARSERS = {
    409            **parser.Parser.CONSTRAINT_PARSERS,
    410            "OPTIONS": lambda self: exp.Properties(expressions=self._parse_with_property()),
    411        }
    412
    413        RANGE_PARSERS = parser.Parser.RANGE_PARSERS.copy()
    414        RANGE_PARSERS.pop(TokenType.OVERLAPS)
    415
    416        NULL_TOKENS = {TokenType.NULL, TokenType.UNKNOWN}
    417
    418        STATEMENT_PARSERS = {
    419            **parser.Parser.STATEMENT_PARSERS,
    420            TokenType.ELSE: lambda self: self._parse_as_command(self._prev),
    421            TokenType.END: lambda self: self._parse_as_command(self._prev),
    422            TokenType.FOR: lambda self: self._parse_for_in(),
    423        }
    424
    425        BRACKET_OFFSETS = {
    426            "OFFSET": (0, False),
    427            "ORDINAL": (1, False),
    428            "SAFE_OFFSET": (0, True),
    429            "SAFE_ORDINAL": (1, True),
    430        }
    431
    432        def _parse_for_in(self) -> exp.ForIn:
    433            this = self._parse_range()
    434            self._match_text_seq("DO")
    435            return self.expression(exp.ForIn, this=this, expression=self._parse_statement())
    436
    437        def _parse_table_part(self, schema: bool = False) -> t.Optional[exp.Expression]:
    438            this = super()._parse_table_part(schema=schema) or self._parse_number()
    439
    440            # https://cloud.google.com/bigquery/docs/reference/standard-sql/lexical#table_names
    441            if isinstance(this, exp.Identifier):
    442                table_name = this.name
    443                while self._match(TokenType.DASH, advance=False) and self._next:
    444                    text = ""
    445                    while self._curr and self._curr.token_type != TokenType.DOT:
    446                        self._advance()
    447                        text += self._prev.text
    448                    table_name += text
    449
    450                this = exp.Identifier(this=table_name, quoted=this.args.get("quoted"))
    451            elif isinstance(this, exp.Literal):
    452                table_name = this.name
    453
    454                if self._is_connected() and self._parse_var(any_token=True):
    455                    table_name += self._prev.text
    456
    457                this = exp.Identifier(this=table_name, quoted=True)
    458
    459            return this
    460
    461        def _parse_table_parts(
    462            self, schema: bool = False, is_db_reference: bool = False, wildcard: bool = False
    463        ) -> exp.Table:
    464            table = super()._parse_table_parts(
    465                schema=schema, is_db_reference=is_db_reference, wildcard=True
    466            )
    467
    468            # proj-1.db.tbl -- `1.` is tokenized as a float so we need to unravel it here
    469            if not table.catalog:
    470                if table.db:
    471                    parts = table.db.split(".")
    472                    if len(parts) == 2 and not table.args["db"].quoted:
    473                        table.set("catalog", exp.Identifier(this=parts[0]))
    474                        table.set("db", exp.Identifier(this=parts[1]))
    475                else:
    476                    parts = table.name.split(".")
    477                    if len(parts) == 2 and not table.this.quoted:
    478                        table.set("db", exp.Identifier(this=parts[0]))
    479                        table.set("this", exp.Identifier(this=parts[1]))
    480
    481            if any("." in p.name for p in table.parts):
    482                catalog, db, this, *rest = (
    483                    exp.to_identifier(p, quoted=True)
    484                    for p in split_num_words(".".join(p.name for p in table.parts), ".", 3)
    485                )
    486
    487                if rest and this:
    488                    this = exp.Dot.build([this, *rest])  # type: ignore
    489
    490                table = exp.Table(
    491                    this=this, db=db, catalog=catalog, pivots=table.args.get("pivots")
    492                )
    493                table.meta["quoted_table"] = True
    494
    495            return table
    496
    497        def _parse_column(self) -> t.Optional[exp.Expression]:
    498            column = super()._parse_column()
    499            if isinstance(column, exp.Column):
    500                parts = column.parts
    501                if any("." in p.name for p in parts):
    502                    catalog, db, table, this, *rest = (
    503                        exp.to_identifier(p, quoted=True)
    504                        for p in split_num_words(".".join(p.name for p in parts), ".", 4)
    505                    )
    506
    507                    if rest and this:
    508                        this = exp.Dot.build([this, *rest])  # type: ignore
    509
    510                    column = exp.Column(this=this, table=table, db=db, catalog=catalog)
    511                    column.meta["quoted_column"] = True
    512
    513            return column
    514
    515        @t.overload
    516        def _parse_json_object(self, agg: Lit[False]) -> exp.JSONObject: ...
    517
    518        @t.overload
    519        def _parse_json_object(self, agg: Lit[True]) -> exp.JSONObjectAgg: ...
    520
    521        def _parse_json_object(self, agg=False):
    522            json_object = super()._parse_json_object()
    523            array_kv_pair = seq_get(json_object.expressions, 0)
    524
    525            # Converts BQ's "signature 2" of JSON_OBJECT into SQLGlot's canonical representation
    526            # https://cloud.google.com/bigquery/docs/reference/standard-sql/json_functions#json_object_signature2
    527            if (
    528                array_kv_pair
    529                and isinstance(array_kv_pair.this, exp.Array)
    530                and isinstance(array_kv_pair.expression, exp.Array)
    531            ):
    532                keys = array_kv_pair.this.expressions
    533                values = array_kv_pair.expression.expressions
    534
    535                json_object.set(
    536                    "expressions",
    537                    [exp.JSONKeyValue(this=k, expression=v) for k, v in zip(keys, values)],
    538                )
    539
    540            return json_object
    541
    542        def _parse_bracket(
    543            self, this: t.Optional[exp.Expression] = None
    544        ) -> t.Optional[exp.Expression]:
    545            bracket = super()._parse_bracket(this)
    546
    547            if this is bracket:
    548                return bracket
    549
    550            if isinstance(bracket, exp.Bracket):
    551                for expression in bracket.expressions:
    552                    name = expression.name.upper()
    553
    554                    if name not in self.BRACKET_OFFSETS:
    555                        break
    556
    557                    offset, safe = self.BRACKET_OFFSETS[name]
    558                    bracket.set("offset", offset)
    559                    bracket.set("safe", safe)
    560                    expression.replace(expression.expressions[0])
    561
    562            return bracket
    563
    564    class Generator(generator.Generator):
    565        EXPLICIT_SET_OP = True
    566        INTERVAL_ALLOWS_PLURAL_FORM = False
    567        JOIN_HINTS = False
    568        QUERY_HINTS = False
    569        TABLE_HINTS = False
    570        LIMIT_FETCH = "LIMIT"
    571        RENAME_TABLE_WITH_DB = False
    572        NVL2_SUPPORTED = False
    573        UNNEST_WITH_ORDINALITY = False
    574        COLLATE_IS_FUNC = True
    575        LIMIT_ONLY_LITERALS = True
    576        SUPPORTS_TABLE_ALIAS_COLUMNS = False
    577        UNPIVOT_ALIASES_ARE_IDENTIFIERS = False
    578        JSON_KEY_VALUE_PAIR_SEP = ","
    579        NULL_ORDERING_SUPPORTED = False
    580        IGNORE_NULLS_IN_FUNC = True
    581        JSON_PATH_SINGLE_QUOTE_ESCAPE = True
    582        CAN_IMPLEMENT_ARRAY_ANY = True
    583        SUPPORTS_TO_NUMBER = False
    584        NAMED_PLACEHOLDER_TOKEN = "@"
    585        HEX_FUNC = "TO_HEX"
    586        WITH_PROPERTIES_PREFIX = "OPTIONS"
    587
    588        TRANSFORMS = {
    589            **generator.Generator.TRANSFORMS,
    590            exp.ApproxDistinct: rename_func("APPROX_COUNT_DISTINCT"),
    591            exp.ArgMax: arg_max_or_min_no_count("MAX_BY"),
    592            exp.ArgMin: arg_max_or_min_no_count("MIN_BY"),
    593            exp.Array: inline_array_unless_query,
    594            exp.ArrayContains: _array_contains_sql,
    595            exp.ArrayFilter: filter_array_using_unnest,
    596            exp.ArraySize: rename_func("ARRAY_LENGTH"),
    597            exp.Cast: transforms.preprocess([transforms.remove_precision_parameterized_types]),
    598            exp.CollateProperty: lambda self, e: (
    599                f"DEFAULT COLLATE {self.sql(e, 'this')}"
    600                if e.args.get("default")
    601                else f"COLLATE {self.sql(e, 'this')}"
    602            ),
    603            exp.Commit: lambda *_: "COMMIT TRANSACTION",
    604            exp.CountIf: rename_func("COUNTIF"),
    605            exp.Create: _create_sql,
    606            exp.CTE: transforms.preprocess([_pushdown_cte_column_names]),
    607            exp.DateAdd: date_add_interval_sql("DATE", "ADD"),
    608            exp.DateDiff: lambda self, e: self.func(
    609                "DATE_DIFF", e.this, e.expression, unit_to_var(e)
    610            ),
    611            exp.DateFromParts: rename_func("DATE"),
    612            exp.DateStrToDate: datestrtodate_sql,
    613            exp.DateSub: date_add_interval_sql("DATE", "SUB"),
    614            exp.DatetimeAdd: date_add_interval_sql("DATETIME", "ADD"),
    615            exp.DatetimeSub: date_add_interval_sql("DATETIME", "SUB"),
    616            exp.DateTrunc: lambda self, e: self.func("DATE_TRUNC", e.this, e.text("unit")),
    617            exp.FromTimeZone: lambda self, e: self.func(
    618                "DATETIME", self.func("TIMESTAMP", e.this, e.args.get("zone")), "'UTC'"
    619            ),
    620            exp.GenerateSeries: rename_func("GENERATE_ARRAY"),
    621            exp.GroupConcat: rename_func("STRING_AGG"),
    622            exp.Hex: lambda self, e: self.func("UPPER", self.func("TO_HEX", self.sql(e, "this"))),
    623            exp.If: if_sql(false_value="NULL"),
    624            exp.ILike: no_ilike_sql,
    625            exp.IntDiv: rename_func("DIV"),
    626            exp.JSONFormat: rename_func("TO_JSON_STRING"),
    627            exp.Max: max_or_greatest,
    628            exp.MD5: lambda self, e: self.func("TO_HEX", self.func("MD5", e.this)),
    629            exp.MD5Digest: rename_func("MD5"),
    630            exp.Min: min_or_least,
    631            exp.PartitionedByProperty: lambda self, e: f"PARTITION BY {self.sql(e, 'this')}",
    632            exp.RegexpExtract: lambda self, e: self.func(
    633                "REGEXP_EXTRACT",
    634                e.this,
    635                e.expression,
    636                e.args.get("position"),
    637                e.args.get("occurrence"),
    638            ),
    639            exp.RegexpReplace: regexp_replace_sql,
    640            exp.RegexpLike: rename_func("REGEXP_CONTAINS"),
    641            exp.ReturnsProperty: _returnsproperty_sql,
    642            exp.Rollback: lambda *_: "ROLLBACK TRANSACTION",
    643            exp.Select: transforms.preprocess(
    644                [
    645                    transforms.explode_to_unnest(),
    646                    transforms.unqualify_unnest,
    647                    transforms.eliminate_distinct_on,
    648                    _alias_ordered_group,
    649                    transforms.eliminate_semi_and_anti_joins,
    650                ]
    651            ),
    652            exp.SHA: rename_func("SHA1"),
    653            exp.SHA2: sha256_sql,
    654            exp.StabilityProperty: lambda self, e: (
    655                "DETERMINISTIC" if e.name == "IMMUTABLE" else "NOT DETERMINISTIC"
    656            ),
    657            exp.StrToDate: lambda self, e: self.func("PARSE_DATE", self.format_time(e), e.this),
    658            exp.StrToTime: lambda self, e: self.func(
    659                "PARSE_TIMESTAMP", self.format_time(e), e.this, e.args.get("zone")
    660            ),
    661            exp.TimeAdd: date_add_interval_sql("TIME", "ADD"),
    662            exp.TimeFromParts: rename_func("TIME"),
    663            exp.TimestampFromParts: rename_func("DATETIME"),
    664            exp.TimeSub: date_add_interval_sql("TIME", "SUB"),
    665            exp.TimestampAdd: date_add_interval_sql("TIMESTAMP", "ADD"),
    666            exp.TimestampDiff: rename_func("TIMESTAMP_DIFF"),
    667            exp.TimestampSub: date_add_interval_sql("TIMESTAMP", "SUB"),
    668            exp.TimeStrToTime: timestrtotime_sql,
    669            exp.Transaction: lambda *_: "BEGIN TRANSACTION",
    670            exp.Trim: lambda self, e: self.func("TRIM", e.this, e.expression),
    671            exp.TsOrDsAdd: _ts_or_ds_add_sql,
    672            exp.TsOrDsDiff: _ts_or_ds_diff_sql,
    673            exp.TsOrDsToTime: rename_func("TIME"),
    674            exp.TsOrDsToTimestamp: rename_func("DATETIME"),
    675            exp.Unhex: rename_func("FROM_HEX"),
    676            exp.UnixDate: rename_func("UNIX_DATE"),
    677            exp.UnixToTime: _unix_to_time_sql,
    678            exp.Values: _derived_table_values_to_unnest,
    679            exp.VariancePop: rename_func("VAR_POP"),
    680        }
    681
    682        SUPPORTED_JSON_PATH_PARTS = {
    683            exp.JSONPathKey,
    684            exp.JSONPathRoot,
    685            exp.JSONPathSubscript,
    686        }
    687
    688        TYPE_MAPPING = {
    689            **generator.Generator.TYPE_MAPPING,
    690            exp.DataType.Type.BIGDECIMAL: "BIGNUMERIC",
    691            exp.DataType.Type.BIGINT: "INT64",
    692            exp.DataType.Type.BINARY: "BYTES",
    693            exp.DataType.Type.BOOLEAN: "BOOL",
    694            exp.DataType.Type.CHAR: "STRING",
    695            exp.DataType.Type.DECIMAL: "NUMERIC",
    696            exp.DataType.Type.DOUBLE: "FLOAT64",
    697            exp.DataType.Type.FLOAT: "FLOAT64",
    698            exp.DataType.Type.INT: "INT64",
    699            exp.DataType.Type.NCHAR: "STRING",
    700            exp.DataType.Type.NVARCHAR: "STRING",
    701            exp.DataType.Type.SMALLINT: "INT64",
    702            exp.DataType.Type.TEXT: "STRING",
    703            exp.DataType.Type.TIMESTAMP: "DATETIME",
    704            exp.DataType.Type.TIMESTAMPTZ: "TIMESTAMP",
    705            exp.DataType.Type.TIMESTAMPLTZ: "TIMESTAMP",
    706            exp.DataType.Type.TINYINT: "INT64",
    707            exp.DataType.Type.VARBINARY: "BYTES",
    708            exp.DataType.Type.ROWVERSION: "BYTES",
    709            exp.DataType.Type.VARCHAR: "STRING",
    710            exp.DataType.Type.VARIANT: "ANY TYPE",
    711        }
    712
    713        PROPERTIES_LOCATION = {
    714            **generator.Generator.PROPERTIES_LOCATION,
    715            exp.PartitionedByProperty: exp.Properties.Location.POST_SCHEMA,
    716            exp.VolatileProperty: exp.Properties.Location.UNSUPPORTED,
    717        }
    718
    719        # from: https://cloud.google.com/bigquery/docs/reference/standard-sql/lexical#reserved_keywords
    720        RESERVED_KEYWORDS = {
    721            "all",
    722            "and",
    723            "any",
    724            "array",
    725            "as",
    726            "asc",
    727            "assert_rows_modified",
    728            "at",
    729            "between",
    730            "by",
    731            "case",
    732            "cast",
    733            "collate",
    734            "contains",
    735            "create",
    736            "cross",
    737            "cube",
    738            "current",
    739            "default",
    740            "define",
    741            "desc",
    742            "distinct",
    743            "else",
    744            "end",
    745            "enum",
    746            "escape",
    747            "except",
    748            "exclude",
    749            "exists",
    750            "extract",
    751            "false",
    752            "fetch",
    753            "following",
    754            "for",
    755            "from",
    756            "full",
    757            "group",
    758            "grouping",
    759            "groups",
    760            "hash",
    761            "having",
    762            "if",
    763            "ignore",
    764            "in",
    765            "inner",
    766            "intersect",
    767            "interval",
    768            "into",
    769            "is",
    770            "join",
    771            "lateral",
    772            "left",
    773            "like",
    774            "limit",
    775            "lookup",
    776            "merge",
    777            "natural",
    778            "new",
    779            "no",
    780            "not",
    781            "null",
    782            "nulls",
    783            "of",
    784            "on",
    785            "or",
    786            "order",
    787            "outer",
    788            "over",
    789            "partition",
    790            "preceding",
    791            "proto",
    792            "qualify",
    793            "range",
    794            "recursive",
    795            "respect",
    796            "right",
    797            "rollup",
    798            "rows",
    799            "select",
    800            "set",
    801            "some",
    802            "struct",
    803            "tablesample",
    804            "then",
    805            "to",
    806            "treat",
    807            "true",
    808            "unbounded",
    809            "union",
    810            "unnest",
    811            "using",
    812            "when",
    813            "where",
    814            "window",
    815            "with",
    816            "within",
    817        }
    818
    819        def mod_sql(self, expression: exp.Mod) -> str:
    820            this = expression.this
    821            expr = expression.expression
    822            return self.func(
    823                "MOD",
    824                this.unnest() if isinstance(this, exp.Paren) else this,
    825                expr.unnest() if isinstance(expr, exp.Paren) else expr,
    826            )
    827
    828        def column_parts(self, expression: exp.Column) -> str:
    829            if expression.meta.get("quoted_column"):
    830                # If a column reference is of the form `dataset.table`.name, we need
    831                # to preserve the quoted table path, otherwise the reference breaks
    832                table_parts = ".".join(p.name for p in expression.parts[:-1])
    833                table_path = self.sql(exp.Identifier(this=table_parts, quoted=True))
    834                return f"{table_path}.{self.sql(expression, 'this')}"
    835
    836            return super().column_parts(expression)
    837
    838        def table_parts(self, expression: exp.Table) -> str:
    839            # Depending on the context, `x.y` may not resolve to the same data source as `x`.`y`, so
    840            # we need to make sure the correct quoting is used in each case.
    841            #
    842            # For example, if there is a CTE x that clashes with a schema name, then the former will
    843            # return the table y in that schema, whereas the latter will return the CTE's y column:
    844            #
    845            # - WITH x AS (SELECT [1, 2] AS y) SELECT * FROM x, `x.y`   -> cross join
    846            # - WITH x AS (SELECT [1, 2] AS y) SELECT * FROM x, `x`.`y` -> implicit unnest
    847            if expression.meta.get("quoted_table"):
    848                table_parts = ".".join(p.name for p in expression.parts)
    849                return self.sql(exp.Identifier(this=table_parts, quoted=True))
    850
    851            return super().table_parts(expression)
    852
    853        def timetostr_sql(self, expression: exp.TimeToStr) -> str:
    854            this = expression.this if isinstance(expression.this, exp.TsOrDsToDate) else expression
    855            return self.func("FORMAT_DATE", self.format_time(expression), this.this)
    856
    857        def eq_sql(self, expression: exp.EQ) -> str:
    858            # Operands of = cannot be NULL in BigQuery
    859            if isinstance(expression.left, exp.Null) or isinstance(expression.right, exp.Null):
    860                if not isinstance(expression.parent, exp.Update):
    861                    return "NULL"
    862
    863            return self.binary(expression, "=")
    864
    865        def attimezone_sql(self, expression: exp.AtTimeZone) -> str:
    866            parent = expression.parent
    867
    868            # BigQuery allows CAST(.. AS {STRING|TIMESTAMP} [FORMAT <fmt> [AT TIME ZONE <tz>]]).
    869            # Only the TIMESTAMP one should use the below conversion, when AT TIME ZONE is included.
    870            if not isinstance(parent, exp.Cast) or not parent.to.is_type("text"):
    871                return self.func(
    872                    "TIMESTAMP", self.func("DATETIME", expression.this, expression.args.get("zone"))
    873                )
    874
    875            return super().attimezone_sql(expression)
    876
    877        def trycast_sql(self, expression: exp.TryCast) -> str:
    878            return self.cast_sql(expression, safe_prefix="SAFE_")
    879
    880        def bracket_sql(self, expression: exp.Bracket) -> str:
    881            this = expression.this
    882            expressions = expression.expressions
    883
    884            if len(expressions) == 1 and this and this.is_type(exp.DataType.Type.STRUCT):
    885                arg = expressions[0]
    886                if arg.type is None:
    887                    from sqlglot.optimizer.annotate_types import annotate_types
    888
    889                    arg = annotate_types(arg)
    890
    891                if arg.type and arg.type.this in exp.DataType.TEXT_TYPES:
    892                    # BQ doesn't support bracket syntax with string values for structs
    893                    return f"{self.sql(this)}.{arg.name}"
    894
    895            expressions_sql = self.expressions(expression, flat=True)
    896            offset = expression.args.get("offset")
    897
    898            if offset == 0:
    899                expressions_sql = f"OFFSET({expressions_sql})"
    900            elif offset == 1:
    901                expressions_sql = f"ORDINAL({expressions_sql})"
    902            elif offset is not None:
    903                self.unsupported(f"Unsupported array offset: {offset}")
    904
    905            if expression.args.get("safe"):
    906                expressions_sql = f"SAFE_{expressions_sql}"
    907
    908            return f"{self.sql(this)}[{expressions_sql}]"
    909
    910        def in_unnest_op(self, expression: exp.Unnest) -> str:
    911            return self.sql(expression)
    912
    913        def except_op(self, expression: exp.Except) -> str:
    914            if not expression.args.get("distinct"):
    915                self.unsupported("EXCEPT without DISTINCT is not supported in BigQuery")
    916            return f"EXCEPT{' DISTINCT' if expression.args.get('distinct') else ' ALL'}"
    917
    918        def intersect_op(self, expression: exp.Intersect) -> str:
    919            if not expression.args.get("distinct"):
    920                self.unsupported("INTERSECT without DISTINCT is not supported in BigQuery")
    921            return f"INTERSECT{' DISTINCT' if expression.args.get('distinct') else ' ALL'}"
    922
    923        def version_sql(self, expression: exp.Version) -> str:
    924            if expression.name == "TIMESTAMP":
    925                expression.set("this", "SYSTEM_TIME")
    926            return super().version_sql(expression)

WEEK_OFFSET = -1

First day of the week in DATE_TRUNC(week). Defaults to 0 (Monday). -1 would be Sunday.

UNNEST_COLUMN_ONLY = True

Whether `UNNEST` table aliases are treated as column aliases.

SUPPORTS_USER_DEFINED_TYPES = False

Whether user-defined data types are supported.

SUPPORTS_SEMI_ANTI_JOIN = False

Whether `SEMI` or `ANTI` joins are supported.

LOG_BASE_FIRST: Optional[bool] = False

Whether the base comes first in the `LOG` function. Possible values: `True`, `False`, `None` (two arguments are not supported by `LOG`)

HEX_LOWERCASE = True

Whether the `HEX` function returns a lowercase hexadecimal string.

NORMALIZATION_STRATEGY = <NormalizationStrategy.CASE_INSENSITIVE: 'CASE_INSENSITIVE'>

Specifies the strategy according to which identifiers should be normalized.

NORMALIZE_FUNCTIONS: bool | str = False

Determines how function names are going to be normalized.

###### Possible values:

> "upper" or True: Convert names to uppercase. "lower": Convert names to lowercase. False: Disables function name normalization.

TIME_MAPPING: Dict[str, str] = {'%D': '%m/%d/%y', '%E6S': '%S.%f'}

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

FORMAT_MAPPING: Dict[str, str] = {'DD': '%d', 'MM': '%m', 'MON': '%b', 'MONTH': '%B', 'YYYY': '%Y', 'YY': '%y', 'HH': '%I', 'HH12': '%I', 'HH24': '%H', 'MI': '%M', 'SS': '%S', 'SSSSS': '%f', 'TZH': '%z'}

Helper which is used for parsing the special syntax `CAST(x AS DATE FORMAT 'yyyy')`. If empty, the corresponding trie will be constructed off of `TIME_MAPPING`.

PSEUDOCOLUMNS: Set[str] = {'_PARTITIONTIME', '_PARTITIONDATE'}

Columns that are auto-generated by the engine corresponding to this dialect. For example, such columns may be excluded from `SELECT *` queries.

def normalize_identifier(self, expression: ~E) -> ~E: View Source

    258    def normalize_identifier(self, expression: E) -> E:
    259        if (
    260            isinstance(expression, exp.Identifier)
    261            and self.normalization_strategy is not NormalizationStrategy.CASE_SENSITIVE
    262        ):
    263            parent = expression.parent
    264            while isinstance(parent, exp.Dot):
    265                parent = parent.parent
    266
    267            # In BigQuery, CTEs are case-insensitive, but UDF and table names are case-sensitive
    268            # by default. The following check uses a heuristic to detect tables based on whether
    269            # they are qualified. This should generally be correct, because tables in BigQuery
    270            # must be qualified with at least a dataset, unless @@dataset_id is set.
    271            case_sensitive = (
    272                isinstance(parent, exp.UserDefinedFunction)
    273                or (
    274                    isinstance(parent, exp.Table)
    275                    and parent.db
    276                    and (parent.meta.get("quoted_table") or not parent.meta.get("maybe_column"))
    277                )
    278                or expression.meta.get("is_table")
    279            )
    280            if not case_sensitive:
    281                expression.set("this", expression.this.lower())
    282
    283        return expression

Transforms an identifier in a way that resembles how it'd be resolved by this dialect.

For example, an identifier like `FoO` would be resolved as `foo` in Postgres, because it lowercases all unquoted identifiers. On the other hand, Snowflake uppercases them, so it would resolve it as `FOO`. If it was quoted, it'd need to be treated as case-sensitive, and so any normalization would be prohibited in order to avoid "breaking" the identifier.

There are also dialects like Spark, which are case-insensitive even when quotes are present, and dialects like MySQL, whose resolution rules match those employed by the underlying operating system, for example they may always be case-sensitive in Linux.

Finally, the normalization behavior of some engines can even be controlled through flags, like in Redshift's case, where users can explicitly set enable_case_sensitive_identifier.

SQLGlot aims to understand and handle all of these different behaviors gracefully, so that it can analyze queries in the optimizer and successfully capture their semantics.

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

tokenizer_class = <class 'BigQuery.Tokenizer'>
jsonpath_tokenizer_class = <class 'sqlglot.tokens.JSONPathTokenizer'>
parser_class = <class 'BigQuery.Parser'>
generator_class = <class 'BigQuery.Generator'>
TIME_TRIE: Dict = {'%': {'D': {0: True}, 'E': {'6': {'S': {0: True}}}}}
FORMAT_TRIE: Dict = {'D': {'D': {0: True}}, 'M': {'M': {0: True}, 'O': {'N': {0: True, 'T': {'H': {0: True}}}}, 'I': {0: True}}, 'Y': {'Y': {'Y': {'Y': {0: True}}, 0: True}}, 'H': {'H': {0: True, '1': {'2': {0: True}}, '2': {'4': {0: True}}}}, 'S': {'S': {0: True, 'S': {'S': {'S': {0: True}}}}}, 'T': {'Z': {'H': {0: True}}}}
INVERSE_TIME_MAPPING: Dict[str, str] = {'%m/%d/%y': '%D', '%S.%f': '%E6S'}
INVERSE_TIME_TRIE: Dict = {'%': {'m': {'/': {'%': {'d': {'/': {'%': {'y': {0: True}}}}}}}, 'S': {'.': {'%': {'f': {0: True}}}}}}
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 = '`'
BIT_START: Optional[str] = None
BIT_END: Optional[str] = None
HEX_START: Optional[str] = '0x'
HEX_END: Optional[str] = ''
BYTE_START: Optional[str] = "b'"
BYTE_END: Optional[str] = "'"
UNICODE_START: Optional[str] = None
UNICODE_END: Optional[str] = None

##### Inherited Members

sqlglot.dialects.dialect.Dialect
  Dialect
  INDEX_OFFSET
  ALIAS_POST_TABLESAMPLE
  TABLESAMPLE_SIZE_IS_PERCENT
  IDENTIFIERS_CAN_START_WITH_DIGIT
  DPIPE_IS_STRING_CONCAT
  STRICT_STRING_CONCAT
  COPY_PARAMS_ARE_CSV
  NULL_ORDERING
  TYPED_DIVISION
  SAFE_DIVISION
  CONCAT_COALESCE
  DATE_FORMAT
  DATEINT_FORMAT
  TIME_FORMAT
  PREFER_CTE_ALIAS_COLUMN
  DATE_PART_MAPPING
  get_or_raise
  format_time
  settings
  case_sensitive
  can_identify
  quote_identifier
  to_json_path
  parse
  parse_into
  generate
  transpile
  tokenize
  tokenizer
  jsonpath_tokenizer
  parser
  generator

class BigQuery.Tokenizer(sqlglot.tokens.Tokenizer): View Source

    285    class Tokenizer(tokens.Tokenizer):
    286        QUOTES = ["'", '"', '"""', "'''"]
    287        COMMENTS = ["--", "#", ("/*", "*/")]
    288        IDENTIFIERS = ["`"]
    289        STRING_ESCAPES = ["\\"]
    290
    291        HEX_STRINGS = [("0x", ""), ("0X", "")]
    292
    293        BYTE_STRINGS = [
    294            (prefix + q, q) for q in t.cast(t.List[str], QUOTES) for prefix in ("b", "B")
    295        ]
    296
    297        RAW_STRINGS = [
    298            (prefix + q, q) for q in t.cast(t.List[str], QUOTES) for prefix in ("r", "R")
    299        ]
    300
    301        KEYWORDS = {
    302            **tokens.Tokenizer.KEYWORDS,
    303            "ANY TYPE": TokenType.VARIANT,
    304            "BEGIN": TokenType.COMMAND,
    305            "BEGIN TRANSACTION": TokenType.BEGIN,
    306            "BYTES": TokenType.BINARY,
    307            "CURRENT_DATETIME": TokenType.CURRENT_DATETIME,
    308            "DATETIME": TokenType.TIMESTAMP,
    309            "DECLARE": TokenType.COMMAND,
    310            "ELSEIF": TokenType.COMMAND,
    311            "EXCEPTION": TokenType.COMMAND,
    312            "FLOAT64": TokenType.DOUBLE,
    313            "FOR SYSTEM_TIME": TokenType.TIMESTAMP_SNAPSHOT,
    314            "MODEL": TokenType.MODEL,
    315            "NOT DETERMINISTIC": TokenType.VOLATILE,
    316            "RECORD": TokenType.STRUCT,
    317            "TIMESTAMP": TokenType.TIMESTAMPTZ,
    318        }
    319        KEYWORDS.pop("DIV")
    320        KEYWORDS.pop("VALUES")

QUOTES = ["'", '"', '"""', "'''"]
COMMENTS = ['--', '#', ('/*', '*/')]
IDENTIFIERS = ['`']
STRING_ESCAPES = ['\\']
HEX_STRINGS = [('0x', ''), ('0X', '')]
BYTE_STRINGS = [("b'", "'"), ("B'", "'"), ('b"', '"'), ('B"', '"'), ('b"""', '"""'), ('B"""', '"""'), ("b'''", "'''"), ("B'''", "'''")]
RAW_STRINGS = [("r'", "'"), ("R'", "'"), ('r"', '"'), ('R"', '"'), ('r"""', '"""'), ('R"""', '"""'), ("r'''", "'''"), ("R'''", "'''")]
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.HINT: 'HINT'>, '==': <TokenType.EQ: 'EQ'>, '::': <TokenType.DCOLON: 'DCOLON'>, '||': <TokenType.DPIPE: 'DPIPE'>, '>=': <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'>, 'ALL': <TokenType.ALL: 'ALL'>, 'ALWAYS': <TokenType.ALWAYS: 'ALWAYS'>, '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.COMMAND: 'COMMAND'>, '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_TIME': <TokenType.CURRENT_TIME: 'CURRENT_TIME'>, 'CURRENT_TIMESTAMP': <TokenType.CURRENT_TIMESTAMP: 'CURRENT_TIMESTAMP'>, 'CURRENT_USER': <TokenType.CURRENT_USER: 'CURRENT_USER'>, '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'>, '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'>, 'LOCK': <TokenType.LOCK: 'LOCK'>, 'MERGE': <TokenType.MERGE: 'MERGE'>, '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'>, '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'>, 'QUALIFY': <TokenType.QUALIFY: 'QUALIFY'>, 'RANGE': <TokenType.RANGE: 'RANGE'>, 'RECURSIVE': <TokenType.RECURSIVE: 'RECURSIVE'>, 'REGEXP': <TokenType.RLIKE: 'RLIKE'>, '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'>, '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'>, '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'>, 'INT128': <TokenType.INT128: 'INT128'>, 'HUGEINT': <TokenType.INT128: 'INT128'>, 'INT2': <TokenType.SMALLINT: 'SMALLINT'>, 'INTEGER': <TokenType.INT: 'INT'>, 'INT': <TokenType.INT: 'INT'>, 'INT4': <TokenType.INT: 'INT'>, 'INT32': <TokenType.INT: 'INT'>, 'INT64': <TokenType.BIGINT: 'BIGINT'>, 'LONG': <TokenType.BIGINT: 'BIGINT'>, 'BIGINT': <TokenType.BIGINT: 'BIGINT'>, 'INT8': <TokenType.TINYINT: 'TINYINT'>, 'UINT': <TokenType.UINT: 'UINT'>, 'DEC': <TokenType.DECIMAL: 'DECIMAL'>, 'DECIMAL': <TokenType.DECIMAL: 'DECIMAL'>, 'BIGDECIMAL': <TokenType.BIGDECIMAL: 'BIGDECIMAL'>, 'BIGNUMERIC': <TokenType.BIGDECIMAL: 'BIGDECIMAL'>, '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.FLOAT: 'FLOAT'>, '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'>, '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'>, 'TIMESTAMP': <TokenType.TIMESTAMPTZ: 'TIMESTAMPTZ'>, '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.TIMESTAMP: 'TIMESTAMP'>, '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'>, 'STRUCT': <TokenType.STRUCT: 'STRUCT'>, 'SEQUENCE': <TokenType.SEQUENCE: 'SEQUENCE'>, 'VARIANT': <TokenType.VARIANT: 'VARIANT'>, 'ALTER': <TokenType.ALTER: 'ALTER'>, 'ANALYZE': <TokenType.COMMAND: 'COMMAND'>, 'CALL': <TokenType.COMMAND: 'COMMAND'>, 'COMMENT': <TokenType.COMMENT: 'COMMENT'>, 'EXPLAIN': <TokenType.COMMAND: 'COMMAND'>, 'GRANT': <TokenType.COMMAND: 'COMMAND'>, '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'>, 'ANY TYPE': <TokenType.VARIANT: 'VARIANT'>, 'BEGIN TRANSACTION': <TokenType.BEGIN: 'BEGIN'>, 'BYTES': <TokenType.BINARY: 'BINARY'>, 'CURRENT_DATETIME': <TokenType.CURRENT_DATETIME: 'CURRENT_DATETIME'>, 'DECLARE': <TokenType.COMMAND: 'COMMAND'>, 'ELSEIF': <TokenType.COMMAND: 'COMMAND'>, 'EXCEPTION': <TokenType.COMMAND: 'COMMAND'>, 'FLOAT64': <TokenType.DOUBLE: 'DOUBLE'>, 'FOR SYSTEM_TIME': <TokenType.TIMESTAMP_SNAPSHOT: 'TIMESTAMP_SNAPSHOT'>, 'MODEL': <TokenType.MODEL: 'MODEL'>, 'NOT DETERMINISTIC': <TokenType.VOLATILE: 'VOLATILE'>, 'RECORD': <TokenType.STRUCT: 'STRUCT'>}

##### Inherited Members

sqlglot.tokens.Tokenizer
  Tokenizer
  SINGLE_TOKENS
  BIT_STRINGS
  HEREDOC_STRINGS
  UNICODE_STRINGS
  IDENTIFIER_ESCAPES
  VAR_SINGLE_TOKENS
  HEREDOC_TAG_IS_IDENTIFIER
  HEREDOC_STRING_ALTERNATIVE
  WHITE_SPACE
  COMMANDS
  COMMAND_PREFIX_TOKENS
  NUMERIC_LITERALS
  dialect
  reset
  tokenize
  tokenize_rs
  size
  sql
  tokens

class BigQuery.Parser(sqlglot.parser.Parser): View Source

    322    class Parser(parser.Parser):
    323        PREFIXED_PIVOT_COLUMNS = True
    324        LOG_DEFAULTS_TO_LN = True
    325        SUPPORTS_IMPLICIT_UNNEST = True
    326
    327        FUNCTIONS = {
    328            **parser.Parser.FUNCTIONS,
    329            "DATE": _build_date,
    330            "DATE_ADD": build_date_delta_with_interval(exp.DateAdd),
    331            "DATE_SUB": build_date_delta_with_interval(exp.DateSub),
    332            "DATE_TRUNC": lambda args: exp.DateTrunc(
    333                unit=exp.Literal.string(str(seq_get(args, 1))),
    334                this=seq_get(args, 0),
    335            ),
    336            "DATETIME": _build_datetime,
    337            "DATETIME_ADD": build_date_delta_with_interval(exp.DatetimeAdd),
    338            "DATETIME_SUB": build_date_delta_with_interval(exp.DatetimeSub),
    339            "DIV": binary_from_function(exp.IntDiv),
    340            "FORMAT_DATE": lambda args: exp.TimeToStr(
    341                this=exp.TsOrDsToDate(this=seq_get(args, 1)), format=seq_get(args, 0)
    342            ),
    343            "GENERATE_ARRAY": exp.GenerateSeries.from_arg_list,
    344            "JSON_EXTRACT_SCALAR": lambda args: exp.JSONExtractScalar(
    345                this=seq_get(args, 0), expression=seq_get(args, 1) or exp.Literal.string("$")
    346            ),
    347            "MD5": exp.MD5Digest.from_arg_list,
    348            "TO_HEX": _build_to_hex,
    349            "PARSE_DATE": lambda args: build_formatted_time(exp.StrToDate, "bigquery")(
    350                [seq_get(args, 1), seq_get(args, 0)]
    351            ),
    352            "PARSE_TIMESTAMP": _build_parse_timestamp,
    353            "REGEXP_CONTAINS": exp.RegexpLike.from_arg_list,
    354            "REGEXP_EXTRACT": lambda args: exp.RegexpExtract(
    355                this=seq_get(args, 0),
    356                expression=seq_get(args, 1),
    357                position=seq_get(args, 2),
    358                occurrence=seq_get(args, 3),
    359                group=exp.Literal.number(1) if re.compile(args[1].name).groups == 1 else None,
    360            ),
    361            "SHA256": lambda args: exp.SHA2(this=seq_get(args, 0), length=exp.Literal.number(256)),
    362            "SHA512": lambda args: exp.SHA2(this=seq_get(args, 0), length=exp.Literal.number(512)),
    363            "SPLIT": lambda args: exp.Split(
    364                # https://cloud.google.com/bigquery/docs/reference/standard-sql/string_functions#split
    365                this=seq_get(args, 0),
    366                expression=seq_get(args, 1) or exp.Literal.string(","),
    367            ),
    368            "TIME": _build_time,
    369            "TIME_ADD": build_date_delta_with_interval(exp.TimeAdd),
    370            "TIME_SUB": build_date_delta_with_interval(exp.TimeSub),
    371            "TIMESTAMP": _build_timestamp,
    372            "TIMESTAMP_ADD": build_date_delta_with_interval(exp.TimestampAdd),
    373            "TIMESTAMP_SUB": build_date_delta_with_interval(exp.TimestampSub),
    374            "TIMESTAMP_MICROS": lambda args: exp.UnixToTime(
    375                this=seq_get(args, 0), scale=exp.UnixToTime.MICROS
    376            ),
    377            "TIMESTAMP_MILLIS": lambda args: exp.UnixToTime(
    378                this=seq_get(args, 0), scale=exp.UnixToTime.MILLIS
    379            ),
    380            "TIMESTAMP_SECONDS": lambda args: exp.UnixToTime(this=seq_get(args, 0)),
    381            "TO_JSON_STRING": exp.JSONFormat.from_arg_list,
    382        }
    383
    384        FUNCTION_PARSERS = {
    385            **parser.Parser.FUNCTION_PARSERS,
    386            "ARRAY": lambda self: self.expression(exp.Array, expressions=[self._parse_statement()]),
    387        }
    388        FUNCTION_PARSERS.pop("TRIM")
    389
    390        NO_PAREN_FUNCTIONS = {
    391            **parser.Parser.NO_PAREN_FUNCTIONS,
    392            TokenType.CURRENT_DATETIME: exp.CurrentDatetime,
    393        }
    394
    395        NESTED_TYPE_TOKENS = {
    396            *parser.Parser.NESTED_TYPE_TOKENS,
    397            TokenType.TABLE,
    398        }
    399
    400        PROPERTY_PARSERS = {
    401            **parser.Parser.PROPERTY_PARSERS,
    402            "NOT DETERMINISTIC": lambda self: self.expression(
    403                exp.StabilityProperty, this=exp.Literal.string("VOLATILE")
    404            ),
    405            "OPTIONS": lambda self: self._parse_with_property(),
    406        }
    407
    408        CONSTRAINT_PARSERS = {
    409            **parser.Parser.CONSTRAINT_PARSERS,
    410            "OPTIONS": lambda self: exp.Properties(expressions=self._parse_with_property()),
    411        }
    412
    413        RANGE_PARSERS = parser.Parser.RANGE_PARSERS.copy()
    414        RANGE_PARSERS.pop(TokenType.OVERLAPS)
    415
    416        NULL_TOKENS = {TokenType.NULL, TokenType.UNKNOWN}
    417
    418        STATEMENT_PARSERS = {
    419            **parser.Parser.STATEMENT_PARSERS,
    420            TokenType.ELSE: lambda self: self._parse_as_command(self._prev),
    421            TokenType.END: lambda self: self._parse_as_command(self._prev),
    422            TokenType.FOR: lambda self: self._parse_for_in(),
    423        }
    424
    425        BRACKET_OFFSETS = {
    426            "OFFSET": (0, False),
    427            "ORDINAL": (1, False),
    428            "SAFE_OFFSET": (0, True),
    429            "SAFE_ORDINAL": (1, True),
    430        }
    431
    432        def _parse_for_in(self) -> exp.ForIn:
    433            this = self._parse_range()
    434            self._match_text_seq("DO")
    435            return self.expression(exp.ForIn, this=this, expression=self._parse_statement())
    436
    437        def _parse_table_part(self, schema: bool = False) -> t.Optional[exp.Expression]:
    438            this = super()._parse_table_part(schema=schema) or self._parse_number()
    439
    440            # https://cloud.google.com/bigquery/docs/reference/standard-sql/lexical#table_names
    441            if isinstance(this, exp.Identifier):
    442                table_name = this.name
    443                while self._match(TokenType.DASH, advance=False) and self._next:
    444                    text = ""
    445                    while self._curr and self._curr.token_type != TokenType.DOT:
    446                        self._advance()
    447                        text += self._prev.text
    448                    table_name += text
    449
    450                this = exp.Identifier(this=table_name, quoted=this.args.get("quoted"))
    451            elif isinstance(this, exp.Literal):
    452                table_name = this.name
    453
    454                if self._is_connected() and self._parse_var(any_token=True):
    455                    table_name += self._prev.text
    456
    457                this = exp.Identifier(this=table_name, quoted=True)
    458
    459            return this
    460
    461        def _parse_table_parts(
    462            self, schema: bool = False, is_db_reference: bool = False, wildcard: bool = False
    463        ) -> exp.Table:
    464            table = super()._parse_table_parts(
    465                schema=schema, is_db_reference=is_db_reference, wildcard=True
    466            )
    467
    468            # proj-1.db.tbl -- `1.` is tokenized as a float so we need to unravel it here
    469            if not table.catalog:
    470                if table.db:
    471                    parts = table.db.split(".")
    472                    if len(parts) == 2 and not table.args["db"].quoted:
    473                        table.set("catalog", exp.Identifier(this=parts[0]))
    474                        table.set("db", exp.Identifier(this=parts[1]))
    475                else:
    476                    parts = table.name.split(".")
    477                    if len(parts) == 2 and not table.this.quoted:
    478                        table.set("db", exp.Identifier(this=parts[0]))
    479                        table.set("this", exp.Identifier(this=parts[1]))
    480
    481            if any("." in p.name for p in table.parts):
    482                catalog, db, this, *rest = (
    483                    exp.to_identifier(p, quoted=True)
    484                    for p in split_num_words(".".join(p.name for p in table.parts), ".", 3)
    485                )
    486
    487                if rest and this:
    488                    this = exp.Dot.build([this, *rest])  # type: ignore
    489
    490                table = exp.Table(
    491                    this=this, db=db, catalog=catalog, pivots=table.args.get("pivots")
    492                )
    493                table.meta["quoted_table"] = True
    494
    495            return table
    496
    497        def _parse_column(self) -> t.Optional[exp.Expression]:
    498            column = super()._parse_column()
    499            if isinstance(column, exp.Column):
    500                parts = column.parts
    501                if any("." in p.name for p in parts):
    502                    catalog, db, table, this, *rest = (
    503                        exp.to_identifier(p, quoted=True)
    504                        for p in split_num_words(".".join(p.name for p in parts), ".", 4)
    505                    )
    506
    507                    if rest and this:
    508                        this = exp.Dot.build([this, *rest])  # type: ignore
    509
    510                    column = exp.Column(this=this, table=table, db=db, catalog=catalog)
    511                    column.meta["quoted_column"] = True
    512
    513            return column
    514
    515        @t.overload
    516        def _parse_json_object(self, agg: Lit[False]) -> exp.JSONObject: ...
    517
    518        @t.overload
    519        def _parse_json_object(self, agg: Lit[True]) -> exp.JSONObjectAgg: ...
    520
    521        def _parse_json_object(self, agg=False):
    522            json_object = super()._parse_json_object()
    523            array_kv_pair = seq_get(json_object.expressions, 0)
    524
    525            # Converts BQ's "signature 2" of JSON_OBJECT into SQLGlot's canonical representation
    526            # https://cloud.google.com/bigquery/docs/reference/standard-sql/json_functions#json_object_signature2
    527            if (
    528                array_kv_pair
    529                and isinstance(array_kv_pair.this, exp.Array)
    530                and isinstance(array_kv_pair.expression, exp.Array)
    531            ):
    532                keys = array_kv_pair.this.expressions
    533                values = array_kv_pair.expression.expressions
    534
    535                json_object.set(
    536                    "expressions",
    537                    [exp.JSONKeyValue(this=k, expression=v) for k, v in zip(keys, values)],
    538                )
    539
    540            return json_object
    541
    542        def _parse_bracket(
    543            self, this: t.Optional[exp.Expression] = None
    544        ) -> t.Optional[exp.Expression]:
    545            bracket = super()._parse_bracket(this)
    546
    547            if this is bracket:
    548                return bracket
    549
    550            if isinstance(bracket, exp.Bracket):
    551                for expression in bracket.expressions:
    552                    name = expression.name.upper()
    553
    554                    if name not in self.BRACKET_OFFSETS:
    555                        break
    556
    557                    offset, safe = self.BRACKET_OFFSETS[name]
    558                    bracket.set("offset", offset)
    559                    bracket.set("safe", safe)
    560                    expression.replace(expression.expressions[0])
    561
    562            return bracket

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

PREFIXED_PIVOT_COLUMNS = True
LOG_DEFAULTS_TO_LN = True
SUPPORTS_IMPLICIT_UNNEST = True
FUNCTIONS = {'ABS': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Abs'>>, 'ADD_MONTHS': <bound method Func.from_arg_list of <class 'sqlglot.expressions.AddMonths'>>, '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'>>, 'APPROX_DISTINCT': <bound method Func.from_arg_list of <class 'sqlglot.expressions.ApproxDistinct'>>, 'APPROX_COUNT_DISTINCT': <bound method Func.from_arg_list of <class 'sqlglot.expressions.ApproxDistinct'>>, 'APPROX_QUANTILE': <bound method Func.from_arg_list of <class 'sqlglot.expressions.ApproxQuantile'>>, 'APPROX_TOP_K': <bound method Func.from_arg_list of <class 'sqlglot.expressions.ApproxTopK'>>, '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': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Array'>>, 'ARRAY_AGG': <bound method Func.from_arg_list of <class 'sqlglot.expressions.ArrayAgg'>>, 'ARRAY_ALL': <bound method Func.from_arg_list of <class 'sqlglot.expressions.ArrayAll'>>, 'ARRAY_ANY': <bound method Func.from_arg_list of <class 'sqlglot.expressions.ArrayAny'>>, 'ARRAY_CONCAT': <bound method Func.from_arg_list of <class 'sqlglot.expressions.ArrayConcat'>>, 'ARRAY_CAT': <bound method Func.from_arg_list of <class 'sqlglot.expressions.ArrayConcat'>>, '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_OVERLAPS': <bound method Func.from_arg_list of <class 'sqlglot.expressions.ArrayOverlaps'>>, '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_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'>>, 'AVG': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Avg'>>, 'CASE': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Case'>>, 'CAST': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Cast'>>, 'CAST_TO_STR_TYPE': <bound method Func.from_arg_list of <class 'sqlglot.expressions.CastToStrType'>>, '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'>>, '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': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Coalesce'>>, 'IFNULL': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Coalesce'>>, 'NVL': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Coalesce'>>, 'COLLATE': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Collate'>>, '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'>>, 'CONCAT': <function Parser.<lambda>>, 'CONCAT_WS': <function Parser.<lambda>>, 'CONNECT_BY_ROOT': <bound method Func.from_arg_list of <class 'sqlglot.expressions.ConnectByRoot'>>, 'CONVERT': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Convert'>>, 'CORR': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Corr'>>, 'COUNT': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Count'>>, 'COUNT_IF': <bound method Func.from_arg_list of <class 'sqlglot.expressions.CountIf'>>, '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'>>, 'CURRENT_DATE': <bound method Func.from_arg_list of <class 'sqlglot.expressions.CurrentDate'>>, 'CURRENT_DATETIME': <bound method Func.from_arg_list of <class 'sqlglot.expressions.CurrentDatetime'>>, 'CURRENT_TIME': <bound method Func.from_arg_list of <class 'sqlglot.expressions.CurrentTime'>>, 'CURRENT_TIMESTAMP': <bound method Func.from_arg_list of <class 'sqlglot.expressions.CurrentTimestamp'>>, 'CURRENT_USER': <bound method Func.from_arg_list of <class 'sqlglot.expressions.CurrentUser'>>, 'DATE': <function _build_date>, 'DATE_ADD': <function build_date_delta_with_interval.<locals>._builder>, '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_STR_TO_DATE': <bound method Func.from_arg_list of <class 'sqlglot.expressions.DateStrToDate'>>, 'DATE_SUB': <function build_date_delta_with_interval.<locals>._builder>, 'DATE_TO_DATE_STR': <function Parser.<lambda>>, 'DATE_TO_DI': <bound method Func.from_arg_list of <class 'sqlglot.expressions.DateToDi'>>, 'DATE_TRUNC': <function BigQuery.Parser.<lambda>>, 'DATETIME': <function _build_datetime>, 'DATETIME_ADD': <function build_date_delta_with_interval.<locals>._builder>, 'DATETIME_DIFF': <bound method Func.from_arg_list of <class 'sqlglot.expressions.DatetimeDiff'>>, 'DATETIME_SUB': <function build_date_delta_with_interval.<locals>._builder>, 'DATETIME_TRUNC': <bound method Func.from_arg_list of <class 'sqlglot.expressions.DatetimeTrunc'>>, 'DAY': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Day'>>, 'DAY_OF_MONTH': <bound method Func.from_arg_list of <class 'sqlglot.expressions.DayOfMonth'>>, 'DAYOFMONTH': <bound method Func.from_arg_list of <class 'sqlglot.expressions.DayOfMonth'>>, 'DAY_OF_WEEK': <bound method Func.from_arg_list of <class 'sqlglot.expressions.DayOfWeek'>>, 'DAYOFWEEK': <bound method Func.from_arg_list of <class 'sqlglot.expressions.DayOfWeek'>>, 'DAY_OF_YEAR': <bound method Func.from_arg_list of <class 'sqlglot.expressions.DayOfYear'>>, 'DAYOFYEAR': <bound method Func.from_arg_list of <class 'sqlglot.expressions.DayOfYear'>>, 'DECODE': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Decode'>>, 'DI_TO_DATE': <bound method Func.from_arg_list of <class 'sqlglot.expressions.DiToDate'>>, 'ENCODE': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Encode'>>, 'EXP': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Exp'>>, 'EXPLODE': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Explode'>>, 'EXPLODE_OUTER': <bound method Func.from_arg_list of <class 'sqlglot.expressions.ExplodeOuter'>>, 'EXTRACT': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Extract'>>, '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'>>, 'FLOOR': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Floor'>>, 'FROM_BASE': <bound method Func.from_arg_list of <class 'sqlglot.expressions.FromBase'>>, 'FROM_BASE64': <bound method Func.from_arg_list of <class 'sqlglot.expressions.FromBase64'>>, 'GAP_FILL': <bound method Func.from_arg_list of <class 'sqlglot.expressions.GapFill'>>, 'GENERATE_DATE_ARRAY': <bound method Func.from_arg_list of <class 'sqlglot.expressions.GenerateDateArray'>>, 'GENERATE_SERIES': <bound method Func.from_arg_list of <class 'sqlglot.expressions.GenerateSeries'>>, 'GREATEST': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Greatest'>>, 'GROUP_CONCAT': <bound method Func.from_arg_list of <class 'sqlglot.expressions.GroupConcat'>>, 'HEX': <function build_hex>, 'HLL': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Hll'>>, 'IF': <bound method Func.from_arg_list of <class 'sqlglot.expressions.If'>>, 'IIF': <bound method Func.from_arg_list of <class 'sqlglot.expressions.If'>>, 'INITCAP': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Initcap'>>, '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'>>, '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_CONTAINS': <bound method Func.from_arg_list of <class 'sqlglot.expressions.JSONArrayContains'>>, 'JSONB_CONTAINS': <bound method Func.from_arg_list of <class 'sqlglot.expressions.JSONBContains'>>, 'JSONB_EXTRACT': <bound method Func.from_arg_list of <class 'sqlglot.expressions.JSONBExtract'>>, 'JSONB_EXTRACT_SCALAR': <bound method Func.from_arg_list of <class 'sqlglot.expressions.JSONBExtractScalar'>>, 'JSON_EXTRACT': <function build_extract_json_with_path.<locals>._builder>, 'JSON_EXTRACT_SCALAR': <function BigQuery.Parser.<lambda>>, 'JSON_FORMAT': <bound method Func.from_arg_list of <class 'sqlglot.expressions.JSONFormat'>>, 'J_S_O_N_OBJECT': <bound method Func.from_arg_list of <class 'sqlglot.expressions.JSONObject'>>, 'J_S_O_N_OBJECT_AGG': <bound method Func.from_arg_list of <class 'sqlglot.expressions.JSONObjectAgg'>>, 'J_S_O_N_TABLE': <bound method Func.from_arg_list of <class 'sqlglot.expressions.JSONTable'>>, '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'>>, 'LEAD': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Lead'>>, 'LEAST': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Least'>>, 'LEFT': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Left'>>, 'LENGTH': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Length'>>, 'LEN': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Length'>>, 'LEVENSHTEIN': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Levenshtein'>>, 'LIST': <bound method Func.from_arg_list of <class 'sqlglot.expressions.List'>>, 'LN': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Ln'>>, '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.MD5Digest'>>, 'MD5_DIGEST': <bound method Func.from_arg_list of <class 'sqlglot.expressions.MD5Digest'>>, 'MAP': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Map'>>, 'MAP_FROM_ENTRIES': <bound method Func.from_arg_list of <class 'sqlglot.expressions.MapFromEntries'>>, 'MATCH_AGAINST': <bound method Func.from_arg_list of <class 'sqlglot.expressions.MatchAgainst'>>, 'MAX': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Max'>>, 'MIN': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Min'>>, 'MONTH': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Month'>>, 'MONTHS_BETWEEN': <bound method Func.from_arg_list of <class 'sqlglot.expressions.MonthsBetween'>>, 'NEXT_VALUE_FOR': <bound method Func.from_arg_list of <class 'sqlglot.expressions.NextValueFor'>>, 'NTH_VALUE': <bound method Func.from_arg_list of <class 'sqlglot.expressions.NthValue'>>, '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'>>, 'OPEN_J_S_O_N': <bound method Func.from_arg_list of <class 'sqlglot.expressions.OpenJSON'>>, 'PARAMETERIZED_AGG': <bound method Func.from_arg_list of <class 'sqlglot.expressions.ParameterizedAgg'>>, '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'>>, 'PERCENTILE_CONT': <bound method Func.from_arg_list of <class 'sqlglot.expressions.PercentileCont'>>, 'PERCENTILE_DISC': <bound method Func.from_arg_list of <class 'sqlglot.expressions.PercentileDisc'>>, 'POSEXPLODE': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Posexplode'>>, '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'>>, 'QUANTILE': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Quantile'>>, 'QUARTER': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Quarter'>>, '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'>>, 'RANGE_N': <bound method Func.from_arg_list of <class 'sqlglot.expressions.RangeN'>>, 'READ_CSV': <bound method Func.from_arg_list of <class 'sqlglot.expressions.ReadCSV'>>, 'REDUCE': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Reduce'>>, 'REGEXP_EXTRACT': <function BigQuery.Parser.<lambda>>, 'REGEXP_I_LIKE': <bound method Func.from_arg_list of <class 'sqlglot.expressions.RegexpILike'>>, 'REGEXP_LIKE': <bound method Func.from_arg_list of <class 'sqlglot.expressions.RegexpLike'>>, 'REGEXP_REPLACE': <bound method Func.from_arg_list of <class 'sqlglot.expressions.RegexpReplace'>>, 'REGEXP_SPLIT': <bound method Func.from_arg_list of <class 'sqlglot.expressions.RegexpSplit'>>, 'REPEAT': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Repeat'>>, 'RIGHT': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Right'>>, 'ROUND': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Round'>>, 'ROW_NUMBER': <bound method Func.from_arg_list of <class 'sqlglot.expressions.RowNumber'>>, 'SHA': <bound method Func.from_arg_list of <class 'sqlglot.expressions.SHA'>>, 'SHA1': <bound method Func.from_arg_list of <class 'sqlglot.expressions.SHA'>>, 'SHA2': <bound method Func.from_arg_list of <class 'sqlglot.expressions.SHA2'>>, 'SAFE_DIVIDE': <bound method Func.from_arg_list of <class 'sqlglot.expressions.SafeDivide'>>, 'SIGN': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Sign'>>, 'SIGNUM': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Sign'>>, 'SORT_ARRAY': <bound method Func.from_arg_list of <class 'sqlglot.expressions.SortArray'>>, 'SPLIT': <function BigQuery.Parser.<lambda>>, 'SQRT': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Sqrt'>>, 'STANDARD_HASH': <bound method Func.from_arg_list of <class 'sqlglot.expressions.StandardHash'>>, 'STAR_MAP': <bound method Func.from_arg_list of <class 'sqlglot.expressions.StarMap'>>, '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'>>, '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_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'>>, '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'>>, 'SUM': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Sum'>>, 'TIME': <function _build_time>, 'TIME_ADD': <function build_date_delta_with_interval.<locals>._builder>, '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_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': <function build_date_delta_with_interval.<locals>._builder>, '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': <function _build_timestamp>, 'TIMESTAMP_ADD': <function build_date_delta_with_interval.<locals>._builder>, '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_SUB': <function build_date_delta_with_interval.<locals>._builder>, 'TIMESTAMP_TRUNC': <bound method Func.from_arg_list of <class 'sqlglot.expressions.TimestampTrunc'>>, 'TO_ARRAY': <bound method Func.from_arg_list of <class 'sqlglot.expressions.ToArray'>>, 'TO_BASE64': <bound method Func.from_arg_list of <class 'sqlglot.expressions.ToBase64'>>, 'TO_CHAR': <bound method Func.from_arg_list of <class 'sqlglot.expressions.ToChar'>>, 'TO_DAYS': <bound method Func.from_arg_list of <class 'sqlglot.expressions.ToDays'>>, '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'>>, '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_CAST': <bound method Func.from_arg_list of <class 'sqlglot.expressions.TryCast'>>, 'TS_OR_DI_TO_DI': <bound method Func.from_arg_list of <class 'sqlglot.expressions.TsOrDiToDi'>>, 'TS_OR_DS_ADD': <bound method Func.from_arg_list of <class 'sqlglot.expressions.TsOrDsAdd'>>, 'TS_OR_DS_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_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'>>, 'UNHEX': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Unhex'>>, 'UNIX_DATE': <bound method Func.from_arg_list of <class 'sqlglot.expressions.UnixDate'>>, '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': <function Parser.<lambda>>, 'UPPER': <function build_upper>, 'UCASE': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Upper'>>, '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'>>, 'WEEK': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Week'>>, 'WEEK_OF_YEAR': <bound method Func.from_arg_list of <class 'sqlglot.expressions.WeekOfYear'>>, 'WEEKOFYEAR': <bound method Func.from_arg_list of <class 'sqlglot.expressions.WeekOfYear'>>, 'WHEN': <bound method Func.from_arg_list of <class 'sqlglot.expressions.When'>>, 'X_M_L_TABLE': <bound method Func.from_arg_list of <class 'sqlglot.expressions.XMLTable'>>, 'XOR': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Xor'>>, 'YEAR': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Year'>>, 'GLOB': <function Parser.<lambda>>, 'JSON_EXTRACT_PATH_TEXT': <function build_extract_json_with_path.<locals>._builder>, 'LIKE': <function build_like>, 'LOG2': <function Parser.<lambda>>, 'LOG10': <function Parser.<lambda>>, 'MOD': <function build_mod>, 'TO_HEX': <function _build_to_hex>, 'DIV': <function binary_from_function.<locals>.<lambda>>, 'FORMAT_DATE': <function BigQuery.Parser.<lambda>>, 'GENERATE_ARRAY': <bound method Func.from_arg_list of <class 'sqlglot.expressions.GenerateSeries'>>, 'PARSE_DATE': <function BigQuery.Parser.<lambda>>, 'PARSE_TIMESTAMP': <function _build_parse_timestamp>, 'REGEXP_CONTAINS': <bound method Func.from_arg_list of <class 'sqlglot.expressions.RegexpLike'>>, 'SHA256': <function BigQuery.Parser.<lambda>>, 'SHA512': <function BigQuery.Parser.<lambda>>, 'TIMESTAMP_MICROS': <function BigQuery.Parser.<lambda>>, 'TIMESTAMP_MILLIS': <function BigQuery.Parser.<lambda>>, 'TIMESTAMP_SECONDS': <function BigQuery.Parser.<lambda>>, 'TO_JSON_STRING': <bound method Func.from_arg_list of <class 'sqlglot.expressions.JSONFormat'>>}
FUNCTION_PARSERS = {'CAST': <function Parser.<lambda>>, 'CONVERT': <function Parser.<lambda>>, 'DECODE': <function Parser.<lambda>>, 'EXTRACT': <function Parser.<lambda>>, 'GAP_FILL': <function Parser.<lambda>>, 'JSON_OBJECT': <function Parser.<lambda>>, 'JSON_OBJECTAGG': <function Parser.<lambda>>, 'JSON_TABLE': <function Parser.<lambda>>, 'MATCH': <function Parser.<lambda>>, 'OPENJSON': <function Parser.<lambda>>, 'POSITION': <function Parser.<lambda>>, 'PREDICT': <function Parser.<lambda>>, 'SAFE_CAST': <function Parser.<lambda>>, 'STRING_AGG': <function Parser.<lambda>>, 'SUBSTRING': <function Parser.<lambda>>, 'TRY_CAST': <function Parser.<lambda>>, 'TRY_CONVERT': <function Parser.<lambda>>, 'ARRAY': <function BigQuery.Parser.<lambda>>}
NO_PAREN_FUNCTIONS = {<TokenType.CURRENT_DATE: 'CURRENT_DATE'>: <class 'sqlglot.expressions.CurrentDate'>, <TokenType.CURRENT_DATETIME: 'CURRENT_DATETIME'>: <class 'sqlglot.expressions.CurrentDatetime'>, <TokenType.CURRENT_TIME: 'CURRENT_TIME'>: <class 'sqlglot.expressions.CurrentTime'>, <TokenType.CURRENT_TIMESTAMP: 'CURRENT_TIMESTAMP'>: <class 'sqlglot.expressions.CurrentTimestamp'>, <TokenType.CURRENT_USER: 'CURRENT_USER'>: <class 'sqlglot.expressions.CurrentUser'>}
NESTED_TYPE_TOKENS = {<TokenType.MAP: 'MAP'>, <TokenType.ARRAY: 'ARRAY'>, <TokenType.OBJECT: 'OBJECT'>, <TokenType.NESTED: 'NESTED'>, <TokenType.NULLABLE: 'NULLABLE'>, <TokenType.LOWCARDINALITY: 'LOWCARDINALITY'>, <TokenType.TABLE: 'TABLE'>, <TokenType.LIST: 'LIST'>, <TokenType.STRUCT: 'STRUCT'>}
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>>, 'DISTKEY': <function Parser.<lambda>>, 'DISTSTYLE': <function Parser.<lambda>>, 'ENGINE': <function Parser.<lambda>>, 'EXECUTE': <function Parser.<lambda>>, 'EXTERNAL': <function Parser.<lambda>>, 'FALLBACK': <function Parser.<lambda>>, 'FORMAT': <function Parser.<lambda>>, 'FREESPACE': <function Parser.<lambda>>, 'GLOBAL': <function Parser.<lambda>>, 'HEAP': <function Parser.<lambda>>, 'ICEBERG': <function Parser.<lambda>>, 'IMMUTABLE': <function Parser.<lambda>>, 'INHERITS': <function Parser.<lambda>>, 'INPUT': <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>>, 'ROW': <function Parser.<lambda>>, 'ROW_FORMAT': <function Parser.<lambda>>, 'SAMPLE': <function Parser.<lambda>>, 'SECURE': <function Parser.<lambda>>, 'SET': <function 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>>, 'NOT DETERMINISTIC': <function BigQuery.Parser.<lambda>>, 'OPTIONS': <function BigQuery.Parser.<lambda>>}
CONSTRAINT_PARSERS = {'AUTOINCREMENT': <function Parser.<lambda>>, 'AUTO_INCREMENT': <function Parser.<lambda>>, 'CASESPECIFIC': <function Parser.<lambda>>, 'CHARACTER SET': <function Parser.<lambda>>, 'CHECK': <function Parser.<lambda>>, 'COLLATE': <function Parser.<lambda>>, 'COMMENT': <function Parser.<lambda>>, 'COMPRESS': <function Parser.<lambda>>, 'CLUSTERED': <function Parser.<lambda>>, 'NONCLUSTERED': <function Parser.<lambda>>, 'DEFAULT': <function Parser.<lambda>>, 'ENCODE': <function Parser.<lambda>>, 'EPHEMERAL': <function Parser.<lambda>>, 'EXCLUDE': <function Parser.<lambda>>, 'FOREIGN KEY': <function Parser.<lambda>>, 'FORMAT': <function Parser.<lambda>>, 'GENERATED': <function Parser.<lambda>>, 'IDENTITY': <function Parser.<lambda>>, 'INLINE': <function Parser.<lambda>>, 'LIKE': <function Parser.<lambda>>, 'NOT': <function Parser.<lambda>>, 'NULL': <function Parser.<lambda>>, 'ON': <function Parser.<lambda>>, 'PATH': <function Parser.<lambda>>, 'PERIOD': <function Parser.<lambda>>, 'PRIMARY KEY': <function Parser.<lambda>>, 'REFERENCES': <function Parser.<lambda>>, 'TITLE': <function Parser.<lambda>>, 'TTL': <function Parser.<lambda>>, 'UNIQUE': <function Parser.<lambda>>, 'UPPERCASE': <function Parser.<lambda>>, 'WITH': <function Parser.<lambda>>, 'OPTIONS': <function BigQuery.Parser.<lambda>>}
RANGE_PARSERS = {<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.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>>}
NULL_TOKENS = {<TokenType.UNKNOWN: 'UNKNOWN'>, <TokenType.NULL: 'NULL'>}
STATEMENT_PARSERS = {<TokenType.ALTER: 'ALTER'>: <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.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.UPDATE: 'UPDATE'>: <function Parser.<lambda>>, <TokenType.USE: 'USE'>: <function Parser.<lambda>>, <TokenType.SEMICOLON: 'SEMICOLON'>: <function Parser.<lambda>>, <TokenType.ELSE: 'ELSE'>: <function BigQuery.Parser.<lambda>>, <TokenType.END: 'END'>: <function BigQuery.Parser.<lambda>>, <TokenType.FOR: 'FOR'>: <function BigQuery.Parser.<lambda>>}
BRACKET_OFFSETS = {'OFFSET': (0, False), 'ORDINAL': (1, False), 'SAFE_OFFSET': (0, True), 'SAFE_ORDINAL': (1, True)}
ID_VAR_TOKENS = {<TokenType.SERIAL: 'SERIAL'>, <TokenType.TSMULTIRANGE: 'TSMULTIRANGE'>, <TokenType.MAP: 'MAP'>, <TokenType.GEOGRAPHY: 'GEOGRAPHY'>, <TokenType.COMMIT: 'COMMIT'>, <TokenType.NESTED: 'NESTED'>, <TokenType.CURRENT_USER: 'CURRENT_USER'>, <TokenType.DICTIONARY: 'DICTIONARY'>, <TokenType.SMALLINT: 'SMALLINT'>, <TokenType.TABLE: 'TABLE'>, <TokenType.LOAD: 'LOAD'>, <TokenType.EXISTS: 'EXISTS'>, <TokenType.ESCAPE: 'ESCAPE'>, <TokenType.TDIGEST: 'TDIGEST'>, <TokenType.SIMPLEAGGREGATEFUNCTION: 'SIMPLEAGGREGATEFUNCTION'>, <TokenType.DECIMAL: 'DECIMAL'>, <TokenType.INT4MULTIRANGE: 'INT4MULTIRANGE'>, <TokenType.BIT: 'BIT'>, <TokenType.OBJECT_IDENTIFIER: 'OBJECT_IDENTIFIER'>, <TokenType.DATE32: 'DATE32'>, <TokenType.CURRENT_TIME: 'CURRENT_TIME'>, <TokenType.TIME: 'TIME'>, <TokenType.CURRENT_TIMESTAMP: 'CURRENT_TIMESTAMP'>, <TokenType.SMALLSERIAL: 'SMALLSERIAL'>, <TokenType.COMMAND: 'COMMAND'>, <TokenType.TINYBLOB: 'TINYBLOB'>, <TokenType.SUPER: 'SUPER'>, <TokenType.PERCENT: 'PERCENT'>, <TokenType.USMALLINT: 'USMALLINT'>, <TokenType.TRUNCATE: 'TRUNCATE'>, <TokenType.NCHAR: 'NCHAR'>, <TokenType.HLLSKETCH: 'HLLSKETCH'>, <TokenType.CONSTRAINT: 'CONSTRAINT'>, <TokenType.CACHE: 'CACHE'>, <TokenType.BIGSERIAL: 'BIGSERIAL'>, <TokenType.OFFSET: 'OFFSET'>, <TokenType.VIEW: 'VIEW'>, <TokenType.FALSE: 'FALSE'>, <TokenType.WINDOW: 'WINDOW'>, <TokenType.FIRST: 'FIRST'>, <TokenType.JSONB: 'JSONB'>, <TokenType.NULL: 'NULL'>, <TokenType.UINT: 'UINT'>, <TokenType.INET: 'INET'>, <TokenType.UNIQUE: 'UNIQUE'>, <TokenType.SCHEMA: 'SCHEMA'>, <TokenType.DESCRIBE: 'DESCRIBE'>, <TokenType.FILTER: 'FILTER'>, <TokenType.NULLABLE: 'NULLABLE'>, <TokenType.DATETIME: 'DATETIME'>, <TokenType.VARIANT: 'VARIANT'>, <TokenType.USE: 'USE'>, <TokenType.FIXEDSTRING: 'FIXEDSTRING'>, <TokenType.INT: 'INT'>, <TokenType.IPV6: 'IPV6'>, <TokenType.FLOAT: 'FLOAT'>, <TokenType.STORAGE_INTEGRATION: 'STORAGE_INTEGRATION'>, <TokenType.CASE: 'CASE'>, <TokenType.INT8RANGE: 'INT8RANGE'>, <TokenType.DESC: 'DESC'>, <TokenType.CURRENT_DATETIME: 'CURRENT_DATETIME'>, <TokenType.BEGIN: 'BEGIN'>, <TokenType.INT8MULTIRANGE: 'INT8MULTIRANGE'>, <TokenType.KILL: 'KILL'>, <TokenType.TSRANGE: 'TSRANGE'>, <TokenType.IPPREFIX: 'IPPREFIX'>, <TokenType.TINYINT: 'TINYINT'>, <TokenType.STRUCT: 'STRUCT'>, <TokenType.OPERATOR: 'OPERATOR'>, <TokenType.FINAL: 'FINAL'>, <TokenType.REPLACE: 'REPLACE'>, <TokenType.ENUM8: 'ENUM8'>, <TokenType.INT4RANGE: 'INT4RANGE'>, <TokenType.BOOLEAN: 'BOOLEAN'>, <TokenType.DELETE: 'DELETE'>, <TokenType.VAR: 'VAR'>, <TokenType.NVARCHAR: 'NVARCHAR'>, <TokenType.TEXT: 'TEXT'>, <TokenType.TIMESTAMP_NS: 'TIMESTAMP_NS'>, <TokenType.UPDATE: 'UPDATE'>, <TokenType.BIGDECIMAL: 'BIGDECIMAL'>, <TokenType.ROW: 'ROW'>, <TokenType.NAME: 'NAME'>, <TokenType.UINT128: 'UINT128'>, <TokenType.UNIQUEIDENTIFIER: 'UNIQUEIDENTIFIER'>, <TokenType.TRUE: 'TRUE'>, <TokenType.PRAGMA: 'PRAGMA'>, <TokenType.WAREHOUSE: 'WAREHOUSE'>, <TokenType.NUMMULTIRANGE: 'NUMMULTIRANGE'>, <TokenType.JSON: 'JSON'>, <TokenType.OVERLAPS: 'OVERLAPS'>, <TokenType.ALL: 'ALL'>, <TokenType.TIMETZ: 'TIMETZ'>, <TokenType.MEDIUMTEXT: 'MEDIUMTEXT'>, <TokenType.UDECIMAL: 'UDECIMAL'>, <TokenType.ROWS: 'ROWS'>, <TokenType.XML: 'XML'>, <TokenType.UBIGINT: 'UBIGINT'>, <TokenType.PSEUDO_TYPE: 'PSEUDO_TYPE'>, <TokenType.NEXT: 'NEXT'>, <TokenType.UNKNOWN: 'UNKNOWN'>, <TokenType.ROWVERSION: 'ROWVERSION'>, <TokenType.ANY: 'ANY'>, <TokenType.MONEY: 'MONEY'>, <TokenType.TIMESTAMP_MS: 'TIMESTAMP_MS'>, <TokenType.OVERWRITE: 'OVERWRITE'>, <TokenType.OBJECT: 'OBJECT'>, <TokenType.LONGTEXT: 'LONGTEXT'>, <TokenType.UINT256: 'UINT256'>, <TokenType.REFRESH: 'REFRESH'>, <TokenType.LIST: 'LIST'>, <TokenType.STREAMLIT: 'STREAMLIT'>, <TokenType.VARCHAR: 'VARCHAR'>, <TokenType.DATE: 'DATE'>, <TokenType.INT256: 'INT256'>, <TokenType.PIVOT: 'PIVOT'>, <TokenType.TIMESTAMPTZ: 'TIMESTAMPTZ'>, <TokenType.TOP: 'TOP'>, <TokenType.LOWCARDINALITY: 'LOWCARDINALITY'>, <TokenType.CURRENT_DATE: 'CURRENT_DATE'>, <TokenType.SEQUENCE: 'SEQUENCE'>, <TokenType.PROCEDURE: 'PROCEDURE'>, <TokenType.FOREIGN_KEY: 'FOREIGN_KEY'>, <TokenType.ENUM: 'ENUM'>, <TokenType.IDENTIFIER: 'IDENTIFIER'>, <TokenType.FULL: 'FULL'>, <TokenType.MEDIUMINT: 'MEDIUMINT'>, <TokenType.IPADDRESS: 'IPADDRESS'>, <TokenType.ANTI: 'ANTI'>, <TokenType.COPY: 'COPY'>, <TokenType.DATEMULTIRANGE: 'DATEMULTIRANGE'>, <TokenType.VARBINARY: 'VARBINARY'>, <TokenType.YEAR: 'YEAR'>, <TokenType.TSTZRANGE: 'TSTZRANGE'>, <TokenType.DIV: 'DIV'>, <TokenType.FUNCTION: 'FUNCTION'>, <TokenType.COLLATE: 'COLLATE'>, <TokenType.ENUM16: 'ENUM16'>, <TokenType.RANGE: 'RANGE'>, <TokenType.INT128: 'INT128'>, <TokenType.UTINYINT: 'UTINYINT'>, <TokenType.AUTO_INCREMENT: 'AUTO_INCREMENT'>, <TokenType.ASC: 'ASC'>, <TokenType.ROLLUP: 'ROLLUP'>, <TokenType.DATERANGE: 'DATERANGE'>, <TokenType.EXECUTE: 'EXECUTE'>, <TokenType.ASOF: 'ASOF'>, <TokenType.DATABASE: 'DATABASE'>, <TokenType.REFERENCES: 'REFERENCES'>, <TokenType.TSTZMULTIRANGE: 'TSTZMULTIRANGE'>, <TokenType.TIMESTAMPNTZ: 'TIMESTAMPNTZ'>, <TokenType.UNNEST: 'UNNEST'>, <TokenType.DOUBLE: 'DOUBLE'>, <TokenType.TINYTEXT: 'TINYTEXT'>, <TokenType.MERGE: 'MERGE'>, <TokenType.TIMESTAMP_S: 'TIMESTAMP_S'>, <TokenType.USERDEFINED: 'USERDEFINED'>, <TokenType.SEMI: 'SEMI'>, <TokenType.IMAGE: 'IMAGE'>, <TokenType.RIGHT: 'RIGHT'>, <TokenType.COMMENT: 'COMMENT'>, <TokenType.KEEP: 'KEEP'>, <TokenType.HSTORE: 'HSTORE'>, <TokenType.AGGREGATEFUNCTION: 'AGGREGATEFUNCTION'>, <TokenType.NATURAL: 'NATURAL'>, <TokenType.TAG: 'TAG'>, <TokenType.SOME: 'SOME'>, <TokenType.LONGBLOB: 'LONGBLOB'>, <TokenType.MODEL: 'MODEL'>, <TokenType.GEOMETRY: 'GEOMETRY'>, <TokenType.BIGINT: 'BIGINT'>, <TokenType.TIMESTAMP: 'TIMESTAMP'>, <TokenType.SMALLMONEY: 'SMALLMONEY'>, <TokenType.IPV4: 'IPV4'>, <TokenType.RECURSIVE: 'RECURSIVE'>, <TokenType.PARTITION: 'PARTITION'>, <TokenType.APPLY: 'APPLY'>, <TokenType.BINARY: 'BINARY'>, <TokenType.ISNULL: 'ISNULL'>, <TokenType.SHOW: 'SHOW'>, <TokenType.UNPIVOT: 'UNPIVOT'>, <TokenType.SET: 'SET'>, <TokenType.STRAIGHT_JOIN: 'STRAIGHT_JOIN'>, <TokenType.BPCHAR: 'BPCHAR'>, <TokenType.NUMRANGE: 'NUMRANGE'>, <TokenType.MEDIUMBLOB: 'MEDIUMBLOB'>, <TokenType.COLUMN: 'COLUMN'>, <TokenType.END: 'END'>, <TokenType.CHAR: 'CHAR'>, <TokenType.FORMAT: 'FORMAT'>, <TokenType.LEFT: 'LEFT'>, <TokenType.ORDINALITY: 'ORDINALITY'>, <TokenType.INDEX: 'INDEX'>, <TokenType.INTERVAL: 'INTERVAL'>, <TokenType.ARRAY: 'ARRAY'>, <TokenType.UUID: 'UUID'>, <TokenType.DEFAULT: 'DEFAULT'>, <TokenType.TIMESTAMPLTZ: 'TIMESTAMPLTZ'>, <TokenType.DATETIME64: 'DATETIME64'>, <TokenType.IS: 'IS'>, <TokenType.TEMPORARY: 'TEMPORARY'>, <TokenType.VOLATILE: 'VOLATILE'>, <TokenType.SETTINGS: 'SETTINGS'>, <TokenType.UMEDIUMINT: 'UMEDIUMINT'>}
TABLE_ALIAS_TOKENS = {<TokenType.SERIAL: 'SERIAL'>, <TokenType.TSMULTIRANGE: 'TSMULTIRANGE'>, <TokenType.MAP: 'MAP'>, <TokenType.GEOGRAPHY: 'GEOGRAPHY'>, <TokenType.COMMIT: 'COMMIT'>, <TokenType.NESTED: 'NESTED'>, <TokenType.CURRENT_USER: 'CURRENT_USER'>, <TokenType.DICTIONARY: 'DICTIONARY'>, <TokenType.SMALLINT: 'SMALLINT'>, <TokenType.TABLE: 'TABLE'>, <TokenType.LOAD: 'LOAD'>, <TokenType.EXISTS: 'EXISTS'>, <TokenType.ESCAPE: 'ESCAPE'>, <TokenType.TDIGEST: 'TDIGEST'>, <TokenType.SIMPLEAGGREGATEFUNCTION: 'SIMPLEAGGREGATEFUNCTION'>, <TokenType.DECIMAL: 'DECIMAL'>, <TokenType.INT4MULTIRANGE: 'INT4MULTIRANGE'>, <TokenType.BIT: 'BIT'>, <TokenType.OBJECT_IDENTIFIER: 'OBJECT_IDENTIFIER'>, <TokenType.DATE32: 'DATE32'>, <TokenType.CURRENT_TIME: 'CURRENT_TIME'>, <TokenType.TIME: 'TIME'>, <TokenType.CURRENT_TIMESTAMP: 'CURRENT_TIMESTAMP'>, <TokenType.SMALLSERIAL: 'SMALLSERIAL'>, <TokenType.COMMAND: 'COMMAND'>, <TokenType.TINYBLOB: 'TINYBLOB'>, <TokenType.SUPER: 'SUPER'>, <TokenType.PERCENT: 'PERCENT'>, <TokenType.USMALLINT: 'USMALLINT'>, <TokenType.TRUNCATE: 'TRUNCATE'>, <TokenType.NCHAR: 'NCHAR'>, <TokenType.HLLSKETCH: 'HLLSKETCH'>, <TokenType.CONSTRAINT: 'CONSTRAINT'>, <TokenType.CACHE: 'CACHE'>, <TokenType.BIGSERIAL: 'BIGSERIAL'>, <TokenType.VIEW: 'VIEW'>, <TokenType.FALSE: 'FALSE'>, <TokenType.JSONB: 'JSONB'>, <TokenType.FIRST: 'FIRST'>, <TokenType.NULL: 'NULL'>, <TokenType.UINT: 'UINT'>, <TokenType.INET: 'INET'>, <TokenType.UNIQUE: 'UNIQUE'>, <TokenType.SCHEMA: 'SCHEMA'>, <TokenType.DESCRIBE: 'DESCRIBE'>, <TokenType.FILTER: 'FILTER'>, <TokenType.NULLABLE: 'NULLABLE'>, <TokenType.DATETIME: 'DATETIME'>, <TokenType.VARIANT: 'VARIANT'>, <TokenType.USE: 'USE'>, <TokenType.FIXEDSTRING: 'FIXEDSTRING'>, <TokenType.INT: 'INT'>, <TokenType.IPV6: 'IPV6'>, <TokenType.FLOAT: 'FLOAT'>, <TokenType.STORAGE_INTEGRATION: 'STORAGE_INTEGRATION'>, <TokenType.CASE: 'CASE'>, <TokenType.INT8RANGE: 'INT8RANGE'>, <TokenType.DESC: 'DESC'>, <TokenType.CURRENT_DATETIME: 'CURRENT_DATETIME'>, <TokenType.BEGIN: 'BEGIN'>, <TokenType.INT8MULTIRANGE: 'INT8MULTIRANGE'>, <TokenType.KILL: 'KILL'>, <TokenType.TSRANGE: 'TSRANGE'>, <TokenType.IPPREFIX: 'IPPREFIX'>, <TokenType.TINYINT: 'TINYINT'>, <TokenType.STRUCT: 'STRUCT'>, <TokenType.OPERATOR: 'OPERATOR'>, <TokenType.FINAL: 'FINAL'>, <TokenType.REPLACE: 'REPLACE'>, <TokenType.ENUM8: 'ENUM8'>, <TokenType.INT4RANGE: 'INT4RANGE'>, <TokenType.BOOLEAN: 'BOOLEAN'>, <TokenType.DELETE: 'DELETE'>, <TokenType.VAR: 'VAR'>, <TokenType.NVARCHAR: 'NVARCHAR'>, <TokenType.TEXT: 'TEXT'>, <TokenType.TIMESTAMP_NS: 'TIMESTAMP_NS'>, <TokenType.UPDATE: 'UPDATE'>, <TokenType.BIGDECIMAL: 'BIGDECIMAL'>, <TokenType.ROW: 'ROW'>, <TokenType.NAME: 'NAME'>, <TokenType.UINT128: 'UINT128'>, <TokenType.UNIQUEIDENTIFIER: 'UNIQUEIDENTIFIER'>, <TokenType.TRUE: 'TRUE'>, <TokenType.PRAGMA: 'PRAGMA'>, <TokenType.WAREHOUSE: 'WAREHOUSE'>, <TokenType.NUMMULTIRANGE: 'NUMMULTIRANGE'>, <TokenType.JSON: 'JSON'>, <TokenType.OVERLAPS: 'OVERLAPS'>, <TokenType.ALL: 'ALL'>, <TokenType.TIMETZ: 'TIMETZ'>, <TokenType.MEDIUMTEXT: 'MEDIUMTEXT'>, <TokenType.UDECIMAL: 'UDECIMAL'>, <TokenType.ROWS: 'ROWS'>, <TokenType.XML: 'XML'>, <TokenType.UBIGINT: 'UBIGINT'>, <TokenType.PSEUDO_TYPE: 'PSEUDO_TYPE'>, <TokenType.NEXT: 'NEXT'>, <TokenType.UNKNOWN: 'UNKNOWN'>, <TokenType.ROWVERSION: 'ROWVERSION'>, <TokenType.ANY: 'ANY'>, <TokenType.MONEY: 'MONEY'>, <TokenType.TIMESTAMP_MS: 'TIMESTAMP_MS'>, <TokenType.OVERWRITE: 'OVERWRITE'>, <TokenType.OBJECT: 'OBJECT'>, <TokenType.LONGTEXT: 'LONGTEXT'>, <TokenType.UINT256: 'UINT256'>, <TokenType.REFRESH: 'REFRESH'>, <TokenType.LIST: 'LIST'>, <TokenType.STREAMLIT: 'STREAMLIT'>, <TokenType.VARCHAR: 'VARCHAR'>, <TokenType.INT256: 'INT256'>, <TokenType.PIVOT: 'PIVOT'>, <TokenType.TIMESTAMPTZ: 'TIMESTAMPTZ'>, <TokenType.TOP: 'TOP'>, <TokenType.LOWCARDINALITY: 'LOWCARDINALITY'>, <TokenType.CURRENT_DATE: 'CURRENT_DATE'>, <TokenType.SEQUENCE: 'SEQUENCE'>, <TokenType.PROCEDURE: 'PROCEDURE'>, <TokenType.FOREIGN_KEY: 'FOREIGN_KEY'>, <TokenType.ENUM: 'ENUM'>, <TokenType.IDENTIFIER: 'IDENTIFIER'>, <TokenType.MEDIUMINT: 'MEDIUMINT'>, <TokenType.IPADDRESS: 'IPADDRESS'>, <TokenType.ANTI: 'ANTI'>, <TokenType.COPY: 'COPY'>, <TokenType.DATEMULTIRANGE: 'DATEMULTIRANGE'>, <TokenType.VARBINARY: 'VARBINARY'>, <TokenType.YEAR: 'YEAR'>, <TokenType.TSTZRANGE: 'TSTZRANGE'>, <TokenType.DIV: 'DIV'>, <TokenType.FUNCTION: 'FUNCTION'>, <TokenType.COLLATE: 'COLLATE'>, <TokenType.ENUM16: 'ENUM16'>, <TokenType.RANGE: 'RANGE'>, <TokenType.INT128: 'INT128'>, <TokenType.UTINYINT: 'UTINYINT'>, <TokenType.AUTO_INCREMENT: 'AUTO_INCREMENT'>, <TokenType.ASC: 'ASC'>, <TokenType.ROLLUP: 'ROLLUP'>, <TokenType.DATERANGE: 'DATERANGE'>, <TokenType.EXECUTE: 'EXECUTE'>, <TokenType.DATABASE: 'DATABASE'>, <TokenType.REFERENCES: 'REFERENCES'>, <TokenType.TSTZMULTIRANGE: 'TSTZMULTIRANGE'>, <TokenType.TIMESTAMPNTZ: 'TIMESTAMPNTZ'>, <TokenType.UNNEST: 'UNNEST'>, <TokenType.DOUBLE: 'DOUBLE'>, <TokenType.TINYTEXT: 'TINYTEXT'>, <TokenType.MERGE: 'MERGE'>, <TokenType.TIMESTAMP_S: 'TIMESTAMP_S'>, <TokenType.USERDEFINED: 'USERDEFINED'>, <TokenType.SEMI: 'SEMI'>, <TokenType.IMAGE: 'IMAGE'>, <TokenType.COMMENT: 'COMMENT'>, <TokenType.KEEP: 'KEEP'>, <TokenType.HSTORE: 'HSTORE'>, <TokenType.AGGREGATEFUNCTION: 'AGGREGATEFUNCTION'>, <TokenType.TAG: 'TAG'>, <TokenType.SOME: 'SOME'>, <TokenType.LONGBLOB: 'LONGBLOB'>, <TokenType.MODEL: 'MODEL'>, <TokenType.GEOMETRY: 'GEOMETRY'>, <TokenType.BIGINT: 'BIGINT'>, <TokenType.TIMESTAMP: 'TIMESTAMP'>, <TokenType.SMALLMONEY: 'SMALLMONEY'>, <TokenType.IPV4: 'IPV4'>, <TokenType.RECURSIVE: 'RECURSIVE'>, <TokenType.PARTITION: 'PARTITION'>, <TokenType.BINARY: 'BINARY'>, <TokenType.ISNULL: 'ISNULL'>, <TokenType.SHOW: 'SHOW'>, <TokenType.UNPIVOT: 'UNPIVOT'>, <TokenType.SET: 'SET'>, <TokenType.STRAIGHT_JOIN: 'STRAIGHT_JOIN'>, <TokenType.BPCHAR: 'BPCHAR'>, <TokenType.NUMRANGE: 'NUMRANGE'>, <TokenType.MEDIUMBLOB: 'MEDIUMBLOB'>, <TokenType.COLUMN: 'COLUMN'>, <TokenType.VOLATILE: 'VOLATILE'>, <TokenType.END: 'END'>, <TokenType.CHAR: 'CHAR'>, <TokenType.FORMAT: 'FORMAT'>, <TokenType.ORDINALITY: 'ORDINALITY'>, <TokenType.INDEX: 'INDEX'>, <TokenType.INTERVAL: 'INTERVAL'>, <TokenType.ARRAY: 'ARRAY'>, <TokenType.UUID: 'UUID'>, <TokenType.DEFAULT: 'DEFAULT'>, <TokenType.TIMESTAMPLTZ: 'TIMESTAMPLTZ'>, <TokenType.DATETIME64: 'DATETIME64'>, <TokenType.IS: 'IS'>, <TokenType.TEMPORARY: 'TEMPORARY'>, <TokenType.DATE: 'DATE'>, <TokenType.SETTINGS: 'SETTINGS'>, <TokenType.UMEDIUMINT: 'UMEDIUMINT'>}
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
  ENUM_TYPE_TOKENS
  AGGREGATE_TYPE_TOKENS
  TYPE_TOKENS
  SIGNED_TO_UNSIGNED_TYPE_TOKEN
  SUBQUERY_PREDICATES
  RESERVED_TOKENS
  DB_CREATABLES
  CREATABLES
  INTERVAL_VARS
  ALIAS_TOKENS
  ARRAY_CONSTRUCTORS
  COMMENT_TABLE_ALIAS_TOKENS
  UPDATE_ALIAS_TOKENS
  TRIM_TYPES
  FUNC_TOKENS
  CONJUNCTION
  ASSIGNMENT
  DISJUNCTION
  EQUALITY
  COMPARISON
  BITWISE
  TERM
  FACTOR
  EXPONENT
  TIMES
  TIMESTAMPS
  SET_OPERATIONS
  JOIN_METHODS
  JOIN_SIDES
  JOIN_KINDS
  JOIN_HINTS
  LAMBDAS
  COLUMN_OPERATORS
  EXPRESSION_PARSERS
  UNARY_PARSERS
  STRING_PARSERS
  NUMERIC_PARSERS
  PRIMARY_PARSERS
  PLACEHOLDER_PARSERS
  ALTER_PARSERS
  ALTER_ALTER_PARSERS
  SCHEMA_UNNAMED_CONSTRAINTS
  NO_PAREN_FUNCTION_PARSERS
  INVALID_FUNC_NAME_TOKENS
  FUNCTIONS_WITH_ALIASED_ARGS
  KEY_VALUE_DEFINITIONS
  QUERY_MODIFIER_PARSERS
  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
  INSERT_ALTERNATIVES
  CLONE_KEYWORDS
  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
  STRICT_CAST
  IDENTIFY_PIVOT_STRINGS
  ALTER_TABLE_ADD_REQUIRED_FOR_EACH_COLUMN
  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
  JSON_ARROWS_REQUIRE_JSON_TYPE
  COLON_IS_JSON_EXTRACT
  VALUES_FOLLOWED_BY_PAREN
  INTERVAL_SPANS
  SUPPORTS_PARTITION_SELECTION
  error_level
  error_message_context
  max_errors
  dialect
  reset
  parse
  parse_into
  check_errors
  raise_error
  expression
  validate_expression
  errors
  sql

class BigQuery.Generator(sqlglot.generator.Generator): View Source

    564    class Generator(generator.Generator):
    565        EXPLICIT_SET_OP = True
    566        INTERVAL_ALLOWS_PLURAL_FORM = False
    567        JOIN_HINTS = False
    568        QUERY_HINTS = False
    569        TABLE_HINTS = False
    570        LIMIT_FETCH = "LIMIT"
    571        RENAME_TABLE_WITH_DB = False
    572        NVL2_SUPPORTED = False
    573        UNNEST_WITH_ORDINALITY = False
    574        COLLATE_IS_FUNC = True
    575        LIMIT_ONLY_LITERALS = True
    576        SUPPORTS_TABLE_ALIAS_COLUMNS = False
    577        UNPIVOT_ALIASES_ARE_IDENTIFIERS = False
    578        JSON_KEY_VALUE_PAIR_SEP = ","
    579        NULL_ORDERING_SUPPORTED = False
    580        IGNORE_NULLS_IN_FUNC = True
    581        JSON_PATH_SINGLE_QUOTE_ESCAPE = True
    582        CAN_IMPLEMENT_ARRAY_ANY = True
    583        SUPPORTS_TO_NUMBER = False
    584        NAMED_PLACEHOLDER_TOKEN = "@"
    585        HEX_FUNC = "TO_HEX"
    586        WITH_PROPERTIES_PREFIX = "OPTIONS"
    587
    588        TRANSFORMS = {
    589            **generator.Generator.TRANSFORMS,
    590            exp.ApproxDistinct: rename_func("APPROX_COUNT_DISTINCT"),
    591            exp.ArgMax: arg_max_or_min_no_count("MAX_BY"),
    592            exp.ArgMin: arg_max_or_min_no_count("MIN_BY"),
    593            exp.Array: inline_array_unless_query,
    594            exp.ArrayContains: _array_contains_sql,
    595            exp.ArrayFilter: filter_array_using_unnest,
    596            exp.ArraySize: rename_func("ARRAY_LENGTH"),
    597            exp.Cast: transforms.preprocess([transforms.remove_precision_parameterized_types]),
    598            exp.CollateProperty: lambda self, e: (
    599                f"DEFAULT COLLATE {self.sql(e, 'this')}"
    600                if e.args.get("default")
    601                else f"COLLATE {self.sql(e, 'this')}"
    602            ),
    603            exp.Commit: lambda *_: "COMMIT TRANSACTION",
    604            exp.CountIf: rename_func("COUNTIF"),
    605            exp.Create: _create_sql,
    606            exp.CTE: transforms.preprocess([_pushdown_cte_column_names]),
    607            exp.DateAdd: date_add_interval_sql("DATE", "ADD"),
    608            exp.DateDiff: lambda self, e: self.func(
    609                "DATE_DIFF", e.this, e.expression, unit_to_var(e)
    610            ),
    611            exp.DateFromParts: rename_func("DATE"),
    612            exp.DateStrToDate: datestrtodate_sql,
    613            exp.DateSub: date_add_interval_sql("DATE", "SUB"),
    614            exp.DatetimeAdd: date_add_interval_sql("DATETIME", "ADD"),
    615            exp.DatetimeSub: date_add_interval_sql("DATETIME", "SUB"),
    616            exp.DateTrunc: lambda self, e: self.func("DATE_TRUNC", e.this, e.text("unit")),
    617            exp.FromTimeZone: lambda self, e: self.func(
    618                "DATETIME", self.func("TIMESTAMP", e.this, e.args.get("zone")), "'UTC'"
    619            ),
    620            exp.GenerateSeries: rename_func("GENERATE_ARRAY"),
    621            exp.GroupConcat: rename_func("STRING_AGG"),
    622            exp.Hex: lambda self, e: self.func("UPPER", self.func("TO_HEX", self.sql(e, "this"))),
    623            exp.If: if_sql(false_value="NULL"),
    624            exp.ILike: no_ilike_sql,
    625            exp.IntDiv: rename_func("DIV"),
    626            exp.JSONFormat: rename_func("TO_JSON_STRING"),
    627            exp.Max: max_or_greatest,
    628            exp.MD5: lambda self, e: self.func("TO_HEX", self.func("MD5", e.this)),
    629            exp.MD5Digest: rename_func("MD5"),
    630            exp.Min: min_or_least,
    631            exp.PartitionedByProperty: lambda self, e: f"PARTITION BY {self.sql(e, 'this')}",
    632            exp.RegexpExtract: lambda self, e: self.func(
    633                "REGEXP_EXTRACT",
    634                e.this,
    635                e.expression,
    636                e.args.get("position"),
    637                e.args.get("occurrence"),
    638            ),
    639            exp.RegexpReplace: regexp_replace_sql,
    640            exp.RegexpLike: rename_func("REGEXP_CONTAINS"),
    641            exp.ReturnsProperty: _returnsproperty_sql,
    642            exp.Rollback: lambda *_: "ROLLBACK TRANSACTION",
    643            exp.Select: transforms.preprocess(
    644                [
    645                    transforms.explode_to_unnest(),
    646                    transforms.unqualify_unnest,
    647                    transforms.eliminate_distinct_on,
    648                    _alias_ordered_group,
    649                    transforms.eliminate_semi_and_anti_joins,
    650                ]
    651            ),
    652            exp.SHA: rename_func("SHA1"),
    653            exp.SHA2: sha256_sql,
    654            exp.StabilityProperty: lambda self, e: (
    655                "DETERMINISTIC" if e.name == "IMMUTABLE" else "NOT DETERMINISTIC"
    656            ),
    657            exp.StrToDate: lambda self, e: self.func("PARSE_DATE", self.format_time(e), e.this),
    658            exp.StrToTime: lambda self, e: self.func(
    659                "PARSE_TIMESTAMP", self.format_time(e), e.this, e.args.get("zone")
    660            ),
    661            exp.TimeAdd: date_add_interval_sql("TIME", "ADD"),
    662            exp.TimeFromParts: rename_func("TIME"),
    663            exp.TimestampFromParts: rename_func("DATETIME"),
    664            exp.TimeSub: date_add_interval_sql("TIME", "SUB"),
    665            exp.TimestampAdd: date_add_interval_sql("TIMESTAMP", "ADD"),
    666            exp.TimestampDiff: rename_func("TIMESTAMP_DIFF"),
    667            exp.TimestampSub: date_add_interval_sql("TIMESTAMP", "SUB"),
    668            exp.TimeStrToTime: timestrtotime_sql,
    669            exp.Transaction: lambda *_: "BEGIN TRANSACTION",
    670            exp.Trim: lambda self, e: self.func("TRIM", e.this, e.expression),
    671            exp.TsOrDsAdd: _ts_or_ds_add_sql,
    672            exp.TsOrDsDiff: _ts_or_ds_diff_sql,
    673            exp.TsOrDsToTime: rename_func("TIME"),
    674            exp.TsOrDsToTimestamp: rename_func("DATETIME"),
    675            exp.Unhex: rename_func("FROM_HEX"),
    676            exp.UnixDate: rename_func("UNIX_DATE"),
    677            exp.UnixToTime: _unix_to_time_sql,
    678            exp.Values: _derived_table_values_to_unnest,
    679            exp.VariancePop: rename_func("VAR_POP"),
    680        }
    681
    682        SUPPORTED_JSON_PATH_PARTS = {
    683            exp.JSONPathKey,
    684            exp.JSONPathRoot,
    685            exp.JSONPathSubscript,
    686        }
    687
    688        TYPE_MAPPING = {
    689            **generator.Generator.TYPE_MAPPING,
    690            exp.DataType.Type.BIGDECIMAL: "BIGNUMERIC",
    691            exp.DataType.Type.BIGINT: "INT64",
    692            exp.DataType.Type.BINARY: "BYTES",
    693            exp.DataType.Type.BOOLEAN: "BOOL",
    694            exp.DataType.Type.CHAR: "STRING",
    695            exp.DataType.Type.DECIMAL: "NUMERIC",
    696            exp.DataType.Type.DOUBLE: "FLOAT64",
    697            exp.DataType.Type.FLOAT: "FLOAT64",
    698            exp.DataType.Type.INT: "INT64",
    699            exp.DataType.Type.NCHAR: "STRING",
    700            exp.DataType.Type.NVARCHAR: "STRING",
    701            exp.DataType.Type.SMALLINT: "INT64",
    702            exp.DataType.Type.TEXT: "STRING",
    703            exp.DataType.Type.TIMESTAMP: "DATETIME",
    704            exp.DataType.Type.TIMESTAMPTZ: "TIMESTAMP",
    705            exp.DataType.Type.TIMESTAMPLTZ: "TIMESTAMP",
    706            exp.DataType.Type.TINYINT: "INT64",
    707            exp.DataType.Type.VARBINARY: "BYTES",
    708            exp.DataType.Type.ROWVERSION: "BYTES",
    709            exp.DataType.Type.VARCHAR: "STRING",
    710            exp.DataType.Type.VARIANT: "ANY TYPE",
    711        }
    712
    713        PROPERTIES_LOCATION = {
    714            **generator.Generator.PROPERTIES_LOCATION,
    715            exp.PartitionedByProperty: exp.Properties.Location.POST_SCHEMA,
    716            exp.VolatileProperty: exp.Properties.Location.UNSUPPORTED,
    717        }
    718
    719        # from: https://cloud.google.com/bigquery/docs/reference/standard-sql/lexical#reserved_keywords
    720        RESERVED_KEYWORDS = {
    721            "all",
    722            "and",
    723            "any",
    724            "array",
    725            "as",
    726            "asc",
    727            "assert_rows_modified",
    728            "at",
    729            "between",
    730            "by",
    731            "case",
    732            "cast",
    733            "collate",
    734            "contains",
    735            "create",
    736            "cross",
    737            "cube",
    738            "current",
    739            "default",
    740            "define",
    741            "desc",
    742            "distinct",
    743            "else",
    744            "end",
    745            "enum",
    746            "escape",
    747            "except",
    748            "exclude",
    749            "exists",
    750            "extract",
    751            "false",
    752            "fetch",
    753            "following",
    754            "for",
    755            "from",
    756            "full",
    757            "group",
    758            "grouping",
    759            "groups",
    760            "hash",
    761            "having",
    762            "if",
    763            "ignore",
    764            "in",
    765            "inner",
    766            "intersect",
    767            "interval",
    768            "into",
    769            "is",
    770            "join",
    771            "lateral",
    772            "left",
    773            "like",
    774            "limit",
    775            "lookup",
    776            "merge",
    777            "natural",
    778            "new",
    779            "no",
    780            "not",
    781            "null",
    782            "nulls",
    783            "of",
    784            "on",
    785            "or",
    786            "order",
    787            "outer",
    788            "over",
    789            "partition",
    790            "preceding",
    791            "proto",
    792            "qualify",
    793            "range",
    794            "recursive",
    795            "respect",
    796            "right",
    797            "rollup",
    798            "rows",
    799            "select",
    800            "set",
    801            "some",
    802            "struct",
    803            "tablesample",
    804            "then",
    805            "to",
    806            "treat",
    807            "true",
    808            "unbounded",
    809            "union",
    810            "unnest",
    811            "using",
    812            "when",
    813            "where",
    814            "window",
    815            "with",
    816            "within",
    817        }
    818
    819        def mod_sql(self, expression: exp.Mod) -> str:
    820            this = expression.this
    821            expr = expression.expression
    822            return self.func(
    823                "MOD",
    824                this.unnest() if isinstance(this, exp.Paren) else this,
    825                expr.unnest() if isinstance(expr, exp.Paren) else expr,
    826            )
    827
    828        def column_parts(self, expression: exp.Column) -> str:
    829            if expression.meta.get("quoted_column"):
    830                # If a column reference is of the form `dataset.table`.name, we need
    831                # to preserve the quoted table path, otherwise the reference breaks
    832                table_parts = ".".join(p.name for p in expression.parts[:-1])
    833                table_path = self.sql(exp.Identifier(this=table_parts, quoted=True))
    834                return f"{table_path}.{self.sql(expression, 'this')}"
    835
    836            return super().column_parts(expression)
    837
    838        def table_parts(self, expression: exp.Table) -> str:
    839            # Depending on the context, `x.y` may not resolve to the same data source as `x`.`y`, so
    840            # we need to make sure the correct quoting is used in each case.
    841            #
    842            # For example, if there is a CTE x that clashes with a schema name, then the former will
    843            # return the table y in that schema, whereas the latter will return the CTE's y column:
    844            #
    845            # - WITH x AS (SELECT [1, 2] AS y) SELECT * FROM x, `x.y`   -> cross join
    846            # - WITH x AS (SELECT [1, 2] AS y) SELECT * FROM x, `x`.`y` -> implicit unnest
    847            if expression.meta.get("quoted_table"):
    848                table_parts = ".".join(p.name for p in expression.parts)
    849                return self.sql(exp.Identifier(this=table_parts, quoted=True))
    850
    851            return super().table_parts(expression)
    852
    853        def timetostr_sql(self, expression: exp.TimeToStr) -> str:
    854            this = expression.this if isinstance(expression.this, exp.TsOrDsToDate) else expression
    855            return self.func("FORMAT_DATE", self.format_time(expression), this.this)
    856
    857        def eq_sql(self, expression: exp.EQ) -> str:
    858            # Operands of = cannot be NULL in BigQuery
    859            if isinstance(expression.left, exp.Null) or isinstance(expression.right, exp.Null):
    860                if not isinstance(expression.parent, exp.Update):
    861                    return "NULL"
    862
    863            return self.binary(expression, "=")
    864
    865        def attimezone_sql(self, expression: exp.AtTimeZone) -> str:
    866            parent = expression.parent
    867
    868            # BigQuery allows CAST(.. AS {STRING|TIMESTAMP} [FORMAT <fmt> [AT TIME ZONE <tz>]]).
    869            # Only the TIMESTAMP one should use the below conversion, when AT TIME ZONE is included.
    870            if not isinstance(parent, exp.Cast) or not parent.to.is_type("text"):
    871                return self.func(
    872                    "TIMESTAMP", self.func("DATETIME", expression.this, expression.args.get("zone"))
    873                )
    874
    875            return super().attimezone_sql(expression)
    876
    877        def trycast_sql(self, expression: exp.TryCast) -> str:
    878            return self.cast_sql(expression, safe_prefix="SAFE_")
    879
    880        def bracket_sql(self, expression: exp.Bracket) -> str:
    881            this = expression.this
    882            expressions = expression.expressions
    883
    884            if len(expressions) == 1 and this and this.is_type(exp.DataType.Type.STRUCT):
    885                arg = expressions[0]
    886                if arg.type is None:
    887                    from sqlglot.optimizer.annotate_types import annotate_types
    888
    889                    arg = annotate_types(arg)
    890
    891                if arg.type and arg.type.this in exp.DataType.TEXT_TYPES:
    892                    # BQ doesn't support bracket syntax with string values for structs
    893                    return f"{self.sql(this)}.{arg.name}"
    894
    895            expressions_sql = self.expressions(expression, flat=True)
    896            offset = expression.args.get("offset")
    897
    898            if offset == 0:
    899                expressions_sql = f"OFFSET({expressions_sql})"
    900            elif offset == 1:
    901                expressions_sql = f"ORDINAL({expressions_sql})"
    902            elif offset is not None:
    903                self.unsupported(f"Unsupported array offset: {offset}")
    904
    905            if expression.args.get("safe"):
    906                expressions_sql = f"SAFE_{expressions_sql}"
    907
    908            return f"{self.sql(this)}[{expressions_sql}]"
    909
    910        def in_unnest_op(self, expression: exp.Unnest) -> str:
    911            return self.sql(expression)
    912
    913        def except_op(self, expression: exp.Except) -> str:
    914            if not expression.args.get("distinct"):
    915                self.unsupported("EXCEPT without DISTINCT is not supported in BigQuery")
    916            return f"EXCEPT{' DISTINCT' if expression.args.get('distinct') else ' ALL'}"
    917
    918        def intersect_op(self, expression: exp.Intersect) -> str:
    919            if not expression.args.get("distinct"):
    920                self.unsupported("INTERSECT without DISTINCT is not supported in BigQuery")
    921            return f"INTERSECT{' DISTINCT' if expression.args.get('distinct') else ' ALL'}"
    922
    923        def version_sql(self, expression: exp.Version) -> str:
    924            if expression.name == "TIMESTAMP":
    925                expression.set("this", "SYSTEM_TIME")
    926            return super().version_sql(expression)

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 or 'always': Always quote. '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

EXPLICIT_SET_OP = True
INTERVAL_ALLOWS_PLURAL_FORM = False
JOIN_HINTS = False
QUERY_HINTS = False
TABLE_HINTS = False
LIMIT_FETCH = 'LIMIT'
RENAME_TABLE_WITH_DB = False
NVL2_SUPPORTED = False
UNNEST_WITH_ORDINALITY = False
COLLATE_IS_FUNC = True
LIMIT_ONLY_LITERALS = True
SUPPORTS_TABLE_ALIAS_COLUMNS = False
UNPIVOT_ALIASES_ARE_IDENTIFIERS = False
JSON_KEY_VALUE_PAIR_SEP = ','
NULL_ORDERING_SUPPORTED = False
IGNORE_NULLS_IN_FUNC = True
JSON_PATH_SINGLE_QUOTE_ESCAPE = True
CAN_IMPLEMENT_ARRAY_ANY = True
SUPPORTS_TO_NUMBER = False
NAMED_PLACEHOLDER_TOKEN = '@'
HEX_FUNC = 'TO_HEX'
WITH_PROPERTIES_PREFIX = 'OPTIONS'
TRANSFORMS = {<class 'sqlglot.expressions.JSONPathKey'>: <function <lambda>>, <class 'sqlglot.expressions.JSONPathRoot'>: <function <lambda>>, <class 'sqlglot.expressions.JSONPathSubscript'>: <function <lambda>>, <class 'sqlglot.expressions.AllowedValuesProperty'>: <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.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.CommentColumnConstraint'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.CopyGrantsProperty'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.DateFormatColumnConstraint'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.DefaultColumnConstraint'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.EncodeColumnConstraint'>: <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.ExternalProperty'>: <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.IntervalSpan'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.JSONExtract'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.JSONExtractScalar'>: <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.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.OutputModelProperty'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.PathColumnConstraint'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.ProjectionPolicyColumnConstraint'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.RemoteWithConnectionModelProperty'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.ReturnsProperty'>: <function _returnsproperty_sql>, <class 'sqlglot.expressions.SampleProperty'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.SecureProperty'>: <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 BigQuery.Generator.<lambda>>, <class 'sqlglot.expressions.StrictProperty'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.TemporaryProperty'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.TagColumnConstraint'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.TitleColumnConstraint'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.Timestamp'>: <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.UppercaseColumnConstraint'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.UnloggedProperty'>: <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.WithOperator'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.ApproxDistinct'>: <function rename_func.<locals>.<lambda>>, <class 'sqlglot.expressions.ArgMax'>: <function arg_max_or_min_no_count.<locals>._arg_max_or_min_sql>, <class 'sqlglot.expressions.ArgMin'>: <function arg_max_or_min_no_count.<locals>._arg_max_or_min_sql>, <class 'sqlglot.expressions.Array'>: <function inline_array_unless_query>, <class 'sqlglot.expressions.ArrayContains'>: <function _array_contains_sql>, <class 'sqlglot.expressions.ArrayFilter'>: <function filter_array_using_unnest>, <class 'sqlglot.expressions.ArraySize'>: <function rename_func.<locals>.<lambda>>, <class 'sqlglot.expressions.Cast'>: <function preprocess.<locals>._to_sql>, <class 'sqlglot.expressions.CollateProperty'>: <function BigQuery.Generator.<lambda>>, <class 'sqlglot.expressions.Commit'>: <function BigQuery.Generator.<lambda>>, <class 'sqlglot.expressions.CountIf'>: <function rename_func.<locals>.<lambda>>, <class 'sqlglot.expressions.Create'>: <function _create_sql>, <class 'sqlglot.expressions.CTE'>: <function preprocess.<locals>._to_sql>, <class 'sqlglot.expressions.DateAdd'>: <function date_add_interval_sql.<locals>.func>, <class 'sqlglot.expressions.DateDiff'>: <function BigQuery.Generator.<lambda>>, <class 'sqlglot.expressions.DateFromParts'>: <function rename_func.<locals>.<lambda>>, <class 'sqlglot.expressions.DateStrToDate'>: <function datestrtodate_sql>, <class 'sqlglot.expressions.DateSub'>: <function date_add_interval_sql.<locals>.func>, <class 'sqlglot.expressions.DatetimeAdd'>: <function date_add_interval_sql.<locals>.func>, <class 'sqlglot.expressions.DatetimeSub'>: <function date_add_interval_sql.<locals>.func>, <class 'sqlglot.expressions.DateTrunc'>: <function BigQuery.Generator.<lambda>>, <class 'sqlglot.expressions.FromTimeZone'>: <function BigQuery.Generator.<lambda>>, <class 'sqlglot.expressions.GenerateSeries'>: <function rename_func.<locals>.<lambda>>, <class 'sqlglot.expressions.GroupConcat'>: <function rename_func.<locals>.<lambda>>, <class 'sqlglot.expressions.Hex'>: <function BigQuery.Generator.<lambda>>, <class 'sqlglot.expressions.If'>: <function if_sql.<locals>._if_sql>, <class 'sqlglot.expressions.ILike'>: <function no_ilike_sql>, <class 'sqlglot.expressions.IntDiv'>: <function rename_func.<locals>.<lambda>>, <class 'sqlglot.expressions.JSONFormat'>: <function rename_func.<locals>.<lambda>>, <class 'sqlglot.expressions.Max'>: <function max_or_greatest>, <class 'sqlglot.expressions.MD5'>: <function BigQuery.Generator.<lambda>>, <class 'sqlglot.expressions.MD5Digest'>: <function rename_func.<locals>.<lambda>>, <class 'sqlglot.expressions.Min'>: <function min_or_least>, <class 'sqlglot.expressions.PartitionedByProperty'>: <function BigQuery.Generator.<lambda>>, <class 'sqlglot.expressions.RegexpExtract'>: <function BigQuery.Generator.<lambda>>, <class 'sqlglot.expressions.RegexpReplace'>: <function regexp_replace_sql>, <class 'sqlglot.expressions.RegexpLike'>: <function rename_func.<locals>.<lambda>>, <class 'sqlglot.expressions.Rollback'>: <function BigQuery.Generator.<lambda>>, <class 'sqlglot.expressions.Select'>: <function preprocess.<locals>._to_sql>, <class 'sqlglot.expressions.SHA'>: <function rename_func.<locals>.<lambda>>, <class 'sqlglot.expressions.SHA2'>: <function sha256_sql>, <class 'sqlglot.expressions.StrToDate'>: <function BigQuery.Generator.<lambda>>, <class 'sqlglot.expressions.StrToTime'>: <function BigQuery.Generator.<lambda>>, <class 'sqlglot.expressions.TimeAdd'>: <function date_add_interval_sql.<locals>.func>, <class 'sqlglot.expressions.TimeFromParts'>: <function rename_func.<locals>.<lambda>>, <class 'sqlglot.expressions.TimestampFromParts'>: <function rename_func.<locals>.<lambda>>, <class 'sqlglot.expressions.TimeSub'>: <function date_add_interval_sql.<locals>.func>, <class 'sqlglot.expressions.TimestampAdd'>: <function date_add_interval_sql.<locals>.func>, <class 'sqlglot.expressions.TimestampDiff'>: <function rename_func.<locals>.<lambda>>, <class 'sqlglot.expressions.TimestampSub'>: <function date_add_interval_sql.<locals>.func>, <class 'sqlglot.expressions.TimeStrToTime'>: <function timestrtotime_sql>, <class 'sqlglot.expressions.Transaction'>: <function BigQuery.Generator.<lambda>>, <class 'sqlglot.expressions.Trim'>: <function BigQuery.Generator.<lambda>>, <class 'sqlglot.expressions.TsOrDsAdd'>: <function _ts_or_ds_add_sql>, <class 'sqlglot.expressions.TsOrDsDiff'>: <function _ts_or_ds_diff_sql>, <class 'sqlglot.expressions.TsOrDsToTime'>: <function rename_func.<locals>.<lambda>>, <class 'sqlglot.expressions.TsOrDsToTimestamp'>: <function rename_func.<locals>.<lambda>>, <class 'sqlglot.expressions.Unhex'>: <function rename_func.<locals>.<lambda>>, <class 'sqlglot.expressions.UnixDate'>: <function rename_func.<locals>.<lambda>>, <class 'sqlglot.expressions.UnixToTime'>: <function _unix_to_time_sql>, <class 'sqlglot.expressions.Values'>: <function _derived_table_values_to_unnest>, <class 'sqlglot.expressions.VariancePop'>: <function rename_func.<locals>.<lambda>>}
SUPPORTED_JSON_PATH_PARTS = {<class 'sqlglot.expressions.JSONPathRoot'>, <class 'sqlglot.expressions.JSONPathKey'>, <class 'sqlglot.expressions.JSONPathSubscript'>}
TYPE_MAPPING = {<Type.NCHAR: 'NCHAR'>: 'STRING', <Type.NVARCHAR: 'NVARCHAR'>: 'STRING', <Type.MEDIUMTEXT: 'MEDIUMTEXT'>: 'TEXT', <Type.LONGTEXT: 'LONGTEXT'>: 'TEXT', <Type.TINYTEXT: 'TINYTEXT'>: 'TEXT', <Type.MEDIUMBLOB: 'MEDIUMBLOB'>: 'BLOB', <Type.LONGBLOB: 'LONGBLOB'>: 'BLOB', <Type.TINYBLOB: 'TINYBLOB'>: 'BLOB', <Type.INET: 'INET'>: 'INET', <Type.ROWVERSION: 'ROWVERSION'>: 'BYTES', <Type.BIGDECIMAL: 'BIGDECIMAL'>: 'BIGNUMERIC', <Type.BIGINT: 'BIGINT'>: 'INT64', <Type.BINARY: 'BINARY'>: 'BYTES', <Type.BOOLEAN: 'BOOLEAN'>: 'BOOL', <Type.CHAR: 'CHAR'>: 'STRING', <Type.DECIMAL: 'DECIMAL'>: 'NUMERIC', <Type.DOUBLE: 'DOUBLE'>: 'FLOAT64', <Type.FLOAT: 'FLOAT'>: 'FLOAT64', <Type.INT: 'INT'>: 'INT64', <Type.SMALLINT: 'SMALLINT'>: 'INT64', <Type.TEXT: 'TEXT'>: 'STRING', <Type.TIMESTAMP: 'TIMESTAMP'>: 'DATETIME', <Type.TIMESTAMPTZ: 'TIMESTAMPTZ'>: 'TIMESTAMP', <Type.TIMESTAMPLTZ: 'TIMESTAMPLTZ'>: 'TIMESTAMP', <Type.TINYINT: 'TINYINT'>: 'INT64', <Type.VARBINARY: 'VARBINARY'>: 'BYTES', <Type.VARCHAR: 'VARCHAR'>: 'STRING', <Type.VARIANT: 'VARIANT'>: 'ANY TYPE'}
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.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.DistKeyProperty'>: <Location.POST_SCHEMA: 'POST_SCHEMA'>, <class 'sqlglot.expressions.DistStyleProperty'>: <Location.POST_SCHEMA: 'POST_SCHEMA'>, <class 'sqlglot.expressions.EngineProperty'>: <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.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.RemoteWithConnectionModelProperty'>: <Location.POST_SCHEMA: 'POST_SCHEMA'>, <class 'sqlglot.expressions.ReturnsProperty'>: <Location.POST_SCHEMA: 'POST_SCHEMA'>, <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.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.StrictProperty'>: <Location.POST_SCHEMA: 'POST_SCHEMA'>, <class 'sqlglot.expressions.TemporaryProperty'>: <Location.POST_CREATE: 'POST_CREATE'>, <class 'sqlglot.expressions.ToTableProperty'>: <Location.POST_SCHEMA: 'POST_SCHEMA'>, <class 'sqlglot.expressions.TransientProperty'>: <Location.POST_CREATE: 'POST_CREATE'>, <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.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.WithSystemVersioningProperty'>: <Location.POST_SCHEMA: 'POST_SCHEMA'>}
RESERVED_KEYWORDS = {'recursive', 'fetch', 'range', 'and', 'within', 'on', 'current', 'qualify', 'natural', 'treat', 'true', 'with', 'where', 'partition', 'cross', 'some', 'from', 'lateral', 'default', 'or', 'inner', 'all', 'extract', 'having', 'else', 'escape', 'no', 'cube', 'collate', 'left', 'by', 'struct', 'preceding', 'right', 'any', 'using', 'respect', 'rollup', 'select', 'if', 'rows', 'cast', 'like', 'new', 'as', 'except', 'false', 'assert_rows_modified', 'set', 'define', 'create', 'for', 'asc', 'in', 'is', 'full', 'proto', 'array', 'of', 'over', 'interval', 'enum', 'window', 'end', 'between', 'group', 'null', 'not', 'distinct', 'to', 'ignore', 'case', 'lookup', 'groups', 'limit', 'grouping', 'unnest', 'nulls', 'exclude', 'then', 'contains', 'following', 'order', 'desc', 'into', 'union', 'join', 'at', 'when', 'hash', 'exists', 'merge', 'intersect', 'tablesample', 'unbounded', 'outer'}
def mod_sql(self, expression: sqlglot.expressions.Mod) -> str: View Source

    819        def mod_sql(self, expression: exp.Mod) -> str:
    820            this = expression.this
    821            expr = expression.expression
    822            return self.func(
    823                "MOD",
    824                this.unnest() if isinstance(this, exp.Paren) else this,
    825                expr.unnest() if isinstance(expr, exp.Paren) else expr,
    826            )

def column_parts(self, expression: sqlglot.expressions.Column) -> str: View Source

    828        def column_parts(self, expression: exp.Column) -> str:
    829            if expression.meta.get("quoted_column"):
    830                # If a column reference is of the form `dataset.table`.name, we need
    831                # to preserve the quoted table path, otherwise the reference breaks
    832                table_parts = ".".join(p.name for p in expression.parts[:-1])
    833                table_path = self.sql(exp.Identifier(this=table_parts, quoted=True))
    834                return f"{table_path}.{self.sql(expression, 'this')}"
    835
    836            return super().column_parts(expression)

def table_parts(self, expression: sqlglot.expressions.Table) -> str: View Source

    838        def table_parts(self, expression: exp.Table) -> str:
    839            # Depending on the context, `x.y` may not resolve to the same data source as `x`.`y`, so
    840            # we need to make sure the correct quoting is used in each case.
    841            #
    842            # For example, if there is a CTE x that clashes with a schema name, then the former will
    843            # return the table y in that schema, whereas the latter will return the CTE's y column:
    844            #
    845            # - WITH x AS (SELECT [1, 2] AS y) SELECT * FROM x, `x.y`   -> cross join
    846            # - WITH x AS (SELECT [1, 2] AS y) SELECT * FROM x, `x`.`y` -> implicit unnest
    847            if expression.meta.get("quoted_table"):
    848                table_parts = ".".join(p.name for p in expression.parts)
    849                return self.sql(exp.Identifier(this=table_parts, quoted=True))
    850
    851            return super().table_parts(expression)

def timetostr_sql(self, expression: sqlglot.expressions.TimeToStr) -> str: View Source

    853        def timetostr_sql(self, expression: exp.TimeToStr) -> str:
    854            this = expression.this if isinstance(expression.this, exp.TsOrDsToDate) else expression
    855            return self.func("FORMAT_DATE", self.format_time(expression), this.this)

def eq_sql(self, expression: sqlglot.expressions.EQ) -> str: View Source

    857        def eq_sql(self, expression: exp.EQ) -> str:
    858            # Operands of = cannot be NULL in BigQuery
    859            if isinstance(expression.left, exp.Null) or isinstance(expression.right, exp.Null):
    860                if not isinstance(expression.parent, exp.Update):
    861                    return "NULL"
    862
    863            return self.binary(expression, "=")

def attimezone_sql(self, expression: sqlglot.expressions.AtTimeZone) -> str: View Source

    865        def attimezone_sql(self, expression: exp.AtTimeZone) -> str:
    866            parent = expression.parent
    867
    868            # BigQuery allows CAST(.. AS {STRING|TIMESTAMP} [FORMAT <fmt> [AT TIME ZONE <tz>]]).
    869            # Only the TIMESTAMP one should use the below conversion, when AT TIME ZONE is included.
    870            if not isinstance(parent, exp.Cast) or not parent.to.is_type("text"):
    871                return self.func(
    872                    "TIMESTAMP", self.func("DATETIME", expression.this, expression.args.get("zone"))
    873                )
    874
    875            return super().attimezone_sql(expression)

def trycast_sql(self, expression: sqlglot.expressions.TryCast) -> str: View Source

    877        def trycast_sql(self, expression: exp.TryCast) -> str:
    878            return self.cast_sql(expression, safe_prefix="SAFE_")

def bracket_sql(self, expression: sqlglot.expressions.Bracket) -> str: View Source

    880        def bracket_sql(self, expression: exp.Bracket) -> str:
    881            this = expression.this
    882            expressions = expression.expressions
    883
    884            if len(expressions) == 1 and this and this.is_type(exp.DataType.Type.STRUCT):
    885                arg = expressions[0]
    886                if arg.type is None:
    887                    from sqlglot.optimizer.annotate_types import annotate_types
    888
    889                    arg = annotate_types(arg)
    890
    891                if arg.type and arg.type.this in exp.DataType.TEXT_TYPES:
    892                    # BQ doesn't support bracket syntax with string values for structs
    893                    return f"{self.sql(this)}.{arg.name}"
    894
    895            expressions_sql = self.expressions(expression, flat=True)
    896            offset = expression.args.get("offset")
    897
    898            if offset == 0:
    899                expressions_sql = f"OFFSET({expressions_sql})"
    900            elif offset == 1:
    901                expressions_sql = f"ORDINAL({expressions_sql})"
    902            elif offset is not None:
    903                self.unsupported(f"Unsupported array offset: {offset}")
    904
    905            if expression.args.get("safe"):
    906                expressions_sql = f"SAFE_{expressions_sql}"
    907
    908            return f"{self.sql(this)}[{expressions_sql}]"

def in_unnest_op(self, expression: sqlglot.expressions.Unnest) -> str: View Source

    910        def in_unnest_op(self, expression: exp.Unnest) -> str:
    911            return self.sql(expression)

def except_op(self, expression: sqlglot.expressions.Except) -> str: View Source

    913        def except_op(self, expression: exp.Except) -> str:
    914            if not expression.args.get("distinct"):
    915                self.unsupported("EXCEPT without DISTINCT is not supported in BigQuery")
    916            return f"EXCEPT{' DISTINCT' if expression.args.get('distinct') else ' ALL'}"

def intersect_op(self, expression: sqlglot.expressions.Intersect) -> str: View Source

    918        def intersect_op(self, expression: exp.Intersect) -> str:
    919            if not expression.args.get("distinct"):
    920                self.unsupported("INTERSECT without DISTINCT is not supported in BigQuery")
    921            return f"INTERSECT{' DISTINCT' if expression.args.get('distinct') else ' ALL'}"

def version_sql(self, expression: sqlglot.expressions.Version) -> str: View Source

    923        def version_sql(self, expression: exp.Version) -> str:
    924            if expression.name == "TIMESTAMP":
    925                expression.set("this", "SYSTEM_TIME")
    926            return super().version_sql(expression)

TRY_SUPPORTED = False
SUPPORTS_UESCAPE = False
AFTER_HAVING_MODIFIER_TRANSFORMS = {'qualify': <function Generator.<lambda>>, 'windows': <function Generator.<lambda>>}

##### Inherited Members

sqlglot.generator.Generator
  Generator
  LOCKING_READS_SUPPORTED
  WRAP_DERIVED_VALUES
  CREATE_FUNCTION_RETURN_AS
  MATCHED_BY_SOURCE
  SINGLE_STRING_INTERVAL
  GROUPINGS_SEP
  INDEX_ON
  QUERY_HINT_SEP
  IS_BOOL_ALLOWED
  DUPLICATE_KEY_UPDATE_WITH_SET
  LIMIT_IS_TOP
  RETURNING_END
  EXTRACT_ALLOWS_QUOTES
  TZ_TO_WITH_TIME_ZONE
  SELECT_KINDS
  VALUES_AS_TABLE
  ALTER_TABLE_INCLUDE_COLUMN_KEYWORD
  AGGREGATE_FILTER_SUPPORTED
  SEMI_ANTI_JOIN_WITH_SIDE
  COMPUTED_COLUMN_WITH_TYPE
  SUPPORTS_TABLE_COPY
  TABLESAMPLE_REQUIRES_PARENS
  TABLESAMPLE_SIZE_IS_ROWS
  TABLESAMPLE_KEYWORDS
  TABLESAMPLE_WITH_METHOD
  TABLESAMPLE_SEED_KEYWORD
  DATA_TYPE_SPECIFIERS_ALLOWED
  ENSURE_BOOLS
  CTE_RECURSIVE_KEYWORD_REQUIRED
  SUPPORTS_SINGLE_ARG_CONCAT
  LAST_DAY_SUPPORTS_DATE_PART
  INSERT_OVERWRITE
  SUPPORTS_SELECT_INTO
  SUPPORTS_UNLOGGED_TABLES
  SUPPORTS_CREATE_TABLE_LIKE
  LIKE_PROPERTY_INSIDE_SCHEMA
  MULTI_ARG_DISTINCT
  JSON_TYPE_REQUIRED_FOR_EXTRACTION
  JSON_PATH_BRACKETED_KEY_SUPPORTED
  SET_OP_MODIFIERS
  COPY_PARAMS_ARE_WRAPPED
  COPY_PARAMS_EQ_REQUIRED
  COPY_HAS_INTO_KEYWORD
  STAR_EXCEPT
  QUOTE_JSON_PATH
  TIME_PART_SINGULARS
  TOKEN_MAPPING
  STRUCT_DELIMITER
  PARAMETER_TOKEN
  WITH_SEPARATED_COMMENTS
  EXCLUDE_COMMENTS
  UNWRAPPED_INTERVAL_VALUES
  PARAMETERIZABLE_TEXT_TYPES
  EXPRESSIONS_WITHOUT_NESTED_CTES
  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
  pad_comment
  maybe_comment
  wrap
  no_identify
  normalize_func
  indent
  sql
  uncache_sql
  cache_sql
  characterset_sql
  column_sql
  columnposition_sql
  columndef_sql
  columnconstraint_sql
  computedcolumnconstraint_sql
  autoincrementcolumnconstraint_sql
  compresscolumnconstraint_sql
  generatedasidentitycolumnconstraint_sql
  generatedasrowcolumnconstraint_sql
  periodforsystemtimeconstraint_sql
  notnullcolumnconstraint_sql
  transformcolumnconstraint_sql
  primarykeycolumnconstraint_sql
  uniquecolumnconstraint_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
  datatype_sql
  directory_sql
  delete_sql
  drop_sql
  except_sql
  fetch_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
  intersect_sql
  introducer_sql
  kill_sql
  pseudotype_sql
  objectidentifier_sql
  onconflict_sql
  returning_sql
  rowformatdelimitedproperty_sql
  withtablehint_sql
  indextablehint_sql
  historicaldata_sql
  table_sql
  tablesample_sql
  pivot_sql
  tuple_sql
  update_sql
  values_sql
  var_sql
  into_sql
  from_sql
  group_sql
  having_sql
  connect_sql
  prior_sql
  join_sql
  lambda_sql
  lateral_op
  lateral_sql
  limit_sql
  offset_sql
  setitem_sql
  set_sql
  pragma_sql
  lock_sql
  literal_sql
  escape_str
  loaddata_sql
  null_sql
  boolean_sql
  order_sql
  withfill_sql
  cluster_sql
  distribute_sql
  sort_sql
  ordered_sql
  matchrecognizemeasure_sql
  matchrecognize_sql
  query_modifiers
  options_modifier
  queryoption_sql
  offset_limit_modifiers
  after_limit_modifiers
  select_sql
  schema_sql
  schema_columns_sql
  star_sql
  parameter_sql
  sessionparameter_sql
  placeholder_sql
  subquery_sql
  qualify_sql
  set_operations
  union_sql
  union_op
  unnest_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
  matchagainst_sql
  jsonkeyvalue_sql
  jsonpath_sql
  json_path_part
  formatjson_sql
  jsonobject_sql
  jsonobjectagg_sql
  jsonarray_sql
  jsonarrayagg_sql
  jsoncolumndef_sql
  jsonschema_sql
  jsontable_sql
  openjsoncolumndef_sql
  openjson_sql
  in_sql
  interval_sql
  return_sql
  reference_sql
  anonymous_sql
  paren_sql
  neg_sql
  not_sql
  alias_sql
  pivotalias_sql
  aliases_sql
  atindex_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
  cast_sql
  currentdate_sql
  currenttimestamp_sql
  collate_sql
  command_sql
  comment_sql
  mergetreettlaction_sql
  mergetreettl_sql
  transaction_sql
  commit_sql
  rollback_sql
  altercolumn_sql
  alterdiststyle_sql
  altersortkey_sql
  renametable_sql
  renamecolumn_sql
  alterset_sql
  altertable_sql
  add_column_sql
  droppartition_sql
  addconstraint_sql
  distinct_sql
  ignorenulls_sql
  respectnulls_sql
  havingmax_sql
  intdiv_sql
  dpipe_sql
  div_sql
  overlaps_sql
  distance_sql
  dot_sql
  propertyeq_sql
  escape_sql
  glob_sql
  gt_sql
  gte_sql
  ilike_sql
  ilikeany_sql
  is_sql
  like_sql
  likeany_sql
  similarto_sql
  lt_sql
  lte_sql
  mul_sql
  neq_sql
  nullsafeeq_sql
  nullsafeneq_sql
  slice_sql
  sub_sql
  try_sql
  log_sql
  use_sql
  binary
  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
  merge_sql
  tochar_sql
  tonumber_sql
  dictproperty_sql
  dictrange_sql
  dictsubproperty_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
  forin_sql
  refresh_sql
  operator_sql
  toarray_sql
  tsordstotime_sql
  tsordstotimestamp_sql
  tsordstodate_sql
  unixdate_sql
  lastday_sql
  dateadd_sql
  arrayany_sql
  generateseries_sql
  struct_sql
  partitionrange_sql
  truncatetable_sql
  convert_sql
  copyparameter_sql
  credentials_sql
  copy_sql
  semicolon_sql
  datadeletionproperty_sql
  maskingpolicycolumnconstraint_sql
  gapfill_sql