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 rename_func, 21 strposition_sql, 22 unit_to_var, 23 trim_sql, 24 timestrtotime_sql, 25) 26from sqlglot.generator import unsupported_args 27from collections import defaultdict 28 29 30def _date_trunc_sql(self: MySQLGenerator, expression: exp.DateTrunc) -> str: 31 expr = self.sql(expression, "this") 32 unit = expression.text("unit").upper() 33 34 if unit == "WEEK": 35 concat = f"CONCAT(YEAR({expr}), ' ', WEEK({expr}, 1), ' 1')" 36 date_format = "%Y %u %w" 37 elif unit == "MONTH": 38 concat = f"CONCAT(YEAR({expr}), ' ', MONTH({expr}), ' 1')" 39 date_format = "%Y %c %e" 40 elif unit == "QUARTER": 41 concat = f"CONCAT(YEAR({expr}), ' ', QUARTER({expr}) * 3 - 2, ' 1')" 42 date_format = "%Y %c %e" 43 elif unit == "YEAR": 44 concat = f"CONCAT(YEAR({expr}), ' 1 1')" 45 date_format = "%Y %c %e" 46 else: 47 if unit != "DAY": 48 self.unsupported(f"Unexpected interval unit: {unit}") 49 return self.func("DATE", expr) 50 51 return self.func("STR_TO_DATE", concat, f"'{date_format}'") 52 53 54def _str_to_date_sql( 55 self: MySQLGenerator, expression: exp.StrToDate | exp.StrToTime | exp.TsOrDsToDate 56) -> str: 57 return self.func("STR_TO_DATE", expression.this, self.format_time(expression)) 58 59 60def _unix_to_time_sql(self: MySQLGenerator, expression: exp.UnixToTime) -> str: 61 scale = expression.args.get("scale") 62 timestamp = expression.this 63 64 if scale in (None, exp.UnixToTime.SECONDS): 65 return self.func("FROM_UNIXTIME", timestamp, self.format_time(expression)) 66 67 return self.func( 68 "FROM_UNIXTIME", 69 exp.Div(this=timestamp, expression=exp.func("POW", 10, scale)), 70 self.format_time(expression), 71 ) 72 73 74def date_add_sql( 75 kind: str, 76) -> t.Callable[[generator.Generator, exp.Expr], str]: 77 def func(self: generator.Generator, expression: exp.Expr) -> str: 78 return self.func( 79 f"DATE_{kind}", 80 expression.this, 81 exp.Interval(this=expression.expression, unit=unit_to_var(expression)), 82 ) 83 84 return func 85 86 87_MAKE_INTERVAL_UNIT_ALIASES = { 88 "years": "year", 89 "months": "month", 90 "weeks": "week", 91 "days": "day", 92 "hours": "hour", 93 "minutes": "minute", 94 "mins": "minute", 95 "seconds": "second", 96 "secs": "second", 97} 98 99 100def _ts_or_ds_to_date_sql(self: MySQLGenerator, expression: exp.TsOrDsToDate) -> str: 101 time_format = expression.args.get("format") 102 return _str_to_date_sql(self, expression) if time_format else self.func("DATE", expression.this) 103 104 105def _remove_ts_or_ds_to_date( 106 to_sql: t.Callable[[MySQLGenerator, exp.Expr], str] | None = None, 107 args: tuple[str, ...] = ("this",), 108) -> t.Callable[[MySQLGenerator, exp.Func], str]: 109 def func(self: MySQLGenerator, expression: exp.Func) -> str: 110 for arg_key in args: 111 arg = expression.args.get(arg_key) 112 if isinstance(arg, (exp.TsOrDsToDate, exp.TsOrDsToTimestamp)) and not arg.args.get( 113 "format" 114 ): 115 expression.set(arg_key, arg.this) 116 117 return to_sql(self, expression) if to_sql else self.function_fallback_sql(expression) 118 119 return func 120 121 122class MySQLGenerator(generator.Generator): 123 SELECT_KINDS: tuple[str, ...] = () 124 TRY_SUPPORTED = False 125 SUPPORTS_UESCAPE = False 126 SUPPORTS_DECODE_CASE = False 127 SUPPORTS_MODIFY_COLUMN = True 128 SUPPORTS_CHANGE_COLUMN = True 129 130 AFTER_HAVING_MODIFIER_TRANSFORMS = generator.AFTER_HAVING_MODIFIER_TRANSFORMS 131 132 INTERVAL_ALLOWS_PLURAL_FORM = False 133 LOCKING_READS_SUPPORTED = True 134 NULL_ORDERING_SUPPORTED: bool | None = None 135 JOIN_HINTS = False 136 TABLE_HINTS = True 137 DUPLICATE_KEY_UPDATE_WITH_SET = False 138 QUERY_HINT_SEP = " " 139 VALUES_AS_TABLE = False 140 NVL2_SUPPORTED = False 141 LAST_DAY_SUPPORTS_DATE_PART = False 142 JSON_TYPE_REQUIRED_FOR_EXTRACTION = True 143 JSON_PATH_BRACKETED_KEY_SUPPORTED = False 144 JSON_KEY_VALUE_PAIR_SEP = "," 145 SUPPORTS_TO_NUMBER = False 146 PARSE_JSON_NAME: str | None = None 147 PAD_FILL_PATTERN_IS_REQUIRED = True 148 WRAP_DERIVED_VALUES = False 149 VARCHAR_REQUIRES_SIZE = True 150 SUPPORTS_MEDIAN = False 151 UPDATE_STATEMENT_SUPPORTS_FROM = False 152 153 TRANSFORMS = { 154 **generator.Generator.TRANSFORMS, 155 exp.ArrayAgg: rename_func("GROUP_CONCAT"), 156 exp.BitwiseAndAgg: rename_func("BIT_AND"), 157 exp.BitwiseOrAgg: rename_func("BIT_OR"), 158 exp.BitwiseXorAgg: rename_func("BIT_XOR"), 159 exp.BitwiseCount: rename_func("BIT_COUNT"), 160 exp.Chr: lambda self, e: self.chr_sql(e, "CHAR"), 161 exp.CurrentDate: no_paren_current_date_sql, 162 exp.CurrentVersion: rename_func("VERSION"), 163 exp.DateDiff: _remove_ts_or_ds_to_date( 164 lambda self, e: self.func("DATEDIFF", e.this, e.expression), ("this", "expression") 165 ), 166 exp.DateAdd: _remove_ts_or_ds_to_date(date_add_sql("ADD")), 167 exp.DateStrToDate: datestrtodate_sql, 168 exp.DateSub: _remove_ts_or_ds_to_date(date_add_sql("SUB")), 169 exp.DateTrunc: _date_trunc_sql, 170 exp.Day: _remove_ts_or_ds_to_date(), 171 exp.DayOfMonth: _remove_ts_or_ds_to_date(rename_func("DAYOFMONTH")), 172 exp.DayOfWeek: _remove_ts_or_ds_to_date(rename_func("DAYOFWEEK")), 173 exp.DayOfYear: _remove_ts_or_ds_to_date(rename_func("DAYOFYEAR")), 174 exp.GroupConcat: lambda self, e: ( 175 f"""GROUP_CONCAT({self.sql(e, "this")} SEPARATOR {self.sql(e, "separator") or "','"})""" 176 ), 177 exp.ILike: no_ilike_sql, 178 exp.JSONExtractScalar: arrow_json_extract_sql, 179 exp.Length: length_or_char_length_sql, 180 exp.LogicalOr: rename_func("MAX"), 181 exp.LogicalAnd: rename_func("MIN"), 182 exp.Max: max_or_greatest, 183 exp.Min: min_or_least, 184 exp.Month: _remove_ts_or_ds_to_date(), 185 exp.NullSafeEQ: lambda self, e: self.binary(e, "<=>"), 186 exp.NullSafeNEQ: lambda self, e: f"NOT {self.binary(e, '<=>')}", 187 exp.NumberToStr: rename_func("FORMAT"), 188 exp.Pivot: no_pivot_sql, 189 exp.Select: transforms.preprocess( 190 [ 191 transforms.eliminate_distinct_on, 192 transforms.eliminate_semi_and_anti_joins, 193 transforms.eliminate_qualify, 194 transforms.eliminate_full_outer_join, 195 transforms.unnest_generate_date_array_using_recursive_cte, 196 ] 197 ), 198 exp.StrPosition: lambda self, e: strposition_sql( 199 self, e, func_name="LOCATE", supports_position=True 200 ), 201 exp.StrToDate: _str_to_date_sql, 202 exp.StrToTime: _str_to_date_sql, 203 exp.Stuff: rename_func("INSERT"), 204 exp.SessionUser: lambda *_: "SESSION_USER()", 205 exp.TableSample: no_tablesample_sql, 206 exp.TimeFromParts: rename_func("MAKETIME"), 207 exp.TimestampAdd: date_add_interval_sql("DATE", "ADD"), 208 exp.TimestampDiff: lambda self, e: self.func( 209 "TIMESTAMPDIFF", unit_to_var(e), e.expression, e.this 210 ), 211 exp.TimestampSub: date_add_interval_sql("DATE", "SUB"), 212 exp.TimeStrToUnix: rename_func("UNIX_TIMESTAMP"), 213 exp.TimeStrToTime: lambda self, e: timestrtotime_sql( 214 self, 215 e, 216 include_precision=not e.args.get("zone"), 217 ), 218 exp.TimeToStr: _remove_ts_or_ds_to_date( 219 lambda self, e: self.func("DATE_FORMAT", e.this, self.format_time(e)) 220 ), 221 exp.Trim: trim_sql, 222 exp.Trunc: rename_func("TRUNCATE"), 223 exp.TryCast: no_trycast_sql, 224 exp.TsOrDsAdd: date_add_sql("ADD"), 225 exp.TsOrDsDiff: lambda self, e: self.func("DATEDIFF", e.this, e.expression), 226 exp.TsOrDsToDate: _ts_or_ds_to_date_sql, 227 exp.Unicode: lambda self, e: f"ORD(CONVERT({self.sql(e.this)} USING utf32))", 228 exp.UnixToTime: _unix_to_time_sql, 229 exp.Week: _remove_ts_or_ds_to_date(), 230 exp.WeekOfYear: _remove_ts_or_ds_to_date(rename_func("WEEKOFYEAR")), 231 exp.Year: _remove_ts_or_ds_to_date(), 232 exp.UtcTimestamp: rename_func("UTC_TIMESTAMP"), 233 exp.UtcTime: rename_func("UTC_TIME"), 234 } 235 236 UNSIGNED_TYPE_MAPPING = { 237 exp.DType.UBIGINT: "BIGINT", 238 exp.DType.UINT: "INT", 239 exp.DType.UMEDIUMINT: "MEDIUMINT", 240 exp.DType.USMALLINT: "SMALLINT", 241 exp.DType.UTINYINT: "TINYINT", 242 exp.DType.UDECIMAL: "DECIMAL", 243 exp.DType.UDOUBLE: "DOUBLE", 244 } 245 246 TIMESTAMP_TYPE_MAPPING = { 247 exp.DType.DATETIME2: "DATETIME", 248 exp.DType.SMALLDATETIME: "DATETIME", 249 exp.DType.TIMESTAMP: "DATETIME", 250 exp.DType.TIMESTAMPNTZ: "DATETIME", 251 exp.DType.TIMESTAMPTZ: "TIMESTAMP", 252 exp.DType.TIMESTAMPLTZ: "TIMESTAMP", 253 } 254 255 TYPE_MAPPING: t.ClassVar = { 256 exp.DType.NCHAR: "CHAR", 257 exp.DType.NVARCHAR: "VARCHAR", 258 exp.DType.INET: "INET", 259 exp.DType.ROWVERSION: "VARBINARY", 260 exp.DType.UBIGINT: "BIGINT", 261 exp.DType.UINT: "INT", 262 exp.DType.UMEDIUMINT: "MEDIUMINT", 263 exp.DType.USMALLINT: "SMALLINT", 264 exp.DType.UTINYINT: "TINYINT", 265 exp.DType.UDECIMAL: "DECIMAL", 266 exp.DType.UDOUBLE: "DOUBLE", 267 exp.DType.DATETIME2: "DATETIME", 268 exp.DType.SMALLDATETIME: "DATETIME", 269 exp.DType.TIMESTAMP: "DATETIME", 270 exp.DType.TIMESTAMPNTZ: "DATETIME", 271 exp.DType.TIMESTAMPTZ: "TIMESTAMP", 272 exp.DType.TIMESTAMPLTZ: "TIMESTAMP", 273 } 274 275 PROPERTIES_LOCATION: t.ClassVar = { 276 **generator.Generator.PROPERTIES_LOCATION, 277 exp.TransientProperty: exp.Properties.Location.UNSUPPORTED, 278 exp.VolatileProperty: exp.Properties.Location.UNSUPPORTED, 279 exp.PartitionedByProperty: exp.Properties.Location.UNSUPPORTED, 280 exp.PartitionByRangeProperty: exp.Properties.Location.POST_SCHEMA, 281 exp.PartitionByListProperty: exp.Properties.Location.POST_SCHEMA, 282 } 283 284 LIMIT_FETCH = "LIMIT" 285 286 LIMIT_ONLY_LITERALS = True 287 288 CHAR_CAST_MAPPING: t.ClassVar = dict.fromkeys( 289 ( 290 exp.DType.LONGTEXT, 291 exp.DType.LONGBLOB, 292 exp.DType.MEDIUMBLOB, 293 exp.DType.MEDIUMTEXT, 294 exp.DType.TEXT, 295 exp.DType.TINYBLOB, 296 exp.DType.TINYTEXT, 297 exp.DType.VARCHAR, 298 ), 299 "CHAR", 300 ) 301 SIGNED_CAST_MAPPING: t.ClassVar = dict.fromkeys( 302 ( 303 exp.DType.BIGINT, 304 exp.DType.BOOLEAN, 305 exp.DType.INT, 306 exp.DType.SMALLINT, 307 exp.DType.TINYINT, 308 exp.DType.MEDIUMINT, 309 ), 310 "SIGNED", 311 ) 312 313 # MySQL doesn't support many datatypes in cast. 314 # https://dev.mysql.com/doc/refman/8.0/en/cast-functions.html#function_cast 315 CAST_MAPPING = { 316 exp.DType.LONGTEXT: "CHAR", 317 exp.DType.LONGBLOB: "CHAR", 318 exp.DType.MEDIUMBLOB: "CHAR", 319 exp.DType.MEDIUMTEXT: "CHAR", 320 exp.DType.TEXT: "CHAR", 321 exp.DType.TINYBLOB: "CHAR", 322 exp.DType.TINYTEXT: "CHAR", 323 exp.DType.VARCHAR: "CHAR", 324 exp.DType.BIGINT: "SIGNED", 325 exp.DType.BOOLEAN: "SIGNED", 326 exp.DType.INT: "SIGNED", 327 exp.DType.SMALLINT: "SIGNED", 328 exp.DType.TINYINT: "SIGNED", 329 exp.DType.MEDIUMINT: "SIGNED", 330 exp.DType.UBIGINT: "UNSIGNED", 331 } 332 333 TIMESTAMP_FUNC_TYPES = { 334 exp.DType.TIMESTAMPTZ, 335 exp.DType.TIMESTAMPLTZ, 336 } 337 338 # https://dev.mysql.com/doc/refman/8.0/en/keywords.html 339 RESERVED_KEYWORDS = { 340 "accessible", 341 "add", 342 "all", 343 "alter", 344 "analyze", 345 "and", 346 "as", 347 "asc", 348 "asensitive", 349 "before", 350 "between", 351 "bigint", 352 "binary", 353 "blob", 354 "both", 355 "by", 356 "call", 357 "cascade", 358 "case", 359 "change", 360 "char", 361 "character", 362 "check", 363 "collate", 364 "column", 365 "condition", 366 "constraint", 367 "continue", 368 "convert", 369 "create", 370 "cross", 371 "cube", 372 "cume_dist", 373 "current_date", 374 "current_time", 375 "current_timestamp", 376 "current_user", 377 "cursor", 378 "database", 379 "databases", 380 "day_hour", 381 "day_microsecond", 382 "day_minute", 383 "day_second", 384 "dec", 385 "decimal", 386 "declare", 387 "default", 388 "delayed", 389 "delete", 390 "dense_rank", 391 "desc", 392 "describe", 393 "deterministic", 394 "distinct", 395 "distinctrow", 396 "div", 397 "double", 398 "drop", 399 "dual", 400 "each", 401 "else", 402 "elseif", 403 "empty", 404 "enclosed", 405 "escaped", 406 "except", 407 "exists", 408 "exit", 409 "explain", 410 "false", 411 "fetch", 412 "first_value", 413 "float", 414 "float4", 415 "float8", 416 "for", 417 "force", 418 "foreign", 419 "from", 420 "fulltext", 421 "function", 422 "generated", 423 "get", 424 "grant", 425 "group", 426 "grouping", 427 "groups", 428 "having", 429 "high_priority", 430 "hour_microsecond", 431 "hour_minute", 432 "hour_second", 433 "if", 434 "ignore", 435 "in", 436 "index", 437 "infile", 438 "inner", 439 "inout", 440 "insensitive", 441 "insert", 442 "int", 443 "int1", 444 "int2", 445 "int3", 446 "int4", 447 "int8", 448 "integer", 449 "intersect", 450 "interval", 451 "into", 452 "io_after_gtids", 453 "io_before_gtids", 454 "is", 455 "iterate", 456 "join", 457 "json_table", 458 "key", 459 "keys", 460 "kill", 461 "lag", 462 "last_value", 463 "lateral", 464 "lead", 465 "leading", 466 "leave", 467 "left", 468 "like", 469 "limit", 470 "linear", 471 "lines", 472 "load", 473 "localtime", 474 "localtimestamp", 475 "lock", 476 "long", 477 "longblob", 478 "longtext", 479 "loop", 480 "low_priority", 481 "master_bind", 482 "master_ssl_verify_server_cert", 483 "match", 484 "maxvalue", 485 "mediumblob", 486 "mediumint", 487 "mediumtext", 488 "middleint", 489 "minute_microsecond", 490 "minute_second", 491 "mod", 492 "modifies", 493 "natural", 494 "not", 495 "no_write_to_binlog", 496 "nth_value", 497 "ntile", 498 "null", 499 "numeric", 500 "of", 501 "on", 502 "optimize", 503 "optimizer_costs", 504 "option", 505 "optionally", 506 "or", 507 "order", 508 "out", 509 "outer", 510 "outfile", 511 "over", 512 "partition", 513 "percent_rank", 514 "precision", 515 "primary", 516 "procedure", 517 "purge", 518 "range", 519 "rank", 520 "read", 521 "reads", 522 "read_write", 523 "real", 524 "recursive", 525 "references", 526 "regexp", 527 "release", 528 "rename", 529 "repeat", 530 "replace", 531 "require", 532 "resignal", 533 "restrict", 534 "return", 535 "revoke", 536 "right", 537 "rlike", 538 "row", 539 "rows", 540 "row_number", 541 "schema", 542 "schemas", 543 "second_microsecond", 544 "select", 545 "sensitive", 546 "separator", 547 "set", 548 "show", 549 "signal", 550 "smallint", 551 "spatial", 552 "specific", 553 "sql", 554 "sqlexception", 555 "sqlstate", 556 "sqlwarning", 557 "sql_big_result", 558 "sql_calc_found_rows", 559 "sql_small_result", 560 "ssl", 561 "starting", 562 "stored", 563 "straight_join", 564 "system", 565 "table", 566 "terminated", 567 "then", 568 "tinyblob", 569 "tinyint", 570 "tinytext", 571 "to", 572 "trailing", 573 "trigger", 574 "true", 575 "undo", 576 "union", 577 "unique", 578 "unlock", 579 "unsigned", 580 "update", 581 "usage", 582 "use", 583 "using", 584 "utc_date", 585 "utc_time", 586 "utc_timestamp", 587 "values", 588 "varbinary", 589 "varchar", 590 "varcharacter", 591 "varying", 592 "virtual", 593 "when", 594 "where", 595 "while", 596 "window", 597 "with", 598 "write", 599 "xor", 600 "year_month", 601 "zerofill", 602 } 603 604 SQL_SECURITY_VIEW_LOCATION = exp.Properties.Location.POST_CREATE 605 606 def makeinterval_sql(self: MySQLGenerator, expression: exp.MakeInterval) -> str: 607 intervals: list[exp.Interval] = [] 608 for arg_key, value in expression.args.items(): 609 if value is None: 610 continue 611 612 if isinstance(value, exp.Kwarg): 613 unit_name = _MAKE_INTERVAL_UNIT_ALIASES.get( 614 value.this.name.lower(), value.this.name.lower() 615 ) 616 value = value.expression 617 else: 618 unit_name = arg_key 619 620 intervals.append(exp.Interval(this=value.copy(), unit=exp.var(unit_name.upper()))) 621 622 if not intervals: 623 return self.function_fallback_sql(expression) 624 625 parent = expression.parent 626 sep = " - " if isinstance(parent, exp.Sub) and parent.expression is expression else " + " 627 628 return sep.join(self.sql(interval) for interval in intervals) 629 630 def locate_properties(self, properties: exp.Properties) -> defaultdict: 631 locations = super().locate_properties(properties) 632 633 # MySQL puts SQL SECURITY before VIEW but after the schema for functions/procedures 634 if isinstance(create := properties.parent, exp.Create) and create.kind == "VIEW": 635 post_schema = locations[exp.Properties.Location.POST_SCHEMA] 636 for i, p in enumerate(post_schema): 637 if isinstance(p, exp.SqlSecurityProperty): 638 post_schema.pop(i) 639 locations[self.SQL_SECURITY_VIEW_LOCATION].append(p) 640 break 641 642 return locations 643 644 def computedcolumnconstraint_sql(self, expression: exp.ComputedColumnConstraint) -> str: 645 persisted = "STORED" if expression.args.get("persisted") else "VIRTUAL" 646 return f"GENERATED ALWAYS AS ({self.sql(expression.this.unnest())}) {persisted}" 647 648 def array_sql(self, expression: exp.Array) -> str: 649 self.unsupported("Arrays are not supported by MySQL") 650 return self.function_fallback_sql(expression) 651 652 def arraycontainsall_sql(self, expression: exp.ArrayContainsAll) -> str: 653 self.unsupported("Array operations are not supported by MySQL") 654 return self.function_fallback_sql(expression) 655 656 def arraycontainedby_sql(self, expression: exp.ArrayContainedBy) -> str: 657 self.unsupported("Array operations are not supported by MySQL") 658 return self.function_fallback_sql(expression) 659 660 def dpipe_sql(self, expression: exp.DPipe) -> str: 661 return self.func("CONCAT", *expression.flatten()) 662 663 def extract_sql(self, expression: exp.Extract) -> str: 664 unit = expression.name 665 if unit and unit.lower() == "epoch": 666 return self.func("UNIX_TIMESTAMP", expression.expression) 667 668 return super().extract_sql(expression) 669 670 def datatype_sql(self, expression: exp.DataType) -> str: 671 if ( 672 self.VARCHAR_REQUIRES_SIZE 673 and expression.is_type(exp.DType.VARCHAR) 674 and not expression.expressions 675 ): 676 # `VARCHAR` must always have a size - if it doesn't, we always generate `TEXT` 677 return "TEXT" 678 679 # https://dev.mysql.com/doc/refman/8.0/en/numeric-type-syntax.html 680 result = super().datatype_sql(expression) 681 if expression.this in self.UNSIGNED_TYPE_MAPPING: 682 result = f"{result} UNSIGNED" 683 684 return result 685 686 def jsonarraycontains_sql(self, expression: exp.JSONArrayContains) -> str: 687 return f"{self.sql(expression, 'this')} MEMBER OF({self.sql(expression, 'expression')})" 688 689 def cast_sql(self, expression: exp.Cast, safe_prefix: str | None = None) -> str: 690 if expression.to.this in self.TIMESTAMP_FUNC_TYPES: 691 return self.func("TIMESTAMP", expression.this) 692 693 to = self.CAST_MAPPING.get(expression.to.this) 694 695 if to: 696 expression.to.set("this", to) 697 return super().cast_sql(expression) 698 699 def show_sql(self, expression: exp.Show) -> str: 700 this = f" {expression.name}" 701 full = " FULL" if expression.args.get("full") else "" 702 global_ = " GLOBAL" if expression.args.get("global_") else "" 703 704 target = self.sql(expression, "target") 705 target = f" {target}" if target else "" 706 if expression.name in ("COLUMNS", "INDEX"): 707 target = f" FROM{target}" 708 elif expression.name == "GRANTS": 709 target = f" FOR{target}" 710 elif expression.name in ("LINKS", "PARTITIONS"): 711 target = f" ON{target}" if target else "" 712 elif expression.name == "PROJECTIONS": 713 target = f" ON TABLE{target}" if target else "" 714 715 db = self._prefixed_sql("FROM", expression, "db") 716 717 like = self._prefixed_sql("LIKE", expression, "like") 718 where = self.sql(expression, "where") 719 720 types = self.expressions(expression, key="types") 721 types = f" {types}" if types else types 722 query = self._prefixed_sql("FOR QUERY", expression, "query") 723 724 if expression.name == "PROFILE": 725 offset = self._prefixed_sql("OFFSET", expression, "offset") 726 limit = self._prefixed_sql("LIMIT", expression, "limit") 727 else: 728 offset = "" 729 limit = self._oldstyle_limit_sql(expression) 730 731 log = self._prefixed_sql("IN", expression, "log") 732 position = self._prefixed_sql("FROM", expression, "position") 733 734 channel = self._prefixed_sql("FOR CHANNEL", expression, "channel") 735 736 if expression.name == "ENGINE": 737 mutex_or_status = " MUTEX" if expression.args.get("mutex") else " STATUS" 738 else: 739 mutex_or_status = "" 740 741 for_table = self._prefixed_sql("FOR TABLE", expression, "for_table") 742 for_group = self._prefixed_sql("FOR GROUP", expression, "for_group") 743 for_user = self._prefixed_sql("FOR USER", expression, "for_user") 744 for_role = self._prefixed_sql("FOR ROLE", expression, "for_role") 745 into_outfile = self._prefixed_sql("INTO OUTFILE", expression, "into_outfile") 746 json = " JSON" if expression.args.get("json") else "" 747 748 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}" 749 750 def alterrename_sql(self, expression: exp.AlterRename, include_to: bool = True) -> str: 751 """To avoid TO keyword in ALTER ... RENAME statements. 752 It's moved from Doris, because it's the same for all MySQL, Doris, and StarRocks. 753 """ 754 return super().alterrename_sql(expression, include_to=False) 755 756 def altercolumn_sql(self, expression: exp.AlterColumn) -> str: 757 dtype = self.sql(expression, "dtype") 758 if not dtype: 759 return super().altercolumn_sql(expression) 760 761 this = self.sql(expression, "this") 762 return f"MODIFY COLUMN {this} {dtype}" 763 764 def _prefixed_sql(self, prefix: str, expression: exp.Expr, arg: str) -> str: 765 sql = self.sql(expression, arg) 766 return f" {prefix} {sql}" if sql else "" 767 768 def _oldstyle_limit_sql(self, expression: exp.Show) -> str: 769 limit = self.sql(expression, "limit") 770 offset = self.sql(expression, "offset") 771 if limit: 772 limit_offset = f"{offset}, {limit}" if offset else limit 773 return f" LIMIT {limit_offset}" 774 return "" 775 776 def timestamptrunc_sql(self, expression: exp.TimestampTrunc) -> str: 777 unit = expression.args.get("unit") 778 779 # Pick an old-enough date to avoid negative timestamp diffs 780 start_ts = "'0000-01-01 00:00:00'" 781 782 # Source: https://stackoverflow.com/a/32955740 783 timestamp_diff = build_date_delta(exp.TimestampDiff)([unit, start_ts, expression.this]) 784 interval = exp.Interval(this=timestamp_diff, unit=unit) 785 dateadd = build_date_delta_with_interval(exp.DateAdd)([start_ts, interval]) 786 787 return self.sql(dateadd) 788 789 def converttimezone_sql(self, expression: exp.ConvertTimezone) -> str: 790 from_tz = expression.args.get("source_tz") 791 to_tz = expression.args.get("target_tz") 792 dt = expression.args.get("timestamp") 793 794 return self.func("CONVERT_TZ", dt, from_tz, to_tz) 795 796 def attimezone_sql(self, expression: exp.AtTimeZone) -> str: 797 self.unsupported("AT TIME ZONE is not supported by MySQL") 798 return self.sql(expression.this) 799 800 def isascii_sql(self, expression: exp.IsAscii) -> str: 801 return f"REGEXP_LIKE({self.sql(expression.this)}, '^[[:ascii:]]*$')" 802 803 def ignorenulls_sql(self, expression: exp.IgnoreNulls) -> str: 804 # https://dev.mysql.com/doc/refman/8.4/en/window-function-descriptions.html 805 self.unsupported("MySQL does not support IGNORE NULLS.") 806 return self.sql(expression.this) 807 808 @unsupported_args("this") 809 def currentschema_sql(self, expression: exp.CurrentSchema) -> str: 810 return self.func("SCHEMA") 811 812 def partition_sql(self, expression: exp.Partition) -> str: 813 parent = expression.parent 814 if isinstance(parent, (exp.PartitionByRangeProperty, exp.PartitionByListProperty)): 815 return self.expressions(expression, flat=True) 816 return super().partition_sql(expression) 817 818 def _partition_by_sql( 819 self, expression: exp.PartitionByRangeProperty | exp.PartitionByListProperty, kind: str 820 ) -> str: 821 partitions = self.expressions(expression, key="partition_expressions", flat=True) 822 create = self.expressions(expression, key="create_expressions", flat=True) 823 return f"PARTITION BY {kind} ({partitions}) ({create})" 824 825 def partitionbyrangeproperty_sql(self, expression: exp.PartitionByRangeProperty) -> str: 826 return self._partition_by_sql(expression, "RANGE") 827 828 def partitionbylistproperty_sql(self, expression: exp.PartitionByListProperty) -> str: 829 return self._partition_by_sql(expression, "LIST") 830 831 def partitionlist_sql(self, expression: exp.PartitionList) -> str: 832 name = self.sql(expression, "this") 833 values = self.expressions(expression, flat=True) 834 return f"PARTITION {name} VALUES IN ({values})" 835 836 def partitionrange_sql(self, expression: exp.PartitionRange) -> str: 837 name = self.sql(expression, "this") 838 values = self.expressions(expression, flat=True) 839 return f"PARTITION {name} VALUES LESS THAN ({values})"
def
date_add_sql( kind: str) -> Callable[[sqlglot.generator.Generator, sqlglot.expressions.core.Expr], str]:
75def date_add_sql( 76 kind: str, 77) -> t.Callable[[generator.Generator, exp.Expr], str]: 78 def func(self: generator.Generator, expression: exp.Expr) -> str: 79 return self.func( 80 f"DATE_{kind}", 81 expression.this, 82 exp.Interval(this=expression.expression, unit=unit_to_var(expression)), 83 ) 84 85 return func
123class MySQLGenerator(generator.Generator): 124 SELECT_KINDS: tuple[str, ...] = () 125 TRY_SUPPORTED = False 126 SUPPORTS_UESCAPE = False 127 SUPPORTS_DECODE_CASE = False 128 SUPPORTS_MODIFY_COLUMN = True 129 SUPPORTS_CHANGE_COLUMN = True 130 131 AFTER_HAVING_MODIFIER_TRANSFORMS = generator.AFTER_HAVING_MODIFIER_TRANSFORMS 132 133 INTERVAL_ALLOWS_PLURAL_FORM = False 134 LOCKING_READS_SUPPORTED = True 135 NULL_ORDERING_SUPPORTED: bool | None = None 136 JOIN_HINTS = False 137 TABLE_HINTS = True 138 DUPLICATE_KEY_UPDATE_WITH_SET = False 139 QUERY_HINT_SEP = " " 140 VALUES_AS_TABLE = False 141 NVL2_SUPPORTED = False 142 LAST_DAY_SUPPORTS_DATE_PART = False 143 JSON_TYPE_REQUIRED_FOR_EXTRACTION = True 144 JSON_PATH_BRACKETED_KEY_SUPPORTED = False 145 JSON_KEY_VALUE_PAIR_SEP = "," 146 SUPPORTS_TO_NUMBER = False 147 PARSE_JSON_NAME: str | None = None 148 PAD_FILL_PATTERN_IS_REQUIRED = True 149 WRAP_DERIVED_VALUES = False 150 VARCHAR_REQUIRES_SIZE = True 151 SUPPORTS_MEDIAN = False 152 UPDATE_STATEMENT_SUPPORTS_FROM = False 153 154 TRANSFORMS = { 155 **generator.Generator.TRANSFORMS, 156 exp.ArrayAgg: rename_func("GROUP_CONCAT"), 157 exp.BitwiseAndAgg: rename_func("BIT_AND"), 158 exp.BitwiseOrAgg: rename_func("BIT_OR"), 159 exp.BitwiseXorAgg: rename_func("BIT_XOR"), 160 exp.BitwiseCount: rename_func("BIT_COUNT"), 161 exp.Chr: lambda self, e: self.chr_sql(e, "CHAR"), 162 exp.CurrentDate: no_paren_current_date_sql, 163 exp.CurrentVersion: rename_func("VERSION"), 164 exp.DateDiff: _remove_ts_or_ds_to_date( 165 lambda self, e: self.func("DATEDIFF", e.this, e.expression), ("this", "expression") 166 ), 167 exp.DateAdd: _remove_ts_or_ds_to_date(date_add_sql("ADD")), 168 exp.DateStrToDate: datestrtodate_sql, 169 exp.DateSub: _remove_ts_or_ds_to_date(date_add_sql("SUB")), 170 exp.DateTrunc: _date_trunc_sql, 171 exp.Day: _remove_ts_or_ds_to_date(), 172 exp.DayOfMonth: _remove_ts_or_ds_to_date(rename_func("DAYOFMONTH")), 173 exp.DayOfWeek: _remove_ts_or_ds_to_date(rename_func("DAYOFWEEK")), 174 exp.DayOfYear: _remove_ts_or_ds_to_date(rename_func("DAYOFYEAR")), 175 exp.GroupConcat: lambda self, e: ( 176 f"""GROUP_CONCAT({self.sql(e, "this")} SEPARATOR {self.sql(e, "separator") or "','"})""" 177 ), 178 exp.ILike: no_ilike_sql, 179 exp.JSONExtractScalar: arrow_json_extract_sql, 180 exp.Length: length_or_char_length_sql, 181 exp.LogicalOr: rename_func("MAX"), 182 exp.LogicalAnd: rename_func("MIN"), 183 exp.Max: max_or_greatest, 184 exp.Min: min_or_least, 185 exp.Month: _remove_ts_or_ds_to_date(), 186 exp.NullSafeEQ: lambda self, e: self.binary(e, "<=>"), 187 exp.NullSafeNEQ: lambda self, e: f"NOT {self.binary(e, '<=>')}", 188 exp.NumberToStr: rename_func("FORMAT"), 189 exp.Pivot: no_pivot_sql, 190 exp.Select: transforms.preprocess( 191 [ 192 transforms.eliminate_distinct_on, 193 transforms.eliminate_semi_and_anti_joins, 194 transforms.eliminate_qualify, 195 transforms.eliminate_full_outer_join, 196 transforms.unnest_generate_date_array_using_recursive_cte, 197 ] 198 ), 199 exp.StrPosition: lambda self, e: strposition_sql( 200 self, e, func_name="LOCATE", supports_position=True 201 ), 202 exp.StrToDate: _str_to_date_sql, 203 exp.StrToTime: _str_to_date_sql, 204 exp.Stuff: rename_func("INSERT"), 205 exp.SessionUser: lambda *_: "SESSION_USER()", 206 exp.TableSample: no_tablesample_sql, 207 exp.TimeFromParts: rename_func("MAKETIME"), 208 exp.TimestampAdd: date_add_interval_sql("DATE", "ADD"), 209 exp.TimestampDiff: lambda self, e: self.func( 210 "TIMESTAMPDIFF", unit_to_var(e), e.expression, e.this 211 ), 212 exp.TimestampSub: date_add_interval_sql("DATE", "SUB"), 213 exp.TimeStrToUnix: rename_func("UNIX_TIMESTAMP"), 214 exp.TimeStrToTime: lambda self, e: timestrtotime_sql( 215 self, 216 e, 217 include_precision=not e.args.get("zone"), 218 ), 219 exp.TimeToStr: _remove_ts_or_ds_to_date( 220 lambda self, e: self.func("DATE_FORMAT", e.this, self.format_time(e)) 221 ), 222 exp.Trim: trim_sql, 223 exp.Trunc: rename_func("TRUNCATE"), 224 exp.TryCast: no_trycast_sql, 225 exp.TsOrDsAdd: date_add_sql("ADD"), 226 exp.TsOrDsDiff: lambda self, e: self.func("DATEDIFF", e.this, e.expression), 227 exp.TsOrDsToDate: _ts_or_ds_to_date_sql, 228 exp.Unicode: lambda self, e: f"ORD(CONVERT({self.sql(e.this)} USING utf32))", 229 exp.UnixToTime: _unix_to_time_sql, 230 exp.Week: _remove_ts_or_ds_to_date(), 231 exp.WeekOfYear: _remove_ts_or_ds_to_date(rename_func("WEEKOFYEAR")), 232 exp.Year: _remove_ts_or_ds_to_date(), 233 exp.UtcTimestamp: rename_func("UTC_TIMESTAMP"), 234 exp.UtcTime: rename_func("UTC_TIME"), 235 } 236 237 UNSIGNED_TYPE_MAPPING = { 238 exp.DType.UBIGINT: "BIGINT", 239 exp.DType.UINT: "INT", 240 exp.DType.UMEDIUMINT: "MEDIUMINT", 241 exp.DType.USMALLINT: "SMALLINT", 242 exp.DType.UTINYINT: "TINYINT", 243 exp.DType.UDECIMAL: "DECIMAL", 244 exp.DType.UDOUBLE: "DOUBLE", 245 } 246 247 TIMESTAMP_TYPE_MAPPING = { 248 exp.DType.DATETIME2: "DATETIME", 249 exp.DType.SMALLDATETIME: "DATETIME", 250 exp.DType.TIMESTAMP: "DATETIME", 251 exp.DType.TIMESTAMPNTZ: "DATETIME", 252 exp.DType.TIMESTAMPTZ: "TIMESTAMP", 253 exp.DType.TIMESTAMPLTZ: "TIMESTAMP", 254 } 255 256 TYPE_MAPPING: t.ClassVar = { 257 exp.DType.NCHAR: "CHAR", 258 exp.DType.NVARCHAR: "VARCHAR", 259 exp.DType.INET: "INET", 260 exp.DType.ROWVERSION: "VARBINARY", 261 exp.DType.UBIGINT: "BIGINT", 262 exp.DType.UINT: "INT", 263 exp.DType.UMEDIUMINT: "MEDIUMINT", 264 exp.DType.USMALLINT: "SMALLINT", 265 exp.DType.UTINYINT: "TINYINT", 266 exp.DType.UDECIMAL: "DECIMAL", 267 exp.DType.UDOUBLE: "DOUBLE", 268 exp.DType.DATETIME2: "DATETIME", 269 exp.DType.SMALLDATETIME: "DATETIME", 270 exp.DType.TIMESTAMP: "DATETIME", 271 exp.DType.TIMESTAMPNTZ: "DATETIME", 272 exp.DType.TIMESTAMPTZ: "TIMESTAMP", 273 exp.DType.TIMESTAMPLTZ: "TIMESTAMP", 274 } 275 276 PROPERTIES_LOCATION: t.ClassVar = { 277 **generator.Generator.PROPERTIES_LOCATION, 278 exp.TransientProperty: exp.Properties.Location.UNSUPPORTED, 279 exp.VolatileProperty: exp.Properties.Location.UNSUPPORTED, 280 exp.PartitionedByProperty: exp.Properties.Location.UNSUPPORTED, 281 exp.PartitionByRangeProperty: exp.Properties.Location.POST_SCHEMA, 282 exp.PartitionByListProperty: exp.Properties.Location.POST_SCHEMA, 283 } 284 285 LIMIT_FETCH = "LIMIT" 286 287 LIMIT_ONLY_LITERALS = True 288 289 CHAR_CAST_MAPPING: t.ClassVar = dict.fromkeys( 290 ( 291 exp.DType.LONGTEXT, 292 exp.DType.LONGBLOB, 293 exp.DType.MEDIUMBLOB, 294 exp.DType.MEDIUMTEXT, 295 exp.DType.TEXT, 296 exp.DType.TINYBLOB, 297 exp.DType.TINYTEXT, 298 exp.DType.VARCHAR, 299 ), 300 "CHAR", 301 ) 302 SIGNED_CAST_MAPPING: t.ClassVar = dict.fromkeys( 303 ( 304 exp.DType.BIGINT, 305 exp.DType.BOOLEAN, 306 exp.DType.INT, 307 exp.DType.SMALLINT, 308 exp.DType.TINYINT, 309 exp.DType.MEDIUMINT, 310 ), 311 "SIGNED", 312 ) 313 314 # MySQL doesn't support many datatypes in cast. 315 # https://dev.mysql.com/doc/refman/8.0/en/cast-functions.html#function_cast 316 CAST_MAPPING = { 317 exp.DType.LONGTEXT: "CHAR", 318 exp.DType.LONGBLOB: "CHAR", 319 exp.DType.MEDIUMBLOB: "CHAR", 320 exp.DType.MEDIUMTEXT: "CHAR", 321 exp.DType.TEXT: "CHAR", 322 exp.DType.TINYBLOB: "CHAR", 323 exp.DType.TINYTEXT: "CHAR", 324 exp.DType.VARCHAR: "CHAR", 325 exp.DType.BIGINT: "SIGNED", 326 exp.DType.BOOLEAN: "SIGNED", 327 exp.DType.INT: "SIGNED", 328 exp.DType.SMALLINT: "SIGNED", 329 exp.DType.TINYINT: "SIGNED", 330 exp.DType.MEDIUMINT: "SIGNED", 331 exp.DType.UBIGINT: "UNSIGNED", 332 } 333 334 TIMESTAMP_FUNC_TYPES = { 335 exp.DType.TIMESTAMPTZ, 336 exp.DType.TIMESTAMPLTZ, 337 } 338 339 # https://dev.mysql.com/doc/refman/8.0/en/keywords.html 340 RESERVED_KEYWORDS = { 341 "accessible", 342 "add", 343 "all", 344 "alter", 345 "analyze", 346 "and", 347 "as", 348 "asc", 349 "asensitive", 350 "before", 351 "between", 352 "bigint", 353 "binary", 354 "blob", 355 "both", 356 "by", 357 "call", 358 "cascade", 359 "case", 360 "change", 361 "char", 362 "character", 363 "check", 364 "collate", 365 "column", 366 "condition", 367 "constraint", 368 "continue", 369 "convert", 370 "create", 371 "cross", 372 "cube", 373 "cume_dist", 374 "current_date", 375 "current_time", 376 "current_timestamp", 377 "current_user", 378 "cursor", 379 "database", 380 "databases", 381 "day_hour", 382 "day_microsecond", 383 "day_minute", 384 "day_second", 385 "dec", 386 "decimal", 387 "declare", 388 "default", 389 "delayed", 390 "delete", 391 "dense_rank", 392 "desc", 393 "describe", 394 "deterministic", 395 "distinct", 396 "distinctrow", 397 "div", 398 "double", 399 "drop", 400 "dual", 401 "each", 402 "else", 403 "elseif", 404 "empty", 405 "enclosed", 406 "escaped", 407 "except", 408 "exists", 409 "exit", 410 "explain", 411 "false", 412 "fetch", 413 "first_value", 414 "float", 415 "float4", 416 "float8", 417 "for", 418 "force", 419 "foreign", 420 "from", 421 "fulltext", 422 "function", 423 "generated", 424 "get", 425 "grant", 426 "group", 427 "grouping", 428 "groups", 429 "having", 430 "high_priority", 431 "hour_microsecond", 432 "hour_minute", 433 "hour_second", 434 "if", 435 "ignore", 436 "in", 437 "index", 438 "infile", 439 "inner", 440 "inout", 441 "insensitive", 442 "insert", 443 "int", 444 "int1", 445 "int2", 446 "int3", 447 "int4", 448 "int8", 449 "integer", 450 "intersect", 451 "interval", 452 "into", 453 "io_after_gtids", 454 "io_before_gtids", 455 "is", 456 "iterate", 457 "join", 458 "json_table", 459 "key", 460 "keys", 461 "kill", 462 "lag", 463 "last_value", 464 "lateral", 465 "lead", 466 "leading", 467 "leave", 468 "left", 469 "like", 470 "limit", 471 "linear", 472 "lines", 473 "load", 474 "localtime", 475 "localtimestamp", 476 "lock", 477 "long", 478 "longblob", 479 "longtext", 480 "loop", 481 "low_priority", 482 "master_bind", 483 "master_ssl_verify_server_cert", 484 "match", 485 "maxvalue", 486 "mediumblob", 487 "mediumint", 488 "mediumtext", 489 "middleint", 490 "minute_microsecond", 491 "minute_second", 492 "mod", 493 "modifies", 494 "natural", 495 "not", 496 "no_write_to_binlog", 497 "nth_value", 498 "ntile", 499 "null", 500 "numeric", 501 "of", 502 "on", 503 "optimize", 504 "optimizer_costs", 505 "option", 506 "optionally", 507 "or", 508 "order", 509 "out", 510 "outer", 511 "outfile", 512 "over", 513 "partition", 514 "percent_rank", 515 "precision", 516 "primary", 517 "procedure", 518 "purge", 519 "range", 520 "rank", 521 "read", 522 "reads", 523 "read_write", 524 "real", 525 "recursive", 526 "references", 527 "regexp", 528 "release", 529 "rename", 530 "repeat", 531 "replace", 532 "require", 533 "resignal", 534 "restrict", 535 "return", 536 "revoke", 537 "right", 538 "rlike", 539 "row", 540 "rows", 541 "row_number", 542 "schema", 543 "schemas", 544 "second_microsecond", 545 "select", 546 "sensitive", 547 "separator", 548 "set", 549 "show", 550 "signal", 551 "smallint", 552 "spatial", 553 "specific", 554 "sql", 555 "sqlexception", 556 "sqlstate", 557 "sqlwarning", 558 "sql_big_result", 559 "sql_calc_found_rows", 560 "sql_small_result", 561 "ssl", 562 "starting", 563 "stored", 564 "straight_join", 565 "system", 566 "table", 567 "terminated", 568 "then", 569 "tinyblob", 570 "tinyint", 571 "tinytext", 572 "to", 573 "trailing", 574 "trigger", 575 "true", 576 "undo", 577 "union", 578 "unique", 579 "unlock", 580 "unsigned", 581 "update", 582 "usage", 583 "use", 584 "using", 585 "utc_date", 586 "utc_time", 587 "utc_timestamp", 588 "values", 589 "varbinary", 590 "varchar", 591 "varcharacter", 592 "varying", 593 "virtual", 594 "when", 595 "where", 596 "while", 597 "window", 598 "with", 599 "write", 600 "xor", 601 "year_month", 602 "zerofill", 603 } 604 605 SQL_SECURITY_VIEW_LOCATION = exp.Properties.Location.POST_CREATE 606 607 def makeinterval_sql(self: MySQLGenerator, expression: exp.MakeInterval) -> str: 608 intervals: list[exp.Interval] = [] 609 for arg_key, value in expression.args.items(): 610 if value is None: 611 continue 612 613 if isinstance(value, exp.Kwarg): 614 unit_name = _MAKE_INTERVAL_UNIT_ALIASES.get( 615 value.this.name.lower(), value.this.name.lower() 616 ) 617 value = value.expression 618 else: 619 unit_name = arg_key 620 621 intervals.append(exp.Interval(this=value.copy(), unit=exp.var(unit_name.upper()))) 622 623 if not intervals: 624 return self.function_fallback_sql(expression) 625 626 parent = expression.parent 627 sep = " - " if isinstance(parent, exp.Sub) and parent.expression is expression else " + " 628 629 return sep.join(self.sql(interval) for interval in intervals) 630 631 def locate_properties(self, properties: exp.Properties) -> defaultdict: 632 locations = super().locate_properties(properties) 633 634 # MySQL puts SQL SECURITY before VIEW but after the schema for functions/procedures 635 if isinstance(create := properties.parent, exp.Create) and create.kind == "VIEW": 636 post_schema = locations[exp.Properties.Location.POST_SCHEMA] 637 for i, p in enumerate(post_schema): 638 if isinstance(p, exp.SqlSecurityProperty): 639 post_schema.pop(i) 640 locations[self.SQL_SECURITY_VIEW_LOCATION].append(p) 641 break 642 643 return locations 644 645 def computedcolumnconstraint_sql(self, expression: exp.ComputedColumnConstraint) -> str: 646 persisted = "STORED" if expression.args.get("persisted") else "VIRTUAL" 647 return f"GENERATED ALWAYS AS ({self.sql(expression.this.unnest())}) {persisted}" 648 649 def array_sql(self, expression: exp.Array) -> str: 650 self.unsupported("Arrays are not supported by MySQL") 651 return self.function_fallback_sql(expression) 652 653 def arraycontainsall_sql(self, expression: exp.ArrayContainsAll) -> str: 654 self.unsupported("Array operations are not supported by MySQL") 655 return self.function_fallback_sql(expression) 656 657 def arraycontainedby_sql(self, expression: exp.ArrayContainedBy) -> str: 658 self.unsupported("Array operations are not supported by MySQL") 659 return self.function_fallback_sql(expression) 660 661 def dpipe_sql(self, expression: exp.DPipe) -> str: 662 return self.func("CONCAT", *expression.flatten()) 663 664 def extract_sql(self, expression: exp.Extract) -> str: 665 unit = expression.name 666 if unit and unit.lower() == "epoch": 667 return self.func("UNIX_TIMESTAMP", expression.expression) 668 669 return super().extract_sql(expression) 670 671 def datatype_sql(self, expression: exp.DataType) -> str: 672 if ( 673 self.VARCHAR_REQUIRES_SIZE 674 and expression.is_type(exp.DType.VARCHAR) 675 and not expression.expressions 676 ): 677 # `VARCHAR` must always have a size - if it doesn't, we always generate `TEXT` 678 return "TEXT" 679 680 # https://dev.mysql.com/doc/refman/8.0/en/numeric-type-syntax.html 681 result = super().datatype_sql(expression) 682 if expression.this in self.UNSIGNED_TYPE_MAPPING: 683 result = f"{result} UNSIGNED" 684 685 return result 686 687 def jsonarraycontains_sql(self, expression: exp.JSONArrayContains) -> str: 688 return f"{self.sql(expression, 'this')} MEMBER OF({self.sql(expression, 'expression')})" 689 690 def cast_sql(self, expression: exp.Cast, safe_prefix: str | None = None) -> str: 691 if expression.to.this in self.TIMESTAMP_FUNC_TYPES: 692 return self.func("TIMESTAMP", expression.this) 693 694 to = self.CAST_MAPPING.get(expression.to.this) 695 696 if to: 697 expression.to.set("this", to) 698 return super().cast_sql(expression) 699 700 def show_sql(self, expression: exp.Show) -> str: 701 this = f" {expression.name}" 702 full = " FULL" if expression.args.get("full") else "" 703 global_ = " GLOBAL" if expression.args.get("global_") else "" 704 705 target = self.sql(expression, "target") 706 target = f" {target}" if target else "" 707 if expression.name in ("COLUMNS", "INDEX"): 708 target = f" FROM{target}" 709 elif expression.name == "GRANTS": 710 target = f" FOR{target}" 711 elif expression.name in ("LINKS", "PARTITIONS"): 712 target = f" ON{target}" if target else "" 713 elif expression.name == "PROJECTIONS": 714 target = f" ON TABLE{target}" if target else "" 715 716 db = self._prefixed_sql("FROM", expression, "db") 717 718 like = self._prefixed_sql("LIKE", expression, "like") 719 where = self.sql(expression, "where") 720 721 types = self.expressions(expression, key="types") 722 types = f" {types}" if types else types 723 query = self._prefixed_sql("FOR QUERY", expression, "query") 724 725 if expression.name == "PROFILE": 726 offset = self._prefixed_sql("OFFSET", expression, "offset") 727 limit = self._prefixed_sql("LIMIT", expression, "limit") 728 else: 729 offset = "" 730 limit = self._oldstyle_limit_sql(expression) 731 732 log = self._prefixed_sql("IN", expression, "log") 733 position = self._prefixed_sql("FROM", expression, "position") 734 735 channel = self._prefixed_sql("FOR CHANNEL", expression, "channel") 736 737 if expression.name == "ENGINE": 738 mutex_or_status = " MUTEX" if expression.args.get("mutex") else " STATUS" 739 else: 740 mutex_or_status = "" 741 742 for_table = self._prefixed_sql("FOR TABLE", expression, "for_table") 743 for_group = self._prefixed_sql("FOR GROUP", expression, "for_group") 744 for_user = self._prefixed_sql("FOR USER", expression, "for_user") 745 for_role = self._prefixed_sql("FOR ROLE", expression, "for_role") 746 into_outfile = self._prefixed_sql("INTO OUTFILE", expression, "into_outfile") 747 json = " JSON" if expression.args.get("json") else "" 748 749 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}" 750 751 def alterrename_sql(self, expression: exp.AlterRename, include_to: bool = True) -> str: 752 """To avoid TO keyword in ALTER ... RENAME statements. 753 It's moved from Doris, because it's the same for all MySQL, Doris, and StarRocks. 754 """ 755 return super().alterrename_sql(expression, include_to=False) 756 757 def altercolumn_sql(self, expression: exp.AlterColumn) -> str: 758 dtype = self.sql(expression, "dtype") 759 if not dtype: 760 return super().altercolumn_sql(expression) 761 762 this = self.sql(expression, "this") 763 return f"MODIFY COLUMN {this} {dtype}" 764 765 def _prefixed_sql(self, prefix: str, expression: exp.Expr, arg: str) -> str: 766 sql = self.sql(expression, arg) 767 return f" {prefix} {sql}" if sql else "" 768 769 def _oldstyle_limit_sql(self, expression: exp.Show) -> str: 770 limit = self.sql(expression, "limit") 771 offset = self.sql(expression, "offset") 772 if limit: 773 limit_offset = f"{offset}, {limit}" if offset else limit 774 return f" LIMIT {limit_offset}" 775 return "" 776 777 def timestamptrunc_sql(self, expression: exp.TimestampTrunc) -> str: 778 unit = expression.args.get("unit") 779 780 # Pick an old-enough date to avoid negative timestamp diffs 781 start_ts = "'0000-01-01 00:00:00'" 782 783 # Source: https://stackoverflow.com/a/32955740 784 timestamp_diff = build_date_delta(exp.TimestampDiff)([unit, start_ts, expression.this]) 785 interval = exp.Interval(this=timestamp_diff, unit=unit) 786 dateadd = build_date_delta_with_interval(exp.DateAdd)([start_ts, interval]) 787 788 return self.sql(dateadd) 789 790 def converttimezone_sql(self, expression: exp.ConvertTimezone) -> str: 791 from_tz = expression.args.get("source_tz") 792 to_tz = expression.args.get("target_tz") 793 dt = expression.args.get("timestamp") 794 795 return self.func("CONVERT_TZ", dt, from_tz, to_tz) 796 797 def attimezone_sql(self, expression: exp.AtTimeZone) -> str: 798 self.unsupported("AT TIME ZONE is not supported by MySQL") 799 return self.sql(expression.this) 800 801 def isascii_sql(self, expression: exp.IsAscii) -> str: 802 return f"REGEXP_LIKE({self.sql(expression.this)}, '^[[:ascii:]]*$')" 803 804 def ignorenulls_sql(self, expression: exp.IgnoreNulls) -> str: 805 # https://dev.mysql.com/doc/refman/8.4/en/window-function-descriptions.html 806 self.unsupported("MySQL does not support IGNORE NULLS.") 807 return self.sql(expression.this) 808 809 @unsupported_args("this") 810 def currentschema_sql(self, expression: exp.CurrentSchema) -> str: 811 return self.func("SCHEMA") 812 813 def partition_sql(self, expression: exp.Partition) -> str: 814 parent = expression.parent 815 if isinstance(parent, (exp.PartitionByRangeProperty, exp.PartitionByListProperty)): 816 return self.expressions(expression, flat=True) 817 return super().partition_sql(expression) 818 819 def _partition_by_sql( 820 self, expression: exp.PartitionByRangeProperty | exp.PartitionByListProperty, kind: str 821 ) -> str: 822 partitions = self.expressions(expression, key="partition_expressions", flat=True) 823 create = self.expressions(expression, key="create_expressions", flat=True) 824 return f"PARTITION BY {kind} ({partitions}) ({create})" 825 826 def partitionbyrangeproperty_sql(self, expression: exp.PartitionByRangeProperty) -> str: 827 return self._partition_by_sql(expression, "RANGE") 828 829 def partitionbylistproperty_sql(self, expression: exp.PartitionByListProperty) -> str: 830 return self._partition_by_sql(expression, "LIST") 831 832 def partitionlist_sql(self, expression: exp.PartitionList) -> str: 833 name = self.sql(expression, "this") 834 values = self.expressions(expression, flat=True) 835 return f"PARTITION {name} VALUES IN ({values})" 836 837 def partitionrange_sql(self, expression: exp.PartitionRange) -> str: 838 name = self.sql(expression, "this") 839 values = self.expressions(expression, flat=True) 840 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 =
{'analyze', 'restrict', 'release', 'cascade', 'having', 'iterate', 'select', 'inner', 'sql_calc_found_rows', 'when', 'hour_minute', 'reads', 'hour_second', 'float4', 'optimizer_costs', 'explain', 'day_second', 'longtext', 'unique', 'then', 'exit', 'set', 'range', 'blob', 'null', 'by', 'dense_rank', 'virtual', 'accessible', 'row_number', 'force', 'asensitive', 'index', 'decimal', 'union', 'utc_time', 'return', 'real', 'right', 'for', 'master_ssl_verify_server_cert', 'int2', 'constraint', 'left', 'varbinary', 'collate', 'separator', 'middleint', 'read', 'column', 'using', 'and', 'cursor', 'like', 'as', 'current_timestamp', 'numeric', 'distinctrow', 'leading', 'fetch', 'case', 'int3', 'float8', 'sql_small_result', 'ntile', 'starting', 'declare', 'sqlwarning', 'undo', 'inout', 'databases', 'out', 'year_month', 'write', 'into', 'enclosed', 'tinytext', 'double', 'system', 'current_date', 'regexp', 'minute_microsecond', 'tinyblob', 'usage', 'change', 'day_minute', 'localtime', 'cume_dist', 'minute_second', 'between', 'rename', 'kill', 'insert', 'div', 'exists', 'desc', 'leave', 'check', 'replace', 'default', 'sql_big_result', 'binary', 'join', 'delete', 'no_write_to_binlog', 'unsigned', 'maxvalue', 'natural', 'varcharacter', 'get', 'terminated', 'outfile', 'drop', 'key', 'loop', 'update', 'outer', 'call', 'if', 'resignal', 'low_priority', 'read_write', 'to', 'delayed', 'load', 'char', 'optimize', 'last_value', 'rlike', 'each', 'bigint', 'schemas', 'sqlexception', 'create', 'character', 'continue', 'show', 'before', 'linear', 'rank', 'current_user', 'from', 'int4', 'else', 'long', 'current_time', 'lead', 'xor', 'escaped', 'master_bind', 'signal', 'int8', 'primary', 'int', 'purge', 'float', 'lag', 'with', 'values', 'of', 'except', 'require', 'procedure', 'specific', 'utc_timestamp', 'precision', 'utc_date', 'group', 'generated', 'trailing', 'longblob', 'on', 'over', 'trigger', 'varying', 'in', 'infile', 'distinct', 'stored', 'recursive', 'lines', 'grouping', 'keys', 'is', 'sql', 'io_after_gtids', 'day_microsecond', 'unlock', 'convert', 'fulltext', 'dec', 'mediumint', 'zerofill', 'cross', 'high_priority', 'elseif', 'json_table', 'spatial', 'both', 'varchar', 'database', 'schema', 'row', 'false', 'groups', 'modifies', 'condition', 'or', 'io_before_gtids', 'cube', 'empty', 'integer', 'window', 'tinyint', 'nth_value', 'references', 'order', 'table', 'lock', 'deterministic', 'alter', 'describe', 'second_microsecond', 'ignore', 'grant', 'add', 'sensitive', 'int1', 'repeat', 'dual', 'mediumblob', 'use', 'rows', 'ssl', 'intersect', 'true', 'match', 'mod', 'revoke', 'function', 'day_hour', 'while', 'mediumtext', 'sqlstate', 'interval', 'insensitive', 'hour_microsecond', 'smallint', 'optionally', 'limit', 'first_value', 'localtimestamp', 'percent_rank', 'asc', 'lateral', 'all', 'where', 'partition', 'straight_join', 'foreign', 'not', 'option'}
def
makeinterval_sql( self: MySQLGenerator, expression: sqlglot.expressions.temporal.MakeInterval) -> str:
607 def makeinterval_sql(self: MySQLGenerator, expression: exp.MakeInterval) -> str: 608 intervals: list[exp.Interval] = [] 609 for arg_key, value in expression.args.items(): 610 if value is None: 611 continue 612 613 if isinstance(value, exp.Kwarg): 614 unit_name = _MAKE_INTERVAL_UNIT_ALIASES.get( 615 value.this.name.lower(), value.this.name.lower() 616 ) 617 value = value.expression 618 else: 619 unit_name = arg_key 620 621 intervals.append(exp.Interval(this=value.copy(), unit=exp.var(unit_name.upper()))) 622 623 if not intervals: 624 return self.function_fallback_sql(expression) 625 626 parent = expression.parent 627 sep = " - " if isinstance(parent, exp.Sub) and parent.expression is expression else " + " 628 629 return sep.join(self.sql(interval) for interval in intervals)
def
locate_properties( self, properties: sqlglot.expressions.properties.Properties) -> collections.defaultdict:
631 def locate_properties(self, properties: exp.Properties) -> defaultdict: 632 locations = super().locate_properties(properties) 633 634 # MySQL puts SQL SECURITY before VIEW but after the schema for functions/procedures 635 if isinstance(create := properties.parent, exp.Create) and create.kind == "VIEW": 636 post_schema = locations[exp.Properties.Location.POST_SCHEMA] 637 for i, p in enumerate(post_schema): 638 if isinstance(p, exp.SqlSecurityProperty): 639 post_schema.pop(i) 640 locations[self.SQL_SECURITY_VIEW_LOCATION].append(p) 641 break 642 643 return locations
def
computedcolumnconstraint_sql( self, expression: sqlglot.expressions.constraints.ComputedColumnConstraint) -> str:
671 def datatype_sql(self, expression: exp.DataType) -> str: 672 if ( 673 self.VARCHAR_REQUIRES_SIZE 674 and expression.is_type(exp.DType.VARCHAR) 675 and not expression.expressions 676 ): 677 # `VARCHAR` must always have a size - if it doesn't, we always generate `TEXT` 678 return "TEXT" 679 680 # https://dev.mysql.com/doc/refman/8.0/en/numeric-type-syntax.html 681 result = super().datatype_sql(expression) 682 if expression.this in self.UNSIGNED_TYPE_MAPPING: 683 result = f"{result} UNSIGNED" 684 685 return result
def
cast_sql( self, expression: sqlglot.expressions.functions.Cast, safe_prefix: str | None = None) -> str:
690 def cast_sql(self, expression: exp.Cast, safe_prefix: str | None = None) -> str: 691 if expression.to.this in self.TIMESTAMP_FUNC_TYPES: 692 return self.func("TIMESTAMP", expression.this) 693 694 to = self.CAST_MAPPING.get(expression.to.this) 695 696 if to: 697 expression.to.set("this", to) 698 return super().cast_sql(expression)
700 def show_sql(self, expression: exp.Show) -> str: 701 this = f" {expression.name}" 702 full = " FULL" if expression.args.get("full") else "" 703 global_ = " GLOBAL" if expression.args.get("global_") else "" 704 705 target = self.sql(expression, "target") 706 target = f" {target}" if target else "" 707 if expression.name in ("COLUMNS", "INDEX"): 708 target = f" FROM{target}" 709 elif expression.name == "GRANTS": 710 target = f" FOR{target}" 711 elif expression.name in ("LINKS", "PARTITIONS"): 712 target = f" ON{target}" if target else "" 713 elif expression.name == "PROJECTIONS": 714 target = f" ON TABLE{target}" if target else "" 715 716 db = self._prefixed_sql("FROM", expression, "db") 717 718 like = self._prefixed_sql("LIKE", expression, "like") 719 where = self.sql(expression, "where") 720 721 types = self.expressions(expression, key="types") 722 types = f" {types}" if types else types 723 query = self._prefixed_sql("FOR QUERY", expression, "query") 724 725 if expression.name == "PROFILE": 726 offset = self._prefixed_sql("OFFSET", expression, "offset") 727 limit = self._prefixed_sql("LIMIT", expression, "limit") 728 else: 729 offset = "" 730 limit = self._oldstyle_limit_sql(expression) 731 732 log = self._prefixed_sql("IN", expression, "log") 733 position = self._prefixed_sql("FROM", expression, "position") 734 735 channel = self._prefixed_sql("FOR CHANNEL", expression, "channel") 736 737 if expression.name == "ENGINE": 738 mutex_or_status = " MUTEX" if expression.args.get("mutex") else " STATUS" 739 else: 740 mutex_or_status = "" 741 742 for_table = self._prefixed_sql("FOR TABLE", expression, "for_table") 743 for_group = self._prefixed_sql("FOR GROUP", expression, "for_group") 744 for_user = self._prefixed_sql("FOR USER", expression, "for_user") 745 for_role = self._prefixed_sql("FOR ROLE", expression, "for_role") 746 into_outfile = self._prefixed_sql("INTO OUTFILE", expression, "into_outfile") 747 json = " JSON" if expression.args.get("json") else "" 748 749 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:
751 def alterrename_sql(self, expression: exp.AlterRename, include_to: bool = True) -> str: 752 """To avoid TO keyword in ALTER ... RENAME statements. 753 It's moved from Doris, because it's the same for all MySQL, Doris, and StarRocks. 754 """ 755 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.
777 def timestamptrunc_sql(self, expression: exp.TimestampTrunc) -> str: 778 unit = expression.args.get("unit") 779 780 # Pick an old-enough date to avoid negative timestamp diffs 781 start_ts = "'0000-01-01 00:00:00'" 782 783 # Source: https://stackoverflow.com/a/32955740 784 timestamp_diff = build_date_delta(exp.TimestampDiff)([unit, start_ts, expression.this]) 785 interval = exp.Interval(this=timestamp_diff, unit=unit) 786 dateadd = build_date_delta_with_interval(exp.DateAdd)([start_ts, interval]) 787 788 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
- 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
- AGGREGATE_FILTER_SUPPORTED
- 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
- 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
- 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
- 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
- add_sql
- and_sql
- or_sql
- xor_sql
- connector_sql
- bitwiseand_sql
- bitwiseleftshift_sql
- bitwisenot_sql
- bitwiseor_sql
- bitwiserightshift_sql
- bitwisexor_sql
- strtotime_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_sql
- chr_sql
- block_sql
- storedprocedure_sql
- ifblock_sql
- whileblock_sql
- execute_sql
- executesql_sql
- altermodifysqlsecurity_sql
- usingproperty_sql
- renameindex_sql