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 166class BigQuery(Dialect): 167 UNNEST_COLUMN_ONLY = True 168 169 # https://cloud.google.com/bigquery/docs/reference/standard-sql/lexical#case_sensitivity 170 RESOLVES_IDENTIFIERS_AS_UPPERCASE = None 171 172 # bigquery udfs are case sensitive 173 NORMALIZE_FUNCTIONS = False 174 175 TIME_MAPPING = { 176 "%D": "%m/%d/%y", 177 } 178 179 FORMAT_MAPPING = { 180 "DD": "%d", 181 "MM": "%m", 182 "MON": "%b", 183 "MONTH": "%B", 184 "YYYY": "%Y", 185 "YY": "%y", 186 "HH": "%I", 187 "HH12": "%I", 188 "HH24": "%H", 189 "MI": "%M", 190 "SS": "%S", 191 "SSSSS": "%f", 192 "TZH": "%z", 193 } 194 195 @classmethod 196 def normalize_identifier(cls, expression: E) -> E: 197 # In BigQuery, CTEs aren't case-sensitive, but table names are (by default, at least). 198 # The following check is essentially a heuristic to detect tables based on whether or 199 # not they're qualified. 200 if isinstance(expression, exp.Identifier): 201 parent = expression.parent 202 203 while isinstance(parent, exp.Dot): 204 parent = parent.parent 205 206 if ( 207 not isinstance(parent, exp.UserDefinedFunction) 208 and not (isinstance(parent, exp.Table) and parent.db) 209 and not expression.meta.get("is_table") 210 ): 211 expression.set("this", expression.this.lower()) 212 213 return expression 214 215 class Tokenizer(tokens.Tokenizer): 216 QUOTES = ["'", '"', '"""', "'''"] 217 COMMENTS = ["--", "#", ("/*", "*/")] 218 IDENTIFIERS = ["`"] 219 STRING_ESCAPES = ["\\"] 220 221 HEX_STRINGS = [("0x", ""), ("0X", "")] 222 223 BYTE_STRINGS = [ 224 (prefix + q, q) for q in t.cast(t.List[str], QUOTES) for prefix in ("b", "B") 225 ] 226 227 RAW_STRINGS = [ 228 (prefix + q, q) for q in t.cast(t.List[str], QUOTES) for prefix in ("r", "R") 229 ] 230 231 KEYWORDS = { 232 **tokens.Tokenizer.KEYWORDS, 233 "ANY TYPE": TokenType.VARIANT, 234 "BEGIN": TokenType.COMMAND, 235 "BEGIN TRANSACTION": TokenType.BEGIN, 236 "CURRENT_DATETIME": TokenType.CURRENT_DATETIME, 237 "BYTES": TokenType.BINARY, 238 "DECLARE": TokenType.COMMAND, 239 "FLOAT64": TokenType.DOUBLE, 240 "INT64": TokenType.BIGINT, 241 "RECORD": TokenType.STRUCT, 242 "TIMESTAMP": TokenType.TIMESTAMPTZ, 243 "NOT DETERMINISTIC": TokenType.VOLATILE, 244 "UNKNOWN": TokenType.NULL, 245 } 246 KEYWORDS.pop("DIV") 247 248 class Parser(parser.Parser): 249 PREFIXED_PIVOT_COLUMNS = True 250 251 LOG_BASE_FIRST = False 252 LOG_DEFAULTS_TO_LN = True 253 254 FUNCTIONS = { 255 **parser.Parser.FUNCTIONS, 256 "DATE_ADD": parse_date_delta_with_interval(exp.DateAdd), 257 "DATE_SUB": parse_date_delta_with_interval(exp.DateSub), 258 "DATE_TRUNC": lambda args: exp.DateTrunc( 259 unit=exp.Literal.string(str(seq_get(args, 1))), 260 this=seq_get(args, 0), 261 ), 262 "DATETIME_ADD": parse_date_delta_with_interval(exp.DatetimeAdd), 263 "DATETIME_SUB": parse_date_delta_with_interval(exp.DatetimeSub), 264 "DIV": lambda args: exp.IntDiv(this=seq_get(args, 0), expression=seq_get(args, 1)), 265 "GENERATE_ARRAY": exp.GenerateSeries.from_arg_list, 266 "PARSE_DATE": lambda args: format_time_lambda(exp.StrToDate, "bigquery")( 267 [seq_get(args, 1), seq_get(args, 0)] 268 ), 269 "PARSE_TIMESTAMP": lambda args: format_time_lambda(exp.StrToTime, "bigquery")( 270 [seq_get(args, 1), seq_get(args, 0)] 271 ), 272 "REGEXP_CONTAINS": exp.RegexpLike.from_arg_list, 273 "REGEXP_EXTRACT": lambda args: exp.RegexpExtract( 274 this=seq_get(args, 0), 275 expression=seq_get(args, 1), 276 position=seq_get(args, 2), 277 occurrence=seq_get(args, 3), 278 group=exp.Literal.number(1) 279 if re.compile(str(seq_get(args, 1))).groups == 1 280 else None, 281 ), 282 "SPLIT": lambda args: exp.Split( 283 # https://cloud.google.com/bigquery/docs/reference/standard-sql/string_functions#split 284 this=seq_get(args, 0), 285 expression=seq_get(args, 1) or exp.Literal.string(","), 286 ), 287 "TIME_ADD": parse_date_delta_with_interval(exp.TimeAdd), 288 "TIME_SUB": parse_date_delta_with_interval(exp.TimeSub), 289 "TIMESTAMP_ADD": parse_date_delta_with_interval(exp.TimestampAdd), 290 "TIMESTAMP_SUB": parse_date_delta_with_interval(exp.TimestampSub), 291 "TO_JSON_STRING": exp.JSONFormat.from_arg_list, 292 } 293 294 FUNCTION_PARSERS = { 295 **parser.Parser.FUNCTION_PARSERS, 296 "ARRAY": lambda self: self.expression(exp.Array, expressions=[self._parse_statement()]), 297 } 298 FUNCTION_PARSERS.pop("TRIM") 299 300 NO_PAREN_FUNCTIONS = { 301 **parser.Parser.NO_PAREN_FUNCTIONS, 302 TokenType.CURRENT_DATETIME: exp.CurrentDatetime, 303 } 304 305 NESTED_TYPE_TOKENS = { 306 *parser.Parser.NESTED_TYPE_TOKENS, 307 TokenType.TABLE, 308 } 309 310 ID_VAR_TOKENS = { 311 *parser.Parser.ID_VAR_TOKENS, 312 TokenType.VALUES, 313 } 314 315 PROPERTY_PARSERS = { 316 **parser.Parser.PROPERTY_PARSERS, 317 "NOT DETERMINISTIC": lambda self: self.expression( 318 exp.StabilityProperty, this=exp.Literal.string("VOLATILE") 319 ), 320 "OPTIONS": lambda self: self._parse_with_property(), 321 } 322 323 CONSTRAINT_PARSERS = { 324 **parser.Parser.CONSTRAINT_PARSERS, 325 "OPTIONS": lambda self: exp.Properties(expressions=self._parse_with_property()), 326 } 327 328 def _parse_table_part(self, schema: bool = False) -> t.Optional[exp.Expression]: 329 this = super()._parse_table_part(schema=schema) 330 331 # https://cloud.google.com/bigquery/docs/reference/standard-sql/lexical#table_names 332 if isinstance(this, exp.Identifier): 333 table_name = this.name 334 while self._match(TokenType.DASH, advance=False) and self._next: 335 self._advance(2) 336 table_name += f"-{self._prev.text}" 337 338 this = exp.Identifier(this=table_name, quoted=this.args.get("quoted")) 339 340 return this 341 342 def _parse_table_parts(self, schema: bool = False) -> exp.Table: 343 table = super()._parse_table_parts(schema=schema) 344 if isinstance(table.this, exp.Identifier) and "." in table.name: 345 catalog, db, this, *rest = ( 346 t.cast(t.Optional[exp.Expression], exp.to_identifier(x)) 347 for x in split_num_words(table.name, ".", 3) 348 ) 349 350 if rest and this: 351 this = exp.Dot.build(t.cast(t.List[exp.Expression], [this, *rest])) 352 353 table = exp.Table(this=this, db=db, catalog=catalog) 354 355 return table 356 357 class Generator(generator.Generator): 358 EXPLICIT_UNION = True 359 INTERVAL_ALLOWS_PLURAL_FORM = False 360 JOIN_HINTS = False 361 TABLE_HINTS = False 362 LIMIT_FETCH = "LIMIT" 363 RENAME_TABLE_WITH_DB = False 364 ESCAPE_LINE_BREAK = True 365 366 TRANSFORMS = { 367 **generator.Generator.TRANSFORMS, 368 exp.ApproxDistinct: rename_func("APPROX_COUNT_DISTINCT"), 369 exp.ArraySize: rename_func("ARRAY_LENGTH"), 370 exp.Cast: transforms.preprocess([transforms.remove_precision_parameterized_types]), 371 exp.CTE: transforms.preprocess([_pushdown_cte_column_names]), 372 exp.DateAdd: _date_add_sql("DATE", "ADD"), 373 exp.DateSub: _date_add_sql("DATE", "SUB"), 374 exp.DatetimeAdd: _date_add_sql("DATETIME", "ADD"), 375 exp.DatetimeSub: _date_add_sql("DATETIME", "SUB"), 376 exp.DateDiff: lambda self, e: f"DATE_DIFF({self.sql(e, 'this')}, {self.sql(e, 'expression')}, {self.sql(e.args.get('unit', 'DAY'))})", 377 exp.DateStrToDate: datestrtodate_sql, 378 exp.DateTrunc: lambda self, e: self.func("DATE_TRUNC", e.this, e.text("unit")), 379 exp.JSONFormat: rename_func("TO_JSON_STRING"), 380 exp.GenerateSeries: rename_func("GENERATE_ARRAY"), 381 exp.GroupConcat: rename_func("STRING_AGG"), 382 exp.ILike: no_ilike_sql, 383 exp.IntDiv: rename_func("DIV"), 384 exp.Max: max_or_greatest, 385 exp.Min: min_or_least, 386 exp.RegexpExtract: lambda self, e: self.func( 387 "REGEXP_EXTRACT", 388 e.this, 389 e.expression, 390 e.args.get("position"), 391 e.args.get("occurrence"), 392 ), 393 exp.RegexpLike: rename_func("REGEXP_CONTAINS"), 394 exp.Select: transforms.preprocess( 395 [ 396 transforms.explode_to_unnest, 397 _unqualify_unnest, 398 transforms.eliminate_distinct_on, 399 _alias_ordered_group, 400 ] 401 ), 402 exp.StrToDate: lambda self, e: f"PARSE_DATE({self.format_time(e)}, {self.sql(e, 'this')})", 403 exp.StrToTime: lambda self, e: f"PARSE_TIMESTAMP({self.format_time(e)}, {self.sql(e, 'this')})", 404 exp.TimeAdd: _date_add_sql("TIME", "ADD"), 405 exp.TimeSub: _date_add_sql("TIME", "SUB"), 406 exp.TimestampAdd: _date_add_sql("TIMESTAMP", "ADD"), 407 exp.TimestampSub: _date_add_sql("TIMESTAMP", "SUB"), 408 exp.TimeStrToTime: timestrtotime_sql, 409 exp.TsOrDsToDate: ts_or_ds_to_date_sql("bigquery"), 410 exp.TsOrDsAdd: _date_add_sql("DATE", "ADD"), 411 exp.PartitionedByProperty: lambda self, e: f"PARTITION BY {self.sql(e, 'this')}", 412 exp.VariancePop: rename_func("VAR_POP"), 413 exp.Values: _derived_table_values_to_unnest, 414 exp.ReturnsProperty: _returnsproperty_sql, 415 exp.Create: _create_sql, 416 exp.Trim: lambda self, e: self.func(f"TRIM", e.this, e.expression), 417 exp.StabilityProperty: lambda self, e: f"DETERMINISTIC" 418 if e.name == "IMMUTABLE" 419 else "NOT DETERMINISTIC", 420 } 421 422 TYPE_MAPPING = { 423 **generator.Generator.TYPE_MAPPING, 424 exp.DataType.Type.BIGDECIMAL: "BIGNUMERIC", 425 exp.DataType.Type.BIGINT: "INT64", 426 exp.DataType.Type.BINARY: "BYTES", 427 exp.DataType.Type.BOOLEAN: "BOOL", 428 exp.DataType.Type.CHAR: "STRING", 429 exp.DataType.Type.DECIMAL: "NUMERIC", 430 exp.DataType.Type.DOUBLE: "FLOAT64", 431 exp.DataType.Type.FLOAT: "FLOAT64", 432 exp.DataType.Type.INT: "INT64", 433 exp.DataType.Type.NCHAR: "STRING", 434 exp.DataType.Type.NVARCHAR: "STRING", 435 exp.DataType.Type.SMALLINT: "INT64", 436 exp.DataType.Type.TEXT: "STRING", 437 exp.DataType.Type.TIMESTAMP: "DATETIME", 438 exp.DataType.Type.TIMESTAMPTZ: "TIMESTAMP", 439 exp.DataType.Type.TIMESTAMPLTZ: "TIMESTAMP", 440 exp.DataType.Type.TINYINT: "INT64", 441 exp.DataType.Type.VARBINARY: "BYTES", 442 exp.DataType.Type.VARCHAR: "STRING", 443 exp.DataType.Type.VARIANT: "ANY TYPE", 444 } 445 446 PROPERTIES_LOCATION = { 447 **generator.Generator.PROPERTIES_LOCATION, 448 exp.PartitionedByProperty: exp.Properties.Location.POST_SCHEMA, 449 exp.VolatileProperty: exp.Properties.Location.UNSUPPORTED, 450 } 451 452 # from: https://cloud.google.com/bigquery/docs/reference/standard-sql/lexical#reserved_keywords 453 RESERVED_KEYWORDS = { 454 *generator.Generator.RESERVED_KEYWORDS, 455 "all", 456 "and", 457 "any", 458 "array", 459 "as", 460 "asc", 461 "assert_rows_modified", 462 "at", 463 "between", 464 "by", 465 "case", 466 "cast", 467 "collate", 468 "contains", 469 "create", 470 "cross", 471 "cube", 472 "current", 473 "default", 474 "define", 475 "desc", 476 "distinct", 477 "else", 478 "end", 479 "enum", 480 "escape", 481 "except", 482 "exclude", 483 "exists", 484 "extract", 485 "false", 486 "fetch", 487 "following", 488 "for", 489 "from", 490 "full", 491 "group", 492 "grouping", 493 "groups", 494 "hash", 495 "having", 496 "if", 497 "ignore", 498 "in", 499 "inner", 500 "intersect", 501 "interval", 502 "into", 503 "is", 504 "join", 505 "lateral", 506 "left", 507 "like", 508 "limit", 509 "lookup", 510 "merge", 511 "natural", 512 "new", 513 "no", 514 "not", 515 "null", 516 "nulls", 517 "of", 518 "on", 519 "or", 520 "order", 521 "outer", 522 "over", 523 "partition", 524 "preceding", 525 "proto", 526 "qualify", 527 "range", 528 "recursive", 529 "respect", 530 "right", 531 "rollup", 532 "rows", 533 "select", 534 "set", 535 "some", 536 "struct", 537 "tablesample", 538 "then", 539 "to", 540 "treat", 541 "true", 542 "unbounded", 543 "union", 544 "unnest", 545 "using", 546 "when", 547 "where", 548 "window", 549 "with", 550 "within", 551 } 552 553 def attimezone_sql(self, expression: exp.AtTimeZone) -> str: 554 if not isinstance(expression.parent, exp.Cast): 555 return self.func( 556 "TIMESTAMP", self.func("DATETIME", expression.this, expression.args.get("zone")) 557 ) 558 return super().attimezone_sql(expression) 559 560 def trycast_sql(self, expression: exp.TryCast) -> str: 561 return self.cast_sql(expression, safe_prefix="SAFE_") 562 563 def cte_sql(self, expression: exp.CTE) -> str: 564 if expression.alias_column_names: 565 self.unsupported("Column names in CTE definition are not supported.") 566 return super().cte_sql(expression) 567 568 def array_sql(self, expression: exp.Array) -> str: 569 first_arg = seq_get(expression.expressions, 0) 570 if isinstance(first_arg, exp.Subqueryable): 571 return f"ARRAY{self.wrap(self.sql(first_arg))}" 572 573 return inline_array_sql(self, expression) 574 575 def transaction_sql(self, *_) -> str: 576 return "BEGIN TRANSACTION" 577 578 def commit_sql(self, *_) -> str: 579 return "COMMIT TRANSACTION" 580 581 def rollback_sql(self, *_) -> str: 582 return "ROLLBACK TRANSACTION" 583 584 def in_unnest_op(self, expression: exp.Unnest) -> str: 585 return self.sql(expression) 586 587 def except_op(self, expression: exp.Except) -> str: 588 if not expression.args.get("distinct", False): 589 self.unsupported("EXCEPT without DISTINCT is not supported in BigQuery") 590 return f"EXCEPT{' DISTINCT' if expression.args.get('distinct') else ' ALL'}" 591 592 def intersect_op(self, expression: exp.Intersect) -> str: 593 if not expression.args.get("distinct", False): 594 self.unsupported("INTERSECT without DISTINCT is not supported in BigQuery") 595 return f"INTERSECT{' DISTINCT' if expression.args.get('distinct') else ' ALL'}" 596 597 def with_properties(self, properties: exp.Properties) -> str: 598 return self.properties(properties, prefix=self.seg("OPTIONS"))
logger =
<Logger sqlglot (WARNING)>
167class BigQuery(Dialect): 168 UNNEST_COLUMN_ONLY = True 169 170 # https://cloud.google.com/bigquery/docs/reference/standard-sql/lexical#case_sensitivity 171 RESOLVES_IDENTIFIERS_AS_UPPERCASE = None 172 173 # bigquery udfs are case sensitive 174 NORMALIZE_FUNCTIONS = False 175 176 TIME_MAPPING = { 177 "%D": "%m/%d/%y", 178 } 179 180 FORMAT_MAPPING = { 181 "DD": "%d", 182 "MM": "%m", 183 "MON": "%b", 184 "MONTH": "%B", 185 "YYYY": "%Y", 186 "YY": "%y", 187 "HH": "%I", 188 "HH12": "%I", 189 "HH24": "%H", 190 "MI": "%M", 191 "SS": "%S", 192 "SSSSS": "%f", 193 "TZH": "%z", 194 } 195 196 @classmethod 197 def normalize_identifier(cls, expression: E) -> E: 198 # In BigQuery, CTEs aren't case-sensitive, but table names are (by default, at least). 199 # The following check is essentially a heuristic to detect tables based on whether or 200 # not they're qualified. 201 if isinstance(expression, exp.Identifier): 202 parent = expression.parent 203 204 while isinstance(parent, exp.Dot): 205 parent = parent.parent 206 207 if ( 208 not isinstance(parent, exp.UserDefinedFunction) 209 and not (isinstance(parent, exp.Table) and parent.db) 210 and not expression.meta.get("is_table") 211 ): 212 expression.set("this", expression.this.lower()) 213 214 return expression 215 216 class Tokenizer(tokens.Tokenizer): 217 QUOTES = ["'", '"', '"""', "'''"] 218 COMMENTS = ["--", "#", ("/*", "*/")] 219 IDENTIFIERS = ["`"] 220 STRING_ESCAPES = ["\\"] 221 222 HEX_STRINGS = [("0x", ""), ("0X", "")] 223 224 BYTE_STRINGS = [ 225 (prefix + q, q) for q in t.cast(t.List[str], QUOTES) for prefix in ("b", "B") 226 ] 227 228 RAW_STRINGS = [ 229 (prefix + q, q) for q in t.cast(t.List[str], QUOTES) for prefix in ("r", "R") 230 ] 231 232 KEYWORDS = { 233 **tokens.Tokenizer.KEYWORDS, 234 "ANY TYPE": TokenType.VARIANT, 235 "BEGIN": TokenType.COMMAND, 236 "BEGIN TRANSACTION": TokenType.BEGIN, 237 "CURRENT_DATETIME": TokenType.CURRENT_DATETIME, 238 "BYTES": TokenType.BINARY, 239 "DECLARE": TokenType.COMMAND, 240 "FLOAT64": TokenType.DOUBLE, 241 "INT64": TokenType.BIGINT, 242 "RECORD": TokenType.STRUCT, 243 "TIMESTAMP": TokenType.TIMESTAMPTZ, 244 "NOT DETERMINISTIC": TokenType.VOLATILE, 245 "UNKNOWN": TokenType.NULL, 246 } 247 KEYWORDS.pop("DIV") 248 249 class Parser(parser.Parser): 250 PREFIXED_PIVOT_COLUMNS = True 251 252 LOG_BASE_FIRST = False 253 LOG_DEFAULTS_TO_LN = True 254 255 FUNCTIONS = { 256 **parser.Parser.FUNCTIONS, 257 "DATE_ADD": parse_date_delta_with_interval(exp.DateAdd), 258 "DATE_SUB": parse_date_delta_with_interval(exp.DateSub), 259 "DATE_TRUNC": lambda args: exp.DateTrunc( 260 unit=exp.Literal.string(str(seq_get(args, 1))), 261 this=seq_get(args, 0), 262 ), 263 "DATETIME_ADD": parse_date_delta_with_interval(exp.DatetimeAdd), 264 "DATETIME_SUB": parse_date_delta_with_interval(exp.DatetimeSub), 265 "DIV": lambda args: exp.IntDiv(this=seq_get(args, 0), expression=seq_get(args, 1)), 266 "GENERATE_ARRAY": exp.GenerateSeries.from_arg_list, 267 "PARSE_DATE": lambda args: format_time_lambda(exp.StrToDate, "bigquery")( 268 [seq_get(args, 1), seq_get(args, 0)] 269 ), 270 "PARSE_TIMESTAMP": lambda args: format_time_lambda(exp.StrToTime, "bigquery")( 271 [seq_get(args, 1), seq_get(args, 0)] 272 ), 273 "REGEXP_CONTAINS": exp.RegexpLike.from_arg_list, 274 "REGEXP_EXTRACT": lambda args: exp.RegexpExtract( 275 this=seq_get(args, 0), 276 expression=seq_get(args, 1), 277 position=seq_get(args, 2), 278 occurrence=seq_get(args, 3), 279 group=exp.Literal.number(1) 280 if re.compile(str(seq_get(args, 1))).groups == 1 281 else None, 282 ), 283 "SPLIT": lambda args: exp.Split( 284 # https://cloud.google.com/bigquery/docs/reference/standard-sql/string_functions#split 285 this=seq_get(args, 0), 286 expression=seq_get(args, 1) or exp.Literal.string(","), 287 ), 288 "TIME_ADD": parse_date_delta_with_interval(exp.TimeAdd), 289 "TIME_SUB": parse_date_delta_with_interval(exp.TimeSub), 290 "TIMESTAMP_ADD": parse_date_delta_with_interval(exp.TimestampAdd), 291 "TIMESTAMP_SUB": parse_date_delta_with_interval(exp.TimestampSub), 292 "TO_JSON_STRING": exp.JSONFormat.from_arg_list, 293 } 294 295 FUNCTION_PARSERS = { 296 **parser.Parser.FUNCTION_PARSERS, 297 "ARRAY": lambda self: self.expression(exp.Array, expressions=[self._parse_statement()]), 298 } 299 FUNCTION_PARSERS.pop("TRIM") 300 301 NO_PAREN_FUNCTIONS = { 302 **parser.Parser.NO_PAREN_FUNCTIONS, 303 TokenType.CURRENT_DATETIME: exp.CurrentDatetime, 304 } 305 306 NESTED_TYPE_TOKENS = { 307 *parser.Parser.NESTED_TYPE_TOKENS, 308 TokenType.TABLE, 309 } 310 311 ID_VAR_TOKENS = { 312 *parser.Parser.ID_VAR_TOKENS, 313 TokenType.VALUES, 314 } 315 316 PROPERTY_PARSERS = { 317 **parser.Parser.PROPERTY_PARSERS, 318 "NOT DETERMINISTIC": lambda self: self.expression( 319 exp.StabilityProperty, this=exp.Literal.string("VOLATILE") 320 ), 321 "OPTIONS": lambda self: self._parse_with_property(), 322 } 323 324 CONSTRAINT_PARSERS = { 325 **parser.Parser.CONSTRAINT_PARSERS, 326 "OPTIONS": lambda self: exp.Properties(expressions=self._parse_with_property()), 327 } 328 329 def _parse_table_part(self, schema: bool = False) -> t.Optional[exp.Expression]: 330 this = super()._parse_table_part(schema=schema) 331 332 # https://cloud.google.com/bigquery/docs/reference/standard-sql/lexical#table_names 333 if isinstance(this, exp.Identifier): 334 table_name = this.name 335 while self._match(TokenType.DASH, advance=False) and self._next: 336 self._advance(2) 337 table_name += f"-{self._prev.text}" 338 339 this = exp.Identifier(this=table_name, quoted=this.args.get("quoted")) 340 341 return this 342 343 def _parse_table_parts(self, schema: bool = False) -> exp.Table: 344 table = super()._parse_table_parts(schema=schema) 345 if isinstance(table.this, exp.Identifier) and "." in table.name: 346 catalog, db, this, *rest = ( 347 t.cast(t.Optional[exp.Expression], exp.to_identifier(x)) 348 for x in split_num_words(table.name, ".", 3) 349 ) 350 351 if rest and this: 352 this = exp.Dot.build(t.cast(t.List[exp.Expression], [this, *rest])) 353 354 table = exp.Table(this=this, db=db, catalog=catalog) 355 356 return table 357 358 class Generator(generator.Generator): 359 EXPLICIT_UNION = True 360 INTERVAL_ALLOWS_PLURAL_FORM = False 361 JOIN_HINTS = False 362 TABLE_HINTS = False 363 LIMIT_FETCH = "LIMIT" 364 RENAME_TABLE_WITH_DB = False 365 ESCAPE_LINE_BREAK = True 366 367 TRANSFORMS = { 368 **generator.Generator.TRANSFORMS, 369 exp.ApproxDistinct: rename_func("APPROX_COUNT_DISTINCT"), 370 exp.ArraySize: rename_func("ARRAY_LENGTH"), 371 exp.Cast: transforms.preprocess([transforms.remove_precision_parameterized_types]), 372 exp.CTE: transforms.preprocess([_pushdown_cte_column_names]), 373 exp.DateAdd: _date_add_sql("DATE", "ADD"), 374 exp.DateSub: _date_add_sql("DATE", "SUB"), 375 exp.DatetimeAdd: _date_add_sql("DATETIME", "ADD"), 376 exp.DatetimeSub: _date_add_sql("DATETIME", "SUB"), 377 exp.DateDiff: lambda self, e: f"DATE_DIFF({self.sql(e, 'this')}, {self.sql(e, 'expression')}, {self.sql(e.args.get('unit', 'DAY'))})", 378 exp.DateStrToDate: datestrtodate_sql, 379 exp.DateTrunc: lambda self, e: self.func("DATE_TRUNC", e.this, e.text("unit")), 380 exp.JSONFormat: rename_func("TO_JSON_STRING"), 381 exp.GenerateSeries: rename_func("GENERATE_ARRAY"), 382 exp.GroupConcat: rename_func("STRING_AGG"), 383 exp.ILike: no_ilike_sql, 384 exp.IntDiv: rename_func("DIV"), 385 exp.Max: max_or_greatest, 386 exp.Min: min_or_least, 387 exp.RegexpExtract: lambda self, e: self.func( 388 "REGEXP_EXTRACT", 389 e.this, 390 e.expression, 391 e.args.get("position"), 392 e.args.get("occurrence"), 393 ), 394 exp.RegexpLike: rename_func("REGEXP_CONTAINS"), 395 exp.Select: transforms.preprocess( 396 [ 397 transforms.explode_to_unnest, 398 _unqualify_unnest, 399 transforms.eliminate_distinct_on, 400 _alias_ordered_group, 401 ] 402 ), 403 exp.StrToDate: lambda self, e: f"PARSE_DATE({self.format_time(e)}, {self.sql(e, 'this')})", 404 exp.StrToTime: lambda self, e: f"PARSE_TIMESTAMP({self.format_time(e)}, {self.sql(e, 'this')})", 405 exp.TimeAdd: _date_add_sql("TIME", "ADD"), 406 exp.TimeSub: _date_add_sql("TIME", "SUB"), 407 exp.TimestampAdd: _date_add_sql("TIMESTAMP", "ADD"), 408 exp.TimestampSub: _date_add_sql("TIMESTAMP", "SUB"), 409 exp.TimeStrToTime: timestrtotime_sql, 410 exp.TsOrDsToDate: ts_or_ds_to_date_sql("bigquery"), 411 exp.TsOrDsAdd: _date_add_sql("DATE", "ADD"), 412 exp.PartitionedByProperty: lambda self, e: f"PARTITION BY {self.sql(e, 'this')}", 413 exp.VariancePop: rename_func("VAR_POP"), 414 exp.Values: _derived_table_values_to_unnest, 415 exp.ReturnsProperty: _returnsproperty_sql, 416 exp.Create: _create_sql, 417 exp.Trim: lambda self, e: self.func(f"TRIM", e.this, e.expression), 418 exp.StabilityProperty: lambda self, e: f"DETERMINISTIC" 419 if e.name == "IMMUTABLE" 420 else "NOT DETERMINISTIC", 421 } 422 423 TYPE_MAPPING = { 424 **generator.Generator.TYPE_MAPPING, 425 exp.DataType.Type.BIGDECIMAL: "BIGNUMERIC", 426 exp.DataType.Type.BIGINT: "INT64", 427 exp.DataType.Type.BINARY: "BYTES", 428 exp.DataType.Type.BOOLEAN: "BOOL", 429 exp.DataType.Type.CHAR: "STRING", 430 exp.DataType.Type.DECIMAL: "NUMERIC", 431 exp.DataType.Type.DOUBLE: "FLOAT64", 432 exp.DataType.Type.FLOAT: "FLOAT64", 433 exp.DataType.Type.INT: "INT64", 434 exp.DataType.Type.NCHAR: "STRING", 435 exp.DataType.Type.NVARCHAR: "STRING", 436 exp.DataType.Type.SMALLINT: "INT64", 437 exp.DataType.Type.TEXT: "STRING", 438 exp.DataType.Type.TIMESTAMP: "DATETIME", 439 exp.DataType.Type.TIMESTAMPTZ: "TIMESTAMP", 440 exp.DataType.Type.TIMESTAMPLTZ: "TIMESTAMP", 441 exp.DataType.Type.TINYINT: "INT64", 442 exp.DataType.Type.VARBINARY: "BYTES", 443 exp.DataType.Type.VARCHAR: "STRING", 444 exp.DataType.Type.VARIANT: "ANY TYPE", 445 } 446 447 PROPERTIES_LOCATION = { 448 **generator.Generator.PROPERTIES_LOCATION, 449 exp.PartitionedByProperty: exp.Properties.Location.POST_SCHEMA, 450 exp.VolatileProperty: exp.Properties.Location.UNSUPPORTED, 451 } 452 453 # from: https://cloud.google.com/bigquery/docs/reference/standard-sql/lexical#reserved_keywords 454 RESERVED_KEYWORDS = { 455 *generator.Generator.RESERVED_KEYWORDS, 456 "all", 457 "and", 458 "any", 459 "array", 460 "as", 461 "asc", 462 "assert_rows_modified", 463 "at", 464 "between", 465 "by", 466 "case", 467 "cast", 468 "collate", 469 "contains", 470 "create", 471 "cross", 472 "cube", 473 "current", 474 "default", 475 "define", 476 "desc", 477 "distinct", 478 "else", 479 "end", 480 "enum", 481 "escape", 482 "except", 483 "exclude", 484 "exists", 485 "extract", 486 "false", 487 "fetch", 488 "following", 489 "for", 490 "from", 491 "full", 492 "group", 493 "grouping", 494 "groups", 495 "hash", 496 "having", 497 "if", 498 "ignore", 499 "in", 500 "inner", 501 "intersect", 502 "interval", 503 "into", 504 "is", 505 "join", 506 "lateral", 507 "left", 508 "like", 509 "limit", 510 "lookup", 511 "merge", 512 "natural", 513 "new", 514 "no", 515 "not", 516 "null", 517 "nulls", 518 "of", 519 "on", 520 "or", 521 "order", 522 "outer", 523 "over", 524 "partition", 525 "preceding", 526 "proto", 527 "qualify", 528 "range", 529 "recursive", 530 "respect", 531 "right", 532 "rollup", 533 "rows", 534 "select", 535 "set", 536 "some", 537 "struct", 538 "tablesample", 539 "then", 540 "to", 541 "treat", 542 "true", 543 "unbounded", 544 "union", 545 "unnest", 546 "using", 547 "when", 548 "where", 549 "window", 550 "with", 551 "within", 552 } 553 554 def attimezone_sql(self, expression: exp.AtTimeZone) -> str: 555 if not isinstance(expression.parent, exp.Cast): 556 return self.func( 557 "TIMESTAMP", self.func("DATETIME", expression.this, expression.args.get("zone")) 558 ) 559 return super().attimezone_sql(expression) 560 561 def trycast_sql(self, expression: exp.TryCast) -> str: 562 return self.cast_sql(expression, safe_prefix="SAFE_") 563 564 def cte_sql(self, expression: exp.CTE) -> str: 565 if expression.alias_column_names: 566 self.unsupported("Column names in CTE definition are not supported.") 567 return super().cte_sql(expression) 568 569 def array_sql(self, expression: exp.Array) -> str: 570 first_arg = seq_get(expression.expressions, 0) 571 if isinstance(first_arg, exp.Subqueryable): 572 return f"ARRAY{self.wrap(self.sql(first_arg))}" 573 574 return inline_array_sql(self, expression) 575 576 def transaction_sql(self, *_) -> str: 577 return "BEGIN TRANSACTION" 578 579 def commit_sql(self, *_) -> str: 580 return "COMMIT TRANSACTION" 581 582 def rollback_sql(self, *_) -> str: 583 return "ROLLBACK TRANSACTION" 584 585 def in_unnest_op(self, expression: exp.Unnest) -> str: 586 return self.sql(expression) 587 588 def except_op(self, expression: exp.Except) -> str: 589 if not expression.args.get("distinct", False): 590 self.unsupported("EXCEPT without DISTINCT is not supported in BigQuery") 591 return f"EXCEPT{' DISTINCT' if expression.args.get('distinct') else ' ALL'}" 592 593 def intersect_op(self, expression: exp.Intersect) -> str: 594 if not expression.args.get("distinct", False): 595 self.unsupported("INTERSECT without DISTINCT is not supported in BigQuery") 596 return f"INTERSECT{' DISTINCT' if expression.args.get('distinct') else ' ALL'}" 597 598 def with_properties(self, properties: exp.Properties) -> str: 599 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:
196 @classmethod 197 def normalize_identifier(cls, expression: E) -> E: 198 # In BigQuery, CTEs aren't case-sensitive, but table names are (by default, at least). 199 # The following check is essentially a heuristic to detect tables based on whether or 200 # not they're qualified. 201 if isinstance(expression, exp.Identifier): 202 parent = expression.parent 203 204 while isinstance(parent, exp.Dot): 205 parent = parent.parent 206 207 if ( 208 not isinstance(parent, exp.UserDefinedFunction) 209 and not (isinstance(parent, exp.Table) and parent.db) 210 and not expression.meta.get("is_table") 211 ): 212 expression.set("this", expression.this.lower()) 213 214 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
216 class Tokenizer(tokens.Tokenizer): 217 QUOTES = ["'", '"', '"""', "'''"] 218 COMMENTS = ["--", "#", ("/*", "*/")] 219 IDENTIFIERS = ["`"] 220 STRING_ESCAPES = ["\\"] 221 222 HEX_STRINGS = [("0x", ""), ("0X", "")] 223 224 BYTE_STRINGS = [ 225 (prefix + q, q) for q in t.cast(t.List[str], QUOTES) for prefix in ("b", "B") 226 ] 227 228 RAW_STRINGS = [ 229 (prefix + q, q) for q in t.cast(t.List[str], QUOTES) for prefix in ("r", "R") 230 ] 231 232 KEYWORDS = { 233 **tokens.Tokenizer.KEYWORDS, 234 "ANY TYPE": TokenType.VARIANT, 235 "BEGIN": TokenType.COMMAND, 236 "BEGIN TRANSACTION": TokenType.BEGIN, 237 "CURRENT_DATETIME": TokenType.CURRENT_DATETIME, 238 "BYTES": TokenType.BINARY, 239 "DECLARE": TokenType.COMMAND, 240 "FLOAT64": TokenType.DOUBLE, 241 "INT64": TokenType.BIGINT, 242 "RECORD": TokenType.STRUCT, 243 "TIMESTAMP": TokenType.TIMESTAMPTZ, 244 "NOT DETERMINISTIC": TokenType.VOLATILE, 245 "UNKNOWN": TokenType.NULL, 246 } 247 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'>}
249 class Parser(parser.Parser): 250 PREFIXED_PIVOT_COLUMNS = True 251 252 LOG_BASE_FIRST = False 253 LOG_DEFAULTS_TO_LN = True 254 255 FUNCTIONS = { 256 **parser.Parser.FUNCTIONS, 257 "DATE_ADD": parse_date_delta_with_interval(exp.DateAdd), 258 "DATE_SUB": parse_date_delta_with_interval(exp.DateSub), 259 "DATE_TRUNC": lambda args: exp.DateTrunc( 260 unit=exp.Literal.string(str(seq_get(args, 1))), 261 this=seq_get(args, 0), 262 ), 263 "DATETIME_ADD": parse_date_delta_with_interval(exp.DatetimeAdd), 264 "DATETIME_SUB": parse_date_delta_with_interval(exp.DatetimeSub), 265 "DIV": lambda args: exp.IntDiv(this=seq_get(args, 0), expression=seq_get(args, 1)), 266 "GENERATE_ARRAY": exp.GenerateSeries.from_arg_list, 267 "PARSE_DATE": lambda args: format_time_lambda(exp.StrToDate, "bigquery")( 268 [seq_get(args, 1), seq_get(args, 0)] 269 ), 270 "PARSE_TIMESTAMP": lambda args: format_time_lambda(exp.StrToTime, "bigquery")( 271 [seq_get(args, 1), seq_get(args, 0)] 272 ), 273 "REGEXP_CONTAINS": exp.RegexpLike.from_arg_list, 274 "REGEXP_EXTRACT": lambda args: exp.RegexpExtract( 275 this=seq_get(args, 0), 276 expression=seq_get(args, 1), 277 position=seq_get(args, 2), 278 occurrence=seq_get(args, 3), 279 group=exp.Literal.number(1) 280 if re.compile(str(seq_get(args, 1))).groups == 1 281 else None, 282 ), 283 "SPLIT": lambda args: exp.Split( 284 # https://cloud.google.com/bigquery/docs/reference/standard-sql/string_functions#split 285 this=seq_get(args, 0), 286 expression=seq_get(args, 1) or exp.Literal.string(","), 287 ), 288 "TIME_ADD": parse_date_delta_with_interval(exp.TimeAdd), 289 "TIME_SUB": parse_date_delta_with_interval(exp.TimeSub), 290 "TIMESTAMP_ADD": parse_date_delta_with_interval(exp.TimestampAdd), 291 "TIMESTAMP_SUB": parse_date_delta_with_interval(exp.TimestampSub), 292 "TO_JSON_STRING": exp.JSONFormat.from_arg_list, 293 } 294 295 FUNCTION_PARSERS = { 296 **parser.Parser.FUNCTION_PARSERS, 297 "ARRAY": lambda self: self.expression(exp.Array, expressions=[self._parse_statement()]), 298 } 299 FUNCTION_PARSERS.pop("TRIM") 300 301 NO_PAREN_FUNCTIONS = { 302 **parser.Parser.NO_PAREN_FUNCTIONS, 303 TokenType.CURRENT_DATETIME: exp.CurrentDatetime, 304 } 305 306 NESTED_TYPE_TOKENS = { 307 *parser.Parser.NESTED_TYPE_TOKENS, 308 TokenType.TABLE, 309 } 310 311 ID_VAR_TOKENS = { 312 *parser.Parser.ID_VAR_TOKENS, 313 TokenType.VALUES, 314 } 315 316 PROPERTY_PARSERS = { 317 **parser.Parser.PROPERTY_PARSERS, 318 "NOT DETERMINISTIC": lambda self: self.expression( 319 exp.StabilityProperty, this=exp.Literal.string("VOLATILE") 320 ), 321 "OPTIONS": lambda self: self._parse_with_property(), 322 } 323 324 CONSTRAINT_PARSERS = { 325 **parser.Parser.CONSTRAINT_PARSERS, 326 "OPTIONS": lambda self: exp.Properties(expressions=self._parse_with_property()), 327 } 328 329 def _parse_table_part(self, schema: bool = False) -> t.Optional[exp.Expression]: 330 this = super()._parse_table_part(schema=schema) 331 332 # https://cloud.google.com/bigquery/docs/reference/standard-sql/lexical#table_names 333 if isinstance(this, exp.Identifier): 334 table_name = this.name 335 while self._match(TokenType.DASH, advance=False) and self._next: 336 self._advance(2) 337 table_name += f"-{self._prev.text}" 338 339 this = exp.Identifier(this=table_name, quoted=this.args.get("quoted")) 340 341 return this 342 343 def _parse_table_parts(self, schema: bool = False) -> exp.Table: 344 table = super()._parse_table_parts(schema=schema) 345 if isinstance(table.this, exp.Identifier) and "." in table.name: 346 catalog, db, this, *rest = ( 347 t.cast(t.Optional[exp.Expression], exp.to_identifier(x)) 348 for x in split_num_words(table.name, ".", 3) 349 ) 350 351 if rest and this: 352 this = exp.Dot.build(t.cast(t.List[exp.Expression], [this, *rest])) 353 354 table = exp.Table(this=this, db=db, catalog=catalog) 355 356 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'>>, '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 BigQuery.Parser.<lambda>>, '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.NULLABLE: 'NULLABLE'>, <TokenType.TABLE: 'TABLE'>, <TokenType.ARRAY: 'ARRAY'>, <TokenType.STRUCT: 'STRUCT'>, <TokenType.MAP: 'MAP'>}
ID_VAR_TOKENS =
{<TokenType.SCHEMA: 'SCHEMA'>, <TokenType.DATABASE: 'DATABASE'>, <TokenType.ISNULL: 'ISNULL'>, <TokenType.FLOAT: 'FLOAT'>, <TokenType.VARIANT: 'VARIANT'>, <TokenType.PROCEDURE: 'PROCEDURE'>, <TokenType.CURRENT_TIMESTAMP: 'CURRENT_TIMESTAMP'>, <TokenType.WINDOW: 'WINDOW'>, <TokenType.TIME: 'TIME'>, <TokenType.VIEW: 'VIEW'>, <TokenType.TABLE: 'TABLE'>, <TokenType.LONGBLOB: 'LONGBLOB'>, <TokenType.PRAGMA: 'PRAGMA'>, <TokenType.DECIMAL: 'DECIMAL'>, <TokenType.SMALLINT: 'SMALLINT'>, <TokenType.NVARCHAR: 'NVARCHAR'>, <TokenType.INTERVAL: 'INTERVAL'>, <TokenType.TSRANGE: 'TSRANGE'>, <TokenType.VALUES: 'VALUES'>, <TokenType.SEMI: 'SEMI'>, <TokenType.TEMPORARY: 'TEMPORARY'>, <TokenType.TIMESTAMPLTZ: 'TIMESTAMPLTZ'>, <TokenType.TIMESTAMP: 'TIMESTAMP'>, <TokenType.VOLATILE: 'VOLATILE'>, <TokenType.PIVOT: 'PIVOT'>, <TokenType.UNIQUEIDENTIFIER: 'UNIQUEIDENTIFIER'>, <TokenType.VAR: 'VAR'>, <TokenType.SUPER: 'SUPER'>, <TokenType.DOUBLE: 'DOUBLE'>, <TokenType.INT4MULTIRANGE: 'INT4MULTIRANGE'>, <TokenType.KEEP: 'KEEP'>, <TokenType.ASC: 'ASC'>, <TokenType.SETTINGS: 'SETTINGS'>, <TokenType.SOME: 'SOME'>, <TokenType.SMALLSERIAL: 'SMALLSERIAL'>, <TokenType.CHAR: 'CHAR'>, <TokenType.FULL: 'FULL'>, <TokenType.INT8RANGE: 'INT8RANGE'>, <TokenType.UINT: 'UINT'>, <TokenType.SMALLMONEY: 'SMALLMONEY'>, <TokenType.NCHAR: 'NCHAR'>, <TokenType.ESCAPE: 'ESCAPE'>, <TokenType.DATE: 'DATE'>, <TokenType.ROW: 'ROW'>, <TokenType.EXECUTE: 'EXECUTE'>, <TokenType.ROWVERSION: 'ROWVERSION'>, <TokenType.TSMULTIRANGE: 'TSMULTIRANGE'>, <TokenType.BINARY: 'BINARY'>, <TokenType.CURRENT_DATE: 'CURRENT_DATE'>, <TokenType.EXISTS: 'EXISTS'>, <TokenType.SHOW: 'SHOW'>, <TokenType.INT4RANGE: 'INT4RANGE'>, <TokenType.GEOMETRY: 'GEOMETRY'>, <TokenType.INT128: 'INT128'>, <TokenType.RANGE: 'RANGE'>, <TokenType.MONEY: 'MONEY'>, <TokenType.TIMESTAMPTZ: 'TIMESTAMPTZ'>, <TokenType.BIGINT: 'BIGINT'>, <TokenType.NEXT: 'NEXT'>, <TokenType.COMMAND: 'COMMAND'>, <TokenType.NUMRANGE: 'NUMRANGE'>, <TokenType.AUTO_INCREMENT: 'AUTO_INCREMENT'>, <TokenType.SERIAL: 'SERIAL'>, <TokenType.COMMENT: 'COMMENT'>, <TokenType.INT256: 'INT256'>, <TokenType.RIGHT: 'RIGHT'>, <TokenType.UTINYINT: 'UTINYINT'>, <TokenType.MERGE: 'MERGE'>, <TokenType.ENUM: 'ENUM'>, <TokenType.ARRAY: 'ARRAY'>, <TokenType.DESCRIBE: 'DESCRIBE'>, <TokenType.INET: 'INET'>, <TokenType.HLLSKETCH: 'HLLSKETCH'>, <TokenType.BEGIN: 'BEGIN'>, <TokenType.CACHE: 'CACHE'>, <TokenType.DIV: 'DIV'>, <TokenType.TRUE: 'TRUE'>, <TokenType.UNPIVOT: 'UNPIVOT'>, <TokenType.FORMAT: 'FORMAT'>, <TokenType.VARCHAR: 'VARCHAR'>, <TokenType.VARBINARY: 'VARBINARY'>, <TokenType.ANY: 'ANY'>, <TokenType.DICTIONARY: 'DICTIONARY'>, <TokenType.CONSTRAINT: 'CONSTRAINT'>, <TokenType.SET: 'SET'>, <TokenType.TOP: 'TOP'>, <TokenType.COMMIT: 'COMMIT'>, <TokenType.ORDINALITY: 'ORDINALITY'>, <TokenType.ALL: 'ALL'>, <TokenType.APPLY: 'APPLY'>, <TokenType.USERDEFINED: 'USERDEFINED'>, <TokenType.DATETIME64: 'DATETIME64'>, <TokenType.IS: 'IS'>, <TokenType.USMALLINT: 'USMALLINT'>, <TokenType.TSTZMULTIRANGE: 'TSTZMULTIRANGE'>, <TokenType.HSTORE: 'HSTORE'>, <TokenType.INDEX: 'INDEX'>, <TokenType.TEXT: 'TEXT'>, <TokenType.IMAGE: 'IMAGE'>, <TokenType.GEOGRAPHY: 'GEOGRAPHY'>, <TokenType.DEFAULT: 'DEFAULT'>, <TokenType.REFERENCES: 'REFERENCES'>, <TokenType.INT8MULTIRANGE: 'INT8MULTIRANGE'>, <TokenType.DATETIME: 'DATETIME'>, <TokenType.BIT: 'BIT'>, <TokenType.END: 'END'>, <TokenType.DATEMULTIRANGE: 'DATEMULTIRANGE'>, <TokenType.UNIQUE: 'UNIQUE'>, <TokenType.TINYINT: 'TINYINT'>, <TokenType.PSEUDO_TYPE: 'PSEUDO_TYPE'>, <TokenType.DATERANGE: 'DATERANGE'>, <TokenType.JSONB: 'JSONB'>, <TokenType.LEFT: 'LEFT'>, <TokenType.OFFSET: 'OFFSET'>, <TokenType.OBJECT: 'OBJECT'>, <TokenType.FALSE: 'FALSE'>, <TokenType.BIGDECIMAL: 'BIGDECIMAL'>, <TokenType.ANTI: 'ANTI'>, <TokenType.COLUMN: 'COLUMN'>, <TokenType.INT: 'INT'>, <TokenType.UBIGINT: 'UBIGINT'>, <TokenType.IF: 'IF'>, <TokenType.BOOLEAN: 'BOOLEAN'>, <TokenType.FILTER: 'FILTER'>, <TokenType.UPDATE: 'UPDATE'>, <TokenType.CASE: 'CASE'>, <TokenType.MAP: 'MAP'>, <TokenType.PARTITION: 'PARTITION'>, <TokenType.LONGTEXT: 'LONGTEXT'>, <TokenType.NUMMULTIRANGE: 'NUMMULTIRANGE'>, <TokenType.NULLABLE: 'NULLABLE'>, <TokenType.DESC: 'DESC'>, <TokenType.CURRENT_DATETIME: 'CURRENT_DATETIME'>, <TokenType.XML: 'XML'>, <TokenType.DELETE: 'DELETE'>, <TokenType.LOAD: 'LOAD'>, <TokenType.MEDIUMBLOB: 'MEDIUMBLOB'>, <TokenType.UINT256: 'UINT256'>, <TokenType.PERCENT: 'PERCENT'>, <TokenType.MEDIUMTEXT: 'MEDIUMTEXT'>, <TokenType.STRUCT: 'STRUCT'>, <TokenType.CURRENT_USER: 'CURRENT_USER'>, <TokenType.FIRST: 'FIRST'>, <TokenType.FUNCTION: 'FUNCTION'>, <TokenType.ROWS: 'ROWS'>, <TokenType.NATURAL: 'NATURAL'>, <TokenType.BIGSERIAL: 'BIGSERIAL'>, <TokenType.CURRENT_TIME: 'CURRENT_TIME'>, <TokenType.UINT128: 'UINT128'>, <TokenType.UUID: 'UUID'>, <TokenType.JSON: 'JSON'>, <TokenType.OVERWRITE: 'OVERWRITE'>, <TokenType.COLLATE: 'COLLATE'>, <TokenType.TSTZRANGE: 'TSTZRANGE'>}
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
358 class Generator(generator.Generator): 359 EXPLICIT_UNION = True 360 INTERVAL_ALLOWS_PLURAL_FORM = False 361 JOIN_HINTS = False 362 TABLE_HINTS = False 363 LIMIT_FETCH = "LIMIT" 364 RENAME_TABLE_WITH_DB = False 365 ESCAPE_LINE_BREAK = True 366 367 TRANSFORMS = { 368 **generator.Generator.TRANSFORMS, 369 exp.ApproxDistinct: rename_func("APPROX_COUNT_DISTINCT"), 370 exp.ArraySize: rename_func("ARRAY_LENGTH"), 371 exp.Cast: transforms.preprocess([transforms.remove_precision_parameterized_types]), 372 exp.CTE: transforms.preprocess([_pushdown_cte_column_names]), 373 exp.DateAdd: _date_add_sql("DATE", "ADD"), 374 exp.DateSub: _date_add_sql("DATE", "SUB"), 375 exp.DatetimeAdd: _date_add_sql("DATETIME", "ADD"), 376 exp.DatetimeSub: _date_add_sql("DATETIME", "SUB"), 377 exp.DateDiff: lambda self, e: f"DATE_DIFF({self.sql(e, 'this')}, {self.sql(e, 'expression')}, {self.sql(e.args.get('unit', 'DAY'))})", 378 exp.DateStrToDate: datestrtodate_sql, 379 exp.DateTrunc: lambda self, e: self.func("DATE_TRUNC", e.this, e.text("unit")), 380 exp.JSONFormat: rename_func("TO_JSON_STRING"), 381 exp.GenerateSeries: rename_func("GENERATE_ARRAY"), 382 exp.GroupConcat: rename_func("STRING_AGG"), 383 exp.ILike: no_ilike_sql, 384 exp.IntDiv: rename_func("DIV"), 385 exp.Max: max_or_greatest, 386 exp.Min: min_or_least, 387 exp.RegexpExtract: lambda self, e: self.func( 388 "REGEXP_EXTRACT", 389 e.this, 390 e.expression, 391 e.args.get("position"), 392 e.args.get("occurrence"), 393 ), 394 exp.RegexpLike: rename_func("REGEXP_CONTAINS"), 395 exp.Select: transforms.preprocess( 396 [ 397 transforms.explode_to_unnest, 398 _unqualify_unnest, 399 transforms.eliminate_distinct_on, 400 _alias_ordered_group, 401 ] 402 ), 403 exp.StrToDate: lambda self, e: f"PARSE_DATE({self.format_time(e)}, {self.sql(e, 'this')})", 404 exp.StrToTime: lambda self, e: f"PARSE_TIMESTAMP({self.format_time(e)}, {self.sql(e, 'this')})", 405 exp.TimeAdd: _date_add_sql("TIME", "ADD"), 406 exp.TimeSub: _date_add_sql("TIME", "SUB"), 407 exp.TimestampAdd: _date_add_sql("TIMESTAMP", "ADD"), 408 exp.TimestampSub: _date_add_sql("TIMESTAMP", "SUB"), 409 exp.TimeStrToTime: timestrtotime_sql, 410 exp.TsOrDsToDate: ts_or_ds_to_date_sql("bigquery"), 411 exp.TsOrDsAdd: _date_add_sql("DATE", "ADD"), 412 exp.PartitionedByProperty: lambda self, e: f"PARTITION BY {self.sql(e, 'this')}", 413 exp.VariancePop: rename_func("VAR_POP"), 414 exp.Values: _derived_table_values_to_unnest, 415 exp.ReturnsProperty: _returnsproperty_sql, 416 exp.Create: _create_sql, 417 exp.Trim: lambda self, e: self.func(f"TRIM", e.this, e.expression), 418 exp.StabilityProperty: lambda self, e: f"DETERMINISTIC" 419 if e.name == "IMMUTABLE" 420 else "NOT DETERMINISTIC", 421 } 422 423 TYPE_MAPPING = { 424 **generator.Generator.TYPE_MAPPING, 425 exp.DataType.Type.BIGDECIMAL: "BIGNUMERIC", 426 exp.DataType.Type.BIGINT: "INT64", 427 exp.DataType.Type.BINARY: "BYTES", 428 exp.DataType.Type.BOOLEAN: "BOOL", 429 exp.DataType.Type.CHAR: "STRING", 430 exp.DataType.Type.DECIMAL: "NUMERIC", 431 exp.DataType.Type.DOUBLE: "FLOAT64", 432 exp.DataType.Type.FLOAT: "FLOAT64", 433 exp.DataType.Type.INT: "INT64", 434 exp.DataType.Type.NCHAR: "STRING", 435 exp.DataType.Type.NVARCHAR: "STRING", 436 exp.DataType.Type.SMALLINT: "INT64", 437 exp.DataType.Type.TEXT: "STRING", 438 exp.DataType.Type.TIMESTAMP: "DATETIME", 439 exp.DataType.Type.TIMESTAMPTZ: "TIMESTAMP", 440 exp.DataType.Type.TIMESTAMPLTZ: "TIMESTAMP", 441 exp.DataType.Type.TINYINT: "INT64", 442 exp.DataType.Type.VARBINARY: "BYTES", 443 exp.DataType.Type.VARCHAR: "STRING", 444 exp.DataType.Type.VARIANT: "ANY TYPE", 445 } 446 447 PROPERTIES_LOCATION = { 448 **generator.Generator.PROPERTIES_LOCATION, 449 exp.PartitionedByProperty: exp.Properties.Location.POST_SCHEMA, 450 exp.VolatileProperty: exp.Properties.Location.UNSUPPORTED, 451 } 452 453 # from: https://cloud.google.com/bigquery/docs/reference/standard-sql/lexical#reserved_keywords 454 RESERVED_KEYWORDS = { 455 *generator.Generator.RESERVED_KEYWORDS, 456 "all", 457 "and", 458 "any", 459 "array", 460 "as", 461 "asc", 462 "assert_rows_modified", 463 "at", 464 "between", 465 "by", 466 "case", 467 "cast", 468 "collate", 469 "contains", 470 "create", 471 "cross", 472 "cube", 473 "current", 474 "default", 475 "define", 476 "desc", 477 "distinct", 478 "else", 479 "end", 480 "enum", 481 "escape", 482 "except", 483 "exclude", 484 "exists", 485 "extract", 486 "false", 487 "fetch", 488 "following", 489 "for", 490 "from", 491 "full", 492 "group", 493 "grouping", 494 "groups", 495 "hash", 496 "having", 497 "if", 498 "ignore", 499 "in", 500 "inner", 501 "intersect", 502 "interval", 503 "into", 504 "is", 505 "join", 506 "lateral", 507 "left", 508 "like", 509 "limit", 510 "lookup", 511 "merge", 512 "natural", 513 "new", 514 "no", 515 "not", 516 "null", 517 "nulls", 518 "of", 519 "on", 520 "or", 521 "order", 522 "outer", 523 "over", 524 "partition", 525 "preceding", 526 "proto", 527 "qualify", 528 "range", 529 "recursive", 530 "respect", 531 "right", 532 "rollup", 533 "rows", 534 "select", 535 "set", 536 "some", 537 "struct", 538 "tablesample", 539 "then", 540 "to", 541 "treat", 542 "true", 543 "unbounded", 544 "union", 545 "unnest", 546 "using", 547 "when", 548 "where", 549 "window", 550 "with", 551 "within", 552 } 553 554 def attimezone_sql(self, expression: exp.AtTimeZone) -> str: 555 if not isinstance(expression.parent, exp.Cast): 556 return self.func( 557 "TIMESTAMP", self.func("DATETIME", expression.this, expression.args.get("zone")) 558 ) 559 return super().attimezone_sql(expression) 560 561 def trycast_sql(self, expression: exp.TryCast) -> str: 562 return self.cast_sql(expression, safe_prefix="SAFE_") 563 564 def cte_sql(self, expression: exp.CTE) -> str: 565 if expression.alias_column_names: 566 self.unsupported("Column names in CTE definition are not supported.") 567 return super().cte_sql(expression) 568 569 def array_sql(self, expression: exp.Array) -> str: 570 first_arg = seq_get(expression.expressions, 0) 571 if isinstance(first_arg, exp.Subqueryable): 572 return f"ARRAY{self.wrap(self.sql(first_arg))}" 573 574 return inline_array_sql(self, expression) 575 576 def transaction_sql(self, *_) -> str: 577 return "BEGIN TRANSACTION" 578 579 def commit_sql(self, *_) -> str: 580 return "COMMIT TRANSACTION" 581 582 def rollback_sql(self, *_) -> str: 583 return "ROLLBACK TRANSACTION" 584 585 def in_unnest_op(self, expression: exp.Unnest) -> str: 586 return self.sql(expression) 587 588 def except_op(self, expression: exp.Except) -> str: 589 if not expression.args.get("distinct", False): 590 self.unsupported("EXCEPT without DISTINCT is not supported in BigQuery") 591 return f"EXCEPT{' DISTINCT' if expression.args.get('distinct') else ' ALL'}" 592 593 def intersect_op(self, expression: exp.Intersect) -> str: 594 if not expression.args.get("distinct", False): 595 self.unsupported("INTERSECT without DISTINCT is not supported in BigQuery") 596 return f"INTERSECT{' DISTINCT' if expression.args.get('distinct') else ' ALL'}" 597 598 def with_properties(self, properties: exp.Properties) -> str: 599 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 =
{'when', 'except', 'asc', 'cast', 'extract', 'lookup', 'recursive', 'of', 'having', 'preceding', 'in', 'inner', 'respect', 'interval', 'if', 'case', 'to', 'fetch', 'natural', 'partition', 'unbounded', 'grouping', 'groups', 'left', 'intersect', 'any', 'false', 'cube', 'join', 'not', 'end', 'on', 'tablesample', 'right', 'assert_rows_modified', 'merge', 'and', 'enum', 'some', 'define', 'treat', 'full', 'lateral', 'new', 'outer', 'struct', 'like', 'proto', 'rollup', 'set', 'current', 'ignore', 'qualify', 'where', 'desc', 'is', 'no', 'range', 'limit', 'for', 'by', 'as', 'create', 'hash', 'unnest', 'from', 'at', 'cross', 'distinct', 'order', 'escape', 'with', 'over', 'then', 'else', 'exclude', 'following', 'select', 'window', 'array', 'or', 'default', 'group', 'within', 'between', 'rows', 'contains', 'union', 'nulls', 'into', 'using', 'collate', 'null', 'all', 'true', 'exists'}
@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
- IS_BOOL_ALLOWED
- 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