Edit on GitHub

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
class MySQL(sqlglot.dialects.dialect.Dialect):
 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.

IDENTIFIERS_CAN_START_WITH_DIGIT = True

Whether an unquoted identifier can start with a digit.

NORMALIZATION_STRATEGY = <NormalizationStrategy.CASE_SENSITIVE: 'CASE_SENSITIVE'>

Specifies the strategy according to which identifiers should be normalized.

TIME_FORMAT = "'%Y-%m-%d %T'"
DPIPE_IS_STRING_CONCAT = False

Whether the DPIPE token (||) is a string concatenation operator.

SUPPORTS_USER_DEFINED_TYPES = False

Whether user-defined data types are supported.

SUPPORTS_SEMI_ANTI_JOIN = False

Whether SEMI or ANTI joins are supported.

SAFE_DIVISION = True

Whether division by zero throws an error (False) or returns NULL (True).

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.

SUPPORTS_COLUMN_JOIN_MARKS = False

Whether the old-style outer join (+) syntax is supported.

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'>
jsonpath_tokenizer_class = <class 'sqlglot.tokens.JSONPathTokenizer'>
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}}}
INVERSE_FORMAT_MAPPING: Dict[str, str] = {}
INVERSE_FORMAT_TRIE: Dict = {}
INVERSE_CREATABLE_KIND_MAPPING: dict[str, str] = {}
ESCAPED_SEQUENCES: Dict[str, str] = {'\x07': '\\a', '\x08': '\\b', '\x0c': '\\f', '\n': '\\n', '\r': '\\r', '\t': '\\t', '\x0b': '\\v', '\\': '\\\\'}
QUOTE_START = "'"
QUOTE_END = "'"
IDENTIFIER_START = '`'
IDENTIFIER_END = '`'
BIT_START: Optional[str] = "b'"
BIT_END: Optional[str] = "'"
HEX_START: Optional[str] = "x'"
HEX_END: Optional[str] = "'"
BYTE_START: Optional[str] = None
BYTE_END: Optional[str] = None
UNICODE_START: Optional[str] = None
UNICODE_END: Optional[str] = None
class MySQL.Tokenizer(sqlglot.tokens.Tokenizer):
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}
QUOTES = ["'", '"']
COMMENTS = ['--', '#', ('/*', '*/')]
IDENTIFIERS = ['`']
STRING_ESCAPES = ["'", '"', '\\']
BIT_STRINGS = [("b'", "'"), ("B'", "'"), ('0b', '')]
HEX_STRINGS = [("x'", "'"), ("X'", "'"), ('0x', '')]
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'>}
class MySQL.Parser(sqlglot.parser.Parser):
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'}
LOG_DEFAULTS_TO_LN = True
STRING_ALIASES = True
VALUES_FOLLOWED_BY_PAREN = False
SUPPORTS_PARTITION_SELECTION = True
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
class MySQL.Generator(sqlglot.generator.Generator):
 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",