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