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 datestrtodate_sql, 12 format_time_lambda, 13 inline_array_sql, 14 max_or_greatest, 15 min_or_least, 16 no_ilike_sql, 17 parse_date_delta_with_interval, 18 rename_func, 19 timestrtotime_sql, 20 ts_or_ds_to_date_sql, 21) 22from sqlglot.helper import seq_get, split_num_words 23from sqlglot.tokens import TokenType 24 25logger = logging.getLogger("sqlglot") 26 27 28def _date_add_sql( 29 data_type: str, kind: str 30) -> t.Callable[[generator.Generator, exp.Expression], str]: 31 def func(self, expression): 32 this = self.sql(expression, "this") 33 unit = expression.args.get("unit") 34 unit = exp.var(unit.name.upper() if unit else "DAY") 35 interval = exp.Interval(this=expression.expression, unit=unit) 36 return f"{data_type}_{kind}({this}, {self.sql(interval)})" 37 38 return func 39 40 41def _derived_table_values_to_unnest(self: generator.Generator, expression: exp.Values) -> str: 42 if not isinstance(expression.unnest().parent, exp.From): 43 return self.values_sql(expression) 44 45 alias = expression.args.get("alias") 46 47 structs = [ 48 exp.Struct( 49 expressions=[ 50 exp.alias_(value, column_name) 51 for value, column_name in zip( 52 t.expressions, 53 alias.columns 54 if alias and alias.columns 55 else (f"_c{i}" for i in range(len(t.expressions))), 56 ) 57 ] 58 ) 59 for t in expression.find_all(exp.Tuple) 60 ] 61 62 return self.unnest_sql(exp.Unnest(expressions=[exp.Array(expressions=structs)])) 63 64 65def _returnsproperty_sql(self: generator.Generator, expression: exp.ReturnsProperty) -> str: 66 this = expression.this 67 if isinstance(this, exp.Schema): 68 this = f"{this.this} <{self.expressions(this)}>" 69 else: 70 this = self.sql(this) 71 return f"RETURNS {this}" 72 73 74def _create_sql(self: generator.Generator, expression: exp.Create) -> str: 75 kind = expression.args["kind"] 76 returns = expression.find(exp.ReturnsProperty) 77 if kind.upper() == "FUNCTION" and returns and returns.args.get("is_table"): 78 expression = expression.copy() 79 expression.set("kind", "TABLE FUNCTION") 80 if isinstance( 81 expression.expression, 82 ( 83 exp.Subquery, 84 exp.Literal, 85 ), 86 ): 87 expression.set("expression", expression.expression.this) 88 89 return self.create_sql(expression) 90 91 return self.create_sql(expression) 92 93 94def _unqualify_unnest(expression: exp.Expression) -> exp.Expression: 95 """Remove references to unnest table aliases since bigquery doesn't allow them. 96 97 These are added by the optimizer's qualify_column step. 98 """ 99 from sqlglot.optimizer.scope import Scope 100 101 if isinstance(expression, exp.Select): 102 for unnest in expression.find_all(exp.Unnest): 103 if isinstance(unnest.parent, (exp.From, exp.Join)) and unnest.alias: 104 for column in Scope(expression).find_all(exp.Column): 105 if column.table == unnest.alias: 106 column.set("table", None) 107 108 return expression 109 110 111# https://issuetracker.google.com/issues/162294746 112# workaround for bigquery bug when grouping by an expression and then ordering 113# WITH x AS (SELECT 1 y) 114# SELECT y + 1 z 115# FROM x 116# GROUP BY x + 1 117# ORDER by z 118def _alias_ordered_group(expression: exp.Expression) -> exp.Expression: 119 if isinstance(expression, exp.Select): 120 group = expression.args.get("group") 121 order = expression.args.get("order") 122 123 if group and order: 124 aliases = { 125 select.this: select.args["alias"] 126 for select in expression.selects 127 if isinstance(select, exp.Alias) 128 } 129 130 for e in group.expressions: 131 alias = aliases.get(e) 132 133 if alias: 134 e.replace(exp.column(alias)) 135 136 return expression 137 138 139def _pushdown_cte_column_names(expression: exp.Expression) -> exp.Expression: 140 """BigQuery doesn't allow column names when defining a CTE, so we try to push them down.""" 141 if isinstance(expression, exp.CTE) and expression.alias_column_names: 142 cte_query = expression.this 143 144 if cte_query.is_star: 145 logger.warning( 146 "Can't push down CTE column names for star queries. Run the query through" 147 " the optimizer or use 'qualify' to expand the star projections first." 148 ) 149 return expression 150 151 column_names = expression.alias_column_names 152 expression.args["alias"].set("columns", None) 153 154 for name, select in zip(column_names, cte_query.selects): 155 to_replace = select 156 157 if isinstance(select, exp.Alias): 158 select = select.this 159 160 # Inner aliases are shadowed by the CTE column names 161 to_replace.replace(exp.alias_(select, name)) 162 163 return expression 164 165 166def _parse_timestamp(args: t.List) -> exp.StrToTime: 167 this = format_time_lambda(exp.StrToTime, "bigquery")([seq_get(args, 1), seq_get(args, 0)]) 168 this.set("zone", seq_get(args, 2)) 169 return this 170 171 172class BigQuery(Dialect): 173 UNNEST_COLUMN_ONLY = True 174 175 # https://cloud.google.com/bigquery/docs/reference/standard-sql/lexical#case_sensitivity 176 RESOLVES_IDENTIFIERS_AS_UPPERCASE = None 177 178 # bigquery udfs are case sensitive 179 NORMALIZE_FUNCTIONS = False 180 181 TIME_MAPPING = { 182 "%D": "%m/%d/%y", 183 } 184 185 FORMAT_MAPPING = { 186 "DD": "%d", 187 "MM": "%m", 188 "MON": "%b", 189 "MONTH": "%B", 190 "YYYY": "%Y", 191 "YY": "%y", 192 "HH": "%I", 193 "HH12": "%I", 194 "HH24": "%H", 195 "MI": "%M", 196 "SS": "%S", 197 "SSSSS": "%f", 198 "TZH": "%z", 199 } 200 201 @classmethod 202 def normalize_identifier(cls, expression: E) -> E: 203 # In BigQuery, CTEs aren't case-sensitive, but table names are (by default, at least). 204 # The following check is essentially a heuristic to detect tables based on whether or 205 # not they're qualified. 206 if isinstance(expression, exp.Identifier): 207 parent = expression.parent 208 209 while isinstance(parent, exp.Dot): 210 parent = parent.parent 211 212 if ( 213 not isinstance(parent, exp.UserDefinedFunction) 214 and not (isinstance(parent, exp.Table) and parent.db) 215 and not expression.meta.get("is_table") 216 ): 217 expression.set("this", expression.this.lower()) 218 219 return expression 220 221 class Tokenizer(tokens.Tokenizer): 222 QUOTES = ["'", '"', '"""', "'''"] 223 COMMENTS = ["--", "#", ("/*", "*/")] 224 IDENTIFIERS = ["`"] 225 STRING_ESCAPES = ["\\"] 226 227 HEX_STRINGS = [("0x", ""), ("0X", "")] 228 229 BYTE_STRINGS = [ 230 (prefix + q, q) for q in t.cast(t.List[str], QUOTES) for prefix in ("b", "B") 231 ] 232 233 RAW_STRINGS = [ 234 (prefix + q, q) for q in t.cast(t.List[str], QUOTES) for prefix in ("r", "R") 235 ] 236 237 KEYWORDS = { 238 **tokens.Tokenizer.KEYWORDS, 239 "ANY TYPE": TokenType.VARIANT, 240 "BEGIN": TokenType.COMMAND, 241 "BEGIN TRANSACTION": TokenType.BEGIN, 242 "CURRENT_DATETIME": TokenType.CURRENT_DATETIME, 243 "BYTES": TokenType.BINARY, 244 "DECLARE": TokenType.COMMAND, 245 "FLOAT64": TokenType.DOUBLE, 246 "INT64": TokenType.BIGINT, 247 "RECORD": TokenType.STRUCT, 248 "TIMESTAMP": TokenType.TIMESTAMPTZ, 249 "NOT DETERMINISTIC": TokenType.VOLATILE, 250 "UNKNOWN": TokenType.NULL, 251 } 252 KEYWORDS.pop("DIV") 253 254 class Parser(parser.Parser): 255 PREFIXED_PIVOT_COLUMNS = True 256 257 LOG_BASE_FIRST = False 258 LOG_DEFAULTS_TO_LN = True 259 260 FUNCTIONS = { 261 **parser.Parser.FUNCTIONS, 262 "DATE_ADD": parse_date_delta_with_interval(exp.DateAdd), 263 "DATE_SUB": parse_date_delta_with_interval(exp.DateSub), 264 "DATE_TRUNC": lambda args: exp.DateTrunc( 265 unit=exp.Literal.string(str(seq_get(args, 1))), 266 this=seq_get(args, 0), 267 ), 268 "DATETIME_ADD": parse_date_delta_with_interval(exp.DatetimeAdd), 269 "DATETIME_SUB": parse_date_delta_with_interval(exp.DatetimeSub), 270 "DIV": lambda args: exp.IntDiv(this=seq_get(args, 0), expression=seq_get(args, 1)), 271 "GENERATE_ARRAY": exp.GenerateSeries.from_arg_list, 272 "PARSE_DATE": lambda args: format_time_lambda(exp.StrToDate, "bigquery")( 273 [seq_get(args, 1), seq_get(args, 0)] 274 ), 275 "PARSE_TIMESTAMP": _parse_timestamp, 276 "REGEXP_CONTAINS": exp.RegexpLike.from_arg_list, 277 "REGEXP_EXTRACT": lambda args: exp.RegexpExtract( 278 this=seq_get(args, 0), 279 expression=seq_get(args, 1), 280 position=seq_get(args, 2), 281 occurrence=seq_get(args, 3), 282 group=exp.Literal.number(1) 283 if re.compile(str(seq_get(args, 1))).groups == 1 284 else None, 285 ), 286 "SPLIT": lambda args: exp.Split( 287 # https://cloud.google.com/bigquery/docs/reference/standard-sql/string_functions#split 288 this=seq_get(args, 0), 289 expression=seq_get(args, 1) or exp.Literal.string(","), 290 ), 291 "TIME_ADD": parse_date_delta_with_interval(exp.TimeAdd), 292 "TIME_SUB": parse_date_delta_with_interval(exp.TimeSub), 293 "TIMESTAMP_ADD": parse_date_delta_with_interval(exp.TimestampAdd), 294 "TIMESTAMP_SUB": parse_date_delta_with_interval(exp.TimestampSub), 295 "TO_JSON_STRING": exp.JSONFormat.from_arg_list, 296 } 297 298 FUNCTION_PARSERS = { 299 **parser.Parser.FUNCTION_PARSERS, 300 "ARRAY": lambda self: self.expression(exp.Array, expressions=[self._parse_statement()]), 301 } 302 FUNCTION_PARSERS.pop("TRIM") 303 304 NO_PAREN_FUNCTIONS = { 305 **parser.Parser.NO_PAREN_FUNCTIONS, 306 TokenType.CURRENT_DATETIME: exp.CurrentDatetime, 307 } 308 309 NESTED_TYPE_TOKENS = { 310 *parser.Parser.NESTED_TYPE_TOKENS, 311 TokenType.TABLE, 312 } 313 314 ID_VAR_TOKENS = { 315 *parser.Parser.ID_VAR_TOKENS, 316 TokenType.VALUES, 317 } 318 319 PROPERTY_PARSERS = { 320 **parser.Parser.PROPERTY_PARSERS, 321 "NOT DETERMINISTIC": lambda self: self.expression( 322 exp.StabilityProperty, this=exp.Literal.string("VOLATILE") 323 ), 324 "OPTIONS": lambda self: self._parse_with_property(), 325 } 326 327 CONSTRAINT_PARSERS = { 328 **parser.Parser.CONSTRAINT_PARSERS, 329 "OPTIONS": lambda self: exp.Properties(expressions=self._parse_with_property()), 330 } 331 332 def _parse_table_part(self, schema: bool = False) -> t.Optional[exp.Expression]: 333 this = super()._parse_table_part(schema=schema) 334 335 # https://cloud.google.com/bigquery/docs/reference/standard-sql/lexical#table_names 336 if isinstance(this, exp.Identifier): 337 table_name = this.name 338 while self._match(TokenType.DASH, advance=False) and self._next: 339 self._advance(2) 340 table_name += f"-{self._prev.text}" 341 342 this = exp.Identifier(this=table_name, quoted=this.args.get("quoted")) 343 344 return this 345 346 def _parse_table_parts(self, schema: bool = False) -> exp.Table: 347 table = super()._parse_table_parts(schema=schema) 348 if isinstance(table.this, exp.Identifier) and "." in table.name: 349 catalog, db, this, *rest = ( 350 t.cast(t.Optional[exp.Expression], exp.to_identifier(x)) 351 for x in split_num_words(table.name, ".", 3) 352 ) 353 354 if rest and this: 355 this = exp.Dot.build(t.cast(t.List[exp.Expression], [this, *rest])) 356 357 table = exp.Table(this=this, db=db, catalog=catalog) 358 359 return table 360 361 class Generator(generator.Generator): 362 EXPLICIT_UNION = True 363 INTERVAL_ALLOWS_PLURAL_FORM = False 364 JOIN_HINTS = False 365 QUERY_HINTS = False 366 TABLE_HINTS = False 367 LIMIT_FETCH = "LIMIT" 368 RENAME_TABLE_WITH_DB = False 369 ESCAPE_LINE_BREAK = True 370 371 TRANSFORMS = { 372 **generator.Generator.TRANSFORMS, 373 exp.ApproxDistinct: rename_func("APPROX_COUNT_DISTINCT"), 374 exp.ArraySize: rename_func("ARRAY_LENGTH"), 375 exp.Cast: transforms.preprocess([transforms.remove_precision_parameterized_types]), 376 exp.CTE: transforms.preprocess([_pushdown_cte_column_names]), 377 exp.DateAdd: _date_add_sql("DATE", "ADD"), 378 exp.DateSub: _date_add_sql("DATE", "SUB"), 379 exp.DatetimeAdd: _date_add_sql("DATETIME", "ADD"), 380 exp.DatetimeSub: _date_add_sql("DATETIME", "SUB"), 381 exp.DateDiff: lambda self, e: f"DATE_DIFF({self.sql(e, 'this')}, {self.sql(e, 'expression')}, {self.sql(e.args.get('unit', 'DAY'))})", 382 exp.DateStrToDate: datestrtodate_sql, 383 exp.DateTrunc: lambda self, e: self.func("DATE_TRUNC", e.this, e.text("unit")), 384 exp.JSONFormat: rename_func("TO_JSON_STRING"), 385 exp.GenerateSeries: rename_func("GENERATE_ARRAY"), 386 exp.GroupConcat: rename_func("STRING_AGG"), 387 exp.ILike: no_ilike_sql, 388 exp.IntDiv: rename_func("DIV"), 389 exp.Max: max_or_greatest, 390 exp.Min: min_or_least, 391 exp.RegexpExtract: lambda self, e: self.func( 392 "REGEXP_EXTRACT", 393 e.this, 394 e.expression, 395 e.args.get("position"), 396 e.args.get("occurrence"), 397 ), 398 exp.RegexpLike: rename_func("REGEXP_CONTAINS"), 399 exp.Select: transforms.preprocess( 400 [ 401 transforms.explode_to_unnest, 402 _unqualify_unnest, 403 transforms.eliminate_distinct_on, 404 _alias_ordered_group, 405 ] 406 ), 407 exp.StrToDate: lambda self, e: f"PARSE_DATE({self.format_time(e)}, {self.sql(e, 'this')})", 408 exp.StrToTime: lambda self, e: self.func( 409 "PARSE_TIMESTAMP", self.format_time(e), e.this, e.args.get("zone") 410 ), 411 exp.TimeAdd: _date_add_sql("TIME", "ADD"), 412 exp.TimeSub: _date_add_sql("TIME", "SUB"), 413 exp.TimestampAdd: _date_add_sql("TIMESTAMP", "ADD"), 414 exp.TimestampSub: _date_add_sql("TIMESTAMP", "SUB"), 415 exp.TimeStrToTime: timestrtotime_sql, 416 exp.TsOrDsToDate: ts_or_ds_to_date_sql("bigquery"), 417 exp.TsOrDsAdd: _date_add_sql("DATE", "ADD"), 418 exp.PartitionedByProperty: lambda self, e: f"PARTITION BY {self.sql(e, 'this')}", 419 exp.VariancePop: rename_func("VAR_POP"), 420 exp.Values: _derived_table_values_to_unnest, 421 exp.ReturnsProperty: _returnsproperty_sql, 422 exp.Create: _create_sql, 423 exp.Trim: lambda self, e: self.func(f"TRIM", e.this, e.expression), 424 exp.StabilityProperty: lambda self, e: f"DETERMINISTIC" 425 if e.name == "IMMUTABLE" 426 else "NOT DETERMINISTIC", 427 } 428 429 TYPE_MAPPING = { 430 **generator.Generator.TYPE_MAPPING, 431 exp.DataType.Type.BIGDECIMAL: "BIGNUMERIC", 432 exp.DataType.Type.BIGINT: "INT64", 433 exp.DataType.Type.BINARY: "BYTES", 434 exp.DataType.Type.BOOLEAN: "BOOL", 435 exp.DataType.Type.CHAR: "STRING", 436 exp.DataType.Type.DECIMAL: "NUMERIC", 437 exp.DataType.Type.DOUBLE: "FLOAT64", 438 exp.DataType.Type.FLOAT: "FLOAT64", 439 exp.DataType.Type.INT: "INT64", 440 exp.DataType.Type.NCHAR: "STRING", 441 exp.DataType.Type.NVARCHAR: "STRING", 442 exp.DataType.Type.SMALLINT: "INT64", 443 exp.DataType.Type.TEXT: "STRING", 444 exp.DataType.Type.TIMESTAMP: "DATETIME", 445 exp.DataType.Type.TIMESTAMPTZ: "TIMESTAMP", 446 exp.DataType.Type.TIMESTAMPLTZ: "TIMESTAMP", 447 exp.DataType.Type.TINYINT: "INT64", 448 exp.DataType.Type.VARBINARY: "BYTES", 449 exp.DataType.Type.VARCHAR: "STRING", 450 exp.DataType.Type.VARIANT: "ANY TYPE", 451 } 452 453 PROPERTIES_LOCATION = { 454 **generator.Generator.PROPERTIES_LOCATION, 455 exp.PartitionedByProperty: exp.Properties.Location.POST_SCHEMA, 456 exp.VolatileProperty: exp.Properties.Location.UNSUPPORTED, 457 } 458 459 # from: https://cloud.google.com/bigquery/docs/reference/standard-sql/lexical#reserved_keywords 460 RESERVED_KEYWORDS = { 461 *generator.Generator.RESERVED_KEYWORDS, 462 "all", 463 "and", 464 "any", 465 "array", 466 "as", 467 "asc", 468 "assert_rows_modified", 469 "at", 470 "between", 471 "by", 472 "case", 473 "cast", 474 "collate", 475 "contains", 476 "create", 477 "cross", 478 "cube", 479 "current", 480 "default", 481 "define", 482 "desc", 483 "distinct", 484 "else", 485 "end", 486 "enum", 487 "escape", 488 "except", 489 "exclude", 490 "exists", 491 "extract", 492 "false", 493 "fetch", 494 "following", 495 "for", 496 "from", 497 "full", 498 "group", 499 "grouping", 500 "groups", 501 "hash", 502 "having", 503 "if", 504 "ignore", 505 "in", 506 "inner", 507 "intersect", 508 "interval", 509 "into", 510 "is", 511 "join", 512 "lateral", 513 "left", 514 "like", 515 "limit", 516 "lookup", 517 "merge", 518 "natural", 519 "new", 520 "no", 521 "not", 522 "null", 523 "nulls", 524 "of", 525 "on", 526 "or", 527 "order", 528 "outer", 529 "over", 530 "partition", 531 "preceding", 532 "proto", 533 "qualify", 534 "range", 535 "recursive", 536 "respect", 537 "right", 538 "rollup", 539 "rows", 540 "select", 541 "set", 542 "some", 543 "struct", 544 "tablesample", 545 "then", 546 "to", 547 "treat", 548 "true", 549 "unbounded", 550 "union", 551 "unnest", 552 "using", 553 "when", 554 "where", 555 "window", 556 "with", 557 "within", 558 } 559 560 def attimezone_sql(self, expression: exp.AtTimeZone) -> str: 561 parent = expression.parent 562 563 # BigQuery allows CAST(.. AS {STRING|TIMESTAMP} [FORMAT <fmt> [AT TIME ZONE <tz>]]). 564 # Only the TIMESTAMP one should use the below conversion, when AT TIME ZONE is included. 565 if not isinstance(parent, exp.Cast) or not parent.to.is_type("text"): 566 return self.func( 567 "TIMESTAMP", self.func("DATETIME", expression.this, expression.args.get("zone")) 568 ) 569 570 return super().attimezone_sql(expression) 571 572 def trycast_sql(self, expression: exp.TryCast) -> str: 573 return self.cast_sql(expression, safe_prefix="SAFE_") 574 575 def cte_sql(self, expression: exp.CTE) -> str: 576 if expression.alias_column_names: 577 self.unsupported("Column names in CTE definition are not supported.") 578 return super().cte_sql(expression) 579 580 def array_sql(self, expression: exp.Array) -> str: 581 first_arg = seq_get(expression.expressions, 0) 582 if isinstance(first_arg, exp.Subqueryable): 583 return f"ARRAY{self.wrap(self.sql(first_arg))}" 584 585 return inline_array_sql(self, expression) 586 587 def transaction_sql(self, *_) -> str: 588 return "BEGIN TRANSACTION" 589 590 def commit_sql(self, *_) -> str: 591 return "COMMIT TRANSACTION" 592 593 def rollback_sql(self, *_) -> str: 594 return "ROLLBACK TRANSACTION" 595 596 def in_unnest_op(self, expression: exp.Unnest) -> str: 597 return self.sql(expression) 598 599 def except_op(self, expression: exp.Except) -> str: 600 if not expression.args.get("distinct", False): 601 self.unsupported("EXCEPT without DISTINCT is not supported in BigQuery") 602 return f"EXCEPT{' DISTINCT' if expression.args.get('distinct') else ' ALL'}" 603 604 def intersect_op(self, expression: exp.Intersect) -> str: 605 if not expression.args.get("distinct", False): 606 self.unsupported("INTERSECT without DISTINCT is not supported in BigQuery") 607 return f"INTERSECT{' DISTINCT' if expression.args.get('distinct') else ' ALL'}" 608 609 def with_properties(self, properties: exp.Properties) -> str: 610 return self.properties(properties, prefix=self.seg("OPTIONS"))
logger =
<Logger sqlglot (WARNING)>
173class BigQuery(Dialect): 174 UNNEST_COLUMN_ONLY = True 175 176 # https://cloud.google.com/bigquery/docs/reference/standard-sql/lexical#case_sensitivity 177 RESOLVES_IDENTIFIERS_AS_UPPERCASE = None 178 179 # bigquery udfs are case sensitive 180 NORMALIZE_FUNCTIONS = False 181 182 TIME_MAPPING = { 183 "%D": "%m/%d/%y", 184 } 185 186 FORMAT_MAPPING = { 187 "DD": "%d", 188 "MM": "%m", 189 "MON": "%b", 190 "MONTH": "%B", 191 "YYYY": "%Y", 192 "YY": "%y", 193 "HH": "%I", 194 "HH12": "%I", 195 "HH24": "%H", 196 "MI": "%M", 197 "SS": "%S", 198 "SSSSS": "%f", 199 "TZH": "%z", 200 } 201 202 @classmethod 203 def normalize_identifier(cls, expression: E) -> E: 204 # In BigQuery, CTEs aren't case-sensitive, but table names are (by default, at least). 205 # The following check is essentially a heuristic to detect tables based on whether or 206 # not they're qualified. 207 if isinstance(expression, exp.Identifier): 208 parent = expression.parent 209 210 while isinstance(parent, exp.Dot): 211 parent = parent.parent 212 213 if ( 214 not isinstance(parent, exp.UserDefinedFunction) 215 and not (isinstance(parent, exp.Table) and parent.db) 216 and not expression.meta.get("is_table") 217 ): 218 expression.set("this", expression.this.lower()) 219 220 return expression 221 222 class Tokenizer(tokens.Tokenizer): 223 QUOTES = ["'", '"', '"""', "'''"] 224 COMMENTS = ["--", "#", ("/*", "*/")] 225 IDENTIFIERS = ["`"] 226 STRING_ESCAPES = ["\\"] 227 228 HEX_STRINGS = [("0x", ""), ("0X", "")] 229 230 BYTE_STRINGS = [ 231 (prefix + q, q) for q in t.cast(t.List[str], QUOTES) for prefix in ("b", "B") 232 ] 233 234 RAW_STRINGS = [ 235 (prefix + q, q) for q in t.cast(t.List[str], QUOTES) for prefix in ("r", "R") 236 ] 237 238 KEYWORDS = { 239 **tokens.Tokenizer.KEYWORDS, 240 "ANY TYPE": TokenType.VARIANT, 241 "BEGIN": TokenType.COMMAND, 242 "BEGIN TRANSACTION": TokenType.BEGIN, 243 "CURRENT_DATETIME": TokenType.CURRENT_DATETIME, 244 "BYTES": TokenType.BINARY, 245 "DECLARE": TokenType.COMMAND, 246 "FLOAT64": TokenType.DOUBLE, 247 "INT64": TokenType.BIGINT, 248 "RECORD": TokenType.STRUCT, 249 "TIMESTAMP": TokenType.TIMESTAMPTZ, 250 "NOT DETERMINISTIC": TokenType.VOLATILE, 251 "UNKNOWN": TokenType.NULL, 252 } 253 KEYWORDS.pop("DIV") 254 255 class Parser(parser.Parser): 256 PREFIXED_PIVOT_COLUMNS = True 257 258 LOG_BASE_FIRST = False 259 LOG_DEFAULTS_TO_LN = True 260 261 FUNCTIONS = { 262 **parser.Parser.FUNCTIONS, 263 "DATE_ADD": parse_date_delta_with_interval(exp.DateAdd), 264 "DATE_SUB": parse_date_delta_with_interval(exp.DateSub), 265 "DATE_TRUNC": lambda args: exp.DateTrunc( 266 unit=exp.Literal.string(str(seq_get(args, 1))), 267 this=seq_get(args, 0), 268 ), 269 "DATETIME_ADD": parse_date_delta_with_interval(exp.DatetimeAdd), 270 "DATETIME_SUB": parse_date_delta_with_interval(exp.DatetimeSub), 271 "DIV": lambda args: exp.IntDiv(this=seq_get(args, 0), expression=seq_get(args, 1)), 272 "GENERATE_ARRAY": exp.GenerateSeries.from_arg_list, 273 "PARSE_DATE": lambda args: format_time_lambda(exp.StrToDate, "bigquery")( 274 [seq_get(args, 1), seq_get(args, 0)] 275 ), 276 "PARSE_TIMESTAMP": _parse_timestamp, 277 "REGEXP_CONTAINS": exp.RegexpLike.from_arg_list, 278 "REGEXP_EXTRACT": lambda args: exp.RegexpExtract( 279 this=seq_get(args, 0), 280 expression=seq_get(args, 1), 281 position=seq_get(args, 2), 282 occurrence=seq_get(args, 3), 283 group=exp.Literal.number(1) 284 if re.compile(str(seq_get(args, 1))).groups == 1 285 else None, 286 ), 287 "SPLIT": lambda args: exp.Split( 288 # https://cloud.google.com/bigquery/docs/reference/standard-sql/string_functions#split 289 this=seq_get(args, 0), 290 expression=seq_get(args, 1) or exp.Literal.string(","), 291 ), 292 "TIME_ADD": parse_date_delta_with_interval(exp.TimeAdd), 293 "TIME_SUB": parse_date_delta_with_interval(exp.TimeSub), 294 "TIMESTAMP_ADD": parse_date_delta_with_interval(exp.TimestampAdd), 295 "TIMESTAMP_SUB": parse_date_delta_with_interval(exp.TimestampSub), 296 "TO_JSON_STRING": exp.JSONFormat.from_arg_list, 297 } 298 299 FUNCTION_PARSERS = { 300 **parser.Parser.FUNCTION_PARSERS, 301 "ARRAY": lambda self: self.expression(exp.Array, expressions=[self._parse_statement()]), 302 } 303 FUNCTION_PARSERS.pop("TRIM") 304 305 NO_PAREN_FUNCTIONS = { 306 **parser.Parser.NO_PAREN_FUNCTIONS, 307 TokenType.CURRENT_DATETIME: exp.CurrentDatetime, 308 } 309 310 NESTED_TYPE_TOKENS = { 311 *parser.Parser.NESTED_TYPE_TOKENS, 312 TokenType.TABLE, 313 } 314 315 ID_VAR_TOKENS = { 316 *parser.Parser.ID_VAR_TOKENS, 317 TokenType.VALUES, 318 } 319 320 PROPERTY_PARSERS = { 321 **parser.Parser.PROPERTY_PARSERS, 322 "NOT DETERMINISTIC": lambda self: self.expression( 323 exp.StabilityProperty, this=exp.Literal.string("VOLATILE") 324 ), 325 "OPTIONS": lambda self: self._parse_with_property(), 326 } 327 328 CONSTRAINT_PARSERS = { 329 **parser.Parser.CONSTRAINT_PARSERS, 330 "OPTIONS": lambda self: exp.Properties(expressions=self._parse_with_property()), 331 } 332 333 def _parse_table_part(self, schema: bool = False) -> t.Optional[exp.Expression]: 334 this = super()._parse_table_part(schema=schema) 335 336 # https://cloud.google.com/bigquery/docs/reference/standard-sql/lexical#table_names 337 if isinstance(this, exp.Identifier): 338 table_name = this.name 339 while self._match(TokenType.DASH, advance=False) and self._next: 340 self._advance(2) 341 table_name += f"-{self._prev.text}" 342 343 this = exp.Identifier(this=table_name, quoted=this.args.get("quoted")) 344 345 return this 346 347 def _parse_table_parts(self, schema: bool = False) -> exp.Table: 348 table = super()._parse_table_parts(schema=schema) 349 if isinstance(table.this, exp.Identifier) and "." in table.name: 350 catalog, db, this, *rest = ( 351 t.cast(t.Optional[exp.Expression], exp.to_identifier(x)) 352 for x in split_num_words(table.name, ".", 3) 353 ) 354 355 if rest and this: 356 this = exp.Dot.build(t.cast(t.List[exp.Expression], [this, *rest])) 357 358 table = exp.Table(this=this, db=db, catalog=catalog) 359 360 return table 361 362 class Generator(generator.Generator): 363 EXPLICIT_UNION = True 364 INTERVAL_ALLOWS_PLURAL_FORM = False 365 JOIN_HINTS = False 366 QUERY_HINTS = False 367 TABLE_HINTS = False 368 LIMIT_FETCH = "LIMIT" 369 RENAME_TABLE_WITH_DB = False 370 ESCAPE_LINE_BREAK = True 371 372 TRANSFORMS = { 373 **generator.Generator.TRANSFORMS, 374 exp.ApproxDistinct: rename_func("APPROX_COUNT_DISTINCT"), 375 exp.ArraySize: rename_func("ARRAY_LENGTH"), 376 exp.Cast: transforms.preprocess([transforms.remove_precision_parameterized_types]), 377 exp.CTE: transforms.preprocess([_pushdown_cte_column_names]), 378 exp.DateAdd: _date_add_sql("DATE", "ADD"), 379 exp.DateSub: _date_add_sql("DATE", "SUB"), 380 exp.DatetimeAdd: _date_add_sql("DATETIME", "ADD"), 381 exp.DatetimeSub: _date_add_sql("DATETIME", "SUB"), 382 exp.DateDiff: lambda self, e: f"DATE_DIFF({self.sql(e, 'this')}, {self.sql(e, 'expression')}, {self.sql(e.args.get('unit', 'DAY'))})", 383 exp.DateStrToDate: datestrtodate_sql, 384 exp.DateTrunc: lambda self, e: self.func("DATE_TRUNC", e.this, e.text("unit")), 385 exp.JSONFormat: rename_func("TO_JSON_STRING"), 386 exp.GenerateSeries: rename_func("GENERATE_ARRAY"), 387 exp.GroupConcat: rename_func("STRING_AGG"), 388 exp.ILike: no_ilike_sql, 389 exp.IntDiv: rename_func("DIV"), 390 exp.Max: max_or_greatest, 391 exp.Min: min_or_least, 392 exp.RegexpExtract: lambda self, e: self.func( 393 "REGEXP_EXTRACT", 394 e.this, 395 e.expression, 396 e.args.get("position"), 397 e.args.get("occurrence"), 398 ), 399 exp.RegexpLike: rename_func("REGEXP_CONTAINS"), 400 exp.Select: transforms.preprocess( 401 [ 402 transforms.explode_to_unnest, 403 _unqualify_unnest, 404 transforms.eliminate_distinct_on, 405 _alias_ordered_group, 406 ] 407 ), 408 exp.StrToDate: lambda self, e: f"PARSE_DATE({self.format_time(e)}, {self.sql(e, 'this')})", 409 exp.StrToTime: lambda self, e: self.func( 410 "PARSE_TIMESTAMP", self.format_time(e), e.this, e.args.get("zone") 411 ), 412 exp.TimeAdd: _date_add_sql("TIME", "ADD"), 413 exp.TimeSub: _date_add_sql("TIME", "SUB"), 414 exp.TimestampAdd: _date_add_sql("TIMESTAMP", "ADD"), 415 exp.TimestampSub: _date_add_sql("TIMESTAMP", "SUB"), 416 exp.TimeStrToTime: timestrtotime_sql, 417 exp.TsOrDsToDate: ts_or_ds_to_date_sql("bigquery"), 418 exp.TsOrDsAdd: _date_add_sql("DATE", "ADD"), 419 exp.PartitionedByProperty: lambda self, e: f"PARTITION BY {self.sql(e, 'this')}", 420 exp.VariancePop: rename_func("VAR_POP"), 421 exp.Values: _derived_table_values_to_unnest, 422 exp.ReturnsProperty: _returnsproperty_sql, 423 exp.Create: _create_sql, 424 exp.Trim: lambda self, e: self.func(f"TRIM", e.this, e.expression), 425 exp.StabilityProperty: lambda self, e: f"DETERMINISTIC" 426 if e.name == "IMMUTABLE" 427 else "NOT DETERMINISTIC", 428 } 429 430 TYPE_MAPPING = { 431 **generator.Generator.TYPE_MAPPING, 432 exp.DataType.Type.BIGDECIMAL: "BIGNUMERIC", 433 exp.DataType.Type.BIGINT: "INT64", 434 exp.DataType.Type.BINARY: "BYTES", 435 exp.DataType.Type.BOOLEAN: "BOOL", 436 exp.DataType.Type.CHAR: "STRING", 437 exp.DataType.Type.DECIMAL: "NUMERIC", 438 exp.DataType.Type.DOUBLE: "FLOAT64", 439 exp.DataType.Type.FLOAT: "FLOAT64", 440 exp.DataType.Type.INT: "INT64", 441 exp.DataType.Type.NCHAR: "STRING", 442 exp.DataType.Type.NVARCHAR: "STRING", 443 exp.DataType.Type.SMALLINT: "INT64", 444 exp.DataType.Type.TEXT: "STRING", 445 exp.DataType.Type.TIMESTAMP: "DATETIME", 446 exp.DataType.Type.TIMESTAMPTZ: "TIMESTAMP", 447 exp.DataType.Type.TIMESTAMPLTZ: "TIMESTAMP", 448 exp.DataType.Type.TINYINT: "INT64", 449 exp.DataType.Type.VARBINARY: "BYTES", 450 exp.DataType.Type.VARCHAR: "STRING", 451 exp.DataType.Type.VARIANT: "ANY TYPE", 452 } 453 454 PROPERTIES_LOCATION = { 455 **generator.Generator.PROPERTIES_LOCATION, 456 exp.PartitionedByProperty: exp.Properties.Location.POST_SCHEMA, 457 exp.VolatileProperty: exp.Properties.Location.UNSUPPORTED, 458 } 459 460 # from: https://cloud.google.com/bigquery/docs/reference/standard-sql/lexical#reserved_keywords 461 RESERVED_KEYWORDS = { 462 *generator.Generator.RESERVED_KEYWORDS, 463 "all", 464 "and", 465 "any", 466 "array", 467 "as", 468 "asc", 469 "assert_rows_modified", 470 "at", 471 "between", 472 "by", 473 "case", 474 "cast", 475 "collate", 476 "contains", 477 "create", 478 "cross", 479 "cube", 480 "current", 481 "default", 482 "define", 483 "desc", 484 "distinct", 485 "else", 486 "end", 487 "enum", 488 "escape", 489 "except", 490 "exclude", 491 "exists", 492 "extract", 493 "false", 494 "fetch", 495 "following", 496 "for", 497 "from", 498 "full", 499 "group", 500 "grouping", 501 "groups", 502 "hash", 503 "having", 504 "if", 505 "ignore", 506 "in", 507 "inner", 508 "intersect", 509 "interval", 510 "into", 511 "is", 512 "join", 513 "lateral", 514 "left", 515 "like", 516 "limit", 517 "lookup", 518 "merge", 519 "natural", 520 "new", 521 "no", 522 "not", 523 "null", 524 "nulls", 525 "of", 526 "on", 527 "or", 528 "order", 529 "outer", 530 "over", 531 "partition", 532 "preceding", 533 "proto", 534 "qualify", 535 "range", 536 "recursive", 537 "respect", 538 "right", 539 "rollup", 540 "rows", 541 "select", 542 "set", 543 "some", 544 "struct", 545 "tablesample", 546 "then", 547 "to", 548 "treat", 549 "true", 550 "unbounded", 551 "union", 552 "unnest", 553 "using", 554 "when", 555 "where", 556 "window", 557 "with", 558 "within", 559 } 560 561 def attimezone_sql(self, expression: exp.AtTimeZone) -> str: 562 parent = expression.parent 563 564 # BigQuery allows CAST(.. AS {STRING|TIMESTAMP} [FORMAT <fmt> [AT TIME ZONE <tz>]]). 565 # Only the TIMESTAMP one should use the below conversion, when AT TIME ZONE is included. 566 if not isinstance(parent, exp.Cast) or not parent.to.is_type("text"): 567 return self.func( 568 "TIMESTAMP", self.func("DATETIME", expression.this, expression.args.get("zone")) 569 ) 570 571 return super().attimezone_sql(expression) 572 573 def trycast_sql(self, expression: exp.TryCast) -> str: 574 return self.cast_sql(expression, safe_prefix="SAFE_") 575 576 def cte_sql(self, expression: exp.CTE) -> str: 577 if expression.alias_column_names: 578 self.unsupported("Column names in CTE definition are not supported.") 579 return super().cte_sql(expression) 580 581 def array_sql(self, expression: exp.Array) -> str: 582 first_arg = seq_get(expression.expressions, 0) 583 if isinstance(first_arg, exp.Subqueryable): 584 return f"ARRAY{self.wrap(self.sql(first_arg))}" 585 586 return inline_array_sql(self, expression) 587 588 def transaction_sql(self, *_) -> str: 589 return "BEGIN TRANSACTION" 590 591 def commit_sql(self, *_) -> str: 592 return "COMMIT TRANSACTION" 593 594 def rollback_sql(self, *_) -> str: 595 return "ROLLBACK TRANSACTION" 596 597 def in_unnest_op(self, expression: exp.Unnest) -> str: 598 return self.sql(expression) 599 600 def except_op(self, expression: exp.Except) -> str: 601 if not expression.args.get("distinct", False): 602 self.unsupported("EXCEPT without DISTINCT is not supported in BigQuery") 603 return f"EXCEPT{' DISTINCT' if expression.args.get('distinct') else ' ALL'}" 604 605 def intersect_op(self, expression: exp.Intersect) -> str: 606 if not expression.args.get("distinct", False): 607 self.unsupported("INTERSECT without DISTINCT is not supported in BigQuery") 608 return f"INTERSECT{' DISTINCT' if expression.args.get('distinct') else ' ALL'}" 609 610 def with_properties(self, properties: exp.Properties) -> str: 611 return self.properties(properties, prefix=self.seg("OPTIONS"))
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:
202 @classmethod 203 def normalize_identifier(cls, expression: E) -> E: 204 # In BigQuery, CTEs aren't case-sensitive, but table names are (by default, at least). 205 # The following check is essentially a heuristic to detect tables based on whether or 206 # not they're qualified. 207 if isinstance(expression, exp.Identifier): 208 parent = expression.parent 209 210 while isinstance(parent, exp.Dot): 211 parent = parent.parent 212 213 if ( 214 not isinstance(parent, exp.UserDefinedFunction) 215 and not (isinstance(parent, exp.Table) and parent.db) 216 and not expression.meta.get("is_table") 217 ): 218 expression.set("this", expression.this.lower()) 219 220 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 regardless of being quoted or not.
tokenizer_class =
<class 'sqlglot.dialects.bigquery.BigQuery.Tokenizer'>
parser_class =
<class 'sqlglot.dialects.bigquery.BigQuery.Parser'>
generator_class =
<class 'sqlglot.dialects.bigquery.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}}}}
Inherited Members
- sqlglot.dialects.dialect.Dialect
- INDEX_OFFSET
- ALIAS_POST_TABLESAMPLE
- IDENTIFIERS_CAN_START_WITH_DIGIT
- STRICT_STRING_CONCAT
- NULL_ORDERING
- 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
222 class Tokenizer(tokens.Tokenizer): 223 QUOTES = ["'", '"', '"""', "'''"] 224 COMMENTS = ["--", "#", ("/*", "*/")] 225 IDENTIFIERS = ["`"] 226 STRING_ESCAPES = ["\\"] 227 228 HEX_STRINGS = [("0x", ""), ("0X", "")] 229 230 BYTE_STRINGS = [ 231 (prefix + q, q) for q in t.cast(t.List[str], QUOTES) for prefix in ("b", "B") 232 ] 233 234 RAW_STRINGS = [ 235 (prefix + q, q) for q in t.cast(t.List[str], QUOTES) for prefix in ("r", "R") 236 ] 237 238 KEYWORDS = { 239 **tokens.Tokenizer.KEYWORDS, 240 "ANY TYPE": TokenType.VARIANT, 241 "BEGIN": TokenType.COMMAND, 242 "BEGIN TRANSACTION": TokenType.BEGIN, 243 "CURRENT_DATETIME": TokenType.CURRENT_DATETIME, 244 "BYTES": TokenType.BINARY, 245 "DECLARE": TokenType.COMMAND, 246 "FLOAT64": TokenType.DOUBLE, 247 "INT64": TokenType.BIGINT, 248 "RECORD": TokenType.STRUCT, 249 "TIMESTAMP": TokenType.TIMESTAMPTZ, 250 "NOT DETERMINISTIC": TokenType.VOLATILE, 251 "UNKNOWN": TokenType.NULL, 252 } 253 KEYWORDS.pop("DIV")
BYTE_STRINGS =
[("b'", "'"), ("B'", "'"), ('b"', '"'), ('B"', '"'), ('b"""', '"""'), ('B"""', '"""'), ("b'''", "'''"), ("B'''", "'''")]
RAW_STRINGS =
[("r'", "'"), ("R'", "'"), ('r"', '"'), ('R"', '"'), ('r"""', '"""'), ('R"""', '"""'), ("r'''", "'''"), ("R'''", "'''")]
KEYWORDS =
{'{%': <TokenType.BLOCK_START: 'BLOCK_START'>, '{%+': <TokenType.BLOCK_START: 'BLOCK_START'>, '{%-': <TokenType.BLOCK_START: 'BLOCK_START'>, '%}': <TokenType.BLOCK_END: 'BLOCK_END'>, '+%}': <TokenType.BLOCK_END: 'BLOCK_END'>, '-%}': <TokenType.BLOCK_END: 'BLOCK_END'>, '{{+': <TokenType.BLOCK_START: 'BLOCK_START'>, '{{-': <TokenType.BLOCK_START: 'BLOCK_START'>, '+}}': <TokenType.BLOCK_END: 'BLOCK_END'>, '-}}': <TokenType.BLOCK_END: 'BLOCK_END'>, '/*+': <TokenType.HINT: 'HINT'>, '==': <TokenType.EQ: 'EQ'>, '::': <TokenType.DCOLON: 'DCOLON'>, '||': <TokenType.DPIPE: 'DPIPE'>, '>=': <TokenType.GTE: 'GTE'>, '<=': <TokenType.LTE: 'LTE'>, '<>': <TokenType.NEQ: 'NEQ'>, '!=': <TokenType.NEQ: 'NEQ'>, '<=>': <TokenType.NULLSAFE_EQ: 'NULLSAFE_EQ'>, '->': <TokenType.ARROW: 'ARROW'>, '->>': <TokenType.DARROW: 'DARROW'>, '=>': <TokenType.FARROW: 'FARROW'>, '#>': <TokenType.HASH_ARROW: 'HASH_ARROW'>, '#>>': <TokenType.DHASH_ARROW: 'DHASH_ARROW'>, '<->': <TokenType.LR_ARROW: 'LR_ARROW'>, '&&': <TokenType.DAMP: 'DAMP'>, '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'>, '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'>, 'IF': <TokenType.IF: 'IF'>, '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'>, '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'>, 'NEXT VALUE FOR': <TokenType.NEXT_VALUE_FOR: 'NEXT_VALUE_FOR'>, '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'>, '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'>, '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'>, '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'>, 'TINYINT': <TokenType.TINYINT: 'TINYINT'>, 'SHORT': <TokenType.SMALLINT: 'SMALLINT'>, 'SMALLINT': <TokenType.SMALLINT: 'SMALLINT'>, 'INT2': <TokenType.SMALLINT: 'SMALLINT'>, 'INTEGER': <TokenType.INT: 'INT'>, 'INT': <TokenType.INT: 'INT'>, 'INT4': <TokenType.INT: 'INT'>, 'LONG': <TokenType.BIGINT: 'BIGINT'>, 'BIGINT': <TokenType.BIGINT: 'BIGINT'>, 'INT8': <TokenType.BIGINT: 'BIGINT'>, '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'>, 'CLOB': <TokenType.TEXT: 'TEXT'>, 'LONGVARCHAR': <TokenType.TEXT: 'TEXT'>, 'BINARY': <TokenType.BINARY: 'BINARY'>, 'BLOB': <TokenType.VARBINARY: 'VARBINARY'>, 'BYTEA': <TokenType.VARBINARY: 'VARBINARY'>, 'VARBINARY': <TokenType.VARBINARY: 'VARBINARY'>, 'TIME': <TokenType.TIME: 'TIME'>, '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'>, 'ANY TYPE': <TokenType.VARIANT: 'VARIANT'>, 'BEGIN TRANSACTION': <TokenType.BEGIN: 'BEGIN'>, 'CURRENT_DATETIME': <TokenType.CURRENT_DATETIME: 'CURRENT_DATETIME'>, 'BYTES': <TokenType.BINARY: 'BINARY'>, 'DECLARE': <TokenType.COMMAND: 'COMMAND'>, 'FLOAT64': <TokenType.DOUBLE: 'DOUBLE'>, 'INT64': <TokenType.BIGINT: 'BIGINT'>, 'RECORD': <TokenType.STRUCT: 'STRUCT'>, 'NOT DETERMINISTIC': <TokenType.VOLATILE: 'VOLATILE'>, 'UNKNOWN': <TokenType.NULL: 'NULL'>}
255 class Parser(parser.Parser): 256 PREFIXED_PIVOT_COLUMNS = True 257 258 LOG_BASE_FIRST = False 259 LOG_DEFAULTS_TO_LN = True 260 261 FUNCTIONS = { 262 **parser.Parser.FUNCTIONS, 263 "DATE_ADD": parse_date_delta_with_interval(exp.DateAdd), 264 "DATE_SUB": parse_date_delta_with_interval(exp.DateSub), 265 "DATE_TRUNC": lambda args: exp.DateTrunc( 266 unit=exp.Literal.string(str(seq_get(args, 1))), 267 this=seq_get(args, 0), 268 ), 269 "DATETIME_ADD": parse_date_delta_with_interval(exp.DatetimeAdd), 270 "DATETIME_SUB": parse_date_delta_with_interval(exp.DatetimeSub), 271 "DIV": lambda args: exp.IntDiv(this=seq_get(args, 0), expression=seq_get(args, 1)), 272 "GENERATE_ARRAY": exp.GenerateSeries.from_arg_list, 273 "PARSE_DATE": lambda args: format_time_lambda(exp.StrToDate, "bigquery")( 274 [seq_get(args, 1), seq_get(args, 0)] 275 ), 276 "PARSE_TIMESTAMP": _parse_timestamp, 277 "REGEXP_CONTAINS": exp.RegexpLike.from_arg_list, 278 "REGEXP_EXTRACT": lambda args: exp.RegexpExtract( 279 this=seq_get(args, 0), 280 expression=seq_get(args, 1), 281 position=seq_get(args, 2), 282 occurrence=seq_get(args, 3), 283 group=exp.Literal.number(1) 284 if re.compile(str(seq_get(args, 1))).groups == 1 285 else None, 286 ), 287 "SPLIT": lambda args: exp.Split( 288 # https://cloud.google.com/bigquery/docs/reference/standard-sql/string_functions#split 289 this=seq_get(args, 0), 290 expression=seq_get(args, 1) or exp.Literal.string(","), 291 ), 292 "TIME_ADD": parse_date_delta_with_interval(exp.TimeAdd), 293 "TIME_SUB": parse_date_delta_with_interval(exp.TimeSub), 294 "TIMESTAMP_ADD": parse_date_delta_with_interval(exp.TimestampAdd), 295 "TIMESTAMP_SUB": parse_date_delta_with_interval(exp.TimestampSub), 296 "TO_JSON_STRING": exp.JSONFormat.from_arg_list, 297 } 298 299 FUNCTION_PARSERS = { 300 **parser.Parser.FUNCTION_PARSERS, 301 "ARRAY": lambda self: self.expression(exp.Array, expressions=[self._parse_statement()]), 302 } 303 FUNCTION_PARSERS.pop("TRIM") 304 305 NO_PAREN_FUNCTIONS = { 306 **parser.Parser.NO_PAREN_FUNCTIONS, 307 TokenType.CURRENT_DATETIME: exp.CurrentDatetime, 308 } 309 310 NESTED_TYPE_TOKENS = { 311 *parser.Parser.NESTED_TYPE_TOKENS, 312 TokenType.TABLE, 313 } 314 315 ID_VAR_TOKENS = { 316 *parser.Parser.ID_VAR_TOKENS, 317 TokenType.VALUES, 318 } 319 320 PROPERTY_PARSERS = { 321 **parser.Parser.PROPERTY_PARSERS, 322 "NOT DETERMINISTIC": lambda self: self.expression( 323 exp.StabilityProperty, this=exp.Literal.string("VOLATILE") 324 ), 325 "OPTIONS": lambda self: self._parse_with_property(), 326 } 327 328 CONSTRAINT_PARSERS = { 329 **parser.Parser.CONSTRAINT_PARSERS, 330 "OPTIONS": lambda self: exp.Properties(expressions=self._parse_with_property()), 331 } 332 333 def _parse_table_part(self, schema: bool = False) -> t.Optional[exp.Expression]: 334 this = super()._parse_table_part(schema=schema) 335 336 # https://cloud.google.com/bigquery/docs/reference/standard-sql/lexical#table_names 337 if isinstance(this, exp.Identifier): 338 table_name = this.name 339 while self._match(TokenType.DASH, advance=False) and self._next: 340 self._advance(2) 341 table_name += f"-{self._prev.text}" 342 343 this = exp.Identifier(this=table_name, quoted=this.args.get("quoted")) 344 345 return this 346 347 def _parse_table_parts(self, schema: bool = False) -> exp.Table: 348 table = super()._parse_table_parts(schema=schema) 349 if isinstance(table.this, exp.Identifier) and "." in table.name: 350 catalog, db, this, *rest = ( 351 t.cast(t.Optional[exp.Expression], exp.to_identifier(x)) 352 for x in split_num_words(table.name, ".", 3) 353 ) 354 355 if rest and this: 356 this = exp.Dot.build(t.cast(t.List[exp.Expression], [this, *rest])) 357 358 table = exp.Table(this=this, db=db, catalog=catalog) 359 360 return table
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'>>, 'ARRAY': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Array'>>, 'ARRAY_AGG': <bound method Func.from_arg_list of <class 'sqlglot.expressions.ArrayAgg'>>, 'ARRAY_ALL': <bound method Func.from_arg_list of <class 'sqlglot.expressions.ArrayAll'>>, 'ARRAY_ANY': <bound method Func.from_arg_list of <class 'sqlglot.expressions.ArrayAny'>>, 'ARRAY_CONCAT': <bound method Func.from_arg_list of <class 'sqlglot.expressions.ArrayConcat'>>, 'ARRAY_CONTAINS': <bound method Func.from_arg_list of <class 'sqlglot.expressions.ArrayContains'>>, 'FILTER': <bound method Func.from_arg_list of <class 'sqlglot.expressions.ArrayFilter'>>, 'ARRAY_FILTER': <bound method Func.from_arg_list of <class 'sqlglot.expressions.ArrayFilter'>>, 'ARRAY_JOIN': <bound method Func.from_arg_list of <class 'sqlglot.expressions.ArrayJoin'>>, 'ARRAY_SIZE': <bound method Func.from_arg_list of <class 'sqlglot.expressions.ArraySize'>>, 'ARRAY_SORT': <bound method Func.from_arg_list of <class 'sqlglot.expressions.ArraySort'>>, 'ARRAY_SUM': <bound method Func.from_arg_list of <class 'sqlglot.expressions.ArraySum'>>, 'ARRAY_UNION_AGG': <bound method Func.from_arg_list of <class 'sqlglot.expressions.ArrayUnionAgg'>>, 'AVG': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Avg'>>, 'CASE': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Case'>>, 'CAST': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Cast'>>, 'CAST_TO_STR_TYPE': <bound method Func.from_arg_list of <class 'sqlglot.expressions.CastToStrType'>>, 'CEIL': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Ceil'>>, 'CEILING': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Ceil'>>, 'COALESCE': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Coalesce'>>, 'IFNULL': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Coalesce'>>, 'NVL': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Coalesce'>>, 'CONCAT': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Concat'>>, 'CONCAT_WS': <bound method Func.from_arg_list of <class 'sqlglot.expressions.ConcatWs'>>, 'COUNT': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Count'>>, 'COUNT_IF': <bound method Func.from_arg_list of <class 'sqlglot.expressions.CountIf'>>, 'CURRENT_DATE': <bound method Func.from_arg_list of <class 'sqlglot.expressions.CurrentDate'>>, 'CURRENT_DATETIME': <bound method Func.from_arg_list of <class 'sqlglot.expressions.CurrentDatetime'>>, 'CURRENT_TIME': <bound method Func.from_arg_list of <class 'sqlglot.expressions.CurrentTime'>>, 'CURRENT_TIMESTAMP': <bound method Func.from_arg_list of <class 'sqlglot.expressions.CurrentTimestamp'>>, 'CURRENT_USER': <bound method Func.from_arg_list of <class 'sqlglot.expressions.CurrentUser'>>, 'DATE': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Date'>>, 'DATE_ADD': <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'>>, 'EXTRACT': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Extract'>>, 'FLOOR': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Floor'>>, 'FROM_BASE': <bound method Func.from_arg_list of <class 'sqlglot.expressions.FromBase'>>, 'FROM_BASE64': <bound method Func.from_arg_list of <class 'sqlglot.expressions.FromBase64'>>, 'GENERATE_SERIES': <bound method Func.from_arg_list of <class 'sqlglot.expressions.GenerateSeries'>>, 'GREATEST': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Greatest'>>, 'GROUP_CONCAT': <bound method Func.from_arg_list of <class 'sqlglot.expressions.GroupConcat'>>, 'HEX': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Hex'>>, 'HLL': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Hll'>>, 'IF': <bound method Func.from_arg_list of <class 'sqlglot.expressions.If'>>, 'INITCAP': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Initcap'>>, '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'>>, 'LAST_DATE_OF_MONTH': <bound method Func.from_arg_list of <class 'sqlglot.expressions.LastDateOfMonth'>>, 'LEAST': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Least'>>, 'LEFT': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Left'>>, 'LENGTH': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Length'>>, 'LEN': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Length'>>, 'LEVENSHTEIN': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Levenshtein'>>, 'LN': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Ln'>>, 'LOG': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Log'>>, 'LOG10': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Log10'>>, 'LOG2': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Log2'>>, 'LOGICAL_AND': <bound method Func.from_arg_list of <class 'sqlglot.expressions.LogicalAnd'>>, 'BOOL_AND': <bound method Func.from_arg_list of <class 'sqlglot.expressions.LogicalAnd'>>, 'BOOLAND_AGG': <bound method Func.from_arg_list of <class 'sqlglot.expressions.LogicalAnd'>>, 'LOGICAL_OR': <bound method Func.from_arg_list of <class 'sqlglot.expressions.LogicalOr'>>, 'BOOL_OR': <bound method Func.from_arg_list of <class 'sqlglot.expressions.LogicalOr'>>, 'BOOLOR_AGG': <bound method Func.from_arg_list of <class 'sqlglot.expressions.LogicalOr'>>, 'LOWER': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Lower'>>, 'LCASE': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Lower'>>, 'MD5': <bound method Func.from_arg_list of <class 'sqlglot.expressions.MD5'>>, 'MAP': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Map'>>, 'MAP_FROM_ENTRIES': <bound method Func.from_arg_list of <class 'sqlglot.expressions.MapFromEntries'>>, 'MATCH_AGAINST': <bound method Func.from_arg_list of <class 'sqlglot.expressions.MatchAgainst'>>, 'MAX': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Max'>>, 'MIN': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Min'>>, 'MONTH': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Month'>>, 'NEXT_VALUE_FOR': <bound method Func.from_arg_list of <class 'sqlglot.expressions.NextValueFor'>>, 'NUMBER_TO_STR': <bound method Func.from_arg_list of <class 'sqlglot.expressions.NumberToStr'>>, 'NVL2': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Nvl2'>>, 'OPEN_J_S_O_N': <bound method Func.from_arg_list of <class 'sqlglot.expressions.OpenJSON'>>, 'PARAMETERIZED_AGG': <bound method Func.from_arg_list of <class 'sqlglot.expressions.ParameterizedAgg'>>, 'PERCENTILE_CONT': <bound method Func.from_arg_list of <class 'sqlglot.expressions.PercentileCont'>>, 'PERCENTILE_DISC': <bound method Func.from_arg_list of <class 'sqlglot.expressions.PercentileDisc'>>, 'POSEXPLODE': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Posexplode'>>, 'POWER': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Pow'>>, 'POW': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Pow'>>, 'QUANTILE': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Quantile'>>, 'RANGE_N': <bound method Func.from_arg_list of <class 'sqlglot.expressions.RangeN'>>, 'READ_CSV': <bound method Func.from_arg_list of <class 'sqlglot.expressions.ReadCSV'>>, 'REDUCE': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Reduce'>>, 'REGEXP_EXTRACT': <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_SPLIT': <bound method Func.from_arg_list of <class 'sqlglot.expressions.RegexpSplit'>>, 'REPEAT': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Repeat'>>, 'RIGHT': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Right'>>, 'ROUND': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Round'>>, 'ROW_NUMBER': <bound method Func.from_arg_list of <class 'sqlglot.expressions.RowNumber'>>, 'SHA': <bound method Func.from_arg_list of <class 'sqlglot.expressions.SHA'>>, 'SHA1': <bound method Func.from_arg_list of <class 'sqlglot.expressions.SHA'>>, 'SHA2': <bound method Func.from_arg_list of <class 'sqlglot.expressions.SHA2'>>, 'SAFE_CONCAT': <bound method Func.from_arg_list of <class 'sqlglot.expressions.SafeConcat'>>, 'SAFE_DIVIDE': <bound method Func.from_arg_list of <class 'sqlglot.expressions.SafeDivide'>>, 'SET_AGG': <bound method Func.from_arg_list of <class 'sqlglot.expressions.SetAgg'>>, 'SORT_ARRAY': <bound method Func.from_arg_list of <class 'sqlglot.expressions.SortArray'>>, 'SPLIT': <function BigQuery.Parser.<lambda>>, 'SQRT': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Sqrt'>>, 'STANDARD_HASH': <bound method Func.from_arg_list of <class 'sqlglot.expressions.StandardHash'>>, 'STAR_MAP': <bound method Func.from_arg_list of <class 'sqlglot.expressions.StarMap'>>, 'STDDEV': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Stddev'>>, 'STDDEV_POP': <bound method Func.from_arg_list of <class 'sqlglot.expressions.StddevPop'>>, 'STDDEV_SAMP': <bound method Func.from_arg_list of <class 'sqlglot.expressions.StddevSamp'>>, 'STR_POSITION': <bound method Func.from_arg_list of <class 'sqlglot.expressions.StrPosition'>>, 'STR_TO_DATE': <bound method Func.from_arg_list of <class 'sqlglot.expressions.StrToDate'>>, 'STR_TO_TIME': <bound method Func.from_arg_list of <class 'sqlglot.expressions.StrToTime'>>, 'STR_TO_UNIX': <bound method Func.from_arg_list of <class 'sqlglot.expressions.StrToUnix'>>, 'STRUCT': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Struct'>>, 'STRUCT_EXTRACT': <bound method Func.from_arg_list of <class 'sqlglot.expressions.StructExtract'>>, 'SUBSTRING': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Substring'>>, 'SUM': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Sum'>>, 'TIME_ADD': <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_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'>>, 'TRIM': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Trim'>>, 'TRY_CAST': <bound method Func.from_arg_list of <class 'sqlglot.expressions.TryCast'>>, 'TS_OR_DI_TO_DI': <bound method Func.from_arg_list of <class 'sqlglot.expressions.TsOrDiToDi'>>, 'TS_OR_DS_ADD': <bound method Func.from_arg_list of <class 'sqlglot.expressions.TsOrDsAdd'>>, 'TS_OR_DS_TO_DATE': <bound method Func.from_arg_list of <class 'sqlglot.expressions.TsOrDsToDate'>>, 'TS_OR_DS_TO_DATE_STR': <function Parser.<lambda>>, 'UNHEX': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Unhex'>>, 'UNIX_TO_STR': <bound method Func.from_arg_list of <class 'sqlglot.expressions.UnixToStr'>>, 'UNIX_TO_TIME': <bound method Func.from_arg_list of <class 'sqlglot.expressions.UnixToTime'>>, 'UNIX_TO_TIME_STR': <bound method Func.from_arg_list of <class 'sqlglot.expressions.UnixToTimeStr'>>, 'UPPER': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Upper'>>, 'UCASE': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Upper'>>, 'VAR_MAP': <function parse_var_map>, 'VARIANCE': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Variance'>>, 'VARIANCE_SAMP': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Variance'>>, 'VAR_SAMP': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Variance'>>, 'VARIANCE_POP': <bound method Func.from_arg_list of <class 'sqlglot.expressions.VariancePop'>>, 'VAR_POP': <bound method Func.from_arg_list of <class 'sqlglot.expressions.VariancePop'>>, 'WEEK': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Week'>>, 'WEEK_OF_YEAR': <bound method Func.from_arg_list of <class 'sqlglot.expressions.WeekOfYear'>>, 'WEEKOFYEAR': <bound method Func.from_arg_list of <class 'sqlglot.expressions.WeekOfYear'>>, 'WHEN': <bound method Func.from_arg_list of <class 'sqlglot.expressions.When'>>, 'X_M_L_TABLE': <bound method Func.from_arg_list of <class 'sqlglot.expressions.XMLTable'>>, 'YEAR': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Year'>>, 'GLOB': <function Parser.<lambda>>, 'LIKE': <function parse_like>, 'DIV': <function BigQuery.Parser.<lambda>>, 'GENERATE_ARRAY': <bound method Func.from_arg_list of <class 'sqlglot.expressions.GenerateSeries'>>, 'PARSE_DATE': <function BigQuery.Parser.<lambda>>, 'PARSE_TIMESTAMP': <function _parse_timestamp>, 'REGEXP_CONTAINS': <bound method Func.from_arg_list of <class 'sqlglot.expressions.RegexpLike'>>, '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>>, 'CONVERT': <function Parser.<lambda>>, 'DECODE': <function Parser.<lambda>>, 'EXTRACT': <function Parser.<lambda>>, 'JSON_OBJECT': <function Parser.<lambda>>, 'LOG': <function Parser.<lambda>>, 'MATCH': <function Parser.<lambda>>, 'OPENJSON': <function Parser.<lambda>>, 'POSITION': <function Parser.<lambda>>, 'SAFE_CAST': <function Parser.<lambda>>, 'STRING_AGG': <function Parser.<lambda>>, 'SUBSTRING': <function Parser.<lambda>>, '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.TABLE: 'TABLE'>, <TokenType.MAP: 'MAP'>, <TokenType.NULLABLE: 'NULLABLE'>, <TokenType.STRUCT: 'STRUCT'>, <TokenType.ARRAY: 'ARRAY'>}
ID_VAR_TOKENS =
{<TokenType.VARBINARY: 'VARBINARY'>, <TokenType.CURRENT_TIMESTAMP: 'CURRENT_TIMESTAMP'>, <TokenType.DELETE: 'DELETE'>, <TokenType.JSON: 'JSON'>, <TokenType.MEDIUMTEXT: 'MEDIUMTEXT'>, <TokenType.UPDATE: 'UPDATE'>, <TokenType.PROCEDURE: 'PROCEDURE'>, <TokenType.DOUBLE: 'DOUBLE'>, <TokenType.DATABASE: 'DATABASE'>, <TokenType.UINT256: 'UINT256'>, <TokenType.BIGSERIAL: 'BIGSERIAL'>, <TokenType.ASC: 'ASC'>, <TokenType.LONGBLOB: 'LONGBLOB'>, <TokenType.VAR: 'VAR'>, <TokenType.SEMI: 'SEMI'>, <TokenType.BIGDECIMAL: 'BIGDECIMAL'>, <TokenType.UINT128: 'UINT128'>, <TokenType.DIV: 'DIV'>, <TokenType.ESCAPE: 'ESCAPE'>, <TokenType.INTERVAL: 'INTERVAL'>, <TokenType.RIGHT: 'RIGHT'>, <TokenType.USERDEFINED: 'USERDEFINED'>, <TokenType.ROW: 'ROW'>, <TokenType.TSTZMULTIRANGE: 'TSTZMULTIRANGE'>, <TokenType.DECIMAL: 'DECIMAL'>, <TokenType.FILTER: 'FILTER'>, <TokenType.FUNCTION: 'FUNCTION'>, <TokenType.NVARCHAR: 'NVARCHAR'>, <TokenType.DATEMULTIRANGE: 'DATEMULTIRANGE'>, <TokenType.TIME: 'TIME'>, <TokenType.ANTI: 'ANTI'>, <TokenType.STRUCT: 'STRUCT'>, <TokenType.BOOLEAN: 'BOOLEAN'>, <TokenType.CURRENT_DATE: 'CURRENT_DATE'>, <TokenType.BINARY: 'BINARY'>, <TokenType.GEOMETRY: 'GEOMETRY'>, <TokenType.VARIANT: 'VARIANT'>, <TokenType.REFERENCES: 'REFERENCES'>, <TokenType.TSRANGE: 'TSRANGE'>, <TokenType.IF: 'IF'>, <TokenType.BIT: 'BIT'>, <TokenType.DATERANGE: 'DATERANGE'>, <TokenType.SOME: 'SOME'>, <TokenType.SMALLINT: 'SMALLINT'>, <TokenType.ALL: 'ALL'>, <TokenType.ARRAY: 'ARRAY'>, <TokenType.JSONB: 'JSONB'>, <TokenType.GEOGRAPHY: 'GEOGRAPHY'>, <TokenType.OVERWRITE: 'OVERWRITE'>, <TokenType.OFFSET: 'OFFSET'>, <TokenType.XML: 'XML'>, <TokenType.CURRENT_TIME: 'CURRENT_TIME'>, <TokenType.TOP: 'TOP'>, <TokenType.DESC: 'DESC'>, <TokenType.TINYINT: 'TINYINT'>, <TokenType.HSTORE: 'HSTORE'>, <TokenType.INT4MULTIRANGE: 'INT4MULTIRANGE'>, <TokenType.END: 'END'>, <TokenType.ENUM: 'ENUM'>, <TokenType.DATETIME: 'DATETIME'>, <TokenType.SMALLMONEY: 'SMALLMONEY'>, <TokenType.INET: 'INET'>, <TokenType.FULL: 'FULL'>, <TokenType.PERCENT: 'PERCENT'>, <TokenType.NATURAL: 'NATURAL'>, <TokenType.UTINYINT: 'UTINYINT'>, <TokenType.LONGTEXT: 'LONGTEXT'>, <TokenType.COLLATE: 'COLLATE'>, <TokenType.TIMESTAMPLTZ: 'TIMESTAMPLTZ'>, <TokenType.TSMULTIRANGE: 'TSMULTIRANGE'>, <TokenType.LOAD: 'LOAD'>, <TokenType.SET: 'SET'>, <TokenType.VARCHAR: 'VARCHAR'>, <TokenType.UINT: 'UINT'>, <TokenType.BIGINT: 'BIGINT'>, <TokenType.SCHEMA: 'SCHEMA'>, <TokenType.CACHE: 'CACHE'>, <TokenType.COLUMN: 'COLUMN'>, <TokenType.PRAGMA: 'PRAGMA'>, <TokenType.NUMRANGE: 'NUMRANGE'>, <TokenType.UNIQUEIDENTIFIER: 'UNIQUEIDENTIFIER'>, <TokenType.MONEY: 'MONEY'>, <TokenType.VOLATILE: 'VOLATILE'>, <TokenType.ROWVERSION: 'ROWVERSION'>, <TokenType.ORDINALITY: 'ORDINALITY'>, <TokenType.PSEUDO_TYPE: 'PSEUDO_TYPE'>, <TokenType.DATE: 'DATE'>, <TokenType.INDEX: 'INDEX'>, <TokenType.RANGE: 'RANGE'>, <TokenType.CONSTRAINT: 'CONSTRAINT'>, <TokenType.UUID: 'UUID'>, <TokenType.OBJECT: 'OBJECT'>, <TokenType.ISNULL: 'ISNULL'>, <TokenType.COMMAND: 'COMMAND'>, <TokenType.DATETIME64: 'DATETIME64'>, <TokenType.SERIAL: 'SERIAL'>, <TokenType.INT8RANGE: 'INT8RANGE'>, <TokenType.IMAGE: 'IMAGE'>, <TokenType.TABLE: 'TABLE'>, <TokenType.TSTZRANGE: 'TSTZRANGE'>, <TokenType.NEXT: 'NEXT'>, <TokenType.LEFT: 'LEFT'>, <TokenType.FALSE: 'FALSE'>, <TokenType.WINDOW: 'WINDOW'>, <TokenType.SMALLSERIAL: 'SMALLSERIAL'>, <TokenType.VALUES: 'VALUES'>, <TokenType.EXECUTE: 'EXECUTE'>, <TokenType.PIVOT: 'PIVOT'>, <TokenType.PARTITION: 'PARTITION'>, <TokenType.INT4RANGE: 'INT4RANGE'>, <TokenType.TEMPORARY: 'TEMPORARY'>, <TokenType.TRUE: 'TRUE'>, <TokenType.INT256: 'INT256'>, <TokenType.DICTIONARY: 'DICTIONARY'>, <TokenType.DESCRIBE: 'DESCRIBE'>, <TokenType.IS: 'IS'>, <TokenType.CHAR: 'CHAR'>, <TokenType.MAP: 'MAP'>, <TokenType.UNIQUE: 'UNIQUE'>, <TokenType.NUMMULTIRANGE: 'NUMMULTIRANGE'>, <TokenType.BEGIN: 'BEGIN'>, <TokenType.TEXT: 'TEXT'>, <TokenType.VIEW: 'VIEW'>, <TokenType.HLLSKETCH: 'HLLSKETCH'>, <TokenType.APPLY: 'APPLY'>, <TokenType.SUPER: 'SUPER'>, <TokenType.MEDIUMBLOB: 'MEDIUMBLOB'>, <TokenType.INT8MULTIRANGE: 'INT8MULTIRANGE'>, <TokenType.AUTO_INCREMENT: 'AUTO_INCREMENT'>, <TokenType.SHOW: 'SHOW'>, <TokenType.NULLABLE: 'NULLABLE'>, <TokenType.SETTINGS: 'SETTINGS'>, <TokenType.NCHAR: 'NCHAR'>, <TokenType.DEFAULT: 'DEFAULT'>, <TokenType.TIMESTAMPTZ: 'TIMESTAMPTZ'>, <TokenType.UBIGINT: 'UBIGINT'>, <TokenType.CURRENT_USER: 'CURRENT_USER'>, <TokenType.INT: 'INT'>, <TokenType.ANY: 'ANY'>, <TokenType.TIMESTAMP: 'TIMESTAMP'>, <TokenType.KEEP: 'KEEP'>, <TokenType.FIRST: 'FIRST'>, <TokenType.FORMAT: 'FORMAT'>, <TokenType.UNPIVOT: 'UNPIVOT'>, <TokenType.USMALLINT: 'USMALLINT'>, <TokenType.FLOAT: 'FLOAT'>, <TokenType.EXISTS: 'EXISTS'>, <TokenType.COMMENT: 'COMMENT'>, <TokenType.CURRENT_DATETIME: 'CURRENT_DATETIME'>, <TokenType.COMMIT: 'COMMIT'>, <TokenType.ROWS: 'ROWS'>, <TokenType.MERGE: 'MERGE'>, <TokenType.CASE: 'CASE'>, <TokenType.INT128: 'INT128'>}
PROPERTY_PARSERS =
{'ALGORITHM': <function Parser.<lambda>>, 'AUTO_INCREMENT': <function Parser.<lambda>>, 'BLOCKCOMPRESSION': <function Parser.<lambda>>, 'CHARACTER SET': <function Parser.<lambda>>, 'CHECKSUM': <function Parser.<lambda>>, 'CLUSTER BY': <function Parser.<lambda>>, 'CLUSTERED': <function Parser.<lambda>>, 'COLLATE': <function Parser.<lambda>>, 'COMMENT': <function Parser.<lambda>>, 'COPY': <function Parser.<lambda>>, 'DATABLOCKSIZE': <function Parser.<lambda>>, 'DEFINER': <function Parser.<lambda>>, 'DETERMINISTIC': <function Parser.<lambda>>, 'DISTKEY': <function Parser.<lambda>>, 'DISTSTYLE': <function Parser.<lambda>>, 'ENGINE': <function Parser.<lambda>>, 'EXECUTE': <function Parser.<lambda>>, 'EXTERNAL': <function Parser.<lambda>>, 'FALLBACK': <function Parser.<lambda>>, 'FORMAT': <function Parser.<lambda>>, 'FREESPACE': <function Parser.<lambda>>, 'IMMUTABLE': <function Parser.<lambda>>, 'JOURNAL': <function Parser.<lambda>>, 'LANGUAGE': <function Parser.<lambda>>, 'LAYOUT': <function Parser.<lambda>>, 'LIFETIME': <function Parser.<lambda>>, 'LIKE': <function Parser.<lambda>>, 'LOCATION': <function Parser.<lambda>>, 'LOCK': <function Parser.<lambda>>, 'LOCKING': <function Parser.<lambda>>, 'LOG': <function Parser.<lambda>>, 'MATERIALIZED': <function Parser.<lambda>>, 'MERGEBLOCKRATIO': <function Parser.<lambda>>, 'MULTISET': <function Parser.<lambda>>, 'NO': <function Parser.<lambda>>, 'ON': <function Parser.<lambda>>, 'ORDER BY': <function Parser.<lambda>>, 'PARTITION BY': <function Parser.<lambda>>, 'PARTITIONED BY': <function Parser.<lambda>>, 'PARTITIONED_BY': <function Parser.<lambda>>, 'PRIMARY KEY': <function Parser.<lambda>>, 'RANGE': <function Parser.<lambda>>, 'RETURNS': <function Parser.<lambda>>, 'ROW': <function Parser.<lambda>>, 'ROW_FORMAT': <function Parser.<lambda>>, 'SET': <function Parser.<lambda>>, 'SETTINGS': <function Parser.<lambda>>, 'SORTKEY': <function Parser.<lambda>>, 'SOURCE': <function Parser.<lambda>>, 'STABLE': <function Parser.<lambda>>, 'STORED': <function Parser.<lambda>>, 'TBLPROPERTIES': <function Parser.<lambda>>, 'TEMP': <function Parser.<lambda>>, 'TEMPORARY': <function Parser.<lambda>>, 'TO': <function Parser.<lambda>>, 'TRANSIENT': <function Parser.<lambda>>, 'TTL': <function Parser.<lambda>>, 'USING': <function Parser.<lambda>>, 'VOLATILE': <function Parser.<lambda>>, 'WITH': <function Parser.<lambda>>, '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>>, 'DEFAULT': <function Parser.<lambda>>, 'ENCODE': <function Parser.<lambda>>, 'FOREIGN KEY': <function Parser.<lambda>>, 'FORMAT': <function Parser.<lambda>>, 'GENERATED': <function Parser.<lambda>>, 'IDENTITY': <function Parser.<lambda>>, 'INLINE': <function Parser.<lambda>>, 'LIKE': <function Parser.<lambda>>, 'NOT': <function Parser.<lambda>>, 'NULL': <function Parser.<lambda>>, 'ON': <function Parser.<lambda>>, 'PATH': <function Parser.<lambda>>, 'PRIMARY KEY': <function Parser.<lambda>>, 'REFERENCES': <function Parser.<lambda>>, 'TITLE': <function Parser.<lambda>>, 'TTL': <function Parser.<lambda>>, 'UNIQUE': <function Parser.<lambda>>, 'UPPERCASE': <function Parser.<lambda>>, 'OPTIONS': <function BigQuery.Parser.<lambda>>}
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
- ENUM_TYPE_TOKENS
- TYPE_TOKENS
- SUBQUERY_PREDICATES
- RESERVED_KEYWORDS
- DB_CREATABLES
- CREATABLES
- INTERVAL_VARS
- TABLE_ALIAS_TOKENS
- COMMENT_TABLE_ALIAS_TOKENS
- UPDATE_ALIAS_TOKENS
- TRIM_TYPES
- FUNC_TOKENS
- CONJUNCTION
- EQUALITY
- COMPARISON
- BITWISE
- TERM
- FACTOR
- TIMESTAMPS
- SET_OPERATIONS
- JOIN_METHODS
- JOIN_SIDES
- JOIN_KINDS
- JOIN_HINTS
- LAMBDAS
- COLUMN_OPERATORS
- EXPRESSION_PARSERS
- STATEMENT_PARSERS
- UNARY_PARSERS
- PRIMARY_PARSERS
- PLACEHOLDER_PARSERS
- RANGE_PARSERS
- ALTER_PARSERS
- SCHEMA_UNNAMED_CONSTRAINTS
- NO_PAREN_FUNCTION_PARSERS
- 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_KINDS
- TABLE_INDEX_HINT_TOKENS
- WINDOW_ALIAS_TOKENS
- WINDOW_BEFORE_PAREN_TOKENS
- WINDOW_SIDES
- ADD_CONSTRAINT_TOKENS
- STRICT_CAST
- CONCAT_NULL_OUTPUTS_STRING
- IDENTIFY_PIVOT_STRINGS
- 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
362 class Generator(generator.Generator): 363 EXPLICIT_UNION = True 364 INTERVAL_ALLOWS_PLURAL_FORM = False 365 JOIN_HINTS = False 366 QUERY_HINTS = False 367 TABLE_HINTS = False 368 LIMIT_FETCH = "LIMIT" 369 RENAME_TABLE_WITH_DB = False 370 ESCAPE_LINE_BREAK = True 371 372 TRANSFORMS = { 373 **generator.Generator.TRANSFORMS, 374 exp.ApproxDistinct: rename_func("APPROX_COUNT_DISTINCT"), 375 exp.ArraySize: rename_func("ARRAY_LENGTH"), 376 exp.Cast: transforms.preprocess([transforms.remove_precision_parameterized_types]), 377 exp.CTE: transforms.preprocess([_pushdown_cte_column_names]), 378 exp.DateAdd: _date_add_sql("DATE", "ADD"), 379 exp.DateSub: _date_add_sql("DATE", "SUB"), 380 exp.DatetimeAdd: _date_add_sql("DATETIME", "ADD"), 381 exp.DatetimeSub: _date_add_sql("DATETIME", "SUB"), 382 exp.DateDiff: lambda self, e: f"DATE_DIFF({self.sql(e, 'this')}, {self.sql(e, 'expression')}, {self.sql(e.args.get('unit', 'DAY'))})", 383 exp.DateStrToDate: datestrtodate_sql, 384 exp.DateTrunc: lambda self, e: self.func("DATE_TRUNC", e.this, e.text("unit")), 385 exp.JSONFormat: rename_func("TO_JSON_STRING"), 386 exp.GenerateSeries: rename_func("GENERATE_ARRAY"), 387 exp.GroupConcat: rename_func("STRING_AGG"), 388 exp.ILike: no_ilike_sql, 389 exp.IntDiv: rename_func("DIV"), 390 exp.Max: max_or_greatest, 391 exp.Min: min_or_least, 392 exp.RegexpExtract: lambda self, e: self.func( 393 "REGEXP_EXTRACT", 394 e.this, 395 e.expression, 396 e.args.get("position"), 397 e.args.get("occurrence"), 398 ), 399 exp.RegexpLike: rename_func("REGEXP_CONTAINS"), 400 exp.Select: transforms.preprocess( 401 [ 402 transforms.explode_to_unnest, 403 _unqualify_unnest, 404 transforms.eliminate_distinct_on, 405 _alias_ordered_group, 406 ] 407 ), 408 exp.StrToDate: lambda self, e: f"PARSE_DATE({self.format_time(e)}, {self.sql(e, 'this')})", 409 exp.StrToTime: lambda self, e: self.func( 410 "PARSE_TIMESTAMP", self.format_time(e), e.this, e.args.get("zone") 411 ), 412 exp.TimeAdd: _date_add_sql("TIME", "ADD"), 413 exp.TimeSub: _date_add_sql("TIME", "SUB"), 414 exp.TimestampAdd: _date_add_sql("TIMESTAMP", "ADD"), 415 exp.TimestampSub: _date_add_sql("TIMESTAMP", "SUB"), 416 exp.TimeStrToTime: timestrtotime_sql, 417 exp.TsOrDsToDate: ts_or_ds_to_date_sql("bigquery"), 418 exp.TsOrDsAdd: _date_add_sql("DATE", "ADD"), 419 exp.PartitionedByProperty: lambda self, e: f"PARTITION BY {self.sql(e, 'this')}", 420 exp.VariancePop: rename_func("VAR_POP"), 421 exp.Values: _derived_table_values_to_unnest, 422 exp.ReturnsProperty: _returnsproperty_sql, 423 exp.Create: _create_sql, 424 exp.Trim: lambda self, e: self.func(f"TRIM", e.this, e.expression), 425 exp.StabilityProperty: lambda self, e: f"DETERMINISTIC" 426 if e.name == "IMMUTABLE" 427 else "NOT DETERMINISTIC", 428 } 429 430 TYPE_MAPPING = { 431 **generator.Generator.TYPE_MAPPING, 432 exp.DataType.Type.BIGDECIMAL: "BIGNUMERIC", 433 exp.DataType.Type.BIGINT: "INT64", 434 exp.DataType.Type.BINARY: "BYTES", 435 exp.DataType.Type.BOOLEAN: "BOOL", 436 exp.DataType.Type.CHAR: "STRING", 437 exp.DataType.Type.DECIMAL: "NUMERIC", 438 exp.DataType.Type.DOUBLE: "FLOAT64", 439 exp.DataType.Type.FLOAT: "FLOAT64", 440 exp.DataType.Type.INT: "INT64", 441 exp.DataType.Type.NCHAR: "STRING", 442 exp.DataType.Type.NVARCHAR: "STRING", 443 exp.DataType.Type.SMALLINT: "INT64", 444 exp.DataType.Type.TEXT: "STRING", 445 exp.DataType.Type.TIMESTAMP: "DATETIME", 446 exp.DataType.Type.TIMESTAMPTZ: "TIMESTAMP", 447 exp.DataType.Type.TIMESTAMPLTZ: "TIMESTAMP", 448 exp.DataType.Type.TINYINT: "INT64", 449 exp.DataType.Type.VARBINARY: "BYTES", 450 exp.DataType.Type.VARCHAR: "STRING", 451 exp.DataType.Type.VARIANT: "ANY TYPE", 452 } 453 454 PROPERTIES_LOCATION = { 455 **generator.Generator.PROPERTIES_LOCATION, 456 exp.PartitionedByProperty: exp.Properties.Location.POST_SCHEMA, 457 exp.VolatileProperty: exp.Properties.Location.UNSUPPORTED, 458 } 459 460 # from: https://cloud.google.com/bigquery/docs/reference/standard-sql/lexical#reserved_keywords 461 RESERVED_KEYWORDS = { 462 *generator.Generator.RESERVED_KEYWORDS, 463 "all", 464 "and", 465 "any", 466 "array", 467 "as", 468 "asc", 469 "assert_rows_modified", 470 "at", 471 "between", 472 "by", 473 "case", 474 "cast", 475 "collate", 476 "contains", 477 "create", 478 "cross", 479 "cube", 480 "current", 481 "default", 482 "define", 483 "desc", 484 "distinct", 485 "else", 486 "end", 487 "enum", 488 "escape", 489 "except", 490 "exclude", 491 "exists", 492 "extract", 493 "false", 494 "fetch", 495 "following", 496 "for", 497 "from", 498 "full", 499 "group", 500 "grouping", 501 "groups", 502 "hash", 503 "having", 504 "if", 505 "ignore", 506 "in", 507 "inner", 508 "intersect", 509 "interval", 510 "into", 511 "is", 512 "join", 513 "lateral", 514 "left", 515 "like", 516 "limit", 517 "lookup", 518 "merge", 519 "natural", 520 "new", 521 "no", 522 "not", 523 "null", 524 "nulls", 525 "of", 526 "on", 527 "or", 528 "order", 529 "outer", 530 "over", 531 "partition", 532 "preceding", 533 "proto", 534 "qualify", 535 "range", 536 "recursive", 537 "respect", 538 "right", 539 "rollup", 540 "rows", 541 "select", 542 "set", 543 "some", 544 "struct", 545 "tablesample", 546 "then", 547 "to", 548 "treat", 549 "true", 550 "unbounded", 551 "union", 552 "unnest", 553 "using", 554 "when", 555 "where", 556 "window", 557 "with", 558 "within", 559 } 560 561 def attimezone_sql(self, expression: exp.AtTimeZone) -> str: 562 parent = expression.parent 563 564 # BigQuery allows CAST(.. AS {STRING|TIMESTAMP} [FORMAT <fmt> [AT TIME ZONE <tz>]]). 565 # Only the TIMESTAMP one should use the below conversion, when AT TIME ZONE is included. 566 if not isinstance(parent, exp.Cast) or not parent.to.is_type("text"): 567 return self.func( 568 "TIMESTAMP", self.func("DATETIME", expression.this, expression.args.get("zone")) 569 ) 570 571 return super().attimezone_sql(expression) 572 573 def trycast_sql(self, expression: exp.TryCast) -> str: 574 return self.cast_sql(expression, safe_prefix="SAFE_") 575 576 def cte_sql(self, expression: exp.CTE) -> str: 577 if expression.alias_column_names: 578 self.unsupported("Column names in CTE definition are not supported.") 579 return super().cte_sql(expression) 580 581 def array_sql(self, expression: exp.Array) -> str: 582 first_arg = seq_get(expression.expressions, 0) 583 if isinstance(first_arg, exp.Subqueryable): 584 return f"ARRAY{self.wrap(self.sql(first_arg))}" 585 586 return inline_array_sql(self, expression) 587 588 def transaction_sql(self, *_) -> str: 589 return "BEGIN TRANSACTION" 590 591 def commit_sql(self, *_) -> str: 592 return "COMMIT TRANSACTION" 593 594 def rollback_sql(self, *_) -> str: 595 return "ROLLBACK TRANSACTION" 596 597 def in_unnest_op(self, expression: exp.Unnest) -> str: 598 return self.sql(expression) 599 600 def except_op(self, expression: exp.Except) -> str: 601 if not expression.args.get("distinct", False): 602 self.unsupported("EXCEPT without DISTINCT is not supported in BigQuery") 603 return f"EXCEPT{' DISTINCT' if expression.args.get('distinct') else ' ALL'}" 604 605 def intersect_op(self, expression: exp.Intersect) -> str: 606 if not expression.args.get("distinct", False): 607 self.unsupported("INTERSECT without DISTINCT is not supported in BigQuery") 608 return f"INTERSECT{' DISTINCT' if expression.args.get('distinct') else ' ALL'}" 609 610 def with_properties(self, properties: exp.Properties) -> str: 611 return self.properties(properties, prefix=self.seg("OPTIONS"))
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_sql.<locals>.func>, <class 'sqlglot.expressions.TsOrDsAdd'>: <function _date_add_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.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.InlineLengthColumnConstraint'>: <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.OnCommitProperty'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.OnUpdateColumnConstraint'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.PathColumnConstraint'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.ReturnsProperty'>: <function _returnsproperty_sql>, <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.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.ArraySize'>: <function rename_func.<locals>.<lambda>>, <class 'sqlglot.expressions.Cast'>: <function preprocess.<locals>._to_sql>, <class 'sqlglot.expressions.CTE'>: <function preprocess.<locals>._to_sql>, <class 'sqlglot.expressions.DateSub'>: <function _date_add_sql.<locals>.func>, <class 'sqlglot.expressions.DatetimeAdd'>: <function _date_add_sql.<locals>.func>, <class 'sqlglot.expressions.DatetimeSub'>: <function _date_add_sql.<locals>.func>, <class 'sqlglot.expressions.DateDiff'>: <function BigQuery.Generator.<lambda>>, <class 'sqlglot.expressions.DateStrToDate'>: <function datestrtodate_sql>, <class 'sqlglot.expressions.DateTrunc'>: <function BigQuery.Generator.<lambda>>, <class 'sqlglot.expressions.JSONFormat'>: <function rename_func.<locals>.<lambda>>, <class 'sqlglot.expressions.GenerateSeries'>: <function rename_func.<locals>.<lambda>>, <class 'sqlglot.expressions.GroupConcat'>: <function rename_func.<locals>.<lambda>>, <class 'sqlglot.expressions.ILike'>: <function no_ilike_sql>, <class 'sqlglot.expressions.IntDiv'>: <function rename_func.<locals>.<lambda>>, <class 'sqlglot.expressions.Max'>: <function max_or_greatest>, <class 'sqlglot.expressions.Min'>: <function min_or_least>, <class 'sqlglot.expressions.RegexpExtract'>: <function BigQuery.Generator.<lambda>>, <class 'sqlglot.expressions.RegexpLike'>: <function rename_func.<locals>.<lambda>>, <class 'sqlglot.expressions.Select'>: <function preprocess.<locals>._to_sql>, <class 'sqlglot.expressions.StrToDate'>: <function BigQuery.Generator.<lambda>>, <class 'sqlglot.expressions.StrToTime'>: <function BigQuery.Generator.<lambda>>, <class 'sqlglot.expressions.TimeAdd'>: <function _date_add_sql.<locals>.func>, <class 'sqlglot.expressions.TimeSub'>: <function _date_add_sql.<locals>.func>, <class 'sqlglot.expressions.TimestampAdd'>: <function _date_add_sql.<locals>.func>, <class 'sqlglot.expressions.TimestampSub'>: <function _date_add_sql.<locals>.func>, <class 'sqlglot.expressions.TimeStrToTime'>: <function timestrtotime_sql>, <class 'sqlglot.expressions.TsOrDsToDate'>: <function ts_or_ds_to_date_sql.<locals>._ts_or_ds_to_date_sql>, <class 'sqlglot.expressions.PartitionedByProperty'>: <function BigQuery.Generator.<lambda>>, <class 'sqlglot.expressions.VariancePop'>: <function rename_func.<locals>.<lambda>>, <class 'sqlglot.expressions.Values'>: <function _derived_table_values_to_unnest>, <class 'sqlglot.expressions.Create'>: <function _create_sql>, <class 'sqlglot.expressions.Trim'>: <function BigQuery.Generator.<lambda>>}
TYPE_MAPPING =
{<Type.NCHAR: 'NCHAR'>: 'STRING', <Type.NVARCHAR: 'NVARCHAR'>: 'STRING', <Type.MEDIUMTEXT: 'MEDIUMTEXT'>: 'TEXT', <Type.LONGTEXT: 'LONGTEXT'>: 'TEXT', <Type.MEDIUMBLOB: 'MEDIUMBLOB'>: 'BLOB', <Type.LONGBLOB: 'LONGBLOB'>: '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.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.OnCommitProperty'>: <Location.POST_EXPRESSION: 'POST_EXPRESSION'>, <class 'sqlglot.expressions.Order'>: <Location.POST_SCHEMA: 'POST_SCHEMA'>, <class 'sqlglot.expressions.PartitionedByProperty'>: <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.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.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.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'>}
RESERVED_KEYWORDS =
{'define', 'within', 'set', 'rows', 'qualify', 'inner', 'using', 'any', 'grouping', 'desc', 'treat', 'to', 'unbounded', 'else', 'except', 'new', 'intersect', 'unnest', 'struct', 'range', 'escape', 'exclude', 'groups', 'extract', 'lookup', 'nulls', 'fetch', 'in', 'with', 'collate', 'end', 'limit', 'null', 'if', 'proto', 'cast', 'on', 'contains', 'into', 'order', 'union', 'for', 'hash', 'no', 'enum', 'left', 'asc', 'cube', 'group', 'where', 'case', 'interval', 'rollup', 'some', 'all', 'full', 'create', 'of', 'merge', 'default', 'partition', 'by', 'right', 'respect', 'outer', 'between', 'when', 'false', 'cross', 'preceding', 'ignore', 'join', 'as', 'recursive', 'tablesample', 'not', 'select', 'from', 'exists', 'then', 'array', 'at', 'or', 'window', 'assert_rows_modified', 'over', 'lateral', 'and', 'current', 'like', 'having', 'distinct', 'following', 'is', 'natural', 'true'}
561 def attimezone_sql(self, expression: exp.AtTimeZone) -> str: 562 parent = expression.parent 563 564 # BigQuery allows CAST(.. AS {STRING|TIMESTAMP} [FORMAT <fmt> [AT TIME ZONE <tz>]]). 565 # Only the TIMESTAMP one should use the below conversion, when AT TIME ZONE is included. 566 if not isinstance(parent, exp.Cast) or not parent.to.is_type("text"): 567 return self.func( 568 "TIMESTAMP", self.func("DATETIME", expression.this, expression.args.get("zone")) 569 ) 570 571 return super().attimezone_sql(expression)
@classmethod
def
can_identify(text: str, identify: str | bool = 'safe') -> bool:
246 @classmethod 247 def can_identify(cls, text: str, identify: str | bool = "safe") -> bool: 248 """Checks if text can be identified given an identify option. 249 250 Args: 251 text: The text to check. 252 identify: 253 "always" or `True`: Always returns true. 254 "safe": True if the identifier is case-insensitive. 255 256 Returns: 257 Whether or not the given text can be identified. 258 """ 259 if identify is True or identify == "always": 260 return True 261 262 if identify == "safe": 263 return not cls.case_sensitive(text) 264 265 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.
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
- SELECT_KINDS
- STAR_MAPPING
- TIME_PART_SINGULARS
- TOKEN_MAPPING
- STRUCT_DELIMITER
- PARAMETER_TOKEN
- WITH_SEPARATED_COMMENTS
- UNWRAPPED_INTERVAL_VALUES
- 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
- autoincrementcolumnconstraint_sql
- compresscolumnconstraint_sql
- generatedasidentitycolumnconstraint_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
- datatypesize_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_sql
- likeproperty_sql
- fallbackproperty_sql
- journalproperty_sql
- freespaceproperty_sql
- checksumproperty_sql
- mergeblockratioproperty_sql
- datablocksizeproperty_sql
- blockcompressionproperty_sql
- isolatedloadingproperty_sql
- lockingproperty_sql
- withdataproperty_sql
- insert_sql
- intersect_sql
- introducer_sql
- pseudotype_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
- 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
- jsonobject_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
- 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
- droppartition_sql
- addconstraint_sql
- distinct_sql
- ignorenulls_sql
- respectnulls_sql
- intdiv_sql
- dpipe_sql
- safedpipe_sql
- div_sql
- overlaps_sql
- distance_sql
- dot_sql
- eq_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
- 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