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