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