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