sqlglot.generators.exasol
1from __future__ import annotations 2 3import typing as t 4 5from sqlglot import exp, generator, transforms 6from sqlglot.dialects.dialect import ( 7 DATE_ADD_OR_SUB, 8 groupconcat_sql, 9 no_last_day_sql, 10 rename_func, 11 strposition_sql, 12 timestrtotime_sql, 13 timestamptrunc_sql, 14) 15from sqlglot.errors import UnsupportedError 16from sqlglot.generator import unsupported_args 17from sqlglot.optimizer.scope import build_scope 18from sqlglot.parsers.exasol import DATE_UNITS 19 20 21def _sha2_sql(self: ExasolGenerator, expression: exp.SHA2) -> str: 22 length = expression.text("length") 23 func_name = "HASH_SHA256" if length == "256" else "HASH_SHA512" 24 return self.func(func_name, expression.this) 25 26 27def _date_diff_sql(self: ExasolGenerator, expression: exp.DateDiff | exp.TsOrDsDiff) -> str: 28 unit = expression.text("unit").upper() or "DAY" 29 30 if unit not in DATE_UNITS: 31 self.unsupported(f"'{unit}' is not supported in Exasol.") 32 return self.function_fallback_sql(expression) 33 34 return self.func(f"{unit}S_BETWEEN", expression.this, expression.expression) 35 36 37# https://docs.exasol.com/db/latest/sql/select.htm#:~:text=If%20you%20have,local.x%3E10 38def _add_local_prefix_for_aliases(expression: exp.Expr) -> exp.Expr: 39 if isinstance(expression, exp.Select): 40 aliases: dict[str, bool] = { 41 alias.name: bool(alias.args.get("quoted")) 42 for sel in expression.selects 43 if isinstance(sel, exp.Alias) and (alias := sel.args.get("alias")) 44 } 45 46 table = expression.find(exp.Table) 47 table_ident = table.this if table else None 48 49 if ( 50 table_ident 51 and table_ident.name.upper() == "LOCAL" 52 and not bool(table_ident.args.get("quoted")) 53 ): 54 table_ident.replace(exp.to_identifier(table_ident.name.upper(), quoted=True)) 55 56 def prefix_local(node, visible_aliases: dict[str, bool]) -> exp.Expr: 57 if isinstance(node, exp.Column) and not node.table: 58 if node.name in visible_aliases: 59 return exp.Column( 60 this=exp.to_identifier(node.name, quoted=visible_aliases[node.name]), 61 table=exp.to_identifier("LOCAL", quoted=False), 62 ) 63 return node 64 65 for key in ("where", "group", "having"): 66 if arg := expression.args.get(key): 67 expression.set(key, arg.transform(lambda node: prefix_local(node, aliases))) 68 69 seen_aliases: dict[str, bool] = {} 70 new_selects: list[exp.Expr] = [] 71 for sel in expression.selects: 72 if isinstance(sel, exp.Alias): 73 inner = sel.this.transform(lambda node: prefix_local(node, seen_aliases)) 74 sel.set("this", inner) 75 76 alias_node = sel.args.get("alias") 77 78 seen_aliases[sel.alias] = bool(alias_node and getattr(alias_node, "quoted", False)) 79 new_selects.append(sel) 80 else: 81 new_selects.append(sel.transform(lambda node: prefix_local(node, seen_aliases))) 82 expression.set("expressions", new_selects) 83 84 return expression 85 86 87def _trunc_sql( 88 self: ExasolGenerator, kind: str, expression: exp.DateTrunc | exp.TimestampTrunc 89) -> str: 90 unit = expression.text("unit") 91 node = expression.this.this if isinstance(expression.this, exp.Cast) else expression.this 92 expr_sql = self.sql(node) 93 if isinstance(node, exp.Literal) and node.is_string: 94 expr_sql = ( 95 f"{kind} '{node.this.replace('T', ' ')}'" 96 if kind == "TIMESTAMP" 97 else f"DATE '{node.this}'" 98 ) 99 return f"DATE_TRUNC('{unit}', {expr_sql})" 100 101 102def _date_trunc_sql(self: ExasolGenerator, expression: exp.DateTrunc) -> str: 103 return _trunc_sql(self, "DATE", expression) 104 105 106def _timestamp_trunc_sql( 107 self: ExasolGenerator, expression: exp.DateTrunc | exp.TimestampTrunc 108) -> str: 109 return _trunc_sql(self, "TIMESTAMP", expression) 110 111 112def is_case_insensitive(node: exp.Expr) -> bool: 113 return isinstance(node, exp.Collate) and node.text("expression").upper() == "UTF8_LCASE" 114 115 116def _substring_index_sql(self: ExasolGenerator, expression: exp.SubstringIndex) -> str: 117 this = expression.this 118 delimiter = expression.args["delimiter"] 119 count_node = expression.args["count"] 120 count_sql = self.sql(expression, "count") 121 num = count_node.to_py() if count_node.is_number else 0 122 123 haystack_sql = self.sql(this) 124 if num == 0: 125 return self.func("SUBSTR", haystack_sql, "1", "0") 126 127 from_right = num < 0 128 direction = "-1" if from_right else "1" 129 occur = self.func("ABS", count_sql) if from_right else count_sql 130 131 delimiter_sql = self.sql(delimiter) 132 133 position = self.func( 134 "INSTR", 135 self.func("LOWER", haystack_sql) if is_case_insensitive(this) else haystack_sql, 136 self.func("LOWER", delimiter_sql) if is_case_insensitive(delimiter) else delimiter_sql, 137 direction, 138 occur, 139 ) 140 nullable_pos = self.func("NULLIF", position, "0") 141 142 if from_right: 143 start = self.func( 144 "NVL", f"{nullable_pos} + {self.func('LENGTH', delimiter_sql)}", direction 145 ) 146 return self.func("SUBSTR", haystack_sql, start) 147 148 length = self.func("NVL", f"{nullable_pos} - 1", self.func("LENGTH", haystack_sql)) 149 return self.func("SUBSTR", haystack_sql, direction, length) 150 151 152# https://docs.exasol.com/db/latest/sql/select.htm#:~:text=The%20select_list%20defines%20the%20columns%20of%20the%20result%20table.%20If%20*%20is%20used%2C%20all%20columns%20are%20listed.%20You%20can%20use%20an%20expression%20like%20t.*%20to%20list%20all%20columns%20of%20the%20table%20t%2C%20the%20view%20t%2C%20or%20the%20object%20with%20the%20table%20alias%20t. 153def _qualify_unscoped_star(expression: exp.Expr) -> exp.Expr: 154 """ 155 Exasol doesn't support a bare * alongside other select items, so we rewrite it 156 Rewrite: SELECT *, <other> FROM <Table> 157 Into: SELECT T.*, <other> FROM <Table> AS T 158 """ 159 160 if not isinstance(expression, exp.Select): 161 return expression 162 163 select_expressions = expression.expressions or [] 164 165 def is_bare_star(expr: exp.Expr) -> bool: 166 return isinstance(expr, exp.Star) and expr.this is None 167 168 has_other_expression = False 169 bare_star_expr: exp.Expr | None = None 170 for expr in select_expressions: 171 has_bare_star = is_bare_star(expr) 172 if has_bare_star and bare_star_expr is None: 173 bare_star_expr = expr 174 elif not has_bare_star: 175 has_other_expression = True 176 if bare_star_expr and has_other_expression: 177 break 178 179 if not (bare_star_expr and has_other_expression): 180 return expression 181 182 scope = build_scope(expression) 183 184 if not scope or not scope.selected_sources: 185 return expression 186 187 table_identifiers: list[exp.Identifier] = [] 188 189 for source_name, (source_expr, _) in scope.selected_sources.items(): 190 ident = ( 191 source_expr.this.copy() 192 if isinstance(source_expr, exp.Table) and isinstance(source_expr.this, exp.Identifier) 193 else exp.to_identifier(source_name) 194 ) 195 table_identifiers.append(ident) 196 197 qualified_star_columns = [ 198 exp.Column(this=bare_star_expr.copy(), table=ident) for ident in table_identifiers 199 ] 200 201 new_select_expressions: list[exp.Expr] = [] 202 203 for select_expr in select_expressions: 204 new_select_expressions.extend(qualified_star_columns) if is_bare_star( 205 select_expr 206 ) else new_select_expressions.append(select_expr) 207 208 expression.set("expressions", new_select_expressions) 209 return expression 210 211 212def _add_date_sql(self: ExasolGenerator, expression: DATE_ADD_OR_SUB) -> str: 213 interval = expression.expression if isinstance(expression.expression, exp.Interval) else None 214 215 unit = ( 216 (interval.text("unit") or "DAY").upper() 217 if interval is not None 218 else (expression.text("unit") or "DAY").upper() 219 ) 220 221 if unit not in DATE_UNITS: 222 self.unsupported(f"'{unit}' is not supported in Exasol.") 223 return self.function_fallback_sql(expression) 224 225 offset_expr: exp.Expr = expression.expression 226 if interval is not None: 227 offset_expr = interval.this 228 229 if isinstance(expression, exp.DateSub): 230 offset_expr = exp.Neg(this=offset_expr) 231 232 return self.func(f"ADD_{unit}S", expression.this, offset_expr) 233 234 235def _group_by_all(expression: exp.Expr) -> exp.Expr: 236 if not isinstance(expression, exp.Select): 237 return expression 238 239 group = expression.args.get("group") 240 if not group or not group.args.get("all"): 241 return expression 242 243 if expression.is_star: 244 if any(proj.find(exp.AggFunc) for proj in expression.expressions): 245 raise UnsupportedError( 246 "GROUP BY ALL with star projection and aggregates is not supported by Exasol" 247 ) 248 expression.set("distinct", exp.Distinct()) 249 expression.set("group", None) 250 return expression 251 252 group_positions = [ 253 exp.Literal.number(i) 254 for i, proj in enumerate(expression.expressions, start=1) 255 if not proj.find(exp.AggFunc) 256 ] 257 258 if not group_positions: 259 expression.set("group", None) 260 return expression 261 262 group.set("expressions", group_positions) 263 group.set("all", None) 264 265 return expression 266 267 268class ExasolGenerator(generator.Generator): 269 SELECT_KINDS: tuple[str, ...] = () 270 TRY_SUPPORTED = False 271 SUPPORTS_UESCAPE = False 272 SUPPORTS_DECODE_CASE = False 273 274 AFTER_HAVING_MODIFIER_TRANSFORMS = generator.AFTER_HAVING_MODIFIER_TRANSFORMS 275 276 # https://docs.exasol.com/db/latest/sql_references/data_types/datatypedetails.htm#StringDataType 277 STRING_TYPE_MAPPING: t.ClassVar = { 278 exp.DType.BLOB: "VARCHAR", 279 exp.DType.LONGBLOB: "VARCHAR", 280 exp.DType.LONGTEXT: "VARCHAR", 281 exp.DType.MEDIUMBLOB: "VARCHAR", 282 exp.DType.MEDIUMTEXT: "VARCHAR", 283 exp.DType.TINYBLOB: "VARCHAR", 284 exp.DType.TINYTEXT: "VARCHAR", 285 # https://docs.exasol.com/db/latest/sql_references/data_types/datatypealiases.htm 286 exp.DType.TEXT: "LONG VARCHAR", 287 exp.DType.VARBINARY: "VARCHAR", 288 } 289 290 # https://docs.exasol.com/db/latest/sql_references/data_types/datatypealiases.htm 291 TYPE_MAPPING = { 292 **generator.Generator.TYPE_MAPPING, 293 **STRING_TYPE_MAPPING, 294 exp.DType.TINYINT: "SMALLINT", 295 exp.DType.MEDIUMINT: "INT", 296 exp.DType.DECIMAL32: "DECIMAL", 297 exp.DType.DECIMAL64: "DECIMAL", 298 exp.DType.DECIMAL128: "DECIMAL", 299 exp.DType.DECIMAL256: "DECIMAL", 300 exp.DType.DATETIME: "TIMESTAMP", 301 exp.DType.TIMESTAMPTZ: "TIMESTAMP", 302 exp.DType.TIMESTAMPLTZ: "TIMESTAMP", 303 exp.DType.TIMESTAMPNTZ: "TIMESTAMP", 304 } 305 306 def datatype_sql(self, expression: exp.DataType) -> str: 307 # Exasol supports a fixed default precision of 3 for TIMESTAMP WITH LOCAL TIME ZONE 308 # and does not allow specifying a different custom precision 309 if expression.is_type(exp.DType.TIMESTAMPLTZ): 310 return "TIMESTAMP WITH LOCAL TIME ZONE" 311 312 return super().datatype_sql(expression) 313 314 TRANSFORMS = { 315 **generator.Generator.TRANSFORMS, 316 # https://docs.exasol.com/db/latest/sql_references/functions/alphabeticallistfunctions/every.htm 317 exp.All: rename_func("EVERY"), 318 # https://docs.exasol.com/db/latest/sql_references/functions/alphabeticallistfunctions/bit_and.htm 319 exp.BitwiseAnd: rename_func("BIT_AND"), 320 # https://docs.exasol.com/db/latest/sql_references/functions/alphabeticallistfunctions/bit_or.htm 321 exp.BitwiseOr: rename_func("BIT_OR"), 322 # https://docs.exasol.com/db/latest/sql_references/functions/alphabeticallistfunctions/bit_not.htm 323 exp.BitwiseNot: rename_func("BIT_NOT"), 324 # https://docs.exasol.com/db/latest/sql_references/functions/alphabeticallistfunctions/bit_lshift.htm 325 exp.BitwiseLeftShift: rename_func("BIT_LSHIFT"), 326 # https://docs.exasol.com/db/latest/sql_references/functions/alphabeticallistfunctions/bit_rshift.htm 327 exp.BitwiseRightShift: rename_func("BIT_RSHIFT"), 328 # https://docs.exasol.com/db/latest/sql_references/functions/alphabeticallistfunctions/bit_xor.htm 329 exp.BitwiseXor: rename_func("BIT_XOR"), 330 exp.CurrentSchema: lambda *_: "CURRENT_SCHEMA", 331 exp.DateDiff: _date_diff_sql, 332 exp.DateAdd: _add_date_sql, 333 exp.TsOrDsAdd: _add_date_sql, 334 exp.DateSub: _add_date_sql, 335 # https://docs.exasol.com/db/latest/sql_references/functions/alphabeticallistfunctions/div.htm#DIV 336 exp.IntDiv: rename_func("DIV"), 337 exp.TsOrDsDiff: _date_diff_sql, 338 exp.DateTrunc: _date_trunc_sql, 339 exp.DayOfWeek: lambda self, e: f"CAST(TO_CHAR({self.sql(e, 'this')}, 'D') AS INTEGER)", 340 exp.DatetimeTrunc: timestamptrunc_sql(), 341 exp.GroupConcat: lambda self, e: groupconcat_sql( 342 self, e, func_name="LISTAGG", within_group=True 343 ), 344 # https://docs.exasol.com/db/latest/sql_references/functions/alphabeticallistfunctions/edit_distance.htm#EDIT_DISTANCE 345 exp.Levenshtein: unsupported_args("ins_cost", "del_cost", "sub_cost", "max_dist")( 346 rename_func("EDIT_DISTANCE") 347 ), 348 # https://docs.exasol.com/db/latest/sql_references/functions/alphabeticallistfunctions/mod.htm 349 exp.Mod: rename_func("MOD"), 350 # https://docs.exasol.com/db/latest/sql_references/functions/alphabeticallistfunctions/from_posix_time.htm 351 exp.UnixToTime: lambda self, e: self.func("FROM_POSIX_TIME", e.this), 352 # https://docs.exasol.com/db/latest/sql_references/functions/alphabeticallistfunctions/rank.htm 353 exp.Rank: unsupported_args("expressions")(lambda *_: "RANK()"), 354 # https://docs.exasol.com/db/latest/sql_references/functions/alphabeticallistfunctions/dense_rank.htm 355 exp.DenseRank: unsupported_args("expressions")(lambda *_: "DENSE_RANK()"), 356 # https://docs.exasol.com/db/latest/sql_references/functions/alphabeticallistfunctions/regexp_substr.htm 357 exp.RegexpExtract: unsupported_args("parameters", "group")(rename_func("REGEXP_SUBSTR")), 358 # https://docs.exasol.com/db/latest/sql_references/functions/alphabeticallistfunctions/regexp_replace.htm 359 exp.RegexpReplace: unsupported_args("modifiers")(rename_func("REGEXP_REPLACE")), 360 # https://docs.exasol.com/db/latest/sql_references/functions/alphabeticallistfunctions/var_pop.htm 361 exp.VariancePop: rename_func("VAR_POP"), 362 # https://docs.exasol.com/db/latest/sql_references/functions/alphabeticallistfunctions/approximate_count_distinct.htm 363 exp.ApproxDistinct: unsupported_args("accuracy")(rename_func("APPROXIMATE_COUNT_DISTINCT")), 364 # https://docs.exasol.com/db/latest/sql_references/functions/alphabeticallistfunctions/to_char%20(datetime).htm 365 exp.TimeToStr: lambda self, e: self.func("TO_CHAR", e.this, self.format_time(e)), 366 exp.ToChar: lambda self, e: self.func("TO_CHAR", e.this, self.format_time(e)), 367 # https://docs.exasol.com/db/latest/sql_references/functions/alphabeticallistfunctions/to_date.htm 368 exp.TsOrDsToDate: lambda self, e: self.func("TO_DATE", e.this, self.format_time(e)), 369 exp.TimeStrToTime: timestrtotime_sql, 370 exp.TimestampTrunc: _timestamp_trunc_sql, 371 exp.StrToTime: lambda self, e: self.func("TO_DATE", e.this, self.format_time(e)), 372 exp.CurrentUser: lambda *_: "CURRENT_USER", 373 exp.AtTimeZone: lambda self, e: self.func( 374 "CONVERT_TZ", 375 e.this, 376 "'UTC'", 377 e.args.get("zone"), 378 ), 379 # https://docs.exasol.com/db/latest/sql_references/functions/alphabeticallistfunctions/instr.htm 380 exp.StrPosition: lambda self, e: strposition_sql( 381 self, e, func_name="INSTR", supports_position=True, supports_occurrence=True 382 ), 383 # https://docs.exasol.com/db/latest/sql_references/functions/alphabeticallistfunctions/hash_sha%5B1%5D.htm#HASH_SHA%5B1%5D 384 exp.SHA: rename_func("HASH_SHA"), 385 # https://docs.exasol.com/db/latest/sql_references/functions/alphabeticallistfunctions/hash_sha256.htm 386 # https://docs.exasol.com/db/latest/sql_references/functions/alphabeticallistfunctions/hash_sha512.htm 387 exp.SHA2: _sha2_sql, 388 exp.MD5: rename_func("HASH_MD5"), 389 # https://docs.exasol.com/db/latest/sql_references/functions/alphabeticallistfunctions/hashtype_md5.htm 390 exp.MD5Digest: rename_func("HASHTYPE_MD5"), 391 # https://docs.exasol.com/db/latest/sql/create_view.htm 392 exp.CommentColumnConstraint: lambda self, e: f"COMMENT IS {self.sql(e, 'this')}", 393 exp.Select: transforms.preprocess( 394 [ 395 _qualify_unscoped_star, 396 _add_local_prefix_for_aliases, 397 _group_by_all, 398 ] 399 ), 400 exp.SubstringIndex: _substring_index_sql, 401 exp.WeekOfYear: rename_func("WEEK"), 402 # https://docs.exasol.com/db/latest/sql_references/functions/alphabeticallistfunctions/to_date.htm 403 exp.Date: rename_func("TO_DATE"), 404 # https://docs.exasol.com/db/latest/sql_references/functions/alphabeticallistfunctions/to_timestamp.htm 405 exp.Timestamp: rename_func("TO_TIMESTAMP"), 406 exp.Quarter: lambda self, e: f"CEIL(MONTH(TO_DATE({self.sql(e, 'this')}))/3)", 407 exp.LastDay: no_last_day_sql, 408 } 409 410 # https://docs.exasol.com/db/7.1/sql_references/system_tables/metadata/exa_sql_keywords.htm 411 RESERVED_KEYWORDS = { 412 "absolute", 413 "action", 414 "add", 415 "after", 416 "all", 417 "allocate", 418 "alter", 419 "and", 420 "any", 421 "append", 422 "are", 423 "array", 424 "as", 425 "asc", 426 "asensitive", 427 "assertion", 428 "at", 429 "attribute", 430 "authid", 431 "authorization", 432 "before", 433 "begin", 434 "between", 435 "bigint", 436 "binary", 437 "bit", 438 "blob", 439 "blocked", 440 "bool", 441 "boolean", 442 "both", 443 "by", 444 "byte", 445 "call", 446 "called", 447 "cardinality", 448 "cascade", 449 "cascaded", 450 "case", 451 "casespecific", 452 "cast", 453 "catalog", 454 "chain", 455 "char", 456 "character", 457 "character_set_catalog", 458 "character_set_name", 459 "character_set_schema", 460 "characteristics", 461 "check", 462 "checked", 463 "clob", 464 "close", 465 "coalesce", 466 "collate", 467 "collation", 468 "collation_catalog", 469 "collation_name", 470 "collation_schema", 471 "column", 472 "commit", 473 "condition", 474 "connect_by_iscycle", 475 "connect_by_isleaf", 476 "connect_by_root", 477 "connection", 478 "constant", 479 "constraint", 480 "constraint_state_default", 481 "constraints", 482 "constructor", 483 "contains", 484 "continue", 485 "control", 486 "convert", 487 "corresponding", 488 "create", 489 "cs", 490 "csv", 491 "cube", 492 "current", 493 "current_cluster", 494 "current_cluster_uid", 495 "current_date", 496 "current_path", 497 "current_role", 498 "current_schema", 499 "current_session", 500 "current_statement", 501 "current_time", 502 "current_timestamp", 503 "current_user", 504 "cursor", 505 "cycle", 506 "data", 507 "datalink", 508 "datetime_interval_code", 509 "datetime_interval_precision", 510 "day", 511 "dbtimezone", 512 "deallocate", 513 "dec", 514 "decimal", 515 "declare", 516 "default", 517 "default_like_escape_character", 518 "deferrable", 519 "deferred", 520 "defined", 521 "definer", 522 "delete", 523 "deref", 524 "derived", 525 "desc", 526 "describe", 527 "descriptor", 528 "deterministic", 529 "disable", 530 "disabled", 531 "disconnect", 532 "dispatch", 533 "distinct", 534 "dlurlcomplete", 535 "dlurlpath", 536 "dlurlpathonly", 537 "dlurlscheme", 538 "dlurlserver", 539 "dlvalue", 540 "do", 541 "domain", 542 "double", 543 "drop", 544 "dynamic", 545 "dynamic_function", 546 "dynamic_function_code", 547 "each", 548 "else", 549 "elseif", 550 "elsif", 551 "emits", 552 "enable", 553 "enabled", 554 "end", 555 "end-exec", 556 "endif", 557 "enforce", 558 "equals", 559 "errors", 560 "escape", 561 "except", 562 "exception", 563 "exec", 564 "execute", 565 "exists", 566 "exit", 567 "export", 568 "external", 569 "extract", 570 "false", 571 "fbv", 572 "fetch", 573 "file", 574 "final", 575 "first", 576 "float", 577 "following", 578 "for", 579 "forall", 580 "force", 581 "format", 582 "found", 583 "free", 584 "from", 585 "fs", 586 "full", 587 "function", 588 "general", 589 "generated", 590 "geometry", 591 "get", 592 "global", 593 "go", 594 "goto", 595 "grant", 596 "granted", 597 "group", 598 "group_concat", 599 "grouping", 600 "groups", 601 "hashtype", 602 "hashtype_format", 603 "having", 604 "high", 605 "hold", 606 "hour", 607 "identity", 608 "if", 609 "ifnull", 610 "immediate", 611 "impersonate", 612 "implementation", 613 "import", 614 "in", 615 "index", 616 "indicator", 617 "inner", 618 "inout", 619 "input", 620 "insensitive", 621 "insert", 622 "instance", 623 "instantiable", 624 "int", 625 "integer", 626 "integrity", 627 "intersect", 628 "interval", 629 "into", 630 "inverse", 631 "invoker", 632 "is", 633 "iterate", 634 "join", 635 "key_member", 636 "key_type", 637 "large", 638 "last", 639 "lateral", 640 "ldap", 641 "leading", 642 "leave", 643 "left", 644 "level", 645 "like", 646 "limit", 647 "listagg", 648 "localtime", 649 "localtimestamp", 650 "locator", 651 "log", 652 "longvarchar", 653 "loop", 654 "low", 655 "map", 656 "match", 657 "matched", 658 "merge", 659 "method", 660 "minus", 661 "minute", 662 "mod", 663 "modifies", 664 "modify", 665 "module", 666 "month", 667 "names", 668 "national", 669 "natural", 670 "nchar", 671 "nclob", 672 "new", 673 "next", 674 "nls_date_format", 675 "nls_date_language", 676 "nls_first_day_of_week", 677 "nls_numeric_characters", 678 "nls_timestamp_format", 679 "no", 680 "nocycle", 681 "nologging", 682 "none", 683 "not", 684 "null", 685 "nullif", 686 "number", 687 "numeric", 688 "nvarchar", 689 "nvarchar2", 690 "object", 691 "of", 692 "off", 693 "old", 694 "on", 695 "only", 696 "open", 697 "option", 698 "options", 699 "or", 700 "order", 701 "ordering", 702 "ordinality", 703 "others", 704 "out", 705 "outer", 706 "output", 707 "over", 708 "overlaps", 709 "overlay", 710 "overriding", 711 "pad", 712 "parallel_enable", 713 "parameter", 714 "parameter_specific_catalog", 715 "parameter_specific_name", 716 "parameter_specific_schema", 717 "parquet", 718 "partial", 719 "path", 720 "permission", 721 "placing", 722 "plus", 723 "preceding", 724 "preferring", 725 "prepare", 726 "preserve", 727 "prior", 728 "privileges", 729 "procedure", 730 "profile", 731 "qualify", 732 "random", 733 "range", 734 "read", 735 "reads", 736 "real", 737 "recovery", 738 "recursive", 739 "ref", 740 "references", 741 "referencing", 742 "refresh", 743 "regexp_like", 744 "relative", 745 "release", 746 "rename", 747 "repeat", 748 "replace", 749 "restore", 750 "restrict", 751 "result", 752 "return", 753 "returned_length", 754 "returned_octet_length", 755 "returns", 756 "revoke", 757 "right", 758 "rollback", 759 "rollup", 760 "routine", 761 "row", 762 "rows", 763 "rowtype", 764 "savepoint", 765 "schema", 766 "scope", 767 "scope_user", 768 "script", 769 "scroll", 770 "search", 771 "second", 772 "section", 773 "security", 774 "select", 775 "selective", 776 "self", 777 "sensitive", 778 "separator", 779 "sequence", 780 "session", 781 "session_user", 782 "sessiontimezone", 783 "set", 784 "sets", 785 "shortint", 786 "similar", 787 "smallint", 788 "some", 789 "source", 790 "space", 791 "specific", 792 "specifictype", 793 "sql", 794 "sql_bigint", 795 "sql_bit", 796 "sql_char", 797 "sql_date", 798 "sql_decimal", 799 "sql_double", 800 "sql_float", 801 "sql_integer", 802 "sql_longvarchar", 803 "sql_numeric", 804 "sql_preprocessor_script", 805 "sql_real", 806 "sql_smallint", 807 "sql_timestamp", 808 "sql_tinyint", 809 "sql_type_date", 810 "sql_type_timestamp", 811 "sql_varchar", 812 "sqlexception", 813 "sqlstate", 814 "sqlwarning", 815 "start", 816 "state", 817 "statement", 818 "static", 819 "structure", 820 "style", 821 "substring", 822 "subtype", 823 "sysdate", 824 "system", 825 "system_user", 826 "systimestamp", 827 "table", 828 "temporary", 829 "text", 830 "then", 831 "time", 832 "timestamp", 833 "timezone_hour", 834 "timezone_minute", 835 "tinyint", 836 "to", 837 "trailing", 838 "transaction", 839 "transform", 840 "transforms", 841 "translation", 842 "treat", 843 "trigger", 844 "trim", 845 "true", 846 "truncate", 847 "under", 848 "union", 849 "unique", 850 "unknown", 851 "unlink", 852 "unnest", 853 "until", 854 "update", 855 "usage", 856 "user", 857 "using", 858 "value", 859 "values", 860 "varchar", 861 "varchar2", 862 "varray", 863 "verify", 864 "view", 865 "when", 866 "whenever", 867 "where", 868 "while", 869 "window", 870 "with", 871 "within", 872 "without", 873 "work", 874 "year", 875 "yes", 876 "zone", 877 } 878 879 def converttimezone_sql(self, expression: exp.ConvertTimezone) -> str: 880 from_tz = expression.args.get("source_tz") 881 to_tz = expression.args.get("target_tz") 882 datetime = expression.args.get("timestamp") 883 options = expression.args.get("options") 884 885 return self.func("CONVERT_TZ", datetime, from_tz, to_tz, options) 886 887 def if_sql(self, expression: exp.If) -> str: 888 this = self.sql(expression, "this") 889 true = self.sql(expression, "true") 890 false = self.sql(expression, "false") 891 return f"IF {this} THEN {true} ELSE {false} ENDIF" 892 893 def collate_sql(self, expression: exp.Collate) -> str: 894 return self.sql(expression.this) 895 896 def jsonextract_sql(self, expression: exp.JSONExtract) -> str: 897 sql = self.func( 898 "JSON_EXTRACT", expression.this, expression.expression, *expression.expressions 899 ) 900 901 emits = self.sql(expression, "emits") 902 if emits: 903 sql = f"{sql} EMITS {emits}" 904 905 return sql 906 907 @unsupported_args("flag") 908 def regexplike_sql(self, expression: exp.RegexpLike) -> str: 909 if not expression.args.get("full_match"): 910 pattern = expression.expression 911 if pattern.is_string: 912 expression.set("expression", exp.Literal.string(f".*{pattern.name}.*")) 913 else: 914 expression.set( 915 "expression", 916 exp.Paren( 917 this=exp.Concat( 918 expressions=[ 919 exp.Literal.string(".*"), 920 pattern, 921 exp.Literal.string(".*"), 922 ] 923 ) 924 ), 925 ) 926 return self.binary(expression, "REGEXP_LIKE")
269class ExasolGenerator(generator.Generator): 270 SELECT_KINDS: tuple[str, ...] = () 271 TRY_SUPPORTED = False 272 SUPPORTS_UESCAPE = False 273 SUPPORTS_DECODE_CASE = False 274 275 AFTER_HAVING_MODIFIER_TRANSFORMS = generator.AFTER_HAVING_MODIFIER_TRANSFORMS 276 277 # https://docs.exasol.com/db/latest/sql_references/data_types/datatypedetails.htm#StringDataType 278 STRING_TYPE_MAPPING: t.ClassVar = { 279 exp.DType.BLOB: "VARCHAR", 280 exp.DType.LONGBLOB: "VARCHAR", 281 exp.DType.LONGTEXT: "VARCHAR", 282 exp.DType.MEDIUMBLOB: "VARCHAR", 283 exp.DType.MEDIUMTEXT: "VARCHAR", 284 exp.DType.TINYBLOB: "VARCHAR", 285 exp.DType.TINYTEXT: "VARCHAR", 286 # https://docs.exasol.com/db/latest/sql_references/data_types/datatypealiases.htm 287 exp.DType.TEXT: "LONG VARCHAR", 288 exp.DType.VARBINARY: "VARCHAR", 289 } 290 291 # https://docs.exasol.com/db/latest/sql_references/data_types/datatypealiases.htm 292 TYPE_MAPPING = { 293 **generator.Generator.TYPE_MAPPING, 294 **STRING_TYPE_MAPPING, 295 exp.DType.TINYINT: "SMALLINT", 296 exp.DType.MEDIUMINT: "INT", 297 exp.DType.DECIMAL32: "DECIMAL", 298 exp.DType.DECIMAL64: "DECIMAL", 299 exp.DType.DECIMAL128: "DECIMAL", 300 exp.DType.DECIMAL256: "DECIMAL", 301 exp.DType.DATETIME: "TIMESTAMP", 302 exp.DType.TIMESTAMPTZ: "TIMESTAMP", 303 exp.DType.TIMESTAMPLTZ: "TIMESTAMP", 304 exp.DType.TIMESTAMPNTZ: "TIMESTAMP", 305 } 306 307 def datatype_sql(self, expression: exp.DataType) -> str: 308 # Exasol supports a fixed default precision of 3 for TIMESTAMP WITH LOCAL TIME ZONE 309 # and does not allow specifying a different custom precision 310 if expression.is_type(exp.DType.TIMESTAMPLTZ): 311 return "TIMESTAMP WITH LOCAL TIME ZONE" 312 313 return super().datatype_sql(expression) 314 315 TRANSFORMS = { 316 **generator.Generator.TRANSFORMS, 317 # https://docs.exasol.com/db/latest/sql_references/functions/alphabeticallistfunctions/every.htm 318 exp.All: rename_func("EVERY"), 319 # https://docs.exasol.com/db/latest/sql_references/functions/alphabeticallistfunctions/bit_and.htm 320 exp.BitwiseAnd: rename_func("BIT_AND"), 321 # https://docs.exasol.com/db/latest/sql_references/functions/alphabeticallistfunctions/bit_or.htm 322 exp.BitwiseOr: rename_func("BIT_OR"), 323 # https://docs.exasol.com/db/latest/sql_references/functions/alphabeticallistfunctions/bit_not.htm 324 exp.BitwiseNot: rename_func("BIT_NOT"), 325 # https://docs.exasol.com/db/latest/sql_references/functions/alphabeticallistfunctions/bit_lshift.htm 326 exp.BitwiseLeftShift: rename_func("BIT_LSHIFT"), 327 # https://docs.exasol.com/db/latest/sql_references/functions/alphabeticallistfunctions/bit_rshift.htm 328 exp.BitwiseRightShift: rename_func("BIT_RSHIFT"), 329 # https://docs.exasol.com/db/latest/sql_references/functions/alphabeticallistfunctions/bit_xor.htm 330 exp.BitwiseXor: rename_func("BIT_XOR"), 331 exp.CurrentSchema: lambda *_: "CURRENT_SCHEMA", 332 exp.DateDiff: _date_diff_sql, 333 exp.DateAdd: _add_date_sql, 334 exp.TsOrDsAdd: _add_date_sql, 335 exp.DateSub: _add_date_sql, 336 # https://docs.exasol.com/db/latest/sql_references/functions/alphabeticallistfunctions/div.htm#DIV 337 exp.IntDiv: rename_func("DIV"), 338 exp.TsOrDsDiff: _date_diff_sql, 339 exp.DateTrunc: _date_trunc_sql, 340 exp.DayOfWeek: lambda self, e: f"CAST(TO_CHAR({self.sql(e, 'this')}, 'D') AS INTEGER)", 341 exp.DatetimeTrunc: timestamptrunc_sql(), 342 exp.GroupConcat: lambda self, e: groupconcat_sql( 343 self, e, func_name="LISTAGG", within_group=True 344 ), 345 # https://docs.exasol.com/db/latest/sql_references/functions/alphabeticallistfunctions/edit_distance.htm#EDIT_DISTANCE 346 exp.Levenshtein: unsupported_args("ins_cost", "del_cost", "sub_cost", "max_dist")( 347 rename_func("EDIT_DISTANCE") 348 ), 349 # https://docs.exasol.com/db/latest/sql_references/functions/alphabeticallistfunctions/mod.htm 350 exp.Mod: rename_func("MOD"), 351 # https://docs.exasol.com/db/latest/sql_references/functions/alphabeticallistfunctions/from_posix_time.htm 352 exp.UnixToTime: lambda self, e: self.func("FROM_POSIX_TIME", e.this), 353 # https://docs.exasol.com/db/latest/sql_references/functions/alphabeticallistfunctions/rank.htm 354 exp.Rank: unsupported_args("expressions")(lambda *_: "RANK()"), 355 # https://docs.exasol.com/db/latest/sql_references/functions/alphabeticallistfunctions/dense_rank.htm 356 exp.DenseRank: unsupported_args("expressions")(lambda *_: "DENSE_RANK()"), 357 # https://docs.exasol.com/db/latest/sql_references/functions/alphabeticallistfunctions/regexp_substr.htm 358 exp.RegexpExtract: unsupported_args("parameters", "group")(rename_func("REGEXP_SUBSTR")), 359 # https://docs.exasol.com/db/latest/sql_references/functions/alphabeticallistfunctions/regexp_replace.htm 360 exp.RegexpReplace: unsupported_args("modifiers")(rename_func("REGEXP_REPLACE")), 361 # https://docs.exasol.com/db/latest/sql_references/functions/alphabeticallistfunctions/var_pop.htm 362 exp.VariancePop: rename_func("VAR_POP"), 363 # https://docs.exasol.com/db/latest/sql_references/functions/alphabeticallistfunctions/approximate_count_distinct.htm 364 exp.ApproxDistinct: unsupported_args("accuracy")(rename_func("APPROXIMATE_COUNT_DISTINCT")), 365 # https://docs.exasol.com/db/latest/sql_references/functions/alphabeticallistfunctions/to_char%20(datetime).htm 366 exp.TimeToStr: lambda self, e: self.func("TO_CHAR", e.this, self.format_time(e)), 367 exp.ToChar: lambda self, e: self.func("TO_CHAR", e.this, self.format_time(e)), 368 # https://docs.exasol.com/db/latest/sql_references/functions/alphabeticallistfunctions/to_date.htm 369 exp.TsOrDsToDate: lambda self, e: self.func("TO_DATE", e.this, self.format_time(e)), 370 exp.TimeStrToTime: timestrtotime_sql, 371 exp.TimestampTrunc: _timestamp_trunc_sql, 372 exp.StrToTime: lambda self, e: self.func("TO_DATE", e.this, self.format_time(e)), 373 exp.CurrentUser: lambda *_: "CURRENT_USER", 374 exp.AtTimeZone: lambda self, e: self.func( 375 "CONVERT_TZ", 376 e.this, 377 "'UTC'", 378 e.args.get("zone"), 379 ), 380 # https://docs.exasol.com/db/latest/sql_references/functions/alphabeticallistfunctions/instr.htm 381 exp.StrPosition: lambda self, e: strposition_sql( 382 self, e, func_name="INSTR", supports_position=True, supports_occurrence=True 383 ), 384 # https://docs.exasol.com/db/latest/sql_references/functions/alphabeticallistfunctions/hash_sha%5B1%5D.htm#HASH_SHA%5B1%5D 385 exp.SHA: rename_func("HASH_SHA"), 386 # https://docs.exasol.com/db/latest/sql_references/functions/alphabeticallistfunctions/hash_sha256.htm 387 # https://docs.exasol.com/db/latest/sql_references/functions/alphabeticallistfunctions/hash_sha512.htm 388 exp.SHA2: _sha2_sql, 389 exp.MD5: rename_func("HASH_MD5"), 390 # https://docs.exasol.com/db/latest/sql_references/functions/alphabeticallistfunctions/hashtype_md5.htm 391 exp.MD5Digest: rename_func("HASHTYPE_MD5"), 392 # https://docs.exasol.com/db/latest/sql/create_view.htm 393 exp.CommentColumnConstraint: lambda self, e: f"COMMENT IS {self.sql(e, 'this')}", 394 exp.Select: transforms.preprocess( 395 [ 396 _qualify_unscoped_star, 397 _add_local_prefix_for_aliases, 398 _group_by_all, 399 ] 400 ), 401 exp.SubstringIndex: _substring_index_sql, 402 exp.WeekOfYear: rename_func("WEEK"), 403 # https://docs.exasol.com/db/latest/sql_references/functions/alphabeticallistfunctions/to_date.htm 404 exp.Date: rename_func("TO_DATE"), 405 # https://docs.exasol.com/db/latest/sql_references/functions/alphabeticallistfunctions/to_timestamp.htm 406 exp.Timestamp: rename_func("TO_TIMESTAMP"), 407 exp.Quarter: lambda self, e: f"CEIL(MONTH(TO_DATE({self.sql(e, 'this')}))/3)", 408 exp.LastDay: no_last_day_sql, 409 } 410 411 # https://docs.exasol.com/db/7.1/sql_references/system_tables/metadata/exa_sql_keywords.htm 412 RESERVED_KEYWORDS = { 413 "absolute", 414 "action", 415 "add", 416 "after", 417 "all", 418 "allocate", 419 "alter", 420 "and", 421 "any", 422 "append", 423 "are", 424 "array", 425 "as", 426 "asc", 427 "asensitive", 428 "assertion", 429 "at", 430 "attribute", 431 "authid", 432 "authorization", 433 "before", 434 "begin", 435 "between", 436 "bigint", 437 "binary", 438 "bit", 439 "blob", 440 "blocked", 441 "bool", 442 "boolean", 443 "both", 444 "by", 445 "byte", 446 "call", 447 "called", 448 "cardinality", 449 "cascade", 450 "cascaded", 451 "case", 452 "casespecific", 453 "cast", 454 "catalog", 455 "chain", 456 "char", 457 "character", 458 "character_set_catalog", 459 "character_set_name", 460 "character_set_schema", 461 "characteristics", 462 "check", 463 "checked", 464 "clob", 465 "close", 466 "coalesce", 467 "collate", 468 "collation", 469 "collation_catalog", 470 "collation_name", 471 "collation_schema", 472 "column", 473 "commit", 474 "condition", 475 "connect_by_iscycle", 476 "connect_by_isleaf", 477 "connect_by_root", 478 "connection", 479 "constant", 480 "constraint", 481 "constraint_state_default", 482 "constraints", 483 "constructor", 484 "contains", 485 "continue", 486 "control", 487 "convert", 488 "corresponding", 489 "create", 490 "cs", 491 "csv", 492 "cube", 493 "current", 494 "current_cluster", 495 "current_cluster_uid", 496 "current_date", 497 "current_path", 498 "current_role", 499 "current_schema", 500 "current_session", 501 "current_statement", 502 "current_time", 503 "current_timestamp", 504 "current_user", 505 "cursor", 506 "cycle", 507 "data", 508 "datalink", 509 "datetime_interval_code", 510 "datetime_interval_precision", 511 "day", 512 "dbtimezone", 513 "deallocate", 514 "dec", 515 "decimal", 516 "declare", 517 "default", 518 "default_like_escape_character", 519 "deferrable", 520 "deferred", 521 "defined", 522 "definer", 523 "delete", 524 "deref", 525 "derived", 526 "desc", 527 "describe", 528 "descriptor", 529 "deterministic", 530 "disable", 531 "disabled", 532 "disconnect", 533 "dispatch", 534 "distinct", 535 "dlurlcomplete", 536 "dlurlpath", 537 "dlurlpathonly", 538 "dlurlscheme", 539 "dlurlserver", 540 "dlvalue", 541 "do", 542 "domain", 543 "double", 544 "drop", 545 "dynamic", 546 "dynamic_function", 547 "dynamic_function_code", 548 "each", 549 "else", 550 "elseif", 551 "elsif", 552 "emits", 553 "enable", 554 "enabled", 555 "end", 556 "end-exec", 557 "endif", 558 "enforce", 559 "equals", 560 "errors", 561 "escape", 562 "except", 563 "exception", 564 "exec", 565 "execute", 566 "exists", 567 "exit", 568 "export", 569 "external", 570 "extract", 571 "false", 572 "fbv", 573 "fetch", 574 "file", 575 "final", 576 "first", 577 "float", 578 "following", 579 "for", 580 "forall", 581 "force", 582 "format", 583 "found", 584 "free", 585 "from", 586 "fs", 587 "full", 588 "function", 589 "general", 590 "generated", 591 "geometry", 592 "get", 593 "global", 594 "go", 595 "goto", 596 "grant", 597 "granted", 598 "group", 599 "group_concat", 600 "grouping", 601 "groups", 602 "hashtype", 603 "hashtype_format", 604 "having", 605 "high", 606 "hold", 607 "hour", 608 "identity", 609 "if", 610 "ifnull", 611 "immediate", 612 "impersonate", 613 "implementation", 614 "import", 615 "in", 616 "index", 617 "indicator", 618 "inner", 619 "inout", 620 "input", 621 "insensitive", 622 "insert", 623 "instance", 624 "instantiable", 625 "int", 626 "integer", 627 "integrity", 628 "intersect", 629 "interval", 630 "into", 631 "inverse", 632 "invoker", 633 "is", 634 "iterate", 635 "join", 636 "key_member", 637 "key_type", 638 "large", 639 "last", 640 "lateral", 641 "ldap", 642 "leading", 643 "leave", 644 "left", 645 "level", 646 "like", 647 "limit", 648 "listagg", 649 "localtime", 650 "localtimestamp", 651 "locator", 652 "log", 653 "longvarchar", 654 "loop", 655 "low", 656 "map", 657 "match", 658 "matched", 659 "merge", 660 "method", 661 "minus", 662 "minute", 663 "mod", 664 "modifies", 665 "modify", 666 "module", 667 "month", 668 "names", 669 "national", 670 "natural", 671 "nchar", 672 "nclob", 673 "new", 674 "next", 675 "nls_date_format", 676 "nls_date_language", 677 "nls_first_day_of_week", 678 "nls_numeric_characters", 679 "nls_timestamp_format", 680 "no", 681 "nocycle", 682 "nologging", 683 "none", 684 "not", 685 "null", 686 "nullif", 687 "number", 688 "numeric", 689 "nvarchar", 690 "nvarchar2", 691 "object", 692 "of", 693 "off", 694 "old", 695 "on", 696 "only", 697 "open", 698 "option", 699 "options", 700 "or", 701 "order", 702 "ordering", 703 "ordinality", 704 "others", 705 "out", 706 "outer", 707 "output", 708 "over", 709 "overlaps", 710 "overlay", 711 "overriding", 712 "pad", 713 "parallel_enable", 714 "parameter", 715 "parameter_specific_catalog", 716 "parameter_specific_name", 717 "parameter_specific_schema", 718 "parquet", 719 "partial", 720 "path", 721 "permission", 722 "placing", 723 "plus", 724 "preceding", 725 "preferring", 726 "prepare", 727 "preserve", 728 "prior", 729 "privileges", 730 "procedure", 731 "profile", 732 "qualify", 733 "random", 734 "range", 735 "read", 736 "reads", 737 "real", 738 "recovery", 739 "recursive", 740 "ref", 741 "references", 742 "referencing", 743 "refresh", 744 "regexp_like", 745 "relative", 746 "release", 747 "rename", 748 "repeat", 749 "replace", 750 "restore", 751 "restrict", 752 "result", 753 "return", 754 "returned_length", 755 "returned_octet_length", 756 "returns", 757 "revoke", 758 "right", 759 "rollback", 760 "rollup", 761 "routine", 762 "row", 763 "rows", 764 "rowtype", 765 "savepoint", 766 "schema", 767 "scope", 768 "scope_user", 769 "script", 770 "scroll", 771 "search", 772 "second", 773 "section", 774 "security", 775 "select", 776 "selective", 777 "self", 778 "sensitive", 779 "separator", 780 "sequence", 781 "session", 782 "session_user", 783 "sessiontimezone", 784 "set", 785 "sets", 786 "shortint", 787 "similar", 788 "smallint", 789 "some", 790 "source", 791 "space", 792 "specific", 793 "specifictype", 794 "sql", 795 "sql_bigint", 796 "sql_bit", 797 "sql_char", 798 "sql_date", 799 "sql_decimal", 800 "sql_double", 801 "sql_float", 802 "sql_integer", 803 "sql_longvarchar", 804 "sql_numeric", 805 "sql_preprocessor_script", 806 "sql_real", 807 "sql_smallint", 808 "sql_timestamp", 809 "sql_tinyint", 810 "sql_type_date", 811 "sql_type_timestamp", 812 "sql_varchar", 813 "sqlexception", 814 "sqlstate", 815 "sqlwarning", 816 "start", 817 "state", 818 "statement", 819 "static", 820 "structure", 821 "style", 822 "substring", 823 "subtype", 824 "sysdate", 825 "system", 826 "system_user", 827 "systimestamp", 828 "table", 829 "temporary", 830 "text", 831 "then", 832 "time", 833 "timestamp", 834 "timezone_hour", 835 "timezone_minute", 836 "tinyint", 837 "to", 838 "trailing", 839 "transaction", 840 "transform", 841 "transforms", 842 "translation", 843 "treat", 844 "trigger", 845 "trim", 846 "true", 847 "truncate", 848 "under", 849 "union", 850 "unique", 851 "unknown", 852 "unlink", 853 "unnest", 854 "until", 855 "update", 856 "usage", 857 "user", 858 "using", 859 "value", 860 "values", 861 "varchar", 862 "varchar2", 863 "varray", 864 "verify", 865 "view", 866 "when", 867 "whenever", 868 "where", 869 "while", 870 "window", 871 "with", 872 "within", 873 "without", 874 "work", 875 "year", 876 "yes", 877 "zone", 878 } 879 880 def converttimezone_sql(self, expression: exp.ConvertTimezone) -> str: 881 from_tz = expression.args.get("source_tz") 882 to_tz = expression.args.get("target_tz") 883 datetime = expression.args.get("timestamp") 884 options = expression.args.get("options") 885 886 return self.func("CONVERT_TZ", datetime, from_tz, to_tz, options) 887 888 def if_sql(self, expression: exp.If) -> str: 889 this = self.sql(expression, "this") 890 true = self.sql(expression, "true") 891 false = self.sql(expression, "false") 892 return f"IF {this} THEN {true} ELSE {false} ENDIF" 893 894 def collate_sql(self, expression: exp.Collate) -> str: 895 return self.sql(expression.this) 896 897 def jsonextract_sql(self, expression: exp.JSONExtract) -> str: 898 sql = self.func( 899 "JSON_EXTRACT", expression.this, expression.expression, *expression.expressions 900 ) 901 902 emits = self.sql(expression, "emits") 903 if emits: 904 sql = f"{sql} EMITS {emits}" 905 906 return sql 907 908 @unsupported_args("flag") 909 def regexplike_sql(self, expression: exp.RegexpLike) -> str: 910 if not expression.args.get("full_match"): 911 pattern = expression.expression 912 if pattern.is_string: 913 expression.set("expression", exp.Literal.string(f".*{pattern.name}.*")) 914 else: 915 expression.set( 916 "expression", 917 exp.Paren( 918 this=exp.Concat( 919 expressions=[ 920 exp.Literal.string(".*"), 921 pattern, 922 exp.Literal.string(".*"), 923 ] 924 ) 925 ), 926 ) 927 return self.binary(expression, "REGEXP_LIKE")
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
STRING_TYPE_MAPPING: ClassVar =
{<DType.BLOB: 'BLOB'>: 'VARCHAR', <DType.LONGBLOB: 'LONGBLOB'>: 'VARCHAR', <DType.LONGTEXT: 'LONGTEXT'>: 'VARCHAR', <DType.MEDIUMBLOB: 'MEDIUMBLOB'>: 'VARCHAR', <DType.MEDIUMTEXT: 'MEDIUMTEXT'>: 'VARCHAR', <DType.TINYBLOB: 'TINYBLOB'>: 'VARCHAR', <DType.TINYTEXT: 'TINYTEXT'>: 'VARCHAR', <DType.TEXT: 'TEXT'>: 'LONG VARCHAR', <DType.VARBINARY: 'VARBINARY'>: 'VARCHAR'}
TYPE_MAPPING =
{<DType.DATETIME2: 'DATETIME2'>: 'TIMESTAMP', <DType.NCHAR: 'NCHAR'>: 'CHAR', <DType.NVARCHAR: 'NVARCHAR'>: 'VARCHAR', <DType.MEDIUMTEXT: 'MEDIUMTEXT'>: 'VARCHAR', <DType.LONGTEXT: 'LONGTEXT'>: 'VARCHAR', <DType.TINYTEXT: 'TINYTEXT'>: 'VARCHAR', <DType.BLOB: 'BLOB'>: 'VARCHAR', <DType.MEDIUMBLOB: 'MEDIUMBLOB'>: 'VARCHAR', <DType.LONGBLOB: 'LONGBLOB'>: 'VARCHAR', <DType.TINYBLOB: 'TINYBLOB'>: 'VARCHAR', <DType.INET: 'INET'>: 'INET', <DType.ROWVERSION: 'ROWVERSION'>: 'VARBINARY', <DType.SMALLDATETIME: 'SMALLDATETIME'>: 'TIMESTAMP', <DType.TEXT: 'TEXT'>: 'LONG VARCHAR', <DType.VARBINARY: 'VARBINARY'>: 'VARCHAR', <DType.TINYINT: 'TINYINT'>: 'SMALLINT', <DType.MEDIUMINT: 'MEDIUMINT'>: 'INT', <DType.DECIMAL32: 'DECIMAL32'>: 'DECIMAL', <DType.DECIMAL64: 'DECIMAL64'>: 'DECIMAL', <DType.DECIMAL128: 'DECIMAL128'>: 'DECIMAL', <DType.DECIMAL256: 'DECIMAL256'>: 'DECIMAL', <DType.DATETIME: 'DATETIME'>: 'TIMESTAMP', <DType.TIMESTAMPTZ: 'TIMESTAMPTZ'>: 'TIMESTAMP', <DType.TIMESTAMPLTZ: 'TIMESTAMPLTZ'>: 'TIMESTAMP', <DType.TIMESTAMPNTZ: 'TIMESTAMPNTZ'>: 'TIMESTAMP'}
307 def datatype_sql(self, expression: exp.DataType) -> str: 308 # Exasol supports a fixed default precision of 3 for TIMESTAMP WITH LOCAL TIME ZONE 309 # and does not allow specifying a different custom precision 310 if expression.is_type(exp.DType.TIMESTAMPLTZ): 311 return "TIMESTAMP WITH LOCAL TIME ZONE" 312 313 return super().datatype_sql(expression)
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.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.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 ExasolGenerator.<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 Generator.<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.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 Generator.<lambda>>, <class 'sqlglot.expressions.temporal.UtcTimestamp'>: <function Generator.<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.core.All'>: <function rename_func.<locals>.<lambda>>, <class 'sqlglot.expressions.core.BitwiseAnd'>: <function rename_func.<locals>.<lambda>>, <class 'sqlglot.expressions.core.BitwiseOr'>: <function rename_func.<locals>.<lambda>>, <class 'sqlglot.expressions.core.BitwiseNot'>: <function rename_func.<locals>.<lambda>>, <class 'sqlglot.expressions.core.BitwiseLeftShift'>: <function rename_func.<locals>.<lambda>>, <class 'sqlglot.expressions.core.BitwiseRightShift'>: <function rename_func.<locals>.<lambda>>, <class 'sqlglot.expressions.core.BitwiseXor'>: <function rename_func.<locals>.<lambda>>, <class 'sqlglot.expressions.functions.CurrentSchema'>: <function ExasolGenerator.<lambda>>, <class 'sqlglot.expressions.temporal.DateDiff'>: <function _date_diff_sql>, <class 'sqlglot.expressions.temporal.DateAdd'>: <function _add_date_sql>, <class 'sqlglot.expressions.temporal.TsOrDsAdd'>: <function _add_date_sql>, <class 'sqlglot.expressions.temporal.DateSub'>: <function _add_date_sql>, <class 'sqlglot.expressions.core.IntDiv'>: <function rename_func.<locals>.<lambda>>, <class 'sqlglot.expressions.temporal.TsOrDsDiff'>: <function _date_diff_sql>, <class 'sqlglot.expressions.temporal.DateTrunc'>: <function _date_trunc_sql>, <class 'sqlglot.expressions.temporal.DayOfWeek'>: <function ExasolGenerator.<lambda>>, <class 'sqlglot.expressions.temporal.DatetimeTrunc'>: <function timestamptrunc_sql.<locals>._timestamptrunc_sql>, <class 'sqlglot.expressions.aggregate.GroupConcat'>: <function ExasolGenerator.<lambda>>, <class 'sqlglot.expressions.string.Levenshtein'>: <function rename_func.<locals>.<lambda>>, <class 'sqlglot.expressions.core.Mod'>: <function rename_func.<locals>.<lambda>>, <class 'sqlglot.expressions.temporal.UnixToTime'>: <function ExasolGenerator.<lambda>>, <class 'sqlglot.expressions.aggregate.Rank'>: <function ExasolGenerator.<lambda>>, <class 'sqlglot.expressions.aggregate.DenseRank'>: <function ExasolGenerator.<lambda>>, <class 'sqlglot.expressions.string.RegexpExtract'>: <function rename_func.<locals>.<lambda>>, <class 'sqlglot.expressions.string.RegexpReplace'>: <function rename_func.<locals>.<lambda>>, <class 'sqlglot.expressions.aggregate.VariancePop'>: <function rename_func.<locals>.<lambda>>, <class 'sqlglot.expressions.core.ApproxDistinct'>: <function rename_func.<locals>.<lambda>>, <class 'sqlglot.expressions.temporal.TimeToStr'>: <function ExasolGenerator.<lambda>>, <class 'sqlglot.expressions.string.ToChar'>: <function ExasolGenerator.<lambda>>, <class 'sqlglot.expressions.temporal.TsOrDsToDate'>: <function ExasolGenerator.<lambda>>, <class 'sqlglot.expressions.temporal.TimeStrToTime'>: <function timestrtotime_sql>, <class 'sqlglot.expressions.temporal.TimestampTrunc'>: <function _timestamp_trunc_sql>, <class 'sqlglot.expressions.temporal.StrToTime'>: <function ExasolGenerator.<lambda>>, <class 'sqlglot.expressions.functions.CurrentUser'>: <function ExasolGenerator.<lambda>>, <class 'sqlglot.expressions.core.AtTimeZone'>: <function ExasolGenerator.<lambda>>, <class 'sqlglot.expressions.string.StrPosition'>: <function ExasolGenerator.<lambda>>, <class 'sqlglot.expressions.string.SHA'>: <function rename_func.<locals>.<lambda>>, <class 'sqlglot.expressions.string.SHA2'>: <function _sha2_sql>, <class 'sqlglot.expressions.string.MD5'>: <function rename_func.<locals>.<lambda>>, <class 'sqlglot.expressions.string.MD5Digest'>: <function rename_func.<locals>.<lambda>>, <class 'sqlglot.expressions.query.Select'>: <function preprocess.<locals>._to_sql>, <class 'sqlglot.expressions.string.SubstringIndex'>: <function _substring_index_sql>, <class 'sqlglot.expressions.temporal.WeekOfYear'>: <function rename_func.<locals>.<lambda>>, <class 'sqlglot.expressions.temporal.Date'>: <function rename_func.<locals>.<lambda>>, <class 'sqlglot.expressions.temporal.Timestamp'>: <function rename_func.<locals>.<lambda>>, <class 'sqlglot.expressions.temporal.Quarter'>: <function ExasolGenerator.<lambda>>, <class 'sqlglot.expressions.temporal.LastDay'>: <function no_last_day_sql>}
RESERVED_KEYWORDS =
{'deallocate', 'characteristics', 'insert', 'export', 'transform', 'collate', 'call', 'bigint', 'sql_timestamp', 'get', 'release', 'exec', 'collation', 'yes', 'decimal', 'specifictype', 'sql_date', 'begin', 'as', 'indicator', 'timezone_hour', 'datalink', 'current_path', 'current_statement', 'table', 'last', 'refresh', 'dlurlserver', 'dbtimezone', 'next', 'style', 'sqlwarning', 'similar', 'hashtype_format', 'preferring', 'real', 'exit', 'without', 'dispatch', 'between', 'when', 'recursive', 'month', 'file', 'connection', 'system', 'format', 'subtype', 'until', 'ifnull', 'search', 'none', 'values', 'sql_numeric', 'checked', 'character_set_catalog', 'groups', 'key_type', 'recovery', 'natural', 'following', 'collation_schema', 'nvarchar2', 'new', 'drop', 'endif', 'csv', 'map', 'systimestamp', 'temporary', 'parallel_enable', 'references', 'each', 'trigger', 'tinyint', 'constraint', 'nls_numeric_characters', 'timestamp', 'order', 'constraints', 'nls_timestamp_format', 'import', 'nullif', 'leading', 'assertion', 'insensitive', 'instantiable', 'security', 'binary', 'describe', 'limit', 'cascade', 'procedure', 'constructor', 'replace', 'sql_char', 'before', 'instance', 'regexp_like', 'listagg', 'descriptor', 'iterate', 'outer', 'loop', 'national', 'or', 'generated', 'end', 'schema', 'smallint', 'deferrable', 'section', 'scope_user', 'go', 'parameter_specific_schema', 'rename', 'read', 'start', 'rowtype', 'repeat', 'separator', 'fbv', 'blob', 'else', 'nls_date_language', 'transforms', 'referencing', 'contains', 'overlaps', 'sql_real', 'attribute', 'sql_bit', 'integer', 'key_member', 'allocate', 'authid', 'where', 'final', 'substring', 'prior', 'merge', 'left', 'all', 'connect_by_iscycle', 'convert', 'global', 'sql_float', 'elseif', 'constant', 'sequence', 'within', 'numeric', 'control', 'null', 'false', 'others', 'names', 'minute', 'current_session', 'from', 'value', 'close', 'dlurlscheme', 'modify', 'source', 'treat', 'both', 'parameter_specific_name', 'deref', 'on', 'out', 'overriding', 'deterministic', 'sessiontimezone', 'called', 'privileges', 'longvarchar', 'permission', 'open', 'bit', 'system_user', 'definer', 'datetime_interval_code', 'condition', 'match', 'output', 'hold', 'default', 'range', 'dynamic_function', 'into', 'sysdate', 'emits', 'over', 'domain', 'full', 'old', 'sql_longvarchar', 'sqlexception', 'do', 'having', 'locator', 'immediate', 'current_user', 'current_cluster', 'double', 'time', 'truncate', 'exception', 'using', 'cursor', 'inverse', 'profile', 'second', 'enabled', 'elsif', 'trailing', 'unique', 'restore', 'disabled', 'collation_name', 'nologging', 'coalesce', 'casespecific', 'under', 'except', 'reads', 'catalog', 'in', 'declare', 'random', 'plus', 'session', 'off', 'current_date', 'are', 'view', 'ldap', 'revoke', 'forall', 'nvarchar', 'force', 'scroll', 'not', 'append', 'scope', 'static', 'grouping', 'dlvalue', 'end-exec', 'cardinality', 'relative', 'equals', 'whenever', 'commit', 'current_schema', 'hashtype', 'unnest', 'at', 'overlay', 'fs', 'invoker', 'result', 'selective', 'connect_by_root', 'input', 'union', 'localtime', 'granted', 'log', 'object', 'localtimestamp', 'desc', 'prepare', 'rows', 'sql_tinyint', 'connect_by_isleaf', 'translation', 'datetime_interval_precision', 'index', 'method', 'parameter', 'savepoint', 'dlurlpathonly', 'fetch', 'blocked', 'interval', 'general', 'to', 'true', 'large', 'timezone_minute', 'session_user', 'sqlstate', 'varchar', 'only', 'create', 'trim', 'chain', 'delete', 'sql_integer', 'varchar2', 'current_timestamp', 'state', 'disconnect', 'asc', 'sets', 'is', 'script', 'derived', 'constraint_state_default', 'placing', 'function', 'number', 'parameter_specific_catalog', 'array', 'ordering', 'rollback', 'leave', 'mod', 'returned_octet_length', 'pad', 'asensitive', 'for', 'sql_double', 'sql_varchar', 'goto', 'identity', 'dlurlcomplete', 'errors', 'any', 'returns', 'current_role', 'execute', 'case', 'structure', 'option', 'byte', 'cs', 'column', 'nls_date_format', 'current_cluster_uid', 'corresponding', 'clob', 'like', 'disable', 'sql_type_timestamp', 'impersonate', 'parquet', 'routine', 'sql_type_date', 'matched', 'enforce', 'grant', 'sensitive', 'data', 'nocycle', 'day', 'usage', 'then', 'defined', 'distinct', 'module', 'return', 'rollup', 'select', 'authorization', 'char', 'action', 'sql', 'bool', 'join', 'modifies', 'external', 'escape', 'of', 'cast', 'cube', 'zone', 'character_set_name', 'dynamic', 'no', 'sql_bigint', 'current_time', 'dec', 'set', 'sql_preprocessor_script', 'alter', 'group_concat', 'specific', 'deferred', 'ref', 'geometry', 'low', 'nchar', 'check', 'continue', 'dlurlpath', 'enable', 'options', 'extract', 'update', 'some', 'cascaded', 'work', 'character', 'statement', 'integrity', 'path', 'sql_decimal', 'shortint', 'preceding', 'self', 'default_like_escape_character', 'exists', 'unlink', 'absolute', 'collation_catalog', 'preserve', 'cycle', 'inner', 'nclob', 'int', 'free', 'window', 'user', 'row', 'implementation', 'ordinality', 'with', 'hour', 'varray', 'right', 'found', 'intersect', 'space', 'text', 'lateral', 'and', 'inout', 'level', 'by', 'group', 'first', 'after', 'current', 'year', 'dynamic_function_code', 'add', 'float', 'restrict', 'boolean', 'sql_smallint', 'minus', 'verify', 'character_set_schema', 'if', 'high', 'transaction', 'while', 'partial', 'returned_length', 'qualify', 'unknown', 'nls_first_day_of_week'}
880 def converttimezone_sql(self, expression: exp.ConvertTimezone) -> str: 881 from_tz = expression.args.get("source_tz") 882 to_tz = expression.args.get("target_tz") 883 datetime = expression.args.get("timestamp") 884 options = expression.args.get("options") 885 886 return self.func("CONVERT_TZ", datetime, from_tz, to_tz, options)
@unsupported_args('flag')
def
regexplike_sql(self, expression: sqlglot.expressions.core.RegexpLike) -> str:
908 @unsupported_args("flag") 909 def regexplike_sql(self, expression: exp.RegexpLike) -> str: 910 if not expression.args.get("full_match"): 911 pattern = expression.expression 912 if pattern.is_string: 913 expression.set("expression", exp.Literal.string(f".*{pattern.name}.*")) 914 else: 915 expression.set( 916 "expression", 917 exp.Paren( 918 this=exp.Concat( 919 expressions=[ 920 exp.Literal.string(".*"), 921 pattern, 922 exp.Literal.string(".*"), 923 ] 924 ) 925 ), 926 ) 927 return self.binary(expression, "REGEXP_LIKE")
Inherited Members
- sqlglot.generator.Generator
- Generator
- NULL_ORDERING_SUPPORTED
- WINDOW_FUNCS_WITH_NULL_ORDERING
- IGNORE_NULLS_IN_FUNC
- IGNORE_NULLS_BEFORE_ORDER
- LOCKING_READS_SUPPORTED
- EXCEPT_INTERSECT_SUPPORT_ALL_CLAUSE
- WRAP_DERIVED_VALUES
- CREATE_FUNCTION_RETURN_AS
- MATCHED_BY_SOURCE
- SUPPORTS_MERGE_WHERE
- SINGLE_STRING_INTERVAL
- INTERVAL_ALLOWS_PLURAL_FORM
- LIMIT_FETCH
- LIMIT_ONLY_LITERALS
- RENAME_TABLE_WITH_DB
- GROUPINGS_SEP
- INDEX_ON
- INOUT_SEPARATOR
- JOIN_HINTS
- DIRECTED_JOINS
- TABLE_HINTS
- QUERY_HINTS
- QUERY_HINT_SEP
- IS_BOOL_ALLOWED
- DUPLICATE_KEY_UPDATE_WITH_SET
- LIMIT_IS_TOP
- RETURNING_END
- EXTRACT_ALLOWS_QUOTES
- TZ_TO_WITH_TIME_ZONE
- NVL2_SUPPORTED
- VALUES_AS_TABLE
- ALTER_TABLE_INCLUDE_COLUMN_KEYWORD
- UNNEST_WITH_ORDINALITY
- AGGREGATE_FILTER_SUPPORTED
- SEMI_ANTI_JOIN_WITH_SIDE
- COMPUTED_COLUMN_WITH_TYPE
- SUPPORTS_TABLE_COPY
- TABLESAMPLE_REQUIRES_PARENS
- TABLESAMPLE_SIZE_IS_ROWS
- TABLESAMPLE_KEYWORDS
- TABLESAMPLE_WITH_METHOD
- TABLESAMPLE_SEED_KEYWORD
- COLLATE_IS_FUNC
- DATA_TYPE_SPECIFIERS_ALLOWED
- ENSURE_BOOLS
- CTE_RECURSIVE_KEYWORD_REQUIRED
- SUPPORTS_SINGLE_ARG_CONCAT
- LAST_DAY_SUPPORTS_DATE_PART
- SUPPORTS_TABLE_ALIAS_COLUMNS
- UNPIVOT_ALIASES_ARE_IDENTIFIERS
- JSON_KEY_VALUE_PAIR_SEP
- INSERT_OVERWRITE
- SUPPORTS_SELECT_INTO
- SUPPORTS_UNLOGGED_TABLES
- SUPPORTS_CREATE_TABLE_LIKE
- LIKE_PROPERTY_INSIDE_SCHEMA
- MULTI_ARG_DISTINCT
- JSON_TYPE_REQUIRED_FOR_EXTRACTION
- JSON_PATH_BRACKETED_KEY_SUPPORTED
- JSON_PATH_SINGLE_QUOTE_ESCAPE
- SUPPORTED_JSON_PATH_PARTS
- CAN_IMPLEMENT_ARRAY_ANY
- SUPPORTS_TO_NUMBER
- 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
- PAD_FILL_PATTERN_IS_REQUIRED
- SUPPORTS_EXPLODING_PROJECTIONS
- ARRAY_CONCAT_IS_VAR_LEN
- SUPPORTS_CONVERT_TIMEZONE
- SUPPORTS_MEDIAN
- SUPPORTS_UNIX_SECONDS
- ALTER_SET_WRAPPED
- NORMALIZE_EXTRACT_DATE_PARTS
- PARSE_JSON_NAME
- 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
- UPDATE_STATEMENT_SUPPORTS_FROM
- STAR_EXCLUDE_REQUIRES_DERIVED_TABLE
- SUPPORTS_DROP_ALTER_ICEBERG_PROPERTY
- UNSUPPORTED_TYPES
- TIME_PART_SINGULARS
- TOKEN_MAPPING
- STRUCT_DELIMITER
- PARAMETER_TOKEN
- NAMED_PLACEHOLDER_TOKEN
- EXPRESSION_PRECEDES_PROPERTIES_CREATABLES
- PROPERTIES_LOCATION
- 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
- computedcolumnconstraint_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
- directory_sql
- delete_sql
- drop_sql
- set_operation
- set_operations
- fetch_sql
- limitoptions_sql
- filter_sql
- hint_sql
- indexparameters_sql
- index_sql
- identifier_sql
- hex_sql
- lowerhex_sql
- inputoutputformat_sql
- national_sql
- partition_sql
- properties_sql
- root_properties
- properties
- with_properties
- locate_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
- distribute_sql
- sort_sql
- ordered_sql
- matchrecognizemeasure_sql
- matchrecognize_sql
- query_modifiers
- options_modifier
- for_modifiers
- 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
- extract_sql
- trim_sql
- convert_concat_args
- concat_sql
- concatws_sql
- check_sql
- foreignkey_sql
- primarykey_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
- attimezone_sql
- fromtimezone_sql
- add_sql
- and_sql
- or_sql
- xor_sql
- connector_sql
- bitwiseand_sql
- bitwiseleftshift_sql
- bitwisenot_sql
- bitwiseor_sql
- bitwiserightshift_sql
- bitwisexor_sql
- cast_sql
- strtotime_sql
- currentdate_sql
- command_sql
- comment_sql
- mergetreettlaction_sql
- mergetreettl_sql
- transaction_sql
- commit_sql
- rollback_sql
- altercolumn_sql
- alterindex_sql
- alterdiststyle_sql
- altersortkey_sql
- alterrename_sql
- renamecolumn_sql
- alterset_sql
- alter_sql
- altersession_sql
- add_column_sql
- droppartition_sql
- addconstraint_sql
- addpartition_sql
- distinct_sql
- ignorenulls_sql
- respectnulls_sql
- havingmax_sql
- intdiv_sql
- dpipe_sql
- div_sql
- safedivide_sql
- overlaps_sql
- distance_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
- 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
- partitionrange_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
- partitionbyrangeproperty_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
- show_sql
- install_sql
- get_put_sql
- translatecharacters_sql
- decodecase_sql
- semanticview_sql
- getextract_sql
- datefromunixdate_sql
- space_sql
- buildproperty_sql
- refreshtriggerproperty_sql
- modelattribute_sql
- directorystage_sql
- uuid_sql
- initcap_sql
- localtime_sql
- localtimestamp_sql
- weekstart_sql
- chr_sql
- block_sql
- storedprocedure_sql
- ifblock_sql
- whileblock_sql
- execute_sql
- executesql_sql
- altermodifysqlsecurity_sql
- usingproperty_sql
- renameindex_sql