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_add_cast, 27 ts_or_ds_to_date_sql, 28) 29from sqlglot.helper import seq_get, split_num_words 30from sqlglot.tokens import TokenType 31 32logger = logging.getLogger("sqlglot") 33 34 35def _derived_table_values_to_unnest(self: BigQuery.Generator, expression: exp.Values) -> str: 36 if not expression.find_ancestor(exp.From, exp.Join): 37 return self.values_sql(expression) 38 39 alias = expression.args.get("alias") 40 41 structs = [ 42 exp.Struct( 43 expressions=[ 44 exp.alias_(value, column_name) 45 for value, column_name in zip( 46 t.expressions, 47 alias.columns 48 if alias and alias.columns 49 else (f"_c{i}" for i in range(len(t.expressions))), 50 ) 51 ] 52 ) 53 for t in expression.find_all(exp.Tuple) 54 ] 55 56 return self.unnest_sql(exp.Unnest(expressions=[exp.Array(expressions=structs)])) 57 58 59def _returnsproperty_sql(self: BigQuery.Generator, expression: exp.ReturnsProperty) -> str: 60 this = expression.this 61 if isinstance(this, exp.Schema): 62 this = f"{this.this} <{self.expressions(this)}>" 63 else: 64 this = self.sql(this) 65 return f"RETURNS {this}" 66 67 68def _create_sql(self: BigQuery.Generator, expression: exp.Create) -> str: 69 kind = expression.args["kind"] 70 returns = expression.find(exp.ReturnsProperty) 71 72 if kind.upper() == "FUNCTION" and returns and returns.args.get("is_table"): 73 expression.set("kind", "TABLE FUNCTION") 74 75 if isinstance(expression.expression, (exp.Subquery, exp.Literal)): 76 expression.set("expression", expression.expression.this) 77 78 return self.create_sql(expression) 79 80 return self.create_sql(expression) 81 82 83def _unqualify_unnest(expression: exp.Expression) -> exp.Expression: 84 """Remove references to unnest table aliases since bigquery doesn't allow them. 85 86 These are added by the optimizer's qualify_column step. 87 """ 88 from sqlglot.optimizer.scope import find_all_in_scope 89 90 if isinstance(expression, exp.Select): 91 unnest_aliases = { 92 unnest.alias 93 for unnest in find_all_in_scope(expression, exp.Unnest) 94 if isinstance(unnest.parent, (exp.From, exp.Join)) 95 } 96 if unnest_aliases: 97 for column in expression.find_all(exp.Column): 98 if column.table in unnest_aliases: 99 column.set("table", None) 100 elif column.db in unnest_aliases: 101 column.set("db", None) 102 103 return expression 104 105 106# https://issuetracker.google.com/issues/162294746 107# workaround for bigquery bug when grouping by an expression and then ordering 108# WITH x AS (SELECT 1 y) 109# SELECT y + 1 z 110# FROM x 111# GROUP BY x + 1 112# ORDER by z 113def _alias_ordered_group(expression: exp.Expression) -> exp.Expression: 114 if isinstance(expression, exp.Select): 115 group = expression.args.get("group") 116 order = expression.args.get("order") 117 118 if group and order: 119 aliases = { 120 select.this: select.args["alias"] 121 for select in expression.selects 122 if isinstance(select, exp.Alias) 123 } 124 125 for e in group.expressions: 126 alias = aliases.get(e) 127 128 if alias: 129 e.replace(exp.column(alias)) 130 131 return expression 132 133 134def _pushdown_cte_column_names(expression: exp.Expression) -> exp.Expression: 135 """BigQuery doesn't allow column names when defining a CTE, so we try to push them down.""" 136 if isinstance(expression, exp.CTE) and expression.alias_column_names: 137 cte_query = expression.this 138 139 if cte_query.is_star: 140 logger.warning( 141 "Can't push down CTE column names for star queries. Run the query through" 142 " the optimizer or use 'qualify' to expand the star projections first." 143 ) 144 return expression 145 146 column_names = expression.alias_column_names 147 expression.args["alias"].set("columns", None) 148 149 for name, select in zip(column_names, cte_query.selects): 150 to_replace = select 151 152 if isinstance(select, exp.Alias): 153 select = select.this 154 155 # Inner aliases are shadowed by the CTE column names 156 to_replace.replace(exp.alias_(select, name)) 157 158 return expression 159 160 161def _parse_timestamp(args: t.List) -> exp.StrToTime: 162 this = format_time_lambda(exp.StrToTime, "bigquery")([seq_get(args, 1), seq_get(args, 0)]) 163 this.set("zone", seq_get(args, 2)) 164 return this 165 166 167def _parse_date(args: t.List) -> exp.Date | exp.DateFromParts: 168 expr_type = exp.DateFromParts if len(args) == 3 else exp.Date 169 return expr_type.from_arg_list(args) 170 171 172def _parse_to_hex(args: t.List) -> exp.Hex | exp.MD5: 173 # TO_HEX(MD5(..)) is common in BigQuery, so it's parsed into MD5 to simplify its transpilation 174 arg = seq_get(args, 0) 175 return exp.MD5(this=arg.this) if isinstance(arg, exp.MD5Digest) else exp.Hex(this=arg) 176 177 178def _array_contains_sql(self: BigQuery.Generator, expression: exp.ArrayContains) -> str: 179 return self.sql( 180 exp.Exists( 181 this=exp.select("1") 182 .from_(exp.Unnest(expressions=[expression.left]).as_("_unnest", table=["_col"])) 183 .where(exp.column("_col").eq(expression.right)) 184 ) 185 ) 186 187 188def _ts_or_ds_add_sql(self: BigQuery.Generator, expression: exp.TsOrDsAdd) -> str: 189 return date_add_interval_sql("DATE", "ADD")(self, ts_or_ds_add_cast(expression)) 190 191 192def _ts_or_ds_diff_sql(self: BigQuery.Generator, expression: exp.TsOrDsDiff) -> str: 193 expression.this.replace(exp.cast(expression.this, "TIMESTAMP", copy=True)) 194 expression.expression.replace(exp.cast(expression.expression, "TIMESTAMP", copy=True)) 195 unit = expression.args.get("unit") or "DAY" 196 return self.func("DATE_DIFF", expression.this, expression.expression, unit) 197 198 199class BigQuery(Dialect): 200 UNNEST_COLUMN_ONLY = True 201 SUPPORTS_USER_DEFINED_TYPES = False 202 SUPPORTS_SEMI_ANTI_JOIN = False 203 LOG_BASE_FIRST = False 204 205 # https://cloud.google.com/bigquery/docs/reference/standard-sql/lexical#case_sensitivity 206 RESOLVES_IDENTIFIERS_AS_UPPERCASE = None 207 208 # bigquery udfs are case sensitive 209 NORMALIZE_FUNCTIONS = False 210 211 TIME_MAPPING = { 212 "%D": "%m/%d/%y", 213 } 214 215 ESCAPE_SEQUENCES = { 216 "\\a": "\a", 217 "\\b": "\b", 218 "\\f": "\f", 219 "\\n": "\n", 220 "\\r": "\r", 221 "\\t": "\t", 222 "\\v": "\v", 223 } 224 225 FORMAT_MAPPING = { 226 "DD": "%d", 227 "MM": "%m", 228 "MON": "%b", 229 "MONTH": "%B", 230 "YYYY": "%Y", 231 "YY": "%y", 232 "HH": "%I", 233 "HH12": "%I", 234 "HH24": "%H", 235 "MI": "%M", 236 "SS": "%S", 237 "SSSSS": "%f", 238 "TZH": "%z", 239 } 240 241 # The _PARTITIONTIME and _PARTITIONDATE pseudo-columns are not returned by a SELECT * statement 242 # https://cloud.google.com/bigquery/docs/querying-partitioned-tables#query_an_ingestion-time_partitioned_table 243 PSEUDOCOLUMNS = {"_PARTITIONTIME", "_PARTITIONDATE"} 244 245 @classmethod 246 def normalize_identifier(cls, expression: E) -> E: 247 if isinstance(expression, exp.Identifier): 248 parent = expression.parent 249 while isinstance(parent, exp.Dot): 250 parent = parent.parent 251 252 # In BigQuery, CTEs aren't case-sensitive, but table names are (by default, at least). 253 # The following check is essentially a heuristic to detect tables based on whether or 254 # not they're qualified. It also avoids normalizing UDFs, because they're case-sensitive. 255 if ( 256 not isinstance(parent, exp.UserDefinedFunction) 257 and not (isinstance(parent, exp.Table) and parent.db) 258 and not expression.meta.get("is_table") 259 ): 260 expression.set("this", expression.this.lower()) 261 262 return expression 263 264 class Tokenizer(tokens.Tokenizer): 265 QUOTES = ["'", '"', '"""', "'''"] 266 COMMENTS = ["--", "#", ("/*", "*/")] 267 IDENTIFIERS = ["`"] 268 STRING_ESCAPES = ["\\"] 269 270 HEX_STRINGS = [("0x", ""), ("0X", "")] 271 272 BYTE_STRINGS = [ 273 (prefix + q, q) for q in t.cast(t.List[str], QUOTES) for prefix in ("b", "B") 274 ] 275 276 RAW_STRINGS = [ 277 (prefix + q, q) for q in t.cast(t.List[str], QUOTES) for prefix in ("r", "R") 278 ] 279 280 KEYWORDS = { 281 **tokens.Tokenizer.KEYWORDS, 282 "ANY TYPE": TokenType.VARIANT, 283 "BEGIN": TokenType.COMMAND, 284 "BEGIN TRANSACTION": TokenType.BEGIN, 285 "BYTES": TokenType.BINARY, 286 "CURRENT_DATETIME": TokenType.CURRENT_DATETIME, 287 "DECLARE": TokenType.COMMAND, 288 "FLOAT64": TokenType.DOUBLE, 289 "FOR SYSTEM_TIME": TokenType.TIMESTAMP_SNAPSHOT, 290 "MODEL": TokenType.MODEL, 291 "NOT DETERMINISTIC": TokenType.VOLATILE, 292 "RECORD": TokenType.STRUCT, 293 "TIMESTAMP": TokenType.TIMESTAMPTZ, 294 } 295 KEYWORDS.pop("DIV") 296 297 class Parser(parser.Parser): 298 PREFIXED_PIVOT_COLUMNS = True 299 300 LOG_DEFAULTS_TO_LN = True 301 302 FUNCTIONS = { 303 **parser.Parser.FUNCTIONS, 304 "DATE": _parse_date, 305 "DATE_ADD": parse_date_delta_with_interval(exp.DateAdd), 306 "DATE_SUB": parse_date_delta_with_interval(exp.DateSub), 307 "DATE_TRUNC": lambda args: exp.DateTrunc( 308 unit=exp.Literal.string(str(seq_get(args, 1))), 309 this=seq_get(args, 0), 310 ), 311 "DATETIME_ADD": parse_date_delta_with_interval(exp.DatetimeAdd), 312 "DATETIME_SUB": parse_date_delta_with_interval(exp.DatetimeSub), 313 "DIV": binary_from_function(exp.IntDiv), 314 "GENERATE_ARRAY": exp.GenerateSeries.from_arg_list, 315 "MD5": exp.MD5Digest.from_arg_list, 316 "TO_HEX": _parse_to_hex, 317 "PARSE_DATE": lambda args: format_time_lambda(exp.StrToDate, "bigquery")( 318 [seq_get(args, 1), seq_get(args, 0)] 319 ), 320 "PARSE_TIMESTAMP": _parse_timestamp, 321 "REGEXP_CONTAINS": exp.RegexpLike.from_arg_list, 322 "REGEXP_EXTRACT": lambda args: exp.RegexpExtract( 323 this=seq_get(args, 0), 324 expression=seq_get(args, 1), 325 position=seq_get(args, 2), 326 occurrence=seq_get(args, 3), 327 group=exp.Literal.number(1) if re.compile(args[1].name).groups == 1 else None, 328 ), 329 "SHA256": lambda args: exp.SHA2(this=seq_get(args, 0), length=exp.Literal.number(256)), 330 "SHA512": lambda args: exp.SHA2(this=seq_get(args, 0), length=exp.Literal.number(512)), 331 "SPLIT": lambda args: exp.Split( 332 # https://cloud.google.com/bigquery/docs/reference/standard-sql/string_functions#split 333 this=seq_get(args, 0), 334 expression=seq_get(args, 1) or exp.Literal.string(","), 335 ), 336 "TIME_ADD": parse_date_delta_with_interval(exp.TimeAdd), 337 "TIME_SUB": parse_date_delta_with_interval(exp.TimeSub), 338 "TIMESTAMP_ADD": parse_date_delta_with_interval(exp.TimestampAdd), 339 "TIMESTAMP_SUB": parse_date_delta_with_interval(exp.TimestampSub), 340 "TO_JSON_STRING": exp.JSONFormat.from_arg_list, 341 } 342 343 FUNCTION_PARSERS = { 344 **parser.Parser.FUNCTION_PARSERS, 345 "ARRAY": lambda self: self.expression(exp.Array, expressions=[self._parse_statement()]), 346 } 347 FUNCTION_PARSERS.pop("TRIM") 348 349 NO_PAREN_FUNCTIONS = { 350 **parser.Parser.NO_PAREN_FUNCTIONS, 351 TokenType.CURRENT_DATETIME: exp.CurrentDatetime, 352 } 353 354 NESTED_TYPE_TOKENS = { 355 *parser.Parser.NESTED_TYPE_TOKENS, 356 TokenType.TABLE, 357 } 358 359 ID_VAR_TOKENS = { 360 *parser.Parser.ID_VAR_TOKENS, 361 TokenType.VALUES, 362 } 363 364 PROPERTY_PARSERS = { 365 **parser.Parser.PROPERTY_PARSERS, 366 "NOT DETERMINISTIC": lambda self: self.expression( 367 exp.StabilityProperty, this=exp.Literal.string("VOLATILE") 368 ), 369 "OPTIONS": lambda self: self._parse_with_property(), 370 } 371 372 CONSTRAINT_PARSERS = { 373 **parser.Parser.CONSTRAINT_PARSERS, 374 "OPTIONS": lambda self: exp.Properties(expressions=self._parse_with_property()), 375 } 376 377 RANGE_PARSERS = parser.Parser.RANGE_PARSERS.copy() 378 RANGE_PARSERS.pop(TokenType.OVERLAPS, None) 379 380 NULL_TOKENS = {TokenType.NULL, TokenType.UNKNOWN} 381 382 STATEMENT_PARSERS = { 383 **parser.Parser.STATEMENT_PARSERS, 384 TokenType.END: lambda self: self._parse_as_command(self._prev), 385 TokenType.FOR: lambda self: self._parse_for_in(), 386 } 387 388 def _parse_for_in(self) -> exp.ForIn: 389 this = self._parse_range() 390 self._match_text_seq("DO") 391 return self.expression(exp.ForIn, this=this, expression=self._parse_statement()) 392 393 def _parse_table_part(self, schema: bool = False) -> t.Optional[exp.Expression]: 394 this = super()._parse_table_part(schema=schema) or self._parse_number() 395 396 # https://cloud.google.com/bigquery/docs/reference/standard-sql/lexical#table_names 397 if isinstance(this, exp.Identifier): 398 table_name = this.name 399 while self._match(TokenType.DASH, advance=False) and self._next: 400 self._advance(2) 401 table_name += f"-{self._prev.text}" 402 403 this = exp.Identifier(this=table_name, quoted=this.args.get("quoted")) 404 elif isinstance(this, exp.Literal): 405 table_name = this.name 406 407 if ( 408 self._curr 409 and self._prev.end == self._curr.start - 1 410 and self._parse_var(any_token=True) 411 ): 412 table_name += self._prev.text 413 414 this = exp.Identifier(this=table_name, quoted=True) 415 416 return this 417 418 def _parse_table_parts(self, schema: bool = False) -> exp.Table: 419 table = super()._parse_table_parts(schema=schema) 420 if isinstance(table.this, exp.Identifier) and "." in table.name: 421 catalog, db, this, *rest = ( 422 t.cast(t.Optional[exp.Expression], exp.to_identifier(x)) 423 for x in split_num_words(table.name, ".", 3) 424 ) 425 426 if rest and this: 427 this = exp.Dot.build(t.cast(t.List[exp.Expression], [this, *rest])) 428 429 table = exp.Table(this=this, db=db, catalog=catalog) 430 431 return table 432 433 def _parse_json_object(self) -> exp.JSONObject: 434 json_object = super()._parse_json_object() 435 array_kv_pair = seq_get(json_object.expressions, 0) 436 437 # Converts BQ's "signature 2" of JSON_OBJECT into SQLGlot's canonical representation 438 # https://cloud.google.com/bigquery/docs/reference/standard-sql/json_functions#json_object_signature2 439 if ( 440 array_kv_pair 441 and isinstance(array_kv_pair.this, exp.Array) 442 and isinstance(array_kv_pair.expression, exp.Array) 443 ): 444 keys = array_kv_pair.this.expressions 445 values = array_kv_pair.expression.expressions 446 447 json_object.set( 448 "expressions", 449 [exp.JSONKeyValue(this=k, expression=v) for k, v in zip(keys, values)], 450 ) 451 452 return json_object 453 454 class Generator(generator.Generator): 455 EXPLICIT_UNION = True 456 INTERVAL_ALLOWS_PLURAL_FORM = False 457 JOIN_HINTS = False 458 QUERY_HINTS = False 459 TABLE_HINTS = False 460 LIMIT_FETCH = "LIMIT" 461 RENAME_TABLE_WITH_DB = False 462 NVL2_SUPPORTED = False 463 UNNEST_WITH_ORDINALITY = False 464 COLLATE_IS_FUNC = True 465 LIMIT_ONLY_LITERALS = True 466 467 TRANSFORMS = { 468 **generator.Generator.TRANSFORMS, 469 exp.ApproxDistinct: rename_func("APPROX_COUNT_DISTINCT"), 470 exp.ArgMax: arg_max_or_min_no_count("MAX_BY"), 471 exp.ArgMin: arg_max_or_min_no_count("MIN_BY"), 472 exp.ArrayContains: _array_contains_sql, 473 exp.ArraySize: rename_func("ARRAY_LENGTH"), 474 exp.Cast: transforms.preprocess([transforms.remove_precision_parameterized_types]), 475 exp.CollateProperty: lambda self, e: f"DEFAULT COLLATE {self.sql(e, 'this')}" 476 if e.args.get("default") 477 else f"COLLATE {self.sql(e, 'this')}", 478 exp.Create: _create_sql, 479 exp.CTE: transforms.preprocess([_pushdown_cte_column_names]), 480 exp.DateAdd: date_add_interval_sql("DATE", "ADD"), 481 exp.DateDiff: lambda self, e: f"DATE_DIFF({self.sql(e, 'this')}, {self.sql(e, 'expression')}, {self.sql(e.args.get('unit', 'DAY'))})", 482 exp.DateFromParts: rename_func("DATE"), 483 exp.DateStrToDate: datestrtodate_sql, 484 exp.DateSub: date_add_interval_sql("DATE", "SUB"), 485 exp.DatetimeAdd: date_add_interval_sql("DATETIME", "ADD"), 486 exp.DatetimeSub: date_add_interval_sql("DATETIME", "SUB"), 487 exp.DateTrunc: lambda self, e: self.func("DATE_TRUNC", e.this, e.text("unit")), 488 exp.GenerateSeries: rename_func("GENERATE_ARRAY"), 489 exp.GroupConcat: rename_func("STRING_AGG"), 490 exp.Hex: rename_func("TO_HEX"), 491 exp.If: if_sql(false_value="NULL"), 492 exp.ILike: no_ilike_sql, 493 exp.IntDiv: rename_func("DIV"), 494 exp.JSONFormat: rename_func("TO_JSON_STRING"), 495 exp.JSONKeyValue: json_keyvalue_comma_sql, 496 exp.Max: max_or_greatest, 497 exp.MD5: lambda self, e: self.func("TO_HEX", self.func("MD5", e.this)), 498 exp.MD5Digest: rename_func("MD5"), 499 exp.Min: min_or_least, 500 exp.PartitionedByProperty: lambda self, e: f"PARTITION BY {self.sql(e, 'this')}", 501 exp.RegexpExtract: lambda self, e: self.func( 502 "REGEXP_EXTRACT", 503 e.this, 504 e.expression, 505 e.args.get("position"), 506 e.args.get("occurrence"), 507 ), 508 exp.RegexpReplace: regexp_replace_sql, 509 exp.RegexpLike: rename_func("REGEXP_CONTAINS"), 510 exp.ReturnsProperty: _returnsproperty_sql, 511 exp.Select: transforms.preprocess( 512 [ 513 transforms.explode_to_unnest(), 514 _unqualify_unnest, 515 transforms.eliminate_distinct_on, 516 _alias_ordered_group, 517 transforms.eliminate_semi_and_anti_joins, 518 ] 519 ), 520 exp.SHA2: lambda self, e: self.func( 521 f"SHA256" if e.text("length") == "256" else "SHA512", e.this 522 ), 523 exp.StabilityProperty: lambda self, e: f"DETERMINISTIC" 524 if e.name == "IMMUTABLE" 525 else "NOT DETERMINISTIC", 526 exp.StrToDate: lambda self, e: f"PARSE_DATE({self.format_time(e)}, {self.sql(e, 'this')})", 527 exp.StrToTime: lambda self, e: self.func( 528 "PARSE_TIMESTAMP", self.format_time(e), e.this, e.args.get("zone") 529 ), 530 exp.TimeAdd: date_add_interval_sql("TIME", "ADD"), 531 exp.TimeSub: date_add_interval_sql("TIME", "SUB"), 532 exp.TimestampAdd: date_add_interval_sql("TIMESTAMP", "ADD"), 533 exp.TimestampSub: date_add_interval_sql("TIMESTAMP", "SUB"), 534 exp.TimeStrToTime: timestrtotime_sql, 535 exp.TimeToStr: lambda self, e: f"FORMAT_DATE({self.format_time(e)}, {self.sql(e, 'this')})", 536 exp.Trim: lambda self, e: self.func(f"TRIM", e.this, e.expression), 537 exp.TsOrDsAdd: _ts_or_ds_add_sql, 538 exp.TsOrDsDiff: _ts_or_ds_diff_sql, 539 exp.TsOrDsToDate: ts_or_ds_to_date_sql("bigquery"), 540 exp.Unhex: rename_func("FROM_HEX"), 541 exp.Values: _derived_table_values_to_unnest, 542 exp.VariancePop: rename_func("VAR_POP"), 543 } 544 545 TYPE_MAPPING = { 546 **generator.Generator.TYPE_MAPPING, 547 exp.DataType.Type.BIGDECIMAL: "BIGNUMERIC", 548 exp.DataType.Type.BIGINT: "INT64", 549 exp.DataType.Type.BINARY: "BYTES", 550 exp.DataType.Type.BOOLEAN: "BOOL", 551 exp.DataType.Type.CHAR: "STRING", 552 exp.DataType.Type.DECIMAL: "NUMERIC", 553 exp.DataType.Type.DOUBLE: "FLOAT64", 554 exp.DataType.Type.FLOAT: "FLOAT64", 555 exp.DataType.Type.INT: "INT64", 556 exp.DataType.Type.NCHAR: "STRING", 557 exp.DataType.Type.NVARCHAR: "STRING", 558 exp.DataType.Type.SMALLINT: "INT64", 559 exp.DataType.Type.TEXT: "STRING", 560 exp.DataType.Type.TIMESTAMP: "DATETIME", 561 exp.DataType.Type.TIMESTAMPTZ: "TIMESTAMP", 562 exp.DataType.Type.TIMESTAMPLTZ: "TIMESTAMP", 563 exp.DataType.Type.TINYINT: "INT64", 564 exp.DataType.Type.VARBINARY: "BYTES", 565 exp.DataType.Type.VARCHAR: "STRING", 566 exp.DataType.Type.VARIANT: "ANY TYPE", 567 } 568 569 PROPERTIES_LOCATION = { 570 **generator.Generator.PROPERTIES_LOCATION, 571 exp.PartitionedByProperty: exp.Properties.Location.POST_SCHEMA, 572 exp.VolatileProperty: exp.Properties.Location.UNSUPPORTED, 573 } 574 575 # from: https://cloud.google.com/bigquery/docs/reference/standard-sql/lexical#reserved_keywords 576 RESERVED_KEYWORDS = { 577 *generator.Generator.RESERVED_KEYWORDS, 578 "all", 579 "and", 580 "any", 581 "array", 582 "as", 583 "asc", 584 "assert_rows_modified", 585 "at", 586 "between", 587 "by", 588 "case", 589 "cast", 590 "collate", 591 "contains", 592 "create", 593 "cross", 594 "cube", 595 "current", 596 "default", 597 "define", 598 "desc", 599 "distinct", 600 "else", 601 "end", 602 "enum", 603 "escape", 604 "except", 605 "exclude", 606 "exists", 607 "extract", 608 "false", 609 "fetch", 610 "following", 611 "for", 612 "from", 613 "full", 614 "group", 615 "grouping", 616 "groups", 617 "hash", 618 "having", 619 "if", 620 "ignore", 621 "in", 622 "inner", 623 "intersect", 624 "interval", 625 "into", 626 "is", 627 "join", 628 "lateral", 629 "left", 630 "like", 631 "limit", 632 "lookup", 633 "merge", 634 "natural", 635 "new", 636 "no", 637 "not", 638 "null", 639 "nulls", 640 "of", 641 "on", 642 "or", 643 "order", 644 "outer", 645 "over", 646 "partition", 647 "preceding", 648 "proto", 649 "qualify", 650 "range", 651 "recursive", 652 "respect", 653 "right", 654 "rollup", 655 "rows", 656 "select", 657 "set", 658 "some", 659 "struct", 660 "tablesample", 661 "then", 662 "to", 663 "treat", 664 "true", 665 "unbounded", 666 "union", 667 "unnest", 668 "using", 669 "when", 670 "where", 671 "window", 672 "with", 673 "within", 674 } 675 676 def eq_sql(self, expression: exp.EQ) -> str: 677 # Operands of = cannot be NULL in BigQuery 678 if isinstance(expression.left, exp.Null) or isinstance(expression.right, exp.Null): 679 return "NULL" 680 681 return self.binary(expression, "=") 682 683 def attimezone_sql(self, expression: exp.AtTimeZone) -> str: 684 parent = expression.parent 685 686 # BigQuery allows CAST(.. AS {STRING|TIMESTAMP} [FORMAT <fmt> [AT TIME ZONE <tz>]]). 687 # Only the TIMESTAMP one should use the below conversion, when AT TIME ZONE is included. 688 if not isinstance(parent, exp.Cast) or not parent.to.is_type("text"): 689 return self.func( 690 "TIMESTAMP", self.func("DATETIME", expression.this, expression.args.get("zone")) 691 ) 692 693 return super().attimezone_sql(expression) 694 695 def trycast_sql(self, expression: exp.TryCast) -> str: 696 return self.cast_sql(expression, safe_prefix="SAFE_") 697 698 def cte_sql(self, expression: exp.CTE) -> str: 699 if expression.alias_column_names: 700 self.unsupported("Column names in CTE definition are not supported.") 701 return super().cte_sql(expression) 702 703 def array_sql(self, expression: exp.Array) -> str: 704 first_arg = seq_get(expression.expressions, 0) 705 if isinstance(first_arg, exp.Subqueryable): 706 return f"ARRAY{self.wrap(self.sql(first_arg))}" 707 708 return inline_array_sql(self, expression) 709 710 def transaction_sql(self, *_) -> str: 711 return "BEGIN TRANSACTION" 712 713 def commit_sql(self, *_) -> str: 714 return "COMMIT TRANSACTION" 715 716 def rollback_sql(self, *_) -> str: 717 return "ROLLBACK TRANSACTION" 718 719 def in_unnest_op(self, expression: exp.Unnest) -> str: 720 return self.sql(expression) 721 722 def except_op(self, expression: exp.Except) -> str: 723 if not expression.args.get("distinct", False): 724 self.unsupported("EXCEPT without DISTINCT is not supported in BigQuery") 725 return f"EXCEPT{' DISTINCT' if expression.args.get('distinct') else ' ALL'}" 726 727 def intersect_op(self, expression: exp.Intersect) -> str: 728 if not expression.args.get("distinct", False): 729 self.unsupported("INTERSECT without DISTINCT is not supported in BigQuery") 730 return f"INTERSECT{' DISTINCT' if expression.args.get('distinct') else ' ALL'}" 731 732 def with_properties(self, properties: exp.Properties) -> str: 733 return self.properties(properties, prefix=self.seg("OPTIONS")) 734 735 def version_sql(self, expression: exp.Version) -> str: 736 if expression.name == "TIMESTAMP": 737 expression.set("this", "SYSTEM_TIME") 738 return super().version_sql(expression)
logger =
<Logger sqlglot (WARNING)>
200class BigQuery(Dialect): 201 UNNEST_COLUMN_ONLY = True 202 SUPPORTS_USER_DEFINED_TYPES = False 203 SUPPORTS_SEMI_ANTI_JOIN = False 204 LOG_BASE_FIRST = False 205 206 # https://cloud.google.com/bigquery/docs/reference/standard-sql/lexical#case_sensitivity 207 RESOLVES_IDENTIFIERS_AS_UPPERCASE = None 208 209 # bigquery udfs are case sensitive 210 NORMALIZE_FUNCTIONS = False 211 212 TIME_MAPPING = { 213 "%D": "%m/%d/%y", 214 } 215 216 ESCAPE_SEQUENCES = { 217 "\\a": "\a", 218 "\\b": "\b", 219 "\\f": "\f", 220 "\\n": "\n", 221 "\\r": "\r", 222 "\\t": "\t", 223 "\\v": "\v", 224 } 225 226 FORMAT_MAPPING = { 227 "DD": "%d", 228 "MM": "%m", 229 "MON": "%b", 230 "MONTH": "%B", 231 "YYYY": "%Y", 232 "YY": "%y", 233 "HH": "%I", 234 "HH12": "%I", 235 "HH24": "%H", 236 "MI": "%M", 237 "SS": "%S", 238 "SSSSS": "%f", 239 "TZH": "%z", 240 } 241 242 # The _PARTITIONTIME and _PARTITIONDATE pseudo-columns are not returned by a SELECT * statement 243 # https://cloud.google.com/bigquery/docs/querying-partitioned-tables#query_an_ingestion-time_partitioned_table 244 PSEUDOCOLUMNS = {"_PARTITIONTIME", "_PARTITIONDATE"} 245 246 @classmethod 247 def normalize_identifier(cls, expression: E) -> E: 248 if isinstance(expression, exp.Identifier): 249 parent = expression.parent 250 while isinstance(parent, exp.Dot): 251 parent = parent.parent 252 253 # In BigQuery, CTEs aren't case-sensitive, but table names are (by default, at least). 254 # The following check is essentially a heuristic to detect tables based on whether or 255 # not they're qualified. It also avoids normalizing UDFs, because they're case-sensitive. 256 if ( 257 not isinstance(parent, exp.UserDefinedFunction) 258 and not (isinstance(parent, exp.Table) and parent.db) 259 and not expression.meta.get("is_table") 260 ): 261 expression.set("this", expression.this.lower()) 262 263 return expression 264 265 class Tokenizer(tokens.Tokenizer): 266 QUOTES = ["'", '"', '"""', "'''"] 267 COMMENTS = ["--", "#", ("/*", "*/")] 268 IDENTIFIERS = ["`"] 269 STRING_ESCAPES = ["\\"] 270 271 HEX_STRINGS = [("0x", ""), ("0X", "")] 272 273 BYTE_STRINGS = [ 274 (prefix + q, q) for q in t.cast(t.List[str], QUOTES) for prefix in ("b", "B") 275 ] 276 277 RAW_STRINGS = [ 278 (prefix + q, q) for q in t.cast(t.List[str], QUOTES) for prefix in ("r", "R") 279 ] 280 281 KEYWORDS = { 282 **tokens.Tokenizer.KEYWORDS, 283 "ANY TYPE": TokenType.VARIANT, 284 "BEGIN": TokenType.COMMAND, 285 "BEGIN TRANSACTION": TokenType.BEGIN, 286 "BYTES": TokenType.BINARY, 287 "CURRENT_DATETIME": TokenType.CURRENT_DATETIME, 288 "DECLARE": TokenType.COMMAND, 289 "FLOAT64": TokenType.DOUBLE, 290 "FOR SYSTEM_TIME": TokenType.TIMESTAMP_SNAPSHOT, 291 "MODEL": TokenType.MODEL, 292 "NOT DETERMINISTIC": TokenType.VOLATILE, 293 "RECORD": TokenType.STRUCT, 294 "TIMESTAMP": TokenType.TIMESTAMPTZ, 295 } 296 KEYWORDS.pop("DIV") 297 298 class Parser(parser.Parser): 299 PREFIXED_PIVOT_COLUMNS = True 300 301 LOG_DEFAULTS_TO_LN = True 302 303 FUNCTIONS = { 304 **parser.Parser.FUNCTIONS, 305 "DATE": _parse_date, 306 "DATE_ADD": parse_date_delta_with_interval(exp.DateAdd), 307 "DATE_SUB": parse_date_delta_with_interval(exp.DateSub), 308 "DATE_TRUNC": lambda args: exp.DateTrunc( 309 unit=exp.Literal.string(str(seq_get(args, 1))), 310 this=seq_get(args, 0), 311 ), 312 "DATETIME_ADD": parse_date_delta_with_interval(exp.DatetimeAdd), 313 "DATETIME_SUB": parse_date_delta_with_interval(exp.DatetimeSub), 314 "DIV": binary_from_function(exp.IntDiv), 315 "GENERATE_ARRAY": exp.GenerateSeries.from_arg_list, 316 "MD5": exp.MD5Digest.from_arg_list, 317 "TO_HEX": _parse_to_hex, 318 "PARSE_DATE": lambda args: format_time_lambda(exp.StrToDate, "bigquery")( 319 [seq_get(args, 1), seq_get(args, 0)] 320 ), 321 "PARSE_TIMESTAMP": _parse_timestamp, 322 "REGEXP_CONTAINS": exp.RegexpLike.from_arg_list, 323 "REGEXP_EXTRACT": lambda args: exp.RegexpExtract( 324 this=seq_get(args, 0), 325 expression=seq_get(args, 1), 326 position=seq_get(args, 2), 327 occurrence=seq_get(args, 3), 328 group=exp.Literal.number(1) if re.compile(args[1].name).groups == 1 else None, 329 ), 330 "SHA256": lambda args: exp.SHA2(this=seq_get(args, 0), length=exp.Literal.number(256)), 331 "SHA512": lambda args: exp.SHA2(this=seq_get(args, 0), length=exp.Literal.number(512)), 332 "SPLIT": lambda args: exp.Split( 333 # https://cloud.google.com/bigquery/docs/reference/standard-sql/string_functions#split 334 this=seq_get(args, 0), 335 expression=seq_get(args, 1) or exp.Literal.string(","), 336 ), 337 "TIME_ADD": parse_date_delta_with_interval(exp.TimeAdd), 338 "TIME_SUB": parse_date_delta_with_interval(exp.TimeSub), 339 "TIMESTAMP_ADD": parse_date_delta_with_interval(exp.TimestampAdd), 340 "TIMESTAMP_SUB": parse_date_delta_with_interval(exp.TimestampSub), 341 "TO_JSON_STRING": exp.JSONFormat.from_arg_list, 342 } 343 344 FUNCTION_PARSERS = { 345 **parser.Parser.FUNCTION_PARSERS, 346 "ARRAY": lambda self: self.expression(exp.Array, expressions=[self._parse_statement()]), 347 } 348 FUNCTION_PARSERS.pop("TRIM") 349 350 NO_PAREN_FUNCTIONS = { 351 **parser.Parser.NO_PAREN_FUNCTIONS, 352 TokenType.CURRENT_DATETIME: exp.CurrentDatetime, 353 } 354 355 NESTED_TYPE_TOKENS = { 356 *parser.Parser.NESTED_TYPE_TOKENS, 357 TokenType.TABLE, 358 } 359 360 ID_VAR_TOKENS = { 361 *parser.Parser.ID_VAR_TOKENS, 362 TokenType.VALUES, 363 } 364 365 PROPERTY_PARSERS = { 366 **parser.Parser.PROPERTY_PARSERS, 367 "NOT DETERMINISTIC": lambda self: self.expression( 368 exp.StabilityProperty, this=exp.Literal.string("VOLATILE") 369 ), 370 "OPTIONS": lambda self: self._parse_with_property(), 371 } 372 373 CONSTRAINT_PARSERS = { 374 **parser.Parser.CONSTRAINT_PARSERS, 375 "OPTIONS": lambda self: exp.Properties(expressions=self._parse_with_property()), 376 } 377 378 RANGE_PARSERS = parser.Parser.RANGE_PARSERS.copy() 379 RANGE_PARSERS.pop(TokenType.OVERLAPS, None) 380 381 NULL_TOKENS = {TokenType.NULL, TokenType.UNKNOWN} 382 383 STATEMENT_PARSERS = { 384 **parser.Parser.STATEMENT_PARSERS, 385 TokenType.END: lambda self: self._parse_as_command(self._prev), 386 TokenType.FOR: lambda self: self._parse_for_in(), 387 } 388 389 def _parse_for_in(self) -> exp.ForIn: 390 this = self._parse_range() 391 self._match_text_seq("DO") 392 return self.expression(exp.ForIn, this=this, expression=self._parse_statement()) 393 394 def _parse_table_part(self, schema: bool = False) -> t.Optional[exp.Expression]: 395 this = super()._parse_table_part(schema=schema) or self._parse_number() 396 397 # https://cloud.google.com/bigquery/docs/reference/standard-sql/lexical#table_names 398 if isinstance(this, exp.Identifier): 399 table_name = this.name 400 while self._match(TokenType.DASH, advance=False) and self._next: 401 self._advance(2) 402 table_name += f"-{self._prev.text}" 403 404 this = exp.Identifier(this=table_name, quoted=this.args.get("quoted")) 405 elif isinstance(this, exp.Literal): 406 table_name = this.name 407 408 if ( 409 self._curr 410 and self._prev.end == self._curr.start - 1 411 and self._parse_var(any_token=True) 412 ): 413 table_name += self._prev.text 414 415 this = exp.Identifier(this=table_name, quoted=True) 416 417 return this 418 419 def _parse_table_parts(self, schema: bool = False) -> exp.Table: 420 table = super()._parse_table_parts(schema=schema) 421 if isinstance(table.this, exp.Identifier) and "." in table.name: 422 catalog, db, this, *rest = ( 423 t.cast(t.Optional[exp.Expression], exp.to_identifier(x)) 424 for x in split_num_words(table.name, ".", 3) 425 ) 426 427 if rest and this: 428 this = exp.Dot.build(t.cast(t.List[exp.Expression], [this, *rest])) 429 430 table = exp.Table(this=this, db=db, catalog=catalog) 431 432 return table 433 434 def _parse_json_object(self) -> exp.JSONObject: 435 json_object = super()._parse_json_object() 436 array_kv_pair = seq_get(json_object.expressions, 0) 437 438 # Converts BQ's "signature 2" of JSON_OBJECT into SQLGlot's canonical representation 439 # https://cloud.google.com/bigquery/docs/reference/standard-sql/json_functions#json_object_signature2 440 if ( 441 array_kv_pair 442 and isinstance(array_kv_pair.this, exp.Array) 443 and isinstance(array_kv_pair.expression, exp.Array) 444 ): 445 keys = array_kv_pair.this.expressions 446 values = array_kv_pair.expression.expressions 447 448 json_object.set( 449 "expressions", 450 [exp.JSONKeyValue(this=k, expression=v) for k, v in zip(keys, values)], 451 ) 452 453 return json_object 454 455 class Generator(generator.Generator): 456 EXPLICIT_UNION = True 457 INTERVAL_ALLOWS_PLURAL_FORM = False 458 JOIN_HINTS = False 459 QUERY_HINTS = False 460 TABLE_HINTS = False 461 LIMIT_FETCH = "LIMIT" 462 RENAME_TABLE_WITH_DB = False 463 NVL2_SUPPORTED = False 464 UNNEST_WITH_ORDINALITY = False 465 COLLATE_IS_FUNC = True 466 LIMIT_ONLY_LITERALS = True 467 468 TRANSFORMS = { 469 **generator.Generator.TRANSFORMS, 470 exp.ApproxDistinct: rename_func("APPROX_COUNT_DISTINCT"), 471 exp.ArgMax: arg_max_or_min_no_count("MAX_BY"), 472 exp.ArgMin: arg_max_or_min_no_count("MIN_BY"), 473 exp.ArrayContains: _array_contains_sql, 474 exp.ArraySize: rename_func("ARRAY_LENGTH"), 475 exp.Cast: transforms.preprocess([transforms.remove_precision_parameterized_types]), 476 exp.CollateProperty: lambda self, e: f"DEFAULT COLLATE {self.sql(e, 'this')}" 477 if e.args.get("default") 478 else f"COLLATE {self.sql(e, 'this')}", 479 exp.Create: _create_sql, 480 exp.CTE: transforms.preprocess([_pushdown_cte_column_names]), 481 exp.DateAdd: date_add_interval_sql("DATE", "ADD"), 482 exp.DateDiff: lambda self, e: f"DATE_DIFF({self.sql(e, 'this')}, {self.sql(e, 'expression')}, {self.sql(e.args.get('unit', 'DAY'))})", 483 exp.DateFromParts: rename_func("DATE"), 484 exp.DateStrToDate: datestrtodate_sql, 485 exp.DateSub: date_add_interval_sql("DATE", "SUB"), 486 exp.DatetimeAdd: date_add_interval_sql("DATETIME", "ADD"), 487 exp.DatetimeSub: date_add_interval_sql("DATETIME", "SUB"), 488 exp.DateTrunc: lambda self, e: self.func("DATE_TRUNC", e.this, e.text("unit")), 489 exp.GenerateSeries: rename_func("GENERATE_ARRAY"), 490 exp.GroupConcat: rename_func("STRING_AGG"), 491 exp.Hex: rename_func("TO_HEX"), 492 exp.If: if_sql(false_value="NULL"), 493 exp.ILike: no_ilike_sql, 494 exp.IntDiv: rename_func("DIV"), 495 exp.JSONFormat: rename_func("TO_JSON_STRING"), 496 exp.JSONKeyValue: json_keyvalue_comma_sql, 497 exp.Max: max_or_greatest, 498 exp.MD5: lambda self, e: self.func("TO_HEX", self.func("MD5", e.this)), 499 exp.MD5Digest: rename_func("MD5"), 500 exp.Min: min_or_least, 501 exp.PartitionedByProperty: lambda self, e: f"PARTITION BY {self.sql(e, 'this')}", 502 exp.RegexpExtract: lambda self, e: self.func( 503 "REGEXP_EXTRACT", 504 e.this, 505 e.expression, 506 e.args.get("position"), 507 e.args.get("occurrence"), 508 ), 509 exp.RegexpReplace: regexp_replace_sql, 510 exp.RegexpLike: rename_func("REGEXP_CONTAINS"), 511 exp.ReturnsProperty: _returnsproperty_sql, 512 exp.Select: transforms.preprocess( 513 [ 514 transforms.explode_to_unnest(), 515 _unqualify_unnest, 516 transforms.eliminate_distinct_on, 517 _alias_ordered_group, 518 transforms.eliminate_semi_and_anti_joins, 519 ] 520 ), 521 exp.SHA2: lambda self, e: self.func( 522 f"SHA256" if e.text("length") == "256" else "SHA512", e.this 523 ), 524 exp.StabilityProperty: lambda self, e: f"DETERMINISTIC" 525 if e.name == "IMMUTABLE" 526 else "NOT DETERMINISTIC", 527 exp.StrToDate: lambda self, e: f"PARSE_DATE({self.format_time(e)}, {self.sql(e, 'this')})", 528 exp.StrToTime: lambda self, e: self.func( 529 "PARSE_TIMESTAMP", self.format_time(e), e.this, e.args.get("zone") 530 ), 531 exp.TimeAdd: date_add_interval_sql("TIME", "ADD"), 532 exp.TimeSub: date_add_interval_sql("TIME", "SUB"), 533 exp.TimestampAdd: date_add_interval_sql("TIMESTAMP", "ADD"), 534 exp.TimestampSub: date_add_interval_sql("TIMESTAMP", "SUB"), 535 exp.TimeStrToTime: timestrtotime_sql, 536 exp.TimeToStr: lambda self, e: f"FORMAT_DATE({self.format_time(e)}, {self.sql(e, 'this')})", 537 exp.Trim: lambda self, e: self.func(f"TRIM", e.this, e.expression), 538 exp.TsOrDsAdd: _ts_or_ds_add_sql, 539 exp.TsOrDsDiff: _ts_or_ds_diff_sql, 540 exp.TsOrDsToDate: ts_or_ds_to_date_sql("bigquery"), 541 exp.Unhex: rename_func("FROM_HEX"), 542 exp.Values: _derived_table_values_to_unnest, 543 exp.VariancePop: rename_func("VAR_POP"), 544 } 545 546 TYPE_MAPPING = { 547 **generator.Generator.TYPE_MAPPING, 548 exp.DataType.Type.BIGDECIMAL: "BIGNUMERIC", 549 exp.DataType.Type.BIGINT: "INT64", 550 exp.DataType.Type.BINARY: "BYTES", 551 exp.DataType.Type.BOOLEAN: "BOOL", 552 exp.DataType.Type.CHAR: "STRING", 553 exp.DataType.Type.DECIMAL: "NUMERIC", 554 exp.DataType.Type.DOUBLE: "FLOAT64", 555 exp.DataType.Type.FLOAT: "FLOAT64", 556 exp.DataType.Type.INT: "INT64", 557 exp.DataType.Type.NCHAR: "STRING", 558 exp.DataType.Type.NVARCHAR: "STRING", 559 exp.DataType.Type.SMALLINT: "INT64", 560 exp.DataType.Type.TEXT: "STRING", 561 exp.DataType.Type.TIMESTAMP: "DATETIME", 562 exp.DataType.Type.TIMESTAMPTZ: "TIMESTAMP", 563 exp.DataType.Type.TIMESTAMPLTZ: "TIMESTAMP", 564 exp.DataType.Type.TINYINT: "INT64", 565 exp.DataType.Type.VARBINARY: "BYTES", 566 exp.DataType.Type.VARCHAR: "STRING", 567 exp.DataType.Type.VARIANT: "ANY TYPE", 568 } 569 570 PROPERTIES_LOCATION = { 571 **generator.Generator.PROPERTIES_LOCATION, 572 exp.PartitionedByProperty: exp.Properties.Location.POST_SCHEMA, 573 exp.VolatileProperty: exp.Properties.Location.UNSUPPORTED, 574 } 575 576 # from: https://cloud.google.com/bigquery/docs/reference/standard-sql/lexical#reserved_keywords 577 RESERVED_KEYWORDS = { 578 *generator.Generator.RESERVED_KEYWORDS, 579 "all", 580 "and", 581 "any", 582 "array", 583 "as", 584 "asc", 585 "assert_rows_modified", 586 "at", 587 "between", 588 "by", 589 "case", 590 "cast", 591 "collate", 592 "contains", 593 "create", 594 "cross", 595 "cube", 596 "current", 597 "default", 598 "define", 599 "desc", 600 "distinct", 601 "else", 602 "end", 603 "enum", 604 "escape", 605 "except", 606 "exclude", 607 "exists", 608 "extract", 609 "false", 610 "fetch", 611 "following", 612 "for", 613 "from", 614 "full", 615 "group", 616 "grouping", 617 "groups", 618 "hash", 619 "having", 620 "if", 621 "ignore", 622 "in", 623 "inner", 624 "intersect", 625 "interval", 626 "into", 627 "is", 628 "join", 629 "lateral", 630 "left", 631 "like", 632 "limit", 633 "lookup", 634 "merge", 635 "natural", 636 "new", 637 "no", 638 "not", 639 "null", 640 "nulls", 641 "of", 642 "on", 643 "or", 644 "order", 645 "outer", 646 "over", 647 "partition", 648 "preceding", 649 "proto", 650 "qualify", 651 "range", 652 "recursive", 653 "respect", 654 "right", 655 "rollup", 656 "rows", 657 "select", 658 "set", 659 "some", 660 "struct", 661 "tablesample", 662 "then", 663 "to", 664 "treat", 665 "true", 666 "unbounded", 667 "union", 668 "unnest", 669 "using", 670 "when", 671 "where", 672 "window", 673 "with", 674 "within", 675 } 676 677 def eq_sql(self, expression: exp.EQ) -> str: 678 # Operands of = cannot be NULL in BigQuery 679 if isinstance(expression.left, exp.Null) or isinstance(expression.right, exp.Null): 680 return "NULL" 681 682 return self.binary(expression, "=") 683 684 def attimezone_sql(self, expression: exp.AtTimeZone) -> str: 685 parent = expression.parent 686 687 # BigQuery allows CAST(.. AS {STRING|TIMESTAMP} [FORMAT <fmt> [AT TIME ZONE <tz>]]). 688 # Only the TIMESTAMP one should use the below conversion, when AT TIME ZONE is included. 689 if not isinstance(parent, exp.Cast) or not parent.to.is_type("text"): 690 return self.func( 691 "TIMESTAMP", self.func("DATETIME", expression.this, expression.args.get("zone")) 692 ) 693 694 return super().attimezone_sql(expression) 695 696 def trycast_sql(self, expression: exp.TryCast) -> str: 697 return self.cast_sql(expression, safe_prefix="SAFE_") 698 699 def cte_sql(self, expression: exp.CTE) -> str: 700 if expression.alias_column_names: 701 self.unsupported("Column names in CTE definition are not supported.") 702 return super().cte_sql(expression) 703 704 def array_sql(self, expression: exp.Array) -> str: 705 first_arg = seq_get(expression.expressions, 0) 706 if isinstance(first_arg, exp.Subqueryable): 707 return f"ARRAY{self.wrap(self.sql(first_arg))}" 708 709 return inline_array_sql(self, expression) 710 711 def transaction_sql(self, *_) -> str: 712 return "BEGIN TRANSACTION" 713 714 def commit_sql(self, *_) -> str: 715 return "COMMIT TRANSACTION" 716 717 def rollback_sql(self, *_) -> str: 718 return "ROLLBACK TRANSACTION" 719 720 def in_unnest_op(self, expression: exp.Unnest) -> str: 721 return self.sql(expression) 722 723 def except_op(self, expression: exp.Except) -> str: 724 if not expression.args.get("distinct", False): 725 self.unsupported("EXCEPT without DISTINCT is not supported in BigQuery") 726 return f"EXCEPT{' DISTINCT' if expression.args.get('distinct') else ' ALL'}" 727 728 def intersect_op(self, expression: exp.Intersect) -> str: 729 if not expression.args.get("distinct", False): 730 self.unsupported("INTERSECT without DISTINCT is not supported in BigQuery") 731 return f"INTERSECT{' DISTINCT' if expression.args.get('distinct') else ' ALL'}" 732 733 def with_properties(self, properties: exp.Properties) -> str: 734 return self.properties(properties, prefix=self.seg("OPTIONS")) 735 736 def version_sql(self, expression: exp.Version) -> str: 737 if expression.name == "TIMESTAMP": 738 expression.set("this", "SYSTEM_TIME") 739 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:
246 @classmethod 247 def normalize_identifier(cls, expression: E) -> E: 248 if isinstance(expression, exp.Identifier): 249 parent = expression.parent 250 while isinstance(parent, exp.Dot): 251 parent = parent.parent 252 253 # In BigQuery, CTEs aren't case-sensitive, but table names are (by default, at least). 254 # The following check is essentially a heuristic to detect tables based on whether or 255 # not they're qualified. It also avoids normalizing UDFs, because they're case-sensitive. 256 if ( 257 not isinstance(parent, exp.UserDefinedFunction) 258 and not (isinstance(parent, exp.Table) and parent.db) 259 and not expression.meta.get("is_table") 260 ): 261 expression.set("this", expression.this.lower()) 262 263 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
265 class Tokenizer(tokens.Tokenizer): 266 QUOTES = ["'", '"', '"""', "'''"] 267 COMMENTS = ["--", "#", ("/*", "*/")] 268 IDENTIFIERS = ["`"] 269 STRING_ESCAPES = ["\\"] 270 271 HEX_STRINGS = [("0x", ""), ("0X", "")] 272 273 BYTE_STRINGS = [ 274 (prefix + q, q) for q in t.cast(t.List[str], QUOTES) for prefix in ("b", "B") 275 ] 276 277 RAW_STRINGS = [ 278 (prefix + q, q) for q in t.cast(t.List[str], QUOTES) for prefix in ("r", "R") 279 ] 280 281 KEYWORDS = { 282 **tokens.Tokenizer.KEYWORDS, 283 "ANY TYPE": TokenType.VARIANT, 284 "BEGIN": TokenType.COMMAND, 285 "BEGIN TRANSACTION": TokenType.BEGIN, 286 "BYTES": TokenType.BINARY, 287 "CURRENT_DATETIME": TokenType.CURRENT_DATETIME, 288 "DECLARE": TokenType.COMMAND, 289 "FLOAT64": TokenType.DOUBLE, 290 "FOR SYSTEM_TIME": TokenType.TIMESTAMP_SNAPSHOT, 291 "MODEL": TokenType.MODEL, 292 "NOT DETERMINISTIC": TokenType.VOLATILE, 293 "RECORD": TokenType.STRUCT, 294 "TIMESTAMP": TokenType.TIMESTAMPTZ, 295 } 296 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.COLON_EQ: 'COLON_EQ'>, '<=>': <TokenType.NULLSAFE_EQ: 'NULLSAFE_EQ'>, '->': <TokenType.ARROW: 'ARROW'>, '->>': <TokenType.DARROW: 'DARROW'>, '=>': <TokenType.FARROW: 'FARROW'>, '#>': <TokenType.HASH_ARROW: 'HASH_ARROW'>, '#>>': <TokenType.DHASH_ARROW: 'DHASH_ARROW'>, '<->': <TokenType.LR_ARROW: 'LR_ARROW'>, '&&': <TokenType.DAMP: 'DAMP'>, '??': <TokenType.DQMARK: 'DQMARK'>, 'ALL': <TokenType.ALL: 'ALL'>, 'ALWAYS': <TokenType.ALWAYS: 'ALWAYS'>, 'AND': <TokenType.AND: 'AND'>, 'ANTI': <TokenType.ANTI: 'ANTI'>, 'ANY': <TokenType.ANY: 'ANY'>, 'ASC': <TokenType.ASC: 'ASC'>, 'AS': <TokenType.ALIAS: 'ALIAS'>, 'ASOF': <TokenType.ASOF: 'ASOF'>, 'AUTOINCREMENT': <TokenType.AUTO_INCREMENT: 'AUTO_INCREMENT'>, 'AUTO_INCREMENT': <TokenType.AUTO_INCREMENT: 'AUTO_INCREMENT'>, 'BEGIN': <TokenType.COMMAND: 'COMMAND'>, 'BETWEEN': <TokenType.BETWEEN: 'BETWEEN'>, 'CACHE': <TokenType.CACHE: 'CACHE'>, 'UNCACHE': <TokenType.UNCACHE: 'UNCACHE'>, 'CASE': <TokenType.CASE: 'CASE'>, 'CHARACTER SET': <TokenType.CHARACTER_SET: 'CHARACTER_SET'>, 'CLUSTER BY': <TokenType.CLUSTER_BY: 'CLUSTER_BY'>, 'COLLATE': <TokenType.COLLATE: 'COLLATE'>, 'COLUMN': <TokenType.COLUMN: 'COLUMN'>, 'COMMIT': <TokenType.COMMIT: 'COMMIT'>, 'CONNECT BY': <TokenType.CONNECT_BY: 'CONNECT_BY'>, 'CONSTRAINT': <TokenType.CONSTRAINT: 'CONSTRAINT'>, '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'>}
298 class Parser(parser.Parser): 299 PREFIXED_PIVOT_COLUMNS = True 300 301 LOG_DEFAULTS_TO_LN = True 302 303 FUNCTIONS = { 304 **parser.Parser.FUNCTIONS, 305 "DATE": _parse_date, 306 "DATE_ADD": parse_date_delta_with_interval(exp.DateAdd), 307 "DATE_SUB": parse_date_delta_with_interval(exp.DateSub), 308 "DATE_TRUNC": lambda args: exp.DateTrunc( 309 unit=exp.Literal.string(str(seq_get(args, 1))), 310 this=seq_get(args, 0), 311 ), 312 "DATETIME_ADD": parse_date_delta_with_interval(exp.DatetimeAdd), 313 "DATETIME_SUB": parse_date_delta_with_interval(exp.DatetimeSub), 314 "DIV": binary_from_function(exp.IntDiv), 315 "GENERATE_ARRAY": exp.GenerateSeries.from_arg_list, 316 "MD5": exp.MD5Digest.from_arg_list, 317 "TO_HEX": _parse_to_hex, 318 "PARSE_DATE": lambda args: format_time_lambda(exp.StrToDate, "bigquery")( 319 [seq_get(args, 1), seq_get(args, 0)] 320 ), 321 "PARSE_TIMESTAMP": _parse_timestamp, 322 "REGEXP_CONTAINS": exp.RegexpLike.from_arg_list, 323 "REGEXP_EXTRACT": lambda args: exp.RegexpExtract( 324 this=seq_get(args, 0), 325 expression=seq_get(args, 1), 326 position=seq_get(args, 2), 327 occurrence=seq_get(args, 3), 328 group=exp.Literal.number(1) if re.compile(args[1].name).groups == 1 else None, 329 ), 330 "SHA256": lambda args: exp.SHA2(this=seq_get(args, 0), length=exp.Literal.number(256)), 331 "SHA512": lambda args: exp.SHA2(this=seq_get(args, 0), length=exp.Literal.number(512)), 332 "SPLIT": lambda args: exp.Split( 333 # https://cloud.google.com/bigquery/docs/reference/standard-sql/string_functions#split 334 this=seq_get(args, 0), 335 expression=seq_get(args, 1) or exp.Literal.string(","), 336 ), 337 "TIME_ADD": parse_date_delta_with_interval(exp.TimeAdd), 338 "TIME_SUB": parse_date_delta_with_interval(exp.TimeSub), 339 "TIMESTAMP_ADD": parse_date_delta_with_interval(exp.TimestampAdd), 340 "TIMESTAMP_SUB": parse_date_delta_with_interval(exp.TimestampSub), 341 "TO_JSON_STRING": exp.JSONFormat.from_arg_list, 342 } 343 344 FUNCTION_PARSERS = { 345 **parser.Parser.FUNCTION_PARSERS, 346 "ARRAY": lambda self: self.expression(exp.Array, expressions=[self._parse_statement()]), 347 } 348 FUNCTION_PARSERS.pop("TRIM") 349 350 NO_PAREN_FUNCTIONS = { 351 **parser.Parser.NO_PAREN_FUNCTIONS, 352 TokenType.CURRENT_DATETIME: exp.CurrentDatetime, 353 } 354 355 NESTED_TYPE_TOKENS = { 356 *parser.Parser.NESTED_TYPE_TOKENS, 357 TokenType.TABLE, 358 } 359 360 ID_VAR_TOKENS = { 361 *parser.Parser.ID_VAR_TOKENS, 362 TokenType.VALUES, 363 } 364 365 PROPERTY_PARSERS = { 366 **parser.Parser.PROPERTY_PARSERS, 367 "NOT DETERMINISTIC": lambda self: self.expression( 368 exp.StabilityProperty, this=exp.Literal.string("VOLATILE") 369 ), 370 "OPTIONS": lambda self: self._parse_with_property(), 371 } 372 373 CONSTRAINT_PARSERS = { 374 **parser.Parser.CONSTRAINT_PARSERS, 375 "OPTIONS": lambda self: exp.Properties(expressions=self._parse_with_property()), 376 } 377 378 RANGE_PARSERS = parser.Parser.RANGE_PARSERS.copy() 379 RANGE_PARSERS.pop(TokenType.OVERLAPS, None) 380 381 NULL_TOKENS = {TokenType.NULL, TokenType.UNKNOWN} 382 383 STATEMENT_PARSERS = { 384 **parser.Parser.STATEMENT_PARSERS, 385 TokenType.END: lambda self: self._parse_as_command(self._prev), 386 TokenType.FOR: lambda self: self._parse_for_in(), 387 } 388 389 def _parse_for_in(self) -> exp.ForIn: 390 this = self._parse_range() 391 self._match_text_seq("DO") 392 return self.expression(exp.ForIn, this=this, expression=self._parse_statement()) 393 394 def _parse_table_part(self, schema: bool = False) -> t.Optional[exp.Expression]: 395 this = super()._parse_table_part(schema=schema) or self._parse_number() 396 397 # https://cloud.google.com/bigquery/docs/reference/standard-sql/lexical#table_names 398 if isinstance(this, exp.Identifier): 399 table_name = this.name 400 while self._match(TokenType.DASH, advance=False) and self._next: 401 self._advance(2) 402 table_name += f"-{self._prev.text}" 403 404 this = exp.Identifier(this=table_name, quoted=this.args.get("quoted")) 405 elif isinstance(this, exp.Literal): 406 table_name = this.name 407 408 if ( 409 self._curr 410 and self._prev.end == self._curr.start - 1 411 and self._parse_var(any_token=True) 412 ): 413 table_name += self._prev.text 414 415 this = exp.Identifier(this=table_name, quoted=True) 416 417 return this 418 419 def _parse_table_parts(self, schema: bool = False) -> exp.Table: 420 table = super()._parse_table_parts(schema=schema) 421 if isinstance(table.this, exp.Identifier) and "." in table.name: 422 catalog, db, this, *rest = ( 423 t.cast(t.Optional[exp.Expression], exp.to_identifier(x)) 424 for x in split_num_words(table.name, ".", 3) 425 ) 426 427 if rest and this: 428 this = exp.Dot.build(t.cast(t.List[exp.Expression], [this, *rest])) 429 430 table = exp.Table(this=this, db=db, catalog=catalog) 431 432 return table 433 434 def _parse_json_object(self) -> exp.JSONObject: 435 json_object = super()._parse_json_object() 436 array_kv_pair = seq_get(json_object.expressions, 0) 437 438 # Converts BQ's "signature 2" of JSON_OBJECT into SQLGlot's canonical representation 439 # https://cloud.google.com/bigquery/docs/reference/standard-sql/json_functions#json_object_signature2 440 if ( 441 array_kv_pair 442 and isinstance(array_kv_pair.this, exp.Array) 443 and isinstance(array_kv_pair.expression, exp.Array) 444 ): 445 keys = array_kv_pair.this.expressions 446 values = array_kv_pair.expression.expressions 447 448 json_object.set( 449 "expressions", 450 [exp.JSONKeyValue(this=k, expression=v) for k, v in zip(keys, values)], 451 ) 452 453 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'>>, 'ARRAY_UNIQUE_AGG': <bound method Func.from_arg_list of <class 'sqlglot.expressions.ArrayUniqueAgg'>>, 'AVG': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Avg'>>, 'CASE': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Case'>>, 'CAST': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Cast'>>, 'CAST_TO_STR_TYPE': <bound method Func.from_arg_list of <class 'sqlglot.expressions.CastToStrType'>>, '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'>>, '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_DIFF': <bound method Func.from_arg_list of <class 'sqlglot.expressions.TsOrDsDiff'>>, 'TS_OR_DS_TO_DATE': <bound method Func.from_arg_list of <class 'sqlglot.expressions.TsOrDsToDate'>>, 'TS_OR_DS_TO_DATE_STR': <function Parser.<lambda>>, '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.LOWCARDINALITY: 'LOWCARDINALITY'>, <TokenType.NESTED: 'NESTED'>, <TokenType.STRUCT: 'STRUCT'>, <TokenType.MAP: 'MAP'>, <TokenType.ARRAY: 'ARRAY'>, <TokenType.TABLE: 'TABLE'>, <TokenType.NULLABLE: 'NULLABLE'>}
ID_VAR_TOKENS =
{<TokenType.TSMULTIRANGE: 'TSMULTIRANGE'>, <TokenType.DATE: 'DATE'>, <TokenType.APPLY: 'APPLY'>, <TokenType.PERCENT: 'PERCENT'>, <TokenType.INDEX: 'INDEX'>, <TokenType.IPADDRESS: 'IPADDRESS'>, <TokenType.UNKNOWN: 'UNKNOWN'>, <TokenType.NULLABLE: 'NULLABLE'>, <TokenType.EXISTS: 'EXISTS'>, <TokenType.DOUBLE: 'DOUBLE'>, <TokenType.RANGE: 'RANGE'>, <TokenType.NATURAL: 'NATURAL'>, <TokenType.FOREIGN_KEY: 'FOREIGN_KEY'>, <TokenType.CURRENT_DATE: 'CURRENT_DATE'>, <TokenType.DICTIONARY: 'DICTIONARY'>, <TokenType.TIME: 'TIME'>, <TokenType.DATETIME64: 'DATETIME64'>, <TokenType.ROW: 'ROW'>, <TokenType.ROWVERSION: 'ROWVERSION'>, <TokenType.ANY: 'ANY'>, <TokenType.FIXEDSTRING: 'FIXEDSTRING'>, <TokenType.IS: 'IS'>, <TokenType.PARTITION: 'PARTITION'>, <TokenType.NEXT: 'NEXT'>, <TokenType.GEOGRAPHY: 'GEOGRAPHY'>, <TokenType.SHOW: 'SHOW'>, <TokenType.CACHE: 'CACHE'>, <TokenType.INT4MULTIRANGE: 'INT4MULTIRANGE'>, <TokenType.OVERWRITE: 'OVERWRITE'>, <TokenType.EXECUTE: 'EXECUTE'>, <TokenType.HLLSKETCH: 'HLLSKETCH'>, <TokenType.TEXT: 'TEXT'>, <TokenType.FORMAT: 'FORMAT'>, <TokenType.UPDATE: 'UPDATE'>, <TokenType.UDECIMAL: 'UDECIMAL'>, <TokenType.DATABASE: 'DATABASE'>, <TokenType.UNPIVOT: 'UNPIVOT'>, <TokenType.CASE: 'CASE'>, <TokenType.ANTI: 'ANTI'>, <TokenType.MEDIUMINT: 'MEDIUMINT'>, <TokenType.REFERENCES: 'REFERENCES'>, <TokenType.KILL: 'KILL'>, <TokenType.INT4RANGE: 'INT4RANGE'>, <TokenType.UBIGINT: 'UBIGINT'>, <TokenType.NCHAR: 'NCHAR'>, <TokenType.USERDEFINED: 'USERDEFINED'>, <TokenType.NULL: 'NULL'>, <TokenType.SET: 'SET'>, <TokenType.COMMIT: 'COMMIT'>, <TokenType.OBJECT: 'OBJECT'>, <TokenType.CURRENT_DATETIME: 'CURRENT_DATETIME'>, <TokenType.KEEP: 'KEEP'>, <TokenType.FILTER: 'FILTER'>, <TokenType.TABLE: 'TABLE'>, <TokenType.UINT128: 'UINT128'>, <TokenType.BOOLEAN: 'BOOLEAN'>, <TokenType.TIMESTAMPLTZ: 'TIMESTAMPLTZ'>, <TokenType.TIMESTAMPTZ: 'TIMESTAMPTZ'>, <TokenType.USMALLINT: 'USMALLINT'>, <TokenType.BINARY: 'BINARY'>, <TokenType.TSTZRANGE: 'TSTZRANGE'>, <TokenType.FUNCTION: 'FUNCTION'>, <TokenType.FALSE: 'FALSE'>, <TokenType.DESC: 'DESC'>, <TokenType.LOWCARDINALITY: 'LOWCARDINALITY'>, <TokenType.OVERLAPS: 'OVERLAPS'>, <TokenType.ESCAPE: 'ESCAPE'>, <TokenType.ASC: 'ASC'>, <TokenType.UTINYINT: 'UTINYINT'>, <TokenType.TOP: 'TOP'>, <TokenType.BIGINT: 'BIGINT'>, <TokenType.SMALLSERIAL: 'SMALLSERIAL'>, <TokenType.FIRST: 'FIRST'>, <TokenType.PRAGMA: 'PRAGMA'>, <TokenType.INT128: 'INT128'>, <TokenType.VARCHAR: 'VARCHAR'>, <TokenType.DECIMAL: 'DECIMAL'>, <TokenType.CONSTRAINT: 'CONSTRAINT'>, <TokenType.TIMETZ: 'TIMETZ'>, <TokenType.END: 'END'>, <TokenType.LONGBLOB: 'LONGBLOB'>, <TokenType.NUMRANGE: 'NUMRANGE'>, <TokenType.CURRENT_USER: 'CURRENT_USER'>, <TokenType.ROWS: 'ROWS'>, <TokenType.CURRENT_TIMESTAMP: 'CURRENT_TIMESTAMP'>, <TokenType.FLOAT: 'FLOAT'>, <TokenType.TSTZMULTIRANGE: 'TSTZMULTIRANGE'>, <TokenType.MAP: 'MAP'>, <TokenType.UNIQUEIDENTIFIER: 'UNIQUEIDENTIFIER'>, <TokenType.MEDIUMBLOB: 'MEDIUMBLOB'>, <TokenType.DATERANGE: 'DATERANGE'>, <TokenType.VIEW: 'VIEW'>, <TokenType.FULL: 'FULL'>, <TokenType.CURRENT_TIME: 'CURRENT_TIME'>, <TokenType.BEGIN: 'BEGIN'>, <TokenType.DATEMULTIRANGE: 'DATEMULTIRANGE'>, <TokenType.MEDIUMTEXT: 'MEDIUMTEXT'>, <TokenType.ENUM16: 'ENUM16'>, <TokenType.DELETE: 'DELETE'>, <TokenType.TINYTEXT: 'TINYTEXT'>, <TokenType.INT: 'INT'>, <TokenType.RIGHT: 'RIGHT'>, <TokenType.INT256: 'INT256'>, <TokenType.COLUMN: 'COLUMN'>, <TokenType.SERIAL: 'SERIAL'>, <TokenType.OFFSET: 'OFFSET'>, <TokenType.DESCRIBE: 'DESCRIBE'>, <TokenType.VAR: 'VAR'>, <TokenType.TIMESTAMP_S: 'TIMESTAMP_S'>, <TokenType.COMMENT: 'COMMENT'>, <TokenType.JSON: 'JSON'>, <TokenType.YEAR: 'YEAR'>, <TokenType.WINDOW: 'WINDOW'>, <TokenType.TIMESTAMP: 'TIMESTAMP'>, <TokenType.TIMESTAMP_MS: 'TIMESTAMP_MS'>, <TokenType.TSRANGE: 'TSRANGE'>, <TokenType.SEMI: 'SEMI'>, <TokenType.VARIANT: 'VARIANT'>, <TokenType.IPPREFIX: 'IPPREFIX'>, <TokenType.BIGSERIAL: 'BIGSERIAL'>, <TokenType.MONEY: 'MONEY'>, <TokenType.LONGTEXT: 'LONGTEXT'>, <TokenType.DIV: 'DIV'>, <TokenType.AUTO_INCREMENT: 'AUTO_INCREMENT'>, <TokenType.RECURSIVE: 'RECURSIVE'>, <TokenType.PROCEDURE: 'PROCEDURE'>, <TokenType.BIGDECIMAL: 'BIGDECIMAL'>, <TokenType.ENUM: 'ENUM'>, <TokenType.LEFT: 'LEFT'>, <TokenType.ISNULL: 'ISNULL'>, <TokenType.REFRESH: 'REFRESH'>, <TokenType.INTERVAL: 'INTERVAL'>, <TokenType.ENUM8: 'ENUM8'>, <TokenType.INET: 'INET'>, <TokenType.UMEDIUMINT: 'UMEDIUMINT'>, <TokenType.SUPER: 'SUPER'>, <TokenType.BIT: 'BIT'>, <TokenType.SCHEMA: 'SCHEMA'>, <TokenType.IMAGE: 'IMAGE'>, <TokenType.INT8MULTIRANGE: 'INT8MULTIRANGE'>, <TokenType.COMMAND: 'COMMAND'>, <TokenType.NUMMULTIRANGE: 'NUMMULTIRANGE'>, <TokenType.SMALLMONEY: 'SMALLMONEY'>, <TokenType.OBJECT_IDENTIFIER: 'OBJECT_IDENTIFIER'>, <TokenType.UNIQUE: 'UNIQUE'>, <TokenType.TINYINT: 'TINYINT'>, <TokenType.PSEUDO_TYPE: 'PSEUDO_TYPE'>, <TokenType.USE: 'USE'>, <TokenType.MERGE: 'MERGE'>, <TokenType.UINT256: 'UINT256'>, <TokenType.NVARCHAR: 'NVARCHAR'>, <TokenType.PIVOT: 'PIVOT'>, <TokenType.TRUE: 'TRUE'>, <TokenType.STRUCT: 'STRUCT'>, <TokenType.HSTORE: 'HSTORE'>, <TokenType.MODEL: 'MODEL'>, <TokenType.SETTINGS: 'SETTINGS'>, <TokenType.INT8RANGE: 'INT8RANGE'>, <TokenType.VOLATILE: 'VOLATILE'>, <TokenType.GEOMETRY: 'GEOMETRY'>, <TokenType.UUID: 'UUID'>, <TokenType.COLLATE: 'COLLATE'>, <TokenType.JSONB: 'JSONB'>, <TokenType.CHAR: 'CHAR'>, <TokenType.SOME: 'SOME'>, <TokenType.TIMESTAMP_NS: 'TIMESTAMP_NS'>, <TokenType.DEFAULT: 'DEFAULT'>, <TokenType.VARBINARY: 'VARBINARY'>, <TokenType.UINT: 'UINT'>, <TokenType.XML: 'XML'>, <TokenType.ALL: 'ALL'>, <TokenType.ARRAY: 'ARRAY'>, <TokenType.TINYBLOB: 'TINYBLOB'>, <TokenType.VALUES: 'VALUES'>, <TokenType.ORDINALITY: 'ORDINALITY'>, <TokenType.NESTED: 'NESTED'>, <TokenType.SMALLINT: 'SMALLINT'>, <TokenType.DATETIME: 'DATETIME'>, <TokenType.LOAD: 'LOAD'>, <TokenType.TEMPORARY: 'TEMPORARY'>}
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.TSMULTIRANGE: 'TSMULTIRANGE'>, <TokenType.DATE: 'DATE'>, <TokenType.PERCENT: 'PERCENT'>, <TokenType.INDEX: 'INDEX'>, <TokenType.IPADDRESS: 'IPADDRESS'>, <TokenType.UNKNOWN: 'UNKNOWN'>, <TokenType.NULLABLE: 'NULLABLE'>, <TokenType.EXISTS: 'EXISTS'>, <TokenType.DOUBLE: 'DOUBLE'>, <TokenType.RANGE: 'RANGE'>, <TokenType.FOREIGN_KEY: 'FOREIGN_KEY'>, <TokenType.CURRENT_DATE: 'CURRENT_DATE'>, <TokenType.DICTIONARY: 'DICTIONARY'>, <TokenType.TIME: 'TIME'>, <TokenType.DATETIME64: 'DATETIME64'>, <TokenType.ROW: 'ROW'>, <TokenType.ROWVERSION: 'ROWVERSION'>, <TokenType.ANY: 'ANY'>, <TokenType.FIXEDSTRING: 'FIXEDSTRING'>, <TokenType.IS: 'IS'>, <TokenType.PARTITION: 'PARTITION'>, <TokenType.NEXT: 'NEXT'>, <TokenType.GEOGRAPHY: 'GEOGRAPHY'>, <TokenType.SHOW: 'SHOW'>, <TokenType.CACHE: 'CACHE'>, <TokenType.INT4MULTIRANGE: 'INT4MULTIRANGE'>, <TokenType.OVERWRITE: 'OVERWRITE'>, <TokenType.EXECUTE: 'EXECUTE'>, <TokenType.HLLSKETCH: 'HLLSKETCH'>, <TokenType.TEXT: 'TEXT'>, <TokenType.FORMAT: 'FORMAT'>, <TokenType.UPDATE: 'UPDATE'>, <TokenType.UDECIMAL: 'UDECIMAL'>, <TokenType.DATABASE: 'DATABASE'>, <TokenType.UNPIVOT: 'UNPIVOT'>, <TokenType.CASE: 'CASE'>, <TokenType.ANTI: 'ANTI'>, <TokenType.MEDIUMINT: 'MEDIUMINT'>, <TokenType.REFERENCES: 'REFERENCES'>, <TokenType.KILL: 'KILL'>, <TokenType.INT4RANGE: 'INT4RANGE'>, <TokenType.UBIGINT: 'UBIGINT'>, <TokenType.NCHAR: 'NCHAR'>, <TokenType.USERDEFINED: 'USERDEFINED'>, <TokenType.NULL: 'NULL'>, <TokenType.SET: 'SET'>, <TokenType.COMMIT: 'COMMIT'>, <TokenType.OBJECT: 'OBJECT'>, <TokenType.CURRENT_DATETIME: 'CURRENT_DATETIME'>, <TokenType.KEEP: 'KEEP'>, <TokenType.FILTER: 'FILTER'>, <TokenType.TABLE: 'TABLE'>, <TokenType.UINT128: 'UINT128'>, <TokenType.BOOLEAN: 'BOOLEAN'>, <TokenType.TIMESTAMPLTZ: 'TIMESTAMPLTZ'>, <TokenType.TIMESTAMPTZ: 'TIMESTAMPTZ'>, <TokenType.USMALLINT: 'USMALLINT'>, <TokenType.BINARY: 'BINARY'>, <TokenType.TSTZRANGE: 'TSTZRANGE'>, <TokenType.FUNCTION: 'FUNCTION'>, <TokenType.FALSE: 'FALSE'>, <TokenType.DESC: 'DESC'>, <TokenType.LOWCARDINALITY: 'LOWCARDINALITY'>, <TokenType.OVERLAPS: 'OVERLAPS'>, <TokenType.ESCAPE: 'ESCAPE'>, <TokenType.ASC: 'ASC'>, <TokenType.UTINYINT: 'UTINYINT'>, <TokenType.TOP: 'TOP'>, <TokenType.BIGINT: 'BIGINT'>, <TokenType.SMALLSERIAL: 'SMALLSERIAL'>, <TokenType.FIRST: 'FIRST'>, <TokenType.PRAGMA: 'PRAGMA'>, <TokenType.INT128: 'INT128'>, <TokenType.VARCHAR: 'VARCHAR'>, <TokenType.DECIMAL: 'DECIMAL'>, <TokenType.CONSTRAINT: 'CONSTRAINT'>, <TokenType.TIMETZ: 'TIMETZ'>, <TokenType.END: 'END'>, <TokenType.LONGBLOB: 'LONGBLOB'>, <TokenType.NUMRANGE: 'NUMRANGE'>, <TokenType.CURRENT_USER: 'CURRENT_USER'>, <TokenType.ROWS: 'ROWS'>, <TokenType.CURRENT_TIMESTAMP: 'CURRENT_TIMESTAMP'>, <TokenType.FLOAT: 'FLOAT'>, <TokenType.TSTZMULTIRANGE: 'TSTZMULTIRANGE'>, <TokenType.MAP: 'MAP'>, <TokenType.UNIQUEIDENTIFIER: 'UNIQUEIDENTIFIER'>, <TokenType.MEDIUMBLOB: 'MEDIUMBLOB'>, <TokenType.DATERANGE: 'DATERANGE'>, <TokenType.VIEW: 'VIEW'>, <TokenType.CURRENT_TIME: 'CURRENT_TIME'>, <TokenType.BEGIN: 'BEGIN'>, <TokenType.DATEMULTIRANGE: 'DATEMULTIRANGE'>, <TokenType.MEDIUMTEXT: 'MEDIUMTEXT'>, <TokenType.ENUM16: 'ENUM16'>, <TokenType.DELETE: 'DELETE'>, <TokenType.TINYTEXT: 'TINYTEXT'>, <TokenType.INT: 'INT'>, <TokenType.INT256: 'INT256'>, <TokenType.COLUMN: 'COLUMN'>, <TokenType.SERIAL: 'SERIAL'>, <TokenType.DESCRIBE: 'DESCRIBE'>, <TokenType.VAR: 'VAR'>, <TokenType.TIMESTAMP_S: 'TIMESTAMP_S'>, <TokenType.COMMENT: 'COMMENT'>, <TokenType.JSON: 'JSON'>, <TokenType.YEAR: 'YEAR'>, <TokenType.TIMESTAMP: 'TIMESTAMP'>, <TokenType.TIMESTAMP_MS: 'TIMESTAMP_MS'>, <TokenType.TSRANGE: 'TSRANGE'>, <TokenType.SEMI: 'SEMI'>, <TokenType.VARIANT: 'VARIANT'>, <TokenType.IPPREFIX: 'IPPREFIX'>, <TokenType.BIGSERIAL: 'BIGSERIAL'>, <TokenType.MONEY: 'MONEY'>, <TokenType.LONGTEXT: 'LONGTEXT'>, <TokenType.DIV: 'DIV'>, <TokenType.AUTO_INCREMENT: 'AUTO_INCREMENT'>, <TokenType.RECURSIVE: 'RECURSIVE'>, <TokenType.PROCEDURE: 'PROCEDURE'>, <TokenType.BIGDECIMAL: 'BIGDECIMAL'>, <TokenType.ENUM: 'ENUM'>, <TokenType.ISNULL: 'ISNULL'>, <TokenType.REFRESH: 'REFRESH'>, <TokenType.INTERVAL: 'INTERVAL'>, <TokenType.ENUM8: 'ENUM8'>, <TokenType.INET: 'INET'>, <TokenType.UMEDIUMINT: 'UMEDIUMINT'>, <TokenType.SUPER: 'SUPER'>, <TokenType.BIT: 'BIT'>, <TokenType.SCHEMA: 'SCHEMA'>, <TokenType.IMAGE: 'IMAGE'>, <TokenType.INT8MULTIRANGE: 'INT8MULTIRANGE'>, <TokenType.COMMAND: 'COMMAND'>, <TokenType.NUMMULTIRANGE: 'NUMMULTIRANGE'>, <TokenType.SMALLMONEY: 'SMALLMONEY'>, <TokenType.OBJECT_IDENTIFIER: 'OBJECT_IDENTIFIER'>, <TokenType.UNIQUE: 'UNIQUE'>, <TokenType.TINYINT: 'TINYINT'>, <TokenType.PSEUDO_TYPE: 'PSEUDO_TYPE'>, <TokenType.USE: 'USE'>, <TokenType.MERGE: 'MERGE'>, <TokenType.UINT256: 'UINT256'>, <TokenType.NVARCHAR: 'NVARCHAR'>, <TokenType.PIVOT: 'PIVOT'>, <TokenType.TRUE: 'TRUE'>, <TokenType.STRUCT: 'STRUCT'>, <TokenType.HSTORE: 'HSTORE'>, <TokenType.MODEL: 'MODEL'>, <TokenType.SETTINGS: 'SETTINGS'>, <TokenType.INT8RANGE: 'INT8RANGE'>, <TokenType.VOLATILE: 'VOLATILE'>, <TokenType.GEOMETRY: 'GEOMETRY'>, <TokenType.UUID: 'UUID'>, <TokenType.COLLATE: 'COLLATE'>, <TokenType.JSONB: 'JSONB'>, <TokenType.CHAR: 'CHAR'>, <TokenType.SOME: 'SOME'>, <TokenType.TIMESTAMP_NS: 'TIMESTAMP_NS'>, <TokenType.DEFAULT: 'DEFAULT'>, <TokenType.VARBINARY: 'VARBINARY'>, <TokenType.UINT: 'UINT'>, <TokenType.XML: 'XML'>, <TokenType.ALL: 'ALL'>, <TokenType.ARRAY: 'ARRAY'>, <TokenType.TINYBLOB: 'TINYBLOB'>, <TokenType.ORDINALITY: 'ORDINALITY'>, <TokenType.NESTED: 'NESTED'>, <TokenType.SMALLINT: 'SMALLINT'>, <TokenType.DATETIME: 'DATETIME'>, <TokenType.LOAD: 'LOAD'>, <TokenType.TEMPORARY: 'TEMPORARY'>}
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
455 class Generator(generator.Generator): 456 EXPLICIT_UNION = True 457 INTERVAL_ALLOWS_PLURAL_FORM = False 458 JOIN_HINTS = False 459 QUERY_HINTS = False 460 TABLE_HINTS = False 461 LIMIT_FETCH = "LIMIT" 462 RENAME_TABLE_WITH_DB = False 463 NVL2_SUPPORTED = False 464 UNNEST_WITH_ORDINALITY = False 465 COLLATE_IS_FUNC = True 466 LIMIT_ONLY_LITERALS = True 467 468 TRANSFORMS = { 469 **generator.Generator.TRANSFORMS, 470 exp.ApproxDistinct: rename_func("APPROX_COUNT_DISTINCT"), 471 exp.ArgMax: arg_max_or_min_no_count("MAX_BY"), 472 exp.ArgMin: arg_max_or_min_no_count("MIN_BY"), 473 exp.ArrayContains: _array_contains_sql, 474 exp.ArraySize: rename_func("ARRAY_LENGTH"), 475 exp.Cast: transforms.preprocess([transforms.remove_precision_parameterized_types]), 476 exp.CollateProperty: lambda self, e: f"DEFAULT COLLATE {self.sql(e, 'this')}" 477 if e.args.get("default") 478 else f"COLLATE {self.sql(e, 'this')}", 479 exp.Create: _create_sql, 480 exp.CTE: transforms.preprocess([_pushdown_cte_column_names]), 481 exp.DateAdd: date_add_interval_sql("DATE", "ADD"), 482 exp.DateDiff: lambda self, e: f"DATE_DIFF({self.sql(e, 'this')}, {self.sql(e, 'expression')}, {self.sql(e.args.get('unit', 'DAY'))})", 483 exp.DateFromParts: rename_func("DATE"), 484 exp.DateStrToDate: datestrtodate_sql, 485 exp.DateSub: date_add_interval_sql("DATE", "SUB"), 486 exp.DatetimeAdd: date_add_interval_sql("DATETIME", "ADD"), 487 exp.DatetimeSub: date_add_interval_sql("DATETIME", "SUB"), 488 exp.DateTrunc: lambda self, e: self.func("DATE_TRUNC", e.this, e.text("unit")), 489 exp.GenerateSeries: rename_func("GENERATE_ARRAY"), 490 exp.GroupConcat: rename_func("STRING_AGG"), 491 exp.Hex: rename_func("TO_HEX"), 492 exp.If: if_sql(false_value="NULL"), 493 exp.ILike: no_ilike_sql, 494 exp.IntDiv: rename_func("DIV"), 495 exp.JSONFormat: rename_func("TO_JSON_STRING"), 496 exp.JSONKeyValue: json_keyvalue_comma_sql, 497 exp.Max: max_or_greatest, 498 exp.MD5: lambda self, e: self.func("TO_HEX", self.func("MD5", e.this)), 499 exp.MD5Digest: rename_func("MD5"), 500 exp.Min: min_or_least, 501 exp.PartitionedByProperty: lambda self, e: f"PARTITION BY {self.sql(e, 'this')}", 502 exp.RegexpExtract: lambda self, e: self.func( 503 "REGEXP_EXTRACT", 504 e.this, 505 e.expression, 506 e.args.get("position"), 507 e.args.get("occurrence"), 508 ), 509 exp.RegexpReplace: regexp_replace_sql, 510 exp.RegexpLike: rename_func("REGEXP_CONTAINS"), 511 exp.ReturnsProperty: _returnsproperty_sql, 512 exp.Select: transforms.preprocess( 513 [ 514 transforms.explode_to_unnest(), 515 _unqualify_unnest, 516 transforms.eliminate_distinct_on, 517 _alias_ordered_group, 518 transforms.eliminate_semi_and_anti_joins, 519 ] 520 ), 521 exp.SHA2: lambda self, e: self.func( 522 f"SHA256" if e.text("length") == "256" else "SHA512", e.this 523 ), 524 exp.StabilityProperty: lambda self, e: f"DETERMINISTIC" 525 if e.name == "IMMUTABLE" 526 else "NOT DETERMINISTIC", 527 exp.StrToDate: lambda self, e: f"PARSE_DATE({self.format_time(e)}, {self.sql(e, 'this')})", 528 exp.StrToTime: lambda self, e: self.func( 529 "PARSE_TIMESTAMP", self.format_time(e), e.this, e.args.get("zone") 530 ), 531 exp.TimeAdd: date_add_interval_sql("TIME", "ADD"), 532 exp.TimeSub: date_add_interval_sql("TIME", "SUB"), 533 exp.TimestampAdd: date_add_interval_sql("TIMESTAMP", "ADD"), 534 exp.TimestampSub: date_add_interval_sql("TIMESTAMP", "SUB"), 535 exp.TimeStrToTime: timestrtotime_sql, 536 exp.TimeToStr: lambda self, e: f"FORMAT_DATE({self.format_time(e)}, {self.sql(e, 'this')})", 537 exp.Trim: lambda self, e: self.func(f"TRIM", e.this, e.expression), 538 exp.TsOrDsAdd: _ts_or_ds_add_sql, 539 exp.TsOrDsDiff: _ts_or_ds_diff_sql, 540 exp.TsOrDsToDate: ts_or_ds_to_date_sql("bigquery"), 541 exp.Unhex: rename_func("FROM_HEX"), 542 exp.Values: _derived_table_values_to_unnest, 543 exp.VariancePop: rename_func("VAR_POP"), 544 } 545 546 TYPE_MAPPING = { 547 **generator.Generator.TYPE_MAPPING, 548 exp.DataType.Type.BIGDECIMAL: "BIGNUMERIC", 549 exp.DataType.Type.BIGINT: "INT64", 550 exp.DataType.Type.BINARY: "BYTES", 551 exp.DataType.Type.BOOLEAN: "BOOL", 552 exp.DataType.Type.CHAR: "STRING", 553 exp.DataType.Type.DECIMAL: "NUMERIC", 554 exp.DataType.Type.DOUBLE: "FLOAT64", 555 exp.DataType.Type.FLOAT: "FLOAT64", 556 exp.DataType.Type.INT: "INT64", 557 exp.DataType.Type.NCHAR: "STRING", 558 exp.DataType.Type.NVARCHAR: "STRING", 559 exp.DataType.Type.SMALLINT: "INT64", 560 exp.DataType.Type.TEXT: "STRING", 561 exp.DataType.Type.TIMESTAMP: "DATETIME", 562 exp.DataType.Type.TIMESTAMPTZ: "TIMESTAMP", 563 exp.DataType.Type.TIMESTAMPLTZ: "TIMESTAMP", 564 exp.DataType.Type.TINYINT: "INT64", 565 exp.DataType.Type.VARBINARY: "BYTES", 566 exp.DataType.Type.VARCHAR: "STRING", 567 exp.DataType.Type.VARIANT: "ANY TYPE", 568 } 569 570 PROPERTIES_LOCATION = { 571 **generator.Generator.PROPERTIES_LOCATION, 572 exp.PartitionedByProperty: exp.Properties.Location.POST_SCHEMA, 573 exp.VolatileProperty: exp.Properties.Location.UNSUPPORTED, 574 } 575 576 # from: https://cloud.google.com/bigquery/docs/reference/standard-sql/lexical#reserved_keywords 577 RESERVED_KEYWORDS = { 578 *generator.Generator.RESERVED_KEYWORDS, 579 "all", 580 "and", 581 "any", 582 "array", 583 "as", 584 "asc", 585 "assert_rows_modified", 586 "at", 587 "between", 588 "by", 589 "case", 590 "cast", 591 "collate", 592 "contains", 593 "create", 594 "cross", 595 "cube", 596 "current", 597 "default", 598 "define", 599 "desc", 600 "distinct", 601 "else", 602 "end", 603 "enum", 604 "escape", 605 "except", 606 "exclude", 607 "exists", 608 "extract", 609 "false", 610 "fetch", 611 "following", 612 "for", 613 "from", 614 "full", 615 "group", 616 "grouping", 617 "groups", 618 "hash", 619 "having", 620 "if", 621 "ignore", 622 "in", 623 "inner", 624 "intersect", 625 "interval", 626 "into", 627 "is", 628 "join", 629 "lateral", 630 "left", 631 "like", 632 "limit", 633 "lookup", 634 "merge", 635 "natural", 636 "new", 637 "no", 638 "not", 639 "null", 640 "nulls", 641 "of", 642 "on", 643 "or", 644 "order", 645 "outer", 646 "over", 647 "partition", 648 "preceding", 649 "proto", 650 "qualify", 651 "range", 652 "recursive", 653 "respect", 654 "right", 655 "rollup", 656 "rows", 657 "select", 658 "set", 659 "some", 660 "struct", 661 "tablesample", 662 "then", 663 "to", 664 "treat", 665 "true", 666 "unbounded", 667 "union", 668 "unnest", 669 "using", 670 "when", 671 "where", 672 "window", 673 "with", 674 "within", 675 } 676 677 def eq_sql(self, expression: exp.EQ) -> str: 678 # Operands of = cannot be NULL in BigQuery 679 if isinstance(expression.left, exp.Null) or isinstance(expression.right, exp.Null): 680 return "NULL" 681 682 return self.binary(expression, "=") 683 684 def attimezone_sql(self, expression: exp.AtTimeZone) -> str: 685 parent = expression.parent 686 687 # BigQuery allows CAST(.. AS {STRING|TIMESTAMP} [FORMAT <fmt> [AT TIME ZONE <tz>]]). 688 # Only the TIMESTAMP one should use the below conversion, when AT TIME ZONE is included. 689 if not isinstance(parent, exp.Cast) or not parent.to.is_type("text"): 690 return self.func( 691 "TIMESTAMP", self.func("DATETIME", expression.this, expression.args.get("zone")) 692 ) 693 694 return super().attimezone_sql(expression) 695 696 def trycast_sql(self, expression: exp.TryCast) -> str: 697 return self.cast_sql(expression, safe_prefix="SAFE_") 698 699 def cte_sql(self, expression: exp.CTE) -> str: 700 if expression.alias_column_names: 701 self.unsupported("Column names in CTE definition are not supported.") 702 return super().cte_sql(expression) 703 704 def array_sql(self, expression: exp.Array) -> str: 705 first_arg = seq_get(expression.expressions, 0) 706 if isinstance(first_arg, exp.Subqueryable): 707 return f"ARRAY{self.wrap(self.sql(first_arg))}" 708 709 return inline_array_sql(self, expression) 710 711 def transaction_sql(self, *_) -> str: 712 return "BEGIN TRANSACTION" 713 714 def commit_sql(self, *_) -> str: 715 return "COMMIT TRANSACTION" 716 717 def rollback_sql(self, *_) -> str: 718 return "ROLLBACK TRANSACTION" 719 720 def in_unnest_op(self, expression: exp.Unnest) -> str: 721 return self.sql(expression) 722 723 def except_op(self, expression: exp.Except) -> str: 724 if not expression.args.get("distinct", False): 725 self.unsupported("EXCEPT without DISTINCT is not supported in BigQuery") 726 return f"EXCEPT{' DISTINCT' if expression.args.get('distinct') else ' ALL'}" 727 728 def intersect_op(self, expression: exp.Intersect) -> str: 729 if not expression.args.get("distinct", False): 730 self.unsupported("INTERSECT without DISTINCT is not supported in BigQuery") 731 return f"INTERSECT{' DISTINCT' if expression.args.get('distinct') else ' ALL'}" 732 733 def with_properties(self, properties: exp.Properties) -> str: 734 return self.properties(properties, prefix=self.seg("OPTIONS")) 735 736 def version_sql(self, expression: exp.Version) -> str: 737 if expression.name == "TIMESTAMP": 738 expression.set("this", "SYSTEM_TIME") 739 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.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.TimeToStr'>: <function BigQuery.Generator.<lambda>>, <class 'sqlglot.expressions.Trim'>: <function BigQuery.Generator.<lambda>>, <class 'sqlglot.expressions.TsOrDsAdd'>: <function _ts_or_ds_add_sql>, <class 'sqlglot.expressions.TsOrDsDiff'>: <function _ts_or_ds_diff_sql>, <class 'sqlglot.expressions.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 =
{'enum', 'hash', 'following', 'lookup', 'treat', 'unbounded', 'right', 'left', 'where', 'union', 'end', 'inner', 'window', 'merge', 'array', 'any', 'false', 'by', 'then', 'proto', 'for', 'ignore', 'rows', 'grouping', 'assert_rows_modified', 'if', 'current', 'outer', 'qualify', 'intersect', 'within', 'preceding', 'select', 'to', 'define', 'partition', 'default', 'except', 'struct', 'distinct', 'set', 'true', 'like', 'groups', 'at', 'respect', 'from', 'fetch', 'new', 'into', 'using', 'cross', 'having', 'order', 'full', 'null', 'asc', 'between', 'or', 'over', 'tablesample', 'cast', 'create', 'limit', 'of', 'range', 'collate', 'join', 'when', 'escape', 'nulls', 'lateral', 'in', 'interval', 'exists', 'recursive', 'no', 'desc', 'not', 'on', 'exclude', 'all', 'natural', 'cube', 'contains', 'case', 'is', 'with', 'some', 'group', 'and', 'as', 'unnest', 'extract', 'rollup', 'else'}
684 def attimezone_sql(self, expression: exp.AtTimeZone) -> str: 685 parent = expression.parent 686 687 # BigQuery allows CAST(.. AS {STRING|TIMESTAMP} [FORMAT <fmt> [AT TIME ZONE <tz>]]). 688 # Only the TIMESTAMP one should use the below conversion, when AT TIME ZONE is included. 689 if not isinstance(parent, exp.Cast) or not parent.to.is_type("text"): 690 return self.func( 691 "TIMESTAMP", self.func("DATETIME", expression.this, expression.args.get("zone")) 692 ) 693 694 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:
291 @classmethod 292 def can_identify(cls, text: str, identify: str | bool = "safe") -> bool: 293 """Checks if text can be identified given an identify option. 294 295 Args: 296 text: The text to check. 297 identify: 298 "always" or `True`: Always returns true. 299 "safe": True if the identifier is case-insensitive. 300 301 Returns: 302 Whether or not the given text can be identified. 303 """ 304 if identify is True or identify == "always": 305 return True 306 307 if identify == "safe": 308 return not cls.case_sensitive(text) 309 310 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
- 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