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