sqlglot.dialects.mysql
1from __future__ import annotations 2 3import typing as t 4 5from sqlglot import exp, generator, parser, tokens, transforms 6from sqlglot.dialects.dialect import ( 7 Dialect, 8 NormalizationStrategy, 9 arrow_json_extract_sql, 10 date_add_interval_sql, 11 datestrtodate_sql, 12 build_formatted_time, 13 isnull_to_is_null, 14 locate_to_strposition, 15 max_or_greatest, 16 min_or_least, 17 no_ilike_sql, 18 no_paren_current_date_sql, 19 no_pivot_sql, 20 no_tablesample_sql, 21 no_trycast_sql, 22 build_date_delta, 23 build_date_delta_with_interval, 24 rename_func, 25 strposition_to_locate_sql, 26 unit_to_var, 27 trim_sql, 28 timestrtotime_sql, 29) 30from sqlglot.helper import seq_get 31from sqlglot.tokens import TokenType 32 33 34def _show_parser(*args: t.Any, **kwargs: t.Any) -> t.Callable[[MySQL.Parser], exp.Show]: 35 def _parse(self: MySQL.Parser) -> exp.Show: 36 return self._parse_show_mysql(*args, **kwargs) 37 38 return _parse 39 40 41def _date_trunc_sql(self: MySQL.Generator, expression: exp.DateTrunc) -> str: 42 expr = self.sql(expression, "this") 43 unit = expression.text("unit").upper() 44 45 if unit == "WEEK": 46 concat = f"CONCAT(YEAR({expr}), ' ', WEEK({expr}, 1), ' 1')" 47 date_format = "%Y %u %w" 48 elif unit == "MONTH": 49 concat = f"CONCAT(YEAR({expr}), ' ', MONTH({expr}), ' 1')" 50 date_format = "%Y %c %e" 51 elif unit == "QUARTER": 52 concat = f"CONCAT(YEAR({expr}), ' ', QUARTER({expr}) * 3 - 2, ' 1')" 53 date_format = "%Y %c %e" 54 elif unit == "YEAR": 55 concat = f"CONCAT(YEAR({expr}), ' 1 1')" 56 date_format = "%Y %c %e" 57 else: 58 if unit != "DAY": 59 self.unsupported(f"Unexpected interval unit: {unit}") 60 return self.func("DATE", expr) 61 62 return self.func("STR_TO_DATE", concat, f"'{date_format}'") 63 64 65# All specifiers for time parts (as opposed to date parts) 66# https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_date-format 67TIME_SPECIFIERS = {"f", "H", "h", "I", "i", "k", "l", "p", "r", "S", "s", "T"} 68 69 70def _has_time_specifier(date_format: str) -> bool: 71 i = 0 72 length = len(date_format) 73 74 while i < length: 75 if date_format[i] == "%": 76 i += 1 77 if i < length and date_format[i] in TIME_SPECIFIERS: 78 return True 79 i += 1 80 return False 81 82 83def _str_to_date(args: t.List) -> exp.StrToDate | exp.StrToTime: 84 mysql_date_format = seq_get(args, 1) 85 date_format = MySQL.format_time(mysql_date_format) 86 this = seq_get(args, 0) 87 88 if mysql_date_format and _has_time_specifier(mysql_date_format.name): 89 return exp.StrToTime(this=this, format=date_format) 90 91 return exp.StrToDate(this=this, format=date_format) 92 93 94def _str_to_date_sql( 95 self: MySQL.Generator, expression: exp.StrToDate | exp.StrToTime | exp.TsOrDsToDate 96) -> str: 97 return self.func("STR_TO_DATE", expression.this, self.format_time(expression)) 98 99 100def _unix_to_time_sql(self: MySQL.Generator, expression: exp.UnixToTime) -> str: 101 scale = expression.args.get("scale") 102 timestamp = expression.this 103 104 if scale in (None, exp.UnixToTime.SECONDS): 105 return self.func("FROM_UNIXTIME", timestamp, self.format_time(expression)) 106 107 return self.func( 108 "FROM_UNIXTIME", 109 exp.Div(this=timestamp, expression=exp.func("POW", 10, scale)), 110 self.format_time(expression), 111 ) 112 113 114def date_add_sql( 115 kind: str, 116) -> t.Callable[[generator.Generator, exp.Expression], str]: 117 def func(self: generator.Generator, expression: exp.Expression) -> str: 118 return self.func( 119 f"DATE_{kind}", 120 expression.this, 121 exp.Interval(this=expression.expression, unit=unit_to_var(expression)), 122 ) 123 124 return func 125 126 127def _ts_or_ds_to_date_sql(self: MySQL.Generator, expression: exp.TsOrDsToDate) -> str: 128 time_format = expression.args.get("format") 129 return _str_to_date_sql(self, expression) if time_format else self.func("DATE", expression.this) 130 131 132def _remove_ts_or_ds_to_date( 133 to_sql: t.Optional[t.Callable[[MySQL.Generator, exp.Expression], str]] = None, 134 args: t.Tuple[str, ...] = ("this",), 135) -> t.Callable[[MySQL.Generator, exp.Func], str]: 136 def func(self: MySQL.Generator, expression: exp.Func) -> str: 137 for arg_key in args: 138 arg = expression.args.get(arg_key) 139 if isinstance(arg, exp.TsOrDsToDate) and not arg.args.get("format"): 140 expression.set(arg_key, arg.this) 141 142 return to_sql(self, expression) if to_sql else self.function_fallback_sql(expression) 143 144 return func 145 146 147class MySQL(Dialect): 148 PROMOTE_TO_INFERRED_DATETIME_TYPE = True 149 150 # https://dev.mysql.com/doc/refman/8.0/en/identifiers.html 151 IDENTIFIERS_CAN_START_WITH_DIGIT = True 152 153 # We default to treating all identifiers as case-sensitive, since it matches MySQL's 154 # behavior on Linux systems. For MacOS and Windows systems, one can override this 155 # setting by specifying `dialect="mysql, normalization_strategy = lowercase"`. 156 # 157 # See also https://dev.mysql.com/doc/refman/8.2/en/identifier-case-sensitivity.html 158 NORMALIZATION_STRATEGY = NormalizationStrategy.CASE_SENSITIVE 159 160 TIME_FORMAT = "'%Y-%m-%d %T'" 161 DPIPE_IS_STRING_CONCAT = False 162 SUPPORTS_USER_DEFINED_TYPES = False 163 SUPPORTS_SEMI_ANTI_JOIN = False 164 SAFE_DIVISION = True 165 166 # https://prestodb.io/docs/current/functions/datetime.html#mysql-date-functions 167 TIME_MAPPING = { 168 "%M": "%B", 169 "%c": "%-m", 170 "%e": "%-d", 171 "%h": "%I", 172 "%i": "%M", 173 "%s": "%S", 174 "%u": "%W", 175 "%k": "%-H", 176 "%l": "%-I", 177 "%T": "%H:%M:%S", 178 "%W": "%A", 179 } 180 181 class Tokenizer(tokens.Tokenizer): 182 QUOTES = ["'", '"'] 183 COMMENTS = ["--", "#", ("/*", "*/")] 184 IDENTIFIERS = ["`"] 185 STRING_ESCAPES = ["'", '"', "\\"] 186 BIT_STRINGS = [("b'", "'"), ("B'", "'"), ("0b", "")] 187 HEX_STRINGS = [("x'", "'"), ("X'", "'"), ("0x", "")] 188 189 KEYWORDS = { 190 **tokens.Tokenizer.KEYWORDS, 191 "CHARSET": TokenType.CHARACTER_SET, 192 # The DESCRIBE and EXPLAIN statements are synonyms. 193 # https://dev.mysql.com/doc/refman/8.4/en/explain.html 194 "EXPLAIN": TokenType.DESCRIBE, 195 "FORCE": TokenType.FORCE, 196 "IGNORE": TokenType.IGNORE, 197 "KEY": TokenType.KEY, 198 "LOCK TABLES": TokenType.COMMAND, 199 "LONGBLOB": TokenType.LONGBLOB, 200 "LONGTEXT": TokenType.LONGTEXT, 201 "MEDIUMBLOB": TokenType.MEDIUMBLOB, 202 "TINYBLOB": TokenType.TINYBLOB, 203 "TINYTEXT": TokenType.TINYTEXT, 204 "MEDIUMTEXT": TokenType.MEDIUMTEXT, 205 "MEDIUMINT": TokenType.MEDIUMINT, 206 "MEMBER OF": TokenType.MEMBER_OF, 207 "SEPARATOR": TokenType.SEPARATOR, 208 "START": TokenType.BEGIN, 209 "SIGNED": TokenType.BIGINT, 210 "SIGNED INTEGER": TokenType.BIGINT, 211 "UNLOCK TABLES": TokenType.COMMAND, 212 "UNSIGNED": TokenType.UBIGINT, 213 "UNSIGNED INTEGER": TokenType.UBIGINT, 214 "YEAR": TokenType.YEAR, 215 "_ARMSCII8": TokenType.INTRODUCER, 216 "_ASCII": TokenType.INTRODUCER, 217 "_BIG5": TokenType.INTRODUCER, 218 "_BINARY": TokenType.INTRODUCER, 219 "_CP1250": TokenType.INTRODUCER, 220 "_CP1251": TokenType.INTRODUCER, 221 "_CP1256": TokenType.INTRODUCER, 222 "_CP1257": TokenType.INTRODUCER, 223 "_CP850": TokenType.INTRODUCER, 224 "_CP852": TokenType.INTRODUCER, 225 "_CP866": TokenType.INTRODUCER, 226 "_CP932": TokenType.INTRODUCER, 227 "_DEC8": TokenType.INTRODUCER, 228 "_EUCJPMS": TokenType.INTRODUCER, 229 "_EUCKR": TokenType.INTRODUCER, 230 "_GB18030": TokenType.INTRODUCER, 231 "_GB2312": TokenType.INTRODUCER, 232 "_GBK": TokenType.INTRODUCER, 233 "_GEOSTD8": TokenType.INTRODUCER, 234 "_GREEK": TokenType.INTRODUCER, 235 "_HEBREW": TokenType.INTRODUCER, 236 "_HP8": TokenType.INTRODUCER, 237 "_KEYBCS2": TokenType.INTRODUCER, 238 "_KOI8R": TokenType.INTRODUCER, 239 "_KOI8U": TokenType.INTRODUCER, 240 "_LATIN1": TokenType.INTRODUCER, 241 "_LATIN2": TokenType.INTRODUCER, 242 "_LATIN5": TokenType.INTRODUCER, 243 "_LATIN7": TokenType.INTRODUCER, 244 "_MACCE": TokenType.INTRODUCER, 245 "_MACROMAN": TokenType.INTRODUCER, 246 "_SJIS": TokenType.INTRODUCER, 247 "_SWE7": TokenType.INTRODUCER, 248 "_TIS620": TokenType.INTRODUCER, 249 "_UCS2": TokenType.INTRODUCER, 250 "_UJIS": TokenType.INTRODUCER, 251 # https://dev.mysql.com/doc/refman/8.0/en/string-literals.html 252 "_UTF8": TokenType.INTRODUCER, 253 "_UTF16": TokenType.INTRODUCER, 254 "_UTF16LE": TokenType.INTRODUCER, 255 "_UTF32": TokenType.INTRODUCER, 256 "_UTF8MB3": TokenType.INTRODUCER, 257 "_UTF8MB4": TokenType.INTRODUCER, 258 "@@": TokenType.SESSION_PARAMETER, 259 } 260 261 COMMANDS = {*tokens.Tokenizer.COMMANDS, TokenType.REPLACE} - {TokenType.SHOW} 262 263 class Parser(parser.Parser): 264 FUNC_TOKENS = { 265 *parser.Parser.FUNC_TOKENS, 266 TokenType.DATABASE, 267 TokenType.SCHEMA, 268 TokenType.VALUES, 269 } 270 271 CONJUNCTION = { 272 **parser.Parser.CONJUNCTION, 273 TokenType.DAMP: exp.And, 274 TokenType.XOR: exp.Xor, 275 } 276 277 DISJUNCTION = { 278 **parser.Parser.DISJUNCTION, 279 TokenType.DPIPE: exp.Or, 280 } 281 282 TABLE_ALIAS_TOKENS = ( 283 parser.Parser.TABLE_ALIAS_TOKENS - parser.Parser.TABLE_INDEX_HINT_TOKENS 284 ) 285 286 RANGE_PARSERS = { 287 **parser.Parser.RANGE_PARSERS, 288 TokenType.MEMBER_OF: lambda self, this: self.expression( 289 exp.JSONArrayContains, 290 this=this, 291 expression=self._parse_wrapped(self._parse_expression), 292 ), 293 } 294 295 FUNCTIONS = { 296 **parser.Parser.FUNCTIONS, 297 "CHAR_LENGTH": exp.Length.from_arg_list, 298 "CHARACTER_LENGTH": exp.Length.from_arg_list, 299 "CONVERT_TZ": lambda args: exp.ConvertTimezone( 300 source_tz=seq_get(args, 1), target_tz=seq_get(args, 2), timestamp=seq_get(args, 0) 301 ), 302 "DATE": lambda args: exp.TsOrDsToDate(this=seq_get(args, 0)), 303 "DATE_ADD": build_date_delta_with_interval(exp.DateAdd), 304 "DATE_FORMAT": build_formatted_time(exp.TimeToStr, "mysql"), 305 "DATE_SUB": build_date_delta_with_interval(exp.DateSub), 306 "DAY": lambda args: exp.Day(this=exp.TsOrDsToDate(this=seq_get(args, 0))), 307 "DAYOFMONTH": lambda args: exp.DayOfMonth(this=exp.TsOrDsToDate(this=seq_get(args, 0))), 308 "DAYOFWEEK": lambda args: exp.DayOfWeek(this=exp.TsOrDsToDate(this=seq_get(args, 0))), 309 "DAYOFYEAR": lambda args: exp.DayOfYear(this=exp.TsOrDsToDate(this=seq_get(args, 0))), 310 "FROM_UNIXTIME": build_formatted_time(exp.UnixToTime, "mysql"), 311 "ISNULL": isnull_to_is_null, 312 "LOCATE": locate_to_strposition, 313 "MAKETIME": exp.TimeFromParts.from_arg_list, 314 "MONTH": lambda args: exp.Month(this=exp.TsOrDsToDate(this=seq_get(args, 0))), 315 "MONTHNAME": lambda args: exp.TimeToStr( 316 this=exp.TsOrDsToDate(this=seq_get(args, 0)), 317 format=exp.Literal.string("%B"), 318 ), 319 "STR_TO_DATE": _str_to_date, 320 "TIMESTAMPDIFF": build_date_delta(exp.TimestampDiff), 321 "TO_DAYS": lambda args: exp.paren( 322 exp.DateDiff( 323 this=exp.TsOrDsToDate(this=seq_get(args, 0)), 324 expression=exp.TsOrDsToDate(this=exp.Literal.string("0000-01-01")), 325 unit=exp.var("DAY"), 326 ) 327 + 1 328 ), 329 "WEEK": lambda args: exp.Week( 330 this=exp.TsOrDsToDate(this=seq_get(args, 0)), mode=seq_get(args, 1) 331 ), 332 "WEEKOFYEAR": lambda args: exp.WeekOfYear(this=exp.TsOrDsToDate(this=seq_get(args, 0))), 333 "YEAR": lambda args: exp.Year(this=exp.TsOrDsToDate(this=seq_get(args, 0))), 334 } 335 336 FUNCTION_PARSERS = { 337 **parser.Parser.FUNCTION_PARSERS, 338 "CHAR": lambda self: self.expression( 339 exp.Chr, 340 expressions=self._parse_csv(self._parse_assignment), 341 charset=self._match(TokenType.USING) and self._parse_var(), 342 ), 343 "GROUP_CONCAT": lambda self: self._parse_group_concat(), 344 # https://dev.mysql.com/doc/refman/5.7/en/miscellaneous-functions.html#function_values 345 "VALUES": lambda self: self.expression( 346 exp.Anonymous, this="VALUES", expressions=[self._parse_id_var()] 347 ), 348 "JSON_VALUE": lambda self: self._parse_json_value(), 349 } 350 351 STATEMENT_PARSERS = { 352 **parser.Parser.STATEMENT_PARSERS, 353 TokenType.SHOW: lambda self: self._parse_show(), 354 } 355 356 SHOW_PARSERS = { 357 "BINARY LOGS": _show_parser("BINARY LOGS"), 358 "MASTER LOGS": _show_parser("BINARY LOGS"), 359 "BINLOG EVENTS": _show_parser("BINLOG EVENTS"), 360 "CHARACTER SET": _show_parser("CHARACTER SET"), 361 "CHARSET": _show_parser("CHARACTER SET"), 362 "COLLATION": _show_parser("COLLATION"), 363 "FULL COLUMNS": _show_parser("COLUMNS", target="FROM", full=True), 364 "COLUMNS": _show_parser("COLUMNS", target="FROM"), 365 "CREATE DATABASE": _show_parser("CREATE DATABASE", target=True), 366 "CREATE EVENT": _show_parser("CREATE EVENT", target=True), 367 "CREATE FUNCTION": _show_parser("CREATE FUNCTION", target=True), 368 "CREATE PROCEDURE": _show_parser("CREATE PROCEDURE", target=True), 369 "CREATE TABLE": _show_parser("CREATE TABLE", target=True), 370 "CREATE TRIGGER": _show_parser("CREATE TRIGGER", target=True), 371 "CREATE VIEW": _show_parser("CREATE VIEW", target=True), 372 "DATABASES": _show_parser("DATABASES"), 373 "SCHEMAS": _show_parser("DATABASES"), 374 "ENGINE": _show_parser("ENGINE", target=True), 375 "STORAGE ENGINES": _show_parser("ENGINES"), 376 "ENGINES": _show_parser("ENGINES"), 377 "ERRORS": _show_parser("ERRORS"), 378 "EVENTS": _show_parser("EVENTS"), 379 "FUNCTION CODE": _show_parser("FUNCTION CODE", target=True), 380 "FUNCTION STATUS": _show_parser("FUNCTION STATUS"), 381 "GRANTS": _show_parser("GRANTS", target="FOR"), 382 "INDEX": _show_parser("INDEX", target="FROM"), 383 "MASTER STATUS": _show_parser("MASTER STATUS"), 384 "OPEN TABLES": _show_parser("OPEN TABLES"), 385 "PLUGINS": _show_parser("PLUGINS"), 386 "PROCEDURE CODE": _show_parser("PROCEDURE CODE", target=True), 387 "PROCEDURE STATUS": _show_parser("PROCEDURE STATUS"), 388 "PRIVILEGES": _show_parser("PRIVILEGES"), 389 "FULL PROCESSLIST": _show_parser("PROCESSLIST", full=True), 390 "PROCESSLIST": _show_parser("PROCESSLIST"), 391 "PROFILE": _show_parser("PROFILE"), 392 "PROFILES": _show_parser("PROFILES"), 393 "RELAYLOG EVENTS": _show_parser("RELAYLOG EVENTS"), 394 "REPLICAS": _show_parser("REPLICAS"), 395 "SLAVE HOSTS": _show_parser("REPLICAS"), 396 "REPLICA STATUS": _show_parser("REPLICA STATUS"), 397 "SLAVE STATUS": _show_parser("REPLICA STATUS"), 398 "GLOBAL STATUS": _show_parser("STATUS", global_=True), 399 "SESSION STATUS": _show_parser("STATUS"), 400 "STATUS": _show_parser("STATUS"), 401 "TABLE STATUS": _show_parser("TABLE STATUS"), 402 "FULL TABLES": _show_parser("TABLES", full=True), 403 "TABLES": _show_parser("TABLES"), 404 "TRIGGERS": _show_parser("TRIGGERS"), 405 "GLOBAL VARIABLES": _show_parser("VARIABLES", global_=True), 406 "SESSION VARIABLES": _show_parser("VARIABLES"), 407 "VARIABLES": _show_parser("VARIABLES"), 408 "WARNINGS": _show_parser("WARNINGS"), 409 } 410 411 PROPERTY_PARSERS = { 412 **parser.Parser.PROPERTY_PARSERS, 413 "LOCK": lambda self: self._parse_property_assignment(exp.LockProperty), 414 } 415 416 SET_PARSERS = { 417 **parser.Parser.SET_PARSERS, 418 "PERSIST": lambda self: self._parse_set_item_assignment("PERSIST"), 419 "PERSIST_ONLY": lambda self: self._parse_set_item_assignment("PERSIST_ONLY"), 420 "CHARACTER SET": lambda self: self._parse_set_item_charset("CHARACTER SET"), 421 "CHARSET": lambda self: self._parse_set_item_charset("CHARACTER SET"), 422 "NAMES": lambda self: self._parse_set_item_names(), 423 } 424 425 CONSTRAINT_PARSERS = { 426 **parser.Parser.CONSTRAINT_PARSERS, 427 "FULLTEXT": lambda self: self._parse_index_constraint(kind="FULLTEXT"), 428 "INDEX": lambda self: self._parse_index_constraint(), 429 "KEY": lambda self: self._parse_index_constraint(), 430 "SPATIAL": lambda self: self._parse_index_constraint(kind="SPATIAL"), 431 } 432 433 ALTER_PARSERS = { 434 **parser.Parser.ALTER_PARSERS, 435 "MODIFY": lambda self: self._parse_alter_table_alter(), 436 } 437 438 SCHEMA_UNNAMED_CONSTRAINTS = { 439 *parser.Parser.SCHEMA_UNNAMED_CONSTRAINTS, 440 "FULLTEXT", 441 "INDEX", 442 "KEY", 443 "SPATIAL", 444 } 445 446 PROFILE_TYPES: parser.OPTIONS_TYPE = { 447 **dict.fromkeys(("ALL", "CPU", "IPC", "MEMORY", "SOURCE", "SWAPS"), tuple()), 448 "BLOCK": ("IO",), 449 "CONTEXT": ("SWITCHES",), 450 "PAGE": ("FAULTS",), 451 } 452 453 TYPE_TOKENS = { 454 *parser.Parser.TYPE_TOKENS, 455 TokenType.SET, 456 } 457 458 ENUM_TYPE_TOKENS = { 459 *parser.Parser.ENUM_TYPE_TOKENS, 460 TokenType.SET, 461 } 462 463 # SELECT [ ALL | DISTINCT | DISTINCTROW ] [ <OPERATION_MODIFIERS> ] 464 OPERATION_MODIFIERS = { 465 "HIGH_PRIORITY", 466 "STRAIGHT_JOIN", 467 "SQL_SMALL_RESULT", 468 "SQL_BIG_RESULT", 469 "SQL_BUFFER_RESULT", 470 "SQL_NO_CACHE", 471 "SQL_CALC_FOUND_ROWS", 472 } 473 474 LOG_DEFAULTS_TO_LN = True 475 STRING_ALIASES = True 476 VALUES_FOLLOWED_BY_PAREN = False 477 SUPPORTS_PARTITION_SELECTION = True 478 479 def _parse_primary_key_part(self) -> t.Optional[exp.Expression]: 480 this = self._parse_id_var() 481 if not self._match(TokenType.L_PAREN): 482 return this 483 484 expression = self._parse_number() 485 self._match_r_paren() 486 return self.expression(exp.ColumnPrefix, this=this, expression=expression) 487 488 def _parse_index_constraint( 489 self, kind: t.Optional[str] = None 490 ) -> exp.IndexColumnConstraint: 491 if kind: 492 self._match_texts(("INDEX", "KEY")) 493 494 this = self._parse_id_var(any_token=False) 495 index_type = self._match(TokenType.USING) and self._advance_any() and self._prev.text 496 expressions = self._parse_wrapped_csv(self._parse_ordered) 497 498 options = [] 499 while True: 500 if self._match_text_seq("KEY_BLOCK_SIZE"): 501 self._match(TokenType.EQ) 502 opt = exp.IndexConstraintOption(key_block_size=self._parse_number()) 503 elif self._match(TokenType.USING): 504 opt = exp.IndexConstraintOption(using=self._advance_any() and self._prev.text) 505 elif self._match_text_seq("WITH", "PARSER"): 506 opt = exp.IndexConstraintOption(parser=self._parse_var(any_token=True)) 507 elif self._match(TokenType.COMMENT): 508 opt = exp.IndexConstraintOption(comment=self._parse_string()) 509 elif self._match_text_seq("VISIBLE"): 510 opt = exp.IndexConstraintOption(visible=True) 511 elif self._match_text_seq("INVISIBLE"): 512 opt = exp.IndexConstraintOption(visible=False) 513 elif self._match_text_seq("ENGINE_ATTRIBUTE"): 514 self._match(TokenType.EQ) 515 opt = exp.IndexConstraintOption(engine_attr=self._parse_string()) 516 elif self._match_text_seq("SECONDARY_ENGINE_ATTRIBUTE"): 517 self._match(TokenType.EQ) 518 opt = exp.IndexConstraintOption(secondary_engine_attr=self._parse_string()) 519 else: 520 opt = None 521 522 if not opt: 523 break 524 525 options.append(opt) 526 527 return self.expression( 528 exp.IndexColumnConstraint, 529 this=this, 530 expressions=expressions, 531 kind=kind, 532 index_type=index_type, 533 options=options, 534 ) 535 536 def _parse_show_mysql( 537 self, 538 this: str, 539 target: bool | str = False, 540 full: t.Optional[bool] = None, 541 global_: t.Optional[bool] = None, 542 ) -> exp.Show: 543 if target: 544 if isinstance(target, str): 545 self._match_text_seq(target) 546 target_id = self._parse_id_var() 547 else: 548 target_id = None 549 550 log = self._parse_string() if self._match_text_seq("IN") else None 551 552 if this in ("BINLOG EVENTS", "RELAYLOG EVENTS"): 553 position = self._parse_number() if self._match_text_seq("FROM") else None 554 db = None 555 else: 556 position = None 557 db = None 558 559 if self._match(TokenType.FROM): 560 db = self._parse_id_var() 561 elif self._match(TokenType.DOT): 562 db = target_id 563 target_id = self._parse_id_var() 564 565 channel = self._parse_id_var() if self._match_text_seq("FOR", "CHANNEL") else None 566 567 like = self._parse_string() if self._match_text_seq("LIKE") else None 568 where = self._parse_where() 569 570 if this == "PROFILE": 571 types = self._parse_csv(lambda: self._parse_var_from_options(self.PROFILE_TYPES)) 572 query = self._parse_number() if self._match_text_seq("FOR", "QUERY") else None 573 offset = self._parse_number() if self._match_text_seq("OFFSET") else None 574 limit = self._parse_number() if self._match_text_seq("LIMIT") else None 575 else: 576 types, query = None, None 577 offset, limit = self._parse_oldstyle_limit() 578 579 mutex = True if self._match_text_seq("MUTEX") else None 580 mutex = False if self._match_text_seq("STATUS") else mutex 581 582 return self.expression( 583 exp.Show, 584 this=this, 585 target=target_id, 586 full=full, 587 log=log, 588 position=position, 589 db=db, 590 channel=channel, 591 like=like, 592 where=where, 593 types=types, 594 query=query, 595 offset=offset, 596 limit=limit, 597 mutex=mutex, 598 **{"global": global_}, # type: ignore 599 ) 600 601 def _parse_oldstyle_limit( 602 self, 603 ) -> t.Tuple[t.Optional[exp.Expression], t.Optional[exp.Expression]]: 604 limit = None 605 offset = None 606 if self._match_text_seq("LIMIT"): 607 parts = self._parse_csv(self._parse_number) 608 if len(parts) == 1: 609 limit = parts[0] 610 elif len(parts) == 2: 611 limit = parts[1] 612 offset = parts[0] 613 614 return offset, limit 615 616 def _parse_set_item_charset(self, kind: str) -> exp.Expression: 617 this = self._parse_string() or self._parse_unquoted_field() 618 return self.expression(exp.SetItem, this=this, kind=kind) 619 620 def _parse_set_item_names(self) -> exp.Expression: 621 charset = self._parse_string() or self._parse_unquoted_field() 622 if self._match_text_seq("COLLATE"): 623 collate = self._parse_string() or self._parse_unquoted_field() 624 else: 625 collate = None 626 627 return self.expression(exp.SetItem, this=charset, collate=collate, kind="NAMES") 628 629 def _parse_type( 630 self, parse_interval: bool = True, fallback_to_identifier: bool = False 631 ) -> t.Optional[exp.Expression]: 632 # mysql binary is special and can work anywhere, even in order by operations 633 # it operates like a no paren func 634 if self._match(TokenType.BINARY, advance=False): 635 data_type = self._parse_types(check_func=True, allow_identifiers=False) 636 637 if isinstance(data_type, exp.DataType): 638 return self.expression(exp.Cast, this=self._parse_column(), to=data_type) 639 640 return super()._parse_type( 641 parse_interval=parse_interval, fallback_to_identifier=fallback_to_identifier 642 ) 643 644 def _parse_group_concat(self) -> t.Optional[exp.Expression]: 645 def concat_exprs( 646 node: t.Optional[exp.Expression], exprs: t.List[exp.Expression] 647 ) -> exp.Expression: 648 if isinstance(node, exp.Distinct) and len(node.expressions) > 1: 649 concat_exprs = [ 650 self.expression(exp.Concat, expressions=node.expressions, safe=True) 651 ] 652 node.set("expressions", concat_exprs) 653 return node 654 if len(exprs) == 1: 655 return exprs[0] 656 return self.expression(exp.Concat, expressions=args, safe=True) 657 658 args = self._parse_csv(self._parse_lambda) 659 660 if args: 661 order = args[-1] if isinstance(args[-1], exp.Order) else None 662 663 if order: 664 # Order By is the last (or only) expression in the list and has consumed the 'expr' before it, 665 # remove 'expr' from exp.Order and add it back to args 666 args[-1] = order.this 667 order.set("this", concat_exprs(order.this, args)) 668 669 this = order or concat_exprs(args[0], args) 670 else: 671 this = None 672 673 separator = self._parse_field() if self._match(TokenType.SEPARATOR) else None 674 675 return self.expression(exp.GroupConcat, this=this, separator=separator) 676 677 def _parse_json_value(self) -> exp.JSONValue: 678 this = self._parse_bitwise() 679 self._match(TokenType.COMMA) 680 path = self._parse_bitwise() 681 682 returning = self._match(TokenType.RETURNING) and self._parse_type() 683 684 return self.expression( 685 exp.JSONValue, 686 this=this, 687 path=self.dialect.to_json_path(path), 688 returning=returning, 689 on_condition=self._parse_on_condition(), 690 ) 691 692 class Generator(generator.Generator): 693 INTERVAL_ALLOWS_PLURAL_FORM = False 694 LOCKING_READS_SUPPORTED = True 695 NULL_ORDERING_SUPPORTED = None 696 JOIN_HINTS = False 697 TABLE_HINTS = True 698 DUPLICATE_KEY_UPDATE_WITH_SET = False 699 QUERY_HINT_SEP = " " 700 VALUES_AS_TABLE = False 701 NVL2_SUPPORTED = False 702 LAST_DAY_SUPPORTS_DATE_PART = False 703 JSON_TYPE_REQUIRED_FOR_EXTRACTION = True 704 JSON_PATH_BRACKETED_KEY_SUPPORTED = False 705 JSON_KEY_VALUE_PAIR_SEP = "," 706 SUPPORTS_TO_NUMBER = False 707 PARSE_JSON_NAME: t.Optional[str] = None 708 PAD_FILL_PATTERN_IS_REQUIRED = True 709 WRAP_DERIVED_VALUES = False 710 VARCHAR_REQUIRES_SIZE = True 711 SUPPORTS_MEDIAN = False 712 713 TRANSFORMS = { 714 **generator.Generator.TRANSFORMS, 715 exp.ArrayAgg: rename_func("GROUP_CONCAT"), 716 exp.CurrentDate: no_paren_current_date_sql, 717 exp.DateDiff: _remove_ts_or_ds_to_date( 718 lambda self, e: self.func("DATEDIFF", e.this, e.expression), ("this", "expression") 719 ), 720 exp.DateAdd: _remove_ts_or_ds_to_date(date_add_sql("ADD")), 721 exp.DateStrToDate: datestrtodate_sql, 722 exp.DateSub: _remove_ts_or_ds_to_date(date_add_sql("SUB")), 723 exp.DateTrunc: _date_trunc_sql, 724 exp.Day: _remove_ts_or_ds_to_date(), 725 exp.DayOfMonth: _remove_ts_or_ds_to_date(rename_func("DAYOFMONTH")), 726 exp.DayOfWeek: _remove_ts_or_ds_to_date(rename_func("DAYOFWEEK")), 727 exp.DayOfYear: _remove_ts_or_ds_to_date(rename_func("DAYOFYEAR")), 728 exp.GroupConcat: lambda self, 729 e: f"""GROUP_CONCAT({self.sql(e, "this")} SEPARATOR {self.sql(e, "separator") or "','"})""", 730 exp.ILike: no_ilike_sql, 731 exp.JSONExtractScalar: arrow_json_extract_sql, 732 exp.Length: rename_func("CHAR_LENGTH"), 733 exp.Max: max_or_greatest, 734 exp.Min: min_or_least, 735 exp.Month: _remove_ts_or_ds_to_date(), 736 exp.NullSafeEQ: lambda self, e: self.binary(e, "<=>"), 737 exp.NullSafeNEQ: lambda self, e: f"NOT {self.binary(e, '<=>')}", 738 exp.Pivot: no_pivot_sql, 739 exp.Select: transforms.preprocess( 740 [ 741 transforms.eliminate_distinct_on, 742 transforms.eliminate_semi_and_anti_joins, 743 transforms.eliminate_qualify, 744 transforms.eliminate_full_outer_join, 745 transforms.unnest_generate_date_array_using_recursive_cte, 746 ] 747 ), 748 exp.StrPosition: strposition_to_locate_sql, 749 exp.StrToDate: _str_to_date_sql, 750 exp.StrToTime: _str_to_date_sql, 751 exp.Stuff: rename_func("INSERT"), 752 exp.TableSample: no_tablesample_sql, 753 exp.TimeFromParts: rename_func("MAKETIME"), 754 exp.TimestampAdd: date_add_interval_sql("DATE", "ADD"), 755 exp.TimestampDiff: lambda self, e: self.func( 756 "TIMESTAMPDIFF", unit_to_var(e), e.expression, e.this 757 ), 758 exp.TimestampSub: date_add_interval_sql("DATE", "SUB"), 759 exp.TimeStrToUnix: rename_func("UNIX_TIMESTAMP"), 760 exp.TimeStrToTime: lambda self, e: timestrtotime_sql( 761 self, 762 e, 763 include_precision=not e.args.get("zone"), 764 ), 765 exp.TimeToStr: _remove_ts_or_ds_to_date( 766 lambda self, e: self.func("DATE_FORMAT", e.this, self.format_time(e)) 767 ), 768 exp.Trim: trim_sql, 769 exp.TryCast: no_trycast_sql, 770 exp.TsOrDsAdd: date_add_sql("ADD"), 771 exp.TsOrDsDiff: lambda self, e: self.func("DATEDIFF", e.this, e.expression), 772 exp.TsOrDsToDate: _ts_or_ds_to_date_sql, 773 exp.UnixToTime: _unix_to_time_sql, 774 exp.Week: _remove_ts_or_ds_to_date(), 775 exp.WeekOfYear: _remove_ts_or_ds_to_date(rename_func("WEEKOFYEAR")), 776 exp.Year: _remove_ts_or_ds_to_date(), 777 } 778 779 UNSIGNED_TYPE_MAPPING = { 780 exp.DataType.Type.UBIGINT: "BIGINT", 781 exp.DataType.Type.UINT: "INT", 782 exp.DataType.Type.UMEDIUMINT: "MEDIUMINT", 783 exp.DataType.Type.USMALLINT: "SMALLINT", 784 exp.DataType.Type.UTINYINT: "TINYINT", 785 exp.DataType.Type.UDECIMAL: "DECIMAL", 786 } 787 788 TIMESTAMP_TYPE_MAPPING = { 789 exp.DataType.Type.TIMESTAMP: "DATETIME", 790 exp.DataType.Type.TIMESTAMPTZ: "TIMESTAMP", 791 exp.DataType.Type.TIMESTAMPLTZ: "TIMESTAMP", 792 } 793 794 TYPE_MAPPING = { 795 **generator.Generator.TYPE_MAPPING, 796 **UNSIGNED_TYPE_MAPPING, 797 **TIMESTAMP_TYPE_MAPPING, 798 } 799 800 TYPE_MAPPING.pop(exp.DataType.Type.MEDIUMTEXT) 801 TYPE_MAPPING.pop(exp.DataType.Type.LONGTEXT) 802 TYPE_MAPPING.pop(exp.DataType.Type.TINYTEXT) 803 TYPE_MAPPING.pop(exp.DataType.Type.MEDIUMBLOB) 804 TYPE_MAPPING.pop(exp.DataType.Type.LONGBLOB) 805 TYPE_MAPPING.pop(exp.DataType.Type.TINYBLOB) 806 807 PROPERTIES_LOCATION = { 808 **generator.Generator.PROPERTIES_LOCATION, 809 exp.TransientProperty: exp.Properties.Location.UNSUPPORTED, 810 exp.VolatileProperty: exp.Properties.Location.UNSUPPORTED, 811 } 812 813 LIMIT_FETCH = "LIMIT" 814 815 LIMIT_ONLY_LITERALS = True 816 817 CHAR_CAST_MAPPING = dict.fromkeys( 818 ( 819 exp.DataType.Type.LONGTEXT, 820 exp.DataType.Type.LONGBLOB, 821 exp.DataType.Type.MEDIUMBLOB, 822 exp.DataType.Type.MEDIUMTEXT, 823 exp.DataType.Type.TEXT, 824 exp.DataType.Type.TINYBLOB, 825 exp.DataType.Type.TINYTEXT, 826 exp.DataType.Type.VARCHAR, 827 ), 828 "CHAR", 829 ) 830 SIGNED_CAST_MAPPING = dict.fromkeys( 831 ( 832 exp.DataType.Type.BIGINT, 833 exp.DataType.Type.BOOLEAN, 834 exp.DataType.Type.INT, 835 exp.DataType.Type.SMALLINT, 836 exp.DataType.Type.TINYINT, 837 exp.DataType.Type.MEDIUMINT, 838 ), 839 "SIGNED", 840 ) 841 842 # MySQL doesn't support many datatypes in cast. 843 # https://dev.mysql.com/doc/refman/8.0/en/cast-functions.html#function_cast 844 CAST_MAPPING = { 845 **CHAR_CAST_MAPPING, 846 **SIGNED_CAST_MAPPING, 847 exp.DataType.Type.UBIGINT: "UNSIGNED", 848 } 849 850 TIMESTAMP_FUNC_TYPES = { 851 exp.DataType.Type.TIMESTAMPTZ, 852 exp.DataType.Type.TIMESTAMPLTZ, 853 } 854 855 # https://dev.mysql.com/doc/refman/8.0/en/keywords.html 856 RESERVED_KEYWORDS = { 857 "accessible", 858 "add", 859 "all", 860 "alter", 861 "analyze", 862 "and", 863 "as", 864 "asc", 865 "asensitive", 866 "before", 867 "between", 868 "bigint", 869 "binary", 870 "blob", 871 "both", 872 "by", 873 "call", 874 "cascade", 875 "case", 876 "change", 877 "char", 878 "character", 879 "check", 880 "collate", 881 "column", 882 "condition", 883 "constraint", 884 "continue", 885 "convert", 886 "create", 887 "cross", 888 "cube", 889 "cume_dist", 890 "current_date", 891 "current_time", 892 "current_timestamp", 893 "current_user", 894 "cursor", 895 "database", 896 "databases", 897 "day_hour", 898 "day_microsecond", 899 "day_minute", 900 "day_second", 901 "dec", 902 "decimal", 903 "declare", 904 "default", 905 "delayed", 906 "delete", 907 "dense_rank", 908 "desc", 909 "describe", 910 "deterministic", 911 "distinct", 912 "distinctrow", 913 "div", 914 "double", 915 "drop", 916 "dual", 917 "each", 918 "else", 919 "elseif", 920 "empty", 921 "enclosed", 922 "escaped", 923 "except", 924 "exists", 925 "exit", 926 "explain", 927 "false", 928 "fetch", 929 "first_value", 930 "float", 931 "float4", 932 "float8", 933 "for", 934 "force", 935 "foreign", 936 "from", 937 "fulltext", 938 "function", 939 "generated", 940 "get", 941 "grant", 942 "group", 943 "grouping", 944 "groups", 945 "having", 946 "high_priority", 947 "hour_microsecond", 948 "hour_minute", 949 "hour_second", 950 "if", 951 "ignore", 952 "in", 953 "index", 954 "infile", 955 "inner", 956 "inout", 957 "insensitive", 958 "insert", 959 "int", 960 "int1", 961 "int2", 962 "int3", 963 "int4", 964 "int8", 965 "integer", 966 "intersect", 967 "interval", 968 "into", 969 "io_after_gtids", 970 "io_before_gtids", 971 "is", 972 "iterate", 973 "join", 974 "json_table", 975 "key", 976 "keys", 977 "kill", 978 "lag", 979 "last_value", 980 "lateral", 981 "lead", 982 "leading", 983 "leave", 984 "left", 985 "like", 986 "limit", 987 "linear", 988 "lines", 989 "load", 990 "localtime", 991 "localtimestamp", 992 "lock", 993 "long", 994 "longblob", 995 "longtext", 996 "loop", 997 "low_priority", 998 "master_bind", 999 "master_ssl_verify_server_cert", 1000 "match", 1001 "maxvalue", 1002 "mediumblob", 1003 "mediumint", 1004 "mediumtext", 1005 "middleint", 1006 "minute_microsecond", 1007 "minute_second", 1008 "mod", 1009 "modifies", 1010 "natural", 1011 "not", 1012 "no_write_to_binlog", 1013 "nth_value", 1014 "ntile", 1015 "null", 1016 "numeric", 1017 "of", 1018 "on", 1019 "optimize", 1020 "optimizer_costs", 1021 "option", 1022 "optionally", 1023 "or", 1024 "order", 1025 "out", 1026 "outer", 1027 "outfile", 1028 "over", 1029 "partition", 1030 "percent_rank", 1031 "precision", 1032 "primary", 1033 "procedure", 1034 "purge", 1035 "range", 1036 "rank", 1037 "read", 1038 "reads", 1039 "read_write", 1040 "real", 1041 "recursive", 1042 "references", 1043 "regexp", 1044 "release", 1045 "rename", 1046 "repeat", 1047 "replace", 1048 "require", 1049 "resignal", 1050 "restrict", 1051 "return", 1052 "revoke", 1053 "right", 1054 "rlike", 1055 "row", 1056 "rows", 1057 "row_number", 1058 "schema", 1059 "schemas", 1060 "second_microsecond", 1061 "select", 1062 "sensitive", 1063 "separator", 1064 "set", 1065 "show", 1066 "signal", 1067 "smallint", 1068 "spatial", 1069 "specific", 1070 "sql", 1071 "sqlexception", 1072 "sqlstate", 1073 "sqlwarning", 1074 "sql_big_result", 1075 "sql_calc_found_rows", 1076 "sql_small_result", 1077 "ssl", 1078 "starting", 1079 "stored", 1080 "straight_join", 1081 "system", 1082 "table", 1083 "terminated", 1084 "then", 1085 "tinyblob", 1086 "tinyint", 1087 "tinytext", 1088 "to", 1089 "trailing", 1090 "trigger", 1091 "true", 1092 "undo", 1093 "union", 1094 "unique", 1095 "unlock", 1096 "unsigned", 1097 "update", 1098 "usage", 1099 "use", 1100 "using", 1101 "utc_date", 1102 "utc_time", 1103 "utc_timestamp", 1104 "values", 1105 "varbinary", 1106 "varchar", 1107 "varcharacter", 1108 "varying", 1109 "virtual", 1110 "when", 1111 "where", 1112 "while", 1113 "window", 1114 "with", 1115 "write", 1116 "xor", 1117 "year_month", 1118 "zerofill", 1119 } 1120 1121 def array_sql(self, expression: exp.Array) -> str: 1122 self.unsupported("Arrays are not supported by MySQL") 1123 return self.function_fallback_sql(expression) 1124 1125 def arraycontainsall_sql(self, expression: exp.ArrayContainsAll) -> str: 1126 self.unsupported("Array operations are not supported by MySQL") 1127 return self.function_fallback_sql(expression) 1128 1129 def dpipe_sql(self, expression: exp.DPipe) -> str: 1130 return self.func("CONCAT", *expression.flatten()) 1131 1132 def extract_sql(self, expression: exp.Extract) -> str: 1133 unit = expression.name 1134 if unit and unit.lower() == "epoch": 1135 return self.func("UNIX_TIMESTAMP", expression.expression) 1136 1137 return super().extract_sql(expression) 1138 1139 def datatype_sql(self, expression: exp.DataType) -> str: 1140 if ( 1141 self.VARCHAR_REQUIRES_SIZE 1142 and expression.is_type(exp.DataType.Type.VARCHAR) 1143 and not expression.expressions 1144 ): 1145 # `VARCHAR` must always have a size - if it doesn't, we always generate `TEXT` 1146 return "TEXT" 1147 1148 # https://dev.mysql.com/doc/refman/8.0/en/numeric-type-syntax.html 1149 result = super().datatype_sql(expression) 1150 if expression.this in self.UNSIGNED_TYPE_MAPPING: 1151 result = f"{result} UNSIGNED" 1152 1153 return result 1154 1155 def jsonarraycontains_sql(self, expression: exp.JSONArrayContains) -> str: 1156 return f"{self.sql(expression, 'this')} MEMBER OF({self.sql(expression, 'expression')})" 1157 1158 def cast_sql(self, expression: exp.Cast, safe_prefix: t.Optional[str] = None) -> str: 1159 if expression.to.this in self.TIMESTAMP_FUNC_TYPES: 1160 return self.func("TIMESTAMP", expression.this) 1161 1162 to = self.CAST_MAPPING.get(expression.to.this) 1163 1164 if to: 1165 expression.to.set("this", to) 1166 return super().cast_sql(expression) 1167 1168 def show_sql(self, expression: exp.Show) -> str: 1169 this = f" {expression.name}" 1170 full = " FULL" if expression.args.get("full") else "" 1171 global_ = " GLOBAL" if expression.args.get("global") else "" 1172 1173 target = self.sql(expression, "target") 1174 target = f" {target}" if target else "" 1175 if expression.name in ("COLUMNS", "INDEX"): 1176 target = f" FROM{target}" 1177 elif expression.name == "GRANTS": 1178 target = f" FOR{target}" 1179 1180 db = self._prefixed_sql("FROM", expression, "db") 1181 1182 like = self._prefixed_sql("LIKE", expression, "like") 1183 where = self.sql(expression, "where") 1184 1185 types = self.expressions(expression, key="types") 1186 types = f" {types}" if types else types 1187 query = self._prefixed_sql("FOR QUERY", expression, "query") 1188 1189 if expression.name == "PROFILE": 1190 offset = self._prefixed_sql("OFFSET", expression, "offset") 1191 limit = self._prefixed_sql("LIMIT", expression, "limit") 1192 else: 1193 offset = "" 1194 limit = self._oldstyle_limit_sql(expression) 1195 1196 log = self._prefixed_sql("IN", expression, "log") 1197 position = self._prefixed_sql("FROM", expression, "position") 1198 1199 channel = self._prefixed_sql("FOR CHANNEL", expression, "channel") 1200 1201 if expression.name == "ENGINE": 1202 mutex_or_status = " MUTEX" if expression.args.get("mutex") else " STATUS" 1203 else: 1204 mutex_or_status = "" 1205 1206 return f"SHOW{full}{global_}{this}{target}{types}{db}{query}{log}{position}{channel}{mutex_or_status}{like}{where}{offset}{limit}" 1207 1208 def altercolumn_sql(self, expression: exp.AlterColumn) -> str: 1209 dtype = self.sql(expression, "dtype") 1210 if not dtype: 1211 return super().altercolumn_sql(expression) 1212 1213 this = self.sql(expression, "this") 1214 return f"MODIFY COLUMN {this} {dtype}" 1215 1216 def _prefixed_sql(self, prefix: str, expression: exp.Expression, arg: str) -> str: 1217 sql = self.sql(expression, arg) 1218 return f" {prefix} {sql}" if sql else "" 1219 1220 def _oldstyle_limit_sql(self, expression: exp.Show) -> str: 1221 limit = self.sql(expression, "limit") 1222 offset = self.sql(expression, "offset") 1223 if limit: 1224 limit_offset = f"{offset}, {limit}" if offset else limit 1225 return f" LIMIT {limit_offset}" 1226 return "" 1227 1228 def chr_sql(self, expression: exp.Chr) -> str: 1229 this = self.expressions(sqls=[expression.this] + expression.expressions) 1230 charset = expression.args.get("charset") 1231 using = f" USING {self.sql(charset)}" if charset else "" 1232 return f"CHAR({this}{using})" 1233 1234 def timestamptrunc_sql(self, expression: exp.TimestampTrunc) -> str: 1235 unit = expression.args.get("unit") 1236 1237 # Pick an old-enough date to avoid negative timestamp diffs 1238 start_ts = "'0000-01-01 00:00:00'" 1239 1240 # Source: https://stackoverflow.com/a/32955740 1241 timestamp_diff = build_date_delta(exp.TimestampDiff)([unit, start_ts, expression.this]) 1242 interval = exp.Interval(this=timestamp_diff, unit=unit) 1243 dateadd = build_date_delta_with_interval(exp.DateAdd)([start_ts, interval]) 1244 1245 return self.sql(dateadd) 1246 1247 def converttimezone_sql(self, expression: exp.ConvertTimezone) -> str: 1248 from_tz = expression.args.get("source_tz") 1249 to_tz = expression.args.get("target_tz") 1250 dt = expression.args.get("timestamp") 1251 1252 return self.func("CONVERT_TZ", dt, from_tz, to_tz) 1253 1254 def attimezone_sql(self, expression: exp.AtTimeZone) -> str: 1255 self.unsupported("AT TIME ZONE is not supported by MySQL") 1256 return self.sql(expression.this)
TIME_SPECIFIERS =
{'T', 's', 'H', 'f', 'S', 'p', 'I', 'r', 'l', 'h', 'i', 'k'}
def
date_add_sql( kind: str) -> Callable[[sqlglot.generator.Generator, sqlglot.expressions.Expression], str]:
115def date_add_sql( 116 kind: str, 117) -> t.Callable[[generator.Generator, exp.Expression], str]: 118 def func(self: generator.Generator, expression: exp.Expression) -> str: 119 return self.func( 120 f"DATE_{kind}", 121 expression.this, 122 exp.Interval(this=expression.expression, unit=unit_to_var(expression)), 123 ) 124 125 return func
148class MySQL(Dialect): 149 PROMOTE_TO_INFERRED_DATETIME_TYPE = True 150 151 # https://dev.mysql.com/doc/refman/8.0/en/identifiers.html 152 IDENTIFIERS_CAN_START_WITH_DIGIT = True 153 154 # We default to treating all identifiers as case-sensitive, since it matches MySQL's 155 # behavior on Linux systems. For MacOS and Windows systems, one can override this 156 # setting by specifying `dialect="mysql, normalization_strategy = lowercase"`. 157 # 158 # See also https://dev.mysql.com/doc/refman/8.2/en/identifier-case-sensitivity.html 159 NORMALIZATION_STRATEGY = NormalizationStrategy.CASE_SENSITIVE 160 161 TIME_FORMAT = "'%Y-%m-%d %T'" 162 DPIPE_IS_STRING_CONCAT = False 163 SUPPORTS_USER_DEFINED_TYPES = False 164 SUPPORTS_SEMI_ANTI_JOIN = False 165 SAFE_DIVISION = True 166 167 # https://prestodb.io/docs/current/functions/datetime.html#mysql-date-functions 168 TIME_MAPPING = { 169 "%M": "%B", 170 "%c": "%-m", 171 "%e": "%-d", 172 "%h": "%I", 173 "%i": "%M", 174 "%s": "%S", 175 "%u": "%W", 176 "%k": "%-H", 177 "%l": "%-I", 178 "%T": "%H:%M:%S", 179 "%W": "%A", 180 } 181 182 class Tokenizer(tokens.Tokenizer): 183 QUOTES = ["'", '"'] 184 COMMENTS = ["--", "#", ("/*", "*/")] 185 IDENTIFIERS = ["`"] 186 STRING_ESCAPES = ["'", '"', "\\"] 187 BIT_STRINGS = [("b'", "'"), ("B'", "'"), ("0b", "")] 188 HEX_STRINGS = [("x'", "'"), ("X'", "'"), ("0x", "")] 189 190 KEYWORDS = { 191 **tokens.Tokenizer.KEYWORDS, 192 "CHARSET": TokenType.CHARACTER_SET, 193 # The DESCRIBE and EXPLAIN statements are synonyms. 194 # https://dev.mysql.com/doc/refman/8.4/en/explain.html 195 "EXPLAIN": TokenType.DESCRIBE, 196 "FORCE": TokenType.FORCE, 197 "IGNORE": TokenType.IGNORE, 198 "KEY": TokenType.KEY, 199 "LOCK TABLES": TokenType.COMMAND, 200 "LONGBLOB": TokenType.LONGBLOB, 201 "LONGTEXT": TokenType.LONGTEXT, 202 "MEDIUMBLOB": TokenType.MEDIUMBLOB, 203 "TINYBLOB": TokenType.TINYBLOB, 204 "TINYTEXT": TokenType.TINYTEXT, 205 "MEDIUMTEXT": TokenType.MEDIUMTEXT, 206 "MEDIUMINT": TokenType.MEDIUMINT, 207 "MEMBER OF": TokenType.MEMBER_OF, 208 "SEPARATOR": TokenType.SEPARATOR, 209 "START": TokenType.BEGIN, 210 "SIGNED": TokenType.BIGINT, 211 "SIGNED INTEGER": TokenType.BIGINT, 212 "UNLOCK TABLES": TokenType.COMMAND, 213 "UNSIGNED": TokenType.UBIGINT, 214 "UNSIGNED INTEGER": TokenType.UBIGINT, 215 "YEAR": TokenType.YEAR, 216 "_ARMSCII8": TokenType.INTRODUCER, 217 "_ASCII": TokenType.INTRODUCER, 218 "_BIG5": TokenType.INTRODUCER, 219 "_BINARY": TokenType.INTRODUCER, 220 "_CP1250": TokenType.INTRODUCER, 221 "_CP1251": TokenType.INTRODUCER, 222 "_CP1256": TokenType.INTRODUCER, 223 "_CP1257": TokenType.INTRODUCER, 224 "_CP850": TokenType.INTRODUCER, 225 "_CP852": TokenType.INTRODUCER, 226 "_CP866": TokenType.INTRODUCER, 227 "_CP932": TokenType.INTRODUCER, 228 "_DEC8": TokenType.INTRODUCER, 229 "_EUCJPMS": TokenType.INTRODUCER, 230 "_EUCKR": TokenType.INTRODUCER, 231 "_GB18030": TokenType.INTRODUCER, 232 "_GB2312": TokenType.INTRODUCER, 233 "_GBK": TokenType.INTRODUCER, 234 "_GEOSTD8": TokenType.INTRODUCER, 235 "_GREEK": TokenType.INTRODUCER, 236 "_HEBREW": TokenType.INTRODUCER, 237 "_HP8": TokenType.INTRODUCER, 238 "_KEYBCS2": TokenType.INTRODUCER, 239 "_KOI8R": TokenType.INTRODUCER, 240 "_KOI8U": TokenType.INTRODUCER, 241 "_LATIN1": TokenType.INTRODUCER, 242 "_LATIN2": TokenType.INTRODUCER, 243 "_LATIN5": TokenType.INTRODUCER, 244 "_LATIN7": TokenType.INTRODUCER, 245 "_MACCE": TokenType.INTRODUCER, 246 "_MACROMAN": TokenType.INTRODUCER, 247 "_SJIS": TokenType.INTRODUCER, 248 "_SWE7": TokenType.INTRODUCER, 249 "_TIS620": TokenType.INTRODUCER, 250 "_UCS2": TokenType.INTRODUCER, 251 "_UJIS": TokenType.INTRODUCER, 252 # https://dev.mysql.com/doc/refman/8.0/en/string-literals.html 253 "_UTF8": TokenType.INTRODUCER, 254 "_UTF16": TokenType.INTRODUCER, 255 "_UTF16LE": TokenType.INTRODUCER, 256 "_UTF32": TokenType.INTRODUCER, 257 "_UTF8MB3": TokenType.INTRODUCER, 258 "_UTF8MB4": TokenType.INTRODUCER, 259 "@@": TokenType.SESSION_PARAMETER, 260 } 261 262 COMMANDS = {*tokens.Tokenizer.COMMANDS, TokenType.REPLACE} - {TokenType.SHOW} 263 264 class Parser(parser.Parser): 265 FUNC_TOKENS = { 266 *parser.Parser.FUNC_TOKENS, 267 TokenType.DATABASE, 268 TokenType.SCHEMA, 269 TokenType.VALUES, 270 } 271 272 CONJUNCTION = { 273 **parser.Parser.CONJUNCTION, 274 TokenType.DAMP: exp.And, 275 TokenType.XOR: exp.Xor, 276 } 277 278 DISJUNCTION = { 279 **parser.Parser.DISJUNCTION, 280 TokenType.DPIPE: exp.Or, 281 } 282 283 TABLE_ALIAS_TOKENS = ( 284 parser.Parser.TABLE_ALIAS_TOKENS - parser.Parser.TABLE_INDEX_HINT_TOKENS 285 ) 286 287 RANGE_PARSERS = { 288 **parser.Parser.RANGE_PARSERS, 289 TokenType.MEMBER_OF: lambda self, this: self.expression( 290 exp.JSONArrayContains, 291 this=this, 292 expression=self._parse_wrapped(self._parse_expression), 293 ), 294 } 295 296 FUNCTIONS = { 297 **parser.Parser.FUNCTIONS, 298 "CHAR_LENGTH": exp.Length.from_arg_list, 299 "CHARACTER_LENGTH": exp.Length.from_arg_list, 300 "CONVERT_TZ": lambda args: exp.ConvertTimezone( 301 source_tz=seq_get(args, 1), target_tz=seq_get(args, 2), timestamp=seq_get(args, 0) 302 ), 303 "DATE": lambda args: exp.TsOrDsToDate(this=seq_get(args, 0)), 304 "DATE_ADD": build_date_delta_with_interval(exp.DateAdd), 305 "DATE_FORMAT": build_formatted_time(exp.TimeToStr, "mysql"), 306 "DATE_SUB": build_date_delta_with_interval(exp.DateSub), 307 "DAY": lambda args: exp.Day(this=exp.TsOrDsToDate(this=seq_get(args, 0))), 308 "DAYOFMONTH": lambda args: exp.DayOfMonth(this=exp.TsOrDsToDate(this=seq_get(args, 0))), 309 "DAYOFWEEK": lambda args: exp.DayOfWeek(this=exp.TsOrDsToDate(this=seq_get(args, 0))), 310 "DAYOFYEAR": lambda args: exp.DayOfYear(this=exp.TsOrDsToDate(this=seq_get(args, 0))), 311 "FROM_UNIXTIME": build_formatted_time(exp.UnixToTime, "mysql"), 312 "ISNULL": isnull_to_is_null, 313 "LOCATE": locate_to_strposition, 314 "MAKETIME": exp.TimeFromParts.from_arg_list, 315 "MONTH": lambda args: exp.Month(this=exp.TsOrDsToDate(this=seq_get(args, 0))), 316 "MONTHNAME": lambda args: exp.TimeToStr( 317 this=exp.TsOrDsToDate(this=seq_get(args, 0)), 318 format=exp.Literal.string("%B"), 319 ), 320 "STR_TO_DATE": _str_to_date, 321 "TIMESTAMPDIFF": build_date_delta(exp.TimestampDiff), 322 "TO_DAYS": lambda args: exp.paren( 323 exp.DateDiff( 324 this=exp.TsOrDsToDate(this=seq_get(args, 0)), 325 expression=exp.TsOrDsToDate(this=exp.Literal.string("0000-01-01")), 326 unit=exp.var("DAY"), 327 ) 328 + 1 329 ), 330 "WEEK": lambda args: exp.Week( 331 this=exp.TsOrDsToDate(this=seq_get(args, 0)), mode=seq_get(args, 1) 332 ), 333 "WEEKOFYEAR": lambda args: exp.WeekOfYear(this=exp.TsOrDsToDate(this=seq_get(args, 0))), 334 "YEAR": lambda args: exp.Year(this=exp.TsOrDsToDate(this=seq_get(args, 0))), 335 } 336 337 FUNCTION_PARSERS = { 338 **parser.Parser.FUNCTION_PARSERS, 339 "CHAR": lambda self: self.expression( 340 exp.Chr, 341 expressions=self._parse_csv(self._parse_assignment), 342 charset=self._match(TokenType.USING) and self._parse_var(), 343 ), 344 "GROUP_CONCAT": lambda self: self._parse_group_concat(), 345 # https://dev.mysql.com/doc/refman/5.7/en/miscellaneous-functions.html#function_values 346 "VALUES": lambda self: self.expression( 347 exp.Anonymous, this="VALUES", expressions=[self._parse_id_var()] 348 ), 349 "JSON_VALUE": lambda self: self._parse_json_value(), 350 } 351 352 STATEMENT_PARSERS = { 353 **parser.Parser.STATEMENT_PARSERS, 354 TokenType.SHOW: lambda self: self._parse_show(), 355 } 356 357 SHOW_PARSERS = { 358 "BINARY LOGS": _show_parser("BINARY LOGS"), 359 "MASTER LOGS": _show_parser("BINARY LOGS"), 360 "BINLOG EVENTS": _show_parser("BINLOG EVENTS"), 361 "CHARACTER SET": _show_parser("CHARACTER SET"), 362 "CHARSET": _show_parser("CHARACTER SET"), 363 "COLLATION": _show_parser("COLLATION"), 364 "FULL COLUMNS": _show_parser("COLUMNS", target="FROM", full=True), 365 "COLUMNS": _show_parser("COLUMNS", target="FROM"), 366 "CREATE DATABASE": _show_parser("CREATE DATABASE", target=True), 367 "CREATE EVENT": _show_parser("CREATE EVENT", target=True), 368 "CREATE FUNCTION": _show_parser("CREATE FUNCTION", target=True), 369 "CREATE PROCEDURE": _show_parser("CREATE PROCEDURE", target=True), 370 "CREATE TABLE": _show_parser("CREATE TABLE", target=True), 371 "CREATE TRIGGER": _show_parser("CREATE TRIGGER", target=True), 372 "CREATE VIEW": _show_parser("CREATE VIEW", target=True), 373 "DATABASES": _show_parser("DATABASES"), 374 "SCHEMAS": _show_parser("DATABASES"), 375 "ENGINE": _show_parser("ENGINE", target=True), 376 "STORAGE ENGINES": _show_parser("ENGINES"), 377 "ENGINES": _show_parser("ENGINES"), 378 "ERRORS": _show_parser("ERRORS"), 379 "EVENTS": _show_parser("EVENTS"), 380 "FUNCTION CODE": _show_parser("FUNCTION CODE", target=True), 381 "FUNCTION STATUS": _show_parser("FUNCTION STATUS"), 382 "GRANTS": _show_parser("GRANTS", target="FOR"), 383 "INDEX": _show_parser("INDEX", target="FROM"), 384 "MASTER STATUS": _show_parser("MASTER STATUS"), 385 "OPEN TABLES": _show_parser("OPEN TABLES"), 386 "PLUGINS": _show_parser("PLUGINS"), 387 "PROCEDURE CODE": _show_parser("PROCEDURE CODE", target=True), 388 "PROCEDURE STATUS": _show_parser("PROCEDURE STATUS"), 389 "PRIVILEGES": _show_parser("PRIVILEGES"), 390 "FULL PROCESSLIST": _show_parser("PROCESSLIST", full=True), 391 "PROCESSLIST": _show_parser("PROCESSLIST"), 392 "PROFILE": _show_parser("PROFILE"), 393 "PROFILES": _show_parser("PROFILES"), 394 "RELAYLOG EVENTS": _show_parser("RELAYLOG EVENTS"), 395 "REPLICAS": _show_parser("REPLICAS"), 396 "SLAVE HOSTS": _show_parser("REPLICAS"), 397 "REPLICA STATUS": _show_parser("REPLICA STATUS"), 398 "SLAVE STATUS": _show_parser("REPLICA STATUS"), 399 "GLOBAL STATUS": _show_parser("STATUS", global_=True), 400 "SESSION STATUS": _show_parser("STATUS"), 401 "STATUS": _show_parser("STATUS"), 402 "TABLE STATUS": _show_parser("TABLE STATUS"), 403 "FULL TABLES": _show_parser("TABLES", full=True), 404 "TABLES": _show_parser("TABLES"), 405 "TRIGGERS": _show_parser("TRIGGERS"), 406 "GLOBAL VARIABLES": _show_parser("VARIABLES", global_=True), 407 "SESSION VARIABLES": _show_parser("VARIABLES"), 408 "VARIABLES": _show_parser("VARIABLES"), 409 "WARNINGS": _show_parser("WARNINGS"), 410 } 411 412 PROPERTY_PARSERS = { 413 **parser.Parser.PROPERTY_PARSERS, 414 "LOCK": lambda self: self._parse_property_assignment(exp.LockProperty), 415 } 416 417 SET_PARSERS = { 418 **parser.Parser.SET_PARSERS, 419 "PERSIST": lambda self: self._parse_set_item_assignment("PERSIST"), 420 "PERSIST_ONLY": lambda self: self._parse_set_item_assignment("PERSIST_ONLY"), 421 "CHARACTER SET": lambda self: self._parse_set_item_charset("CHARACTER SET"), 422 "CHARSET": lambda self: self._parse_set_item_charset("CHARACTER SET"), 423 "NAMES": lambda self: self._parse_set_item_names(), 424 } 425 426 CONSTRAINT_PARSERS = { 427 **parser.Parser.CONSTRAINT_PARSERS, 428 "FULLTEXT": lambda self: self._parse_index_constraint(kind="FULLTEXT"), 429 "INDEX": lambda self: self._parse_index_constraint(), 430 "KEY": lambda self: self._parse_index_constraint(), 431 "SPATIAL": lambda self: self._parse_index_constraint(kind="SPATIAL"), 432 } 433 434 ALTER_PARSERS = { 435 **parser.Parser.ALTER_PARSERS, 436 "MODIFY": lambda self: self._parse_alter_table_alter(), 437 } 438 439 SCHEMA_UNNAMED_CONSTRAINTS = { 440 *parser.Parser.SCHEMA_UNNAMED_CONSTRAINTS, 441 "FULLTEXT", 442 "INDEX", 443 "KEY", 444 "SPATIAL", 445 } 446 447 PROFILE_TYPES: parser.OPTIONS_TYPE = { 448 **dict.fromkeys(("ALL", "CPU", "IPC", "MEMORY", "SOURCE", "SWAPS"), tuple()), 449 "BLOCK": ("IO",), 450 "CONTEXT": ("SWITCHES",), 451 "PAGE": ("FAULTS",), 452 } 453 454 TYPE_TOKENS = { 455 *parser.Parser.TYPE_TOKENS, 456 TokenType.SET, 457 } 458 459 ENUM_TYPE_TOKENS = { 460 *parser.Parser.ENUM_TYPE_TOKENS, 461 TokenType.SET, 462 } 463 464 # SELECT [ ALL | DISTINCT | DISTINCTROW ] [ <OPERATION_MODIFIERS> ] 465 OPERATION_MODIFIERS = { 466 "HIGH_PRIORITY", 467 "STRAIGHT_JOIN", 468 "SQL_SMALL_RESULT", 469 "SQL_BIG_RESULT", 470 "SQL_BUFFER_RESULT", 471 "SQL_NO_CACHE", 472 "SQL_CALC_FOUND_ROWS", 473 } 474 475 LOG_DEFAULTS_TO_LN = True 476 STRING_ALIASES = True 477 VALUES_FOLLOWED_BY_PAREN = False 478 SUPPORTS_PARTITION_SELECTION = True 479 480 def _parse_primary_key_part(self) -> t.Optional[exp.Expression]: 481 this = self._parse_id_var() 482 if not self._match(TokenType.L_PAREN): 483 return this 484 485 expression = self._parse_number() 486 self._match_r_paren() 487 return self.expression(exp.ColumnPrefix, this=this, expression=expression) 488 489 def _parse_index_constraint( 490 self, kind: t.Optional[str] = None 491 ) -> exp.IndexColumnConstraint: 492 if kind: 493 self._match_texts(("INDEX", "KEY")) 494 495 this = self._parse_id_var(any_token=False) 496 index_type = self._match(TokenType.USING) and self._advance_any() and self._prev.text 497 expressions = self._parse_wrapped_csv(self._parse_ordered) 498 499 options = [] 500 while True: 501 if self._match_text_seq("KEY_BLOCK_SIZE"): 502 self._match(TokenType.EQ) 503 opt = exp.IndexConstraintOption(key_block_size=self._parse_number()) 504 elif self._match(TokenType.USING): 505 opt = exp.IndexConstraintOption(using=self._advance_any() and self._prev.text) 506 elif self._match_text_seq("WITH", "PARSER"): 507 opt = exp.IndexConstraintOption(parser=self._parse_var(any_token=True)) 508 elif self._match(TokenType.COMMENT): 509 opt = exp.IndexConstraintOption(comment=self._parse_string()) 510 elif self._match_text_seq("VISIBLE"): 511 opt = exp.IndexConstraintOption(visible=True) 512 elif self._match_text_seq("INVISIBLE"): 513 opt = exp.IndexConstraintOption(visible=False) 514 elif self._match_text_seq("ENGINE_ATTRIBUTE"): 515 self._match(TokenType.EQ) 516 opt = exp.IndexConstraintOption(engine_attr=self._parse_string()) 517 elif self._match_text_seq("SECONDARY_ENGINE_ATTRIBUTE"): 518 self._match(TokenType.EQ) 519 opt = exp.IndexConstraintOption(secondary_engine_attr=self._parse_string()) 520 else: 521 opt = None 522 523 if not opt: 524 break 525 526 options.append(opt) 527 528 return self.expression( 529 exp.IndexColumnConstraint, 530 this=this, 531 expressions=expressions, 532 kind=kind, 533 index_type=index_type, 534 options=options, 535 ) 536 537 def _parse_show_mysql( 538 self, 539 this: str, 540 target: bool | str = False, 541 full: t.Optional[bool] = None, 542 global_: t.Optional[bool] = None, 543 ) -> exp.Show: 544 if target: 545 if isinstance(target, str): 546 self._match_text_seq(target) 547 target_id = self._parse_id_var() 548 else: 549 target_id = None 550 551 log = self._parse_string() if self._match_text_seq("IN") else None 552 553 if this in ("BINLOG EVENTS", "RELAYLOG EVENTS"): 554 position = self._parse_number() if self._match_text_seq("FROM") else None 555 db = None 556 else: 557 position = None 558 db = None 559 560 if self._match(TokenType.FROM): 561 db = self._parse_id_var() 562 elif self._match(TokenType.DOT): 563 db = target_id 564 target_id = self._parse_id_var() 565 566 channel = self._parse_id_var() if self._match_text_seq("FOR", "CHANNEL") else None 567 568 like = self._parse_string() if self._match_text_seq("LIKE") else None 569 where = self._parse_where() 570 571 if this == "PROFILE": 572 types = self._parse_csv(lambda: self._parse_var_from_options(self.PROFILE_TYPES)) 573 query = self._parse_number() if self._match_text_seq("FOR", "QUERY") else None 574 offset = self._parse_number() if self._match_text_seq("OFFSET") else None 575 limit = self._parse_number() if self._match_text_seq("LIMIT") else None 576 else: 577 types, query = None, None 578 offset, limit = self._parse_oldstyle_limit() 579 580 mutex = True if self._match_text_seq("MUTEX") else None 581 mutex = False if self._match_text_seq("STATUS") else mutex 582 583 return self.expression( 584 exp.Show, 585 this=this, 586 target=target_id, 587 full=full, 588 log=log, 589 position=position, 590 db=db, 591 channel=channel, 592 like=like, 593 where=where, 594 types=types, 595 query=query, 596 offset=offset, 597 limit=limit, 598 mutex=mutex, 599 **{"global": global_}, # type: ignore 600 ) 601 602 def _parse_oldstyle_limit( 603 self, 604 ) -> t.Tuple[t.Optional[exp.Expression], t.Optional[exp.Expression]]: 605 limit = None 606 offset = None 607 if self._match_text_seq("LIMIT"): 608 parts = self._parse_csv(self._parse_number) 609 if len(parts) == 1: 610 limit = parts[0] 611 elif len(parts) == 2: 612 limit = parts[1] 613 offset = parts[0] 614 615 return offset, limit 616 617 def _parse_set_item_charset(self, kind: str) -> exp.Expression: 618 this = self._parse_string() or self._parse_unquoted_field() 619 return self.expression(exp.SetItem, this=this, kind=kind) 620 621 def _parse_set_item_names(self) -> exp.Expression: 622 charset = self._parse_string() or self._parse_unquoted_field() 623 if self._match_text_seq("COLLATE"): 624 collate = self._parse_string() or self._parse_unquoted_field() 625 else: 626 collate = None 627 628 return self.expression(exp.SetItem, this=charset, collate=collate, kind="NAMES") 629 630 def _parse_type( 631 self, parse_interval: bool = True, fallback_to_identifier: bool = False 632 ) -> t.Optional[exp.Expression]: 633 # mysql binary is special and can work anywhere, even in order by operations 634 # it operates like a no paren func 635 if self._match(TokenType.BINARY, advance=False): 636 data_type = self._parse_types(check_func=True, allow_identifiers=False) 637 638 if isinstance(data_type, exp.DataType): 639 return self.expression(exp.Cast, this=self._parse_column(), to=data_type) 640 641 return super()._parse_type( 642 parse_interval=parse_interval, fallback_to_identifier=fallback_to_identifier 643 ) 644 645 def _parse_group_concat(self) -> t.Optional[exp.Expression]: 646 def concat_exprs( 647 node: t.Optional[exp.Expression], exprs: t.List[exp.Expression] 648 ) -> exp.Expression: 649 if isinstance(node, exp.Distinct) and len(node.expressions) > 1: 650 concat_exprs = [ 651 self.expression(exp.Concat, expressions=node.expressions, safe=True) 652 ] 653 node.set("expressions", concat_exprs) 654 return node 655 if len(exprs) == 1: 656 return exprs[0] 657 return self.expression(exp.Concat, expressions=args, safe=True) 658 659 args = self._parse_csv(self._parse_lambda) 660 661 if args: 662 order = args[-1] if isinstance(args[-1], exp.Order) else None 663 664 if order: 665 # Order By is the last (or only) expression in the list and has consumed the 'expr' before it, 666 # remove 'expr' from exp.Order and add it back to args 667 args[-1] = order.this 668 order.set("this", concat_exprs(order.this, args)) 669 670 this = order or concat_exprs(args[0], args) 671 else: 672 this = None 673 674 separator = self._parse_field() if self._match(TokenType.SEPARATOR) else None 675 676 return self.expression(exp.GroupConcat, this=this, separator=separator) 677 678 def _parse_json_value(self) -> exp.JSONValue: 679 this = self._parse_bitwise() 680 self._match(TokenType.COMMA) 681 path = self._parse_bitwise() 682 683 returning = self._match(TokenType.RETURNING) and self._parse_type() 684 685 return self.expression( 686 exp.JSONValue, 687 this=this, 688 path=self.dialect.to_json_path(path), 689 returning=returning, 690 on_condition=self._parse_on_condition(), 691 ) 692 693 class Generator(generator.Generator): 694 INTERVAL_ALLOWS_PLURAL_FORM = False 695 LOCKING_READS_SUPPORTED = True 696 NULL_ORDERING_SUPPORTED = None 697 JOIN_HINTS = False 698 TABLE_HINTS = True 699 DUPLICATE_KEY_UPDATE_WITH_SET = False 700 QUERY_HINT_SEP = " " 701 VALUES_AS_TABLE = False 702 NVL2_SUPPORTED = False 703 LAST_DAY_SUPPORTS_DATE_PART = False 704 JSON_TYPE_REQUIRED_FOR_EXTRACTION = True 705 JSON_PATH_BRACKETED_KEY_SUPPORTED = False 706 JSON_KEY_VALUE_PAIR_SEP = "," 707 SUPPORTS_TO_NUMBER = False 708 PARSE_JSON_NAME: t.Optional[str] = None 709 PAD_FILL_PATTERN_IS_REQUIRED = True 710 WRAP_DERIVED_VALUES = False 711 VARCHAR_REQUIRES_SIZE = True 712 SUPPORTS_MEDIAN = False 713 714 TRANSFORMS = { 715 **generator.Generator.TRANSFORMS, 716 exp.ArrayAgg: rename_func("GROUP_CONCAT"), 717 exp.CurrentDate: no_paren_current_date_sql, 718 exp.DateDiff: _remove_ts_or_ds_to_date( 719 lambda self, e: self.func("DATEDIFF", e.this, e.expression), ("this", "expression") 720 ), 721 exp.DateAdd: _remove_ts_or_ds_to_date(date_add_sql("ADD")), 722 exp.DateStrToDate: datestrtodate_sql, 723 exp.DateSub: _remove_ts_or_ds_to_date(date_add_sql("SUB")), 724 exp.DateTrunc: _date_trunc_sql, 725 exp.Day: _remove_ts_or_ds_to_date(), 726 exp.DayOfMonth: _remove_ts_or_ds_to_date(rename_func("DAYOFMONTH")), 727 exp.DayOfWeek: _remove_ts_or_ds_to_date(rename_func("DAYOFWEEK")), 728 exp.DayOfYear: _remove_ts_or_ds_to_date(rename_func("DAYOFYEAR")), 729 exp.GroupConcat: lambda self, 730 e: f"""GROUP_CONCAT({self.sql(e, "this")} SEPARATOR {self.sql(e, "separator") or "','"})""", 731 exp.ILike: no_ilike_sql, 732 exp.JSONExtractScalar: arrow_json_extract_sql, 733 exp.Length: rename_func("CHAR_LENGTH"), 734 exp.Max: max_or_greatest, 735 exp.Min: min_or_least, 736 exp.Month: _remove_ts_or_ds_to_date(), 737 exp.NullSafeEQ: lambda self, e: self.binary(e, "<=>"), 738 exp.NullSafeNEQ: lambda self, e: f"NOT {self.binary(e, '<=>')}", 739 exp.Pivot: no_pivot_sql, 740 exp.Select: transforms.preprocess( 741 [ 742 transforms.eliminate_distinct_on, 743 transforms.eliminate_semi_and_anti_joins, 744 transforms.eliminate_qualify, 745 transforms.eliminate_full_outer_join, 746 transforms.unnest_generate_date_array_using_recursive_cte, 747 ] 748 ), 749 exp.StrPosition: strposition_to_locate_sql, 750 exp.StrToDate: _str_to_date_sql, 751 exp.StrToTime: _str_to_date_sql, 752 exp.Stuff: rename_func("INSERT"), 753 exp.TableSample: no_tablesample_sql, 754 exp.TimeFromParts: rename_func("MAKETIME"), 755 exp.TimestampAdd: date_add_interval_sql("DATE", "ADD"), 756 exp.TimestampDiff: lambda self, e: self.func( 757 "TIMESTAMPDIFF", unit_to_var(e), e.expression, e.this 758 ), 759 exp.TimestampSub: date_add_interval_sql("DATE", "SUB"), 760 exp.TimeStrToUnix: rename_func("UNIX_TIMESTAMP"), 761 exp.TimeStrToTime: lambda self, e: timestrtotime_sql( 762 self, 763 e, 764 include_precision=not e.args.get("zone"), 765 ), 766 exp.TimeToStr: _remove_ts_or_ds_to_date( 767 lambda self, e: self.func("DATE_FORMAT", e.this, self.format_time(e)) 768 ), 769 exp.Trim: trim_sql, 770 exp.TryCast: no_trycast_sql, 771 exp.TsOrDsAdd: date_add_sql("ADD"), 772 exp.TsOrDsDiff: lambda self, e: self.func("DATEDIFF", e.this, e.expression), 773 exp.TsOrDsToDate: _ts_or_ds_to_date_sql, 774 exp.UnixToTime: _unix_to_time_sql, 775 exp.Week: _remove_ts_or_ds_to_date(), 776 exp.WeekOfYear: _remove_ts_or_ds_to_date(rename_func("WEEKOFYEAR")), 777 exp.Year: _remove_ts_or_ds_to_date(), 778 } 779 780 UNSIGNED_TYPE_MAPPING = { 781 exp.DataType.Type.UBIGINT: "BIGINT", 782 exp.DataType.Type.UINT: "INT", 783 exp.DataType.Type.UMEDIUMINT: "MEDIUMINT", 784 exp.DataType.Type.USMALLINT: "SMALLINT", 785 exp.DataType.Type.UTINYINT: "TINYINT", 786 exp.DataType.Type.UDECIMAL: "DECIMAL", 787 } 788 789 TIMESTAMP_TYPE_MAPPING = { 790 exp.DataType.Type.TIMESTAMP: "DATETIME", 791 exp.DataType.Type.TIMESTAMPTZ: "TIMESTAMP", 792 exp.DataType.Type.TIMESTAMPLTZ: "TIMESTAMP", 793 } 794 795 TYPE_MAPPING = { 796 **generator.Generator.TYPE_MAPPING, 797 **UNSIGNED_TYPE_MAPPING, 798 **TIMESTAMP_TYPE_MAPPING, 799 } 800 801 TYPE_MAPPING.pop(exp.DataType.Type.MEDIUMTEXT) 802 TYPE_MAPPING.pop(exp.DataType.Type.LONGTEXT) 803 TYPE_MAPPING.pop(exp.DataType.Type.TINYTEXT) 804 TYPE_MAPPING.pop(exp.DataType.Type.MEDIUMBLOB) 805 TYPE_MAPPING.pop(exp.DataType.Type.LONGBLOB) 806 TYPE_MAPPING.pop(exp.DataType.Type.TINYBLOB) 807 808 PROPERTIES_LOCATION = { 809 **generator.Generator.PROPERTIES_LOCATION, 810 exp.TransientProperty: exp.Properties.Location.UNSUPPORTED, 811 exp.VolatileProperty: exp.Properties.Location.UNSUPPORTED, 812 } 813 814 LIMIT_FETCH = "LIMIT" 815 816 LIMIT_ONLY_LITERALS = True 817 818 CHAR_CAST_MAPPING = dict.fromkeys( 819 ( 820 exp.DataType.Type.LONGTEXT, 821 exp.DataType.Type.LONGBLOB, 822 exp.DataType.Type.MEDIUMBLOB, 823 exp.DataType.Type.MEDIUMTEXT, 824 exp.DataType.Type.TEXT, 825 exp.DataType.Type.TINYBLOB, 826 exp.DataType.Type.TINYTEXT, 827 exp.DataType.Type.VARCHAR, 828 ), 829 "CHAR", 830 ) 831 SIGNED_CAST_MAPPING = dict.fromkeys( 832 ( 833 exp.DataType.Type.BIGINT, 834 exp.DataType.Type.BOOLEAN, 835 exp.DataType.Type.INT, 836 exp.DataType.Type.SMALLINT, 837 exp.DataType.Type.TINYINT, 838 exp.DataType.Type.MEDIUMINT, 839 ), 840 "SIGNED", 841 ) 842 843 # MySQL doesn't support many datatypes in cast. 844 # https://dev.mysql.com/doc/refman/8.0/en/cast-functions.html#function_cast 845 CAST_MAPPING = { 846 **CHAR_CAST_MAPPING, 847 **SIGNED_CAST_MAPPING, 848 exp.DataType.Type.UBIGINT: "UNSIGNED", 849 } 850 851 TIMESTAMP_FUNC_TYPES = { 852 exp.DataType.Type.TIMESTAMPTZ, 853 exp.DataType.Type.TIMESTAMPLTZ, 854 } 855 856 # https://dev.mysql.com/doc/refman/8.0/en/keywords.html 857 RESERVED_KEYWORDS = { 858 "accessible", 859 "add", 860 "all", 861 "alter", 862 "analyze", 863 "and", 864 "as", 865 "asc", 866 "asensitive", 867 "before", 868 "between", 869 "bigint", 870 "binary", 871 "blob", 872 "both", 873 "by", 874 "call", 875 "cascade", 876 "case", 877 "change", 878 "char", 879 "character", 880 "check", 881 "collate", 882 "column", 883 "condition", 884 "constraint", 885 "continue", 886 "convert", 887 "create", 888 "cross", 889 "cube", 890 "cume_dist", 891 "current_date", 892 "current_time", 893 "current_timestamp", 894 "current_user", 895 "cursor", 896 "database", 897 "databases", 898 "day_hour", 899 "day_microsecond", 900 "day_minute", 901 "day_second", 902 "dec", 903 "decimal", 904 "declare", 905 "default", 906 "delayed", 907 "delete", 908 "dense_rank", 909 "desc", 910 "describe", 911 "deterministic", 912 "distinct", 913 "distinctrow", 914 "div", 915 "double", 916 "drop", 917 "dual", 918 "each", 919 "else", 920 "elseif", 921 "empty", 922 "enclosed", 923 "escaped", 924 "except", 925 "exists", 926 "exit", 927 "explain", 928 "false", 929 "fetch", 930 "first_value", 931 "float", 932 "float4", 933 "float8", 934 "for", 935 "force", 936 "foreign", 937 "from", 938 "fulltext", 939 "function", 940 "generated", 941 "get", 942 "grant", 943 "group", 944 "grouping", 945 "groups", 946 "having", 947 "high_priority", 948 "hour_microsecond", 949 "hour_minute", 950 "hour_second", 951 "if", 952 "ignore", 953 "in", 954 "index", 955 "infile", 956 "inner", 957 "inout", 958 "insensitive", 959 "insert", 960 "int", 961 "int1", 962 "int2", 963 "int3", 964 "int4", 965 "int8", 966 "integer", 967 "intersect", 968 "interval", 969 "into", 970 "io_after_gtids", 971 "io_before_gtids", 972 "is", 973 "iterate", 974 "join", 975 "json_table", 976 "key", 977 "keys", 978 "kill", 979 "lag", 980 "last_value", 981 "lateral", 982 "lead", 983 "leading", 984 "leave", 985 "left", 986 "like", 987 "limit", 988 "linear", 989 "lines", 990 "load", 991 "localtime", 992 "localtimestamp", 993 "lock", 994 "long", 995 "longblob", 996 "longtext", 997 "loop", 998 "low_priority", 999 "master_bind", 1000 "master_ssl_verify_server_cert", 1001 "match", 1002 "maxvalue", 1003 "mediumblob", 1004 "mediumint", 1005 "mediumtext", 1006 "middleint", 1007 "minute_microsecond", 1008 "minute_second", 1009 "mod", 1010 "modifies", 1011 "natural", 1012 "not", 1013 "no_write_to_binlog", 1014 "nth_value", 1015 "ntile", 1016 "null", 1017 "numeric", 1018 "of", 1019 "on", 1020 "optimize", 1021 "optimizer_costs", 1022 "option", 1023 "optionally", 1024 "or", 1025 "order", 1026 "out", 1027 "outer", 1028 "outfile", 1029 "over", 1030 "partition", 1031 "percent_rank", 1032 "precision", 1033 "primary", 1034 "procedure", 1035 "purge", 1036 "range", 1037 "rank", 1038 "read", 1039 "reads", 1040 "read_write", 1041 "real", 1042 "recursive", 1043 "references", 1044 "regexp", 1045 "release", 1046 "rename", 1047 "repeat", 1048 "replace", 1049 "require", 1050 "resignal", 1051 "restrict", 1052 "return", 1053 "revoke", 1054 "right", 1055 "rlike", 1056 "row", 1057 "rows", 1058 "row_number", 1059 "schema", 1060 "schemas", 1061 "second_microsecond", 1062 "select", 1063 "sensitive", 1064 "separator", 1065 "set", 1066 "show", 1067 "signal", 1068 "smallint", 1069 "spatial", 1070 "specific", 1071 "sql", 1072 "sqlexception", 1073 "sqlstate", 1074 "sqlwarning", 1075 "sql_big_result", 1076 "sql_calc_found_rows", 1077 "sql_small_result", 1078 "ssl", 1079 "starting", 1080 "stored", 1081 "straight_join", 1082 "system", 1083 "table", 1084 "terminated", 1085 "then", 1086 "tinyblob", 1087 "tinyint", 1088 "tinytext", 1089 "to", 1090 "trailing", 1091 "trigger", 1092 "true", 1093 "undo", 1094 "union", 1095 "unique", 1096 "unlock", 1097 "unsigned", 1098 "update", 1099 "usage", 1100 "use", 1101 "using", 1102 "utc_date", 1103 "utc_time", 1104 "utc_timestamp", 1105 "values", 1106 "varbinary", 1107 "varchar", 1108 "varcharacter", 1109 "varying", 1110 "virtual", 1111 "when", 1112 "where", 1113 "while", 1114 "window", 1115 "with", 1116 "write", 1117 "xor", 1118 "year_month", 1119 "zerofill", 1120 } 1121 1122 def array_sql(self, expression: exp.Array) -> str: 1123 self.unsupported("Arrays are not supported by MySQL") 1124 return self.function_fallback_sql(expression) 1125 1126 def arraycontainsall_sql(self, expression: exp.ArrayContainsAll) -> str: 1127 self.unsupported("Array operations are not supported by MySQL") 1128 return self.function_fallback_sql(expression) 1129 1130 def dpipe_sql(self, expression: exp.DPipe) -> str: 1131 return self.func("CONCAT", *expression.flatten()) 1132 1133 def extract_sql(self, expression: exp.Extract) -> str: 1134 unit = expression.name 1135 if unit and unit.lower() == "epoch": 1136 return self.func("UNIX_TIMESTAMP", expression.expression) 1137 1138 return super().extract_sql(expression) 1139 1140 def datatype_sql(self, expression: exp.DataType) -> str: 1141 if ( 1142 self.VARCHAR_REQUIRES_SIZE 1143 and expression.is_type(exp.DataType.Type.VARCHAR) 1144 and not expression.expressions 1145 ): 1146 # `VARCHAR` must always have a size - if it doesn't, we always generate `TEXT` 1147 return "TEXT" 1148 1149 # https://dev.mysql.com/doc/refman/8.0/en/numeric-type-syntax.html 1150 result = super().datatype_sql(expression) 1151 if expression.this in self.UNSIGNED_TYPE_MAPPING: 1152 result = f"{result} UNSIGNED" 1153 1154 return result 1155 1156 def jsonarraycontains_sql(self, expression: exp.JSONArrayContains) -> str: 1157 return f"{self.sql(expression, 'this')} MEMBER OF({self.sql(expression, 'expression')})" 1158 1159 def cast_sql(self, expression: exp.Cast, safe_prefix: t.Optional[str] = None) -> str: 1160 if expression.to.this in self.TIMESTAMP_FUNC_TYPES: 1161 return self.func("TIMESTAMP", expression.this) 1162 1163 to = self.CAST_MAPPING.get(expression.to.this) 1164 1165 if to: 1166 expression.to.set("this", to) 1167 return super().cast_sql(expression) 1168 1169 def show_sql(self, expression: exp.Show) -> str: 1170 this = f" {expression.name}" 1171 full = " FULL" if expression.args.get("full") else "" 1172 global_ = " GLOBAL" if expression.args.get("global") else "" 1173 1174 target = self.sql(expression, "target") 1175 target = f" {target}" if target else "" 1176 if expression.name in ("COLUMNS", "INDEX"): 1177 target = f" FROM{target}" 1178 elif expression.name == "GRANTS": 1179 target = f" FOR{target}" 1180 1181 db = self._prefixed_sql("FROM", expression, "db") 1182 1183 like = self._prefixed_sql("LIKE", expression, "like") 1184 where = self.sql(expression, "where") 1185 1186 types = self.expressions(expression, key="types") 1187 types = f" {types}" if types else types 1188 query = self._prefixed_sql("FOR QUERY", expression, "query") 1189 1190 if expression.name == "PROFILE": 1191 offset = self._prefixed_sql("OFFSET", expression, "offset") 1192 limit = self._prefixed_sql("LIMIT", expression, "limit") 1193 else: 1194 offset = "" 1195 limit = self._oldstyle_limit_sql(expression) 1196 1197 log = self._prefixed_sql("IN", expression, "log") 1198 position = self._prefixed_sql("FROM", expression, "position") 1199 1200 channel = self._prefixed_sql("FOR CHANNEL", expression, "channel") 1201 1202 if expression.name == "ENGINE": 1203 mutex_or_status = " MUTEX" if expression.args.get("mutex") else " STATUS" 1204 else: 1205 mutex_or_status = "" 1206 1207 return f"SHOW{full}{global_}{this}{target}{types}{db}{query}{log}{position}{channel}{mutex_or_status}{like}{where}{offset}{limit}" 1208 1209 def altercolumn_sql(self, expression: exp.AlterColumn) -> str: 1210 dtype = self.sql(expression, "dtype") 1211 if not dtype: 1212 return super().altercolumn_sql(expression) 1213 1214 this = self.sql(expression, "this") 1215 return f"MODIFY COLUMN {this} {dtype}" 1216 1217 def _prefixed_sql(self, prefix: str, expression: exp.Expression, arg: str) -> str: 1218 sql = self.sql(expression, arg) 1219 return f" {prefix} {sql}" if sql else "" 1220 1221 def _oldstyle_limit_sql(self, expression: exp.Show) -> str: 1222 limit = self.sql(expression, "limit") 1223 offset = self.sql(expression, "offset") 1224 if limit: 1225 limit_offset = f"{offset}, {limit}" if offset else limit 1226 return f" LIMIT {limit_offset}" 1227 return "" 1228 1229 def chr_sql(self, expression: exp.Chr) -> str: 1230 this = self.expressions(sqls=[expression.this] + expression.expressions) 1231 charset = expression.args.get("charset") 1232 using = f" USING {self.sql(charset)}" if charset else "" 1233 return f"CHAR({this}{using})" 1234 1235 def timestamptrunc_sql(self, expression: exp.TimestampTrunc) -> str: 1236 unit = expression.args.get("unit") 1237 1238 # Pick an old-enough date to avoid negative timestamp diffs 1239 start_ts = "'0000-01-01 00:00:00'" 1240 1241 # Source: https://stackoverflow.com/a/32955740 1242 timestamp_diff = build_date_delta(exp.TimestampDiff)([unit, start_ts, expression.this]) 1243 interval = exp.Interval(this=timestamp_diff, unit=unit) 1244 dateadd = build_date_delta_with_interval(exp.DateAdd)([start_ts, interval]) 1245 1246 return self.sql(dateadd) 1247 1248 def converttimezone_sql(self, expression: exp.ConvertTimezone) -> str: 1249 from_tz = expression.args.get("source_tz") 1250 to_tz = expression.args.get("target_tz") 1251 dt = expression.args.get("timestamp") 1252 1253 return self.func("CONVERT_TZ", dt, from_tz, to_tz) 1254 1255 def attimezone_sql(self, expression: exp.AtTimeZone) -> str: 1256 self.unsupported("AT TIME ZONE is not supported by MySQL") 1257 return self.sql(expression.this)
PROMOTE_TO_INFERRED_DATETIME_TYPE =
True
This flag is used in the optimizer's canonicalize rule and determines whether x will be promoted to the literal's type in x::DATE < '2020-01-01 12:05:03' (i.e., DATETIME). When false, the literal is cast to x's type to match it instead.
NORMALIZATION_STRATEGY =
<NormalizationStrategy.CASE_SENSITIVE: 'CASE_SENSITIVE'>
Specifies the strategy according to which identifiers should be normalized.
TIME_MAPPING: Dict[str, str] =
{'%M': '%B', '%c': '%-m', '%e': '%-d', '%h': '%I', '%i': '%M', '%s': '%S', '%u': '%W', '%k': '%-H', '%l': '%-I', '%T': '%H:%M:%S', '%W': '%A'}
Associates this dialect's time formats with their equivalent Python strftime
formats.
UNESCAPED_SEQUENCES: Dict[str, str] =
{'\\a': '\x07', '\\b': '\x08', '\\f': '\x0c', '\\n': '\n', '\\r': '\r', '\\t': '\t', '\\v': '\x0b', '\\\\': '\\'}
Mapping of an escaped sequence (\n
) to its unescaped version (
).
tokenizer_class =
<class 'MySQL.Tokenizer'>
parser_class =
<class 'MySQL.Parser'>
generator_class =
<class 'MySQL.Generator'>
TIME_TRIE: Dict =
{'%': {'M': {0: True}, 'c': {0: True}, 'e': {0: True}, 'h': {0: True}, 'i': {0: True}, 's': {0: True}, 'u': {0: True}, 'k': {0: True}, 'l': {0: True}, 'T': {0: True}, 'W': {0: True}}}
FORMAT_TRIE: Dict =
{'%': {'M': {0: True}, 'c': {0: True}, 'e': {0: True}, 'h': {0: True}, 'i': {0: True}, 's': {0: True}, 'u': {0: True}, 'k': {0: True}, 'l': {0: True}, 'T': {0: True}, 'W': {0: True}}}
INVERSE_TIME_MAPPING: Dict[str, str] =
{'%B': '%M', '%-m': '%c', '%-d': '%e', '%I': '%h', '%M': '%i', '%S': '%s', '%W': '%u', '%-H': '%k', '%-I': '%l', '%H:%M:%S': '%T', '%A': '%W'}
INVERSE_TIME_TRIE: Dict =
{'%': {'B': {0: True}, '-': {'m': {0: True}, 'd': {0: True}, 'H': {0: True}, 'I': {0: True}}, 'I': {0: True}, 'M': {0: True}, 'S': {0: True}, 'W': {0: True}, 'H': {':': {'%': {'M': {':': {'%': {'S': {0: True}}}}}}}, 'A': {0: True}}}
ESCAPED_SEQUENCES: Dict[str, str] =
{'\x07': '\\a', '\x08': '\\b', '\x0c': '\\f', '\n': '\\n', '\r': '\\r', '\t': '\\t', '\x0b': '\\v', '\\': '\\\\'}
Inherited Members
- sqlglot.dialects.dialect.Dialect
- Dialect
- INDEX_OFFSET
- WEEK_OFFSET
- UNNEST_COLUMN_ONLY
- ALIAS_POST_TABLESAMPLE
- TABLESAMPLE_SIZE_IS_PERCENT
- STRICT_STRING_CONCAT
- COPY_PARAMS_ARE_CSV
- NORMALIZE_FUNCTIONS
- PRESERVE_ORIGINAL_NAMES
- LOG_BASE_FIRST
- NULL_ORDERING
- TYPED_DIVISION
- CONCAT_COALESCE
- HEX_LOWERCASE
- DATE_FORMAT
- DATEINT_FORMAT
- FORMAT_MAPPING
- PSEUDOCOLUMNS
- PREFER_CTE_ALIAS_COLUMN
- FORCE_EARLY_ALIAS_REF_EXPANSION
- EXPAND_ALIAS_REFS_EARLY_ONLY_IN_GROUP_BY
- SUPPORTS_ORDER_BY_ALL
- HAS_DISTINCT_ARRAY_CONSTRUCTORS
- SUPPORTS_FIXED_SIZE_ARRAYS
- STRICT_JSON_PATH_SYNTAX
- ON_CONDITION_EMPTY_BEFORE_ERROR
- ARRAY_AGG_INCLUDES_NULLS
- SUPPORTS_VALUES_DEFAULT
- REGEXP_EXTRACT_DEFAULT_GROUP
- SET_OP_DISTINCT_BY_DEFAULT
- CREATABLE_KIND_MAPPING
- DATE_PART_MAPPING
- TYPE_TO_EXPRESSIONS
- ANNOTATORS
- get_or_raise
- format_time
- settings
- normalize_identifier
- case_sensitive
- can_identify
- quote_identifier
- to_json_path
- parse
- parse_into
- generate
- transpile
- tokenize
- tokenizer
- jsonpath_tokenizer
- parser
- generator
182 class Tokenizer(tokens.Tokenizer): 183 QUOTES = ["'", '"'] 184 COMMENTS = ["--", "#", ("/*", "*/")] 185 IDENTIFIERS = ["`"] 186 STRING_ESCAPES = ["'", '"', "\\"] 187 BIT_STRINGS = [("b'", "'"), ("B'", "'"), ("0b", "")] 188 HEX_STRINGS = [("x'", "'"), ("X'", "'"), ("0x", "")] 189 190 KEYWORDS = { 191 **tokens.Tokenizer.KEYWORDS, 192 "CHARSET": TokenType.CHARACTER_SET, 193 # The DESCRIBE and EXPLAIN statements are synonyms. 194 # https://dev.mysql.com/doc/refman/8.4/en/explain.html 195 "EXPLAIN": TokenType.DESCRIBE, 196 "FORCE": TokenType.FORCE, 197 "IGNORE": TokenType.IGNORE, 198 "KEY": TokenType.KEY, 199 "LOCK TABLES": TokenType.COMMAND, 200 "LONGBLOB": TokenType.LONGBLOB, 201 "LONGTEXT": TokenType.LONGTEXT, 202 "MEDIUMBLOB": TokenType.MEDIUMBLOB, 203 "TINYBLOB": TokenType.TINYBLOB, 204 "TINYTEXT": TokenType.TINYTEXT, 205 "MEDIUMTEXT": TokenType.MEDIUMTEXT, 206 "MEDIUMINT": TokenType.MEDIUMINT, 207 "MEMBER OF": TokenType.MEMBER_OF, 208 "SEPARATOR": TokenType.SEPARATOR, 209 "START": TokenType.BEGIN, 210 "SIGNED": TokenType.BIGINT, 211 "SIGNED INTEGER": TokenType.BIGINT, 212 "UNLOCK TABLES": TokenType.COMMAND, 213 "UNSIGNED": TokenType.UBIGINT, 214 "UNSIGNED INTEGER": TokenType.UBIGINT, 215 "YEAR": TokenType.YEAR, 216 "_ARMSCII8": TokenType.INTRODUCER, 217 "_ASCII": TokenType.INTRODUCER, 218 "_BIG5": TokenType.INTRODUCER, 219 "_BINARY": TokenType.INTRODUCER, 220 "_CP1250": TokenType.INTRODUCER, 221 "_CP1251": TokenType.INTRODUCER, 222 "_CP1256": TokenType.INTRODUCER, 223 "_CP1257": TokenType.INTRODUCER, 224 "_CP850": TokenType.INTRODUCER, 225 "_CP852": TokenType.INTRODUCER, 226 "_CP866": TokenType.INTRODUCER, 227 "_CP932": TokenType.INTRODUCER, 228 "_DEC8": TokenType.INTRODUCER, 229 "_EUCJPMS": TokenType.INTRODUCER, 230 "_EUCKR": TokenType.INTRODUCER, 231 "_GB18030": TokenType.INTRODUCER, 232 "_GB2312": TokenType.INTRODUCER, 233 "_GBK": TokenType.INTRODUCER, 234 "_GEOSTD8": TokenType.INTRODUCER, 235 "_GREEK": TokenType.INTRODUCER, 236 "_HEBREW": TokenType.INTRODUCER, 237 "_HP8": TokenType.INTRODUCER, 238 "_KEYBCS2": TokenType.INTRODUCER, 239 "_KOI8R": TokenType.INTRODUCER, 240 "_KOI8U": TokenType.INTRODUCER, 241 "_LATIN1": TokenType.INTRODUCER, 242 "_LATIN2": TokenType.INTRODUCER, 243 "_LATIN5": TokenType.INTRODUCER, 244 "_LATIN7": TokenType.INTRODUCER, 245 "_MACCE": TokenType.INTRODUCER, 246 "_MACROMAN": TokenType.INTRODUCER, 247 "_SJIS": TokenType.INTRODUCER, 248 "_SWE7": TokenType.INTRODUCER, 249 "_TIS620": TokenType.INTRODUCER, 250 "_UCS2": TokenType.INTRODUCER, 251 "_UJIS": TokenType.INTRODUCER, 252 # https://dev.mysql.com/doc/refman/8.0/en/string-literals.html 253 "_UTF8": TokenType.INTRODUCER, 254 "_UTF16": TokenType.INTRODUCER, 255 "_UTF16LE": TokenType.INTRODUCER, 256 "_UTF32": TokenType.INTRODUCER, 257 "_UTF8MB3": TokenType.INTRODUCER, 258 "_UTF8MB4": TokenType.INTRODUCER, 259 "@@": TokenType.SESSION_PARAMETER, 260 } 261 262 COMMANDS = {*tokens.Tokenizer.COMMANDS, TokenType.REPLACE} - {TokenType.SHOW}
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.COLON_EQ: 'COLON_EQ'>, '<=>': <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'>, '??': <TokenType.DQMARK: 'DQMARK'>, '~~~': <TokenType.GLOB: 'GLOB'>, '~~': <TokenType.LIKE: 'LIKE'>, '~~*': <TokenType.ILIKE: 'ILIKE'>, '~*': <TokenType.IRLIKE: 'IRLIKE'>, '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.BEGIN: 'BEGIN'>, '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'>, 'CONNECT BY': <TokenType.CONNECT_BY: 'CONNECT_BY'>, 'CONSTRAINT': <TokenType.CONSTRAINT: 'CONSTRAINT'>, 'COPY': <TokenType.COPY: 'COPY'>, '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'>, 'DIV': <TokenType.DIV: 'DIV'>, 'DROP': <TokenType.DROP: 'DROP'>, 'ELSE': <TokenType.ELSE: 'ELSE'>, 'END': <TokenType.END: 'END'>, 'ENUM': <TokenType.ENUM: 'ENUM'>, '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'>, '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'>, 'KILL': <TokenType.KILL: 'KILL'>, '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'>, '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'>, 'XOR': <TokenType.XOR: 'XOR'>, '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'>, 'RENAME': <TokenType.RENAME: 'RENAME'>, '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'>, 'START WITH': <TokenType.START_WITH: 'START_WITH'>, 'STRAIGHT_JOIN': <TokenType.STRAIGHT_JOIN: 'STRAIGHT_JOIN'>, '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'>, 'TRUNCATE': <TokenType.TRUNCATE: 'TRUNCATE'>, 'UNION': <TokenType.UNION: 'UNION'>, 'UNKNOWN': <TokenType.UNKNOWN: 'UNKNOWN'>, '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'>, 'MEDIUMINT': <TokenType.MEDIUMINT: 'MEDIUMINT'>, 'INT1': <TokenType.TINYINT: 'TINYINT'>, 'TINYINT': <TokenType.TINYINT: 'TINYINT'>, 'INT16': <TokenType.SMALLINT: 'SMALLINT'>, 'SHORT': <TokenType.SMALLINT: 'SMALLINT'>, 'SMALLINT': <TokenType.SMALLINT: 'SMALLINT'>, 'INT128': <TokenType.INT128: 'INT128'>, 'HUGEINT': <TokenType.INT128: 'INT128'>, 'UHUGEINT': <TokenType.UINT128: 'UINT128'>, 'INT2': <TokenType.SMALLINT: 'SMALLINT'>, 'INTEGER': <TokenType.INT: 'INT'>, 'INT': <TokenType.INT: 'INT'>, 'INT4': <TokenType.INT: 'INT'>, 'INT32': <TokenType.INT: 'INT'>, 'INT64': <TokenType.BIGINT: 'BIGINT'>, 'LONG': <TokenType.BIGINT: 'BIGINT'>, 'BIGINT': <TokenType.BIGINT: 'BIGINT'>, 'INT8': <TokenType.TINYINT: 'TINYINT'>, 'UINT': <TokenType.UINT: 'UINT'>, 'DEC': <TokenType.DECIMAL: 'DECIMAL'>, 'DECIMAL': <TokenType.DECIMAL: 'DECIMAL'>, 'DECIMAL32': <TokenType.DECIMAL32: 'DECIMAL32'>, 'DECIMAL64': <TokenType.DECIMAL64: 'DECIMAL64'>, 'DECIMAL128': <TokenType.DECIMAL128: 'DECIMAL128'>, 'DECIMAL256': <TokenType.DECIMAL256: 'DECIMAL256'>, 'BIGDECIMAL': <TokenType.BIGDECIMAL: 'BIGDECIMAL'>, 'BIGNUMERIC': <TokenType.BIGDECIMAL: 'BIGDECIMAL'>, 'LIST': <TokenType.LIST: 'LIST'>, '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'>, 'JSONB': <TokenType.JSONB: 'JSONB'>, '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'>, 'BPCHAR': <TokenType.BPCHAR: 'BPCHAR'>, 'STR': <TokenType.TEXT: 'TEXT'>, 'STRING': <TokenType.TEXT: 'TEXT'>, 'TEXT': <TokenType.TEXT: 'TEXT'>, 'LONGTEXT': <TokenType.LONGTEXT: 'LONGTEXT'>, 'MEDIUMTEXT': <TokenType.MEDIUMTEXT: 'MEDIUMTEXT'>, 'TINYTEXT': <TokenType.TINYTEXT: 'TINYTEXT'>, 'CLOB': <TokenType.TEXT: 'TEXT'>, 'LONGVARCHAR': <TokenType.TEXT: 'TEXT'>, 'BINARY': <TokenType.BINARY: 'BINARY'>, 'BLOB': <TokenType.VARBINARY: 'VARBINARY'>, 'LONGBLOB': <TokenType.LONGBLOB: 'LONGBLOB'>, 'MEDIUMBLOB': <TokenType.MEDIUMBLOB: 'MEDIUMBLOB'>, 'TINYBLOB': <TokenType.TINYBLOB: 'TINYBLOB'>, 'BYTEA': <TokenType.VARBINARY: 'VARBINARY'>, 'VARBINARY': <TokenType.VARBINARY: 'VARBINARY'>, 'TIME': <TokenType.TIME: 'TIME'>, 'TIMETZ': <TokenType.TIMETZ: 'TIMETZ'>, 'TIMESTAMP': <TokenType.TIMESTAMP: 'TIMESTAMP'>, 'TIMESTAMPTZ': <TokenType.TIMESTAMPTZ: 'TIMESTAMPTZ'>, 'TIMESTAMPLTZ': <TokenType.TIMESTAMPLTZ: 'TIMESTAMPLTZ'>, 'TIMESTAMP_LTZ': <TokenType.TIMESTAMPLTZ: 'TIMESTAMPLTZ'>, 'TIMESTAMPNTZ': <TokenType.TIMESTAMPNTZ: 'TIMESTAMPNTZ'>, 'TIMESTAMP_NTZ': <TokenType.TIMESTAMPNTZ: 'TIMESTAMPNTZ'>, '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'>, 'VECTOR': <TokenType.VECTOR: 'VECTOR'>, 'STRUCT': <TokenType.STRUCT: 'STRUCT'>, 'SEQUENCE': <TokenType.SEQUENCE: 'SEQUENCE'>, 'VARIANT': <TokenType.VARIANT: 'VARIANT'>, 'ALTER': <TokenType.ALTER: 'ALTER'>, 'ANALYZE': <TokenType.COMMAND: 'COMMAND'>, 'CALL': <TokenType.COMMAND: 'COMMAND'>, 'COMMENT': <TokenType.COMMENT: 'COMMENT'>, 'EXPLAIN': <TokenType.DESCRIBE: 'DESCRIBE'>, 'GRANT': <TokenType.GRANT: 'GRANT'>, 'OPTIMIZE': <TokenType.COMMAND: 'COMMAND'>, 'PREPARE': <TokenType.COMMAND: 'COMMAND'>, 'VACUUM': <TokenType.COMMAND: 'COMMAND'>, 'USER-DEFINED': <TokenType.USERDEFINED: 'USERDEFINED'>, 'FOR VERSION': <TokenType.VERSION_SNAPSHOT: 'VERSION_SNAPSHOT'>, 'FOR TIMESTAMP': <TokenType.TIMESTAMP_SNAPSHOT: 'TIMESTAMP_SNAPSHOT'>, 'CHARSET': <TokenType.CHARACTER_SET: 'CHARACTER_SET'>, 'FORCE': <TokenType.FORCE: 'FORCE'>, 'IGNORE': <TokenType.IGNORE: 'IGNORE'>, 'KEY': <TokenType.KEY: 'KEY'>, 'LOCK TABLES': <TokenType.COMMAND: 'COMMAND'>, 'MEMBER OF': <TokenType.MEMBER_OF: 'MEMBER_OF'>, 'SEPARATOR': <TokenType.SEPARATOR: 'SEPARATOR'>, 'START': <TokenType.BEGIN: 'BEGIN'>, 'SIGNED': <TokenType.BIGINT: 'BIGINT'>, 'SIGNED INTEGER': <TokenType.BIGINT: 'BIGINT'>, 'UNLOCK TABLES': <TokenType.COMMAND: 'COMMAND'>, 'UNSIGNED': <TokenType.UBIGINT: 'UBIGINT'>, 'UNSIGNED INTEGER': <TokenType.UBIGINT: 'UBIGINT'>, 'YEAR': <TokenType.YEAR: 'YEAR'>, '_ARMSCII8': <TokenType.INTRODUCER: 'INTRODUCER'>, '_ASCII': <TokenType.INTRODUCER: 'INTRODUCER'>, '_BIG5': <TokenType.INTRODUCER: 'INTRODUCER'>, '_BINARY': <TokenType.INTRODUCER: 'INTRODUCER'>, '_CP1250': <TokenType.INTRODUCER: 'INTRODUCER'>, '_CP1251': <TokenType.INTRODUCER: 'INTRODUCER'>, '_CP1256': <TokenType.INTRODUCER: 'INTRODUCER'>, '_CP1257': <TokenType.INTRODUCER: 'INTRODUCER'>, '_CP850': <TokenType.INTRODUCER: 'INTRODUCER'>, '_CP852': <TokenType.INTRODUCER: 'INTRODUCER'>, '_CP866': <TokenType.INTRODUCER: 'INTRODUCER'>, '_CP932': <TokenType.INTRODUCER: 'INTRODUCER'>, '_DEC8': <TokenType.INTRODUCER: 'INTRODUCER'>, '_EUCJPMS': <TokenType.INTRODUCER: 'INTRODUCER'>, '_EUCKR': <TokenType.INTRODUCER: 'INTRODUCER'>, '_GB18030': <TokenType.INTRODUCER: 'INTRODUCER'>, '_GB2312': <TokenType.INTRODUCER: 'INTRODUCER'>, '_GBK': <TokenType.INTRODUCER: 'INTRODUCER'>, '_GEOSTD8': <TokenType.INTRODUCER: 'INTRODUCER'>, '_GREEK': <TokenType.INTRODUCER: 'INTRODUCER'>, '_HEBREW': <TokenType.INTRODUCER: 'INTRODUCER'>, '_HP8': <TokenType.INTRODUCER: 'INTRODUCER'>, '_KEYBCS2': <TokenType.INTRODUCER: 'INTRODUCER'>, '_KOI8R': <TokenType.INTRODUCER: 'INTRODUCER'>, '_KOI8U': <TokenType.INTRODUCER: 'INTRODUCER'>, '_LATIN1': <TokenType.INTRODUCER: 'INTRODUCER'>, '_LATIN2': <TokenType.INTRODUCER: 'INTRODUCER'>, '_LATIN5': <TokenType.INTRODUCER: 'INTRODUCER'>, '_LATIN7': <TokenType.INTRODUCER: 'INTRODUCER'>, '_MACCE': <TokenType.INTRODUCER: 'INTRODUCER'>, '_MACROMAN': <TokenType.INTRODUCER: 'INTRODUCER'>, '_SJIS': <TokenType.INTRODUCER: 'INTRODUCER'>, '_SWE7': <TokenType.INTRODUCER: 'INTRODUCER'>, '_TIS620': <TokenType.INTRODUCER: 'INTRODUCER'>, '_UCS2': <TokenType.INTRODUCER: 'INTRODUCER'>, '_UJIS': <TokenType.INTRODUCER: 'INTRODUCER'>, '_UTF8': <TokenType.INTRODUCER: 'INTRODUCER'>, '_UTF16': <TokenType.INTRODUCER: 'INTRODUCER'>, '_UTF16LE': <TokenType.INTRODUCER: 'INTRODUCER'>, '_UTF32': <TokenType.INTRODUCER: 'INTRODUCER'>, '_UTF8MB3': <TokenType.INTRODUCER: 'INTRODUCER'>, '_UTF8MB4': <TokenType.INTRODUCER: 'INTRODUCER'>, '@@': <TokenType.SESSION_PARAMETER: 'SESSION_PARAMETER'>}
COMMANDS =
{<TokenType.FETCH: 'FETCH'>, <TokenType.RENAME: 'RENAME'>, <TokenType.REPLACE: 'REPLACE'>, <TokenType.EXECUTE: 'EXECUTE'>, <TokenType.COMMAND: 'COMMAND'>}
Inherited Members
- sqlglot.tokens.Tokenizer
- Tokenizer
- SINGLE_TOKENS
- BYTE_STRINGS
- RAW_STRINGS
- HEREDOC_STRINGS
- UNICODE_STRINGS
- VAR_SINGLE_TOKENS
- IDENTIFIER_ESCAPES
- HEREDOC_TAG_IS_IDENTIFIER
- HEREDOC_STRING_ALTERNATIVE
- STRING_ESCAPES_ALLOWED_IN_RAW_STRINGS
- NESTED_COMMENTS
- HINT_START
- TOKENS_PRECEDING_HINT
- WHITE_SPACE
- COMMAND_PREFIX_TOKENS
- NUMERIC_LITERALS
- dialect
- reset
- tokenize
- tokenize_rs
- size
- sql
- tokens
264 class Parser(parser.Parser): 265 FUNC_TOKENS = { 266 *parser.Parser.FUNC_TOKENS, 267 TokenType.DATABASE, 268 TokenType.SCHEMA, 269 TokenType.VALUES, 270 } 271 272 CONJUNCTION = { 273 **parser.Parser.CONJUNCTION, 274 TokenType.DAMP: exp.And, 275 TokenType.XOR: exp.Xor, 276 } 277 278 DISJUNCTION = { 279 **parser.Parser.DISJUNCTION, 280 TokenType.DPIPE: exp.Or, 281 } 282 283 TABLE_ALIAS_TOKENS = ( 284 parser.Parser.TABLE_ALIAS_TOKENS - parser.Parser.TABLE_INDEX_HINT_TOKENS 285 ) 286 287 RANGE_PARSERS = { 288 **parser.Parser.RANGE_PARSERS, 289 TokenType.MEMBER_OF: lambda self, this: self.expression( 290 exp.JSONArrayContains, 291 this=this, 292 expression=self._parse_wrapped(self._parse_expression), 293 ), 294 } 295 296 FUNCTIONS = { 297 **parser.Parser.FUNCTIONS, 298 "CHAR_LENGTH": exp.Length.from_arg_list, 299 "CHARACTER_LENGTH": exp.Length.from_arg_list, 300 "CONVERT_TZ": lambda args: exp.ConvertTimezone( 301 source_tz=seq_get(args, 1), target_tz=seq_get(args, 2), timestamp=seq_get(args, 0) 302 ), 303 "DATE": lambda args: exp.TsOrDsToDate(this=seq_get(args, 0)), 304 "DATE_ADD": build_date_delta_with_interval(exp.DateAdd), 305 "DATE_FORMAT": build_formatted_time(exp.TimeToStr, "mysql"), 306 "DATE_SUB": build_date_delta_with_interval(exp.DateSub), 307 "DAY": lambda args: exp.Day(this=exp.TsOrDsToDate(this=seq_get(args, 0))), 308 "DAYOFMONTH": lambda args: exp.DayOfMonth(this=exp.TsOrDsToDate(this=seq_get(args, 0))), 309 "DAYOFWEEK": lambda args: exp.DayOfWeek(this=exp.TsOrDsToDate(this=seq_get(args, 0))), 310 "DAYOFYEAR": lambda args: exp.DayOfYear(this=exp.TsOrDsToDate(this=seq_get(args, 0))), 311 "FROM_UNIXTIME": build_formatted_time(exp.UnixToTime, "mysql"), 312 "ISNULL": isnull_to_is_null, 313 "LOCATE": locate_to_strposition, 314 "MAKETIME": exp.TimeFromParts.from_arg_list, 315 "MONTH": lambda args: exp.Month(this=exp.TsOrDsToDate(this=seq_get(args, 0))), 316 "MONTHNAME": lambda args: exp.TimeToStr( 317 this=exp.TsOrDsToDate(this=seq_get(args, 0)), 318 format=exp.Literal.string("%B"), 319 ), 320 "STR_TO_DATE": _str_to_date, 321 "TIMESTAMPDIFF": build_date_delta(exp.TimestampDiff), 322 "TO_DAYS": lambda args: exp.paren( 323 exp.DateDiff( 324 this=exp.TsOrDsToDate(this=seq_get(args, 0)), 325 expression=exp.TsOrDsToDate(this=exp.Literal.string("0000-01-01")), 326 unit=exp.var("DAY"), 327 ) 328 + 1 329 ), 330 "WEEK": lambda args: exp.Week( 331 this=exp.TsOrDsToDate(this=seq_get(args, 0)), mode=seq_get(args, 1) 332 ), 333 "WEEKOFYEAR": lambda args: exp.WeekOfYear(this=exp.TsOrDsToDate(this=seq_get(args, 0))), 334 "YEAR": lambda args: exp.Year(this=exp.TsOrDsToDate(this=seq_get(args, 0))), 335 } 336 337 FUNCTION_PARSERS = { 338 **parser.Parser.FUNCTION_PARSERS, 339 "CHAR": lambda self: self.expression( 340 exp.Chr, 341 expressions=self._parse_csv(self._parse_assignment), 342 charset=self._match(TokenType.USING) and self._parse_var(), 343 ), 344 "GROUP_CONCAT": lambda self: self._parse_group_concat(), 345 # https://dev.mysql.com/doc/refman/5.7/en/miscellaneous-functions.html#function_values 346 "VALUES": lambda self: self.expression( 347 exp.Anonymous, this="VALUES", expressions=[self._parse_id_var()] 348 ), 349 "JSON_VALUE": lambda self: self._parse_json_value(), 350 } 351 352 STATEMENT_PARSERS = { 353 **parser.Parser.STATEMENT_PARSERS, 354 TokenType.SHOW: lambda self: self._parse_show(), 355 } 356 357 SHOW_PARSERS = { 358 "BINARY LOGS": _show_parser("BINARY LOGS"), 359 "MASTER LOGS": _show_parser("BINARY LOGS"), 360 "BINLOG EVENTS": _show_parser("BINLOG EVENTS"), 361 "CHARACTER SET": _show_parser("CHARACTER SET"), 362 "CHARSET": _show_parser("CHARACTER SET"), 363 "COLLATION": _show_parser("COLLATION"), 364 "FULL COLUMNS": _show_parser("COLUMNS", target="FROM", full=True), 365 "COLUMNS": _show_parser("COLUMNS", target="FROM"), 366 "CREATE DATABASE": _show_parser("CREATE DATABASE", target=True), 367 "CREATE EVENT": _show_parser("CREATE EVENT", target=True), 368 "CREATE FUNCTION": _show_parser("CREATE FUNCTION", target=True), 369 "CREATE PROCEDURE": _show_parser("CREATE PROCEDURE", target=True), 370 "CREATE TABLE": _show_parser("CREATE TABLE", target=True), 371 "CREATE TRIGGER": _show_parser("CREATE TRIGGER", target=True), 372 "CREATE VIEW": _show_parser("CREATE VIEW", target=True), 373 "DATABASES": _show_parser("DATABASES"), 374 "SCHEMAS": _show_parser("DATABASES"), 375 "ENGINE": _show_parser("ENGINE", target=True), 376 "STORAGE ENGINES": _show_parser("ENGINES"), 377 "ENGINES": _show_parser("ENGINES"), 378 "ERRORS": _show_parser("ERRORS"), 379 "EVENTS": _show_parser("EVENTS"), 380 "FUNCTION CODE": _show_parser("FUNCTION CODE", target=True), 381 "FUNCTION STATUS": _show_parser("FUNCTION STATUS"), 382 "GRANTS": _show_parser("GRANTS", target="FOR"), 383 "INDEX": _show_parser("INDEX", target="FROM"), 384 "MASTER STATUS": _show_parser("MASTER STATUS"), 385 "OPEN TABLES": _show_parser("OPEN TABLES"), 386 "PLUGINS": _show_parser("PLUGINS"), 387 "PROCEDURE CODE": _show_parser("PROCEDURE CODE", target=True), 388 "PROCEDURE STATUS": _show_parser("PROCEDURE STATUS"), 389 "PRIVILEGES": _show_parser("PRIVILEGES"), 390 "FULL PROCESSLIST": _show_parser("PROCESSLIST", full=True), 391 "PROCESSLIST": _show_parser("PROCESSLIST"), 392 "PROFILE": _show_parser("PROFILE"), 393 "PROFILES": _show_parser("PROFILES"), 394 "RELAYLOG EVENTS": _show_parser("RELAYLOG EVENTS"), 395 "REPLICAS": _show_parser("REPLICAS"), 396 "SLAVE HOSTS": _show_parser("REPLICAS"), 397 "REPLICA STATUS": _show_parser("REPLICA STATUS"), 398 "SLAVE STATUS": _show_parser("REPLICA STATUS"), 399 "GLOBAL STATUS": _show_parser("STATUS", global_=True), 400 "SESSION STATUS": _show_parser("STATUS"), 401 "STATUS": _show_parser("STATUS"), 402 "TABLE STATUS": _show_parser("TABLE STATUS"), 403 "FULL TABLES": _show_parser("TABLES", full=True), 404 "TABLES": _show_parser("TABLES"), 405 "TRIGGERS": _show_parser("TRIGGERS"), 406 "GLOBAL VARIABLES": _show_parser("VARIABLES", global_=True), 407 "SESSION VARIABLES": _show_parser("VARIABLES"), 408 "VARIABLES": _show_parser("VARIABLES"), 409 "WARNINGS": _show_parser("WARNINGS"), 410 } 411 412 PROPERTY_PARSERS = { 413 **parser.Parser.PROPERTY_PARSERS, 414 "LOCK": lambda self: self._parse_property_assignment(exp.LockProperty), 415 } 416 417 SET_PARSERS = { 418 **parser.Parser.SET_PARSERS, 419 "PERSIST": lambda self: self._parse_set_item_assignment("PERSIST"), 420 "PERSIST_ONLY": lambda self: self._parse_set_item_assignment("PERSIST_ONLY"), 421 "CHARACTER SET": lambda self: self._parse_set_item_charset("CHARACTER SET"), 422 "CHARSET": lambda self: self._parse_set_item_charset("CHARACTER SET"), 423 "NAMES": lambda self: self._parse_set_item_names(), 424 } 425 426 CONSTRAINT_PARSERS = { 427 **parser.Parser.CONSTRAINT_PARSERS, 428 "FULLTEXT": lambda self: self._parse_index_constraint(kind="FULLTEXT"), 429 "INDEX": lambda self: self._parse_index_constraint(), 430 "KEY": lambda self: self._parse_index_constraint(), 431 "SPATIAL": lambda self: self._parse_index_constraint(kind="SPATIAL"), 432 } 433 434 ALTER_PARSERS = { 435 **parser.Parser.ALTER_PARSERS, 436 "MODIFY": lambda self: self._parse_alter_table_alter(), 437 } 438 439 SCHEMA_UNNAMED_CONSTRAINTS = { 440 *parser.Parser.SCHEMA_UNNAMED_CONSTRAINTS, 441 "FULLTEXT", 442 "INDEX", 443 "KEY", 444 "SPATIAL", 445 } 446 447 PROFILE_TYPES: parser.OPTIONS_TYPE = { 448 **dict.fromkeys(("ALL", "CPU", "IPC", "MEMORY", "SOURCE", "SWAPS"), tuple()), 449 "BLOCK": ("IO",), 450 "CONTEXT": ("SWITCHES",), 451 "PAGE": ("FAULTS",), 452 } 453 454 TYPE_TOKENS = { 455 *parser.Parser.TYPE_TOKENS, 456 TokenType.SET, 457 } 458 459 ENUM_TYPE_TOKENS = { 460 *parser.Parser.ENUM_TYPE_TOKENS, 461 TokenType.SET, 462 } 463 464 # SELECT [ ALL | DISTINCT | DISTINCTROW ] [ <OPERATION_MODIFIERS> ] 465 OPERATION_MODIFIERS = { 466 "HIGH_PRIORITY", 467 "STRAIGHT_JOIN", 468 "SQL_SMALL_RESULT", 469 "SQL_BIG_RESULT", 470 "SQL_BUFFER_RESULT", 471 "SQL_NO_CACHE", 472 "SQL_CALC_FOUND_ROWS", 473 } 474 475 LOG_DEFAULTS_TO_LN = True 476 STRING_ALIASES = True 477 VALUES_FOLLOWED_BY_PAREN = False 478 SUPPORTS_PARTITION_SELECTION = True 479 480 def _parse_primary_key_part(self) -> t.Optional[exp.Expression]: 481 this = self._parse_id_var() 482 if not self._match(TokenType.L_PAREN): 483 return this 484 485 expression = self._parse_number() 486 self._match_r_paren() 487 return self.expression(exp.ColumnPrefix, this=this, expression=expression) 488 489 def _parse_index_constraint( 490 self, kind: t.Optional[str] = None 491 ) -> exp.IndexColumnConstraint: 492 if kind: 493 self._match_texts(("INDEX", "KEY")) 494 495 this = self._parse_id_var(any_token=False) 496 index_type = self._match(TokenType.USING) and self._advance_any() and self._prev.text 497 expressions = self._parse_wrapped_csv(self._parse_ordered) 498 499 options = [] 500 while True: 501 if self._match_text_seq("KEY_BLOCK_SIZE"): 502 self._match(TokenType.EQ) 503 opt = exp.IndexConstraintOption(key_block_size=self._parse_number()) 504 elif self._match(TokenType.USING): 505 opt = exp.IndexConstraintOption(using=self._advance_any() and self._prev.text) 506 elif self._match_text_seq("WITH", "PARSER"): 507 opt = exp.IndexConstraintOption(parser=self._parse_var(any_token=True)) 508 elif self._match(TokenType.COMMENT): 509 opt = exp.IndexConstraintOption(comment=self._parse_string()) 510 elif self._match_text_seq("VISIBLE"): 511 opt = exp.IndexConstraintOption(visible=True) 512 elif self._match_text_seq("INVISIBLE"): 513 opt = exp.IndexConstraintOption(visible=False) 514 elif self._match_text_seq("ENGINE_ATTRIBUTE"): 515 self._match(TokenType.EQ) 516 opt = exp.IndexConstraintOption(engine_attr=self._parse_string()) 517 elif self._match_text_seq("SECONDARY_ENGINE_ATTRIBUTE"): 518 self._match(TokenType.EQ) 519 opt = exp.IndexConstraintOption(secondary_engine_attr=self._parse_string()) 520 else: 521 opt = None 522 523 if not opt: 524 break 525 526 options.append(opt) 527 528 return self.expression( 529 exp.IndexColumnConstraint, 530 this=this, 531 expressions=expressions, 532 kind=kind, 533 index_type=index_type, 534 options=options, 535 ) 536 537 def _parse_show_mysql( 538 self, 539 this: str, 540 target: bool | str = False, 541 full: t.Optional[bool] = None, 542 global_: t.Optional[bool] = None, 543 ) -> exp.Show: 544 if target: 545 if isinstance(target, str): 546 self._match_text_seq(target) 547 target_id = self._parse_id_var() 548 else: 549 target_id = None 550 551 log = self._parse_string() if self._match_text_seq("IN") else None 552 553 if this in ("BINLOG EVENTS", "RELAYLOG EVENTS"): 554 position = self._parse_number() if self._match_text_seq("FROM") else None 555 db = None 556 else: 557 position = None 558 db = None 559 560 if self._match(TokenType.FROM): 561 db = self._parse_id_var() 562 elif self._match(TokenType.DOT): 563 db = target_id 564 target_id = self._parse_id_var() 565 566 channel = self._parse_id_var() if self._match_text_seq("FOR", "CHANNEL") else None 567 568 like = self._parse_string() if self._match_text_seq("LIKE") else None 569 where = self._parse_where() 570 571 if this == "PROFILE": 572 types = self._parse_csv(lambda: self._parse_var_from_options(self.PROFILE_TYPES)) 573 query = self._parse_number() if self._match_text_seq("FOR", "QUERY") else None 574 offset = self._parse_number() if self._match_text_seq("OFFSET") else None 575 limit = self._parse_number() if self._match_text_seq("LIMIT") else None 576 else: 577 types, query = None, None 578 offset, limit = self._parse_oldstyle_limit() 579 580 mutex = True if self._match_text_seq("MUTEX") else None 581 mutex = False if self._match_text_seq("STATUS") else mutex 582 583 return self.expression( 584 exp.Show, 585 this=this, 586 target=target_id, 587 full=full, 588 log=log, 589 position=position, 590 db=db, 591 channel=channel, 592 like=like, 593 where=where, 594 types=types, 595 query=query, 596 offset=offset, 597 limit=limit, 598 mutex=mutex, 599 **{"global": global_}, # type: ignore 600 ) 601 602 def _parse_oldstyle_limit( 603 self, 604 ) -> t.Tuple[t.Optional[exp.Expression], t.Optional[exp.Expression]]: 605 limit = None 606 offset = None 607 if self._match_text_seq("LIMIT"): 608 parts = self._parse_csv(self._parse_number) 609 if len(parts) == 1: 610 limit = parts[0] 611 elif len(parts) == 2: 612 limit = parts[1] 613 offset = parts[0] 614 615 return offset, limit 616 617 def _parse_set_item_charset(self, kind: str) -> exp.Expression: 618 this = self._parse_string() or self._parse_unquoted_field() 619 return self.expression(exp.SetItem, this=this, kind=kind) 620 621 def _parse_set_item_names(self) -> exp.Expression: 622 charset = self._parse_string() or self._parse_unquoted_field() 623 if self._match_text_seq("COLLATE"): 624 collate = self._parse_string() or self._parse_unquoted_field() 625 else: 626 collate = None 627 628 return self.expression(exp.SetItem, this=charset, collate=collate, kind="NAMES") 629 630 def _parse_type( 631 self, parse_interval: bool = True, fallback_to_identifier: bool = False 632 ) -> t.Optional[exp.Expression]: 633 # mysql binary is special and can work anywhere, even in order by operations 634 # it operates like a no paren func 635 if self._match(TokenType.BINARY, advance=False): 636 data_type = self._parse_types(check_func=True, allow_identifiers=False) 637 638 if isinstance(data_type, exp.DataType): 639 return self.expression(exp.Cast, this=self._parse_column(), to=data_type) 640 641 return super()._parse_type( 642 parse_interval=parse_interval, fallback_to_identifier=fallback_to_identifier 643 ) 644 645 def _parse_group_concat(self) -> t.Optional[exp.Expression]: 646 def concat_exprs( 647 node: t.Optional[exp.Expression], exprs: t.List[exp.Expression] 648 ) -> exp.Expression: 649 if isinstance(node, exp.Distinct) and len(node.expressions) > 1: 650 concat_exprs = [ 651 self.expression(exp.Concat, expressions=node.expressions, safe=True) 652 ] 653 node.set("expressions", concat_exprs) 654 return node 655 if len(exprs) == 1: 656 return exprs[0] 657 return self.expression(exp.Concat, expressions=args, safe=True) 658 659 args = self._parse_csv(self._parse_lambda) 660 661 if args: 662 order = args[-1] if isinstance(args[-1], exp.Order) else None 663 664 if order: 665 # Order By is the last (or only) expression in the list and has consumed the 'expr' before it, 666 # remove 'expr' from exp.Order and add it back to args 667 args[-1] = order.this 668 order.set("this", concat_exprs(order.this, args)) 669 670 this = order or concat_exprs(args[0], args) 671 else: 672 this = None 673 674 separator = self._parse_field() if self._match(TokenType.SEPARATOR) else None 675 676 return self.expression(exp.GroupConcat, this=this, separator=separator) 677 678 def _parse_json_value(self) -> exp.JSONValue: 679 this = self._parse_bitwise() 680 self._match(TokenType.COMMA) 681 path = self._parse_bitwise() 682 683 returning = self._match(TokenType.RETURNING) and self._parse_type() 684 685 return self.expression( 686 exp.JSONValue, 687 this=this, 688 path=self.dialect.to_json_path(path), 689 returning=returning, 690 on_condition=self._parse_on_condition(), 691 )
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: 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
FUNC_TOKENS =
{<TokenType.TIMESTAMPTZ: 'TIMESTAMPTZ'>, <TokenType.UDECIMAL: 'UDECIMAL'>, <TokenType.LIST: 'LIST'>, <TokenType.TIME: 'TIME'>, <TokenType.INET: 'INET'>, <TokenType.ILIKE: 'ILIKE'>, <TokenType.VAR: 'VAR'>, <TokenType.ISNULL: 'ISNULL'>, <TokenType.TABLE: 'TABLE'>, <TokenType.UBIGINT: 'UBIGINT'>, <TokenType.DATE: 'DATE'>, <TokenType.BINARY: 'BINARY'>, <TokenType.TSRANGE: 'TSRANGE'>, <TokenType.ENUM: 'ENUM'>, <TokenType.CURRENT_DATETIME: 'CURRENT_DATETIME'>, <TokenType.XOR: 'XOR'>, <TokenType.OBJECT_IDENTIFIER: 'OBJECT_IDENTIFIER'>, <TokenType.YEAR: 'YEAR'>, <TokenType.TIMESTAMPLTZ: 'TIMESTAMPLTZ'>, <TokenType.MAP: 'MAP'>, <TokenType.BIT: 'BIT'>, <TokenType.DATETIME64: 'DATETIME64'>, <TokenType.VECTOR: 'VECTOR'>, <TokenType.UNNEST: 'UNNEST'>, <TokenType.WINDOW: 'WINDOW'>, <TokenType.DOUBLE: 'DOUBLE'>, <TokenType.BPCHAR: 'BPCHAR'>, <TokenType.DATE32: 'DATE32'>, <TokenType.ANY: 'ANY'>, <TokenType.CURRENT_TIMESTAMP: 'CURRENT_TIMESTAMP'>, <TokenType.ALL: 'ALL'>, <TokenType.SCHEMA: 'SCHEMA'>, <TokenType.BOOLEAN: 'BOOLEAN'>, <TokenType.ENUM16: 'ENUM16'>, <TokenType.NESTED: 'NESTED'>, <TokenType.NUMMULTIRANGE: 'NUMMULTIRANGE'>, <TokenType.VARBINARY: 'VARBINARY'>, <TokenType.GEOGRAPHY: 'GEOGRAPHY'>, <TokenType.CURRENT_TIME: 'CURRENT_TIME'>, <TokenType.RIGHT: 'RIGHT'>, <TokenType.BIGDECIMAL: 'BIGDECIMAL'>, <TokenType.LOWCARDINALITY: 'LOWCARDINALITY'>, <TokenType.SMALLINT: 'SMALLINT'>, <TokenType.TSMULTIRANGE: 'TSMULTIRANGE'>, <TokenType.DATEMULTIRANGE: 'DATEMULTIRANGE'>, <TokenType.DECIMAL: 'DECIMAL'>, <TokenType.SOME: 'SOME'>, <TokenType.INT4RANGE: 'INT4RANGE'>, <TokenType.USMALLINT: 'USMALLINT'>, <TokenType.OFFSET: 'OFFSET'>, <TokenType.MEDIUMBLOB: 'MEDIUMBLOB'>, <TokenType.CURRENT_DATE: 'CURRENT_DATE'>, <TokenType.COMMAND: 'COMMAND'>, <TokenType.GEOMETRY: 'GEOMETRY'>, <TokenType.FIXEDSTRING: 'FIXEDSTRING'>, <TokenType.IDENTIFIER: 'IDENTIFIER'>, <TokenType.IPV4: 'IPV4'>, <TokenType.UINT256: 'UINT256'>, <TokenType.ROWVERSION: 'ROWVERSION'>, <TokenType.ARRAY: 'ARRAY'>, <TokenType.DECIMAL128: 'DECIMAL128'>, <TokenType.SIMPLEAGGREGATEFUNCTION: 'SIMPLEAGGREGATEFUNCTION'>, <TokenType.HLLSKETCH: 'HLLSKETCH'>, <TokenType.SUPER: 'SUPER'>, <TokenType.UTINYINT: 'UTINYINT'>, <TokenType.SMALLSERIAL: 'SMALLSERIAL'>, <TokenType.CHAR: 'CHAR'>, <TokenType.VALUES: 'VALUES'>, <TokenType.IPADDRESS: 'IPADDRESS'>, <TokenType.EXISTS: 'EXISTS'>, <TokenType.TEXT: 'TEXT'>, <TokenType.MEDIUMINT: 'MEDIUMINT'>, <TokenType.TINYTEXT: 'TINYTEXT'>, <TokenType.USERDEFINED: 'USERDEFINED'>, <TokenType.MONEY: 'MONEY'>, <TokenType.INT4MULTIRANGE: 'INT4MULTIRANGE'>, <TokenType.FILTER: 'FILTER'>, <TokenType.MERGE: 'MERGE'>, <TokenType.INDEX: 'INDEX'>, <TokenType.TINYBLOB: 'TINYBLOB'>, <TokenType.BIGSERIAL: 'BIGSERIAL'>, <TokenType.GLOB: 'GLOB'>, <TokenType.DECIMAL32: 'DECIMAL32'>, <TokenType.INT8RANGE: 'INT8RANGE'>, <TokenType.TIMESTAMP_S: 'TIMESTAMP_S'>, <TokenType.MULTIPOLYGON: 'MULTIPOLYGON'>, <TokenType.RING: 'RING'>, <TokenType.DECIMAL256: 'DECIMAL256'>, <TokenType.INSERT: 'INSERT'>, <TokenType.NAME: 'NAME'>, <TokenType.SEQUENCE: 'SEQUENCE'>, <TokenType.MEDIUMTEXT: 'MEDIUMTEXT'>, <TokenType.POLYGON: 'POLYGON'>, <TokenType.NVARCHAR: 'NVARCHAR'>, <TokenType.NULL: 'NULL'>, <TokenType.IPV6: 'IPV6'>, <TokenType.FORMAT: 'FORMAT'>, <TokenType.DATERANGE: 'DATERANGE'>, <TokenType.INTERVAL: 'INTERVAL'>, <TokenType.TSTZRANGE: 'TSTZRANGE'>, <TokenType.UINT128: 'UINT128'>, <TokenType.TIMESTAMPNTZ: 'TIMESTAMPNTZ'>, <TokenType.DATABASE: 'DATABASE'>, <TokenType.TSTZMULTIRANGE: 'TSTZMULTIRANGE'>, <TokenType.MULTILINESTRING: 'MULTILINESTRING'>, <TokenType.FLOAT: 'FLOAT'>, <TokenType.ENUM8: 'ENUM8'>, <TokenType.HSTORE: 'HSTORE'>, <TokenType.UINT: 'UINT'>, <TokenType.BIGINT: 'BIGINT'>, <TokenType.TIMESTAMP_NS: 'TIMESTAMP_NS'>, <TokenType.AGGREGATEFUNCTION: 'AGGREGATEFUNCTION'>, <TokenType.TIMESTAMP_MS: 'TIMESTAMP_MS'>, <TokenType.REPLACE: 'REPLACE'>, <TokenType.COLLATE: 'COLLATE'>, <TokenType.LEFT: 'LEFT'>, <TokenType.NUMRANGE: 'NUMRANGE'>, <TokenType.RLIKE: 'RLIKE'>, <TokenType.PSEUDO_TYPE: 'PSEUDO_TYPE'>, <TokenType.UNION: 'UNION'>, <TokenType.OBJECT: 'OBJECT'>, <TokenType.NCHAR: 'NCHAR'>, <TokenType.TDIGEST: 'TDIGEST'>, <TokenType.LIKE: 'LIKE'>, <TokenType.UNIQUEIDENTIFIER: 'UNIQUEIDENTIFIER'>, <TokenType.SMALLMONEY: 'SMALLMONEY'>, <TokenType.ROW: 'ROW'>, <TokenType.TINYINT: 'TINYINT'>, <TokenType.LONGTEXT: 'LONGTEXT'>, <TokenType.INT: 'INT'>, <TokenType.LONGBLOB: 'LONGBLOB'>, <TokenType.IPPREFIX: 'IPPREFIX'>, <TokenType.UNKNOWN: 'UNKNOWN'>, <TokenType.VARCHAR: 'VARCHAR'>, <TokenType.TRUNCATE: 'TRUNCATE'>, <TokenType.POINT: 'POINT'>, <TokenType.VARIANT: 'VARIANT'>, <TokenType.JSON: 'JSON'>, <TokenType.UUID: 'UUID'>, <TokenType.STRUCT: 'STRUCT'>, <TokenType.RANGE: 'RANGE'>, <TokenType.INT8MULTIRANGE: 'INT8MULTIRANGE'>, <TokenType.XML: 'XML'>, <TokenType.INT256: 'INT256'>, <TokenType.DECIMAL64: 'DECIMAL64'>, <TokenType.IMAGE: 'IMAGE'>, <TokenType.CURRENT_USER: 'CURRENT_USER'>, <TokenType.NULLABLE: 'NULLABLE'>, <TokenType.FIRST: 'FIRST'>, <TokenType.INT128: 'INT128'>, <TokenType.TIMETZ: 'TIMETZ'>, <TokenType.TIMESTAMP: 'TIMESTAMP'>, <TokenType.UMEDIUMINT: 'UMEDIUMINT'>, <TokenType.JSONB: 'JSONB'>, <TokenType.SERIAL: 'SERIAL'>, <TokenType.LINESTRING: 'LINESTRING'>, <TokenType.PRIMARY_KEY: 'PRIMARY_KEY'>, <TokenType.DATETIME: 'DATETIME'>}
CONJUNCTION =
{<TokenType.AND: 'AND'>: <class 'sqlglot.expressions.And'>, <TokenType.DAMP: 'DAMP'>: <class 'sqlglot.expressions.And'>, <TokenType.XOR: 'XOR'>: <class 'sqlglot.expressions.Xor'>}
DISJUNCTION =
{<TokenType.OR: 'OR'>: <class 'sqlglot.expressions.Or'>, <TokenType.DPIPE: 'DPIPE'>: <class 'sqlglot.expressions.Or'>}
TABLE_ALIAS_TOKENS =
{<TokenType.ROWS: 'ROWS'>, <TokenType.FUNCTION: 'FUNCTION'>, <TokenType.RENAME: 'RENAME'>, <TokenType.TIMESTAMPTZ: 'TIMESTAMPTZ'>, <TokenType.SOURCE: 'SOURCE'>, <TokenType.UDECIMAL: 'UDECIMAL'>, <TokenType.LIST: 'LIST'>, <TokenType.TIME: 'TIME'>, <TokenType.INET: 'INET'>, <TokenType.REFRESH: 'REFRESH'>, <TokenType.COMMIT: 'COMMIT'>, <TokenType.VAR: 'VAR'>, <TokenType.DETACH: 'DETACH'>, <TokenType.ISNULL: 'ISNULL'>, <TokenType.TABLE: 'TABLE'>, <TokenType.OPERATOR: 'OPERATOR'>, <TokenType.UBIGINT: 'UBIGINT'>, <TokenType.DATE: 'DATE'>, <TokenType.BINARY: 'BINARY'>, <TokenType.TSRANGE: 'TSRANGE'>, <TokenType.ENUM: 'ENUM'>, <TokenType.KEEP: 'KEEP'>, <TokenType.CURRENT_DATETIME: 'CURRENT_DATETIME'>, <TokenType.OBJECT_IDENTIFIER: 'OBJECT_IDENTIFIER'>, <TokenType.COLUMN: 'COLUMN'>, <TokenType.YEAR: 'YEAR'>, <TokenType.COPY: 'COPY'>, <TokenType.TIMESTAMPLTZ: 'TIMESTAMPLTZ'>, <TokenType.MAP: 'MAP'>, <TokenType.BIT: 'BIT'>, <TokenType.DATETIME64: 'DATETIME64'>, <TokenType.FINAL: 'FINAL'>, <TokenType.VECTOR: 'VECTOR'>, <TokenType.UNNEST: 'UNNEST'>, <TokenType.BPCHAR: 'BPCHAR'>, <TokenType.SCHEMA: 'SCHEMA'>, <TokenType.ANY: 'ANY'>, <TokenType.DOUBLE: 'DOUBLE'>, <TokenType.DATE32: 'DATE32'>, <TokenType.CURRENT_TIMESTAMP: 'CURRENT_TIMESTAMP'>, <TokenType.ALL: 'ALL'>, <TokenType.ORDINALITY: 'ORDINALITY'>, <TokenType.KILL: 'KILL'>, <TokenType.BOOLEAN: 'BOOLEAN'>, <TokenType.ENUM16: 'ENUM16'>, <TokenType.END: 'END'>, <TokenType.PARTITION: 'PARTITION'>, <TokenType.FOREIGN_KEY: 'FOREIGN_KEY'>, <TokenType.MODEL: 'MODEL'>, <TokenType.NESTED: 'NESTED'>, <TokenType.ESCAPE: 'ESCAPE'>, <TokenType.PROCEDURE: 'PROCEDURE'>, <TokenType.NUMMULTIRANGE: 'NUMMULTIRANGE'>, <TokenType.VARBINARY: 'VARBINARY'>, <TokenType.GEOGRAPHY: 'GEOGRAPHY'>, <TokenType.CURRENT_TIME: 'CURRENT_TIME'>, <TokenType.SHOW: 'SHOW'>, <TokenType.BIGDECIMAL: 'BIGDECIMAL'>, <TokenType.LOWCARDINALITY: 'LOWCARDINALITY'>, <TokenType.SMALLINT: 'SMALLINT'>, <TokenType.TSMULTIRANGE: 'TSMULTIRANGE'>, <TokenType.PRAGMA: 'PRAGMA'>, <TokenType.FALSE: 'FALSE'>, <TokenType.DATEMULTIRANGE: 'DATEMULTIRANGE'>, <TokenType.SOME: 'SOME'>, <TokenType.DECIMAL: 'DECIMAL'>, <TokenType.INT4RANGE: 'INT4RANGE'>, <TokenType.USMALLINT: 'USMALLINT'>, <TokenType.MEDIUMBLOB: 'MEDIUMBLOB'>, <TokenType.ANTI: 'ANTI'>, <TokenType.CURRENT_DATE: 'CURRENT_DATE'>, <TokenType.COMMAND: 'COMMAND'>, <TokenType.GEOMETRY: 'GEOMETRY'>, <TokenType.FIXEDSTRING: 'FIXEDSTRING'>, <TokenType.IDENTIFIER: 'IDENTIFIER'>, <TokenType.IPV4: 'IPV4'>, <TokenType.UINT256: 'UINT256'>, <TokenType.ATTACH: 'ATTACH'>, <TokenType.ROWVERSION: 'ROWVERSION'>, <TokenType.SINK: 'SINK'>, <TokenType.TOP: 'TOP'>, <TokenType.ARRAY: 'ARRAY'>, <TokenType.DECIMAL128: 'DECIMAL128'>, <TokenType.SIMPLEAGGREGATEFUNCTION: 'SIMPLEAGGREGATEFUNCTION'>, <TokenType.HLLSKETCH: 'HLLSKETCH'>, <TokenType.SUPER: 'SUPER'>, <TokenType.UTINYINT: 'UTINYINT'>, <TokenType.SMALLSERIAL: 'SMALLSERIAL'>, <TokenType.VIEW: 'VIEW'>, <TokenType.CHAR: 'CHAR'>, <TokenType.PIVOT: 'PIVOT'>, <TokenType.IPADDRESS: 'IPADDRESS'>, <TokenType.WAREHOUSE: 'WAREHOUSE'>, <TokenType.EXISTS: 'EXISTS'>, <TokenType.LOAD: 'LOAD'>, <TokenType.SETTINGS: 'SETTINGS'>, <TokenType.TEXT: 'TEXT'>, <TokenType.MEDIUMINT: 'MEDIUMINT'>, <TokenType.TINYTEXT: 'TINYTEXT'>, <TokenType.USERDEFINED: 'USERDEFINED'>, <TokenType.MONEY: 'MONEY'>, <TokenType.INT4MULTIRANGE: 'INT4MULTIRANGE'>, <TokenType.DEFAULT: 'DEFAULT'>, <TokenType.FILTER: 'FILTER'>, <TokenType.MERGE: 'MERGE'>, <TokenType.INDEX: 'INDEX'>, <TokenType.TINYBLOB: 'TINYBLOB'>, <TokenType.BIGSERIAL: 'BIGSERIAL'>, <TokenType.CASE: 'CASE'>, <TokenType.DECIMAL32: 'DECIMAL32'>, <TokenType.INT8RANGE: 'INT8RANGE'>, <TokenType.TIMESTAMP_S: 'TIMESTAMP_S'>, <TokenType.DELETE: 'DELETE'>, <TokenType.MULTIPOLYGON: 'MULTIPOLYGON'>, <TokenType.RING: 'RING'>, <TokenType.DECIMAL256: 'DECIMAL256'>, <TokenType.NAME: 'NAME'>, <TokenType.OVERLAPS: 'OVERLAPS'>, <TokenType.COMMENT: 'COMMENT'>, <TokenType.SEMI: 'SEMI'>, <TokenType.VOLATILE: 'VOLATILE'>, <TokenType.SEQUENCE: 'SEQUENCE'>, <TokenType.STORAGE_INTEGRATION: 'STORAGE_INTEGRATION'>, <TokenType.MEDIUMTEXT: 'MEDIUMTEXT'>, <TokenType.DIV: 'DIV'>, <TokenType.POLYGON: 'POLYGON'>, <TokenType.NVARCHAR: 'NVARCHAR'>, <TokenType.NULL: 'NULL'>, <TokenType.UNIQUE: 'UNIQUE'>, <TokenType.IPV6: 'IPV6'>, <TokenType.FORMAT: 'FORMAT'>, <TokenType.CUBE: 'CUBE'>, <TokenType.DESCRIBE: 'DESCRIBE'>, <TokenType.DATERANGE: 'DATERANGE'>, <TokenType.INTERVAL: 'INTERVAL'>, <TokenType.TSTZRANGE: 'TSTZRANGE'>, <TokenType.DATABASE: 'DATABASE'>, <TokenType.UINT128: 'UINT128'>, <TokenType.TIMESTAMPNTZ: 'TIMESTAMPNTZ'>, <TokenType.TSTZMULTIRANGE: 'TSTZMULTIRANGE'>, <TokenType.MULTILINESTRING: 'MULTILINESTRING'>, <TokenType.TAG: 'TAG'>, <TokenType.FLOAT: 'FLOAT'>, <TokenType.ENUM8: 'ENUM8'>, <TokenType.HSTORE: 'HSTORE'>, <TokenType.UINT: 'UINT'>, <TokenType.ASC: 'ASC'>, <TokenType.BIGINT: 'BIGINT'>, <TokenType.TIMESTAMP_NS: 'TIMESTAMP_NS'>, <TokenType.AGGREGATEFUNCTION: 'AGGREGATEFUNCTION'>, <TokenType.REPLACE: 'REPLACE'>, <TokenType.PERCENT: 'PERCENT'>, <TokenType.TIMESTAMP_MS: 'TIMESTAMP_MS'>, <TokenType.COLLATE: 'COLLATE'>, <TokenType.ROLLUP: 'ROLLUP'>, <TokenType.NUMRANGE: 'NUMRANGE'>, <TokenType.TEMPORARY: 'TEMPORARY'>, <TokenType.DESC: 'DESC'>, <TokenType.RECURSIVE: 'RECURSIVE'>, <TokenType.EXECUTE: 'EXECUTE'>, <TokenType.PSEUDO_TYPE: 'PSEUDO_TYPE'>, <TokenType.TRUE: 'TRUE'>, <TokenType.OBJECT: 'OBJECT'>, <TokenType.NCHAR: 'NCHAR'>, <TokenType.TDIGEST: 'TDIGEST'>, <TokenType.UNIQUEIDENTIFIER: 'UNIQUEIDENTIFIER'>, <TokenType.CACHE: 'CACHE'>, <TokenType.SMALLMONEY: 'SMALLMONEY'>, <TokenType.ROW: 'ROW'>, <TokenType.TINYINT: 'TINYINT'>, <TokenType.LONGTEXT: 'LONGTEXT'>, <TokenType.DICTIONARY: 'DICTIONARY'>, <TokenType.SET: 'SET'>, <TokenType.UNPIVOT: 'UNPIVOT'>, <TokenType.INT: 'INT'>, <TokenType.LONGBLOB: 'LONGBLOB'>, <TokenType.IPPREFIX: 'IPPREFIX'>, <TokenType.UNKNOWN: 'UNKNOWN'>, <TokenType.AUTO_INCREMENT: 'AUTO_INCREMENT'>, <TokenType.VARCHAR: 'VARCHAR'>, <TokenType.TRUNCATE: 'TRUNCATE'>, <TokenType.POINT: 'POINT'>, <TokenType.CONSTRAINT: 'CONSTRAINT'>, <TokenType.VARIANT: 'VARIANT'>, <TokenType.BEGIN: 'BEGIN'>, <TokenType.JSON: 'JSON'>, <TokenType.OVERWRITE: 'OVERWRITE'>, <TokenType.UUID: 'UUID'>, <TokenType.STRUCT: 'STRUCT'>, <TokenType.RANGE: 'RANGE'>, <TokenType.INT8MULTIRANGE: 'INT8MULTIRANGE'>, <TokenType.XML: 'XML'>, <TokenType.INT256: 'INT256'>, <TokenType.DECIMAL64: 'DECIMAL64'>, <TokenType.STREAMLIT: 'STREAMLIT'>, <TokenType.IMAGE: 'IMAGE'>, <TokenType.CURRENT_USER: 'CURRENT_USER'>, <TokenType.UPDATE: 'UPDATE'>, <TokenType.NULLABLE: 'NULLABLE'>, <TokenType.FIRST: 'FIRST'>, <TokenType.INT128: 'INT128'>, <TokenType.TIMETZ: 'TIMETZ'>, <TokenType.TIMESTAMP: 'TIMESTAMP'>, <TokenType.UMEDIUMINT: 'UMEDIUMINT'>, <TokenType.IS: 'IS'>, <TokenType.JSONB: 'JSONB'>, <TokenType.SERIAL: 'SERIAL'>, <TokenType.LINESTRING: 'LINESTRING'>, <TokenType.NEXT: 'NEXT'>, <TokenType.REFERENCES: 'REFERENCES'>, <TokenType.DATETIME: 'DATETIME'>}
RANGE_PARSERS =
{<TokenType.AT_GT: 'AT_GT'>: <function binary_range_parser.<locals>._parse_binary_range>, <TokenType.BETWEEN: 'BETWEEN'>: <function Parser.<lambda>>, <TokenType.GLOB: 'GLOB'>: <function binary_range_parser.<locals>._parse_binary_range>, <TokenType.ILIKE: 'ILIKE'>: <function binary_range_parser.<locals>._parse_binary_range>, <TokenType.IN: 'IN'>: <function Parser.<lambda>>, <TokenType.IRLIKE: 'IRLIKE'>: <function binary_range_parser.<locals>._parse_binary_range>, <TokenType.IS: 'IS'>: <function Parser.<lambda>>, <TokenType.LIKE: 'LIKE'>: <function binary_range_parser.<locals>._parse_binary_range>, <TokenType.LT_AT: 'LT_AT'>: <function binary_range_parser.<locals>._parse_binary_range>, <TokenType.OVERLAPS: 'OVERLAPS'>: <function binary_range_parser.<locals>._parse_binary_range>, <TokenType.RLIKE: 'RLIKE'>: <function binary_range_parser.<locals>._parse_binary_range>, <TokenType.SIMILAR_TO: 'SIMILAR_TO'>: <function binary_range_parser.<locals>._parse_binary_range>, <TokenType.FOR: 'FOR'>: <function Parser.<lambda>>, <TokenType.MEMBER_OF: 'MEMBER_OF'>: <function MySQL.Parser.<lambda>>}
FUNCTIONS =
{'ABS': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Abs'>>, 'ADD_MONTHS': <bound method Func.from_arg_list of <class 'sqlglot.expressions.AddMonths'>>, 'ANONYMOUS_AGG_FUNC': <bound method Func.from_arg_list of <class 'sqlglot.expressions.AnonymousAggFunc'>>, 'ANY_VALUE': <bound method Func.from_arg_list of <class 'sqlglot.expressions.AnyValue'>>, 'APPLY': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Apply'>>, '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'>>, 'APPROX_TOP_K': <bound method Func.from_arg_list of <class 'sqlglot.expressions.ApproxTopK'>>, 'ARG_MAX': <bound method Func.from_arg_list of <class 'sqlglot.expressions.ArgMax'>>, 'ARGMAX': <bound method Func.from_arg_list of <class 'sqlglot.expressions.ArgMax'>>, 'MAX_BY': <bound method Func.from_arg_list of <class 'sqlglot.expressions.ArgMax'>>, 'ARG_MIN': <bound method Func.from_arg_list of <class 'sqlglot.expressions.ArgMin'>>, 'ARGMIN': <bound method Func.from_arg_list of <class 'sqlglot.expressions.ArgMin'>>, 'MIN_BY': <bound method Func.from_arg_list of <class 'sqlglot.expressions.ArgMin'>>, 'ARRAY': <function Parser.<lambda>>, 'ARRAY_AGG': <function Parser.<lambda>>, '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_CAT': <bound method Func.from_arg_list of <class 'sqlglot.expressions.ArrayConcat'>>, 'ARRAY_CONSTRUCT_COMPACT': <bound method Func.from_arg_list of <class 'sqlglot.expressions.ArrayConstructCompact'>>, 'ARRAY_CONTAINS': <bound method Func.from_arg_list of <class 'sqlglot.expressions.ArrayContains'>>, 'ARRAY_HAS': <bound method Func.from_arg_list of <class 'sqlglot.expressions.ArrayContains'>>, 'ARRAY_CONTAINS_ALL': <bound method Func.from_arg_list of <class 'sqlglot.expressions.ArrayContainsAll'>>, 'ARRAY_HAS_ALL': <bound method Func.from_arg_list of <class 'sqlglot.expressions.ArrayContainsAll'>>, '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_OVERLAPS': <bound method Func.from_arg_list of <class 'sqlglot.expressions.ArrayOverlaps'>>, 'ARRAY_SIZE': <bound method Func.from_arg_list of <class 'sqlglot.expressions.ArraySize'>>, 'ARRAY_LENGTH': <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_TO_STRING': <bound method Func.from_arg_list of <class 'sqlglot.expressions.ArrayToString'>>, 'ARRAY_JOIN': <bound method Func.from_arg_list of <class 'sqlglot.expressions.ArrayToString'>>, 'ARRAY_UNION_AGG': <bound method Func.from_arg_list of <class 'sqlglot.expressions.ArrayUnionAgg'>>, 'ARRAY_UNIQUE_AGG': <bound method Func.from_arg_list of <class 'sqlglot.expressions.ArrayUniqueAgg'>>, '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'>>, 'CBRT': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Cbrt'>>, 'CEIL': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Ceil'>>, 'CEILING': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Ceil'>>, 'CHR': <function Parser.<lambda>>, 'CHAR': <function Parser.<lambda>>, 'COALESCE': <function build_coalesce>, 'IFNULL': <function build_coalesce>, 'NVL': <function build_coalesce>, 'COLLATE': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Collate'>>, 'COLUMNS': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Columns'>>, 'COMBINED_AGG_FUNC': <bound method Func.from_arg_list of <class 'sqlglot.expressions.CombinedAggFunc'>>, 'COMBINED_PARAMETERIZED_AGG': <bound method Func.from_arg_list of <class 'sqlglot.expressions.CombinedParameterizedAgg'>>, 'CONCAT': <function Parser.<lambda>>, 'CONCAT_WS': <function Parser.<lambda>>, 'CONNECT_BY_ROOT': <bound method Func.from_arg_list of <class 'sqlglot.expressions.ConnectByRoot'>>, 'CONTAINS': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Contains'>>, 'CONVERT': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Convert'>>, 'CONVERT_TIMEZONE': <function build_convert_timezone>, 'CORR': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Corr'>>, 'COUNT': <function Parser.<lambda>>, 'COUNT_IF': <bound method Func.from_arg_list of <class 'sqlglot.expressions.CountIf'>>, 'COUNTIF': <bound method Func.from_arg_list of <class 'sqlglot.expressions.CountIf'>>, 'COVAR_POP': <bound method Func.from_arg_list of <class 'sqlglot.expressions.CovarPop'>>, 'COVAR_SAMP': <bound method Func.from_arg_list of <class 'sqlglot.expressions.CovarSamp'>>, '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': <function MySQL.Parser.<lambda>>, 'DATE_ADD': <function build_date_delta_with_interval.<locals>._builder>, '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'>>, 'DATE_FROM_PARTS': <bound method Func.from_arg_list of <class 'sqlglot.expressions.DateFromParts'>>, '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 build_date_delta_with_interval.<locals>._builder>, 'DATE_TO_DATE_STR': <function Parser.<lambda>>, 'DATE_TO_DI': <bound method Func.from_arg_list of <class 'sqlglot.expressions.DateToDi'>>, 'DATE_TRUNC': <bound method Func.from_arg_list of <class 'sqlglot.expressions.DateTrunc'>>, 'DATETIME': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Datetime'>>, 'DATETIME_ADD': <bound method Func.from_arg_list of <class 'sqlglot.expressions.DatetimeAdd'>>, 'DATETIME_DIFF': <bound method Func.from_arg_list of <class 'sqlglot.expressions.DatetimeDiff'>>, 'DATETIME_SUB': <bound method Func.from_arg_list of <class 'sqlglot.expressions.DatetimeSub'>>, 'DATETIME_TRUNC': <bound method Func.from_arg_list of <class 'sqlglot.expressions.DatetimeTrunc'>>, 'DAY': <function MySQL.Parser.<lambda>>, 'DAY_OF_MONTH': <bound method Func.from_arg_list of <class 'sqlglot.expressions.DayOfMonth'>>, 'DAYOFMONTH': <function MySQL.Parser.<lambda>>, 'DAY_OF_WEEK': <bound method Func.from_arg_list of <class 'sqlglot.expressions.DayOfWeek'>>, 'DAYOFWEEK': <function MySQL.Parser.<lambda>>, 'DAYOFWEEK_ISO': <bound method Func.from_arg_list of <class 'sqlglot.expressions.DayOfWeekIso'>>, 'ISODOW': <bound method Func.from_arg_list of <class 'sqlglot.expressions.DayOfWeekIso'>>, 'DAY_OF_YEAR': <bound method Func.from_arg_list of <class 'sqlglot.expressions.DayOfYear'>>, 'DAYOFYEAR': <function MySQL.Parser.<lambda>>, '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'>>, 'EXISTS': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Exists'>>, 'EXP': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Exp'>>, 'EXPLODE': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Explode'>>, 'EXPLODE_OUTER': <bound method Func.from_arg_list of <class 'sqlglot.expressions.ExplodeOuter'>>, 'EXPLODING_GENERATE_SERIES': <bound method Func.from_arg_list of <class 'sqlglot.expressions.ExplodingGenerateSeries'>>, 'EXTRACT': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Extract'>>, 'FEATURES_AT_TIME': <bound method Func.from_arg_list of <class 'sqlglot.expressions.FeaturesAtTime'>>, 'FIRST': <bound method Func.from_arg_list of <class 'sqlglot.expressions.First'>>, 'FIRST_VALUE': <bound method Func.from_arg_list of <class 'sqlglot.expressions.FirstValue'>>, 'FLATTEN': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Flatten'>>, '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'>>, 'FROM_ISO8601_TIMESTAMP': <bound method Func.from_arg_list of <class 'sqlglot.expressions.FromISO8601Timestamp'>>, 'GAP_FILL': <bound method Func.from_arg_list of <class 'sqlglot.expressions.GapFill'>>, 'GENERATE_DATE_ARRAY': <function Parser.<lambda>>, 'GENERATE_SERIES': <bound method Func.from_arg_list of <class 'sqlglot.expressions.GenerateSeries'>>, 'GENERATE_TIMESTAMP_ARRAY': <bound method Func.from_arg_list of <class 'sqlglot.expressions.GenerateTimestampArray'>>, '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': <function build_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'>>, 'IIF': <bound method Func.from_arg_list of <class 'sqlglot.expressions.If'>>, 'INITCAP': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Initcap'>>, 'INLINE': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Inline'>>, 'INT64': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Int64'>>, 'IS_INF': <bound method Func.from_arg_list of <class 'sqlglot.expressions.IsInf'>>, 'ISINF': <bound method Func.from_arg_list of <class 'sqlglot.expressions.IsInf'>>, 'IS_NAN': <bound method Func.from_arg_list of <class 'sqlglot.expressions.IsNan'>>, 'ISNAN': <bound method Func.from_arg_list of <class 'sqlglot.expressions.IsNan'>>, 'J_S_O_N_ARRAY': <bound method Func.from_arg_list of <class 'sqlglot.expressions.JSONArray'>>, 'J_S_O_N_ARRAY_AGG': <bound method Func.from_arg_list of <class 'sqlglot.expressions.JSONArrayAgg'>>, 'JSON_ARRAY_CONTAINS': <bound method Func.from_arg_list of <class 'sqlglot.expressions.JSONArrayContains'>>, 'JSONB_CONTAINS': <bound method Func.from_arg_list of <class 'sqlglot.expressions.JSONBContains'>>, 'JSONB_EXISTS': <bound method Func.from_arg_list of <class 'sqlglot.expressions.JSONBExists'>>, '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'>>, 'J_S_O_N_EXISTS': <bound method Func.from_arg_list of <class 'sqlglot.expressions.JSONExists'>>, 'JSON_EXTRACT': <function build_extract_json_with_path.<locals>._builder>, 'JSON_EXTRACT_ARRAY': <bound method Func.from_arg_list of <class 'sqlglot.expressions.JSONExtractArray'>>, 'JSON_EXTRACT_SCALAR': <function build_extract_json_with_path.<locals>._builder>, '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'>>, 'J_S_O_N_OBJECT_AGG': <bound method Func.from_arg_list of <class 'sqlglot.expressions.JSONObjectAgg'>>, 'J_S_O_N_TABLE': <bound method Func.from_arg_list of <class 'sqlglot.expressions.JSONTable'>>, 'J_S_O_N_VALUE_ARRAY': <bound method Func.from_arg_list of <class 'sqlglot.expressions.JSONValueArray'>>, 'LAG': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Lag'>>, 'LAST': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Last'>>, 'LAST_DAY': <bound method Func.from_arg_list of <class 'sqlglot.expressions.LastDay'>>, 'LAST_DAY_OF_MONTH': <bound method Func.from_arg_list of <class 'sqlglot.expressions.LastDay'>>, 'LAST_VALUE': <bound method Func.from_arg_list of <class 'sqlglot.expressions.LastValue'>>, 'LEAD': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Lead'>>, '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'>>, 'LIST': <bound method Func.from_arg_list of <class 'sqlglot.expressions.List'>>, 'LN': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Ln'>>, 'LOG': <function build_logarithm>, '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': <function build_lower>, 'LCASE': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Lower'>>, 'LOWER_HEX': <bound method Func.from_arg_list of <class 'sqlglot.expressions.LowerHex'>>, 'MD5': <bound method Func.from_arg_list of <class 'sqlglot.expressions.MD5'>>, 'MD5_DIGEST': <bound method Func.from_arg_list of <class 'sqlglot.expressions.MD5Digest'>>, 'MAKE_INTERVAL': <bound method Func.from_arg_list of <class 'sqlglot.expressions.MakeInterval'>>, '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'>>, 'MEDIAN': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Median'>>, 'MIN': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Min'>>, 'MONTH': <function MySQL.Parser.<lambda>>, 'MONTHS_BETWEEN': <bound method Func.from_arg_list of <class 'sqlglot.expressions.MonthsBetween'>>, 'NEXT_VALUE_FOR': <bound method Func.from_arg_list of <class 'sqlglot.expressions.NextValueFor'>>, 'NORMALIZE': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Normalize'>>, 'NTH_VALUE': <bound method Func.from_arg_list of <class 'sqlglot.expressions.NthValue'>>, 'NULLIF': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Nullif'>>, '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'>>, 'OBJECT_INSERT': <bound method Func.from_arg_list of <class 'sqlglot.expressions.ObjectInsert'>>, 'OPEN_J_S_O_N': <bound method Func.from_arg_list of <class 'sqlglot.expressions.OpenJSON'>>, 'OVERLAY': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Overlay'>>, 'PAD': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Pad'>>, 'PARAMETERIZED_AGG': <bound method Func.from_arg_list of <class 'sqlglot.expressions.ParameterizedAgg'>>, 'PARSE_JSON': <bound method Func.from_arg_list of <class 'sqlglot.expressions.ParseJSON'>>, 'JSON_PARSE': <bound method Func.from_arg_list of <class 'sqlglot.expressions.ParseJSON'>>, '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'>>, 'POSEXPLODE_OUTER': <bound method Func.from_arg_list of <class 'sqlglot.expressions.PosexplodeOuter'>>, 'POWER': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Pow'>>, 'POW': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Pow'>>, 'PREDICT': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Predict'>>, 'QUANTILE': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Quantile'>>, 'QUARTER': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Quarter'>>, 'RAND': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Rand'>>, 'RANDOM': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Rand'>>, 'RANDN': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Randn'>>, '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': <bound method Func.from_arg_list of <class 'sqlglot.expressions.RegexpExtract'>>, 'REGEXP_EXTRACT_ALL': <bound method Func.from_arg_list of <class 'sqlglot.expressions.RegexpExtractAll'>>, '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_REPLACE': <bound method Func.from_arg_list of <class 'sqlglot.expressions.RegexpReplace'>>, '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_DIVIDE': <bound method Func.from_arg_list of <class 'sqlglot.expressions.SafeDivide'>>, 'SIGN': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Sign'>>, 'SIGNUM': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Sign'>>, 'SORT_ARRAY': <bound method Func.from_arg_list of <class 'sqlglot.expressions.SortArray'>>, 'SPLIT': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Split'>>, 'SPLIT_PART': <bound method Func.from_arg_list of <class 'sqlglot.expressions.SplitPart'>>, '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'>>, 'STARTS_WITH': <bound method Func.from_arg_list of <class 'sqlglot.expressions.StartsWith'>>, 'STARTSWITH': <bound method Func.from_arg_list of <class 'sqlglot.expressions.StartsWith'>>, 'STDDEV': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Stddev'>>, 'STDEV': <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': <function _str_to_date>, 'STR_TO_MAP': <bound method Func.from_arg_list of <class 'sqlglot.expressions.StrToMap'>>, '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'>>, 'STRING': <bound method Func.from_arg_list of <class 'sqlglot.expressions.String'>>, 'STRING_TO_ARRAY': <bound method Func.from_arg_list of <class 'sqlglot.expressions.StringToArray'>>, 'SPLIT_BY_STRING': <bound method Func.from_arg_list of <class 'sqlglot.expressions.StringToArray'>>, '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'>>, 'STUFF': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Stuff'>>, 'INSERT': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Stuff'>>, 'SUBSTRING': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Substring'>>, 'SUBSTR': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Substring'>>, 'SUM': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Sum'>>, 'TIME': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Time'>>, 'TIME_ADD': <bound method Func.from_arg_list of <class 'sqlglot.expressions.TimeAdd'>>, 'TIME_DIFF': <bound method Func.from_arg_list of <class 'sqlglot.expressions.TimeDiff'>>, 'TIME_FROM_PARTS': <bound method Func.from_arg_list of <class 'sqlglot.expressions.TimeFromParts'>>, 'TIMEFROMPARTS': <bound method Func.from_arg_list of <class 'sqlglot.expressions.TimeFromParts'>>, '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': <bound method Func.from_arg_list of <class 'sqlglot.expressions.TimeSub'>>, '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': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Timestamp'>>, 'TIMESTAMP_ADD': <bound method Func.from_arg_list of <class 'sqlglot.expressions.TimestampAdd'>>, 'TIMESTAMPDIFF': <function build_date_delta.<locals>._builder>, 'TIMESTAMP_DIFF': <bound method Func.from_arg_list of <class 'sqlglot.expressions.TimestampDiff'>>, 'TIMESTAMP_FROM_PARTS': <bound method Func.from_arg_list of <class 'sqlglot.expressions.TimestampFromParts'>>, 'TIMESTAMPFROMPARTS': <bound method Func.from_arg_list of <class 'sqlglot.expressions.TimestampFromParts'>>, 'TIMESTAMP_SUB': <bound method Func.from_arg_list of <class 'sqlglot.expressions.TimestampSub'>>, 'TIMESTAMP_TRUNC': <bound method Func.from_arg_list of <class 'sqlglot.expressions.TimestampTrunc'>>, 'TO_ARRAY': <bound method Func.from_arg_list of <class 'sqlglot.expressions.ToArray'>>, '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'>>, 'TO_DAYS': <function MySQL.Parser.<lambda>>, 'TO_DOUBLE': <bound method Func.from_arg_list of <class 'sqlglot.expressions.ToDouble'>>, 'TO_MAP': <bound method Func.from_arg_list of <class 'sqlglot.expressions.ToMap'>>, 'TO_NUMBER': <bound method Func.from_arg_list of <class 'sqlglot.expressions.ToNumber'>>, 'TRANSFORM': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Transform'>>, 'TRIM': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Trim'>>, 'TRY': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Try'>>, '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_DIFF': <bound method Func.from_arg_list of <class 'sqlglot.expressions.TsOrDsDiff'>>, '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>>, 'TS_OR_DS_TO_DATETIME': <bound method Func.from_arg_list of <class 'sqlglot.expressions.TsOrDsToDatetime'>>, 'TS_OR_DS_TO_TIME': <bound method Func.from_arg_list of <class 'sqlglot.expressions.TsOrDsToTime'>>, 'TS_OR_DS_TO_TIMESTAMP': <bound method Func.from_arg_list of <class 'sqlglot.expressions.TsOrDsToTimestamp'>>, 'UNHEX': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Unhex'>>, 'UNIX_DATE': <bound method Func.from_arg_list of <class 'sqlglot.expressions.UnixDate'>>, 'UNIX_SECONDS': <bound method Func.from_arg_list of <class 'sqlglot.expressions.UnixSeconds'>>, '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'>>, 'UNNEST': <function Parser.<lambda>>, 'UPPER': <function build_upper>, 'UCASE': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Upper'>>, 'UUID': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Uuid'>>, 'GEN_RANDOM_UUID': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Uuid'>>, 'GENERATE_UUID': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Uuid'>>, 'UUID_STRING': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Uuid'>>, 'VAR_MAP': <function build_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': <function MySQL.Parser.<lambda>>, 'WEEK_OF_YEAR': <bound method Func.from_arg_list of <class 'sqlglot.expressions.WeekOfYear'>>, 'WEEKOFYEAR': <function MySQL.Parser.<lambda>>, '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'>>, 'XOR': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Xor'>>, 'YEAR': <function MySQL.Parser.<lambda>>, 'ARRAYAGG': <function Parser.<lambda>>, 'GLOB': <function Parser.<lambda>>, 'INSTR': <function Parser.<lambda>>, 'JSON_EXTRACT_PATH_TEXT': <function build_extract_json_with_path.<locals>._builder>, 'LIKE': <function build_like>, 'LOG2': <function Parser.<lambda>>, 'LOG10': <function Parser.<lambda>>, 'LPAD': <function Parser.<lambda>>, 'LEFTPAD': <function Parser.<lambda>>, 'LTRIM': <function Parser.<lambda>>, 'MOD': <function build_mod>, 'RIGHTPAD': <function Parser.<lambda>>, 'RPAD': <function Parser.<lambda>>, 'RTRIM': <function Parser.<lambda>>, 'SCOPE_RESOLUTION': <function Parser.<lambda>>, 'TO_HEX': <function build_hex>, 'CHAR_LENGTH': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Length'>>, 'CHARACTER_LENGTH': <bound method Func.from_arg_list of <class 'sqlglot.expressions.Length'>>, 'CONVERT_TZ': <function MySQL.Parser.<lambda>>, 'DATE_FORMAT': <function build_formatted_time.<locals>._builder>, 'FROM_UNIXTIME': <function build_formatted_time.<locals>._builder>, 'ISNULL': <function isnull_to_is_null>, 'LOCATE': <function locate_to_strposition>, 'MAKETIME': <bound method Func.from_arg_list of <class 'sqlglot.expressions.TimeFromParts'>>, 'MONTHNAME': <function MySQL.Parser.<lambda>>}
FUNCTION_PARSERS =
{'CAST': <function Parser.<lambda>>, 'CONVERT': <function Parser.<lambda>>, 'DECODE': <function Parser.<lambda>>, 'EXTRACT': <function Parser.<lambda>>, 'GAP_FILL': <function Parser.<lambda>>, 'JSON_OBJECT': <function Parser.<lambda>>, 'JSON_OBJECTAGG': <function Parser.<lambda>>, 'JSON_TABLE': <function Parser.<lambda>>, 'MATCH': <function Parser.<lambda>>, 'NORMALIZE': <function Parser.<lambda>>, 'OPENJSON': <function Parser.<lambda>>, 'OVERLAY': <function Parser.<lambda>>, 'POSITION': <function Parser.<lambda>>, 'PREDICT': <function Parser.<lambda>>, 'SAFE_CAST': <function Parser.<lambda>>, 'STRING_AGG': <function Parser.<lambda>>, 'SUBSTRING': <function Parser.<lambda>>, 'TRIM': <function Parser.<lambda>>, 'TRY_CAST': <function Parser.<lambda>>, 'TRY_CONVERT': <function Parser.<lambda>>, 'CHAR': <function MySQL.Parser.<lambda>>, 'GROUP_CONCAT': <function MySQL.Parser.<lambda>>, 'VALUES': <function MySQL.Parser.<lambda>>, 'JSON_VALUE': <function MySQL.Parser.<lambda>>}
STATEMENT_PARSERS =
{<TokenType.ALTER: 'ALTER'>: <function Parser.<lambda>>, <TokenType.BEGIN: 'BEGIN'>: <function Parser.<lambda>>, <TokenType.CACHE: 'CACHE'>: <function Parser.<lambda>>, <TokenType.COMMENT: 'COMMENT'>: <function Parser.<lambda>>, <TokenType.COMMIT: 'COMMIT'>: <function Parser.<lambda>>, <TokenType.COPY: 'COPY'>: <function Parser.<lambda>>, <TokenType.CREATE: 'CREATE'>: <function Parser.<lambda>>, <TokenType.DELETE: 'DELETE'>: <function Parser.<lambda>>, <TokenType.DESC: 'DESC'>: <function Parser.<lambda>>, <TokenType.DESCRIBE: 'DESCRIBE'>: <function Parser.<lambda>>, <TokenType.DROP: 'DROP'>: <function Parser.<lambda>>, <TokenType.GRANT: 'GRANT'>: <function Parser.<lambda>>, <TokenType.INSERT: 'INSERT'>: <function Parser.<lambda>>, <TokenType.KILL: 'KILL'>: <function Parser.<lambda>>, <TokenType.LOAD: 'LOAD'>: <function Parser.<lambda>>, <TokenType.MERGE: 'MERGE'>: <function Parser.<lambda>>, <TokenType.PIVOT: 'PIVOT'>: <function Parser.<lambda>>, <TokenType.PRAGMA: 'PRAGMA'>: <function Parser.<lambda>>, <TokenType.REFRESH: 'REFRESH'>: <function Parser.<lambda>>, <TokenType.ROLLBACK: 'ROLLBACK'>: <function Parser.<lambda>>, <TokenType.SET: 'SET'>: <function Parser.<lambda>>, <TokenType.TRUNCATE: 'TRUNCATE'>: <function Parser.<lambda>>, <TokenType.UNCACHE: 'UNCACHE'>: <function Parser.<lambda>>, <TokenType.UPDATE: 'UPDATE'>: <function Parser.<lambda>>, <TokenType.USE: 'USE'>: <function Parser.<lambda>>, <TokenType.SEMICOLON: 'SEMICOLON'>: <function Parser.<lambda>>, <TokenType.SHOW: 'SHOW'>: <function MySQL.Parser.<lambda>>}
SHOW_PARSERS =
{'BINARY LOGS': <function _show_parser.<locals>._parse>, 'MASTER LOGS': <function _show_parser.<locals>._parse>, 'BINLOG EVENTS': <function _show_parser.<locals>._parse>, 'CHARACTER SET': <function _show_parser.<locals>._parse>, 'CHARSET': <function _show_parser.<locals>._parse>, 'COLLATION': <function _show_parser.<locals>._parse>, 'FULL COLUMNS': <function _show_parser.<locals>._parse>, 'COLUMNS': <function _show_parser.<locals>._parse>, 'CREATE DATABASE': <function _show_parser.<locals>._parse>, 'CREATE EVENT': <function _show_parser.<locals>._parse>, 'CREATE FUNCTION': <function _show_parser.<locals>._parse>, 'CREATE PROCEDURE': <function _show_parser.<locals>._parse>, 'CREATE TABLE': <function _show_parser.<locals>._parse>, 'CREATE TRIGGER': <function _show_parser.<locals>._parse>, 'CREATE VIEW': <function _show_parser.<locals>._parse>, 'DATABASES': <function _show_parser.<locals>._parse>, 'SCHEMAS': <function _show_parser.<locals>._parse>, 'ENGINE': <function _show_parser.<locals>._parse>, 'STORAGE ENGINES': <function _show_parser.<locals>._parse>, 'ENGINES': <function _show_parser.<locals>._parse>, 'ERRORS': <function _show_parser.<locals>._parse>, 'EVENTS': <function _show_parser.<locals>._parse>, 'FUNCTION CODE': <function _show_parser.<locals>._parse>, 'FUNCTION STATUS': <function _show_parser.<locals>._parse>, 'GRANTS': <function _show_parser.<locals>._parse>, 'INDEX': <function _show_parser.<locals>._parse>, 'MASTER STATUS': <function _show_parser.<locals>._parse>, 'OPEN TABLES': <function _show_parser.<locals>._parse>, 'PLUGINS': <function _show_parser.<locals>._parse>, 'PROCEDURE CODE': <function _show_parser.<locals>._parse>, 'PROCEDURE STATUS': <function _show_parser.<locals>._parse>, 'PRIVILEGES': <function _show_parser.<locals>._parse>, 'FULL PROCESSLIST': <function _show_parser.<locals>._parse>, 'PROCESSLIST': <function _show_parser.<locals>._parse>, 'PROFILE': <function _show_parser.<locals>._parse>, 'PROFILES': <function _show_parser.<locals>._parse>, 'RELAYLOG EVENTS': <function _show_parser.<locals>._parse>, 'REPLICAS': <function _show_parser.<locals>._parse>, 'SLAVE HOSTS': <function _show_parser.<locals>._parse>, 'REPLICA STATUS': <function _show_parser.<locals>._parse>, 'SLAVE STATUS': <function _show_parser.<locals>._parse>, 'GLOBAL STATUS': <function _show_parser.<locals>._parse>, 'SESSION STATUS': <function _show_parser.<locals>._parse>, 'STATUS': <function _show_parser.<locals>._parse>, 'TABLE STATUS': <function _show_parser.<locals>._parse>, 'FULL TABLES': <function _show_parser.<locals>._parse>, 'TABLES': <function _show_parser.<locals>._parse>, 'TRIGGERS': <function _show_parser.<locals>._parse>, 'GLOBAL VARIABLES': <function _show_parser.<locals>._parse>, 'SESSION VARIABLES': <function _show_parser.<locals>._parse>, 'VARIABLES': <function _show_parser.<locals>._parse>, 'WARNINGS': <function _show_parser.<locals>._parse>}
PROPERTY_PARSERS =
{'ALLOWED_VALUES': <function Parser.<lambda>>, 'ALGORITHM': <function Parser.<lambda>>, 'AUTO': <function Parser.<lambda>>, 'AUTO_INCREMENT': <function Parser.<lambda>>, 'BACKUP': <function Parser.<lambda>>, 'BLOCKCOMPRESSION': <function Parser.<lambda>>, 'CHARSET': <function Parser.<lambda>>, 'CHARACTER SET': <function Parser.<lambda>>, 'CHECKSUM': <function Parser.<lambda>>, 'CLUSTER BY': <function Parser.<lambda>>, 'CLUSTERED': <function Parser.<lambda>>, 'COLLATE': <function Parser.<lambda>>, 'COMMENT': <function Parser.<lambda>>, 'CONTAINS': <function Parser.<lambda>>, 'COPY': <function Parser.<lambda>>, 'DATABLOCKSIZE': <function Parser.<lambda>>, 'DATA_DELETION': <function Parser.<lambda>>, 'DEFINER': <function Parser.<lambda>>, 'DETERMINISTIC': <function Parser.<lambda>>, 'DISTRIBUTED': <function Parser.<lambda>>, 'DUPLICATE': <function Parser.<lambda>>, 'DYNAMIC': <function Parser.<lambda>>, 'DISTKEY': <function Parser.<lambda>>, 'DISTSTYLE': <function Parser.<lambda>>, 'EMPTY': <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>>, 'GLOBAL': <function Parser.<lambda>>, 'HEAP': <function Parser.<lambda>>, 'ICEBERG': <function Parser.<lambda>>, 'IMMUTABLE': <function Parser.<lambda>>, 'INHERITS': <function Parser.<lambda>>, 'INPUT': <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 MySQL.Parser.<lambda>>, 'LOCKING': <function Parser.<lambda>>, 'LOG': <function Parser.<lambda>>, 'MATERIALIZED': <function Parser.<lambda>>, 'MERGEBLOCKRATIO': <function Parser.<lambda>>, 'MODIFIES': <function Parser.<lambda>>, 'MULTISET': <function Parser.<lambda>>, 'NO': <function Parser.<lambda>>, 'ON': <function Parser.<lambda>>, 'ORDER BY': <function Parser.<lambda>>, 'OUTPUT': <function Parser.<lambda>>, 'PARTITION': <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>>, 'READS': <function Parser.<lambda>>, 'REMOTE': <function Parser.<lambda>>, 'RETURNS': <function Parser.<lambda>>, 'STRICT': <function Parser.<lambda>>, 'STREAMING': <function Parser.<lambda>>, 'ROW': <function Parser.<lambda>>, 'ROW_FORMAT': <function Parser.<lambda>>, 'SAMPLE': <function Parser.<lambda>>, 'SECURE': <function Parser.<lambda>>, 'SECURITY': <function Parser.<lambda>>, 'SET': <function Parser.<lambda>>, 'SETTINGS': <function Parser.<lambda>>, 'SHARING': <function Parser.<lambda>>, 'SORTKEY': <function Parser.<lambda>>, 'SOURCE': <function Parser.<lambda>>, 'STABLE': <function Parser.<lambda>>, 'STORED': <function Parser.<lambda>>, 'SYSTEM_VERSIONING': <function Parser.<lambda>>, 'TBLPROPERTIES': <function Parser.<lambda>>, 'TEMP': <function Parser.<lambda>>, 'TEMPORARY': <function Parser.<lambda>>, 'TO': <function Parser.<lambda>>, 'TRANSIENT': <function Parser.<lambda>>, 'TRANSFORM': <function Parser.<lambda>>, 'TTL': <function Parser.<lambda>>, 'USING': <function Parser.<lambda>>, 'UNLOGGED': <function Parser.<lambda>>, 'VOLATILE': <function Parser.<lambda>>, 'WITH': <function Parser.<lambda>>}
SET_PARSERS =
{'GLOBAL': <function Parser.<lambda>>, 'LOCAL': <function Parser.<lambda>>, 'SESSION': <function Parser.<lambda>>, 'TRANSACTION': <function Parser.<lambda>>, 'PERSIST': <function MySQL.Parser.<lambda>>, 'PERSIST_ONLY': <function MySQL.Parser.<lambda>>, 'CHARACTER SET': <function MySQL.Parser.<lambda>>, 'CHARSET': <function MySQL.Parser.<lambda>>, 'NAMES': <function MySQL.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>>, 'CLUSTERED': <function Parser.<lambda>>, 'NONCLUSTERED': <function Parser.<lambda>>, 'DEFAULT': <function Parser.<lambda>>, 'ENCODE': <function Parser.<lambda>>, 'EPHEMERAL': <function Parser.<lambda>>, 'EXCLUDE': <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>>, 'PERIOD': <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>>, 'WATERMARK': <function Parser.<lambda>>, 'WITH': <function Parser.<lambda>>, 'FULLTEXT': <function MySQL.Parser.<lambda>>, 'INDEX': <function MySQL.Parser.<lambda>>, 'KEY': <function MySQL.Parser.<lambda>>, 'SPATIAL': <function MySQL.Parser.<lambda>>}
ALTER_PARSERS =
{'ADD': <function Parser.<lambda>>, 'AS': <function Parser.<lambda>>, 'ALTER': <function Parser.<lambda>>, 'CLUSTER BY': <function Parser.<lambda>>, 'DELETE': <function Parser.<lambda>>, 'DROP': <function Parser.<lambda>>, 'RENAME': <function Parser.<lambda>>, 'SET': <function Parser.<lambda>>, 'SWAP': <function Parser.<lambda>>, 'MODIFY': <function MySQL.Parser.<lambda>>}
SCHEMA_UNNAMED_CONSTRAINTS =
{'WATERMARK', 'LIKE', 'CHECK', 'INDEX', 'KEY', 'SPATIAL', 'UNIQUE', 'PERIOD', 'FOREIGN KEY', 'FULLTEXT', 'EXCLUDE', 'PRIMARY KEY'}
PROFILE_TYPES: Dict[str, Sequence[Union[Sequence[str], str]]] =
{'ALL': (), 'CPU': (), 'IPC': (), 'MEMORY': (), 'SOURCE': (), 'SWAPS': (), 'BLOCK': ('IO',), 'CONTEXT': ('SWITCHES',), 'PAGE': ('FAULTS',)}
TYPE_TOKENS =
{<TokenType.NAME: 'NAME'>, <TokenType.TIMESTAMPTZ: 'TIMESTAMPTZ'>, <TokenType.UDECIMAL: 'UDECIMAL'>, <TokenType.LIST: 'LIST'>, <TokenType.TIME: 'TIME'>, <TokenType.INET: 'INET'>, <TokenType.MEDIUMTEXT: 'MEDIUMTEXT'>, <TokenType.POLYGON: 'POLYGON'>, <TokenType.UBIGINT: 'UBIGINT'>, <TokenType.NVARCHAR: 'NVARCHAR'>, <TokenType.DATE: 'DATE'>, <TokenType.NULL: 'NULL'>, <TokenType.BINARY: 'BINARY'>, <TokenType.TSRANGE: 'TSRANGE'>, <TokenType.ENUM: 'ENUM'>, <TokenType.IPV6: 'IPV6'>, <TokenType.OBJECT_IDENTIFIER: 'OBJECT_IDENTIFIER'>, <TokenType.DATERANGE: 'DATERANGE'>, <TokenType.YEAR: 'YEAR'>, <TokenType.INTERVAL: 'INTERVAL'>, <TokenType.TIMESTAMPLTZ: 'TIMESTAMPLTZ'>, <TokenType.MAP: 'MAP'>, <TokenType.TSTZRANGE: 'TSTZRANGE'>, <TokenType.UINT128: 'UINT128'>, <TokenType.TIMESTAMPNTZ: 'TIMESTAMPNTZ'>, <TokenType.TSTZMULTIRANGE: 'TSTZMULTIRANGE'>, <TokenType.MULTILINESTRING: 'MULTILINESTRING'>, <TokenType.BIT: 'BIT'>, <TokenType.DATETIME64: 'DATETIME64'>, <TokenType.VECTOR: 'VECTOR'>, <TokenType.FLOAT: 'FLOAT'>, <TokenType.DOUBLE: 'DOUBLE'>, <TokenType.BPCHAR: 'BPCHAR'>, <TokenType.ENUM8: 'ENUM8'>, <TokenType.HSTORE: 'HSTORE'>, <TokenType.DATE32: 'DATE32'>, <TokenType.UINT: 'UINT'>, <TokenType.BIGINT: 'BIGINT'>, <TokenType.TIMESTAMP_NS: 'TIMESTAMP_NS'>, <TokenType.AGGREGATEFUNCTION: 'AGGREGATEFUNCTION'>, <TokenType.TIMESTAMP_MS: 'TIMESTAMP_MS'>, <TokenType.BOOLEAN: 'BOOLEAN'>, <TokenType.ENUM16: 'ENUM16'>, <TokenType.NUMRANGE: 'NUMRANGE'>, <TokenType.NESTED: 'NESTED'>, <TokenType.NUMMULTIRANGE: 'NUMMULTIRANGE'>, <TokenType.VARBINARY: 'VARBINARY'>, <TokenType.GEOGRAPHY: 'GEOGRAPHY'>, <TokenType.PSEUDO_TYPE: 'PSEUDO_TYPE'>, <TokenType.UNION: 'UNION'>, <TokenType.OBJECT: 'OBJECT'>, <TokenType.NCHAR: 'NCHAR'>, <TokenType.TDIGEST: 'TDIGEST'>, <TokenType.BIGDECIMAL: 'BIGDECIMAL'>, <TokenType.LOWCARDINALITY: 'LOWCARDINALITY'>, <TokenType.SMALLINT: 'SMALLINT'>, <TokenType.UNIQUEIDENTIFIER: 'UNIQUEIDENTIFIER'>, <TokenType.TSMULTIRANGE: 'TSMULTIRANGE'>, <TokenType.DATEMULTIRANGE: 'DATEMULTIRANGE'>, <TokenType.SMALLMONEY: 'SMALLMONEY'>, <TokenType.DECIMAL256: 'DECIMAL256'>, <TokenType.TINYINT: 'TINYINT'>, <TokenType.LONGTEXT: 'LONGTEXT'>, <TokenType.DECIMAL: 'DECIMAL'>, <TokenType.INT: 'INT'>, <TokenType.SET: 'SET'>, <TokenType.LONGBLOB: 'LONGBLOB'>, <TokenType.INT4RANGE: 'INT4RANGE'>, <TokenType.IPPREFIX: 'IPPREFIX'>, <TokenType.USMALLINT: 'USMALLINT'>, <TokenType.MEDIUMBLOB: 'MEDIUMBLOB'>, <TokenType.UNKNOWN: 'UNKNOWN'>, <TokenType.VARCHAR: 'VARCHAR'>, <TokenType.POINT: 'POINT'>, <TokenType.GEOMETRY: 'GEOMETRY'>, <TokenType.FIXEDSTRING: 'FIXEDSTRING'>, <TokenType.IPV4: 'IPV4'>, <TokenType.VARIANT: 'VARIANT'>, <TokenType.UINT256: 'UINT256'>, <TokenType.JSON: 'JSON'>, <TokenType.UUID: 'UUID'>, <TokenType.ROWVERSION: 'ROWVERSION'>, <TokenType.ARRAY: 'ARRAY'>, <TokenType.STRUCT: 'STRUCT'>, <TokenType.DECIMAL128: 'DECIMAL128'>, <TokenType.SIMPLEAGGREGATEFUNCTION: 'SIMPLEAGGREGATEFUNCTION'>, <TokenType.HLLSKETCH: 'HLLSKETCH'>, <TokenType.SUPER: 'SUPER'>, <TokenType.RANGE: 'RANGE'>, <TokenType.INT8MULTIRANGE: 'INT8MULTIRANGE'>, <TokenType.UTINYINT: 'UTINYINT'>, <TokenType.SMALLSERIAL: 'SMALLSERIAL'>, <TokenType.CHAR: 'CHAR'>, <TokenType.XML: 'XML'>, <TokenType.INT256: 'INT256'>, <TokenType.DECIMAL64: 'DECIMAL64'>, <TokenType.IPADDRESS: 'IPADDRESS'>, <TokenType.IMAGE: 'IMAGE'>, <TokenType.NULLABLE: 'NULLABLE'>, <TokenType.INT128: 'INT128'>, <TokenType.TIMETZ: 'TIMETZ'>, <TokenType.TEXT: 'TEXT'>, <TokenType.MEDIUMINT: 'MEDIUMINT'>, <TokenType.TINYTEXT: 'TINYTEXT'>, <TokenType.USERDEFINED: 'USERDEFINED'>, <TokenType.MONEY: 'MONEY'>, <TokenType.INT4MULTIRANGE: 'INT4MULTIRANGE'>, <TokenType.TIMESTAMP: 'TIMESTAMP'>, <TokenType.UMEDIUMINT: 'UMEDIUMINT'>, <TokenType.TINYBLOB: 'TINYBLOB'>, <TokenType.BIGSERIAL: 'BIGSERIAL'>, <TokenType.JSONB: 'JSONB'>, <TokenType.SERIAL: 'SERIAL'>, <TokenType.LINESTRING: 'LINESTRING'>, <TokenType.DECIMAL32: 'DECIMAL32'>, <TokenType.INT8RANGE: 'INT8RANGE'>, <TokenType.TIMESTAMP_S: 'TIMESTAMP_S'>, <TokenType.DATETIME: 'DATETIME'>, <TokenType.MULTIPOLYGON: 'MULTIPOLYGON'>, <TokenType.RING: 'RING'>}
ENUM_TYPE_TOKENS =
{<TokenType.ENUM: 'ENUM'>, <TokenType.ENUM16: 'ENUM16'>, <TokenType.SET: 'SET'>, <TokenType.ENUM8: 'ENUM8'>}
OPERATION_MODIFIERS =
{'SQL_BUFFER_RESULT', 'STRAIGHT_JOIN', 'SQL_BIG_RESULT', 'SQL_CALC_FOUND_ROWS', 'SQL_NO_CACHE', 'SQL_SMALL_RESULT', 'HIGH_PRIORITY'}
SHOW_TRIE: Dict =
{'BINARY': {'LOGS': {0: True}}, 'MASTER': {'LOGS': {0: True}, 'STATUS': {0: True}}, 'BINLOG': {'EVENTS': {0: True}}, 'CHARACTER': {'SET': {0: True}}, 'CHARSET': {0: True}, 'COLLATION': {0: True}, 'FULL': {'COLUMNS': {0: True}, 'PROCESSLIST': {0: True}, 'TABLES': {0: True}}, 'COLUMNS': {0: True}, 'CREATE': {'DATABASE': {0: True}, 'EVENT': {0: True}, 'FUNCTION': {0: True}, 'PROCEDURE': {0: True}, 'TABLE': {0: True}, 'TRIGGER': {0: True}, 'VIEW': {0: True}}, 'DATABASES': {0: True}, 'SCHEMAS': {0: True}, 'ENGINE': {0: True}, 'STORAGE': {'ENGINES': {0: True}}, 'ENGINES': {0: True}, 'ERRORS': {0: True}, 'EVENTS': {0: True}, 'FUNCTION': {'CODE': {0: True}, 'STATUS': {0: True}}, 'GRANTS': {0: True}, 'INDEX': {0: True}, 'OPEN': {'TABLES': {0: True}}, 'PLUGINS': {0: True}, 'PROCEDURE': {'CODE': {0: True}, 'STATUS': {0: True}}, 'PRIVILEGES': {0: True}, 'PROCESSLIST': {0: True}, 'PROFILE': {0: True}, 'PROFILES': {0: True}, 'RELAYLOG': {'EVENTS': {0: True}}, 'REPLICAS': {0: True}, 'SLAVE': {'HOSTS': {0: True}, 'STATUS': {0: True}}, 'REPLICA': {'STATUS': {0: True}}, 'GLOBAL': {'STATUS': {0: True}, 'VARIABLES': {0: True}}, 'SESSION': {'STATUS': {0: True}, 'VARIABLES': {0: True}}, 'STATUS': {0: True}, 'TABLE': {'STATUS': {0: True}}, 'TABLES': {0: True}, 'TRIGGERS': {0: True}, 'VARIABLES': {0: True}, 'WARNINGS': {0: True}}
SET_TRIE: Dict =
{'GLOBAL': {0: True}, 'LOCAL': {0: True}, 'SESSION': {0: True}, 'TRANSACTION': {0: True}, 'PERSIST': {0: True}, 'PERSIST_ONLY': {0: True}, 'CHARACTER': {'SET': {0: True}}, 'CHARSET': {0: True}, 'NAMES': {0: True}}
Inherited Members
- sqlglot.parser.Parser
- Parser
- NO_PAREN_FUNCTIONS
- STRUCT_TYPE_TOKENS
- NESTED_TYPE_TOKENS
- AGGREGATE_TYPE_TOKENS
- SIGNED_TO_UNSIGNED_TYPE_TOKEN
- SUBQUERY_PREDICATES
- RESERVED_TOKENS
- DB_CREATABLES
- CREATABLES
- ALTERABLES
- ID_VAR_TOKENS
- INTERVAL_VARS
- ALIAS_TOKENS
- ARRAY_CONSTRUCTORS
- COMMENT_TABLE_ALIAS_TOKENS
- UPDATE_ALIAS_TOKENS
- TRIM_TYPES
- ASSIGNMENT
- EQUALITY
- COMPARISON
- BITWISE
- TERM
- FACTOR
- EXPONENT
- TIMES
- TIMESTAMPS
- SET_OPERATIONS
- JOIN_METHODS
- JOIN_SIDES
- JOIN_KINDS
- JOIN_HINTS
- LAMBDAS
- COLUMN_OPERATORS
- EXPRESSION_PARSERS
- UNARY_PARSERS
- STRING_PARSERS
- NUMERIC_PARSERS
- PRIMARY_PARSERS
- PLACEHOLDER_PARSERS
- ALTER_ALTER_PARSERS
- NO_PAREN_FUNCTION_PARSERS
- INVALID_FUNC_NAME_TOKENS
- FUNCTIONS_WITH_ALIASED_ARGS
- KEY_VALUE_DEFINITIONS
- QUERY_MODIFIER_PARSERS
- TYPE_LITERAL_PARSERS
- TYPE_CONVERTERS
- DDL_SELECT_TOKENS
- PRE_VOLATILE_TOKENS
- TRANSACTION_KIND
- TRANSACTION_CHARACTERISTICS
- CONFLICT_ACTIONS
- CREATE_SEQUENCE
- ISOLATED_LOADING_OPTIONS
- USABLES
- CAST_ACTIONS
- SCHEMA_BINDING_OPTIONS
- PROCEDURE_OPTIONS
- EXECUTE_AS_OPTIONS
- KEY_CONSTRAINT_OPTIONS
- INSERT_ALTERNATIVES
- CLONE_KEYWORDS
- HISTORICAL_DATA_PREFIX
- HISTORICAL_DATA_KIND
- OPCLASS_FOLLOW_KEYWORDS
- OPTYPE_FOLLOW_TOKENS
- TABLE_INDEX_HINT_TOKENS
- VIEW_ATTRIBUTES
- WINDOW_ALIAS_TOKENS
- WINDOW_BEFORE_PAREN_TOKENS
- WINDOW_SIDES
- JSON_KEY_VALUE_SEPARATOR_TOKENS
- FETCH_TOKENS
- ADD_CONSTRAINT_TOKENS
- DISTINCT_TOKENS
- NULL_TOKENS
- UNNEST_OFFSET_ALIAS_TOKENS
- SELECT_START_TOKENS
- COPY_INTO_VARLEN_OPTIONS
- IS_JSON_PREDICATE_KIND
- ODBC_DATETIME_LITERALS
- ON_CONDITION_TOKENS
- PRIVILEGE_FOLLOW_TOKENS
- DESCRIBE_STYLES
- STRICT_CAST
- PREFIXED_PIVOT_COLUMNS
- IDENTIFY_PIVOT_STRINGS
- ALTER_TABLE_ADD_REQUIRED_FOR_EACH_COLUMN
- TABLESAMPLE_CSV
- DEFAULT_SAMPLING_METHOD
- SET_REQUIRES_ASSIGNMENT_DELIMITER
- TRIM_PATTERN_FIRST
- MODIFIERS_ATTACHED_TO_SET_OP
- SET_OP_MODIFIERS
- NO_PAREN_IF_COMMANDS
- JSON_ARROWS_REQUIRE_JSON_TYPE
- COLON_IS_VARIANT_EXTRACT
- SUPPORTS_IMPLICIT_UNNEST
- INTERVAL_SPANS
- WRAPPED_TRANSFORM_COLUMN_CONSTRAINT
- error_level
- error_message_context
- max_errors
- dialect
- reset
- parse
- parse_into
- check_errors
- raise_error
- expression
- validate_expression
- errors
- sql
693 class Generator(generator.Generator): 694 INTERVAL_ALLOWS_PLURAL_FORM = False 695 LOCKING_READS_SUPPORTED = True 696 NULL_ORDERING_SUPPORTED = None 697 JOIN_HINTS = False 698 TABLE_HINTS = True 699 DUPLICATE_KEY_UPDATE_WITH_SET = False 700 QUERY_HINT_SEP = " " 701 VALUES_AS_TABLE = False 702 NVL2_SUPPORTED = False 703 LAST_DAY_SUPPORTS_DATE_PART = False 704 JSON_TYPE_REQUIRED_FOR_EXTRACTION = True 705 JSON_PATH_BRACKETED_KEY_SUPPORTED = False 706 JSON_KEY_VALUE_PAIR_SEP = "," 707 SUPPORTS_TO_NUMBER = False 708 PARSE_JSON_NAME: t.Optional[str] = None 709 PAD_FILL_PATTERN_IS_REQUIRED = True 710 WRAP_DERIVED_VALUES = False 711 VARCHAR_REQUIRES_SIZE = True 712 SUPPORTS_MEDIAN = False 713 714 TRANSFORMS = { 715 **generator.Generator.TRANSFORMS, 716 exp.ArrayAgg: rename_func("GROUP_CONCAT"), 717 exp.CurrentDate: no_paren_current_date_sql, 718 exp.DateDiff: _remove_ts_or_ds_to_date( 719 lambda self, e: self.func("DATEDIFF", e.this, e.expression), ("this", "expression") 720 ), 721 exp.DateAdd: _remove_ts_or_ds_to_date(date_add_sql("ADD")), 722 exp.DateStrToDate: datestrtodate_sql, 723 exp.DateSub: _remove_ts_or_ds_to_date(date_add_sql("SUB")), 724 exp.DateTrunc: _date_trunc_sql, 725 exp.Day: _remove_ts_or_ds_to_date(), 726 exp.DayOfMonth: _remove_ts_or_ds_to_date(rename_func("DAYOFMONTH")), 727 exp.DayOfWeek: _remove_ts_or_ds_to_date(rename_func("DAYOFWEEK")), 728 exp.DayOfYear: _remove_ts_or_ds_to_date(rename_func("DAYOFYEAR")), 729 exp.GroupConcat: lambda self, 730 e: f"""GROUP_CONCAT({self.sql(e, "this")} SEPARATOR {self.sql(e, "separator") or "','"})""", 731 exp.ILike: no_ilike_sql, 732 exp.JSONExtractScalar: arrow_json_extract_sql, 733 exp.Length: rename_func("CHAR_LENGTH"), 734 exp.Max: max_or_greatest, 735 exp.Min: min_or_least, 736 exp.Month: _remove_ts_or_ds_to_date(), 737 exp.NullSafeEQ: lambda self, e: self.binary(e, "<=>"), 738 exp.NullSafeNEQ: lambda self, e: f"NOT {self.binary(e, '<=>')}", 739 exp.Pivot: no_pivot_sql, 740 exp.Select: transforms.preprocess( 741 [ 742 transforms.eliminate_distinct_on, 743 transforms.eliminate_semi_and_anti_joins, 744 transforms.eliminate_qualify, 745 transforms.eliminate_full_outer_join, 746 transforms.unnest_generate_date_array_using_recursive_cte, 747 ] 748 ), 749 exp.StrPosition: strposition_to_locate_sql, 750 exp.StrToDate: _str_to_date_sql, 751 exp.StrToTime: _str_to_date_sql, 752 exp.Stuff: rename_func("INSERT"), 753 exp.TableSample: no_tablesample_sql, 754 exp.TimeFromParts: rename_func("MAKETIME"), 755 exp.TimestampAdd: date_add_interval_sql("DATE", "ADD"), 756 exp.TimestampDiff: lambda self, e: self.func( 757 "TIMESTAMPDIFF", unit_to_var(e), e.expression, e.this 758 ), 759 exp.TimestampSub: date_add_interval_sql("DATE", "SUB"), 760 exp.TimeStrToUnix: rename_func("UNIX_TIMESTAMP"), 761 exp.TimeStrToTime: lambda self, e: timestrtotime_sql( 762 self, 763 e, 764 include_precision=not e.args.get("zone"), 765 ), 766 exp.TimeToStr: _remove_ts_or_ds_to_date( 767 lambda self, e: self.func("DATE_FORMAT", e.this, self.format_time(e)) 768 ), 769 exp.Trim: trim_sql, 770 exp.TryCast: no_trycast_sql, 771 exp.TsOrDsAdd: date_add_sql("ADD"), 772 exp.TsOrDsDiff: lambda self, e: self.func("DATEDIFF", e.this, e.expression), 773 exp.TsOrDsToDate: _ts_or_ds_to_date_sql, 774 exp.UnixToTime: _unix_to_time_sql, 775 exp.Week: _remove_ts_or_ds_to_date(), 776 exp.WeekOfYear: _remove_ts_or_ds_to_date(rename_func("WEEKOFYEAR")), 777 exp.Year: _remove_ts_or_ds_to_date(), 778 } 779 780 UNSIGNED_TYPE_MAPPING = { 781 exp.DataType.Type.UBIGINT: "BIGINT", 782 exp.DataType.Type.UINT: "INT", 783 exp.DataType.Type.UMEDIUMINT: "MEDIUMINT", 784 exp.DataType.Type.USMALLINT: "SMALLINT", 785 exp.DataType.Type.UTINYINT: "TINYINT", 786 exp.DataType.Type.UDECIMAL: "DECIMAL", 787 } 788 789 TIMESTAMP_TYPE_MAPPING = { 790 exp.DataType.Type.TIMESTAMP: "DATETIME", 791 exp.DataType.Type.TIMESTAMPTZ: "TIMESTAMP", 792 exp.DataType.Type.TIMESTAMPLTZ: "TIMESTAMP", 793 } 794 795 TYPE_MAPPING = { 796 **generator.Generator.TYPE_MAPPING, 797 **UNSIGNED_TYPE_MAPPING, 798 **TIMESTAMP_TYPE_MAPPING, 799 } 800 801 TYPE_MAPPING.pop(exp.DataType.Type.MEDIUMTEXT) 802 TYPE_MAPPING.pop(exp.DataType.Type.LONGTEXT) 803 TYPE_MAPPING.pop(exp.DataType.Type.TINYTEXT) 804 TYPE_MAPPING.pop(exp.DataType.Type.MEDIUMBLOB) 805 TYPE_MAPPING.pop(exp.DataType.Type.LONGBLOB) 806 TYPE_MAPPING.pop(exp.DataType.Type.TINYBLOB) 807 808 PROPERTIES_LOCATION = { 809 **generator.Generator.PROPERTIES_LOCATION, 810 exp.TransientProperty: exp.Properties.Location.UNSUPPORTED, 811 exp.VolatileProperty: exp.Properties.Location.UNSUPPORTED, 812 } 813 814 LIMIT_FETCH = "LIMIT" 815 816 LIMIT_ONLY_LITERALS = True 817 818 CHAR_CAST_MAPPING = dict.fromkeys( 819 ( 820 exp.DataType.Type.LONGTEXT, 821 exp.DataType.Type.LONGBLOB, 822 exp.DataType.Type.MEDIUMBLOB, 823 exp.DataType.Type.MEDIUMTEXT, 824 exp.DataType.Type.TEXT, 825 exp.DataType.Type.TINYBLOB, 826 exp.DataType.Type.TINYTEXT, 827 exp.DataType.Type.VARCHAR, 828 ), 829 "CHAR", 830 ) 831 SIGNED_CAST_MAPPING = dict.fromkeys( 832 ( 833 exp.DataType.Type.BIGINT, 834 exp.DataType.Type.BOOLEAN, 835 exp.DataType.Type.INT, 836 exp.DataType.Type.SMALLINT, 837 exp.DataType.Type.TINYINT, 838 exp.DataType.Type.MEDIUMINT, 839 ), 840 "SIGNED", 841 ) 842 843 # MySQL doesn't support many datatypes in cast. 844 # https://dev.mysql.com/doc/refman/8.0/en/cast-functions.html#function_cast 845 CAST_MAPPING = { 846 **CHAR_CAST_MAPPING, 847 **SIGNED_CAST_MAPPING, 848 exp.DataType.Type.UBIGINT: "UNSIGNED", 849 } 850 851 TIMESTAMP_FUNC_TYPES = { 852 exp.DataType.Type.TIMESTAMPTZ, 853 exp.DataType.Type.TIMESTAMPLTZ, 854 } 855 856 # https://dev.mysql.com/doc/refman/8.0/en/keywords.html 857 RESERVED_KEYWORDS = { 858 "accessible", 859 "add", 860 "all", 861 "alter", 862 "analyze", 863 "and", 864 "as", 865 "asc", 866 "asensitive", 867 "before", 868 "between", 869 "bigint", 870 "binary", 871 "blob", 872 "both", 873 "by", 874 "call", 875 "cascade", 876 "case", 877 "change", 878 "char", 879 "character", 880 "check", 881 "collate", 882 "column", 883 "condition", 884 "constraint", 885 "continue", 886 "convert", 887 "create", 888 "cross", 889 "cube", 890 "cume_dist", 891 "current_date", 892 "current_time", 893 "current_timestamp", 894 "current_user", 895 "cursor", 896 "database", 897 "databases", 898 "day_hour", 899 "day_microsecond", 900 "day_minute", 901 "day_second", 902 "dec", 903 "decimal", 904 "declare", 905 "default", 906 "delayed", 907 "delete", 908 "dense_rank", 909 "desc", 910 "describe", 911 "deterministic", 912 "distinct", 913 "distinctrow", 914 "div", 915 "double", 916 "drop", 917 "dual", 918 "each", 919 "else", 920 "elseif", 921 "empty", 922 "enclosed", 923 "escaped", 924 "except", 925 "exists", 926 "exit", 927 "explain", 928 "false", 929 "fetch", 930 "first_value", 931 "float", 932 "float4", 933 "float8", 934 "for", 935 "force", 936 "foreign", 937 "from", 938 "fulltext", 939 "function", 940 "generated", 941 "get", 942 "grant", 943 "group", 944 "grouping", 945 "groups", 946 "having",