sqlglot.generators.mysql
1from __future__ import annotations 2 3import typing as t 4 5from sqlglot import exp, generator, transforms 6from sqlglot.dialects.dialect import ( 7 arrow_json_extract_sql, 8 build_date_delta, 9 build_date_delta_with_interval, 10 date_add_interval_sql, 11 datestrtodate_sql, 12 length_or_char_length_sql, 13 max_or_greatest, 14 min_or_least, 15 no_ilike_sql, 16 no_paren_current_date_sql, 17 no_pivot_sql, 18 no_tablesample_sql, 19 no_trycast_sql, 20 remove_ts_or_ds_to_date, 21 rename_func, 22 strposition_sql, 23 unit_to_var, 24 trim_sql, 25 timestrtotime_sql, 26) 27from sqlglot.generator import unsupported_args 28from collections import defaultdict 29 30 31def _date_trunc_sql(self: MySQLGenerator, expression: exp.DateTrunc) -> str: 32 expr = self.sql(expression, "this") 33 unit_expr = expression.args.get("unit") 34 unit = ( 35 self.weekstart_name(unit_expr) 36 if isinstance(unit_expr, exp.WeekStart) 37 else expression.text("unit").upper() 38 ) 39 40 if unit == "WEEK": 41 concat = f"CONCAT(YEAR({expr}), ' ', WEEK({expr}, 1), ' 1')" 42 date_format = "%Y %u %w" 43 elif unit == "MONTH": 44 concat = f"CONCAT(YEAR({expr}), ' ', MONTH({expr}), ' 1')" 45 date_format = "%Y %c %e" 46 elif unit == "QUARTER": 47 concat = f"CONCAT(YEAR({expr}), ' ', QUARTER({expr}) * 3 - 2, ' 1')" 48 date_format = "%Y %c %e" 49 elif unit == "YEAR": 50 concat = f"CONCAT(YEAR({expr}), ' 1 1')" 51 date_format = "%Y %c %e" 52 else: 53 if unit != "DAY": 54 self.unsupported(f"Unexpected interval unit: {unit}") 55 return self.func("DATE", expr) 56 57 return self.func("STR_TO_DATE", concat, f"'{date_format}'") 58 59 60def _str_to_date_sql( 61 self: MySQLGenerator, expression: exp.StrToDate | exp.StrToTime | exp.TsOrDsToDate 62) -> str: 63 return self.func("STR_TO_DATE", expression.this, self.format_time(expression)) 64 65 66def _unix_to_time_sql(self: MySQLGenerator, expression: exp.UnixToTime) -> str: 67 scale = expression.args.get("scale") 68 timestamp = expression.this 69 70 if scale in (None, exp.UnixToTime.SECONDS): 71 return self.func("FROM_UNIXTIME", timestamp, self.format_time(expression)) 72 73 return self.func( 74 "FROM_UNIXTIME", 75 exp.Div(this=timestamp, expression=exp.func("POW", 10, scale)), 76 self.format_time(expression), 77 ) 78 79 80def date_add_sql( 81 kind: str, 82) -> t.Callable[[generator.Generator, exp.Expr], str]: 83 def func(self: generator.Generator, expression: exp.Expr) -> str: 84 return self.func( 85 f"DATE_{kind}", 86 expression.this, 87 exp.Interval(this=expression.expression, unit=unit_to_var(expression)), 88 ) 89 90 return func 91 92 93_MAKE_INTERVAL_UNIT_ALIASES = { 94 "years": "year", 95 "months": "month", 96 "weeks": "week", 97 "days": "day", 98 "hours": "hour", 99 "minutes": "minute", 100 "mins": "minute", 101 "seconds": "second", 102 "secs": "second", 103} 104 105 106def _ts_or_ds_to_date_sql(self: MySQLGenerator, expression: exp.TsOrDsToDate) -> str: 107 time_format = expression.args.get("format") 108 return _str_to_date_sql(self, expression) if time_format else self.func("DATE", expression.this) 109 110 111class MySQLGenerator(generator.Generator): 112 SELECT_KINDS: tuple[str, ...] = () 113 TRY_SUPPORTED = False 114 SUPPORTS_UESCAPE = False 115 SUPPORTS_DECODE_CASE = False 116 SUPPORTS_MODIFY_COLUMN = True 117 SUPPORTS_CHANGE_COLUMN = True 118 119 AFTER_HAVING_MODIFIER_TRANSFORMS = generator.AFTER_HAVING_MODIFIER_TRANSFORMS 120 121 INTERVAL_ALLOWS_PLURAL_FORM = False 122 LOCKING_READS_SUPPORTED = True 123 NULL_ORDERING_SUPPORTED: bool | None = None 124 JOIN_HINTS = False 125 TABLE_HINTS = True 126 DUPLICATE_KEY_UPDATE_WITH_SET = False 127 QUERY_HINT_SEP = " " 128 VALUES_AS_TABLE = False 129 NVL2_SUPPORTED = False 130 LAST_DAY_SUPPORTS_DATE_PART = False 131 JSON_TYPE_REQUIRED_FOR_EXTRACTION = True 132 JSON_PATH_BRACKETED_KEY_SUPPORTED = False 133 JSON_KEY_VALUE_PAIR_SEP = "," 134 SUPPORTS_TO_NUMBER = False 135 PARSE_JSON_NAME: str | None = None 136 PAD_FILL_PATTERN_IS_REQUIRED = True 137 WRAP_DERIVED_VALUES = False 138 VARCHAR_REQUIRES_SIZE = True 139 SUPPORTS_MEDIAN = False 140 UPDATE_STATEMENT_SUPPORTS_FROM = False 141 142 TRANSFORMS = { 143 **generator.Generator.TRANSFORMS, 144 exp.ArrayAgg: rename_func("GROUP_CONCAT"), 145 exp.BitwiseAndAgg: rename_func("BIT_AND"), 146 exp.BitwiseOrAgg: rename_func("BIT_OR"), 147 exp.BitwiseXorAgg: rename_func("BIT_XOR"), 148 exp.BitwiseCount: rename_func("BIT_COUNT"), 149 exp.Chr: lambda self, e: self.chr_sql(e, "CHAR"), 150 exp.CurrentDate: no_paren_current_date_sql, 151 exp.CurrentVersion: rename_func("VERSION"), 152 exp.DateDiff: remove_ts_or_ds_to_date( 153 lambda self, e: self.func("DATEDIFF", e.this, e.expression), ("this", "expression") 154 ), 155 exp.DateAdd: remove_ts_or_ds_to_date(date_add_sql("ADD")), 156 exp.DateStrToDate: datestrtodate_sql, 157 exp.DateSub: remove_ts_or_ds_to_date(date_add_sql("SUB")), 158 exp.DateTrunc: _date_trunc_sql, 159 exp.Day: remove_ts_or_ds_to_date(), 160 exp.DayOfMonth: remove_ts_or_ds_to_date(rename_func("DAYOFMONTH")), 161 exp.DayOfWeek: remove_ts_or_ds_to_date(rename_func("DAYOFWEEK")), 162 exp.DayOfYear: remove_ts_or_ds_to_date(rename_func("DAYOFYEAR")), 163 exp.GroupConcat: lambda self, e: ( 164 f"""GROUP_CONCAT({self.sql(e, "this")} SEPARATOR {self.sql(e, "separator") or "','"})""" 165 ), 166 exp.ILike: no_ilike_sql, 167 exp.JSONExtractScalar: arrow_json_extract_sql, 168 exp.Length: length_or_char_length_sql, 169 exp.LogicalOr: rename_func("MAX"), 170 exp.LogicalAnd: rename_func("MIN"), 171 exp.Max: max_or_greatest, 172 exp.Min: min_or_least, 173 exp.Month: remove_ts_or_ds_to_date(), 174 exp.NullSafeEQ: lambda self, e: self.binary(e, "<=>"), 175 exp.NullSafeNEQ: lambda self, e: f"NOT {self.binary(e, '<=>')}", 176 exp.NumberToStr: rename_func("FORMAT"), 177 exp.Pivot: no_pivot_sql, 178 exp.Select: transforms.preprocess( 179 [ 180 transforms.eliminate_distinct_on, 181 transforms.eliminate_semi_and_anti_joins, 182 transforms.eliminate_qualify, 183 transforms.eliminate_full_outer_join, 184 transforms.unnest_generate_date_array_using_recursive_cte, 185 ] 186 ), 187 exp.StrPosition: lambda self, e: strposition_sql( 188 self, e, func_name="LOCATE", supports_position=True 189 ), 190 exp.StrToDate: _str_to_date_sql, 191 exp.StrToTime: _str_to_date_sql, 192 exp.Stuff: rename_func("INSERT"), 193 exp.SessionUser: lambda *_: "SESSION_USER()", 194 exp.TableSample: no_tablesample_sql, 195 exp.TimeFromParts: rename_func("MAKETIME"), 196 exp.TimestampAdd: date_add_interval_sql("DATE", "ADD"), 197 exp.TimestampDiff: lambda self, e: self.func( 198 "TIMESTAMPDIFF", unit_to_var(e), e.expression, e.this 199 ), 200 exp.TimestampSub: date_add_interval_sql("DATE", "SUB"), 201 exp.TimeStrToUnix: rename_func("UNIX_TIMESTAMP"), 202 exp.TimeStrToTime: lambda self, e: timestrtotime_sql( 203 self, 204 e, 205 include_precision=not e.args.get("zone"), 206 ), 207 exp.TimeToStr: remove_ts_or_ds_to_date( 208 lambda self, e: self.func("DATE_FORMAT", e.this, self.format_time(e)) 209 ), 210 exp.Trim: trim_sql, 211 exp.Trunc: rename_func("TRUNCATE"), 212 exp.TryCast: no_trycast_sql, 213 exp.TsOrDsAdd: date_add_sql("ADD"), 214 exp.TsOrDsDiff: lambda self, e: self.func("DATEDIFF", e.this, e.expression), 215 exp.TsOrDsToDate: _ts_or_ds_to_date_sql, 216 exp.Unicode: lambda self, e: f"ORD(CONVERT({self.sql(e.this)} USING utf32))", 217 exp.UnixToTime: _unix_to_time_sql, 218 exp.Week: remove_ts_or_ds_to_date(), 219 exp.WeekOfYear: remove_ts_or_ds_to_date(rename_func("WEEKOFYEAR")), 220 exp.Year: remove_ts_or_ds_to_date(), 221 exp.UtcTimestamp: rename_func("UTC_TIMESTAMP"), 222 exp.UtcTime: rename_func("UTC_TIME"), 223 } 224 225 UNSIGNED_TYPE_MAPPING = { 226 exp.DType.UBIGINT: "BIGINT", 227 exp.DType.UINT: "INT", 228 exp.DType.UMEDIUMINT: "MEDIUMINT", 229 exp.DType.USMALLINT: "SMALLINT", 230 exp.DType.UTINYINT: "TINYINT", 231 exp.DType.UDECIMAL: "DECIMAL", 232 exp.DType.UDOUBLE: "DOUBLE", 233 } 234 235 TIMESTAMP_TYPE_MAPPING = { 236 exp.DType.DATETIME2: "DATETIME", 237 exp.DType.SMALLDATETIME: "DATETIME", 238 exp.DType.TIMESTAMP: "DATETIME", 239 exp.DType.TIMESTAMPNTZ: "DATETIME", 240 exp.DType.TIMESTAMPTZ: "TIMESTAMP", 241 exp.DType.TIMESTAMPLTZ: "TIMESTAMP", 242 } 243 244 TYPE_MAPPING: t.ClassVar = { 245 exp.DType.NCHAR: "CHAR", 246 exp.DType.NVARCHAR: "VARCHAR", 247 exp.DType.INET: "INET", 248 exp.DType.ROWVERSION: "VARBINARY", 249 exp.DType.UBIGINT: "BIGINT", 250 exp.DType.UINT: "INT", 251 exp.DType.UMEDIUMINT: "MEDIUMINT", 252 exp.DType.USMALLINT: "SMALLINT", 253 exp.DType.UTINYINT: "TINYINT", 254 exp.DType.UDECIMAL: "DECIMAL", 255 exp.DType.UDOUBLE: "DOUBLE", 256 exp.DType.DATETIME2: "DATETIME", 257 exp.DType.SMALLDATETIME: "DATETIME", 258 exp.DType.TIMESTAMP: "DATETIME", 259 exp.DType.TIMESTAMPNTZ: "DATETIME", 260 exp.DType.TIMESTAMPTZ: "TIMESTAMP", 261 exp.DType.TIMESTAMPLTZ: "TIMESTAMP", 262 } 263 264 PROPERTIES_LOCATION: t.ClassVar = { 265 **generator.Generator.PROPERTIES_LOCATION, 266 exp.TransientProperty: exp.Properties.Location.UNSUPPORTED, 267 exp.VolatileProperty: exp.Properties.Location.UNSUPPORTED, 268 exp.PartitionedByProperty: exp.Properties.Location.UNSUPPORTED, 269 exp.PartitionByRangeProperty: exp.Properties.Location.POST_SCHEMA, 270 exp.PartitionByListProperty: exp.Properties.Location.POST_SCHEMA, 271 } 272 273 LIMIT_FETCH = "LIMIT" 274 275 LIMIT_ONLY_LITERALS = True 276 277 CHAR_CAST_MAPPING: t.ClassVar = dict.fromkeys( 278 ( 279 exp.DType.LONGTEXT, 280 exp.DType.LONGBLOB, 281 exp.DType.MEDIUMBLOB, 282 exp.DType.MEDIUMTEXT, 283 exp.DType.TEXT, 284 exp.DType.TINYBLOB, 285 exp.DType.TINYTEXT, 286 exp.DType.VARCHAR, 287 ), 288 "CHAR", 289 ) 290 SIGNED_CAST_MAPPING: t.ClassVar = dict.fromkeys( 291 ( 292 exp.DType.BIGINT, 293 exp.DType.BOOLEAN, 294 exp.DType.INT, 295 exp.DType.SMALLINT, 296 exp.DType.TINYINT, 297 exp.DType.MEDIUMINT, 298 ), 299 "SIGNED", 300 ) 301 302 # MySQL doesn't support many datatypes in cast. 303 # https://dev.mysql.com/doc/refman/8.0/en/cast-functions.html#function_cast 304 CAST_MAPPING = { 305 exp.DType.LONGTEXT: "CHAR", 306 exp.DType.LONGBLOB: "CHAR", 307 exp.DType.MEDIUMBLOB: "CHAR", 308 exp.DType.MEDIUMTEXT: "CHAR", 309 exp.DType.TEXT: "CHAR", 310 exp.DType.TINYBLOB: "CHAR", 311 exp.DType.TINYTEXT: "CHAR", 312 exp.DType.VARCHAR: "CHAR", 313 exp.DType.BIGINT: "SIGNED", 314 exp.DType.BOOLEAN: "SIGNED", 315 exp.DType.INT: "SIGNED", 316 exp.DType.SMALLINT: "SIGNED", 317 exp.DType.TINYINT: "SIGNED", 318 exp.DType.MEDIUMINT: "SIGNED", 319 exp.DType.UBIGINT: "UNSIGNED", 320 } 321 322 TIMESTAMP_FUNC_TYPES = { 323 exp.DType.TIMESTAMPTZ, 324 exp.DType.TIMESTAMPLTZ, 325 } 326 327 # https://dev.mysql.com/doc/refman/8.0/en/keywords.html 328 RESERVED_KEYWORDS = { 329 "accessible", 330 "add", 331 "all", 332 "alter", 333 "analyze", 334 "and", 335 "as", 336 "asc", 337 "asensitive", 338 "before", 339 "between", 340 "bigint", 341 "binary", 342 "blob", 343 "both", 344 "by", 345 "call", 346 "cascade", 347 "case", 348 "change", 349 "char", 350 "character", 351 "check", 352 "collate", 353 "column", 354 "condition", 355 "constraint", 356 "continue", 357 "convert", 358 "create", 359 "cross", 360 "cube", 361 "cume_dist", 362 "current_date", 363 "current_time", 364 "current_timestamp", 365 "current_user", 366 "cursor", 367 "database", 368 "databases", 369 "day_hour", 370 "day_microsecond", 371 "day_minute", 372 "day_second", 373 "dec", 374 "decimal", 375 "declare", 376 "default", 377 "delayed", 378 "delete", 379 "dense_rank", 380 "desc", 381 "describe", 382 "deterministic", 383 "distinct", 384 "distinctrow", 385 "div", 386 "double", 387 "drop", 388 "dual", 389 "each", 390 "else", 391 "elseif", 392 "empty", 393 "enclosed", 394 "escaped", 395 "except", 396 "exists", 397 "exit", 398 "explain", 399 "false", 400 "fetch", 401 "first_value", 402 "float", 403 "float4", 404 "float8", 405 "for", 406 "force", 407 "foreign", 408 "from", 409 "fulltext", 410 "function", 411 "generated", 412 "get", 413 "grant", 414 "group", 415 "grouping", 416 "groups", 417 "having", 418 "high_priority", 419 "hour_microsecond", 420 "hour_minute", 421 "hour_second", 422 "if", 423 "ignore", 424 "in", 425 "index", 426 "infile", 427 "inner", 428 "inout", 429 "insensitive", 430 "insert", 431 "int", 432 "int1", 433 "int2", 434 "int3", 435 "int4", 436 "int8", 437 "integer", 438 "intersect", 439 "interval", 440 "into", 441 "io_after_gtids", 442 "io_before_gtids", 443 "is", 444 "iterate", 445 "join", 446 "json_table", 447 "key", 448 "keys", 449 "kill", 450 "lag", 451 "last_value", 452 "lateral", 453 "lead", 454 "leading", 455 "leave", 456 "left", 457 "like", 458 "limit", 459 "linear", 460 "lines", 461 "load", 462 "localtime", 463 "localtimestamp", 464 "lock", 465 "long", 466 "longblob", 467 "longtext", 468 "loop", 469 "low_priority", 470 "master_bind", 471 "master_ssl_verify_server_cert", 472 "match", 473 "maxvalue", 474 "mediumblob", 475 "mediumint", 476 "mediumtext", 477 "middleint", 478 "minute_microsecond", 479 "minute_second", 480 "mod", 481 "modifies", 482 "natural", 483 "not", 484 "no_write_to_binlog", 485 "nth_value", 486 "ntile", 487 "null", 488 "numeric", 489 "of", 490 "on", 491 "optimize", 492 "optimizer_costs", 493 "option", 494 "optionally", 495 "or", 496 "order", 497 "out", 498 "outer", 499 "outfile", 500 "over", 501 "partition", 502 "percent_rank", 503 "precision", 504 "primary", 505 "procedure", 506 "purge", 507 "range", 508 "rank", 509 "read", 510 "reads", 511 "read_write", 512 "real", 513 "recursive", 514 "references", 515 "regexp", 516 "release", 517 "rename", 518 "repeat", 519 "replace", 520 "require", 521 "resignal", 522 "restrict", 523 "return", 524 "revoke", 525 "right", 526 "rlike", 527 "row", 528 "rows", 529 "row_number", 530 "schema", 531 "schemas", 532 "second_microsecond", 533 "select", 534 "sensitive", 535 "separator", 536 "set", 537 "show", 538 "signal", 539 "smallint", 540 "spatial", 541 "specific", 542 "sql", 543 "sqlexception", 544 "sqlstate", 545 "sqlwarning", 546 "sql_big_result", 547 "sql_calc_found_rows", 548 "sql_small_result", 549 "ssl", 550 "starting", 551 "stored", 552 "straight_join", 553 "system", 554 "table", 555 "terminated", 556 "then", 557 "tinyblob", 558 "tinyint", 559 "tinytext", 560 "to", 561 "trailing", 562 "trigger", 563 "true", 564 "undo", 565 "union", 566 "unique", 567 "unlock", 568 "unsigned", 569 "update", 570 "usage", 571 "use", 572 "using", 573 "utc_date", 574 "utc_time", 575 "utc_timestamp", 576 "values", 577 "varbinary", 578 "varchar", 579 "varcharacter", 580 "varying", 581 "virtual", 582 "when", 583 "where", 584 "while", 585 "window", 586 "with", 587 "write", 588 "xor", 589 "year_month", 590 "zerofill", 591 } 592 593 SQL_SECURITY_VIEW_LOCATION = exp.Properties.Location.POST_CREATE 594 595 def makeinterval_sql(self: MySQLGenerator, expression: exp.MakeInterval) -> str: 596 intervals: list[exp.Interval] = [] 597 for arg_key, value in expression.args.items(): 598 if value is None: 599 continue 600 601 if isinstance(value, exp.Kwarg): 602 unit_name = _MAKE_INTERVAL_UNIT_ALIASES.get( 603 value.this.name.lower(), value.this.name.lower() 604 ) 605 value = value.expression 606 else: 607 unit_name = arg_key 608 609 intervals.append(exp.Interval(this=value.copy(), unit=exp.var(unit_name.upper()))) 610 611 if not intervals: 612 return self.function_fallback_sql(expression) 613 614 parent = expression.parent 615 sep = " - " if isinstance(parent, exp.Sub) and parent.expression is expression else " + " 616 617 return sep.join(self.sql(interval) for interval in intervals) 618 619 def locate_properties(self, properties: exp.Properties) -> defaultdict: 620 locations = super().locate_properties(properties) 621 622 # MySQL puts SQL SECURITY before VIEW but after the schema for functions/procedures 623 if isinstance(create := properties.parent, exp.Create) and create.kind == "VIEW": 624 post_schema = locations[exp.Properties.Location.POST_SCHEMA] 625 for i, p in enumerate(post_schema): 626 if isinstance(p, exp.SqlSecurityProperty): 627 post_schema.pop(i) 628 locations[self.SQL_SECURITY_VIEW_LOCATION].append(p) 629 break 630 631 return locations 632 633 def computedcolumnconstraint_sql(self, expression: exp.ComputedColumnConstraint) -> str: 634 persisted = "STORED" if expression.args.get("persisted") else "VIRTUAL" 635 return f"GENERATED ALWAYS AS ({self.sql(expression.this.unnest())}) {persisted}" 636 637 def array_sql(self, expression: exp.Array) -> str: 638 self.unsupported("Arrays are not supported by MySQL") 639 return self.function_fallback_sql(expression) 640 641 def arraycontainsall_sql(self, expression: exp.ArrayContainsAll) -> str: 642 self.unsupported("Array operations are not supported by MySQL") 643 return self.function_fallback_sql(expression) 644 645 def arraycontainedby_sql(self, expression: exp.ArrayContainedBy) -> str: 646 self.unsupported("Array operations are not supported by MySQL") 647 return self.function_fallback_sql(expression) 648 649 def dpipe_sql(self, expression: exp.DPipe) -> str: 650 return self.func("CONCAT", *expression.flatten()) 651 652 def extract_sql(self, expression: exp.Extract) -> str: 653 unit = expression.name 654 if unit and unit.lower() == "epoch": 655 return self.func("UNIX_TIMESTAMP", expression.expression) 656 657 return super().extract_sql(expression) 658 659 def datatype_sql(self, expression: exp.DataType) -> str: 660 if ( 661 self.VARCHAR_REQUIRES_SIZE 662 and expression.is_type(exp.DType.VARCHAR) 663 and not expression.expressions 664 ): 665 # `VARCHAR` must always have a size - if it doesn't, we always generate `TEXT` 666 return "TEXT" 667 668 # https://dev.mysql.com/doc/refman/8.0/en/numeric-type-syntax.html 669 result = super().datatype_sql(expression) 670 if expression.this in self.UNSIGNED_TYPE_MAPPING: 671 result = f"{result} UNSIGNED" 672 673 return result 674 675 def jsonarraycontains_sql(self, expression: exp.JSONArrayContains) -> str: 676 return f"{self.sql(expression, 'this')} MEMBER OF({self.sql(expression, 'expression')})" 677 678 def cast_sql(self, expression: exp.Cast, safe_prefix: str | None = None) -> str: 679 if expression.to.this in self.TIMESTAMP_FUNC_TYPES: 680 return self.func("TIMESTAMP", expression.this) 681 682 to = self.CAST_MAPPING.get(expression.to.this) 683 684 if to: 685 expression.to.set("this", to) 686 return super().cast_sql(expression) 687 688 def show_sql(self, expression: exp.Show) -> str: 689 this = f" {expression.name}" 690 full = " FULL" if expression.args.get("full") else "" 691 global_ = " GLOBAL" if expression.args.get("global_") else "" 692 693 target = self.sql(expression, "target") 694 target = f" {target}" if target else "" 695 if expression.name in ("COLUMNS", "INDEX"): 696 target = f" FROM{target}" 697 elif expression.name == "GRANTS": 698 target = f" FOR{target}" 699 elif expression.name in ("LINKS", "PARTITIONS"): 700 target = f" ON{target}" if target else "" 701 elif expression.name == "PROJECTIONS": 702 target = f" ON TABLE{target}" if target else "" 703 704 db = self._prefixed_sql("FROM", expression, "db") 705 706 like = self._prefixed_sql("LIKE", expression, "like") 707 where = self.sql(expression, "where") 708 709 types = self.expressions(expression, key="types") 710 types = f" {types}" if types else types 711 query = self._prefixed_sql("FOR QUERY", expression, "query") 712 713 if expression.name == "PROFILE": 714 offset = self._prefixed_sql("OFFSET", expression, "offset") 715 limit = self._prefixed_sql("LIMIT", expression, "limit") 716 else: 717 offset = "" 718 limit = self._oldstyle_limit_sql(expression) 719 720 log = self._prefixed_sql("IN", expression, "log") 721 position = self._prefixed_sql("FROM", expression, "position") 722 723 channel = self._prefixed_sql("FOR CHANNEL", expression, "channel") 724 725 if expression.name == "ENGINE": 726 mutex_or_status = " MUTEX" if expression.args.get("mutex") else " STATUS" 727 else: 728 mutex_or_status = "" 729 730 for_table = self._prefixed_sql("FOR TABLE", expression, "for_table") 731 for_group = self._prefixed_sql("FOR GROUP", expression, "for_group") 732 for_user = self._prefixed_sql("FOR USER", expression, "for_user") 733 for_role = self._prefixed_sql("FOR ROLE", expression, "for_role") 734 into_outfile = self._prefixed_sql("INTO OUTFILE", expression, "into_outfile") 735 json = " JSON" if expression.args.get("json") else "" 736 737 return f"SHOW{full}{global_}{this}{json}{target}{for_table}{types}{db}{query}{log}{position}{channel}{mutex_or_status}{like}{where}{offset}{limit}{for_group}{for_user}{for_role}{into_outfile}" 738 739 def alterrename_sql(self, expression: exp.AlterRename, include_to: bool = True) -> str: 740 """To avoid TO keyword in ALTER ... RENAME statements. 741 It's moved from Doris, because it's the same for all MySQL, Doris, and StarRocks. 742 """ 743 return super().alterrename_sql(expression, include_to=False) 744 745 def altercolumn_sql(self, expression: exp.AlterColumn) -> str: 746 dtype = self.sql(expression, "dtype") 747 if not dtype: 748 return super().altercolumn_sql(expression) 749 750 this = self.sql(expression, "this") 751 return f"MODIFY COLUMN {this} {dtype}" 752 753 def _prefixed_sql(self, prefix: str, expression: exp.Expr, arg: str) -> str: 754 sql = self.sql(expression, arg) 755 return f" {prefix} {sql}" if sql else "" 756 757 def _oldstyle_limit_sql(self, expression: exp.Show) -> str: 758 limit = self.sql(expression, "limit") 759 offset = self.sql(expression, "offset") 760 if limit: 761 limit_offset = f"{offset}, {limit}" if offset else limit 762 return f" LIMIT {limit_offset}" 763 return "" 764 765 def timestamptrunc_sql(self, expression: exp.TimestampTrunc) -> str: 766 unit = expression.args.get("unit") 767 if isinstance(unit, exp.WeekStart): 768 unit = exp.var(self.weekstart_name(unit)) 769 770 # Pick an old-enough date to avoid negative timestamp diffs 771 start_ts = "'0000-01-01 00:00:00'" 772 773 # Source: https://stackoverflow.com/a/32955740 774 timestamp_diff = build_date_delta(exp.TimestampDiff)([unit, start_ts, expression.this]) 775 interval = exp.Interval(this=timestamp_diff, unit=unit) 776 dateadd = build_date_delta_with_interval(exp.DateAdd)([start_ts, interval]) 777 778 return self.sql(dateadd) 779 780 def converttimezone_sql(self, expression: exp.ConvertTimezone) -> str: 781 from_tz = expression.args.get("source_tz") 782 to_tz = expression.args.get("target_tz") 783 dt = expression.args.get("timestamp") 784 785 return self.func("CONVERT_TZ", dt, from_tz, to_tz) 786 787 def attimezone_sql(self, expression: exp.AtTimeZone) -> str: 788 self.unsupported("AT TIME ZONE is not supported by MySQL") 789 return self.sql(expression.this) 790 791 def isascii_sql(self, expression: exp.IsAscii) -> str: 792 return f"REGEXP_LIKE({self.sql(expression.this)}, '^[[:ascii:]]*$')" 793 794 def ignorenulls_sql(self, expression: exp.IgnoreNulls) -> str: 795 # https://dev.mysql.com/doc/refman/8.4/en/window-function-descriptions.html 796 self.unsupported("MySQL does not support IGNORE NULLS.") 797 return self.sql(expression.this) 798 799 @unsupported_args("this") 800 def currentschema_sql(self, expression: exp.CurrentSchema) -> str: 801 return self.func("SCHEMA") 802 803 def partition_sql(self, expression: exp.Partition) -> str: 804 parent = expression.parent 805 if isinstance(parent, (exp.PartitionByRangeProperty, exp.PartitionByListProperty)): 806 return self.expressions(expression, flat=True) 807 return super().partition_sql(expression) 808 809 def _partition_by_sql( 810 self, expression: exp.PartitionByRangeProperty | exp.PartitionByListProperty, kind: str 811 ) -> str: 812 partitions = self.expressions(expression, key="partition_expressions", flat=True) 813 create = self.expressions(expression, key="create_expressions", flat=True) 814 return f"PARTITION BY {kind} ({partitions}) ({create})" 815 816 def partitionbyrangeproperty_sql(self, expression: exp.PartitionByRangeProperty) -> str: 817 return self._partition_by_sql(expression, "RANGE") 818 819 def partitionbylistproperty_sql(self, expression: exp.PartitionByListProperty) -> str: 820 return self._partition_by_sql(expression, "LIST") 821 822 def partitionlist_sql(self, expression: exp.PartitionList) -> str: 823 name = self.sql(expression, "this") 824 values = self.expressions(expression, flat=True) 825 return f"PARTITION {name} VALUES IN ({values})" 826 827 def partitionrange_sql(self, expression: exp.PartitionRange) -> str: 828 name = self.sql(expression, "this") 829 values = self.expressions(expression, flat=True) 830 return f"PARTITION {name} VALUES LESS THAN ({values})"
def
date_add_sql( kind: str) -> Callable[[sqlglot.generator.Generator, sqlglot.expressions.core.Expr], str]:
81def date_add_sql( 82 kind: str, 83) -> t.Callable[[generator.Generator, exp.Expr], str]: 84 def func(self: generator.Generator, expression: exp.Expr) -> str: 85 return self.func( 86 f"DATE_{kind}", 87 expression.this, 88 exp.Interval(this=expression.expression, unit=unit_to_var(expression)), 89 ) 90 91 return func
112class MySQLGenerator(generator.Generator): 113 SELECT_KINDS: tuple[str, ...] = () 114 TRY_SUPPORTED = False 115 SUPPORTS_UESCAPE = False 116 SUPPORTS_DECODE_CASE = False 117 SUPPORTS_MODIFY_COLUMN = True 118 SUPPORTS_CHANGE_COLUMN = True 119 120 AFTER_HAVING_MODIFIER_TRANSFORMS = generator.AFTER_HAVING_MODIFIER_TRANSFORMS 121 122 INTERVAL_ALLOWS_PLURAL_FORM = False 123 LOCKING_READS_SUPPORTED = True 124 NULL_ORDERING_SUPPORTED: bool | None = None 125 JOIN_HINTS = False 126 TABLE_HINTS = True 127 DUPLICATE_KEY_UPDATE_WITH_SET = False 128 QUERY_HINT_SEP = " " 129 VALUES_AS_TABLE = False 130 NVL2_SUPPORTED = False 131 LAST_DAY_SUPPORTS_DATE_PART = False 132 JSON_TYPE_REQUIRED_FOR_EXTRACTION = True 133 JSON_PATH_BRACKETED_KEY_SUPPORTED = False 134 JSON_KEY_VALUE_PAIR_SEP = "," 135 SUPPORTS_TO_NUMBER = False 136 PARSE_JSON_NAME: str | None = None 137 PAD_FILL_PATTERN_IS_REQUIRED = True 138 WRAP_DERIVED_VALUES = False 139 VARCHAR_REQUIRES_SIZE = True 140 SUPPORTS_MEDIAN = False 141 UPDATE_STATEMENT_SUPPORTS_FROM = False 142 143 TRANSFORMS = { 144 **generator.Generator.TRANSFORMS, 145 exp.ArrayAgg: rename_func("GROUP_CONCAT"), 146 exp.BitwiseAndAgg: rename_func("BIT_AND"), 147 exp.BitwiseOrAgg: rename_func("BIT_OR"), 148 exp.BitwiseXorAgg: rename_func("BIT_XOR"), 149 exp.BitwiseCount: rename_func("BIT_COUNT"), 150 exp.Chr: lambda self, e: self.chr_sql(e, "CHAR"), 151 exp.CurrentDate: no_paren_current_date_sql, 152 exp.CurrentVersion: rename_func("VERSION"), 153 exp.DateDiff: remove_ts_or_ds_to_date( 154 lambda self, e: self.func("DATEDIFF", e.this, e.expression), ("this", "expression") 155 ), 156 exp.DateAdd: remove_ts_or_ds_to_date(date_add_sql("ADD")), 157 exp.DateStrToDate: datestrtodate_sql, 158 exp.DateSub: remove_ts_or_ds_to_date(date_add_sql("SUB")), 159 exp.DateTrunc: _date_trunc_sql, 160 exp.Day: remove_ts_or_ds_to_date(), 161 exp.DayOfMonth: remove_ts_or_ds_to_date(rename_func("DAYOFMONTH")), 162 exp.DayOfWeek: remove_ts_or_ds_to_date(rename_func("DAYOFWEEK")), 163 exp.DayOfYear: remove_ts_or_ds_to_date(rename_func("DAYOFYEAR")), 164 exp.GroupConcat: lambda self, e: ( 165 f"""GROUP_CONCAT({self.sql(e, "this")} SEPARATOR {self.sql(e, "separator") or "','"})""" 166 ), 167 exp.ILike: no_ilike_sql, 168 exp.JSONExtractScalar: arrow_json_extract_sql, 169 exp.Length: length_or_char_length_sql, 170 exp.LogicalOr: rename_func("MAX"), 171 exp.LogicalAnd: rename_func("MIN"), 172 exp.Max: max_or_greatest, 173 exp.Min: min_or_least, 174 exp.Month: remove_ts_or_ds_to_date(), 175 exp.NullSafeEQ: lambda self, e: self.binary(e, "<=>"), 176 exp.NullSafeNEQ: lambda self, e: f"NOT {self.binary(e, '<=>')}", 177 exp.NumberToStr: rename_func("FORMAT"), 178 exp.Pivot: no_pivot_sql, 179 exp.Select: transforms.preprocess( 180 [ 181 transforms.eliminate_distinct_on, 182 transforms.eliminate_semi_and_anti_joins, 183 transforms.eliminate_qualify, 184 transforms.eliminate_full_outer_join, 185 transforms.unnest_generate_date_array_using_recursive_cte, 186 ] 187 ), 188 exp.StrPosition: lambda self, e: strposition_sql( 189 self, e, func_name="LOCATE", supports_position=True 190 ), 191 exp.StrToDate: _str_to_date_sql, 192 exp.StrToTime: _str_to_date_sql, 193 exp.Stuff: rename_func("INSERT"), 194 exp.SessionUser: lambda *_: "SESSION_USER()", 195 exp.TableSample: no_tablesample_sql, 196 exp.TimeFromParts: rename_func("MAKETIME"), 197 exp.TimestampAdd: date_add_interval_sql("DATE", "ADD"), 198 exp.TimestampDiff: lambda self, e: self.func( 199 "TIMESTAMPDIFF", unit_to_var(e), e.expression, e.this 200 ), 201 exp.TimestampSub: date_add_interval_sql("DATE", "SUB"), 202 exp.TimeStrToUnix: rename_func("UNIX_TIMESTAMP"), 203 exp.TimeStrToTime: lambda self, e: timestrtotime_sql( 204 self, 205 e, 206 include_precision=not e.args.get("zone"), 207 ), 208 exp.TimeToStr: remove_ts_or_ds_to_date( 209 lambda self, e: self.func("DATE_FORMAT", e.this, self.format_time(e)) 210 ), 211 exp.Trim: trim_sql, 212 exp.Trunc: rename_func("TRUNCATE"), 213 exp.TryCast: no_trycast_sql, 214 exp.TsOrDsAdd: date_add_sql("ADD"), 215 exp.TsOrDsDiff: lambda self, e: self.func("DATEDIFF", e.this, e.expression), 216 exp.TsOrDsToDate: _ts_or_ds_to_date_sql, 217 exp.Unicode: lambda self, e: f"ORD(CONVERT({self.sql(e.this)} USING utf32))", 218 exp.UnixToTime: _unix_to_time_sql, 219 exp.Week: remove_ts_or_ds_to_date(), 220 exp.WeekOfYear: remove_ts_or_ds_to_date(rename_func("WEEKOFYEAR")), 221 exp.Year: remove_ts_or_ds_to_date(), 222 exp.UtcTimestamp: rename_func("UTC_TIMESTAMP"), 223 exp.UtcTime: rename_func("UTC_TIME"), 224 } 225 226 UNSIGNED_TYPE_MAPPING = { 227 exp.DType.UBIGINT: "BIGINT", 228 exp.DType.UINT: "INT", 229 exp.DType.UMEDIUMINT: "MEDIUMINT", 230 exp.DType.USMALLINT: "SMALLINT", 231 exp.DType.UTINYINT: "TINYINT", 232 exp.DType.UDECIMAL: "DECIMAL", 233 exp.DType.UDOUBLE: "DOUBLE", 234 } 235 236 TIMESTAMP_TYPE_MAPPING = { 237 exp.DType.DATETIME2: "DATETIME", 238 exp.DType.SMALLDATETIME: "DATETIME", 239 exp.DType.TIMESTAMP: "DATETIME", 240 exp.DType.TIMESTAMPNTZ: "DATETIME", 241 exp.DType.TIMESTAMPTZ: "TIMESTAMP", 242 exp.DType.TIMESTAMPLTZ: "TIMESTAMP", 243 } 244 245 TYPE_MAPPING: t.ClassVar = { 246 exp.DType.NCHAR: "CHAR", 247 exp.DType.NVARCHAR: "VARCHAR", 248 exp.DType.INET: "INET", 249 exp.DType.ROWVERSION: "VARBINARY", 250 exp.DType.UBIGINT: "BIGINT", 251 exp.DType.UINT: "INT", 252 exp.DType.UMEDIUMINT: "MEDIUMINT", 253 exp.DType.USMALLINT: "SMALLINT", 254 exp.DType.UTINYINT: "TINYINT", 255 exp.DType.UDECIMAL: "DECIMAL", 256 exp.DType.UDOUBLE: "DOUBLE", 257 exp.DType.DATETIME2: "DATETIME", 258 exp.DType.SMALLDATETIME: "DATETIME", 259 exp.DType.TIMESTAMP: "DATETIME", 260 exp.DType.TIMESTAMPNTZ: "DATETIME", 261 exp.DType.TIMESTAMPTZ: "TIMESTAMP", 262 exp.DType.TIMESTAMPLTZ: "TIMESTAMP", 263 } 264 265 PROPERTIES_LOCATION: t.ClassVar = { 266 **generator.Generator.PROPERTIES_LOCATION, 267 exp.TransientProperty: exp.Properties.Location.UNSUPPORTED, 268 exp.VolatileProperty: exp.Properties.Location.UNSUPPORTED, 269 exp.PartitionedByProperty: exp.Properties.Location.UNSUPPORTED, 270 exp.PartitionByRangeProperty: exp.Properties.Location.POST_SCHEMA, 271 exp.PartitionByListProperty: exp.Properties.Location.POST_SCHEMA, 272 } 273 274 LIMIT_FETCH = "LIMIT" 275 276 LIMIT_ONLY_LITERALS = True 277 278 CHAR_CAST_MAPPING: t.ClassVar = dict.fromkeys( 279 ( 280 exp.DType.LONGTEXT, 281 exp.DType.LONGBLOB, 282 exp.DType.MEDIUMBLOB, 283 exp.DType.MEDIUMTEXT, 284 exp.DType.TEXT, 285 exp.DType.TINYBLOB, 286 exp.DType.TINYTEXT, 287 exp.DType.VARCHAR, 288 ), 289 "CHAR", 290 ) 291 SIGNED_CAST_MAPPING: t.ClassVar = dict.fromkeys( 292 ( 293 exp.DType.BIGINT, 294 exp.DType.BOOLEAN, 295 exp.DType.INT, 296 exp.DType.SMALLINT, 297 exp.DType.TINYINT, 298 exp.DType.MEDIUMINT, 299 ), 300 "SIGNED", 301 ) 302 303 # MySQL doesn't support many datatypes in cast. 304 # https://dev.mysql.com/doc/refman/8.0/en/cast-functions.html#function_cast 305 CAST_MAPPING = { 306 exp.DType.LONGTEXT: "CHAR", 307 exp.DType.LONGBLOB: "CHAR", 308 exp.DType.MEDIUMBLOB: "CHAR", 309 exp.DType.MEDIUMTEXT: "CHAR", 310 exp.DType.TEXT: "CHAR", 311 exp.DType.TINYBLOB: "CHAR", 312 exp.DType.TINYTEXT: "CHAR", 313 exp.DType.VARCHAR: "CHAR", 314 exp.DType.BIGINT: "SIGNED", 315 exp.DType.BOOLEAN: "SIGNED", 316 exp.DType.INT: "SIGNED", 317 exp.DType.SMALLINT: "SIGNED", 318 exp.DType.TINYINT: "SIGNED", 319 exp.DType.MEDIUMINT: "SIGNED", 320 exp.DType.UBIGINT: "UNSIGNED", 321 } 322 323 TIMESTAMP_FUNC_TYPES = { 324 exp.DType.TIMESTAMPTZ, 325 exp.DType.TIMESTAMPLTZ, 326 } 327 328 # https://dev.mysql.com/doc/refman/8.0/en/keywords.html 329 RESERVED_KEYWORDS = { 330 "accessible", 331 "add", 332 "all", 333 "alter", 334 "analyze", 335 "and", 336 "as", 337 "asc", 338 "asensitive", 339 "before", 340 "between", 341 "bigint", 342 "binary", 343 "blob", 344 "both", 345 "by", 346 "call", 347 "cascade", 348 "case", 349 "change", 350 "char", 351 "character", 352 "check", 353 "collate", 354 "column", 355 "condition", 356 "constraint", 357 "continue", 358 "convert", 359 "create", 360 "cross", 361 "cube", 362 "cume_dist", 363 "current_date", 364 "current_time", 365 "current_timestamp", 366 "current_user", 367 "cursor", 368 "database", 369 "databases", 370 "day_hour", 371 "day_microsecond", 372 "day_minute", 373 "day_second", 374 "dec", 375 "decimal", 376 "declare", 377 "default", 378 "delayed", 379 "delete", 380 "dense_rank", 381 "desc", 382 "describe", 383 "deterministic", 384 "distinct", 385 "distinctrow", 386 "div", 387 "double", 388 "drop", 389 "dual", 390 "each", 391 "else", 392 "elseif", 393 "empty", 394 "enclosed", 395 "escaped", 396 "except", 397 "exists", 398 "exit", 399 "explain", 400 "false", 401 "fetch", 402 "first_value", 403 "float", 404 "float4", 405 "float8", 406 "for", 407 "force", 408 "foreign", 409 "from", 410 "fulltext", 411 "function", 412 "generated", 413 "get", 414 "grant", 415 "group", 416 "grouping", 417 "groups", 418 "having", 419 "high_priority", 420 "hour_microsecond", 421 "hour_minute", 422 "hour_second", 423 "if", 424 "ignore", 425 "in", 426 "index", 427 "infile", 428 "inner", 429 "inout", 430 "insensitive", 431 "insert", 432 "int", 433 "int1", 434 "int2", 435 "int3", 436 "int4", 437 "int8", 438 "integer", 439 "intersect", 440 "interval", 441 "into", 442 "io_after_gtids", 443 "io_before_gtids", 444 "is", 445 "iterate", 446 "join", 447 "json_table", 448 "key", 449 "keys", 450 "kill", 451 "lag", 452 "last_value", 453 "lateral", 454 "lead", 455 "leading", 456 "leave", 457 "left", 458 "like", 459 "limit", 460 "linear", 461 "lines", 462 "load", 463 "localtime", 464 "localtimestamp", 465 "lock", 466 "long", 467 "longblob", 468 "longtext", 469 "loop", 470 "low_priority", 471 "master_bind", 472 "master_ssl_verify_server_cert", 473 "match", 474 "maxvalue", 475 "mediumblob", 476 "mediumint", 477 "mediumtext", 478 "middleint", 479 "minute_microsecond", 480 "minute_second", 481 "mod", 482 "modifies", 483 "natural", 484 "not", 485 "no_write_to_binlog", 486 "nth_value", 487 "ntile", 488 "null", 489 "numeric", 490 "of", 491 "on", 492 "optimize", 493 "optimizer_costs", 494 "option", 495 "optionally", 496 "or", 497 "order", 498 "out", 499 "outer", 500 "outfile", 501 "over", 502 "partition", 503 "percent_rank", 504 "precision", 505 "primary", 506 "procedure", 507 "purge", 508 "range", 509 "rank", 510 "read", 511 "reads", 512 "read_write", 513 "real", 514 "recursive", 515 "references", 516 "regexp", 517 "release", 518 "rename", 519 "repeat", 520 "replace", 521 "require", 522 "resignal", 523 "restrict", 524 "return", 525 "revoke", 526 "right", 527 "rlike", 528 "row", 529 "rows", 530 "row_number", 531 "schema", 532 "schemas", 533 "second_microsecond", 534 "select", 535 "sensitive", 536 "separator", 537 "set", 538 "show", 539 "signal", 540 "smallint", 541 "spatial", 542 "specific", 543 "sql", 544 "sqlexception", 545 "sqlstate", 546 "sqlwarning", 547 "sql_big_result", 548 "sql_calc_found_rows", 549 "sql_small_result", 550 "ssl", 551 "starting", 552 "stored", 553 "straight_join", 554 "system", 555 "table", 556 "terminated", 557 "then", 558 "tinyblob", 559 "tinyint", 560 "tinytext", 561 "to", 562 "trailing", 563 "trigger", 564 "true", 565 "undo", 566 "union", 567 "unique", 568 "unlock", 569 "unsigned", 570 "update", 571 "usage", 572 "use", 573 "using", 574 "utc_date", 575 "utc_time", 576 "utc_timestamp", 577 "values", 578 "varbinary", 579 "varchar", 580 "varcharacter", 581 "varying", 582 "virtual", 583 "when", 584 "where", 585 "while", 586 "window", 587 "with", 588 "write", 589 "xor", 590 "year_month", 591 "zerofill", 592 } 593 594 SQL_SECURITY_VIEW_LOCATION = exp.Properties.Location.POST_CREATE 595 596 def makeinterval_sql(self: MySQLGenerator, expression: exp.MakeInterval) -> str: 597 intervals: list[exp.Interval] = [] 598 for arg_key, value in expression.args.items(): 599 if value is None: 600 continue 601 602 if isinstance(value, exp.Kwarg): 603 unit_name = _MAKE_INTERVAL_UNIT_ALIASES.get( 604 value.this.name.lower(), value.this.name.lower() 605 ) 606 value = value.expression 607 else: 608 unit_name = arg_key 609 610 intervals.append(exp.Interval(this=value.copy(), unit=exp.var(unit_name.upper()))) 611 612 if not intervals: 613 return self.function_fallback_sql(expression) 614 615 parent = expression.parent 616 sep = " - " if isinstance(parent, exp.Sub) and parent.expression is expression else " + " 617 618 return sep.join(self.sql(interval) for interval in intervals) 619 620 def locate_properties(self, properties: exp.Properties) -> defaultdict: 621 locations = super().locate_properties(properties) 622 623 # MySQL puts SQL SECURITY before VIEW but after the schema for functions/procedures 624 if isinstance(create := properties.parent, exp.Create) and create.kind == "VIEW": 625 post_schema = locations[exp.Properties.Location.POST_SCHEMA] 626 for i, p in enumerate(post_schema): 627 if isinstance(p, exp.SqlSecurityProperty): 628 post_schema.pop(i) 629 locations[self.SQL_SECURITY_VIEW_LOCATION].append(p) 630 break 631 632 return locations 633 634 def computedcolumnconstraint_sql(self, expression: exp.ComputedColumnConstraint) -> str: 635 persisted = "STORED" if expression.args.get("persisted") else "VIRTUAL" 636 return f"GENERATED ALWAYS AS ({self.sql(expression.this.unnest())}) {persisted}" 637 638 def array_sql(self, expression: exp.Array) -> str: 639 self.unsupported("Arrays are not supported by MySQL") 640 return self.function_fallback_sql(expression) 641 642 def arraycontainsall_sql(self, expression: exp.ArrayContainsAll) -> str: 643 self.unsupported("Array operations are not supported by MySQL") 644 return self.function_fallback_sql(expression) 645 646 def arraycontainedby_sql(self, expression: exp.ArrayContainedBy) -> str: 647 self.unsupported("Array operations are not supported by MySQL") 648 return self.function_fallback_sql(expression) 649 650 def dpipe_sql(self, expression: exp.DPipe) -> str: 651 return self.func("CONCAT", *expression.flatten()) 652 653 def extract_sql(self, expression: exp.Extract) -> str: 654 unit = expression.name 655 if unit and unit.lower() == "epoch": 656 return self.func("UNIX_TIMESTAMP", expression.expression) 657 658 return super().extract_sql(expression) 659 660 def datatype_sql(self, expression: exp.DataType) -> str: 661 if ( 662 self.VARCHAR_REQUIRES_SIZE 663 and expression.is_type(exp.DType.VARCHAR) 664 and not expression.expressions 665 ): 666 # `VARCHAR` must always have a size - if it doesn't, we always generate `TEXT` 667 return "TEXT" 668 669 # https://dev.mysql.com/doc/refman/8.0/en/numeric-type-syntax.html 670 result = super().datatype_sql(expression) 671 if expression.this in self.UNSIGNED_TYPE_MAPPING: 672 result = f"{result} UNSIGNED" 673 674 return result 675 676 def jsonarraycontains_sql(self, expression: exp.JSONArrayContains) -> str: 677 return f"{self.sql(expression, 'this')} MEMBER OF({self.sql(expression, 'expression')})" 678 679 def cast_sql(self, expression: exp.Cast, safe_prefix: str | None = None) -> str: 680 if expression.to.this in self.TIMESTAMP_FUNC_TYPES: 681 return self.func("TIMESTAMP", expression.this) 682 683 to = self.CAST_MAPPING.get(expression.to.this) 684 685 if to: 686 expression.to.set("this", to) 687 return super().cast_sql(expression) 688 689 def show_sql(self, expression: exp.Show) -> str: 690 this = f" {expression.name}" 691 full = " FULL" if expression.args.get("full") else "" 692 global_ = " GLOBAL" if expression.args.get("global_") else "" 693 694 target = self.sql(expression, "target") 695 target = f" {target}" if target else "" 696 if expression.name in ("COLUMNS", "INDEX"): 697 target = f" FROM{target}" 698 elif expression.name == "GRANTS": 699 target = f" FOR{target}" 700 elif expression.name in ("LINKS", "PARTITIONS"): 701 target = f" ON{target}" if target else "" 702 elif expression.name == "PROJECTIONS": 703 target = f" ON TABLE{target}" if target else "" 704 705 db = self._prefixed_sql("FROM", expression, "db") 706 707 like = self._prefixed_sql("LIKE", expression, "like") 708 where = self.sql(expression, "where") 709 710 types = self.expressions(expression, key="types") 711 types = f" {types}" if types else types 712 query = self._prefixed_sql("FOR QUERY", expression, "query") 713 714 if expression.name == "PROFILE": 715 offset = self._prefixed_sql("OFFSET", expression, "offset") 716 limit = self._prefixed_sql("LIMIT", expression, "limit") 717 else: 718 offset = "" 719 limit = self._oldstyle_limit_sql(expression) 720 721 log = self._prefixed_sql("IN", expression, "log") 722 position = self._prefixed_sql("FROM", expression, "position") 723 724 channel = self._prefixed_sql("FOR CHANNEL", expression, "channel") 725 726 if expression.name == "ENGINE": 727 mutex_or_status = " MUTEX" if expression.args.get("mutex") else " STATUS" 728 else: 729 mutex_or_status = "" 730 731 for_table = self._prefixed_sql("FOR TABLE", expression, "for_table") 732 for_group = self._prefixed_sql("FOR GROUP", expression, "for_group") 733 for_user = self._prefixed_sql("FOR USER", expression, "for_user") 734 for_role = self._prefixed_sql("FOR ROLE", expression, "for_role") 735 into_outfile = self._prefixed_sql("INTO OUTFILE", expression, "into_outfile") 736 json = " JSON" if expression.args.get("json") else "" 737 738 return f"SHOW{full}{global_}{this}{json}{target}{for_table}{types}{db}{query}{log}{position}{channel}{mutex_or_status}{like}{where}{offset}{limit}{for_group}{for_user}{for_role}{into_outfile}" 739 740 def alterrename_sql(self, expression: exp.AlterRename, include_to: bool = True) -> str: 741 """To avoid TO keyword in ALTER ... RENAME statements. 742 It's moved from Doris, because it's the same for all MySQL, Doris, and StarRocks. 743 """ 744 return super().alterrename_sql(expression, include_to=False) 745 746 def altercolumn_sql(self, expression: exp.AlterColumn) -> str: 747 dtype = self.sql(expression, "dtype") 748 if not dtype: 749 return super().altercolumn_sql(expression) 750 751 this = self.sql(expression, "this") 752 return f"MODIFY COLUMN {this} {dtype}" 753 754 def _prefixed_sql(self, prefix: str, expression: exp.Expr, arg: str) -> str: 755 sql = self.sql(expression, arg) 756 return f" {prefix} {sql}" if sql else "" 757 758 def _oldstyle_limit_sql(self, expression: exp.Show) -> str: 759 limit = self.sql(expression, "limit") 760 offset = self.sql(expression, "offset") 761 if limit: 762 limit_offset = f"{offset}, {limit}" if offset else limit 763 return f" LIMIT {limit_offset}" 764 return "" 765 766 def timestamptrunc_sql(self, expression: exp.TimestampTrunc) -> str: 767 unit = expression.args.get("unit") 768 if isinstance(unit, exp.WeekStart): 769 unit = exp.var(self.weekstart_name(unit)) 770 771 # Pick an old-enough date to avoid negative timestamp diffs 772 start_ts = "'0000-01-01 00:00:00'" 773 774 # Source: https://stackoverflow.com/a/32955740 775 timestamp_diff = build_date_delta(exp.TimestampDiff)([unit, start_ts, expression.this]) 776 interval = exp.Interval(this=timestamp_diff, unit=unit) 777 dateadd = build_date_delta_with_interval(exp.DateAdd)([start_ts, interval]) 778 779 return self.sql(dateadd) 780 781 def converttimezone_sql(self, expression: exp.ConvertTimezone) -> str: 782 from_tz = expression.args.get("source_tz") 783 to_tz = expression.args.get("target_tz") 784 dt = expression.args.get("timestamp") 785 786 return self.func("CONVERT_TZ", dt, from_tz, to_tz) 787 788 def attimezone_sql(self, expression: exp.AtTimeZone) -> str: 789 self.unsupported("AT TIME ZONE is not supported by MySQL") 790 return self.sql(expression.this) 791 792 def isascii_sql(self, expression: exp.IsAscii) -> str: 793 return f"REGEXP_LIKE({self.sql(expression.this)}, '^[[:ascii:]]*$')" 794 795 def ignorenulls_sql(self, expression: exp.IgnoreNulls) -> str: 796 # https://dev.mysql.com/doc/refman/8.4/en/window-function-descriptions.html 797 self.unsupported("MySQL does not support IGNORE NULLS.") 798 return self.sql(expression.this) 799 800 @unsupported_args("this") 801 def currentschema_sql(self, expression: exp.CurrentSchema) -> str: 802 return self.func("SCHEMA") 803 804 def partition_sql(self, expression: exp.Partition) -> str: 805 parent = expression.parent 806 if isinstance(parent, (exp.PartitionByRangeProperty, exp.PartitionByListProperty)): 807 return self.expressions(expression, flat=True) 808 return super().partition_sql(expression) 809 810 def _partition_by_sql( 811 self, expression: exp.PartitionByRangeProperty | exp.PartitionByListProperty, kind: str 812 ) -> str: 813 partitions = self.expressions(expression, key="partition_expressions", flat=True) 814 create = self.expressions(expression, key="create_expressions", flat=True) 815 return f"PARTITION BY {kind} ({partitions}) ({create})" 816 817 def partitionbyrangeproperty_sql(self, expression: exp.PartitionByRangeProperty) -> str: 818 return self._partition_by_sql(expression, "RANGE") 819 820 def partitionbylistproperty_sql(self, expression: exp.PartitionByListProperty) -> str: 821 return self._partition_by_sql(expression, "LIST") 822 823 def partitionlist_sql(self, expression: exp.PartitionList) -> str: 824 name = self.sql(expression, "this") 825 values = self.expressions(expression, flat=True) 826 return f"PARTITION {name} VALUES IN ({values})" 827 828 def partitionrange_sql(self, expression: exp.PartitionRange) -> str: 829 name = self.sql(expression, "this") 830 values = self.expressions(expression, flat=True) 831 return f"PARTITION {name} VALUES LESS THAN ({values})"
Generator converts a given syntax tree to the corresponding SQL string.
Arguments:
- pretty: Whether to format the produced SQL string. Default: False.
- identify: Determines when an identifier should be quoted. Possible values are: False (default): Never quote, except in cases where it's mandatory by the dialect. True: Always quote except for specials cases. 'safe': Only quote identifiers that are case insensitive.
- normalize: Whether to normalize identifiers to lowercase. Default: False.
- pad: The pad size in a formatted string. For example, this affects the indentation of a projection in a query, relative to its nesting level. Default: 2.
- indent: The indentation size in a formatted string. For example, this affects the
indentation of subqueries and filters under a
WHEREclause. Default: 2. - normalize_functions: How to normalize function names. Possible values are: "upper" or True (default): Convert names to uppercase. "lower": Convert names to lowercase. False: Disables function name normalization.
- unsupported_level: Determines the generator's behavior when it encounters unsupported expressions. Default ErrorLevel.WARN.
- max_unsupported: Maximum number of unsupported messages to include in a raised UnsupportedError. This is only relevant if unsupported_level is ErrorLevel.RAISE. Default: 3
- leading_comma: Whether the comma is leading or trailing in select expressions. This is only relevant when generating in pretty mode. Default: False
- max_text_width: The max number of characters in a segment before creating new lines in pretty mode. The default is on the smaller end because the length only represents a segment and not the true line length. Default: 80
- comments: Whether to preserve comments in the output SQL code. Default: True
TRANSFORMS =
{<class 'sqlglot.expressions.query.JSONPathFilter'>: <function <lambda>>, <class 'sqlglot.expressions.query.JSONPathKey'>: <function <lambda>>, <class 'sqlglot.expressions.query.JSONPathRecursive'>: <function <lambda>>, <class 'sqlglot.expressions.query.JSONPathRoot'>: <function <lambda>>, <class 'sqlglot.expressions.query.JSONPathScript'>: <function <lambda>>, <class 'sqlglot.expressions.query.JSONPathSelector'>: <function <lambda>>, <class 'sqlglot.expressions.query.JSONPathSlice'>: <function <lambda>>, <class 'sqlglot.expressions.query.JSONPathSubscript'>: <function <lambda>>, <class 'sqlglot.expressions.query.JSONPathUnion'>: <function <lambda>>, <class 'sqlglot.expressions.query.JSONPathWildcard'>: <function <lambda>>, <class 'sqlglot.expressions.core.Adjacent'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.properties.AllowedValuesProperty'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.query.AnalyzeColumns'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.query.AnalyzeWith'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.array.ArrayContainedBy'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.array.ArrayContainsAll'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.array.ArrayOverlaps'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.constraints.AssumeColumnConstraint'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.properties.AutoRefreshProperty'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.properties.BackupProperty'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.constraints.CaseSpecificColumnConstraint'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.properties.CalledOnNullInputProperty'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.math.Ceil'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.constraints.CharacterSetColumnConstraint'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.properties.CharacterSetProperty'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.constraints.ClusteredColumnConstraint'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.constraints.CollateColumnConstraint'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.constraints.CommentColumnConstraint'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.functions.ConnectByRoot'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.string.ConvertToCharset'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.properties.CopyGrantsProperty'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.properties.CredentialsProperty'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.functions.CurrentCatalog'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.functions.SessionUser'>: <function MySQLGenerator.<lambda>>, <class 'sqlglot.expressions.constraints.DateFormatColumnConstraint'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.constraints.DefaultColumnConstraint'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.properties.ApiProperty'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.properties.ApplicationProperty'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.properties.CatalogProperty'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.properties.ComputeProperty'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.properties.DatabaseProperty'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.properties.DynamicProperty'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.properties.EmptyProperty'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.constraints.EncodeColumnConstraint'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.query.EndStatement'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.properties.EnviromentProperty'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.properties.HandlerProperty'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.properties.ParameterStyleProperty'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.constraints.EphemeralColumnConstraint'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.constraints.ExcludeColumnConstraint'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.properties.ExecuteAsProperty'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.query.Except'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.properties.ExternalProperty'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.math.Floor'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.query.Get'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.properties.GlobalProperty'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.properties.HeapProperty'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.properties.HybridProperty'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.properties.IcebergProperty'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.properties.InheritsProperty'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.constraints.InlineLengthColumnConstraint'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.properties.InputModelProperty'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.query.Intersect'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.datatypes.IntervalSpan'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.functions.Int64'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.json.JSONBContainsAnyTopKeys'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.json.JSONBContainsAllTopKeys'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.json.JSONBDeleteAtPath'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.json.JSONBPathExists'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.json.JSONObject'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.json.JSONObjectAgg'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.properties.LanguageProperty'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.properties.LocationProperty'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.properties.LogProperty'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.properties.MaskingProperty'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.properties.MaterializedProperty'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.functions.NetFunc'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.properties.NetworkProperty'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.constraints.NonClusteredColumnConstraint'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.properties.NoPrimaryIndexProperty'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.constraints.NotForReplicationColumnConstraint'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.properties.OnCommitProperty'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.properties.OnProperty'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.constraints.OnUpdateColumnConstraint'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.core.Operator'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.properties.OutputModelProperty'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.core.ExtendsLeft'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.core.ExtendsRight'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.constraints.PathColumnConstraint'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.properties.PartitionedByBucket'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.properties.PartitionByTruncate'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.core.PivotAny'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.array.PositionalColumn'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.constraints.ProjectionPolicyColumnConstraint'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.constraints.InvisibleColumnConstraint'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.constraints.ZeroFillColumnConstraint'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.query.Put'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.properties.RemoteWithConnectionModelProperty'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.properties.ReturnsProperty'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.properties.RowAccessProperty'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.core.SafeFunc'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.properties.SampleProperty'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.properties.SecureProperty'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.properties.SecurityIntegrationProperty'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.properties.SetConfigProperty'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.properties.SetProperty'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.properties.SettingsProperty'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.properties.SharingProperty'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.properties.SqlReadWriteProperty'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.properties.SqlSecurityProperty'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.properties.StabilityProperty'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.query.Stream'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.properties.StreamingTableProperty'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.properties.StrictProperty'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.ddl.SwapTable'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.query.TableColumn'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.properties.Tags'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.properties.TemporaryProperty'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.constraints.TitleColumnConstraint'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.array.ToMap'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.properties.ToTableProperty'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.properties.TransformModelProperty'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.properties.TransientProperty'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.properties.VirtualProperty'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.ddl.TriggerExecute'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.query.Union'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.properties.UnloggedProperty'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.properties.UsingTemplateProperty'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.query.UsingData'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.constraints.UppercaseColumnConstraint'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.temporal.UtcDate'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.temporal.UtcTime'>: <function rename_func.<locals>.<lambda>>, <class 'sqlglot.expressions.temporal.UtcTimestamp'>: <function rename_func.<locals>.<lambda>>, <class 'sqlglot.expressions.query.Variadic'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.array.VarMap'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.properties.ViewAttributeProperty'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.properties.VolatileProperty'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.properties.WithJournalTableProperty'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.properties.WithProcedureOptions'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.properties.WithSchemaBindingProperty'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.constraints.WithOperator'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.properties.ForceProperty'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.aggregate.ArrayAgg'>: <function rename_func.<locals>.<lambda>>, <class 'sqlglot.expressions.math.BitwiseAndAgg'>: <function rename_func.<locals>.<lambda>>, <class 'sqlglot.expressions.math.BitwiseOrAgg'>: <function rename_func.<locals>.<lambda>>, <class 'sqlglot.expressions.math.BitwiseXorAgg'>: <function rename_func.<locals>.<lambda>>, <class 'sqlglot.expressions.math.BitwiseCount'>: <function rename_func.<locals>.<lambda>>, <class 'sqlglot.expressions.string.Chr'>: <function MySQLGenerator.<lambda>>, <class 'sqlglot.expressions.temporal.CurrentDate'>: <function no_paren_current_date_sql>, <class 'sqlglot.expressions.functions.CurrentVersion'>: <function rename_func.<locals>.<lambda>>, <class 'sqlglot.expressions.temporal.DateDiff'>: <function remove_ts_or_ds_to_date.<locals>.func>, <class 'sqlglot.expressions.temporal.DateAdd'>: <function remove_ts_or_ds_to_date.<locals>.func>, <class 'sqlglot.expressions.temporal.DateStrToDate'>: <function datestrtodate_sql>, <class 'sqlglot.expressions.temporal.DateSub'>: <function remove_ts_or_ds_to_date.<locals>.func>, <class 'sqlglot.expressions.temporal.DateTrunc'>: <function _date_trunc_sql>, <class 'sqlglot.expressions.temporal.Day'>: <function remove_ts_or_ds_to_date.<locals>.func>, <class 'sqlglot.expressions.temporal.DayOfMonth'>: <function remove_ts_or_ds_to_date.<locals>.func>, <class 'sqlglot.expressions.temporal.DayOfWeek'>: <function remove_ts_or_ds_to_date.<locals>.func>, <class 'sqlglot.expressions.temporal.DayOfYear'>: <function remove_ts_or_ds_to_date.<locals>.func>, <class 'sqlglot.expressions.aggregate.GroupConcat'>: <function MySQLGenerator.<lambda>>, <class 'sqlglot.expressions.core.ILike'>: <function no_ilike_sql>, <class 'sqlglot.expressions.json.JSONExtractScalar'>: <function arrow_json_extract_sql>, <class 'sqlglot.expressions.string.Length'>: <function length_or_char_length_sql>, <class 'sqlglot.expressions.aggregate.LogicalOr'>: <function rename_func.<locals>.<lambda>>, <class 'sqlglot.expressions.aggregate.LogicalAnd'>: <function rename_func.<locals>.<lambda>>, <class 'sqlglot.expressions.aggregate.Max'>: <function max_or_greatest>, <class 'sqlglot.expressions.aggregate.Min'>: <function min_or_least>, <class 'sqlglot.expressions.temporal.Month'>: <function remove_ts_or_ds_to_date.<locals>.func>, <class 'sqlglot.expressions.core.NullSafeEQ'>: <function MySQLGenerator.<lambda>>, <class 'sqlglot.expressions.core.NullSafeNEQ'>: <function MySQLGenerator.<lambda>>, <class 'sqlglot.expressions.string.NumberToStr'>: <function rename_func.<locals>.<lambda>>, <class 'sqlglot.expressions.query.Pivot'>: <function no_pivot_sql>, <class 'sqlglot.expressions.query.Select'>: <function preprocess.<locals>._to_sql>, <class 'sqlglot.expressions.string.StrPosition'>: <function MySQLGenerator.<lambda>>, <class 'sqlglot.expressions.temporal.StrToDate'>: <function _str_to_date_sql>, <class 'sqlglot.expressions.temporal.StrToTime'>: <function _str_to_date_sql>, <class 'sqlglot.expressions.string.Stuff'>: <function rename_func.<locals>.<lambda>>, <class 'sqlglot.expressions.query.TableSample'>: <function no_tablesample_sql>, <class 'sqlglot.expressions.temporal.TimeFromParts'>: <function rename_func.<locals>.<lambda>>, <class 'sqlglot.expressions.temporal.TimestampAdd'>: <function date_add_interval_sql.<locals>.func>, <class 'sqlglot.expressions.temporal.TimestampDiff'>: <function MySQLGenerator.<lambda>>, <class 'sqlglot.expressions.temporal.TimestampSub'>: <function date_add_interval_sql.<locals>.func>, <class 'sqlglot.expressions.temporal.TimeStrToUnix'>: <function rename_func.<locals>.<lambda>>, <class 'sqlglot.expressions.temporal.TimeStrToTime'>: <function MySQLGenerator.<lambda>>, <class 'sqlglot.expressions.temporal.TimeToStr'>: <function remove_ts_or_ds_to_date.<locals>.func>, <class 'sqlglot.expressions.string.Trim'>: <function trim_sql>, <class 'sqlglot.expressions.math.Trunc'>: <function rename_func.<locals>.<lambda>>, <class 'sqlglot.expressions.functions.TryCast'>: <function no_trycast_sql>, <class 'sqlglot.expressions.temporal.TsOrDsAdd'>: <function date_add_sql.<locals>.func>, <class 'sqlglot.expressions.temporal.TsOrDsDiff'>: <function MySQLGenerator.<lambda>>, <class 'sqlglot.expressions.temporal.TsOrDsToDate'>: <function _ts_or_ds_to_date_sql>, <class 'sqlglot.expressions.string.Unicode'>: <function MySQLGenerator.<lambda>>, <class 'sqlglot.expressions.temporal.UnixToTime'>: <function _unix_to_time_sql>, <class 'sqlglot.expressions.temporal.Week'>: <function remove_ts_or_ds_to_date.<locals>.func>, <class 'sqlglot.expressions.temporal.WeekOfYear'>: <function remove_ts_or_ds_to_date.<locals>.func>, <class 'sqlglot.expressions.temporal.Year'>: <function remove_ts_or_ds_to_date.<locals>.func>}
UNSIGNED_TYPE_MAPPING =
{<DType.UBIGINT: 'UBIGINT'>: 'BIGINT', <DType.UINT: 'UINT'>: 'INT', <DType.UMEDIUMINT: 'UMEDIUMINT'>: 'MEDIUMINT', <DType.USMALLINT: 'USMALLINT'>: 'SMALLINT', <DType.UTINYINT: 'UTINYINT'>: 'TINYINT', <DType.UDECIMAL: 'UDECIMAL'>: 'DECIMAL', <DType.UDOUBLE: 'UDOUBLE'>: 'DOUBLE'}
TIMESTAMP_TYPE_MAPPING =
{<DType.DATETIME2: 'DATETIME2'>: 'DATETIME', <DType.SMALLDATETIME: 'SMALLDATETIME'>: 'DATETIME', <DType.TIMESTAMP: 'TIMESTAMP'>: 'DATETIME', <DType.TIMESTAMPNTZ: 'TIMESTAMPNTZ'>: 'DATETIME', <DType.TIMESTAMPTZ: 'TIMESTAMPTZ'>: 'TIMESTAMP', <DType.TIMESTAMPLTZ: 'TIMESTAMPLTZ'>: 'TIMESTAMP'}
TYPE_MAPPING: ClassVar =
{<DType.NCHAR: 'NCHAR'>: 'CHAR', <DType.NVARCHAR: 'NVARCHAR'>: 'VARCHAR', <DType.INET: 'INET'>: 'INET', <DType.ROWVERSION: 'ROWVERSION'>: 'VARBINARY', <DType.UBIGINT: 'UBIGINT'>: 'BIGINT', <DType.UINT: 'UINT'>: 'INT', <DType.UMEDIUMINT: 'UMEDIUMINT'>: 'MEDIUMINT', <DType.USMALLINT: 'USMALLINT'>: 'SMALLINT', <DType.UTINYINT: 'UTINYINT'>: 'TINYINT', <DType.UDECIMAL: 'UDECIMAL'>: 'DECIMAL', <DType.UDOUBLE: 'UDOUBLE'>: 'DOUBLE', <DType.DATETIME2: 'DATETIME2'>: 'DATETIME', <DType.SMALLDATETIME: 'SMALLDATETIME'>: 'DATETIME', <DType.TIMESTAMP: 'TIMESTAMP'>: 'DATETIME', <DType.TIMESTAMPNTZ: 'TIMESTAMPNTZ'>: 'DATETIME', <DType.TIMESTAMPTZ: 'TIMESTAMPTZ'>: 'TIMESTAMP', <DType.TIMESTAMPLTZ: 'TIMESTAMPLTZ'>: 'TIMESTAMP'}
PROPERTIES_LOCATION: ClassVar =
{<class 'sqlglot.expressions.properties.AllowedValuesProperty'>: <PropertiesLocation.POST_SCHEMA: 'POST_SCHEMA'>, <class 'sqlglot.expressions.properties.AlgorithmProperty'>: <PropertiesLocation.POST_CREATE: 'POST_CREATE'>, <class 'sqlglot.expressions.properties.ApiProperty'>: <PropertiesLocation.POST_CREATE: 'POST_CREATE'>, <class 'sqlglot.expressions.properties.ApplicationProperty'>: <PropertiesLocation.POST_CREATE: 'POST_CREATE'>, <class 'sqlglot.expressions.properties.AutoIncrementProperty'>: <PropertiesLocation.POST_SCHEMA: 'POST_SCHEMA'>, <class 'sqlglot.expressions.properties.AutoRefreshProperty'>: <PropertiesLocation.POST_SCHEMA: 'POST_SCHEMA'>, <class 'sqlglot.expressions.properties.BackupProperty'>: <PropertiesLocation.POST_SCHEMA: 'POST_SCHEMA'>, <class 'sqlglot.expressions.properties.BlockCompressionProperty'>: <PropertiesLocation.POST_NAME: 'POST_NAME'>, <class 'sqlglot.expressions.properties.CalledOnNullInputProperty'>: <PropertiesLocation.POST_SCHEMA: 'POST_SCHEMA'>, <class 'sqlglot.expressions.properties.CatalogProperty'>: <PropertiesLocation.POST_CREATE: 'POST_CREATE'>, <class 'sqlglot.expressions.properties.CharacterSetProperty'>: <PropertiesLocation.POST_SCHEMA: 'POST_SCHEMA'>, <class 'sqlglot.expressions.properties.ChecksumProperty'>: <PropertiesLocation.POST_NAME: 'POST_NAME'>, <class 'sqlglot.expressions.properties.CollateProperty'>: <PropertiesLocation.POST_SCHEMA: 'POST_SCHEMA'>, <class 'sqlglot.expressions.properties.ComputeProperty'>: <PropertiesLocation.POST_CREATE: 'POST_CREATE'>, <class 'sqlglot.expressions.properties.CopyGrantsProperty'>: <PropertiesLocation.POST_SCHEMA: 'POST_SCHEMA'>, <class 'sqlglot.expressions.query.Cluster'>: <PropertiesLocation.POST_SCHEMA: 'POST_SCHEMA'>, <class 'sqlglot.expressions.properties.ClusteredByProperty'>: <PropertiesLocation.POST_SCHEMA: 'POST_SCHEMA'>, <class 'sqlglot.expressions.properties.ClusterProperty'>: <PropertiesLocation.POST_SCHEMA: 'POST_SCHEMA'>, <class 'sqlglot.expressions.properties.DistributedByProperty'>: <PropertiesLocation.POST_SCHEMA: 'POST_SCHEMA'>, <class 'sqlglot.expressions.properties.DuplicateKeyProperty'>: <PropertiesLocation.POST_SCHEMA: 'POST_SCHEMA'>, <class 'sqlglot.expressions.properties.DataBlocksizeProperty'>: <PropertiesLocation.POST_NAME: 'POST_NAME'>, <class 'sqlglot.expressions.properties.DatabaseProperty'>: <PropertiesLocation.POST_CREATE: 'POST_CREATE'>, <class 'sqlglot.expressions.properties.DataDeletionProperty'>: <PropertiesLocation.POST_SCHEMA: 'POST_SCHEMA'>, <class 'sqlglot.expressions.properties.DefinerProperty'>: <PropertiesLocation.POST_CREATE: 'POST_CREATE'>, <class 'sqlglot.expressions.properties.DictRange'>: <PropertiesLocation.POST_SCHEMA: 'POST_SCHEMA'>, <class 'sqlglot.expressions.properties.DictProperty'>: <PropertiesLocation.POST_SCHEMA: 'POST_SCHEMA'>, <class 'sqlglot.expressions.properties.DynamicProperty'>: <PropertiesLocation.POST_CREATE: 'POST_CREATE'>, <class 'sqlglot.expressions.properties.DistKeyProperty'>: <PropertiesLocation.POST_SCHEMA: 'POST_SCHEMA'>, <class 'sqlglot.expressions.properties.DistStyleProperty'>: <PropertiesLocation.POST_SCHEMA: 'POST_SCHEMA'>, <class 'sqlglot.expressions.properties.EmptyProperty'>: <PropertiesLocation.POST_SCHEMA: 'POST_SCHEMA'>, <class 'sqlglot.expressions.properties.EncodeProperty'>: <PropertiesLocation.POST_EXPRESSION: 'POST_EXPRESSION'>, <class 'sqlglot.expressions.properties.EngineProperty'>: <PropertiesLocation.POST_SCHEMA: 'POST_SCHEMA'>, <class 'sqlglot.expressions.properties.EnviromentProperty'>: <PropertiesLocation.POST_SCHEMA: 'POST_SCHEMA'>, <class 'sqlglot.expressions.properties.HandlerProperty'>: <PropertiesLocation.POST_SCHEMA: 'POST_SCHEMA'>, <class 'sqlglot.expressions.properties.ParameterStyleProperty'>: <PropertiesLocation.POST_SCHEMA: 'POST_SCHEMA'>, <class 'sqlglot.expressions.properties.ExecuteAsProperty'>: <PropertiesLocation.POST_SCHEMA: 'POST_SCHEMA'>, <class 'sqlglot.expressions.properties.ExternalProperty'>: <PropertiesLocation.POST_CREATE: 'POST_CREATE'>, <class 'sqlglot.expressions.properties.FallbackProperty'>: <PropertiesLocation.POST_NAME: 'POST_NAME'>, <class 'sqlglot.expressions.properties.FileFormatProperty'>: <PropertiesLocation.POST_WITH: 'POST_WITH'>, <class 'sqlglot.expressions.properties.FreespaceProperty'>: <PropertiesLocation.POST_NAME: 'POST_NAME'>, <class 'sqlglot.expressions.properties.GlobalProperty'>: <PropertiesLocation.POST_CREATE: 'POST_CREATE'>, <class 'sqlglot.expressions.properties.HeapProperty'>: <PropertiesLocation.POST_WITH: 'POST_WITH'>, <class 'sqlglot.expressions.properties.HybridProperty'>: <PropertiesLocation.POST_CREATE: 'POST_CREATE'>, <class 'sqlglot.expressions.properties.InheritsProperty'>: <PropertiesLocation.POST_SCHEMA: 'POST_SCHEMA'>, <class 'sqlglot.expressions.properties.IcebergProperty'>: <PropertiesLocation.POST_CREATE: 'POST_CREATE'>, <class 'sqlglot.expressions.properties.IncludeProperty'>: <PropertiesLocation.POST_SCHEMA: 'POST_SCHEMA'>, <class 'sqlglot.expressions.properties.InputModelProperty'>: <PropertiesLocation.POST_SCHEMA: 'POST_SCHEMA'>, <class 'sqlglot.expressions.properties.IsolatedLoadingProperty'>: <PropertiesLocation.POST_NAME: 'POST_NAME'>, <class 'sqlglot.expressions.properties.JournalProperty'>: <PropertiesLocation.POST_NAME: 'POST_NAME'>, <class 'sqlglot.expressions.properties.LanguageProperty'>: <PropertiesLocation.POST_SCHEMA: 'POST_SCHEMA'>, <class 'sqlglot.expressions.properties.LikeProperty'>: <PropertiesLocation.POST_SCHEMA: 'POST_SCHEMA'>, <class 'sqlglot.expressions.properties.LocationProperty'>: <PropertiesLocation.POST_SCHEMA: 'POST_SCHEMA'>, <class 'sqlglot.expressions.properties.LockProperty'>: <PropertiesLocation.POST_SCHEMA: 'POST_SCHEMA'>, <class 'sqlglot.expressions.properties.LockingProperty'>: <PropertiesLocation.POST_ALIAS: 'POST_ALIAS'>, <class 'sqlglot.expressions.properties.LogProperty'>: <PropertiesLocation.POST_NAME: 'POST_NAME'>, <class 'sqlglot.expressions.properties.MaskingProperty'>: <PropertiesLocation.POST_CREATE: 'POST_CREATE'>, <class 'sqlglot.expressions.properties.MaterializedProperty'>: <PropertiesLocation.POST_CREATE: 'POST_CREATE'>, <class 'sqlglot.expressions.properties.MergeBlockRatioProperty'>: <PropertiesLocation.POST_NAME: 'POST_NAME'>, <class 'sqlglot.expressions.properties.ModuleProperty'>: <PropertiesLocation.POST_SCHEMA: 'POST_SCHEMA'>, <class 'sqlglot.expressions.properties.NetworkProperty'>: <PropertiesLocation.POST_CREATE: 'POST_CREATE'>, <class 'sqlglot.expressions.properties.NoPrimaryIndexProperty'>: <PropertiesLocation.POST_EXPRESSION: 'POST_EXPRESSION'>, <class 'sqlglot.expressions.properties.OnProperty'>: <PropertiesLocation.POST_SCHEMA: 'POST_SCHEMA'>, <class 'sqlglot.expressions.properties.OnCommitProperty'>: <PropertiesLocation.POST_EXPRESSION: 'POST_EXPRESSION'>, <class 'sqlglot.expressions.query.Order'>: <PropertiesLocation.POST_SCHEMA: 'POST_SCHEMA'>, <class 'sqlglot.expressions.properties.OutputModelProperty'>: <PropertiesLocation.POST_SCHEMA: 'POST_SCHEMA'>, <class 'sqlglot.expressions.properties.PartitionedByProperty'>: <PropertiesLocation.UNSUPPORTED: 'UNSUPPORTED'>, <class 'sqlglot.expressions.properties.PartitionedOfProperty'>: <PropertiesLocation.POST_SCHEMA: 'POST_SCHEMA'>, <class 'sqlglot.expressions.constraints.PrimaryKey'>: <PropertiesLocation.POST_SCHEMA: 'POST_SCHEMA'>, <class 'sqlglot.expressions.properties.Property'>: <PropertiesLocation.POST_WITH: 'POST_WITH'>, <class 'sqlglot.expressions.properties.RefreshTriggerProperty'>: <PropertiesLocation.POST_SCHEMA: 'POST_SCHEMA'>, <class 'sqlglot.expressions.properties.RemoteWithConnectionModelProperty'>: <PropertiesLocation.POST_SCHEMA: 'POST_SCHEMA'>, <class 'sqlglot.expressions.properties.ReturnsProperty'>: <PropertiesLocation.POST_SCHEMA: 'POST_SCHEMA'>, <class 'sqlglot.expressions.properties.RollupProperty'>: <PropertiesLocation.UNSUPPORTED: 'UNSUPPORTED'>, <class 'sqlglot.expressions.properties.RowAccessProperty'>: <PropertiesLocation.UNSUPPORTED: 'UNSUPPORTED'>, <class 'sqlglot.expressions.properties.RowFormatProperty'>: <PropertiesLocation.POST_SCHEMA: 'POST_SCHEMA'>, <class 'sqlglot.expressions.properties.RowFormatDelimitedProperty'>: <PropertiesLocation.POST_SCHEMA: 'POST_SCHEMA'>, <class 'sqlglot.expressions.properties.RowFormatSerdeProperty'>: <PropertiesLocation.POST_SCHEMA: 'POST_SCHEMA'>, <class 'sqlglot.expressions.properties.SampleProperty'>: <PropertiesLocation.POST_SCHEMA: 'POST_SCHEMA'>, <class 'sqlglot.expressions.properties.SchemaCommentProperty'>: <PropertiesLocation.POST_SCHEMA: 'POST_SCHEMA'>, <class 'sqlglot.expressions.properties.SecureProperty'>: <PropertiesLocation.POST_CREATE: 'POST_CREATE'>, <class 'sqlglot.expressions.properties.SecurityIntegrationProperty'>: <PropertiesLocation.POST_CREATE: 'POST_CREATE'>, <class 'sqlglot.expressions.properties.SerdeProperties'>: <PropertiesLocation.POST_SCHEMA: 'POST_SCHEMA'>, <class 'sqlglot.expressions.ddl.Set'>: <PropertiesLocation.POST_SCHEMA: 'POST_SCHEMA'>, <class 'sqlglot.expressions.properties.SettingsProperty'>: <PropertiesLocation.POST_SCHEMA: 'POST_SCHEMA'>, <class 'sqlglot.expressions.properties.SetProperty'>: <PropertiesLocation.POST_CREATE: 'POST_CREATE'>, <class 'sqlglot.expressions.properties.SetConfigProperty'>: <PropertiesLocation.POST_SCHEMA: 'POST_SCHEMA'>, <class 'sqlglot.expressions.properties.SharingProperty'>: <PropertiesLocation.POST_EXPRESSION: 'POST_EXPRESSION'>, <class 'sqlglot.expressions.ddl.SequenceProperties'>: <PropertiesLocation.POST_EXPRESSION: 'POST_EXPRESSION'>, <class 'sqlglot.expressions.ddl.TriggerProperties'>: <PropertiesLocation.POST_EXPRESSION: 'POST_EXPRESSION'>, <class 'sqlglot.expressions.properties.SortKeyProperty'>: <PropertiesLocation.POST_SCHEMA: 'POST_SCHEMA'>, <class 'sqlglot.expressions.properties.SqlReadWriteProperty'>: <PropertiesLocation.POST_SCHEMA: 'POST_SCHEMA'>, <class 'sqlglot.expressions.properties.SqlSecurityProperty'>: <PropertiesLocation.POST_SCHEMA: 'POST_SCHEMA'>, <class 'sqlglot.expressions.properties.StabilityProperty'>: <PropertiesLocation.POST_SCHEMA: 'POST_SCHEMA'>, <class 'sqlglot.expressions.properties.StorageHandlerProperty'>: <PropertiesLocation.POST_SCHEMA: 'POST_SCHEMA'>, <class 'sqlglot.expressions.properties.StreamingTableProperty'>: <PropertiesLocation.POST_CREATE: 'POST_CREATE'>, <class 'sqlglot.expressions.properties.StrictProperty'>: <PropertiesLocation.POST_SCHEMA: 'POST_SCHEMA'>, <class 'sqlglot.expressions.properties.Tags'>: <PropertiesLocation.POST_WITH: 'POST_WITH'>, <class 'sqlglot.expressions.properties.TemporaryProperty'>: <PropertiesLocation.POST_CREATE: 'POST_CREATE'>, <class 'sqlglot.expressions.properties.ToTableProperty'>: <PropertiesLocation.POST_SCHEMA: 'POST_SCHEMA'>, <class 'sqlglot.expressions.properties.TransientProperty'>: <PropertiesLocation.UNSUPPORTED: 'UNSUPPORTED'>, <class 'sqlglot.expressions.properties.TransformModelProperty'>: <PropertiesLocation.POST_SCHEMA: 'POST_SCHEMA'>, <class 'sqlglot.expressions.ddl.MergeTreeTTL'>: <PropertiesLocation.POST_SCHEMA: 'POST_SCHEMA'>, <class 'sqlglot.expressions.properties.UnloggedProperty'>: <PropertiesLocation.POST_CREATE: 'POST_CREATE'>, <class 'sqlglot.expressions.properties.UsingProperty'>: <PropertiesLocation.POST_EXPRESSION: 'POST_EXPRESSION'>, <class 'sqlglot.expressions.properties.UsingTemplateProperty'>: <PropertiesLocation.POST_SCHEMA: 'POST_SCHEMA'>, <class 'sqlglot.expressions.properties.ViewAttributeProperty'>: <PropertiesLocation.POST_SCHEMA: 'POST_SCHEMA'>, <class 'sqlglot.expressions.properties.VirtualProperty'>: <PropertiesLocation.POST_CREATE: 'POST_CREATE'>, <class 'sqlglot.expressions.properties.VolatileProperty'>: <PropertiesLocation.UNSUPPORTED: 'UNSUPPORTED'>, <class 'sqlglot.expressions.properties.WithDataProperty'>: <PropertiesLocation.POST_EXPRESSION: 'POST_EXPRESSION'>, <class 'sqlglot.expressions.properties.WithJournalTableProperty'>: <PropertiesLocation.POST_NAME: 'POST_NAME'>, <class 'sqlglot.expressions.properties.WithProcedureOptions'>: <PropertiesLocation.POST_SCHEMA: 'POST_SCHEMA'>, <class 'sqlglot.expressions.properties.WithSchemaBindingProperty'>: <PropertiesLocation.POST_SCHEMA: 'POST_SCHEMA'>, <class 'sqlglot.expressions.properties.WithSystemVersioningProperty'>: <PropertiesLocation.POST_SCHEMA: 'POST_SCHEMA'>, <class 'sqlglot.expressions.properties.ForceProperty'>: <PropertiesLocation.POST_CREATE: 'POST_CREATE'>, <class 'sqlglot.expressions.properties.PartitionByRangeProperty'>: <PropertiesLocation.POST_SCHEMA: 'POST_SCHEMA'>, <class 'sqlglot.expressions.properties.PartitionByListProperty'>: <PropertiesLocation.POST_SCHEMA: 'POST_SCHEMA'>}
CHAR_CAST_MAPPING: ClassVar =
{<DType.LONGTEXT: 'LONGTEXT'>: 'CHAR', <DType.LONGBLOB: 'LONGBLOB'>: 'CHAR', <DType.MEDIUMBLOB: 'MEDIUMBLOB'>: 'CHAR', <DType.MEDIUMTEXT: 'MEDIUMTEXT'>: 'CHAR', <DType.TEXT: 'TEXT'>: 'CHAR', <DType.TINYBLOB: 'TINYBLOB'>: 'CHAR', <DType.TINYTEXT: 'TINYTEXT'>: 'CHAR', <DType.VARCHAR: 'VARCHAR'>: 'CHAR'}
SIGNED_CAST_MAPPING: ClassVar =
{<DType.BIGINT: 'BIGINT'>: 'SIGNED', <DType.BOOLEAN: 'BOOLEAN'>: 'SIGNED', <DType.INT: 'INT'>: 'SIGNED', <DType.SMALLINT: 'SMALLINT'>: 'SIGNED', <DType.TINYINT: 'TINYINT'>: 'SIGNED', <DType.MEDIUMINT: 'MEDIUMINT'>: 'SIGNED'}
CAST_MAPPING =
{<DType.LONGTEXT: 'LONGTEXT'>: 'CHAR', <DType.LONGBLOB: 'LONGBLOB'>: 'CHAR', <DType.MEDIUMBLOB: 'MEDIUMBLOB'>: 'CHAR', <DType.MEDIUMTEXT: 'MEDIUMTEXT'>: 'CHAR', <DType.TEXT: 'TEXT'>: 'CHAR', <DType.TINYBLOB: 'TINYBLOB'>: 'CHAR', <DType.TINYTEXT: 'TINYTEXT'>: 'CHAR', <DType.VARCHAR: 'VARCHAR'>: 'CHAR', <DType.BIGINT: 'BIGINT'>: 'SIGNED', <DType.BOOLEAN: 'BOOLEAN'>: 'SIGNED', <DType.INT: 'INT'>: 'SIGNED', <DType.SMALLINT: 'SMALLINT'>: 'SIGNED', <DType.TINYINT: 'TINYINT'>: 'SIGNED', <DType.MEDIUMINT: 'MEDIUMINT'>: 'SIGNED', <DType.UBIGINT: 'UBIGINT'>: 'UNSIGNED'}
RESERVED_KEYWORDS =
{'from', 'io_after_gtids', 'and', 'cume_dist', 'sql', 'unique', 'window', 'between', 'write', 'last_value', 'utc_date', 'procedure', 'cursor', 'not', 'first_value', 'lead', 'char', 'iterate', 'localtime', 'binary', 'if', 'virtual', 'starting', 'add', 'int3', 'join', 'rank', 'distinctrow', 'references', 'partition', 'master_bind', 'int1', 'require', 'cube', 'utc_time', 'by', 'range', 'having', 'ntile', 'desc', 'cascade', 'rlike', 'check', 'recursive', 'convert', 'lock', 'sql_big_result', 'float8', 'localtimestamp', 'when', 'fetch', 'distinct', 'ignore', 'schemas', 'minute_second', 'utc_timestamp', 'varying', 'outfile', 'modifies', 'load', 'varchar', 'asc', 'while', 'column', 'unsigned', 'inout', 'repeat', 'separator', 'longblob', 'restrict', 'revoke', 'zerofill', 'out', 'for', 'left', 'in', 'float', 'sqlwarning', 'kill', 'both', 'regexp', 'linear', 'sqlstate', 'tinyblob', 'limit', 'call', 'show', 'spatial', 'stored', 'day_hour', 'set', 'percent_rank', 'default', 'insert', 'usage', 'dense_rank', 'low_priority', 'double', 'numeric', 'update', 'union', 'lines', 'day_microsecond', 'real', 'insensitive', 'before', 'replace', 'varbinary', 'xor', 'straight_join', 'true', 'ssl', 'accessible', 'index', 'smallint', 'delete', 'minute_microsecond', 'rename', 'order', 'optimize', 'right', 'nth_value', 'hour_second', 'over', 'day_minute', 'null', 'mediumtext', 'is', 'intersect', 'trigger', 'blob', 'middleint', 'option', 'int4', 'table', 'infile', 'float4', 'sqlexception', 'mod', 'then', 'or', 'high_priority', 'signal', 'select', 'sensitive', 'keys', 'tinytext', 'undo', 'unlock', 'optionally', 'drop', 'false', 'alter', 'master_ssl_verify_server_cert', 'bigint', 'optimizer_costs', 'io_before_gtids', 'mediumblob', 'exit', 'system', 'values', 'of', 'primary', 'analyze', 'day_second', 'int', 'all', 'continue', 'grant', 'current_user', 'div', 'schema', 'except', 'databases', 'dec', 'each', 'terminated', 'lag', 'grouping', 'sql_small_result', 'database', 'integer', 'constraint', 'leave', 'no_write_to_binlog', 'read', 'loop', 'on', 'elseif', 'int2', 'get', 'sql_calc_found_rows', 'release', 'collate', 'explain', 'into', 'condition', 'long', 'declare', 'match', 'using', 'hour_microsecond', 'int8', 'mediumint', 'read_write', 'interval', 'force', 'varcharacter', 'group', 'escaped', 'hour_minute', 'natural', 'maxvalue', 'row', 'rows', 'outer', 'exists', 'describe', 'create', 'leading', 'cross', 'where', 'change', 'asensitive', 'specific', 'generated', 'precision', 'resignal', 'inner', 'current_date', 'dual', 'delayed', 'second_microsecond', 'empty', 'else', 'tinyint', 'json_table', 'use', 'as', 'decimal', 'return', 'foreign', 'current_timestamp', 'key', 'function', 'to', 'character', 'lateral', 'fulltext', 'enclosed', 'current_time', 'trailing', 'case', 'with', 'purge', 'like', 'longtext', 'row_number', 'reads', 'groups', 'deterministic', 'year_month'}
def
makeinterval_sql( self: MySQLGenerator, expression: sqlglot.expressions.temporal.MakeInterval) -> str:
596 def makeinterval_sql(self: MySQLGenerator, expression: exp.MakeInterval) -> str: 597 intervals: list[exp.Interval] = [] 598 for arg_key, value in expression.args.items(): 599 if value is None: 600 continue 601 602 if isinstance(value, exp.Kwarg): 603 unit_name = _MAKE_INTERVAL_UNIT_ALIASES.get( 604 value.this.name.lower(), value.this.name.lower() 605 ) 606 value = value.expression 607 else: 608 unit_name = arg_key 609 610 intervals.append(exp.Interval(this=value.copy(), unit=exp.var(unit_name.upper()))) 611 612 if not intervals: 613 return self.function_fallback_sql(expression) 614 615 parent = expression.parent 616 sep = " - " if isinstance(parent, exp.Sub) and parent.expression is expression else " + " 617 618 return sep.join(self.sql(interval) for interval in intervals)
def
locate_properties( self, properties: sqlglot.expressions.properties.Properties) -> collections.defaultdict:
620 def locate_properties(self, properties: exp.Properties) -> defaultdict: 621 locations = super().locate_properties(properties) 622 623 # MySQL puts SQL SECURITY before VIEW but after the schema for functions/procedures 624 if isinstance(create := properties.parent, exp.Create) and create.kind == "VIEW": 625 post_schema = locations[exp.Properties.Location.POST_SCHEMA] 626 for i, p in enumerate(post_schema): 627 if isinstance(p, exp.SqlSecurityProperty): 628 post_schema.pop(i) 629 locations[self.SQL_SECURITY_VIEW_LOCATION].append(p) 630 break 631 632 return locations
def
computedcolumnconstraint_sql( self, expression: sqlglot.expressions.constraints.ComputedColumnConstraint) -> str:
660 def datatype_sql(self, expression: exp.DataType) -> str: 661 if ( 662 self.VARCHAR_REQUIRES_SIZE 663 and expression.is_type(exp.DType.VARCHAR) 664 and not expression.expressions 665 ): 666 # `VARCHAR` must always have a size - if it doesn't, we always generate `TEXT` 667 return "TEXT" 668 669 # https://dev.mysql.com/doc/refman/8.0/en/numeric-type-syntax.html 670 result = super().datatype_sql(expression) 671 if expression.this in self.UNSIGNED_TYPE_MAPPING: 672 result = f"{result} UNSIGNED" 673 674 return result
def
cast_sql( self, expression: sqlglot.expressions.functions.Cast, safe_prefix: str | None = None) -> str:
679 def cast_sql(self, expression: exp.Cast, safe_prefix: str | None = None) -> str: 680 if expression.to.this in self.TIMESTAMP_FUNC_TYPES: 681 return self.func("TIMESTAMP", expression.this) 682 683 to = self.CAST_MAPPING.get(expression.to.this) 684 685 if to: 686 expression.to.set("this", to) 687 return super().cast_sql(expression)
689 def show_sql(self, expression: exp.Show) -> str: 690 this = f" {expression.name}" 691 full = " FULL" if expression.args.get("full") else "" 692 global_ = " GLOBAL" if expression.args.get("global_") else "" 693 694 target = self.sql(expression, "target") 695 target = f" {target}" if target else "" 696 if expression.name in ("COLUMNS", "INDEX"): 697 target = f" FROM{target}" 698 elif expression.name == "GRANTS": 699 target = f" FOR{target}" 700 elif expression.name in ("LINKS", "PARTITIONS"): 701 target = f" ON{target}" if target else "" 702 elif expression.name == "PROJECTIONS": 703 target = f" ON TABLE{target}" if target else "" 704 705 db = self._prefixed_sql("FROM", expression, "db") 706 707 like = self._prefixed_sql("LIKE", expression, "like") 708 where = self.sql(expression, "where") 709 710 types = self.expressions(expression, key="types") 711 types = f" {types}" if types else types 712 query = self._prefixed_sql("FOR QUERY", expression, "query") 713 714 if expression.name == "PROFILE": 715 offset = self._prefixed_sql("OFFSET", expression, "offset") 716 limit = self._prefixed_sql("LIMIT", expression, "limit") 717 else: 718 offset = "" 719 limit = self._oldstyle_limit_sql(expression) 720 721 log = self._prefixed_sql("IN", expression, "log") 722 position = self._prefixed_sql("FROM", expression, "position") 723 724 channel = self._prefixed_sql("FOR CHANNEL", expression, "channel") 725 726 if expression.name == "ENGINE": 727 mutex_or_status = " MUTEX" if expression.args.get("mutex") else " STATUS" 728 else: 729 mutex_or_status = "" 730 731 for_table = self._prefixed_sql("FOR TABLE", expression, "for_table") 732 for_group = self._prefixed_sql("FOR GROUP", expression, "for_group") 733 for_user = self._prefixed_sql("FOR USER", expression, "for_user") 734 for_role = self._prefixed_sql("FOR ROLE", expression, "for_role") 735 into_outfile = self._prefixed_sql("INTO OUTFILE", expression, "into_outfile") 736 json = " JSON" if expression.args.get("json") else "" 737 738 return f"SHOW{full}{global_}{this}{json}{target}{for_table}{types}{db}{query}{log}{position}{channel}{mutex_or_status}{like}{where}{offset}{limit}{for_group}{for_user}{for_role}{into_outfile}"
def
alterrename_sql( self, expression: sqlglot.expressions.ddl.AlterRename, include_to: bool = True) -> str:
740 def alterrename_sql(self, expression: exp.AlterRename, include_to: bool = True) -> str: 741 """To avoid TO keyword in ALTER ... RENAME statements. 742 It's moved from Doris, because it's the same for all MySQL, Doris, and StarRocks. 743 """ 744 return super().alterrename_sql(expression, include_to=False)
To avoid TO keyword in ALTER ... RENAME statements. It's moved from Doris, because it's the same for all MySQL, Doris, and StarRocks.
766 def timestamptrunc_sql(self, expression: exp.TimestampTrunc) -> str: 767 unit = expression.args.get("unit") 768 if isinstance(unit, exp.WeekStart): 769 unit = exp.var(self.weekstart_name(unit)) 770 771 # Pick an old-enough date to avoid negative timestamp diffs 772 start_ts = "'0000-01-01 00:00:00'" 773 774 # Source: https://stackoverflow.com/a/32955740 775 timestamp_diff = build_date_delta(exp.TimestampDiff)([unit, start_ts, expression.this]) 776 interval = exp.Interval(this=timestamp_diff, unit=unit) 777 dateadd = build_date_delta_with_interval(exp.DateAdd)([start_ts, interval]) 778 779 return self.sql(dateadd)
@unsupported_args('this')
def
currentschema_sql(self, expression: sqlglot.expressions.functions.CurrentSchema) -> str:
def
partitionbyrangeproperty_sql( self, expression: sqlglot.expressions.properties.PartitionByRangeProperty) -> str:
def
partitionbylistproperty_sql( self, expression: sqlglot.expressions.properties.PartitionByListProperty) -> str:
Inherited Members
- sqlglot.generator.Generator
- Generator
- WINDOW_FUNCS_WITH_NULL_ORDERING
- IGNORE_NULLS_IN_FUNC
- IGNORE_NULLS_BEFORE_ORDER
- EXCEPT_INTERSECT_SUPPORT_ALL_CLAUSE
- CREATE_FUNCTION_RETURN_AS
- MATCHED_BY_SOURCE
- SUPPORTS_MERGE_WHERE
- SINGLE_STRING_INTERVAL
- AUTO_REFRESH_BARE_INTERVALS
- RENAME_TABLE_WITH_DB
- GROUPINGS_SEP
- INDEX_ON
- INOUT_SEPARATOR
- DIRECTED_JOINS
- QUERY_HINTS
- IS_BOOL_ALLOWED
- LIMIT_IS_TOP
- RETURNING_END
- EXTRACT_ALLOWS_QUOTES
- TZ_TO_WITH_TIME_ZONE
- ALTER_TABLE_INCLUDE_COLUMN_KEYWORD
- UNNEST_WITH_ORDINALITY
- SEMI_ANTI_JOIN_WITH_SIDE
- COMPUTED_COLUMN_WITH_TYPE
- SUPPORTS_TABLE_COPY
- TABLESAMPLE_REQUIRES_PARENS
- TABLESAMPLE_SIZE_IS_ROWS
- TABLESAMPLE_KEYWORDS
- TABLESAMPLE_WITH_METHOD
- TABLESAMPLE_SEED_KEYWORD
- HISTORICAL_DATA_POST_ALIAS
- COLLATE_IS_FUNC
- DATA_TYPE_SPECIFIERS_ALLOWED
- ENSURE_BOOLS
- CTE_RECURSIVE_KEYWORD_REQUIRED
- SUPPORTS_SINGLE_ARG_CONCAT
- SUPPORTS_TABLE_ALIAS_COLUMNS
- SUPPORTS_NAMED_CTE_COLUMNS
- UNPIVOT_ALIASES_ARE_IDENTIFIERS
- PIVOT_ALIAS_WITH_AS
- INSERT_OVERWRITE
- SUPPORTS_SELECT_INTO
- SUPPORTS_UNLOGGED_TABLES
- SUPPORTS_CREATE_TABLE_LIKE
- LIKE_PROPERTY_INSIDE_SCHEMA
- MULTI_ARG_DISTINCT
- JSON_PATH_SINGLE_QUOTE_ESCAPE
- JSON_PATH_KEY_QUOTED_FORCES_BRACKETS
- SUPPORTED_JSON_PATH_PARTS
- CAN_IMPLEMENT_ARRAY_ANY
- SUPPORTS_WINDOW_EXCLUDE
- SET_OP_MODIFIERS
- COPY_PARAMS_ARE_WRAPPED
- COPY_PARAMS_EQ_REQUIRED
- COPY_HAS_INTO_KEYWORD
- UNICODE_SUBSTITUTE
- STAR_EXCEPT
- HEX_FUNC
- WITH_PROPERTIES_PREFIX
- QUOTE_JSON_PATH
- SUPPORTS_EXPLODING_PROJECTIONS
- ARRAY_CONCAT_IS_VAR_LEN
- SUPPORTS_CONVERT_TIMEZONE
- SUPPORTS_UNIX_SECONDS
- ALTER_SET_WRAPPED
- NORMALIZE_EXTRACT_DATE_PARTS
- ARRAY_SIZE_NAME
- ALTER_SET_TYPE
- ARRAY_SIZE_DIM_REQUIRED
- SUPPORTS_BETWEEN_FLAGS
- SUPPORTS_LIKE_QUANTIFIERS
- MATCH_AGAINST_TABLE_PREFIX
- SET_ASSIGNMENT_REQUIRES_VARIABLE_KEYWORD
- DECLARE_DEFAULT_ASSIGNMENT
- STAR_EXCLUDE_REQUIRES_DERIVED_TABLE
- SUPPORTS_DROP_ALTER_ICEBERG_PROPERTY
- UNSUPPORTED_TYPES
- TYPE_PARAM_SETTINGS
- TIME_PART_SINGULARS
- TOKEN_MAPPING
- STRUCT_DELIMITER
- PARAMETER_TOKEN
- NAMED_PLACEHOLDER_TOKEN
- EXPRESSION_PRECEDES_PROPERTIES_CREATABLES
- WITH_SEPARATED_COMMENTS
- EXCLUDE_COMMENTS
- UNWRAPPED_INTERVAL_VALUES
- PARAMETERIZABLE_TEXT_TYPES
- EXPRESSIONS_WITHOUT_NESTED_CTES
- RESPECT_IGNORE_NULLS_UNSUPPORTED_EXPRESSIONS
- SAFE_JSON_PATH_KEY_RE
- SENTINEL_LINE_BREAK
- pretty
- identify
- normalize
- pad
- unsupported_level
- max_unsupported
- leading_comma
- max_text_width
- comments
- dialect
- normalize_functions
- unsupported_messages
- generate
- preprocess
- unsupported
- sep
- seg
- sanitize_comment
- maybe_comment
- wrap
- no_identify
- normalize_func
- indent
- sql
- uncache_sql
- cache_sql
- characterset_sql
- column_parts
- column_sql
- pseudocolumn_sql
- columnposition_sql
- columndef_sql
- columnconstraint_sql
- autoincrementcolumnconstraint_sql
- compresscolumnconstraint_sql
- generatedasidentitycolumnconstraint_sql
- generatedasrowcolumnconstraint_sql
- periodforsystemtimeconstraint_sql
- notnullcolumnconstraint_sql
- primarykeycolumnconstraint_sql
- uniquecolumnconstraint_sql
- inoutcolumnconstraint_sql
- createable_sql
- create_sql
- sequenceproperties_sql
- triggerproperties_sql
- triggerreferencing_sql
- triggerevent_sql
- clone_sql
- describe_sql
- heredoc_sql
- prepend_ctes
- with_sql
- cte_sql
- tablealias_sql
- bitstring_sql
- hexstring_sql
- bytestring_sql
- unicodestring_sql
- rawstring_sql
- datatypeparam_sql
- datatype_param_bound_limiter
- directory_sql
- delete_sql
- drop_sql
- set_operation
- set_operations
- fetch_sql
- limitoptions_sql
- filter_sql
- hint_sql
- indexparameters_sql
- index_sql
- dynamicidentifier_sql
- identifier_sql
- hex_sql
- lowerhex_sql
- inputoutputformat_sql
- national_sql
- properties_sql
- root_properties
- properties
- with_properties
- property_name
- property_sql
- uuidproperty_sql
- likeproperty_sql
- fallbackproperty_sql
- journalproperty_sql
- freespaceproperty_sql
- checksumproperty_sql
- mergeblockratioproperty_sql
- moduleproperty_sql
- datablocksizeproperty_sql
- blockcompressionproperty_sql
- isolatedloadingproperty_sql
- partitionboundspec_sql
- partitionedofproperty_sql
- lockingproperty_sql
- withdataproperty_sql
- withsystemversioningproperty_sql
- insert_sql
- introducer_sql
- kill_sql
- pseudotype_sql
- objectidentifier_sql
- onconflict_sql
- returning_sql
- rowformatdelimitedproperty_sql
- withtablehint_sql
- indextablehint_sql
- historicaldata_sql
- table_parts
- table_sql
- tablefromrows_sql
- tablesample_sql
- pivot_sql
- version_sql
- tuple_sql
- update_sql
- values_sql
- var_sql
- into_sql
- from_sql
- groupingsets_sql
- rollup_sql
- rollupindex_sql
- rollupproperty_sql
- cube_sql
- group_sql
- having_sql
- connect_sql
- prior_sql
- join_sql
- lambda_sql
- lateral_op
- lateral_sql
- limit_sql
- offset_sql
- setitem_sql
- set_sql
- queryband_sql
- pragma_sql
- lock_sql
- literal_sql
- escape_str
- loaddata_sql
- null_sql
- boolean_sql
- booland_sql
- boolor_sql
- order_sql
- withfill_sql
- cluster_sql
- clusterproperty_sql
- distribute_sql
- sort_sql
- ordered_sql
- matchrecognizemeasure_sql
- matchrecognize_sql
- query_modifiers
- options_modifier
- forclause_sql
- queryoption_sql
- offset_limit_modifiers
- after_limit_modifiers
- select_sql
- schema_sql
- schema_columns_sql
- star_sql
- parameter_sql
- sessionparameter_sql
- placeholder_sql
- subquery_sql
- qualify_sql
- unnest_sql
- prewhere_sql
- where_sql
- window_sql
- partition_by_sql
- windowspec_sql
- withingroup_sql
- between_sql
- bracket_offset_expressions
- bracket_sql
- all_sql
- any_sql
- exists_sql
- case_sql
- constraint_sql
- nextvaluefor_sql
- trim_sql
- convert_concat_args
- concat_sql
- concatws_sql
- check_sql
- foreignkey_sql
- primarykey_sql
- timeserieskey_sql
- if_sql
- matchagainst_sql
- jsonkeyvalue_sql
- jsonpath_sql
- json_path_part
- formatjson_sql
- formatphrase_sql
- jsonarray_sql
- jsonarrayagg_sql
- jsoncolumndef_sql
- jsonschema_sql
- jsontable_sql
- openjsoncolumndef_sql
- openjson_sql
- in_sql
- in_unnest_op
- interval_sql
- return_sql
- reference_sql
- anonymous_sql
- paren_sql
- neg_sql
- not_sql
- alias_sql
- pivotalias_sql
- aliases_sql
- atindex_sql
- fromtimezone_sql
- fromiso8601date_sql
- fromiso8601timestamp_sql
- fromiso8601timestampnanos_sql
- add_sql
- and_sql
- or_sql
- xor_sql
- connector_sql
- bitwiseand_sql
- bitwiseleftshift_sql
- bitwisenot_sql
- bitwiseor_sql
- bitwiserightshift_sql
- bitwisexor_sql
- strtotime_sql
- strtodate_sql
- parsedatetime_sql
- currentdate_sql
- collate_sql
- command_sql
- comment_sql
- mergetreettlaction_sql
- mergetreettl_sql
- transaction_sql
- commit_sql
- rollback_sql
- modifycolumn_sql
- alterindex_sql
- alterdiststyle_sql
- altersortkey_sql
- renamecolumn_sql
- alterset_sql
- alter_sql
- altersession_sql
- add_column_sql
- droppartition_sql
- dropprimarykey_sql
- addconstraint_sql
- addpartition_sql
- distinct_sql
- respectnulls_sql
- havingmax_sql
- intdiv_sql
- div_sql
- safedivide_sql
- overlaps_sql
- distance_sql
- distancend_sql
- dot_sql
- eq_sql
- propertyeq_sql
- escape_sql
- glob_sql
- gt_sql
- gte_sql
- is_sql
- like_sql
- ilike_sql
- match_sql
- similarto_sql
- lt_sql
- lte_sql
- mod_sql
- mul_sql
- neq_sql
- nullsafeeq_sql
- nullsafeneq_sql
- sub_sql
- trycast_sql
- jsoncast_sql
- try_sql
- log_sql
- use_sql
- binary
- ceil_floor
- function_fallback_sql
- func
- format_args
- too_wide
- format_time
- expressions
- op_expressions
- naked_property
- tag_sql
- token_sql
- userdefinedfunction_sql
- macrooverloads_sql
- macrooverload_sql
- joinhint_sql
- kwarg_sql
- when_sql
- whens_sql
- merge_sql
- tochar_sql
- tonumber_sql
- dictproperty_sql
- dictrange_sql
- dictsubproperty_sql
- duplicatekeyproperty_sql
- uniquekeyproperty_sql
- distributedbyproperty_sql
- oncluster_sql
- clusteredbyproperty_sql
- anyvalue_sql
- querytransform_sql
- indexconstraintoption_sql
- checkcolumnconstraint_sql
- indexcolumnconstraint_sql
- nvl2_sql
- comprehension_sql
- columnprefix_sql
- opclass_sql
- predict_sql
- generateembedding_sql
- generatetext_sql
- generatetable_sql
- generatebool_sql
- generateint_sql
- generatedouble_sql
- mltranslate_sql
- mlforecast_sql
- aiforecast_sql
- featuresattime_sql
- vectorsearch_sql
- forin_sql
- refresh_sql
- toarray_sql
- tsordstotime_sql
- tsordstotimestamp_sql
- tsordstodatetime_sql
- tsordstodate_sql
- unixdate_sql
- lastday_sql
- dateadd_sql
- arrayany_sql
- struct_sql
- truncatetable_sql
- convert_sql
- copyparameter_sql
- credentials_sql
- copy_sql
- semicolon_sql
- datadeletionproperty_sql
- maskingpolicycolumnconstraint_sql
- gapfill_sql
- scope_resolution
- scoperesolution_sql
- parsejson_sql
- rand_sql
- changes_sql
- pad_sql
- summarize_sql
- explodinggenerateseries_sql
- json_sql
- jsonvalue_sql
- skipjsoncolumn_sql
- conditionalinsert_sql
- multitableinserts_sql
- oncondition_sql
- jsonextractquote_sql
- jsonexists_sql
- arrayagg_sql
- slice_sql
- apply_sql
- grant_sql
- revoke_sql
- grantprivilege_sql
- grantprincipal_sql
- columns_sql
- overlay_sql
- todouble_sql
- string_sql
- median_sql
- overflowtruncatebehavior_sql
- unixseconds_sql
- arraysize_sql
- attach_sql
- detach_sql
- attachoption_sql
- watermarkcolumnconstraint_sql
- encodeproperty_sql
- includeproperty_sql
- xmlelement_sql
- xmlkeyvalueoption_sql
- partitionbyrangepropertydynamic_sql
- unpivotcolumns_sql
- analyzesample_sql
- analyzestatistics_sql
- analyzehistogram_sql
- analyzedelete_sql
- analyzelistchainedrows_sql
- analyzevalidate_sql
- analyze_sql
- xmltable_sql
- xmlnamespace_sql
- export_sql
- declare_sql
- declareitem_sql
- recursivewithsearch_sql
- parameterizedagg_sql
- anonymousaggfunc_sql
- combinedaggfunc_sql
- combinedparameterizedagg_sql
- install_sql
- get_put_sql
- translatecharacters_sql
- decodecase_sql
- semanticview_sql
- getextract_sql
- datefromunixdate_sql
- space_sql
- buildproperty_sql
- refreshtriggerproperty_sql
- modelattribute_sql
- directorystage_sql
- uuid_sql
- initcap_sql
- localtime_sql
- localtimestamp_sql
- weekstart_name
- weekstart_sql
- chr_sql
- block_sql
- functionspecification_sql
- storedprocedure_sql
- ifblock_sql
- whileblock_sql
- execute_sql
- executesql_sql
- altermodifysqlsecurity_sql
- usingproperty_sql
- renameindex_sql