sqlglot.dialects.bigquery
1from __future__ import annotations 2 3import logging 4import re 5import typing as t 6 7from sqlglot import exp, generator, parser, tokens, transforms 8from sqlglot._typing import E 9from sqlglot.dialects.dialect import ( 10 Dialect, 11 arg_max_or_min_no_count, 12 binary_from_function, 13 date_add_interval_sql, 14 datestrtodate_sql, 15 format_time_lambda, 16 if_sql, 17 inline_array_sql, 18 json_keyvalue_comma_sql, 19 max_or_greatest, 20 min_or_least, 21 no_ilike_sql, 22 parse_date_delta_with_interval, 23 regexp_replace_sql, 24 rename_func, 25 timestrtotime_sql, 26 ts_or_ds_to_date_sql, 27) 28from sqlglot.helper import seq_get, split_num_words 29from sqlglot.tokens import TokenType 30 31logger = logging.getLogger("sqlglot") 32 33 34def _derived_table_values_to_unnest(self: BigQuery.Generator, expression: exp.Values) -> str: 35 if not expression.find_ancestor(exp.From, exp.Join): 36 return self.values_sql(expression) 37 38 alias = expression.args.get("alias") 39 40 structs = [ 41 exp.Struct( 42 expressions=[ 43 exp.alias_(value, column_name) 44 for value, column_name in zip( 45 t.expressions, 46 alias.columns 47 if alias and alias.columns 48 else (f"_c{i}" for i in range(len(t.expressions))), 49 ) 50 ] 51 ) 52 for t in expression.find_all(exp.Tuple) 53 ] 54 55 return self.unnest_sql(exp.Unnest(expressions=[exp.Array(expressions=structs)])) 56 57 58def _returnsproperty_sql(self: BigQuery.Generator, expression: exp.ReturnsProperty) -> str: 59 this = expression.this 60 if isinstance(this, exp.Schema): 61 this = f"{this.this} <{self.expressions(this)}>" 62 else: 63 this = self.sql(this) 64 return f"RETURNS {this}" 65 66 67def _create_sql(self: BigQuery.Generator, expression: exp.Create) -> str: 68 kind = expression.args["kind"] 69 returns = expression.find(exp.ReturnsProperty) 70 71 if kind.upper() == "FUNCTION" and returns and returns.args.get("is_table"): 72 expression.set("kind", "TABLE FUNCTION") 73 74 if isinstance(expression.expression, (exp.Subquery, exp.Literal)): 75 expression.set("expression", expression.expression.this) 76 77 return self.create_sql(expression) 78 79 return self.create_sql(expression) 80 81 82def _unqualify_unnest(expression: exp.Expression) -> exp.Expression: 83 """Remove references to unnest table aliases since bigquery doesn't allow them. 84 85 These are added by the optimizer's qualify_column step. 86 """ 87 from sqlglot.optimizer.scope import find_all_in_scope 88 89 if isinstance(expression, exp.Select): 90 unnest_aliases = { 91 unnest.alias 92 for unnest in find_all_in_scope(expression, exp.Unnest) 93 if isinstance(unnest.parent, (exp.From, exp.Join)) 94 } 95 if unnest_aliases: 96 for column in expression.find_all(exp.Column): 97 if column.table in unnest_aliases: 98 column.set("table", None) 99 elif column.db in unnest_aliases: 100 column.set("db", None) 101 102 return expression 103 104 105# https://issuetracker.google.com/issues/162294746 106# workaround for bigquery bug when grouping by an expression and then ordering 107# WITH x AS (SELECT 1 y) 108# SELECT y + 1 z 109# FROM x 110# GROUP BY x + 1 111# ORDER by z 112def _alias_ordered_group(expression: exp.Expression) -> exp.Expression: 113 if isinstance(expression, exp.Select): 114 group = expression.args.get("group") 115 order = expression.args.get("order") 116 117 if group and order: 118 aliases = { 119 select.this: select.args["alias"] 120 for select in expression.selects 121 if isinstance(select, exp.Alias) 122 } 123 124 for e in group.expressions: 125 alias = aliases.get(e) 126 127 if alias: 128 e.replace(exp.column(alias)) 129 130 return expression 131 132 133def _pushdown_cte_column_names(expression: exp.Expression) -> exp.Expression: 134 """BigQuery doesn't allow column names when defining a CTE, so we try to push them down.""" 135 if isinstance(expression, exp.CTE) and expression.alias_column_names: 136 cte_query = expression.this 137 138 if cte_query.is_star: 139 logger.warning( 140 "Can't push down CTE column names for star queries. Run the query through" 141 " the optimizer or use 'qualify' to expand the star projections first." 142 ) 143 return expression 144 145 column_names = expression.alias_column_names 146 expression.args["alias"].set("columns", None) 147 148 for name, select in zip(column_names, cte_query.selects): 149 to_replace = select 150 151 if isinstance(select, exp.Alias): 152 select = select.this 153 154 # Inner aliases are shadowed by the CTE column names 155 to_replace.replace(exp.alias_(select, name)) 156 157 return expression 158 159 160def _parse_timestamp(args: t.List) -> exp.StrToTime: 161 this = format_time_lambda(exp.StrToTime, "bigquery")([seq_get(args, 1), seq_get(args, 0)]) 162 this.set("zone", seq_get(args, 2)) 163 return this 164 165 166def _parse_date(args: t.List) -> exp.Date | exp.DateFromParts: 167 expr_type = exp.DateFromParts if len(args) == 3 else exp.Date 168 return expr_type.from_arg_list(args) 169 170 171def _parse_to_hex(args: t.List) -> exp.Hex | exp.MD5: 172 # TO_HEX(MD5(..)) is common in BigQuery, so it's parsed into MD5 to simplify its transpilation 173 arg = seq_get(args, 0) 174 return exp.MD5(this=arg.this) if isinstance(arg, exp.MD5Digest) else exp.Hex(this=arg) 175 176 177def _array_contains_sql(self: BigQuery.Generator, expression: exp.ArrayContains) -> str: 178 return self.sql( 179 exp.Exists( 180 this=exp.select("1") 181 .from_(exp.Unnest(expressions=[expression.left]).as_("_unnest", table=["_col"])) 182 .where(exp.column("_col").eq(expression.right)) 183 ) 184 ) 185 186 187class BigQuery(Dialect): 188 UNNEST_COLUMN_ONLY = True 189 SUPPORTS_USER_DEFINED_TYPES = False 190 SUPPORTS_SEMI_ANTI_JOIN = False 191 LOG_BASE_FIRST = False 192 193 # https://cloud.google.com/bigquery/docs/reference/standard-sql/lexical#case_sensitivity 194 RESOLVES_IDENTIFIERS_AS_UPPERCASE = None 195 196 # bigquery udfs are case sensitive 197 NORMALIZE_FUNCTIONS = False 198 199 TIME_MAPPING = { 200 "%D": "%m/%d/%y", 201 } 202 203 ESCAPE_SEQUENCES = { 204 "\\a": "\a", 205 "\\b": "\b", 206 "\\f": "\f", 207 "\\n": "\n", 208 "\\r": "\r", 209 "\\t": "\t", 210 "\\v": "\v", 211 } 212 213 FORMAT_MAPPING = { 214 "DD": "%d", 215 "MM": "%m", 216 "MON": "%b", 217 "MONTH": "%B", 218 "YYYY": "%Y", 219 "YY": "%y", 220 "HH": "%I", 221 "HH12": "%I", 222 "HH24": "%H", 223 "MI": "%M", 224 "SS": "%S", 225 "SSSSS": "%f", 226 "TZH": "%z", 227 } 228 229 # The _PARTITIONTIME and _PARTITIONDATE pseudo-columns are not returned by a SELECT * statement 230 # https://cloud.google.com/bigquery/docs/querying-partitioned-tables#query_an_ingestion-time_partitioned_table 231 PSEUDOCOLUMNS = {"_PARTITIONTIME", "_PARTITIONDATE"} 232 233 @classmethod 234 def normalize_identifier(cls, expression: E) -> E: 235 if isinstance(expression, exp.Identifier): 236 parent = expression.parent 237 while isinstance(parent, exp.Dot): 238 parent = parent.parent 239 240 # In BigQuery, CTEs aren't case-sensitive, but table names are (by default, at least). 241 # The following check is essentially a heuristic to detect tables based on whether or 242 # not they're qualified. It also avoids normalizing UDFs, because they're case-sensitive. 243 if ( 244 not isinstance(parent, exp.UserDefinedFunction) 245 and not (isinstance(parent, exp.Table) and parent.db) 246 and not expression.meta.get("is_table") 247 ): 248 expression.set("this", expression.this.lower()) 249 250 return expression 251 252 class Tokenizer(tokens.Tokenizer): 253 QUOTES = ["'", '"', '"""', "'''"] 254 COMMENTS = ["--", "#", ("/*", "*/")] 255 IDENTIFIERS = ["`"] 256 STRING_ESCAPES = ["\\"] 257 258 HEX_STRINGS = [("0x", ""), ("0X", "")] 259 260 BYTE_STRINGS = [ 261 (prefix + q, q) for q in t.cast(t.List[str], QUOTES) for prefix in ("b", "B") 262 ] 263 264 RAW_STRINGS = [ 265 (prefix + q, q) for q in t.cast(t.List[str], QUOTES) for prefix in ("r", "R") 266 ] 267 268 KEYWORDS = { 269 **tokens.Tokenizer.KEYWORDS, 270 "ANY TYPE": TokenType.VARIANT, 271 "BEGIN": TokenType.COMMAND, 272 "BEGIN TRANSACTION": TokenType.BEGIN, 273 "BYTES": TokenType.BINARY, 274 "CURRENT_DATETIME": TokenType.CURRENT_DATETIME, 275 "DECLARE": TokenType.COMMAND, 276 "FLOAT64": TokenType.DOUBLE, 277 "FOR SYSTEM_TIME": TokenType.TIMESTAMP_SNAPSHOT, 278 "MODEL": TokenType.MODEL, 279 "NOT DETERMINISTIC": TokenType.VOLATILE, 280 "RECORD": TokenType.STRUCT, 281 "TIMESTAMP": TokenType.TIMESTAMPTZ, 282 } 283 KEYWORDS.pop("DIV") 284 285 class Parser(parser.Parser): 286 PREFIXED_PIVOT_COLUMNS = True 287 288 LOG_DEFAULTS_TO_LN = True 289 290 FUNCTIONS = { 291 **parser.Parser.FUNCTIONS, 292 "DATE": _parse_date, 293 "DATE_ADD": parse_date_delta_with_interval(exp.DateAdd), 294 "DATE_SUB": parse_date_delta_with_interval(exp.DateSub), 295 "DATE_TRUNC": lambda args: exp.DateTrunc( 296 unit=exp.Literal.string(str(seq_get(args, 1))), 297 this=seq_get(args, 0), 298 ), 299 "DATETIME_ADD": parse_date_delta_with_interval(exp.DatetimeAdd), 300 "DATETIME_SUB": parse_date_delta_with_interval(exp.DatetimeSub), 301 "DIV": binary_from_function(exp.IntDiv), 302 "GENERATE_ARRAY": exp.GenerateSeries.from_arg_list, 303 "MD5": exp.MD5Digest.from_arg_list, 304 "TO_HEX": _parse_to_hex, 305 "PARSE_DATE": lambda args: format_time_lambda(exp.StrToDate, "bigquery")( 306 [seq_get(args, 1), seq_get(args, 0)] 307 ), 308 "PARSE_TIMESTAMP": _parse_timestamp, 309 "REGEXP_CONTAINS": exp.RegexpLike.from_arg_list, 310 "REGEXP_EXTRACT": lambda args: exp.RegexpExtract( 311 this=seq_get(args, 0), 312 expression=seq_get(args, 1), 313 position=seq_get(args, 2), 314 occurrence=seq_get(args, 3), 315 group=exp.Literal.number(1) if re.compile(args[1].name).groups == 1 else None, 316 ), 317 "SHA256": lambda args: exp.SHA2(this=seq_get(args, 0), length=exp.Literal.number(256)), 318 "SHA512": lambda args: exp.SHA2(this=seq_get(args, 0), length=exp.Literal.number(512)), 319 "SPLIT": lambda args: exp.Split( 320 # https://cloud.google.com/bigquery/docs/reference/standard-sql/string_functions#split 321 this=seq_get(args, 0), 322 expression=seq_get(args, 1) or exp.Literal.string(","), 323 ), 324 "TIME_ADD": parse_date_delta_with_interval(exp.TimeAdd), 325 "TIME_SUB": parse_date_delta_with_interval(exp.TimeSub), 326 "TIMESTAMP_ADD": parse_date_delta_with_interval(exp.TimestampAdd), 327 "TIMESTAMP_SUB": parse_date_delta_with_interval(exp.TimestampSub), 328 "TO_JSON_STRING": exp.JSONFormat.from_arg_list, 329 } 330 331 FUNCTION_PARSERS = { 332 **parser.Parser.FUNCTION_PARSERS, 333 "ARRAY": lambda self: self.expression(exp.Array, expressions=[self._parse_statement()]), 334 } 335 FUNCTION_PARSERS.pop("TRIM") 336 337 NO_PAREN_FUNCTIONS = { 338 **parser.Parser.NO_PAREN_FUNCTIONS, 339 TokenType.CURRENT_DATETIME: exp.CurrentDatetime, 340 } 341 342 NESTED_TYPE_TOKENS = { 343 *parser.Parser.NESTED_TYPE_TOKENS, 344 TokenType.TABLE, 345 } 346 347 ID_VAR_TOKENS = { 348 *parser.Parser.ID_VAR_TOKENS, 349 TokenType.VALUES, 350 } 351 352 PROPERTY_PARSERS = { 353 **parser.Parser.PROPERTY_PARSERS, 354 "NOT DETERMINISTIC": lambda self: self.expression( 355 exp.StabilityProperty, this=exp.Literal.string("VOLATILE") 356 ), 357 "OPTIONS": lambda self: self._parse_with_property(), 358 } 359 360 CONSTRAINT_PARSERS = { 361 **parser.Parser.CONSTRAINT_PARSERS, 362 "OPTIONS": lambda self: exp.Properties(expressions=self._parse_with_property()), 363 } 364 365 RANGE_PARSERS = parser.Parser.RANGE_PARSERS.copy() 366 RANGE_PARSERS.pop(TokenType.OVERLAPS, None) 367 368 NULL_TOKENS = {TokenType.NULL, TokenType.UNKNOWN} 369 370 STATEMENT_PARSERS = { 371 **parser.Parser.STATEMENT_PARSERS, 372 TokenType.END: lambda self: self._parse_as_command(self._prev), 373 TokenType.FOR: lambda self: self._parse_for_in(), 374 } 375 376 def _parse_for_in(self) -> exp.ForIn: 377 this = self._parse_range() 378 self._match_text_seq("DO") 379 return self.expression(exp.ForIn, this=this, expression=self._parse_statement()) 380 381 def _parse_table_part(self, schema: bool = False) -> t.Optional[exp.Expression]: 382 this = super()._parse_table_part(schema=schema) or self._parse_number() 383 384 # https://cloud.google.com/bigquery/docs/reference/standard-sql/lexical#table_names 385 if isinstance(this, exp.Identifier): 386 table_name = this.name 387 while self._match(TokenType.DASH, advance=False) and self._next: 388 self._advance(2) 389 table_name += f"-{self._prev.text}" 390 391 this = exp.Identifier(this=table_name, quoted=this.args.get("quoted")) 392 elif isinstance(this, exp.Literal): 393 table_name = this.name 394 395 if ( 396 self._curr 397 and self._prev.end == self._curr.start - 1 398 and self._parse_var(any_token=True) 399 ): 400 table_name += self._prev.text 401 402 this = exp.Identifier(this=table_name, quoted=True) 403 404 return this 405 406 def _parse_table_parts(self, schema: bool = False) -> exp.Table: 407 table = super()._parse_table_parts(schema=schema) 408 if isinstance(table.this, exp.Identifier) and "." in table.name: 409 catalog, db, this, *rest = ( 410 t.cast(t.Optional[exp.Expression], exp.to_identifier(x)) 411 for x in split_num_words(table.name, ".", 3) 412 ) 413 414 if rest and this: 415 this = exp.Dot.build(t.cast(t.List[exp.Expression], [this, *rest])) 416 417 table = exp.Table(this=this, db=db, catalog=catalog) 418 419 return table 420 421 def _parse_json_object(self) -> exp.JSONObject: 422 json_object = super()._parse_json_object() 423 array_kv_pair = seq_get(json_object.expressions, 0) 424 425 # Converts BQ's "signature 2" of JSON_OBJECT into SQLGlot's canonical representation 426 # https://cloud.google.com/bigquery/docs/reference/standard-sql/json_functions#json_object_signature2 427 if ( 428 array_kv_pair 429 and isinstance(array_kv_pair.this, exp.Array) 430 and isinstance(array_kv_pair.expression, exp.Array) 431 ): 432 keys = array_kv_pair.this.expressions 433 values = array_kv_pair.expression.expressions 434 435 json_object.set( 436 "expressions", 437 [exp.JSONKeyValue(this=k, expression=v) for k, v in zip(keys, values)], 438 ) 439 440 return json_object 441 442 class Generator(generator.Generator): 443 EXPLICIT_UNION = True 444 INTERVAL_ALLOWS_PLURAL_FORM = False 445 JOIN_HINTS = False 446 QUERY_HINTS = False 447 TABLE_HINTS = False 448 LIMIT_FETCH = "LIMIT" 449 RENAME_TABLE_WITH_DB = False 450 NVL2_SUPPORTED = False 451 UNNEST_WITH_ORDINALITY = False 452 COLLATE_IS_FUNC = True 453 454 TRANSFORMS = { 455 **generator.Generator.TRANSFORMS, 456 exp.ApproxDistinct: rename_func("APPROX_COUNT_DISTINCT"), 457 exp.ArgMax: arg_max_or_min_no_count("MAX_BY"), 458 exp.ArgMin: arg_max_or_min_no_count("MIN_BY"), 459 exp.ArrayContains: _array_contains_sql, 460 exp.ArraySize: rename_func("ARRAY_LENGTH"), 461 exp.Cast: transforms.preprocess([transforms.remove_precision_parameterized_types]), 462 exp.CollateProperty: lambda self, e: f"DEFAULT COLLATE {self.sql(e, 'this')}" 463 if e.args.get("default") 464 else f"COLLATE {self.sql(e, 'this')}", 465 exp.Create: _create_sql, 466 exp.CTE: transforms.preprocess([_pushdown_cte_column_names]), 467 exp.DateAdd: date_add_interval_sql("DATE", "ADD"), 468 exp.DateDiff: lambda self, e: f"DATE_DIFF({self.sql(e, 'this')}, {self.sql(e, 'expression')}, {self.sql(e.args.get('unit', 'DAY'))})", 469 exp.DateFromParts: rename_func("DATE"), 470 exp.DateStrToDate: datestrtodate_sql, 471 exp.DateSub: date_add_interval_sql("DATE", "SUB"), 472 exp.DatetimeAdd: date_add_interval_sql("DATETIME", "ADD"), 473 exp.DatetimeSub: date_add_interval_sql("DATETIME", "SUB"), 474 exp.DateTrunc: lambda self, e: self.func("DATE_TRUNC", e.this, e.text("unit")), 475 exp.GenerateSeries: rename_func("GENERATE_ARRAY"), 476 exp.GroupConcat: rename_func("STRING_AGG"), 477 exp.Hex: rename_func("TO_HEX"), 478 exp.If: if_sql(false_value="NULL"), 479 exp.ILike: no_ilike_sql, 480 exp.IntDiv: rename_func("DIV"), 481 exp.JSONFormat: rename_func("TO_JSON_STRING"), 482 exp.JSONKeyValue: json_keyvalue_comma_sql, 483 exp.Max: max_or_greatest, 484 exp.MD5: lambda self, e: self.func("TO_HEX", self.func("MD5", e.this)), 485 exp.MD5Digest: rename_func("MD5"), 486 exp.Min: min_or_least, 487 exp.PartitionedByProperty: lambda self, e: f"PARTITION BY {self.sql(e, 'this')}", 488 exp.RegexpExtract: lambda self, e: self.func( 489 "REGEXP_EXTRACT", 490 e.this, 491 e.expression, 492 e.args.get("position"), 493 e.args.get("occurrence"), 494 ), 495 exp.RegexpReplace: regexp_replace_sql, 496 exp.RegexpLike: rename_func("REGEXP_CONTAINS"), 497 exp.ReturnsProperty: _returnsproperty_sql, 498 exp.Select: transforms.preprocess( 499 [ 500 transforms.explode_to_unnest(), 501 _unqualify_unnest, 502 transforms.eliminate_distinct_on, 503 _alias_ordered_group, 504 transforms.eliminate_semi_and_anti_joins, 505 ] 506 ), 507 exp.SHA2: lambda self, e: self.func( 508 f"SHA256" if e.text("length") == "256" else "SHA512", e.this 509 ), 510 exp.StabilityProperty: lambda self, e: f"DETERMINISTIC" 511 if e.name == "IMMUTABLE" 512 else "NOT DETERMINISTIC", 513 exp.StrToDate: lambda self, e: f"PARSE_DATE({self.format_time(e)}, {self.sql(e, 'this')})", 514 exp.StrToTime: lambda self, e: self.func( 515 "PARSE_TIMESTAMP", self.format_time(e), e.this, e.args.get("zone") 516 ), 517 exp.TimeAdd: date_add_interval_sql("TIME", "ADD"), 518 exp.TimeSub: date_add_interval_sql("TIME", "SUB"), 519 exp.TimestampAdd: date_add_interval_sql("TIMESTAMP", "ADD"), 520 exp.TimestampSub: date_add_interval_sql("TIMESTAMP", "SUB"), 521 exp.TimeStrToTime: timestrtotime_sql, 522 exp.Trim: lambda self, e: self.func(f"TRIM", e.this, e.expression), 523 exp.TsOrDsAdd: date_add_interval_sql("DATE", "ADD"), 524 exp.TsOrDsToDate: ts_or_ds_to_date_sql("bigquery"), 525 exp.Unhex: rename_func("FROM_HEX"), 526 exp.Values: _derived_table_values_to_unnest, 527 exp.VariancePop: rename_func("VAR_POP"), 528 } 529 530 TYPE_MAPPING = { 531 **generator.Generator.TYPE_MAPPING, 532 exp.DataType.Type.BIGDECIMAL: "BIGNUMERIC", 533 exp.DataType.Type.BIGINT: "INT64", 534 exp.DataType.Type.BINARY: "BYTES", 535 exp.DataType.Type.BOOLEAN: "BOOL", 536 exp.DataType.Type.CHAR: "STRING", 537 exp.DataType.Type.DECIMAL: "NUMERIC", 538 exp.DataType.Type.DOUBLE: "FLOAT64", 539 exp.DataType.Type.FLOAT: "FLOAT64", 540 exp.DataType.Type.INT: "INT64", 541 exp.DataType.Type.NCHAR: "STRING", 542 exp.DataType.Type.NVARCHAR: "STRING", 543 exp.DataType.Type.SMALLINT: "INT64", 544 exp.DataType.Type.TEXT: "STRING", 545 exp.DataType.Type.TIMESTAMP: "DATETIME", 546 exp.DataType.Type.TIMESTAMPTZ: "TIMESTAMP", 547 exp.DataType.Type.TIMESTAMPLTZ: "TIMESTAMP", 548 exp.DataType.Type.TINYINT: "INT64", 549 exp.DataType.Type.VARBINARY: "BYTES", 550 exp.DataType.Type.VARCHAR: "STRING", 551 exp.DataType.Type.VARIANT: "ANY TYPE", 552 } 553 554 PROPERTIES_LOCATION = { 555 **generator.Generator.PROPERTIES_LOCATION, 556 exp.PartitionedByProperty: exp.Properties.Location.POST_SCHEMA, 557 exp.VolatileProperty: exp.Properties.Location.UNSUPPORTED, 558 } 559 560 # from: https://cloud.google.com/bigquery/docs/reference/standard-sql/lexical#reserved_keywords 561 RESERVED_KEYWORDS = { 562 *generator.Generator.RESERVED_KEYWORDS, 563 "all", 564 "and", 565 "any", 566 "array", 567 "as", 568 "asc", 569 "assert_rows_modified", 570 "at", 571 "between", 572 "by", 573 "case", 574 "cast", 575 "collate", 576 "contains", 577 "create", 578 "cross", 579 "cube", 580 "current", 581 "default", 582 "define", 583 "desc", 584 "distinct", 585 "else", 586 "end", 587 "enum", 588 "escape", 589 "except", 590 "exclude", 591 "exists", 592 "extract", 593 "false", 594 "fetch", 595 "following", 596 "for", 597 "from", 598 "full", 599 "group", 600 "grouping", 601 "groups", 602 "hash", 603 "having", 604 "if", 605 "ignore", 606 "in", 607 "inner", 608 "intersect", 609 "interval", 610 "into", 611 "is", 612 "join", 613 "lateral", 614 "left", 615 "like", 616 "limit", 617 "lookup", 618 "merge", 619 "natural", 620 "new", 621 "no", 622 "not", 623 "null", 624 "nulls", 625 "of", 626 "on", 627 "or", 628 "order", 629 "outer", 630 "over", 631 "partition", 632 "preceding", 633 "proto", 634 "qualify", 635 "range", 636 "recursive", 637 "respect", 638 "right", 639 "rollup", 640 "rows", 641 "select", 642 "set", 643 "some", 644 "struct", 645 "tablesample", 646 "then", 647 "to", 648 "treat", 649 "true", 650 "unbounded", 651 "union", 652 "unnest", 653 "using", 654 "when", 655 "where", 656 "window", 657 "with", 658 "within", 659 } 660 661 def eq_sql(self, expression: exp.EQ) -> str: 662 # Operands of = cannot be NULL in BigQuery 663 if isinstance(expression.left, exp.Null) or isinstance(expression.right, exp.Null): 664 return "NULL" 665 666 return self.binary(expression, "=") 667 668 def attimezone_sql(self, expression: exp.AtTimeZone) -> str: 669 parent = expression.parent 670 671 # BigQuery allows CAST(.. AS {STRING|TIMESTAMP} [FORMAT <fmt> [AT TIME ZONE <tz>]]). 672 # Only the TIMESTAMP one should use the below conversion, when AT TIME ZONE is included. 673 if not isinstance(parent, exp.Cast) or not parent.to.is_type("text"): 674 return self.func( 675 "TIMESTAMP", self.func("DATETIME", expression.this, expression.args.get("zone")) 676 ) 677 678 return super().attimezone_sql(expression) 679 680 def trycast_sql(self, expression: exp.TryCast) -> str: 681 return self.cast_sql(expression, safe_prefix="SAFE_") 682 683 def cte_sql(self, expression: exp.CTE) -> str: 684 if expression.alias_column_names: 685 self.unsupported("Column names in CTE definition are not supported.") 686 return super().cte_sql(expression) 687 688 def array_sql(self, expression: exp.Array) -> str: 689 first_arg = seq_get(expression.expressions, 0) 690 if isinstance(first_arg, exp.Subqueryable): 691 return f"ARRAY{self.wrap(self.sql(first_arg))}" 692 693 return inline_array_sql(self, expression) 694 695 def transaction_sql(self, *_) -> str: 696 return "BEGIN TRANSACTION" 697 698 def commit_sql(self, *_) -> str: 699 return "COMMIT TRANSACTION" 700 701 def rollback_sql(self, *_) -> str: 702 return "ROLLBACK TRANSACTION" 703 704 def in_unnest_op(self, expression: exp.Unnest) -> str: 705 return self.sql(expression) 706 707 def except_op(self, expression: exp.Except) -> str: 708 if not expression.args.get("distinct", False): 709 self.unsupported("EXCEPT without DISTINCT is not supported in BigQuery") 710 return f"EXCEPT{' DISTINCT' if expression.args.get('distinct') else ' ALL'}" 711 712 def intersect_op(self, expression: exp.Intersect) -> str: 713 if not expression.args.get("distinct", False): 714 self.unsupported("INTERSECT without DISTINCT is not supported in BigQuery") 715 return f"INTERSECT{' DISTINCT' if expression.args.get('distinct') else ' ALL'}" 716 717 def with_properties(self, properties: exp.Properties) -> str: 718 return self.properties(properties, prefix=self.seg("OPTIONS")) 719 720 def version_sql(self, expression: exp.Version) -> str: 721 if expression.name == "TIMESTAMP": 722 expression.set("this", "SYSTEM_TIME") 723 return super().version_sql(expression)
logger =
<Logger sqlglot (WARNING)>
188class BigQuery(Dialect): 189 UNNEST_COLUMN_ONLY = True 190 SUPPORTS_USER_DEFINED_TYPES = False 191 SUPPORTS_SEMI_ANTI_JOIN = False 192 LOG_BASE_FIRST = False 193 194 # https://cloud.google.com/bigquery/docs/reference/standard-sql/lexical#case_sensitivity 195 RESOLVES_IDENTIFIERS_AS_UPPERCASE = None 196 197 # bigquery udfs are case sensitive 198 NORMALIZE_FUNCTIONS = False 199 200 TIME_MAPPING = { 201 "%D": "%m/%d/%y", 202 } 203 204 ESCAPE_SEQUENCES = { 205 "\\a": "\a", 206 "\\b": "\b", 207 "\\f": "\f", 208 "\\n": "\n", 209 "\\r": "\r", 210 "\\t": "\t", 211 "\\v": "\v", 212 } 213 214 FORMAT_MAPPING = { 215 "DD": "%d", 216 "MM": "%m", 217 "MON": "%b", 218 "MONTH": "%B", 219 "YYYY": "%Y", 220 "YY": "%y", 221 "HH": "%I", 222 "HH12": "%I", 223 "HH24": "%H", 224 "MI": "%M", 225 "SS": "%S", 226 "SSSSS": "%f", 227 "TZH": "%z", 228 } 229 230 # The _PARTITIONTIME and _PARTITIONDATE pseudo-columns are not returned by a SELECT * statement 231 # https://cloud.google.com/bigquery/docs/querying-partitioned-tables#query_an_ingestion-time_partitioned_table 232 PSEUDOCOLUMNS = {"_PARTITIONTIME", "_PARTITIONDATE"} 233 234 @classmethod 235 def normalize_identifier(cls, expression: E) -> E: 236 if isinstance(expression, exp.Identifier): 237 parent = expression.parent 238 while isinstance(parent, exp.Dot): 239 parent = parent.parent 240 241 # In BigQuery, CTEs aren't case-sensitive, but table names are (by default, at least). 242 # The following check is essentially a heuristic to detect tables based on whether or 243 # not they're qualified. It also avoids normalizing UDFs, because they're case-sensitive. 244 if ( 245 not isinstance(parent, exp.UserDefinedFunction) 246 and not (isinstance(parent, exp.Table) and parent.db) 247 and not expression.meta.get("is_table") 248 ): 249 expression.set("this", expression.this.lower()) 250 251 return expression 252 253 class Tokenizer(tokens.Tokenizer): 254 QUOTES = ["'", '"', '"""', "'''"] 255 COMMENTS = ["--", "#", ("/*", "*/")] 256 IDENTIFIERS = ["`"] 257 STRING_ESCAPES = ["\\"] 258 259 HEX_STRINGS = [("0x", ""), ("0X", "")] 260 261 BYTE_STRINGS = [ 262 (prefix + q, q) for q in t.cast(t.List[str], QUOTES) for prefix in ("b", "B") 263 ] 264 265 RAW_STRINGS = [ 266 (prefix + q, q) for q in t.cast(t.List[str], QUOTES) for prefix in ("r", "R") 267 ] 268 269 KEYWORDS = { 270 **tokens.Tokenizer.KEYWORDS, 271 "ANY TYPE": TokenType.VARIANT, 272 "BEGIN": TokenType.COMMAND, 273 "BEGIN TRANSACTION": TokenType.BEGIN, 274 "BYTES": TokenType.BINARY, 275 "CURRENT_DATETIME": TokenType.CURRENT_DATETIME, 276 "DECLARE": TokenType.COMMAND, 277 "FLOAT64": TokenType.DOUBLE, 278 "FOR SYSTEM_TIME": TokenType.TIMESTAMP_SNAPSHOT, 279 "MODEL": TokenType.MODEL, 280 "NOT DETERMINISTIC": TokenType.VOLATILE, 281 "RECORD": TokenType.STRUCT, 282 "TIMESTAMP": TokenType.TIMESTAMPTZ, 283 } 284 KEYWORDS.pop("DIV") 285 286 class Parser(parser.Parser): 287 PREFIXED_PIVOT_COLUMNS = True 288 289 LOG_DEFAULTS_TO_LN = True 290 291 FUNCTIONS = { 292 **parser.Parser.FUNCTIONS, 293 "DATE": _parse_date, 294 "DATE_ADD": parse_date_delta_with_interval(exp.DateAdd), 295 "DATE_SUB": parse_date_delta_with_interval(exp.DateSub), 296 "DATE_TRUNC": lambda args: exp.DateTrunc( 297 unit=exp.Literal.string(str(seq_get(args, 1))), 298 this=seq_get(args, 0), 299 ), 300 "DATETIME_ADD": parse_date_delta_with_interval(exp.DatetimeAdd), 301 "DATETIME_SUB": parse_date_delta_with_interval(exp.DatetimeSub), 302 "DIV": binary_from_function(exp.IntDiv), 303 "GENERATE_ARRAY": exp.GenerateSeries.from_arg_list, 304 "MD5": exp.MD5Digest.from_arg_list, 305 "TO_HEX": _parse_to_hex, 306 "PARSE_DATE": lambda args: format_time_lambda(exp.StrToDate, "bigquery")( 307 [seq_get(args, 1), seq_get(args, 0)] 308 ), 309 "PARSE_TIMESTAMP": _parse_timestamp, 310 "REGEXP_CONTAINS": exp.RegexpLike.from_arg_list, 311 "REGEXP_EXTRACT": lambda args: exp.RegexpExtract( 312 this=seq_get(args, 0), 313 expression=seq_get(args, 1), 314 position=seq_get(args, 2), 315 occurrence=seq_get(args, 3), 316 group=exp.Literal.number(1) if re.compile(args[1].name).groups == 1 else None, 317 ), 318 "SHA256": lambda args: exp.SHA2(this=seq_get(args, 0), length=exp.Literal.number(256)), 319 "SHA512": lambda args: exp.SHA2(this=seq_get(args, 0), length=exp.Literal.number(512)), 320 "SPLIT": lambda args: exp.Split( 321 # https://cloud.google.com/bigquery/docs/reference/standard-sql/string_functions#split 322 this=seq_get(args, 0), 323 expression=seq_get(args, 1) or exp.Literal.string(","), 324 ), 325 "TIME_ADD": parse_date_delta_with_interval(exp.TimeAdd), 326 "TIME_SUB": parse_date_delta_with_interval(exp.TimeSub), 327 "TIMESTAMP_ADD": parse_date_delta_with_interval(exp.TimestampAdd), 328 "TIMESTAMP_SUB": parse_date_delta_with_interval(exp.TimestampSub), 329 "TO_JSON_STRING": exp.JSONFormat.from_arg_list, 330 } 331 332 FUNCTION_PARSERS = { 333 **parser.Parser.FUNCTION_PARSERS, 334 "ARRAY": lambda self: self.expression(exp.Array, expressions=[self._parse_statement()]), 335 } 336 FUNCTION_PARSERS.pop("TRIM") 337 338 NO_PAREN_FUNCTIONS = { 339 **parser.Parser.NO_PAREN_FUNCTIONS, 340 TokenType.CURRENT_DATETIME: exp.CurrentDatetime, 341 } 342 343 NESTED_TYPE_TOKENS = { 344 *parser.Parser.NESTED_TYPE_TOKENS, 345 TokenType.TABLE, 346 } 347 348 ID_VAR_TOKENS = { 349 *parser.Parser.ID_VAR_TOKENS, 350 TokenType.VALUES, 351 } 352 353 PROPERTY_PARSERS = { 354 **parser.Parser.PROPERTY_PARSERS, 355 "NOT DETERMINISTIC": lambda self: self.expression( 356 exp.StabilityProperty, this=exp.Literal.string("VOLATILE") 357 ), 358 "OPTIONS": lambda self: self._parse_with_property(), 359 } 360 361 CONSTRAINT_PARSERS = { 362 **parser.Parser.CONSTRAINT_PARSERS, 363 "OPTIONS": lambda self: exp.Properties(expressions=self._parse_with_property()), 364 } 365 366 RANGE_PARSERS = parser.Parser.RANGE_PARSERS.copy() 367 RANGE_PARSERS.pop(TokenType.OVERLAPS, None) 368 369 NULL_TOKENS = {TokenType.NULL, TokenType.UNKNOWN} 370 371 STATEMENT_PARSERS = { 372 **parser.Parser.STATEMENT_PARSERS, 373 TokenType.END: lambda self: self._parse_as_command(self._prev), 374 TokenType.FOR: lambda self: self._parse_for_in(), 375 } 376 377 def _parse_for_in(self) -> exp.ForIn: 378 this = self._parse_range() 379 self._match_text_seq("DO") 380 return self.expression(exp.ForIn, this=this, expression=self._parse_statement()) 381 382 def _parse_table_part(self, schema: bool = False) -> t.Optional[exp.Expression]: 383 this = super()._parse_table_part(schema=schema) or self._parse_number() 384 385 # https://cloud.google.com/bigquery/docs/reference/standard-sql/lexical#table_names 386 if isinstance(this, exp.Identifier): 387 table_name = this.name 388 while self._match(TokenType.DASH, advance=False) and self._next: 389 self._advance(2) 390 table_name += f"-{self._prev.text}" 391 392 this = exp.Identifier(this=table_name, quoted=this.args.get("quoted")) 393 elif isinstance(this, exp.Literal): 394 table_name = this.name 395 396 if ( 397 self._curr 398 and self._prev.end == self._curr.start - 1 399 and self._parse_var(any_token=True) 400 ): 401 table_name += self._prev.text 402 403 this = exp.Identifier(this=table_name, quoted=True) 404 405 return this 406 407 def _parse_table_parts(self, schema: bool = False) -> exp.Table: 408 table = super()._parse_table_parts(schema=schema) 409 if isinstance(table.this, exp.Identifier) and "." in table.name: 410 catalog, db, this, *rest = ( 411 t.cast(t.Optional[exp.Expression], exp.to_identifier(x)) 412 for x in split_num_words(table.name, ".", 3) 413 ) 414 415 if rest and this: 416 this = exp.Dot.build(t.cast(t.List[exp.Expression], [this, *rest])) 417 418 table = exp.Table(this=this, db=db, catalog=catalog) 419 420 return table 421 422 def _parse_json_object(self) -> exp.JSONObject: 423 json_object = super()._parse_json_object() 424 array_kv_pair = seq_get(json_object.expressions, 0) 425 426 # Converts BQ's "signature 2" of JSON_OBJECT into SQLGlot's canonical representation 427 # https://cloud.google.com/bigquery/docs/reference/standard-sql/json_functions#json_object_signature2 428 if ( 429 array_kv_pair 430 and isinstance(array_kv_pair.this, exp.Array) 431 and isinstance(array_kv_pair.expression, exp.Array) 432 ): 433 keys = array_kv_pair.this.expressions 434 values = array_kv_pair.expression.expressions 435 436 json_object.set( 437 "expressions", 438 [exp.JSONKeyValue(this=k, expression=v) for k, v in zip(keys, values)], 439 ) 440 441 return json_object 442 443 class Generator(generator.Generator): 444 EXPLICIT_UNION = True 445 INTERVAL_ALLOWS_PLURAL_FORM = False 446 JOIN_HINTS = False 447 QUERY_HINTS = False 448 TABLE_HINTS = False 449 LIMIT_FETCH = "LIMIT" 450 RENAME_TABLE_WITH_DB = False 451 NVL2_SUPPORTED = False 452 UNNEST_WITH_ORDINALITY = False 453 COLLATE_IS_FUNC = True 454 455 TRANSFORMS = { 456 **generator.Generator.TRANSFORMS, 457 exp.ApproxDistinct: rename_func("APPROX_COUNT_DISTINCT"), 458 exp.ArgMax: arg_max_or_min_no_count("MAX_BY"), 459 exp.ArgMin: arg_max_or_min_no_count("MIN_BY"), 460 exp.ArrayContains: _array_contains_sql, 461 exp.ArraySize: rename_func("ARRAY_LENGTH"), 462 exp.Cast: transforms.preprocess([transforms.remove_precision_parameterized_types]), 463 exp.CollateProperty: lambda self, e: f"DEFAULT COLLATE {self.sql(e, 'this')}" 464 if e.args.get("default") 465 else f"COLLATE {self.sql(e, 'this')}", 466 exp.Create: _create_sql, 467 exp.CTE: transforms.preprocess([_pushdown_cte_column_names]), 468 exp.DateAdd: date_add_interval_sql("DATE", "ADD"), 469 exp.DateDiff: lambda self, e: f"DATE_DIFF({self.sql(e, 'this')}, {self.sql(e, 'expression')}, {self.sql(e.args.get('unit', 'DAY'))})", 470 exp.DateFromParts: rename_func("DATE"), 471 exp.DateStrToDate: datestrtodate_sql, 472 exp.DateSub: date_add_interval_sql("DATE", "SUB"), 473 exp.DatetimeAdd: date_add_interval_sql("DATETIME", "ADD"), 474 exp.DatetimeSub: date_add_interval_sql("DATETIME", "SUB"), 475 exp.DateTrunc: lambda self, e: self.func("DATE_TRUNC", e.this, e.text("unit")), 476 exp.GenerateSeries: rename_func("GENERATE_ARRAY"), 477 exp.GroupConcat: rename_func("STRING_AGG"), 478 exp.Hex: rename_func("TO_HEX"), 479 exp.If: if_sql(false_value="NULL"), 480 exp.ILike: no_ilike_sql, 481 exp.IntDiv: rename_func("DIV"), 482 exp.JSONFormat: rename_func("TO_JSON_STRING"), 483 exp.JSONKeyValue: json_keyvalue_comma_sql, 484 exp.Max: max_or_greatest, 485 exp.MD5: lambda self, e: self.func("TO_HEX", self.func("MD5", e.this)), 486 exp.MD5Digest: rename_func("MD5"), 487 exp.Min: min_or_least, 488 exp.PartitionedByProperty: lambda self, e: f"PARTITION BY {self.sql(e, 'this')}", 489 exp.RegexpExtract: lambda self, e: self.func( 490 "REGEXP_EXTRACT", 491 e.this, 492 e.expression, 493 e.args.get("position"), 494 e.args.get("occurrence"), 495 ), 496 exp.RegexpReplace: regexp_replace_sql, 497 exp.RegexpLike: rename_func("REGEXP_CONTAINS"), 498 exp.ReturnsProperty: _returnsproperty_sql, 499 exp.Select: transforms.preprocess( 500 [ 501 transforms.explode_to_unnest(), 502 _unqualify_unnest, 503 transforms.eliminate_distinct_on, 504 _alias_ordered_group, 505 transforms.eliminate_semi_and_anti_joins, 506 ] 507 ), 508 exp.SHA2: lambda self, e: self.func( 509 f"SHA256" if e.text("length") == "256" else "SHA512", e.this 510 ), 511 exp.StabilityProperty: lambda self, e: f"DETERMINISTIC" 512 if e.name == "IMMUTABLE" 513 else "NOT DETERMINISTIC", 514 exp.StrToDate: lambda self, e: f"PARSE_DATE({self.format_time(e)}, {self.sql(e, 'this')})", 515 exp.StrToTime: lambda self, e: self.func( 516 "PARSE_TIMESTAMP", self.format_time(e), e.this, e.args.get("zone") 517 ), 518 exp.TimeAdd: date_add_interval_sql("TIME", "ADD"), 519 exp.TimeSub: date_add_interval_sql("TIME", "SUB"), 520 exp.TimestampAdd: date_add_interval_sql("TIMESTAMP", "ADD"), 521 exp.TimestampSub: date_add_interval_sql("TIMESTAMP", "SUB"), 522 exp.TimeStrToTime: timestrtotime_sql, 523 exp.Trim: lambda self, e: self.func(f"TRIM", e.this, e.expression), 524 exp.TsOrDsAdd: date_add_interval_sql("DATE", "ADD"), 525 exp.TsOrDsToDate: ts_or_ds_to_date_sql("bigquery"), 526 exp.Unhex: rename_func("FROM_HEX"), 527 exp.Values: _derived_table_values_to_unnest, 528 exp.VariancePop: rename_func("VAR_POP"), 529 } 530 531 TYPE_MAPPING = { 532 **generator.Generator.TYPE_MAPPING, 533 exp.DataType.Type.BIGDECIMAL: "BIGNUMERIC", 534 exp.DataType.Type.BIGINT: "INT64", 535 exp.DataType.Type.BINARY: "BYTES", 536 exp.DataType.Type.BOOLEAN: "BOOL", 537 exp.DataType.Type.CHAR: "STRING", 538 exp.DataType.Type.DECIMAL: "NUMERIC", 539 exp.DataType.Type.DOUBLE: "FLOAT64", 540 exp.DataType.Type.FLOAT: "FLOAT64", 541 exp.DataType.Type.INT: "INT64", 542 exp.DataType.Type.NCHAR: "STRING", 543 exp.DataType.Type.NVARCHAR: "STRING", 544 exp.DataType.Type.SMALLINT: "INT64", 545 exp.DataType.Type.TEXT: "STRING", 546 exp.DataType.Type.TIMESTAMP: "DATETIME", 547 exp.DataType.Type.TIMESTAMPTZ: "TIMESTAMP", 548 exp.DataType.Type.TIMESTAMPLTZ: "TIMESTAMP", 549 exp.DataType.Type.TINYINT: "INT64", 550 exp.DataType.Type.VARBINARY: "BYTES", 551 exp.DataType.Type.VARCHAR: "STRING", 552 exp.DataType.Type.VARIANT: "ANY TYPE", 553 } 554 555 PROPERTIES_LOCATION = { 556 **generator.Generator.PROPERTIES_LOCATION, 557 exp.PartitionedByProperty: exp.Properties.Location.POST_SCHEMA, 558 exp.VolatileProperty: exp.Properties.Location.UNSUPPORTED, 559 } 560 561 # from: https://cloud.google.com/bigquery/docs/reference/standard-sql/lexical#reserved_keywords 562 RESERVED_KEYWORDS = { 563 *generator.Generator.RESERVED_KEYWORDS, 564 "all", 565 "and", 566 "any", 567 "array", 568 "as", 569 "asc", 570 "assert_rows_modified", 571 "at", 572 "between", 573 "by", 574 "case", 575 "cast", 576 "collate", 577 "contains", 578 "create", 579 "cross", 580 "cube", 581 "current", 582 "default", 583 "define", 584 "desc", 585 "distinct", 586 "else", 587 "end", 588 "enum", 589 "escape", 590 "except", 591 "exclude", 592 "exists", 593 "extract", 594 "false", 595 "fetch", 596 "following", 597 "for", 598 "from", 599 "full", 600 "group", 601 "grouping", 602 "groups", 603 "hash", 604 "having", 605 "if", 606 "ignore", 607 "in", 608 "inner", 609 "intersect", 610 "interval", 611 "into", 612 "is", 613 "join", 614 "lateral", 615 "left", 616 "like", 617 "limit", 618 "lookup", 619 "merge", 620 "natural", 621 "new", 622 "no", 623 "not", 624 "null", 625 "nulls", 626 "of", 627 "on", 628 "or", 629 "order", 630 "outer", 631 "over", 632 "partition", 633 "preceding", 634 "proto", 635 "qualify", 636 "range", 637 "recursive", 638 "respect", 639 "right", 640 "rollup", 641 "rows", 642 "select", 643 "set", 644 "some", 645 "struct", 646 "tablesample", 647 "then", 648 "to", 649 "treat", 650 "true", 651 "unbounded", 652 "union", 653 "unnest", 654 "using", 655 "when", 656 "where", 657 "window", 658 "with", 659 "within", 660 } 661 662 def eq_sql(self, expression: exp.EQ) -> str: 663 # Operands of = cannot be NULL in BigQuery 664 if isinstance(expression.left, exp.Null) or isinstance(expression.right, exp.Null): 665 return "NULL" 666 667 return self.binary(expression, "=") 668 669 def attimezone_sql(self, expression: exp.AtTimeZone) -> str: 670 parent = expression.parent 671 672 # BigQuery allows CAST(.. AS {STRING|TIMESTAMP} [FORMAT <fmt> [AT TIME ZONE <tz>]]). 673 # Only the TIMESTAMP one should use the below conversion, when AT TIME ZONE is included. 674 if not isinstance(parent, exp.Cast) or not parent.to.is_type("text"): 675 return self.func( 676 "TIMESTAMP", self.func("DATETIME", expression.this, expression.args.get("zone")) 677 ) 678 679 return super().attimezone_sql(expression) 680 681 def trycast_sql(self, expression: exp.TryCast) -> str: 682 return self.cast_sql(expression, safe_prefix="SAFE_") 683 684 def cte_sql(self, expression: exp.CTE) -> str: 685 if expression.alias_column_names: 686 self.unsupported("Column names in CTE definition are not supported.") 687 return super().cte_sql(expression) 688 689 def array_sql(self, expression: exp.Array) -> str: 690 first_arg = seq_get(expression.expressions, 0) 691 if isinstance(first_arg, exp.Subqueryable): 692 return f"ARRAY{self.wrap(self.sql(first_arg))}" 693 694 return inline_array_sql(self, expression) 695 696 def transaction_sql(self, *_) -> str: 697 return "BEGIN TRANSACTION" 698 699 def commit_sql(self, *_) -> str: 700 return "COMMIT TRANSACTION" 701 702 def rollback_sql(self, *_) -> str: 703 return "ROLLBACK TRANSACTION" 704 705 def in_unnest_op(self, expression: exp.Unnest) -> str: 706 return self.sql(expression) 707 708 def except_op(self, expression: exp.Except) -> str: 709 if not expression.args.get("distinct", False): 710 self.unsupported("EXCEPT without DISTINCT is not supported in BigQuery") 711 return f"EXCEPT{' DISTINCT' if expression.args.get('distinct') else ' ALL'}" 712 713 def intersect_op(self, expression: exp.Intersect) -> str: 714 if not expression.args.get("distinct", False): 715 self.unsupported("INTERSECT without DISTINCT is not supported in BigQuery") 716 return f"INTERSECT{' DISTINCT' if expression.args.get('distinct') else ' ALL'}" 717 718 def with_properties(self, properties: exp.Properties) -> str: 719 return self.properties(properties, prefix=self.seg("OPTIONS")) 720 721 def version_sql(self, expression: exp.Version) -> str: 722 if expression.name == "TIMESTAMP": 723 expression.set("this", "SYSTEM_TIME") 724 return super().version_sql(expression)
ESCAPE_SEQUENCES: Dict[str, str] =
{'\\a': '\x07', '\\b': '\x08', '\\f': '\x0c', '\\n': '\n', '\\r': '\r', '\\t': '\t', '\\v': '\x0b'}
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'}
@classmethod
def
normalize_identifier(cls, expression: ~E) -> ~E:
234 @classmethod 235 def normalize_identifier(cls, expression: E) -> E: 236 if isinstance(expression, exp.Identifier): 237 parent = expression.parent 238 while isinstance(parent, exp.Dot): 239 parent = parent.parent 240 241 # In BigQuery, CTEs aren't case-sensitive, but table names are (by default, at least). 242 # The following check is essentially a heuristic to detect tables based on whether or 243 # not they're qualified. It also avoids normalizing UDFs, because they're case-sensitive. 244 if ( 245 not isinstance(parent, exp.UserDefinedFunction) 246 and not (isinstance(parent, exp.Table) and parent.db) 247 and not expression.meta.get("is_table") 248 ): 249 expression.set("this", expression.this.lower()) 250 251 return expression
Normalizes an unquoted identifier to either lower or upper case, thus essentially making it case-insensitive. If a dialect treats all identifiers as case-insensitive, they will be normalized to lowercase regardless of being quoted or not.
tokenizer_class =
<class 'BigQuery.Tokenizer'>
parser_class =
<class 'BigQuery.Parser'>
generator_class =
<class 'BigQuery.Generator'>
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_ESCAPE_SEQUENCES: Dict[str, str] =
{'\x07': '\\a', '\x08': '\\b', '\x0c': '\\f', '\n': '\\n', '\r': '\\r', '\t': '\\t', '\x0b': '\\v'}
Inherited Members
- sqlglot.dialects.dialect.Dialect
- INDEX_OFFSET
- ALIAS_POST_TABLESAMPLE
- IDENTIFIERS_CAN_START_WITH_DIGIT
- DPIPE_IS_STRING_CONCAT
- STRICT_STRING_CONCAT
- NULL_ORDERING
- TYPED_DIVISION
- SAFE_DIVISION
- DATE_FORMAT
- DATEINT_FORMAT
- TIME_FORMAT
- get_or_raise
- format_time
- case_sensitive
- can_identify
- quote_identifier
- parse
- parse_into
- generate
- transpile
- tokenize
- tokenizer
- parser
- generator
253 class Tokenizer(tokens.Tokenizer): 254 QUOTES = ["'", '"', '"""', "'''"] 255 COMMENTS = ["--", "#", ("/*", "*/")] 256 IDENTIFIERS = ["`"] 257 STRING_ESCAPES = ["\\"] 258 259 HEX_STRINGS = [("0x", ""), ("0X", "")] 260 261 BYTE_STRINGS = [ 262 (prefix + q, q) for q in t.cast(t.List[str], QUOTES) for prefix in ("b", "B") 263 ] 264 265 RAW_STRINGS = [ 266 (prefix + q, q) for q in t.cast(t.List[str], QUOTES) for prefix in ("r", "R") 267 ] 268 269 KEYWORDS = { 270 **tokens.Tokenizer.KEYWORDS, 271 "ANY TYPE": TokenType.VARIANT, 272 "BEGIN": TokenType.COMMAND, 273 "BEGIN TRANSACTION": TokenType.BEGIN, 274 "BYTES": TokenType.BINARY, 275 "CURRENT_DATETIME": TokenType.CURRENT_DATETIME, 276 "DECLARE": TokenType.COMMAND, 277 "FLOAT64": TokenType.DOUBLE, 278 "FOR SYSTEM_TIME": TokenType.TIMESTAMP_SNAPSHOT, 279 "MODEL": TokenType.MODEL, 280 "NOT DETERMINISTIC": TokenType.VOLATILE, 281 "RECORD": TokenType.STRUCT, 282 "TIMESTAMP": TokenType.TIMESTAMPTZ, 283 } 284 KEYWORDS.pop("DIV")
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.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'>, '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'>, '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'>, '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'>, 'UNION': <TokenType.UNION: 'UNION'>, 'UNKNOWN': <TokenType.UNKNOWN: 'UNKNOWN'>, 'UNNEST': <TokenType.UNNEST: 'UNNEST'>, 'UNPIVOT': <TokenType.UNPIVOT: 'UNPIVOT'>, 'UPDATE': <TokenType.UPDATE: 'UPDATE'>, 'USE': <TokenType.USE: 'USE'>, 'USING': <TokenType.USING: 'USING'>, 'UUID': <TokenType.UUID: 'UUID'>, 'VALUES': <TokenType.VALUES: 'VALUES'>, 'VIEW': <TokenType.VIEW: 'VIEW'>, 'VOLATILE': <TokenType.VOLATILE: 'VOLATILE'>, 'WHEN': <TokenType.WHEN: 'WHEN'>, 'WHERE': <TokenType.WHERE: 'WHERE'>, 'WINDOW': <TokenType.WINDOW: 'WINDOW'>, 'WITH': <TokenType.WITH: 'WITH'>, 'APPLY': <TokenType.APPLY: 'APPLY'>, 'ARRAY': <TokenType.ARRAY: 'ARRAY'>, 'BIT': <TokenType.BIT: 'BIT'>, 'BOOL': <TokenType.BOOLEAN: 'BOOLEAN'>, 'BOOLEAN': <TokenType.BOOLEAN: 'BOOLEAN'>, 'BYTE': <TokenType.TINYINT: 'TINYINT'>, 'MEDIUMINT': <TokenType.MEDIUMINT: 'MEDIUMINT'>, 'INT1': <TokenType.TINYINT: 'TINYINT'>, 'TINYINT': <TokenType.TINYINT: 'TINYINT'>, 'INT16': <TokenType.SMALLINT: 'SMALLINT'>, 'SHORT': <TokenType.SMALLINT: 'SMALLINT'>, 'SMALLINT': <TokenType.SMALLINT: 'SMALLINT'>, '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'>, 'DEC': <TokenType.DECIMAL: 'DECIMAL'>, 'DECIMAL': <TokenType.DECIMAL: 'DECIMAL'>, 'BIGDECIMAL': <TokenType.BIGDECIMAL: 'BIGDECIMAL'>, 'BIGNUMERIC': <TokenType.BIGDECIMAL: 'BIGDECIMAL'>, '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'>, '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'>, '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'>, 'DATE': <TokenType.DATE: 'DATE'>, 'DATETIME': <TokenType.DATETIME: 'DATETIME'>, 'INT4RANGE': <TokenType.INT4RANGE: 'INT4RANGE'>, 'INT4MULTIRANGE': <TokenType.INT4MULTIRANGE: 'INT4MULTIRANGE'>, 'INT8RANGE': <TokenType.INT8RANGE: 'INT8RANGE'>, 'INT8MULTIRANGE': <TokenType.INT8MULTIRANGE: 'INT8MULTIRANGE'>, 'NUMRANGE': <TokenType.NUMRANGE: 'NUMRANGE'>, 'NUMMULTIRANGE': <TokenType.NUMMULTIRANGE: 'NUMMULTIRANGE'>, 'TSRANGE': <TokenType.TSRANGE: 'TSRANGE'>, 'TSMULTIRANGE': <TokenType.TSMULTIRANGE: 'TSMULTIRANGE'>, 'TSTZRANGE': <TokenType.TSTZRANGE: 'TSTZRANGE'>, 'TSTZMULTIRANGE': <TokenType.TSTZMULTIRANGE: 'TSTZMULTIRANGE'>, 'DATERANGE': <TokenType.DATERANGE: 'DATERANGE'>, 'DATEMULTIRANGE': <TokenType.DATEMULTIRANGE: 'DATEMULTIRANGE'>, 'UNIQUE': <TokenType.UNIQUE: 'UNIQUE'>, 'STRUCT': <TokenType.STRUCT: 'STRUCT'>, 'VARIANT': <TokenType.VARIANT: 'VARIANT'>, 'ALTER': <TokenType.ALTER: 'ALTER'>, 'ANALYZE': <TokenType.COMMAND: 'COMMAND'>, 'CALL': <TokenType.COMMAND: 'COMMAND'>, 'COMMENT': <TokenType.COMMENT: 'COMMENT'>, 'COPY': <TokenType.COMMAND: 'COMMAND'>, 'EXPLAIN': <TokenType.COMMAND: 'COMMAND'>, 'GRANT': <TokenType.COMMAND: 'COMMAND'>, 'OPTIMIZE': <TokenType.COMMAND: 'COMMAND'>, 'PREPARE': <TokenType.COMMAND: 'COMMAND'>, 'TRUNCATE': <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'>, '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'>}
286 class Parser(parser.Parser): 287 PREFIXED_PIVOT_COLUMNS = True 288 289 LOG_DEFAULTS_TO_LN = True 290 291 FUNCTIONS = { 292 **parser.Parser.FUNCTIONS, 293 "DATE": _parse_date, 294 "DATE_ADD": parse_date_delta_with_interval(exp.DateAdd), 295 "DATE_SUB": parse_date_delta_with_interval(exp.DateSub), 296 "DATE_TRUNC": lambda args: exp.DateTrunc( 297 unit=exp.Literal.string(str(seq_get(args, 1))), 298 this=seq_get(args, 0), 299 ), 300 "DATETIME_ADD": parse_date_delta_with_interval(exp.DatetimeAdd), 301 "DATETIME_SUB": parse_date_delta_with_interval(exp.DatetimeSub), 302 "DIV": binary_from_function(exp.IntDiv), 303 "GENERATE_ARRAY": exp.GenerateSeries.from_arg_list, 304 "MD5": exp.MD5Digest.from_arg_list, 305 "TO_HEX": _parse_to_hex, 306 "PARSE_DATE": lambda args: format_time_lambda(exp.StrToDate, "bigquery")( 307 [seq_get(args, 1), seq_get(args, 0)] 308 ), 309 "PARSE_TIMESTAMP": _parse_timestamp, 310 "REGEXP_CONTAINS": exp.RegexpLike.from_arg_list, 311 "REGEXP_EXTRACT": lambda args: exp.RegexpExtract( 312 this=seq_get(args, 0), 313 expression=seq_get(args, 1), 314 position=seq_get(args, 2), 315 occurrence=seq_get(args, 3), 316 group=exp.Literal.number(1) if re.compile(args[1].name).groups == 1 else None, 317 ), 318 "SHA256": lambda args: exp.SHA2(this=seq_get(args, 0), length=exp.Literal.number(256)), 319 "SHA512": lambda args: exp.SHA2(this=seq_get(args, 0), length=exp.Literal.number(512)), 320 "SPLIT": lambda args: exp.Split( 321 # https://cloud.google.com/bigquery/docs/reference/standard-sql/string_functions#split 322 this=seq_get(args, 0), 323 expression=seq_get(args, 1) or exp.Literal.string(","), 324 ), 325 "TIME_ADD": parse_date_delta_with_interval(exp.TimeAdd), 326 "TIME_SUB": parse_date_delta_with_interval(exp.TimeSub), 327 "TIMESTAMP_ADD": parse_date_delta_with_interval(exp.TimestampAdd), 328 "TIMESTAMP_SUB": parse_date_delta_with_interval(exp.TimestampSub), 329 "TO_JSON_STRING": exp.JSONFormat.from_arg_list, 330 } 331 332 FUNCTION_PARSERS = { 333 **parser.Parser.FUNCTION_PARSERS, 334 "ARRAY": lambda self: self.expression(exp.Array, expressions=[self._parse_statement()]), 335 } 336 FUNCTION_PARSERS.pop("TRIM") 337 338 NO_PAREN_FUNCTIONS = { 339 **parser.Parser.NO_PAREN_FUNCTIONS, 340 TokenType.CURRENT_DATETIME: exp.CurrentDatetime, 341 } 342 343 NESTED_TYPE_TOKENS = { 344 *parser.Parser.NESTED_TYPE_TOKENS, 345 TokenType.TABLE, 346 } 347 348 ID_VAR_TOKENS = { 349 *parser.Parser.ID_VAR_TOKENS, 350 TokenType.VALUES, 351 } 352 353 PROPERTY_PARSERS = { 354 **parser.Parser.PROPERTY_PARSERS, 355 "NOT DETERMINISTIC": lambda self: self.expression( 356 exp.StabilityProperty, this=exp.Literal.string("VOLATILE") 357 ), 358 "OPTIONS": lambda self: self._parse_with_property(), 359 } 360 361 CONSTRAINT_PARSERS = { 362 **parser.Parser.CONSTRAINT_PARSERS, 363 "OPTIONS": lambda self: exp.Properties(expressions=self._parse_with_property()), 364 } 365 366 RANGE_PARSERS = parser.Parser.RANGE_PARSERS.copy() 367 RANGE_PARSERS.pop(TokenType.OVERLAPS, None) 368 369 NULL_TOKENS = {TokenType.NULL, TokenType.UNKNOWN} 370 371 STATEMENT_PARSERS = { 372 **parser.Parser.STATEMENT_PARSERS, 373 TokenType.END: lambda self: self._parse_as_command(self._prev), 374 TokenType.FOR: lambda self: self._parse_for_in(), 375 } 376 377 def _parse_for_in(self) -> exp.ForIn: 378 this = self._parse_range() 379 self._match_text_seq("DO") 380 return self.expression(exp.ForIn, this=this, expression=self._parse_statement()) 381 382 def _parse_table_part(self, schema: bool = False) -> t.Optional[exp.Expression]: 383 this = super()._parse_table_part(schema=schema) or self._parse_number() 384 385 # https://cloud.google.com/bigquery/docs/reference/standard-sql/lexical#table_names 386 if isinstance(this, exp.Identifier): 387 table_name = this.name 388 while self._match(TokenType.DASH, advance=False) and self._next: 389 self._advance(2) 390 table_name += f"-{self._prev.text}" 391 392 this = exp.Identifier(this=table_name, quoted=this.args.get("quoted")) 393 elif isinstance(this, exp.Literal): 394 table_name = this.name 395 396 if ( 397 self._curr 398 and self._prev.end == self._curr.start - 1 399 and self._parse_var(any_token=True) 400 ): 401 table_name += self._prev.text 402 403 this = exp.Identifier(this=table_name, quoted=True) 404 405 return this 406 407 def _parse_table_parts(self, schema: bool = False) -> exp.Table: 408 table = super()._parse_table_parts(schema=schema) 409 if isinstance(table.this, exp.Identifier) and "." in table.name: 410 catalog, db, this, *rest = ( 411 t.cast(t.Optional[exp.Expression], exp.to_identifier(x)) 412 for x in split_num_words(table.name, ".", 3) 413 ) 414 415 if rest and this: 416 this = exp.Dot.build(t.cast(t.List[exp.Expression], [this, *rest])) 417 418 table = exp.Table(this=this, db=db, catalog=catalog) 419 420 return table 421 422 def _parse_json_object(self) -> exp.JSONObject: 423 json_object = super()._parse_json_object() 424 array_kv_pair = seq_get(json_object.expressions, 0) 425 426 # Converts BQ's "signature 2" of JSON_OBJECT into SQLGlot's canonical representation 427 # https://cloud.google.com/bigquery/docs/reference/standard-sql/json_functions#json_object_signature2 428 if ( 429 array_kv_pair 430 and isinstance(array_kv_pair.this, exp.Array) 431 and isinstance(array_kv_pair.expression, exp.Array) 432 ): 433 keys = array_kv_pair.this.expressions 434 values = array_kv_pair.expression.expressions 435 436 json_object.set( 437 "expressions", 438 [exp.JSONKeyValue(this=k, expression=v) for k, v in zip(keys, values)], 439 ) 440 441 return json_object
Parser consumes a list of tokens produced by the Tokenizer and produces a parsed syntax tree.
Arguments:
- error_level: The desired error level. Default: ErrorLevel.IMMEDIATE
- error_message_context: Determines the amount of context to capture from a query string when displaying the error message (in number of characters). Default: 100
- max_errors: Maximum number of error messages to include in a raised ParseError. This is only relevant if error_level is ErrorLevel.RAISE. Default: 3
FUNCTIONS =
{'ABS': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Abs'>>, 'ANY_VALUE': <bound method Func.from_arg_list of <class 'sqlglot.expressions.AnyValue'>>, 'APPROX_DISTINCT': <bound method Func.from_arg_list of <class 'sqlglot.expressions.ApproxDistinct'>>, 'APPROX_COUNT_DISTINCT': <bound method Func.from_arg_list of <class 'sqlglot.expressions.ApproxDistinct'>>, 'APPROX_QUANTILE': <bound method Func.from_arg_list of <class 'sqlglot.expressions.ApproxQuantile'>>, '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_CONTAINS': <bound method Func.from_arg_list of <class 'sqlglot.expressions.ArrayContains'>>, 'FILTER': <bound method Func.from_arg_list of <class 'sqlglot.expressions.ArrayFilter'>>, 'ARRAY_FILTER': <bound method Func.from_arg_list of <class 'sqlglot.expressions.ArrayFilter'>>, 'ARRAY_JOIN': <bound method Func.from_arg_list of <class 'sqlglot.expressions.ArrayJoin'>>, 'ARRAY_SIZE': <bound method Func.from_arg_list of <class 'sqlglot.expressions.ArraySize'>>, 'ARRAY_SORT': <bound method Func.from_arg_list of <class 'sqlglot.expressions.ArraySort'>>, 'ARRAY_SUM': <bound method Func.from_arg_list of <class 'sqlglot.expressions.ArraySum'>>, 'ARRAY_UNION_AGG': <bound method Func.from_arg_list of <class 'sqlglot.expressions.ArrayUnionAgg'>>, 'AVG': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Avg'>>, 'CASE': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Case'>>, 'CAST': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Cast'>>, 'CAST_TO_STR_TYPE': <bound method Func.from_arg_list of <class 'sqlglot.expressions.CastToStrType'>>, 'CEIL': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Ceil'>>, 'CEILING': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Ceil'>>, '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'>>, 'CONCAT': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Concat'>>, 'CONCAT_WS': <bound method Func.from_arg_list of <class 'sqlglot.expressions.ConcatWs'>>, 'COUNT': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Count'>>, 'COUNT_IF': <bound method Func.from_arg_list of <class 'sqlglot.expressions.CountIf'>>, 'CURRENT_DATE': <bound method Func.from_arg_list of <class 'sqlglot.expressions.CurrentDate'>>, 'CURRENT_DATETIME': <bound method Func.from_arg_list of <class 'sqlglot.expressions.CurrentDatetime'>>, 'CURRENT_TIME': <bound method Func.from_arg_list of <class 'sqlglot.expressions.CurrentTime'>>, 'CURRENT_TIMESTAMP': <bound method Func.from_arg_list of <class 'sqlglot.expressions.CurrentTimestamp'>>, 'CURRENT_USER': <bound method Func.from_arg_list of <class 'sqlglot.expressions.CurrentUser'>>, 'DATE': <function _parse_date>, 'DATE_ADD': <function parse_date_delta_with_interval.<locals>.func>, 'DATEDIFF': <bound method Func.from_arg_list of <class 'sqlglot.expressions.DateDiff'>>, 'DATE_DIFF': <bound method Func.from_arg_list of <class 'sqlglot.expressions.DateDiff'>>, 'DATEFROMPARTS': <bound method Func.from_arg_list of <class 'sqlglot.expressions.DateFromParts'>>, 'DATE_STR_TO_DATE': <bound method Func.from_arg_list of <class 'sqlglot.expressions.DateStrToDate'>>, 'DATE_SUB': <function parse_date_delta_with_interval.<locals>.func>, '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_ADD': <function parse_date_delta_with_interval.<locals>.func>, 'DATETIME_DIFF': <bound method Func.from_arg_list of <class 'sqlglot.expressions.DatetimeDiff'>>, 'DATETIME_SUB': <function parse_date_delta_with_interval.<locals>.func>, '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'>>, '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'>>, 'GENERATE_SERIES': <bound method Func.from_arg_list of <class 'sqlglot.expressions.GenerateSeries'>>, 'GREATEST': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Greatest'>>, 'GROUP_CONCAT': <bound method Func.from_arg_list of <class 'sqlglot.expressions.GroupConcat'>>, 'HEX': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Hex'>>, 'HLL': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Hll'>>, 'IF': <bound method Func.from_arg_list of <class 'sqlglot.expressions.If'>>, 'INITCAP': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Initcap'>>, '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_EXTRACT': <bound method Func.from_arg_list of <class 'sqlglot.expressions.JSONBExtract'>>, 'JSONB_EXTRACT_SCALAR': <bound method Func.from_arg_list of <class 'sqlglot.expressions.JSONBExtractScalar'>>, 'JSON_EXTRACT': <bound method Func.from_arg_list of <class 'sqlglot.expressions.JSONExtract'>>, 'JSON_EXTRACT_SCALAR': <bound method Func.from_arg_list of <class 'sqlglot.expressions.JSONExtractScalar'>>, 'JSON_FORMAT': <bound method Func.from_arg_list of <class 'sqlglot.expressions.JSONFormat'>>, 'J_S_O_N_OBJECT': <bound method Func.from_arg_list of <class 'sqlglot.expressions.JSONObject'>>, 'J_S_O_N_TABLE': <bound method Func.from_arg_list of <class 'sqlglot.expressions.JSONTable'>>, 'LAST': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Last'>>, 'LAST_DATE_OF_MONTH': <bound method Func.from_arg_list of <class 'sqlglot.expressions.LastDateOfMonth'>>, 'LEAST': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Least'>>, 'LEFT': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Left'>>, 'LENGTH': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Length'>>, 'LEN': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Length'>>, 'LEVENSHTEIN': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Levenshtein'>>, 'LN': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Ln'>>, 'LOG': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Log'>>, 'LOG10': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Log10'>>, 'LOG2': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Log2'>>, 'LOGICAL_AND': <bound method Func.from_arg_list of <class 'sqlglot.expressions.LogicalAnd'>>, 'BOOL_AND': <bound method Func.from_arg_list of <class 'sqlglot.expressions.LogicalAnd'>>, 'BOOLAND_AGG': <bound method Func.from_arg_list of <class 'sqlglot.expressions.LogicalAnd'>>, 'LOGICAL_OR': <bound method Func.from_arg_list of <class 'sqlglot.expressions.LogicalOr'>>, 'BOOL_OR': <bound method Func.from_arg_list of <class 'sqlglot.expressions.LogicalOr'>>, 'BOOLOR_AGG': <bound method Func.from_arg_list of <class 'sqlglot.expressions.LogicalOr'>>, 'LOWER': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Lower'>>, 'LCASE': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Lower'>>, 'MD5': <bound method Func.from_arg_list of <class 'sqlglot.expressions.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'>>, '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'>>, '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_CONCAT': <bound method Func.from_arg_list of <class 'sqlglot.expressions.SafeConcat'>>, 'SAFE_DIVIDE': <bound method Func.from_arg_list of <class 'sqlglot.expressions.SafeDivide'>>, 'SET_AGG': <bound method Func.from_arg_list of <class 'sqlglot.expressions.SetAgg'>>, 'SORT_ARRAY': <bound method Func.from_arg_list of <class 'sqlglot.expressions.SortArray'>>, 'SPLIT': <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'>>, '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_ADD': <function parse_date_delta_with_interval.<locals>.func>, 'TIME_DIFF': <bound method Func.from_arg_list of <class 'sqlglot.expressions.TimeDiff'>>, 'TIME_STR_TO_DATE': <bound method Func.from_arg_list of <class 'sqlglot.expressions.TimeStrToDate'>>, 'TIME_STR_TO_TIME': <bound method Func.from_arg_list of <class 'sqlglot.expressions.TimeStrToTime'>>, 'TIME_STR_TO_UNIX': <bound method Func.from_arg_list of <class 'sqlglot.expressions.TimeStrToUnix'>>, 'TIME_SUB': <function parse_date_delta_with_interval.<locals>.func>, 'TIME_TO_STR': <bound method Func.from_arg_list of <class 'sqlglot.expressions.TimeToStr'>>, 'TIME_TO_TIME_STR': <function Parser.<lambda>>, 'TIME_TO_UNIX': <bound method Func.from_arg_list of <class 'sqlglot.expressions.TimeToUnix'>>, 'TIME_TRUNC': <bound method Func.from_arg_list of <class 'sqlglot.expressions.TimeTrunc'>>, 'TIMESTAMP': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Timestamp'>>, 'TIMESTAMP_ADD': <function parse_date_delta_with_interval.<locals>.func>, 'TIMESTAMP_DIFF': <bound method Func.from_arg_list of <class 'sqlglot.expressions.TimestampDiff'>>, 'TIMESTAMP_SUB': <function parse_date_delta_with_interval.<locals>.func>, 'TIMESTAMP_TRUNC': <bound method Func.from_arg_list of <class 'sqlglot.expressions.TimestampTrunc'>>, 'TO_BASE64': <bound method Func.from_arg_list of <class 'sqlglot.expressions.ToBase64'>>, 'TO_CHAR': <bound method Func.from_arg_list of <class 'sqlglot.expressions.ToChar'>>, 'TO_DAYS': <bound method Func.from_arg_list of <class 'sqlglot.expressions.ToDays'>>, '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_CAST': <bound method Func.from_arg_list of <class 'sqlglot.expressions.TryCast'>>, 'TS_OR_DI_TO_DI': <bound method Func.from_arg_list of <class 'sqlglot.expressions.TsOrDiToDi'>>, 'TS_OR_DS_ADD': <bound method Func.from_arg_list of <class 'sqlglot.expressions.TsOrDsAdd'>>, 'TS_OR_DS_TO_DATE': <bound method Func.from_arg_list of <class 'sqlglot.expressions.TsOrDsToDate'>>, 'TS_OR_DS_TO_DATE_STR': <function Parser.<lambda>>, 'UNHEX': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Unhex'>>, 'UNIX_TO_STR': <bound method Func.from_arg_list of <class 'sqlglot.expressions.UnixToStr'>>, 'UNIX_TO_TIME': <bound method Func.from_arg_list of <class 'sqlglot.expressions.UnixToTime'>>, 'UNIX_TO_TIME_STR': <bound method Func.from_arg_list of <class 'sqlglot.expressions.UnixToTimeStr'>>, 'UPPER': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Upper'>>, 'UCASE': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Upper'>>, 'VAR_MAP': <function parse_var_map>, 'VARIANCE': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Variance'>>, 'VARIANCE_SAMP': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Variance'>>, 'VAR_SAMP': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Variance'>>, 'VARIANCE_POP': <bound method Func.from_arg_list of <class 'sqlglot.expressions.VariancePop'>>, 'VAR_POP': <bound method Func.from_arg_list of <class 'sqlglot.expressions.VariancePop'>>, 'WEEK': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Week'>>, 'WEEK_OF_YEAR': <bound method Func.from_arg_list of <class 'sqlglot.expressions.WeekOfYear'>>, 'WEEKOFYEAR': <bound method Func.from_arg_list of <class 'sqlglot.expressions.WeekOfYear'>>, 'WHEN': <bound method Func.from_arg_list of <class 'sqlglot.expressions.When'>>, 'X_M_L_TABLE': <bound method Func.from_arg_list of <class 'sqlglot.expressions.XMLTable'>>, '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>>, 'LIKE': <function parse_like>, 'DIV': <function binary_from_function.<locals>.<lambda>>, 'GENERATE_ARRAY': <bound method Func.from_arg_list of <class 'sqlglot.expressions.GenerateSeries'>>, 'TO_HEX': <function _parse_to_hex>, 'PARSE_DATE': <function BigQuery.Parser.<lambda>>, 'PARSE_TIMESTAMP': <function _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>>, 'TO_JSON_STRING': <bound method Func.from_arg_list of <class 'sqlglot.expressions.JSONFormat'>>}
FUNCTION_PARSERS =
{'ANY_VALUE': <function Parser.<lambda>>, 'CAST': <function Parser.<lambda>>, 'CONCAT': <function Parser.<lambda>>, 'CONCAT_WS': <function Parser.<lambda>>, 'CONVERT': <function Parser.<lambda>>, 'DECODE': <function Parser.<lambda>>, 'EXTRACT': <function Parser.<lambda>>, 'JSON_OBJECT': <function Parser.<lambda>>, 'JSON_TABLE': <function Parser.<lambda>>, 'LOG': <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.ARRAY: 'ARRAY'>, <TokenType.TABLE: 'TABLE'>, <TokenType.NULLABLE: 'NULLABLE'>, <TokenType.NESTED: 'NESTED'>, <TokenType.LOWCARDINALITY: 'LOWCARDINALITY'>, <TokenType.STRUCT: 'STRUCT'>, <TokenType.MAP: 'MAP'>}
ID_VAR_TOKENS =
{<TokenType.TIMESTAMP_MS: 'TIMESTAMP_MS'>, <TokenType.VALUES: 'VALUES'>, <TokenType.ESCAPE: 'ESCAPE'>, <TokenType.TINYINT: 'TINYINT'>, <TokenType.SUPER: 'SUPER'>, <TokenType.NESTED: 'NESTED'>, <TokenType.BEGIN: 'BEGIN'>, <TokenType.SMALLMONEY: 'SMALLMONEY'>, <TokenType.END: 'END'>, <TokenType.MAP: 'MAP'>, <TokenType.TIMESTAMPTZ: 'TIMESTAMPTZ'>, <TokenType.TSTZRANGE: 'TSTZRANGE'>, <TokenType.INT8RANGE: 'INT8RANGE'>, <TokenType.INT128: 'INT128'>, <TokenType.DATERANGE: 'DATERANGE'>, <TokenType.XML: 'XML'>, <TokenType.NUMMULTIRANGE: 'NUMMULTIRANGE'>, <TokenType.COMMENT: 'COMMENT'>, <TokenType.DATABASE: 'DATABASE'>, <TokenType.UINT256: 'UINT256'>, <TokenType.NULL: 'NULL'>, <TokenType.VARBINARY: 'VARBINARY'>, <TokenType.UINT: 'UINT'>, <TokenType.IMAGE: 'IMAGE'>, <TokenType.INT: 'INT'>, <TokenType.VAR: 'VAR'>, <TokenType.UTINYINT: 'UTINYINT'>, <TokenType.REFERENCES: 'REFERENCES'>, <TokenType.MEDIUMINT: 'MEDIUMINT'>, <TokenType.LEFT: 'LEFT'>, <TokenType.TIMESTAMPLTZ: 'TIMESTAMPLTZ'>, <TokenType.OVERWRITE: 'OVERWRITE'>, <TokenType.PERCENT: 'PERCENT'>, <TokenType.DEFAULT: 'DEFAULT'>, <TokenType.PROCEDURE: 'PROCEDURE'>, <TokenType.FIXEDSTRING: 'FIXEDSTRING'>, <TokenType.MEDIUMTEXT: 'MEDIUMTEXT'>, <TokenType.HSTORE: 'HSTORE'>, <TokenType.UNIQUEIDENTIFIER: 'UNIQUEIDENTIFIER'>, <TokenType.KEEP: 'KEEP'>, <TokenType.IS: 'IS'>, <TokenType.MONEY: 'MONEY'>, <TokenType.COLLATE: 'COLLATE'>, <TokenType.AUTO_INCREMENT: 'AUTO_INCREMENT'>, <TokenType.DELETE: 'DELETE'>, <TokenType.USMALLINT: 'USMALLINT'>, <TokenType.BINARY: 'BINARY'>, <TokenType.SET: 'SET'>, <TokenType.CACHE: 'CACHE'>, <TokenType.ORDINALITY: 'ORDINALITY'>, <TokenType.TABLE: 'TABLE'>, <TokenType.SMALLSERIAL: 'SMALLSERIAL'>, <TokenType.TEMPORARY: 'TEMPORARY'>, <TokenType.FULL: 'FULL'>, <TokenType.EXISTS: 'EXISTS'>, <TokenType.HLLSKETCH: 'HLLSKETCH'>, <TokenType.DATETIME: 'DATETIME'>, <TokenType.LOAD: 'LOAD'>, <TokenType.TIMETZ: 'TIMETZ'>, <TokenType.JSONB: 'JSONB'>, <TokenType.IPPREFIX: 'IPPREFIX'>, <TokenType.CASE: 'CASE'>, <TokenType.TIME: 'TIME'>, <TokenType.KILL: 'KILL'>, <TokenType.TRUE: 'TRUE'>, <TokenType.NCHAR: 'NCHAR'>, <TokenType.TIMESTAMP_S: 'TIMESTAMP_S'>, <TokenType.BIGSERIAL: 'BIGSERIAL'>, <TokenType.INDEX: 'INDEX'>, <TokenType.OVERLAPS: 'OVERLAPS'>, <TokenType.COLUMN: 'COLUMN'>, <TokenType.PARTITION: 'PARTITION'>, <TokenType.CURRENT_TIME: 'CURRENT_TIME'>, <TokenType.TSTZMULTIRANGE: 'TSTZMULTIRANGE'>, <TokenType.CURRENT_DATETIME: 'CURRENT_DATETIME'>, <TokenType.UUID: 'UUID'>, <TokenType.SCHEMA: 'SCHEMA'>, <TokenType.NVARCHAR: 'NVARCHAR'>, <TokenType.RECURSIVE: 'RECURSIVE'>, <TokenType.EXECUTE: 'EXECUTE'>, <TokenType.INT4MULTIRANGE: 'INT4MULTIRANGE'>, <TokenType.CURRENT_USER: 'CURRENT_USER'>, <TokenType.UNPIVOT: 'UNPIVOT'>, <TokenType.SETTINGS: 'SETTINGS'>, <TokenType.INT4RANGE: 'INT4RANGE'>, <TokenType.TSMULTIRANGE: 'TSMULTIRANGE'>, <TokenType.ENUM8: 'ENUM8'>, <TokenType.PSEUDO_TYPE: 'PSEUDO_TYPE'>, <TokenType.ROWVERSION: 'ROWVERSION'>, <TokenType.LONGTEXT: 'LONGTEXT'>, <TokenType.ASC: 'ASC'>, <TokenType.ALL: 'ALL'>, <TokenType.COMMAND: 'COMMAND'>, <TokenType.INTERVAL: 'INTERVAL'>, <TokenType.INT8MULTIRANGE: 'INT8MULTIRANGE'>, <TokenType.FLOAT: 'FLOAT'>, <TokenType.NATURAL: 'NATURAL'>, <TokenType.UDECIMAL: 'UDECIMAL'>, <TokenType.OBJECT: 'OBJECT'>, <TokenType.FIRST: 'FIRST'>, <TokenType.BOOLEAN: 'BOOLEAN'>, <TokenType.NEXT: 'NEXT'>, <TokenType.SHOW: 'SHOW'>, <TokenType.SEMI: 'SEMI'>, <TokenType.USERDEFINED: 'USERDEFINED'>, <TokenType.CONSTRAINT: 'CONSTRAINT'>, <TokenType.PIVOT: 'PIVOT'>, <TokenType.VOLATILE: 'VOLATILE'>, <TokenType.FUNCTION: 'FUNCTION'>, <TokenType.DOUBLE: 'DOUBLE'>, <TokenType.TIMESTAMP: 'TIMESTAMP'>, <TokenType.ROWS: 'ROWS'>, <TokenType.UMEDIUMINT: 'UMEDIUMINT'>, <TokenType.TOP: 'TOP'>, <TokenType.ISNULL: 'ISNULL'>, <TokenType.TINYTEXT: 'TINYTEXT'>, <TokenType.UBIGINT: 'UBIGINT'>, <TokenType.ANTI: 'ANTI'>, <TokenType.UINT128: 'UINT128'>, <TokenType.VARCHAR: 'VARCHAR'>, <TokenType.YEAR: 'YEAR'>, <TokenType.TSRANGE: 'TSRANGE'>, <TokenType.LOWCARDINALITY: 'LOWCARDINALITY'>, <TokenType.TINYBLOB: 'TINYBLOB'>, <TokenType.DATETIME64: 'DATETIME64'>, <TokenType.UPDATE: 'UPDATE'>, <TokenType.MODEL: 'MODEL'>, <TokenType.CHAR: 'CHAR'>, <TokenType.TEXT: 'TEXT'>, <TokenType.APPLY: 'APPLY'>, <TokenType.GEOGRAPHY: 'GEOGRAPHY'>, <TokenType.FILTER: 'FILTER'>, <TokenType.USE: 'USE'>, <TokenType.RANGE: 'RANGE'>, <TokenType.SMALLINT: 'SMALLINT'>, <TokenType.IPADDRESS: 'IPADDRESS'>, <TokenType.BIGDECIMAL: 'BIGDECIMAL'>, <TokenType.ENUM16: 'ENUM16'>, <TokenType.TIMESTAMP_NS: 'TIMESTAMP_NS'>, <TokenType.OFFSET: 'OFFSET'>, <TokenType.CURRENT_DATE: 'CURRENT_DATE'>, <TokenType.WINDOW: 'WINDOW'>, <TokenType.DATE: 'DATE'>, <TokenType.VARIANT: 'VARIANT'>, <TokenType.JSON: 'JSON'>, <TokenType.DICTIONARY: 'DICTIONARY'>, <TokenType.DESC: 'DESC'>, <TokenType.ROW: 'ROW'>, <TokenType.UNIQUE: 'UNIQUE'>, <TokenType.DATEMULTIRANGE: 'DATEMULTIRANGE'>, <TokenType.SERIAL: 'SERIAL'>, <TokenType.INET: 'INET'>, <TokenType.ANY: 'ANY'>, <TokenType.LONGBLOB: 'LONGBLOB'>, <TokenType.NULLABLE: 'NULLABLE'>, <TokenType.DESCRIBE: 'DESCRIBE'>, <TokenType.BIT: 'BIT'>, <TokenType.PRAGMA: 'PRAGMA'>, <TokenType.SOME: 'SOME'>, <TokenType.RIGHT: 'RIGHT'>, <TokenType.CURRENT_TIMESTAMP: 'CURRENT_TIMESTAMP'>, <TokenType.FORMAT: 'FORMAT'>, <TokenType.STRUCT: 'STRUCT'>, <TokenType.FALSE: 'FALSE'>, <TokenType.REFRESH: 'REFRESH'>, <TokenType.ENUM: 'ENUM'>, <TokenType.UNKNOWN: 'UNKNOWN'>, <TokenType.COMMIT: 'COMMIT'>, <TokenType.DIV: 'DIV'>, <TokenType.MERGE: 'MERGE'>, <TokenType.MEDIUMBLOB: 'MEDIUMBLOB'>, <TokenType.ARRAY: 'ARRAY'>, <TokenType.NUMRANGE: 'NUMRANGE'>, <TokenType.GEOMETRY: 'GEOMETRY'>, <TokenType.OBJECT_IDENTIFIER: 'OBJECT_IDENTIFIER'>, <TokenType.VIEW: 'VIEW'>, <TokenType.INT256: 'INT256'>, <TokenType.DECIMAL: 'DECIMAL'>, <TokenType.BIGINT: 'BIGINT'>}
PROPERTY_PARSERS =
{'ALGORITHM': <function Parser.<lambda>>, 'AUTO_INCREMENT': <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>>, 'COPY': <function Parser.<lambda>>, 'DATABLOCKSIZE': <function Parser.<lambda>>, 'DEFINER': <function Parser.<lambda>>, 'DETERMINISTIC': <function Parser.<lambda>>, 'DISTKEY': <function Parser.<lambda>>, 'DISTSTYLE': <function Parser.<lambda>>, 'ENGINE': <function Parser.<lambda>>, 'EXECUTE': <function Parser.<lambda>>, 'EXTERNAL': <function Parser.<lambda>>, 'FALLBACK': <function Parser.<lambda>>, 'FORMAT': <function Parser.<lambda>>, 'FREESPACE': <function Parser.<lambda>>, 'HEAP': <function Parser.<lambda>>, 'IMMUTABLE': <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>>, '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>>, 'REMOTE': <function Parser.<lambda>>, 'RETURNS': <function Parser.<lambda>>, 'ROW': <function Parser.<lambda>>, 'ROW_FORMAT': <function Parser.<lambda>>, 'SAMPLE': <function Parser.<lambda>>, 'SET': <function Parser.<lambda>>, 'SETTINGS': <function Parser.<lambda>>, 'SORTKEY': <function Parser.<lambda>>, 'SOURCE': <function Parser.<lambda>>, 'STABLE': <function Parser.<lambda>>, 'STORED': <function Parser.<lambda>>, '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>>, '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>>, '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>.<lambda>>, <TokenType.ILIKE: 'ILIKE'>: <function binary_range_parser.<locals>.<lambda>>, <TokenType.IN: 'IN'>: <function Parser.<lambda>>, <TokenType.IRLIKE: 'IRLIKE'>: <function binary_range_parser.<locals>.<lambda>>, <TokenType.IS: 'IS'>: <function Parser.<lambda>>, <TokenType.LIKE: 'LIKE'>: <function binary_range_parser.<locals>.<lambda>>, <TokenType.RLIKE: 'RLIKE'>: <function binary_range_parser.<locals>.<lambda>>, <TokenType.SIMILAR_TO: 'SIMILAR_TO'>: <function binary_range_parser.<locals>.<lambda>>, <TokenType.FOR: 'FOR'>: <function Parser.<lambda>>}
STATEMENT_PARSERS =
{<TokenType.ALTER: 'ALTER'>: <function Parser.<lambda>>, <TokenType.BEGIN: 'BEGIN'>: <function Parser.<lambda>>, <TokenType.CACHE: 'CACHE'>: <function Parser.<lambda>>, <TokenType.COMMIT: 'COMMIT'>: <function Parser.<lambda>>, <TokenType.COMMENT: 'COMMENT'>: <function Parser.<lambda>>, <TokenType.CREATE: 'CREATE'>: <function Parser.<lambda>>, <TokenType.DELETE: 'DELETE'>: <function Parser.<lambda>>, <TokenType.DESC: 'DESC'>: <function Parser.<lambda>>, <TokenType.DESCRIBE: 'DESCRIBE'>: <function Parser.<lambda>>, <TokenType.DROP: 'DROP'>: <function Parser.<lambda>>, <TokenType.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.UNCACHE: 'UNCACHE'>: <function Parser.<lambda>>, <TokenType.UPDATE: 'UPDATE'>: <function Parser.<lambda>>, <TokenType.USE: 'USE'>: <function Parser.<lambda>>, <TokenType.END: 'END'>: <function BigQuery.Parser.<lambda>>, <TokenType.FOR: 'FOR'>: <function BigQuery.Parser.<lambda>>}
TABLE_ALIAS_TOKENS =
{<TokenType.TIMESTAMP_MS: 'TIMESTAMP_MS'>, <TokenType.ESCAPE: 'ESCAPE'>, <TokenType.TINYINT: 'TINYINT'>, <TokenType.SUPER: 'SUPER'>, <TokenType.NESTED: 'NESTED'>, <TokenType.BEGIN: 'BEGIN'>, <TokenType.SMALLMONEY: 'SMALLMONEY'>, <TokenType.END: 'END'>, <TokenType.MAP: 'MAP'>, <TokenType.TIMESTAMPTZ: 'TIMESTAMPTZ'>, <TokenType.TSTZRANGE: 'TSTZRANGE'>, <TokenType.INT8RANGE: 'INT8RANGE'>, <TokenType.INT128: 'INT128'>, <TokenType.DATERANGE: 'DATERANGE'>, <TokenType.XML: 'XML'>, <TokenType.NUMMULTIRANGE: 'NUMMULTIRANGE'>, <TokenType.COMMENT: 'COMMENT'>, <TokenType.DATABASE: 'DATABASE'>, <TokenType.UINT256: 'UINT256'>, <TokenType.NULL: 'NULL'>, <TokenType.VARBINARY: 'VARBINARY'>, <TokenType.UINT: 'UINT'>, <TokenType.IMAGE: 'IMAGE'>, <TokenType.INT: 'INT'>, <TokenType.VAR: 'VAR'>, <TokenType.UTINYINT: 'UTINYINT'>, <TokenType.REFERENCES: 'REFERENCES'>, <TokenType.MEDIUMINT: 'MEDIUMINT'>, <TokenType.TIMESTAMPLTZ: 'TIMESTAMPLTZ'>, <TokenType.OVERWRITE: 'OVERWRITE'>, <TokenType.PERCENT: 'PERCENT'>, <TokenType.DEFAULT: 'DEFAULT'>, <TokenType.PROCEDURE: 'PROCEDURE'>, <TokenType.FIXEDSTRING: 'FIXEDSTRING'>, <TokenType.MEDIUMTEXT: 'MEDIUMTEXT'>, <TokenType.HSTORE: 'HSTORE'>, <TokenType.UNIQUEIDENTIFIER: 'UNIQUEIDENTIFIER'>, <TokenType.KEEP: 'KEEP'>, <TokenType.IS: 'IS'>, <TokenType.MONEY: 'MONEY'>, <TokenType.COLLATE: 'COLLATE'>, <TokenType.AUTO_INCREMENT: 'AUTO_INCREMENT'>, <TokenType.DELETE: 'DELETE'>, <TokenType.USMALLINT: 'USMALLINT'>, <TokenType.BINARY: 'BINARY'>, <TokenType.SET: 'SET'>, <TokenType.CACHE: 'CACHE'>, <TokenType.ORDINALITY: 'ORDINALITY'>, <TokenType.TABLE: 'TABLE'>, <TokenType.SMALLSERIAL: 'SMALLSERIAL'>, <TokenType.TEMPORARY: 'TEMPORARY'>, <TokenType.EXISTS: 'EXISTS'>, <TokenType.HLLSKETCH: 'HLLSKETCH'>, <TokenType.DATETIME: 'DATETIME'>, <TokenType.LOAD: 'LOAD'>, <TokenType.TIMETZ: 'TIMETZ'>, <TokenType.JSONB: 'JSONB'>, <TokenType.IPPREFIX: 'IPPREFIX'>, <TokenType.CASE: 'CASE'>, <TokenType.TIME: 'TIME'>, <TokenType.KILL: 'KILL'>, <TokenType.TRUE: 'TRUE'>, <TokenType.NCHAR: 'NCHAR'>, <TokenType.TIMESTAMP_S: 'TIMESTAMP_S'>, <TokenType.BIGSERIAL: 'BIGSERIAL'>, <TokenType.INDEX: 'INDEX'>, <TokenType.OVERLAPS: 'OVERLAPS'>, <TokenType.COLUMN: 'COLUMN'>, <TokenType.PARTITION: 'PARTITION'>, <TokenType.CURRENT_TIME: 'CURRENT_TIME'>, <TokenType.TSTZMULTIRANGE: 'TSTZMULTIRANGE'>, <TokenType.CURRENT_DATETIME: 'CURRENT_DATETIME'>, <TokenType.UUID: 'UUID'>, <TokenType.SCHEMA: 'SCHEMA'>, <TokenType.NVARCHAR: 'NVARCHAR'>, <TokenType.RECURSIVE: 'RECURSIVE'>, <TokenType.EXECUTE: 'EXECUTE'>, <TokenType.INT4MULTIRANGE: 'INT4MULTIRANGE'>, <TokenType.CURRENT_USER: 'CURRENT_USER'>, <TokenType.UNPIVOT: 'UNPIVOT'>, <TokenType.SETTINGS: 'SETTINGS'>, <TokenType.INT4RANGE: 'INT4RANGE'>, <TokenType.TSMULTIRANGE: 'TSMULTIRANGE'>, <TokenType.ENUM8: 'ENUM8'>, <TokenType.PSEUDO_TYPE: 'PSEUDO_TYPE'>, <TokenType.ROWVERSION: 'ROWVERSION'>, <TokenType.LONGTEXT: 'LONGTEXT'>, <TokenType.ASC: 'ASC'>, <TokenType.ALL: 'ALL'>, <TokenType.COMMAND: 'COMMAND'>, <TokenType.INTERVAL: 'INTERVAL'>, <TokenType.INT8MULTIRANGE: 'INT8MULTIRANGE'>, <TokenType.FLOAT: 'FLOAT'>, <TokenType.UDECIMAL: 'UDECIMAL'>, <TokenType.OBJECT: 'OBJECT'>, <TokenType.FIRST: 'FIRST'>, <TokenType.BOOLEAN: 'BOOLEAN'>, <TokenType.NEXT: 'NEXT'>, <TokenType.SHOW: 'SHOW'>, <TokenType.SEMI: 'SEMI'>, <TokenType.USERDEFINED: 'USERDEFINED'>, <TokenType.CONSTRAINT: 'CONSTRAINT'>, <TokenType.PIVOT: 'PIVOT'>, <TokenType.VOLATILE: 'VOLATILE'>, <TokenType.FUNCTION: 'FUNCTION'>, <TokenType.DOUBLE: 'DOUBLE'>, <TokenType.TIMESTAMP: 'TIMESTAMP'>, <TokenType.ROWS: 'ROWS'>, <TokenType.UMEDIUMINT: 'UMEDIUMINT'>, <TokenType.TOP: 'TOP'>, <TokenType.ISNULL: 'ISNULL'>, <TokenType.TINYTEXT: 'TINYTEXT'>, <TokenType.UBIGINT: 'UBIGINT'>, <TokenType.ANTI: 'ANTI'>, <TokenType.UINT128: 'UINT128'>, <TokenType.VARCHAR: 'VARCHAR'>, <TokenType.YEAR: 'YEAR'>, <TokenType.TSRANGE: 'TSRANGE'>, <TokenType.LOWCARDINALITY: 'LOWCARDINALITY'>, <TokenType.TINYBLOB: 'TINYBLOB'>, <TokenType.DATETIME64: 'DATETIME64'>, <TokenType.UPDATE: 'UPDATE'>, <TokenType.MODEL: 'MODEL'>, <TokenType.CHAR: 'CHAR'>, <TokenType.TEXT: 'TEXT'>, <TokenType.GEOGRAPHY: 'GEOGRAPHY'>, <TokenType.FILTER: 'FILTER'>, <TokenType.USE: 'USE'>, <TokenType.RANGE: 'RANGE'>, <TokenType.SMALLINT: 'SMALLINT'>, <TokenType.IPADDRESS: 'IPADDRESS'>, <TokenType.BIGDECIMAL: 'BIGDECIMAL'>, <TokenType.ENUM16: 'ENUM16'>, <TokenType.TIMESTAMP_NS: 'TIMESTAMP_NS'>, <TokenType.CURRENT_DATE: 'CURRENT_DATE'>, <TokenType.DATE: 'DATE'>, <TokenType.VARIANT: 'VARIANT'>, <TokenType.JSON: 'JSON'>, <TokenType.DICTIONARY: 'DICTIONARY'>, <TokenType.DESC: 'DESC'>, <TokenType.ROW: 'ROW'>, <TokenType.UNIQUE: 'UNIQUE'>, <TokenType.DATEMULTIRANGE: 'DATEMULTIRANGE'>, <TokenType.SERIAL: 'SERIAL'>, <TokenType.INET: 'INET'>, <TokenType.ANY: 'ANY'>, <TokenType.LONGBLOB: 'LONGBLOB'>, <TokenType.NULLABLE: 'NULLABLE'>, <TokenType.DESCRIBE: 'DESCRIBE'>, <TokenType.BIT: 'BIT'>, <TokenType.PRAGMA: 'PRAGMA'>, <TokenType.SOME: 'SOME'>, <TokenType.CURRENT_TIMESTAMP: 'CURRENT_TIMESTAMP'>, <TokenType.FORMAT: 'FORMAT'>, <TokenType.STRUCT: 'STRUCT'>, <TokenType.FALSE: 'FALSE'>, <TokenType.REFRESH: 'REFRESH'>, <TokenType.ENUM: 'ENUM'>, <TokenType.UNKNOWN: 'UNKNOWN'>, <TokenType.COMMIT: 'COMMIT'>, <TokenType.DIV: 'DIV'>, <TokenType.MERGE: 'MERGE'>, <TokenType.MEDIUMBLOB: 'MEDIUMBLOB'>, <TokenType.ARRAY: 'ARRAY'>, <TokenType.NUMRANGE: 'NUMRANGE'>, <TokenType.GEOMETRY: 'GEOMETRY'>, <TokenType.OBJECT_IDENTIFIER: 'OBJECT_IDENTIFIER'>, <TokenType.VIEW: 'VIEW'>, <TokenType.INT256: 'INT256'>, <TokenType.DECIMAL: 'DECIMAL'>, <TokenType.BIGINT: 'BIGINT'>}
SET_TRIE: Dict =
{'GLOBAL': {0: True}, 'LOCAL': {0: True}, 'SESSION': {0: True}, 'TRANSACTION': {0: True}}
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'}
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}}}}
Inherited Members
- sqlglot.parser.Parser
- Parser
- STRUCT_TYPE_TOKENS
- ENUM_TYPE_TOKENS
- TYPE_TOKENS
- SIGNED_TO_UNSIGNED_TYPE_TOKEN
- SUBQUERY_PREDICATES
- RESERVED_KEYWORDS
- DB_CREATABLES
- CREATABLES
- INTERVAL_VARS
- COMMENT_TABLE_ALIAS_TOKENS
- UPDATE_ALIAS_TOKENS
- TRIM_TYPES
- FUNC_TOKENS
- CONJUNCTION
- 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
- PRIMARY_PARSERS
- PLACEHOLDER_PARSERS
- ALTER_PARSERS
- SCHEMA_UNNAMED_CONSTRAINTS
- NO_PAREN_FUNCTION_PARSERS
- INVALID_FUNC_NAME_TOKENS
- FUNCTIONS_WITH_ALIASED_ARGS
- QUERY_MODIFIER_PARSERS
- SET_PARSERS
- SHOW_PARSERS
- TYPE_LITERAL_PARSERS
- MODIFIABLES
- DDL_SELECT_TOKENS
- PRE_VOLATILE_TOKENS
- TRANSACTION_KIND
- TRANSACTION_CHARACTERISTICS
- INSERT_ALTERNATIVES
- CLONE_KEYWORDS
- CLONE_KINDS
- OPCLASS_FOLLOW_KEYWORDS
- OPTYPE_FOLLOW_TOKENS
- TABLE_INDEX_HINT_TOKENS
- WINDOW_ALIAS_TOKENS
- WINDOW_BEFORE_PAREN_TOKENS
- WINDOW_SIDES
- FETCH_TOKENS
- ADD_CONSTRAINT_TOKENS
- DISTINCT_TOKENS
- UNNEST_OFFSET_ALIAS_TOKENS
- STRICT_CAST
- CONCAT_NULL_OUTPUTS_STRING
- IDENTIFY_PIVOT_STRINGS
- ALTER_TABLE_ADD_COLUMN_KEYWORD
- TABLESAMPLE_CSV
- SET_REQUIRES_ASSIGNMENT_DELIMITER
- TRIM_PATTERN_FIRST
- TYPED_DIVISION
- SAFE_DIVISION
- INDEX_OFFSET
- ALIAS_POST_TABLESAMPLE
- STRICT_STRING_CONCAT
- NULL_ORDERING
- error_level
- error_message_context
- max_errors
- reset
- parse
- parse_into
- check_errors
- raise_error
- expression
- validate_expression
- errors
- sql
443 class Generator(generator.Generator): 444 EXPLICIT_UNION = True 445 INTERVAL_ALLOWS_PLURAL_FORM = False 446 JOIN_HINTS = False 447 QUERY_HINTS = False 448 TABLE_HINTS = False 449 LIMIT_FETCH = "LIMIT" 450 RENAME_TABLE_WITH_DB = False 451 NVL2_SUPPORTED = False 452 UNNEST_WITH_ORDINALITY = False 453 COLLATE_IS_FUNC = True 454 455 TRANSFORMS = { 456 **generator.Generator.TRANSFORMS, 457 exp.ApproxDistinct: rename_func("APPROX_COUNT_DISTINCT"), 458 exp.ArgMax: arg_max_or_min_no_count("MAX_BY"), 459 exp.ArgMin: arg_max_or_min_no_count("MIN_BY"), 460 exp.ArrayContains: _array_contains_sql, 461 exp.ArraySize: rename_func("ARRAY_LENGTH"), 462 exp.Cast: transforms.preprocess([transforms.remove_precision_parameterized_types]), 463 exp.CollateProperty: lambda self, e: f"DEFAULT COLLATE {self.sql(e, 'this')}" 464 if e.args.get("default") 465 else f"COLLATE {self.sql(e, 'this')}", 466 exp.Create: _create_sql, 467 exp.CTE: transforms.preprocess([_pushdown_cte_column_names]), 468 exp.DateAdd: date_add_interval_sql("DATE", "ADD"), 469 exp.DateDiff: lambda self, e: f"DATE_DIFF({self.sql(e, 'this')}, {self.sql(e, 'expression')}, {self.sql(e.args.get('unit', 'DAY'))})", 470 exp.DateFromParts: rename_func("DATE"), 471 exp.DateStrToDate: datestrtodate_sql, 472 exp.DateSub: date_add_interval_sql("DATE", "SUB"), 473 exp.DatetimeAdd: date_add_interval_sql("DATETIME", "ADD"), 474 exp.DatetimeSub: date_add_interval_sql("DATETIME", "SUB"), 475 exp.DateTrunc: lambda self, e: self.func("DATE_TRUNC", e.this, e.text("unit")), 476 exp.GenerateSeries: rename_func("GENERATE_ARRAY"), 477 exp.GroupConcat: rename_func("STRING_AGG"), 478 exp.Hex: rename_func("TO_HEX"), 479 exp.If: if_sql(false_value="NULL"), 480 exp.ILike: no_ilike_sql, 481 exp.IntDiv: rename_func("DIV"), 482 exp.JSONFormat: rename_func("TO_JSON_STRING"), 483 exp.JSONKeyValue: json_keyvalue_comma_sql, 484 exp.Max: max_or_greatest, 485 exp.MD5: lambda self, e: self.func("TO_HEX", self.func("MD5", e.this)), 486 exp.MD5Digest: rename_func("MD5"), 487 exp.Min: min_or_least, 488 exp.PartitionedByProperty: lambda self, e: f"PARTITION BY {self.sql(e, 'this')}", 489 exp.RegexpExtract: lambda self, e: self.func( 490 "REGEXP_EXTRACT", 491 e.this, 492 e.expression, 493 e.args.get("position"), 494 e.args.get("occurrence"), 495 ), 496 exp.RegexpReplace: regexp_replace_sql, 497 exp.RegexpLike: rename_func("REGEXP_CONTAINS"), 498 exp.ReturnsProperty: _returnsproperty_sql, 499 exp.Select: transforms.preprocess( 500 [ 501 transforms.explode_to_unnest(), 502 _unqualify_unnest, 503 transforms.eliminate_distinct_on, 504 _alias_ordered_group, 505 transforms.eliminate_semi_and_anti_joins, 506 ] 507 ), 508 exp.SHA2: lambda self, e: self.func( 509 f"SHA256" if e.text("length") == "256" else "SHA512", e.this 510 ), 511 exp.StabilityProperty: lambda self, e: f"DETERMINISTIC" 512 if e.name == "IMMUTABLE" 513 else "NOT DETERMINISTIC", 514 exp.StrToDate: lambda self, e: f"PARSE_DATE({self.format_time(e)}, {self.sql(e, 'this')})", 515 exp.StrToTime: lambda self, e: self.func( 516 "PARSE_TIMESTAMP", self.format_time(e), e.this, e.args.get("zone") 517 ), 518 exp.TimeAdd: date_add_interval_sql("TIME", "ADD"), 519 exp.TimeSub: date_add_interval_sql("TIME", "SUB"), 520 exp.TimestampAdd: date_add_interval_sql("TIMESTAMP", "ADD"), 521 exp.TimestampSub: date_add_interval_sql("TIMESTAMP", "SUB"), 522 exp.TimeStrToTime: timestrtotime_sql, 523 exp.Trim: lambda self, e: self.func(f"TRIM", e.this, e.expression), 524 exp.TsOrDsAdd: date_add_interval_sql("DATE", "ADD"), 525 exp.TsOrDsToDate: ts_or_ds_to_date_sql("bigquery"), 526 exp.Unhex: rename_func("FROM_HEX"), 527 exp.Values: _derived_table_values_to_unnest, 528 exp.VariancePop: rename_func("VAR_POP"), 529 } 530 531 TYPE_MAPPING = { 532 **generator.Generator.TYPE_MAPPING, 533 exp.DataType.Type.BIGDECIMAL: "BIGNUMERIC", 534 exp.DataType.Type.BIGINT: "INT64", 535 exp.DataType.Type.BINARY: "BYTES", 536 exp.DataType.Type.BOOLEAN: "BOOL", 537 exp.DataType.Type.CHAR: "STRING", 538 exp.DataType.Type.DECIMAL: "NUMERIC", 539 exp.DataType.Type.DOUBLE: "FLOAT64", 540 exp.DataType.Type.FLOAT: "FLOAT64", 541 exp.DataType.Type.INT: "INT64", 542 exp.DataType.Type.NCHAR: "STRING", 543 exp.DataType.Type.NVARCHAR: "STRING", 544 exp.DataType.Type.SMALLINT: "INT64", 545 exp.DataType.Type.TEXT: "STRING", 546 exp.DataType.Type.TIMESTAMP: "DATETIME", 547 exp.DataType.Type.TIMESTAMPTZ: "TIMESTAMP", 548 exp.DataType.Type.TIMESTAMPLTZ: "TIMESTAMP", 549 exp.DataType.Type.TINYINT: "INT64", 550 exp.DataType.Type.VARBINARY: "BYTES", 551 exp.DataType.Type.VARCHAR: "STRING", 552 exp.DataType.Type.VARIANT: "ANY TYPE", 553 } 554 555 PROPERTIES_LOCATION = { 556 **generator.Generator.PROPERTIES_LOCATION, 557 exp.PartitionedByProperty: exp.Properties.Location.POST_SCHEMA, 558 exp.VolatileProperty: exp.Properties.Location.UNSUPPORTED, 559 } 560 561 # from: https://cloud.google.com/bigquery/docs/reference/standard-sql/lexical#reserved_keywords 562 RESERVED_KEYWORDS = { 563 *generator.Generator.RESERVED_KEYWORDS, 564 "all", 565 "and", 566 "any", 567 "array", 568 "as", 569 "asc", 570 "assert_rows_modified", 571 "at", 572 "between", 573 "by", 574 "case", 575 "cast", 576 "collate", 577 "contains", 578 "create", 579 "cross", 580 "cube", 581 "current", 582 "default", 583 "define", 584 "desc", 585 "distinct", 586 "else", 587 "end", 588 "enum", 589 "escape", 590 "except", 591 "exclude", 592 "exists", 593 "extract", 594 "false", 595 "fetch", 596 "following", 597 "for", 598 "from", 599 "full", 600 "group", 601 "grouping", 602 "groups", 603 "hash", 604 "having", 605 "if", 606 "ignore", 607 "in", 608 "inner", 609 "intersect", 610 "interval", 611 "into", 612 "is", 613 "join", 614 "lateral", 615 "left", 616 "like", 617 "limit", 618 "lookup", 619 "merge", 620 "natural", 621 "new", 622 "no", 623 "not", 624 "null", 625 "nulls", 626 "of", 627 "on", 628 "or", 629 "order", 630 "outer", 631 "over", 632 "partition", 633 "preceding", 634 "proto", 635 "qualify", 636 "range", 637 "recursive", 638 "respect", 639 "right", 640 "rollup", 641 "rows", 642 "select", 643 "set", 644 "some", 645 "struct", 646 "tablesample", 647 "then", 648 "to", 649 "treat", 650 "true", 651 "unbounded", 652 "union", 653 "unnest", 654 "using", 655 "when", 656 "where", 657 "window", 658 "with", 659 "within", 660 } 661 662 def eq_sql(self, expression: exp.EQ) -> str: 663 # Operands of = cannot be NULL in BigQuery 664 if isinstance(expression.left, exp.Null) or isinstance(expression.right, exp.Null): 665 return "NULL" 666 667 return self.binary(expression, "=") 668 669 def attimezone_sql(self, expression: exp.AtTimeZone) -> str: 670 parent = expression.parent 671 672 # BigQuery allows CAST(.. AS {STRING|TIMESTAMP} [FORMAT <fmt> [AT TIME ZONE <tz>]]). 673 # Only the TIMESTAMP one should use the below conversion, when AT TIME ZONE is included. 674 if not isinstance(parent, exp.Cast) or not parent.to.is_type("text"): 675 return self.func( 676 "TIMESTAMP", self.func("DATETIME", expression.this, expression.args.get("zone")) 677 ) 678 679 return super().attimezone_sql(expression) 680 681 def trycast_sql(self, expression: exp.TryCast) -> str: 682 return self.cast_sql(expression, safe_prefix="SAFE_") 683 684 def cte_sql(self, expression: exp.CTE) -> str: 685 if expression.alias_column_names: 686 self.unsupported("Column names in CTE definition are not supported.") 687 return super().cte_sql(expression) 688 689 def array_sql(self, expression: exp.Array) -> str: 690 first_arg = seq_get(expression.expressions, 0) 691 if isinstance(first_arg, exp.Subqueryable): 692 return f"ARRAY{self.wrap(self.sql(first_arg))}" 693 694 return inline_array_sql(self, expression) 695 696 def transaction_sql(self, *_) -> str: 697 return "BEGIN TRANSACTION" 698 699 def commit_sql(self, *_) -> str: 700 return "COMMIT TRANSACTION" 701 702 def rollback_sql(self, *_) -> str: 703 return "ROLLBACK TRANSACTION" 704 705 def in_unnest_op(self, expression: exp.Unnest) -> str: 706 return self.sql(expression) 707 708 def except_op(self, expression: exp.Except) -> str: 709 if not expression.args.get("distinct", False): 710 self.unsupported("EXCEPT without DISTINCT is not supported in BigQuery") 711 return f"EXCEPT{' DISTINCT' if expression.args.get('distinct') else ' ALL'}" 712 713 def intersect_op(self, expression: exp.Intersect) -> str: 714 if not expression.args.get("distinct", False): 715 self.unsupported("INTERSECT without DISTINCT is not supported in BigQuery") 716 return f"INTERSECT{' DISTINCT' if expression.args.get('distinct') else ' ALL'}" 717 718 def with_properties(self, properties: exp.Properties) -> str: 719 return self.properties(properties, prefix=self.seg("OPTIONS")) 720 721 def version_sql(self, expression: exp.Version) -> str: 722 if expression.name == "TIMESTAMP": 723 expression.set("this", "SYSTEM_TIME") 724 return super().version_sql(expression)
Generator converts a given syntax tree to the corresponding SQL string.
Arguments:
- pretty: Whether or not 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 or not to normalize identifiers to lowercase. Default: False.
- pad: Determines the pad size in a formatted string. Default: 2.
- indent: Determines the indentation size in a formatted string. Default: 2.
- normalize_functions: Whether or not to normalize all 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: Determines whether or not 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 or not to preserve comments in the output SQL code. Default: True
TRANSFORMS =
{<class 'sqlglot.expressions.DateAdd'>: <function date_add_interval_sql.<locals>.func>, <class 'sqlglot.expressions.TsOrDsAdd'>: <function date_add_interval_sql.<locals>.func>, <class 'sqlglot.expressions.CaseSpecificColumnConstraint'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.CharacterSetColumnConstraint'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.CharacterSetProperty'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.CheckColumnConstraint'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.ClusteredColumnConstraint'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.CollateColumnConstraint'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.CopyGrantsProperty'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.CommentColumnConstraint'>: <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.ExecuteAsProperty'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.ExternalProperty'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.HeapProperty'>: <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.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.NoPrimaryIndexProperty'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.NonClusteredColumnConstraint'>: <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.RemoteWithConnectionModelProperty'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.ReturnsProperty'>: <function _returnsproperty_sql>, <class 'sqlglot.expressions.SampleProperty'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.SetProperty'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.SettingsProperty'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.SqlSecurityProperty'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.StabilityProperty'>: <function BigQuery.Generator.<lambda>>, <class 'sqlglot.expressions.TemporaryProperty'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.ToTableProperty'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.TransientProperty'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.TransformModelProperty'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.TitleColumnConstraint'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.UppercaseColumnConstraint'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.VarMap'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.VolatileProperty'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.WithJournalTableProperty'>: <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.ArrayContains'>: <function _array_contains_sql>, <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.Create'>: <function _create_sql>, <class 'sqlglot.expressions.CTE'>: <function preprocess.<locals>._to_sql>, <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.GenerateSeries'>: <function rename_func.<locals>.<lambda>>, <class 'sqlglot.expressions.GroupConcat'>: <function rename_func.<locals>.<lambda>>, <class 'sqlglot.expressions.Hex'>: <function rename_func.<locals>.<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.JSONKeyValue'>: <function json_keyvalue_comma_sql>, <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.Select'>: <function preprocess.<locals>._to_sql>, <class 'sqlglot.expressions.SHA2'>: <function BigQuery.Generator.<lambda>>, <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.TimeSub'>: <function date_add_interval_sql.<locals>.func>, <class 'sqlglot.expressions.TimestampAdd'>: <function date_add_interval_sql.<locals>.func>, <class 'sqlglot.expressions.TimestampSub'>: <function date_add_interval_sql.<locals>.func>, <class 'sqlglot.expressions.TimeStrToTime'>: <function timestrtotime_sql>, <class 'sqlglot.expressions.Trim'>: <function BigQuery.Generator.<lambda>>, <class 'sqlglot.expressions.TsOrDsToDate'>: <function ts_or_ds_to_date_sql.<locals>._ts_or_ds_to_date_sql>, <class 'sqlglot.expressions.Unhex'>: <function rename_func.<locals>.<lambda>>, <class 'sqlglot.expressions.Values'>: <function _derived_table_values_to_unnest>, <class 'sqlglot.expressions.VariancePop'>: <function rename_func.<locals>.<lambda>>}
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.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.AlgorithmProperty'>: <Location.POST_CREATE: 'POST_CREATE'>, <class 'sqlglot.expressions.AutoIncrementProperty'>: <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.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.HeapProperty'>: <Location.POST_WITH: 'POST_WITH'>, <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.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.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.SortKeyProperty'>: <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.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.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 =
{'as', 'or', 'recursive', 'qualify', 'at', 'asc', 'exists', 'extract', 'if', 'else', 'natural', 'merge', 'union', 'null', 'exclude', 'for', 'window', 'following', 'is', 'like', 'intersect', 'full', 'join', 'unbounded', 'between', 'range', 'and', 'set', 'unnest', 'not', 'treat', 'array', 'limit', 'within', 'create', 'define', 'then', 'when', 'with', 'in', 'contains', 'left', 'lookup', 'enum', 'on', 'where', 'nulls', 'proto', 'current', 'right', 'case', 'distinct', 'select', 'fetch', 'outer', 'of', 'false', 'assert_rows_modified', 'end', 'over', 'group', 'respect', 'cast', 'struct', 'desc', 'true', 'cross', 'interval', 'groups', 'using', 'rollup', 'inner', 'escape', 'cube', 'default', 'except', 'no', 'partition', 'hash', 'grouping', 'to', 'any', 'by', 'order', 'from', 'into', 'rows', 'all', 'having', 'preceding', 'tablesample', 'collate', 'ignore', 'new', 'some', 'lateral'}
669 def attimezone_sql(self, expression: exp.AtTimeZone) -> str: 670 parent = expression.parent 671 672 # BigQuery allows CAST(.. AS {STRING|TIMESTAMP} [FORMAT <fmt> [AT TIME ZONE <tz>]]). 673 # Only the TIMESTAMP one should use the below conversion, when AT TIME ZONE is included. 674 if not isinstance(parent, exp.Cast) or not parent.to.is_type("text"): 675 return self.func( 676 "TIMESTAMP", self.func("DATETIME", expression.this, expression.args.get("zone")) 677 ) 678 679 return super().attimezone_sql(expression)
INVERSE_ESCAPE_SEQUENCES: Dict[str, str] =
{'\x07': '\\a', '\x08': '\\b', '\x0c': '\\f', '\n': '\\n', '\r': '\\r', '\t': '\\t', '\x0b': '\\v'}
@classmethod
def
can_identify(text: str, identify: str | bool = 'safe') -> bool:
288 @classmethod 289 def can_identify(cls, text: str, identify: str | bool = "safe") -> bool: 290 """Checks if text can be identified given an identify option. 291 292 Args: 293 text: The text to check. 294 identify: 295 "always" or `True`: Always returns true. 296 "safe": True if the identifier is case-insensitive. 297 298 Returns: 299 Whether or not the given text can be identified. 300 """ 301 if identify is True or identify == "always": 302 return True 303 304 if identify == "safe": 305 return not cls.case_sensitive(text) 306 307 return False
Checks if text can be identified given an identify option.
Arguments:
- text: The text to check.
- identify: "always" or
True
: Always returns true. "safe": True if the identifier is case-insensitive.
Returns:
Whether or not the given text can be identified.
TOKENIZER_CLASS =
<class 'BigQuery.Tokenizer'>
Inherited Members
- sqlglot.generator.Generator
- Generator
- NULL_ORDERING_SUPPORTED
- LOCKING_READS_SUPPORTED
- WRAP_DERIVED_VALUES
- CREATE_FUNCTION_RETURN_AS
- MATCHED_BY_SOURCE
- SINGLE_STRING_INTERVAL
- TABLESAMPLE_WITH_METHOD
- TABLESAMPLE_SIZE_IS_PERCENT
- LIMIT_ONLY_LITERALS
- GROUPINGS_SEP
- INDEX_ON
- QUERY_HINT_SEP
- IS_BOOL_ALLOWED
- DUPLICATE_KEY_UPDATE_WITH_SET
- LIMIT_IS_TOP
- RETURNING_END
- COLUMN_JOIN_MARKS_SUPPORTED
- EXTRACT_ALLOWS_QUOTES
- TZ_TO_WITH_TIME_ZONE
- SELECT_KINDS
- VALUES_AS_TABLE
- ALTER_TABLE_ADD_COLUMN_KEYWORD
- AGGREGATE_FILTER_SUPPORTED
- SEMI_ANTI_JOIN_WITH_SIDE
- SUPPORTS_PARAMETERS
- COMPUTED_COLUMN_WITH_TYPE
- SUPPORTS_TABLE_COPY
- TABLESAMPLE_REQUIRES_PARENS
- DATA_TYPE_SPECIFIERS_ALLOWED
- ENSURE_BOOLS
- CTE_RECURSIVE_KEYWORD_REQUIRED
- TYPED_DIVISION
- SAFE_DIVISION
- STAR_MAPPING
- TIME_PART_SINGULARS
- TOKEN_MAPPING
- STRUCT_DELIMITER
- PARAMETER_TOKEN
- WITH_SEPARATED_COMMENTS
- EXCLUDE_COMMENTS
- UNWRAPPED_INTERVAL_VALUES
- EXPRESSIONS_WITHOUT_NESTED_CTES
- KEY_VALUE_DEFINITONS
- SENTINEL_LINE_BREAK
- INDEX_OFFSET
- ALIAS_POST_TABLESAMPLE
- IDENTIFIERS_CAN_START_WITH_DIGIT
- STRICT_STRING_CONCAT
- NULL_ORDERING
- pretty
- identify
- normalize
- pad
- unsupported_level
- max_unsupported
- leading_comma
- max_text_width
- comments
- normalize_functions
- unsupported_messages
- generate
- 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
- primarykeycolumnconstraint_sql
- uniquecolumnconstraint_sql
- createable_sql
- create_sql
- clone_sql
- describe_sql
- prepend_ctes
- with_sql
- tablealias_sql
- bitstring_sql
- hexstring_sql
- bytestring_sql
- rawstring_sql
- datatypeparam_sql
- datatype_sql
- directory_sql
- delete_sql
- drop_sql
- except_sql
- fetch_sql
- filter_sql
- hint_sql
- index_sql
- identifier_sql
- inputoutputformat_sql
- national_sql
- partition_sql
- properties_sql
- root_properties
- 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
- 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_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
- cluster_sql
- distribute_sql
- sort_sql
- ordered_sql
- matchrecognize_sql
- query_modifiers
- offset_limit_modifiers
- after_having_modifiers
- after_limit_modifiers
- select_sql
- schema_sql
- schema_columns_sql
- star_sql
- parameter_sql
- sessionparameter_sql
- placeholder_sql
- subquery_sql
- qualify_sql
- union_sql
- union_op
- unnest_sql
- where_sql
- window_sql
- partition_by_sql
- windowspec_sql
- withingroup_sql
- between_sql
- bracket_sql
- safebracket_sql
- all_sql
- any_sql
- exists_sql
- case_sql
- constraint_sql
- nextvaluefor_sql
- extract_sql
- trim_sql
- safeconcat_sql
- check_sql
- foreignkey_sql
- primarykey_sql
- if_sql
- matchagainst_sql
- jsonkeyvalue_sql
- formatjson_sql
- jsonobject_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
- aliases_sql
- add_sql
- and_sql
- xor_sql
- connector_sql
- bitwiseand_sql
- bitwiseleftshift_sql
- bitwisenot_sql
- bitwiseor_sql
- bitwiserightshift_sql
- bitwisexor_sql
- cast_sql
- currentdate_sql
- collate_sql
- command_sql
- comment_sql
- mergetreettlaction_sql
- mergetreettl_sql
- altercolumn_sql
- renametable_sql
- altertable_sql
- add_column_sql
- droppartition_sql
- addconstraint_sql
- distinct_sql
- ignorenulls_sql
- respectnulls_sql
- intdiv_sql
- dpipe_sql
- safedpipe_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
- mod_sql
- mul_sql
- neq_sql
- nullsafeeq_sql
- nullsafeneq_sql
- or_sql
- slice_sql
- sub_sql
- log_sql
- use_sql
- binary
- function_fallback_sql
- func
- format_args
- text_width
- format_time
- expressions
- op_expressions
- naked_property
- set_operation
- tag_sql
- token_sql
- userdefinedfunction_sql
- joinhint_sql
- kwarg_sql
- when_sql
- merge_sql
- tochar_sql
- dictproperty_sql
- dictrange_sql
- dictsubproperty_sql
- oncluster_sql
- clusteredbyproperty_sql
- anyvalue_sql
- querytransform_sql
- indexconstraintoption_sql
- indexcolumnconstraint_sql
- nvl2_sql
- comprehension_sql
- columnprefix_sql
- opclass_sql
- predict_sql
- forin_sql
- refresh_sql