sqlglot expressions builders.
1"""sqlglot expressions builders.""" 2 3from __future__ import annotations 4 5import re 6import typing as t 7 8from sqlglot.helper import seq_get, ensure_collection, split_num_words 9from sqlglot.errors import ParseError, TokenError 10from sqlglot.expressions.core import ( 11 Alias, 12 Anonymous, 13 AtTimeZone, 14 Between, 15 Binary, 16 BitwiseNot, 17 Boolean, 18 Bracket, 19 Column, 20 Condition, 21 Dot, 22 EQ, 23 Expr, 24 Func, 25 Identifier, 26 In, 27 Literal, 28 Neg, 29 Not, 30 Null, 31 Paren, 32 Placeholder, 33 TABLE_PARTS, 34 Var, 35 logger, 36 SAFE_IDENTIFIER_RE, 37 maybe_parse, 38 maybe_copy, 39 to_identifier, 40 convert, 41 alias_, 42 column, 43) 44from sqlglot.expressions.datatypes import DataType, DType, Interval 45from sqlglot.expressions.query import ( 46 CTE, 47 From, 48 Schema, 49 Select, 50 SetOperation, 51 Subquery, 52 Table, 53 TableAlias, 54 Tuple, 55 Values, 56 Where, 57 With, 58 Query, 59) 60from sqlglot.expressions.ddl import Alter, AlterRename, Create, RenameColumn 61from sqlglot.expressions.dml import Delete, Insert, Merge, Update, When, Whens 62from sqlglot.expressions.functions import Case, Cast 63from sqlglot.expressions.array import Array 64 65 66if t.TYPE_CHECKING: 67 from collections.abc import Sequence, Iterable, Iterator 68 from sqlglot.dialects.dialect import DialectType 69 from sqlglot.expressions.core import ExpOrStr 70 from sqlglot.expressions.datatypes import DATA_TYPE 71 from sqlglot._typing import ParserArgs, ParserNoDialectArgs, E, P 72 from typing_extensions import Unpack, Concatenate 73 74 75def select( 76 *expressions: ExpOrStr, 77 dialect: DialectType = None, 78 copy: bool = True, 79 **opts: Unpack[ParserNoDialectArgs], 80) -> Select: 81 """ 82 Initializes a syntax tree from one or multiple SELECT expressions. 83 84 Example: 85 >>> select("col1", "col2").from_("tbl").sql() 86 'SELECT col1, col2 FROM tbl' 87 88 Args: 89 *expressions: the SQL code string to parse as the expressions of a 90 SELECT statement. If an Expr instance is passed, this is used as-is. 91 dialect: the dialect used to parse the input expressions (in the case that an 92 input expression is a SQL string). 93 **opts: other options to use to parse the input expressions (again, in the case 94 that an input expression is a SQL string). 95 96 Returns: 97 Select: the syntax tree for the SELECT statement. 98 """ 99 return Select().select(*expressions, dialect=dialect, copy=copy, **opts) 100 101 102def from_( 103 expression: ExpOrStr, 104 dialect: DialectType = None, 105 copy: bool = True, 106 **opts: Unpack[ParserNoDialectArgs], 107) -> Select: 108 """ 109 Initializes a syntax tree from a FROM expression. 110 111 Example: 112 >>> from_("tbl").select("col1", "col2").sql() 113 'SELECT col1, col2 FROM tbl' 114 115 Args: 116 *expression: the SQL code string to parse as the FROM expressions of a 117 SELECT statement. If an Expr instance is passed, this is used as-is. 118 dialect: the dialect used to parse the input expression (in the case that the 119 input expression is a SQL string). 120 **opts: other options to use to parse the input expressions (again, in the case 121 that the input expression is a SQL string). 122 123 Returns: 124 Select: the syntax tree for the SELECT statement. 125 """ 126 return Select().from_(expression, dialect=dialect, copy=copy, **opts) 127 128 129def update( 130 table: str | Table, 131 properties: dict[str, object] | None = None, 132 where: ExpOrStr | None = None, 133 from_: ExpOrStr | None = None, 134 with_: dict[str, ExpOrStr] | None = None, 135 dialect: DialectType = None, 136 copy: bool = True, 137 **opts: Unpack[ParserNoDialectArgs], 138) -> Update: 139 """ 140 Creates an update statement. 141 142 Example: 143 >>> update("my_table", {"x": 1, "y": "2", "z": None}, from_="baz_cte", where="baz_cte.id > 1 and my_table.id = baz_cte.id", with_={"baz_cte": "SELECT id FROM foo"}).sql() 144 "WITH baz_cte AS (SELECT id FROM foo) UPDATE my_table SET x = 1, y = '2', z = NULL FROM baz_cte WHERE baz_cte.id > 1 AND my_table.id = baz_cte.id" 145 146 Args: 147 properties: dictionary of properties to SET which are 148 auto converted to sql objects eg None -> NULL 149 where: sql conditional parsed into a WHERE statement 150 from_: sql statement parsed into a FROM statement 151 with_: dictionary of CTE aliases / select statements to include in a WITH clause. 152 dialect: the dialect used to parse the input expressions. 153 copy: whether to copy the input expressions. 154 **opts: other options to use to parse the input expressions. 155 156 Returns: 157 Update: the syntax tree for the UPDATE statement. 158 """ 159 update_expr = Update(this=maybe_parse(table, into=Table, dialect=dialect, copy=copy)) 160 if properties: 161 update_expr.set( 162 "expressions", 163 [ 164 EQ(this=maybe_parse(k, dialect=dialect, copy=copy, **opts), expression=convert(v)) 165 for k, v in properties.items() 166 ], 167 ) 168 if from_: 169 update_expr.set( 170 "from_", 171 maybe_parse(from_, into=From, dialect=dialect, prefix="FROM", copy=copy, **opts), 172 ) 173 if isinstance(where, Condition): 174 where = Where(this=where) 175 if where: 176 update_expr.set( 177 "where", 178 maybe_parse(where, into=Where, dialect=dialect, prefix="WHERE", copy=copy, **opts), 179 ) 180 if with_: 181 cte_list = [ 182 alias_( 183 CTE(this=maybe_parse(qry, dialect=dialect, copy=copy, **opts)), alias, table=True 184 ) 185 for alias, qry in with_.items() 186 ] 187 update_expr.set( 188 "with_", 189 With(expressions=cte_list), 190 ) 191 return update_expr 192 193 194def delete( 195 table: ExpOrStr, 196 where: ExpOrStr | None = None, 197 returning: ExpOrStr | None = None, 198 dialect: DialectType = None, 199 **opts: Unpack[ParserNoDialectArgs], 200) -> Delete: 201 """ 202 Builds a delete statement. 203 204 Example: 205 >>> delete("my_table", where="id > 1").sql() 206 'DELETE FROM my_table WHERE id > 1' 207 208 Args: 209 where: sql conditional parsed into a WHERE statement 210 returning: sql conditional parsed into a RETURNING statement 211 dialect: the dialect used to parse the input expressions. 212 **opts: other options to use to parse the input expressions. 213 214 Returns: 215 Delete: the syntax tree for the DELETE statement. 216 """ 217 delete_expr = Delete().delete(table, dialect=dialect, copy=False, **opts) 218 if where: 219 delete_expr = delete_expr.where(where, dialect=dialect, copy=False, **opts) 220 if returning: 221 delete_expr = delete_expr.returning(returning, dialect=dialect, copy=False, **opts) 222 return delete_expr 223 224 225def insert( 226 expression: ExpOrStr, 227 into: str | Table, 228 columns: Sequence[str | Identifier] | None = None, 229 overwrite: bool | None = None, 230 returning: ExpOrStr | None = None, 231 dialect: DialectType = None, 232 copy: bool = True, 233 **opts: Unpack[ParserNoDialectArgs], 234) -> Insert: 235 """ 236 Builds an INSERT statement. 237 238 Example: 239 >>> insert("VALUES (1, 2, 3)", "tbl").sql() 240 'INSERT INTO tbl VALUES (1, 2, 3)' 241 242 Args: 243 expression: the sql string or expression of the INSERT statement 244 into: the tbl to insert data to. 245 columns: optionally the table's column names. 246 overwrite: whether to INSERT OVERWRITE or not. 247 returning: sql conditional parsed into a RETURNING statement 248 dialect: the dialect used to parse the input expressions. 249 copy: whether to copy the expression. 250 **opts: other options to use to parse the input expressions. 251 252 Returns: 253 Insert: the syntax tree for the INSERT statement. 254 """ 255 expr = maybe_parse(expression, dialect=dialect, copy=copy, **opts) 256 this: Table | Schema = maybe_parse(into, into=Table, dialect=dialect, copy=copy, **opts) 257 258 if columns: 259 this = Schema(this=this, expressions=[to_identifier(c, copy=copy) for c in columns]) 260 261 insert = Insert(this=this, expression=expr, overwrite=overwrite) 262 263 if returning: 264 insert = insert.returning(returning, dialect=dialect, copy=False, **opts) 265 266 return insert 267 268 269def merge( 270 *when_exprs: ExpOrStr, 271 into: ExpOrStr, 272 using: ExpOrStr, 273 on: ExpOrStr, 274 returning: ExpOrStr | None = None, 275 dialect: DialectType = None, 276 copy: bool = True, 277 **opts: Unpack[ParserNoDialectArgs], 278) -> Merge: 279 """ 280 Builds a MERGE statement. 281 282 Example: 283 >>> merge("WHEN MATCHED THEN UPDATE SET col1 = source_table.col1", 284 ... "WHEN NOT MATCHED THEN INSERT (col1) VALUES (source_table.col1)", 285 ... into="my_table", 286 ... using="source_table", 287 ... on="my_table.id = source_table.id").sql() 288 'MERGE INTO my_table USING source_table ON my_table.id = source_table.id WHEN MATCHED THEN UPDATE SET col1 = source_table.col1 WHEN NOT MATCHED THEN INSERT (col1) VALUES (source_table.col1)' 289 290 Args: 291 *when_exprs: The WHEN clauses specifying actions for matched and unmatched rows. 292 into: The target table to merge data into. 293 using: The source table to merge data from. 294 on: The join condition for the merge. 295 returning: The columns to return from the merge. 296 dialect: The dialect used to parse the input expressions. 297 copy: Whether to copy the expression. 298 **opts: Other options to use to parse the input expressions. 299 300 Returns: 301 Merge: The syntax tree for the MERGE statement. 302 """ 303 expressions: list[Expr] = [] 304 for when_expr in when_exprs: 305 expression = maybe_parse(when_expr, dialect=dialect, copy=copy, into=Whens, **opts) 306 expressions.extend([expression] if isinstance(expression, When) else expression.expressions) 307 308 merge = Merge( 309 this=maybe_parse(into, dialect=dialect, copy=copy, **opts), 310 using=maybe_parse(using, dialect=dialect, copy=copy, **opts), 311 on=maybe_parse(on, dialect=dialect, copy=copy, **opts), 312 whens=Whens(expressions=expressions), 313 ) 314 if returning: 315 merge = merge.returning(returning, dialect=dialect, copy=False, **opts) 316 317 if isinstance(using_clause := merge.args.get("using"), Alias): 318 using_clause.replace(alias_(using_clause.this, using_clause.args["alias"], table=True)) 319 320 return merge 321 322 323def parse_identifier(name: str | Identifier, dialect: DialectType = None) -> Identifier: 324 """ 325 Parses a given string into an identifier. 326 327 Args: 328 name: The name to parse into an identifier. 329 dialect: The dialect to parse against. 330 331 Returns: 332 The identifier ast node. 333 """ 334 if isinstance(name, str) and SAFE_IDENTIFIER_RE.match(name): 335 # Simple names parse to a single unquoted identifier in all dialects, so we can 336 # avoid the tokenizer/parser round-trip for them. 337 return Identifier(this=name, quoted=False) 338 339 try: 340 expression = maybe_parse(name, dialect=dialect, into=Identifier) 341 except (ParseError, TokenError): 342 expression = to_identifier(name) 343 344 return expression 345 346 347INTERVAL_STRING_RE = re.compile(r"\s*(-?[0-9]+(?:\.[0-9]+)?)\s*([a-zA-Z]+)\s*") 348 349 350INTERVAL_DAY_TIME_RE = re.compile( 351 r"\s*-?\s*\d+(?:\.\d+)?\s+(?:-?(?:\d+:)?\d+:\d+(?:\.\d+)?|-?(?:\d+:){1,2}|:)\s*" 352) 353 354 355def to_interval(interval: str | Expr) -> Interval: 356 """Builds an interval expression from a string like '1 day' or '5 months'.""" 357 if isinstance(interval, Literal): 358 if not interval.is_string: 359 raise ValueError("Invalid interval string.") 360 361 interval = interval.this 362 363 interval = maybe_parse(f"INTERVAL {interval}") 364 assert isinstance(interval, Interval) 365 return interval 366 367 368def to_table( 369 sql_path: str | Table, dialect: DialectType = None, copy: bool = True, **kwargs: object 370) -> Table: 371 """ 372 Create a table expression from a `[catalog].[schema].[table]` sql path. Catalog and schema are optional. 373 If a table is passed in then that table is returned. 374 375 Args: 376 sql_path: a `[catalog].[schema].[table]` string. 377 dialect: the source dialect according to which the table name will be parsed. 378 copy: Whether to copy a table if it is passed in. 379 kwargs: the kwargs to instantiate the resulting `Table` expression with. 380 381 Returns: 382 A table expression. 383 """ 384 if isinstance(sql_path, Table): 385 return maybe_copy(sql_path, copy=copy) 386 387 try: 388 table = maybe_parse(sql_path, into=Table, dialect=dialect) 389 except ParseError: 390 catalog, db, this = split_num_words(sql_path, ".", 3) 391 392 if not this: 393 raise 394 395 table = table_(this, db=db, catalog=catalog) 396 397 return table.set_kwargs(kwargs) 398 399 400def to_column( 401 sql_path: str | Column, 402 quoted: bool | None = None, 403 dialect: DialectType = None, 404 copy: bool = True, 405 **kwargs: t.Any, 406) -> Column | Dot: 407 """ 408 Create a column from a `[table].[column]` sql path. Table is optional. 409 If a column is passed in then that column is returned. 410 411 Args: 412 sql_path: a `[table].[column]` string. 413 quoted: Whether or not to force quote identifiers. 414 dialect: the source dialect according to which the column name will be parsed. 415 copy: Whether to copy a column if it is passed in. 416 kwargs: the kwargs to instantiate the resulting `Column` expression with. 417 418 Returns: 419 A column expression. 420 """ 421 if isinstance(sql_path, Column): 422 return maybe_copy(sql_path, copy=copy) 423 424 try: 425 col = maybe_parse(sql_path, into=Column, dialect=dialect) 426 except ParseError: 427 return column(*reversed(sql_path.split(".")), quoted=quoted, **kwargs) 428 429 for k, v in kwargs.items(): 430 col.set(k, v) 431 432 if quoted: 433 for i in col.find_all(Identifier): 434 i.set("quoted", True) 435 436 return col 437 438 439def subquery( 440 expression: ExpOrStr, 441 alias: Identifier | str | None = None, 442 dialect: DialectType = None, 443 copy: bool = True, 444 **opts: Unpack[ParserNoDialectArgs], 445) -> Select: 446 """ 447 Build a subquery expression that's selected from. 448 449 Example: 450 >>> subquery('select x from tbl', 'bar').select('x').sql() 451 'SELECT x FROM (SELECT x FROM tbl) AS bar' 452 453 Args: 454 expression: the SQL code strings to parse. 455 If an Expr instance is passed, this is used as-is. 456 alias: the alias name to use. 457 dialect: the dialect used to parse the input expression. 458 **opts: other options to use to parse the input expressions. 459 460 Returns: 461 A new Select instance with the subquery expression included. 462 """ 463 expr = ( 464 maybe_parse(expression, dialect=dialect, **opts).assert_is(Query).subquery(alias, copy=copy) 465 ) 466 return Select().from_(expr, dialect=dialect, **opts) 467 468 469def cast( 470 expression: ExpOrStr, 471 to: DATA_TYPE, 472 copy: bool = True, 473 dialect: DialectType = None, 474 **opts: Unpack[ParserNoDialectArgs], 475) -> Cast: 476 """Cast an expression to a data type. 477 478 Example: 479 >>> cast('x + 1', 'int').sql() 480 'CAST(x + 1 AS INT)' 481 482 Args: 483 expression: The expression to cast. 484 to: The datatype to cast to. 485 copy: Whether to copy the supplied expressions. 486 dialect: The target dialect. This is used to prevent a re-cast in the following scenario: 487 - The expression to be cast is already a exp.Cast expression 488 - The existing cast is to a type that is logically equivalent to new type 489 490 For example, if :expression='CAST(x as DATETIME)' and :to=Type.TIMESTAMP, 491 but in the target dialect DATETIME is mapped to TIMESTAMP, then we will NOT return `CAST(x (as DATETIME) as TIMESTAMP)` 492 and instead just return the original expression `CAST(x as DATETIME)`. 493 494 This is to prevent it being output as a double cast `CAST(x (as TIMESTAMP) as TIMESTAMP)` once the DATETIME -> TIMESTAMP 495 mapping is applied in the target dialect generator. 496 497 Returns: 498 The new Cast instance. 499 """ 500 expr = maybe_parse(expression, copy=copy, dialect=dialect, **opts) 501 data_type = DataType.build(to, copy=copy, dialect=dialect, **opts) 502 503 # dont re-cast if the expression is already a cast to the correct type 504 if isinstance(expr, Cast): 505 from sqlglot.dialects.dialect import Dialect 506 507 target_dialect = Dialect.get_or_raise(dialect) 508 type_mapping = target_dialect.generator_class.TYPE_MAPPING 509 510 existing_cast_type = expr.to.this 511 new_cast_type: DType = data_type.this 512 # `this` is only a plain type enum for simple types; complex ones such as 513 # INTERVAL nest another expression there, so the equivalence check is skipped. 514 types_are_equivalent = ( 515 isinstance(existing_cast_type, DType) 516 and isinstance(new_cast_type, DType) 517 and type_mapping.get(existing_cast_type, existing_cast_type.value) 518 == type_mapping.get(new_cast_type, new_cast_type.value) 519 ) 520 521 if expr.is_type(data_type) or types_are_equivalent: 522 return expr 523 524 expr = Cast(this=expr, to=data_type) 525 expr.type = data_type 526 527 return expr 528 529 530def table_( 531 table: Identifier | str | None, 532 db: Identifier | str | None = None, 533 catalog: Identifier | str | None = None, 534 quoted: bool | None = None, 535 alias: Identifier | str | None = None, 536) -> Table: 537 """Build a Table. 538 539 Args: 540 table: Table name. 541 db: Database name. 542 catalog: Catalog name. 543 quote: Whether to force quotes on the table's identifiers. 544 alias: Table's alias. 545 546 Returns: 547 The new Table instance. 548 """ 549 return Table( 550 this=to_identifier(table, quoted=quoted) if table else None, 551 db=to_identifier(db, quoted=quoted) if db else None, 552 catalog=to_identifier(catalog, quoted=quoted) if catalog else None, 553 alias=TableAlias(this=to_identifier(alias)) if alias else None, 554 ) 555 556 557def values( 558 values: Iterable[tuple[object, ...] | Tuple], 559 alias: str | None = None, 560 columns: Iterable[str] | dict[str, DataType] | None = None, 561) -> Values: 562 """Build VALUES statement. 563 564 Example: 565 >>> values([(1, '2')]).sql() 566 "VALUES (1, '2')" 567 568 Args: 569 values: values statements that will be converted to SQL 570 alias: optional alias 571 columns: Optional list of ordered column names or ordered dictionary of column names to types. 572 If either are provided then an alias is also required. 573 574 Returns: 575 Values: the Values expression object 576 """ 577 if columns and not alias: 578 raise ValueError("Alias is required when providing columns") 579 580 return Values( 581 expressions=[convert(tup) for tup in values], 582 alias=( 583 TableAlias(this=to_identifier(alias), columns=[to_identifier(x) for x in columns]) 584 if columns 585 else (TableAlias(this=to_identifier(alias)) if alias else None) 586 ), 587 ) 588 589 590def var(name: ExpOrStr | None) -> Var: 591 """Build a SQL variable. 592 593 Example: 594 >>> repr(var('x')) 595 'Var(this=x)' 596 597 >>> repr(var(column('x', table='y'))) 598 'Var(this=x)' 599 600 Args: 601 name: The name of the var or an expression who's name will become the var. 602 603 Returns: 604 The new variable node. 605 """ 606 if not name: 607 raise ValueError("Cannot convert empty name into var.") 608 609 if isinstance(name, Expr): 610 name = name.name 611 return Var(this=name) 612 613 614def rename_table( 615 old_name: str | Table, 616 new_name: str | Table, 617 dialect: DialectType = None, 618) -> Alter: 619 """Build ALTER TABLE... RENAME... expression 620 621 Args: 622 old_name: The old name of the table 623 new_name: The new name of the table 624 dialect: The dialect to parse the table. 625 626 Returns: 627 Alter table expression 628 """ 629 old_table = to_table(old_name, dialect=dialect) 630 new_table = to_table(new_name, dialect=dialect) 631 return Alter( 632 this=old_table, 633 kind="TABLE", 634 actions=[ 635 AlterRename(this=new_table), 636 ], 637 ) 638 639 640def rename_column( 641 table_name: str | Table, 642 old_column_name: str | Column, 643 new_column_name: str | Column, 644 exists: bool | None = None, 645 dialect: DialectType = None, 646) -> Alter: 647 """Build ALTER TABLE... RENAME COLUMN... expression 648 649 Args: 650 table_name: Name of the table 651 old_column: The old name of the column 652 new_column: The new name of the column 653 exists: Whether to add the `IF EXISTS` clause 654 dialect: The dialect to parse the table/column. 655 656 Returns: 657 Alter table expression 658 """ 659 table = to_table(table_name, dialect=dialect) 660 old_column = to_column(old_column_name, dialect=dialect) 661 new_column = to_column(new_column_name, dialect=dialect) 662 return Alter( 663 this=table, 664 kind="TABLE", 665 actions=[ 666 RenameColumn(this=old_column, to=new_column, exists=exists), 667 ], 668 ) 669 670 671def replace_children( 672 expression: Expr, 673 fun: t.Callable[Concatenate[Expr, P], object], 674 *args: P.args, 675 **kwargs: P.kwargs, 676) -> None: 677 """ 678 Replace children of an expression with the result of a lambda fun(child) -> exp. 679 """ 680 for k, v in tuple(expression.args.items()): 681 is_list_arg = type(v) is list 682 683 child_nodes = v if is_list_arg else [v] 684 new_child_nodes = [] 685 686 for cn in child_nodes: 687 if isinstance(cn, Expr): 688 for child_node in ensure_collection(fun(cn, *args, **kwargs)): 689 new_child_nodes.append(child_node) 690 else: 691 new_child_nodes.append(cn) 692 693 if is_list_arg: 694 expression.set(k, new_child_nodes) 695 else: 696 expression.set(k, seq_get(new_child_nodes, 0)) 697 698 699def replace_tree( 700 expression: Expr, 701 fun: t.Callable[[Expr], Expr], 702 prune: t.Callable[[Expr], bool] | None = None, 703) -> Expr: 704 """ 705 Replace an entire tree with the result of function calls on each node. 706 707 This will be traversed in reverse dfs, so leaves first. 708 If new nodes are created as a result of function calls, they will also be traversed. 709 """ 710 stack = list(expression.dfs(prune=prune)) 711 712 while stack: 713 node = stack.pop() 714 new_node = fun(node) 715 716 if new_node is not node: 717 node.replace(new_node) 718 719 if isinstance(new_node, Expr): 720 stack.append(new_node) 721 722 return new_node 723 724 725def find_tables(expression: Expr) -> set[Table]: 726 """ 727 Find all tables referenced in a query. 728 729 Args: 730 expressions: The query to find the tables in. 731 732 Returns: 733 A set of all the tables. 734 """ 735 from sqlglot.optimizer.scope import traverse_scope 736 737 return { 738 table 739 for scope in traverse_scope(expression) 740 for table in scope.tables 741 if isinstance(table, Table) and table.name and table.name not in scope.cte_sources 742 } 743 744 745def column_table_names(expression: Expr, exclude: str = "") -> set[str]: 746 """ 747 Return all table names referenced through columns in an expression. 748 749 Example: 750 >>> import sqlglot 751 >>> sorted(column_table_names(sqlglot.parse_one("a.b AND c.d AND c.e"))) 752 ['a', 'c'] 753 754 Args: 755 expression: expression to find table names. 756 exclude: a table name to exclude 757 758 Returns: 759 A list of unique names. 760 """ 761 return { 762 table 763 for table in (column.table for column in expression.find_all(Column)) 764 if table and table != exclude 765 } 766 767 768def table_name(table: Table | str, dialect: DialectType = None, identify: bool = False) -> str: 769 """Get the full name of a table as a string. 770 771 Args: 772 table: Table expression node or string. 773 dialect: The dialect to generate the table name for. 774 identify: Determines when an identifier should be quoted. Possible values are: 775 False (default): Never quote, except in cases where it's mandatory by the dialect. 776 True: Always quote. 777 778 Examples: 779 >>> from sqlglot import exp, parse_one 780 >>> table_name(parse_one("select * from a.b.c").find(exp.Table)) 781 'a.b.c' 782 783 Returns: 784 The table name. 785 """ 786 787 expr = maybe_parse(table, into=Table, dialect=dialect) 788 789 if not expr: 790 raise ValueError(f"Cannot parse {table}") 791 792 return ".".join( 793 ( 794 part.sql(dialect=dialect, identify=True, copy=False, comments=False) 795 if identify or not SAFE_IDENTIFIER_RE.match(part.name) 796 else part.name 797 ) 798 for part in expr.parts 799 ) 800 801 802def normalize_table_name(table: str | Table, dialect: DialectType = None, copy: bool = True) -> str: 803 """Returns a case normalized table name without quotes. 804 805 Args: 806 table: the table to normalize 807 dialect: the dialect to use for normalization rules 808 copy: whether to copy the expression. 809 810 Examples: 811 >>> normalize_table_name("`A-B`.c", dialect="bigquery") 812 'A-B.c' 813 """ 814 from sqlglot.optimizer.normalize_identifiers import normalize_identifiers 815 816 return ".".join( 817 p.name 818 for p in normalize_identifiers( 819 to_table(table, dialect=dialect, copy=copy), dialect=dialect 820 ).parts 821 ) 822 823 824def replace_tables( 825 expression: E, mapping: dict[str, str], dialect: DialectType = None, copy: bool = True 826) -> E: 827 """Replace all tables in expression according to the mapping. 828 829 Args: 830 expression: expression node to be transformed and replaced. 831 mapping: mapping of table names. 832 dialect: the dialect of the mapping table 833 copy: whether to copy the expression. 834 835 Examples: 836 >>> from sqlglot import exp, parse_one 837 >>> replace_tables(parse_one("select * from a.b"), {"a.b": "c"}).sql() 838 'SELECT * FROM c /* a.b */' 839 840 Returns: 841 The mapped expression. 842 """ 843 844 mapping = {normalize_table_name(k, dialect=dialect): v for k, v in mapping.items()} 845 846 def _replace_tables(node: Expr) -> Expr: 847 if isinstance(node, Table) and node.meta_get("replace") is not False: 848 original = normalize_table_name(node, dialect=dialect) 849 new_name = mapping.get(original) 850 851 if new_name: 852 table = to_table( 853 new_name, 854 **{k: v for k, v in node.args.items() if k not in TABLE_PARTS}, 855 dialect=dialect, 856 ) 857 table.add_comments([original]) 858 return table 859 return node 860 861 return expression.transform(_replace_tables, copy=copy) # type: ignore 862 863 864OPERATORS = (AtTimeZone, Between, Binary, BitwiseNot, In, Neg, Not) 865 866 867def _is_operand(placeholder: Placeholder) -> bool: 868 parent = placeholder.parent 869 if isinstance(parent, (Bracket, In)): 870 return placeholder.arg_key == "this" 871 return isinstance(parent, OPERATORS) 872 873 874def _takes_query(placeholder: Placeholder) -> bool: 875 parent = placeholder.parent 876 if isinstance(parent, In): 877 return placeholder.arg_key == "expressions" and len(parent.expressions) == 1 878 if isinstance(parent, Func): 879 return len(list(parent.iter_expressions())) == 1 880 if isinstance(parent, Table): 881 return isinstance(parent.parent, (Create, Subquery)) 882 return not parent or isinstance(parent, (CTE, Paren, SetOperation)) 883 884 885def _replace_placeholder(placeholder: Placeholder, expression: Expr) -> Expr: 886 if ( 887 isinstance(expression, Query) 888 and not isinstance(expression, Subquery) 889 and not _takes_query(placeholder) 890 ): 891 return expression.subquery(copy=False) 892 if ( 893 _is_operand(placeholder) 894 and isinstance(expression, OPERATORS) 895 and not isinstance(expression, Dot) 896 ): 897 return Paren(this=expression) 898 return expression 899 900 901def replace_placeholders(expression: Expr, *args: object, **kwargs: t.Any) -> Expr: 902 """Replace placeholders in an expression. 903 904 Args: 905 expression: expression node to be transformed and replaced. 906 args: positional names that will substitute unnamed placeholders in the given order. 907 kwargs: keyword arguments that will substitute named placeholders. 908 909 Examples: 910 >>> from sqlglot import exp, parse_one 911 >>> replace_placeholders( 912 ... parse_one("select * from :tbl where ? = ?"), 913 ... exp.to_identifier("str_col"), "b", tbl=exp.to_identifier("foo") 914 ... ).sql() 915 "SELECT * FROM foo WHERE str_col = 'b'" 916 917 Returns: 918 The mapped expression. 919 """ 920 921 def _replace_placeholders(node: Expr, args: Iterator[object], **kwargs: object) -> Expr: 922 if isinstance(node, Placeholder): 923 if node.this: 924 new_name = kwargs.get(node.this) 925 if new_name is not None: 926 return _replace_placeholder(node, convert(new_name)) 927 else: 928 try: 929 return _replace_placeholder(node, convert(next(args))) 930 except StopIteration: 931 pass 932 return node 933 934 return expression.transform(_replace_placeholders, iter(args), **kwargs) 935 936 937def expand( 938 expression: Expr, 939 sources: dict[str, Query | t.Callable[[], Query]], 940 dialect: DialectType = None, 941 copy: bool = True, 942) -> Expr: 943 """Transforms an expression by expanding all referenced sources into subqueries. 944 945 Examples: 946 >>> from sqlglot import parse_one 947 >>> expand(parse_one("select * from x AS z"), {"x": parse_one("select * from y")}).sql() 948 'SELECT * FROM (SELECT * FROM y) AS z /* source: x */' 949 950 >>> expand(parse_one("select * from x AS z"), {"x": parse_one("select * from y"), "y": parse_one("select * from z")}).sql() 951 'SELECT * FROM (SELECT * FROM (SELECT * FROM z) AS y /* source: y */) AS z /* source: x */' 952 953 Args: 954 expression: The expression to expand. 955 sources: A dict of name to query or a callable that provides a query on demand. 956 dialect: The dialect of the sources dict or the callable. 957 copy: Whether to copy the expression during transformation. Defaults to True. 958 959 Returns: 960 The transformed expression. 961 """ 962 normalized_sources = {normalize_table_name(k, dialect=dialect): v for k, v in sources.items()} 963 964 def _expand(node: Expr): 965 if isinstance(node, Table): 966 name = normalize_table_name(node, dialect=dialect) 967 source = normalized_sources.get(name) 968 969 if source: 970 # Create a subquery with the same alias (or table name if no alias) 971 parsed_source = source() if callable(source) else source 972 subquery = parsed_source.subquery(node.alias or name) 973 subquery.comments = [f"source: {name}"] 974 975 # Continue expanding within the subquery 976 return subquery.transform(_expand, copy=False) 977 978 return node 979 980 return expression.transform(_expand, copy=copy) 981 982 983def func( 984 name: str, *args: t.Any, copy: bool = True, dialect: DialectType = None, **kwargs: t.Any 985) -> Func: 986 """ 987 Returns a Func expression. 988 989 Examples: 990 >>> func("abs", 5).sql() 991 'ABS(5)' 992 993 >>> func("cast", this=5, to=DataType.build("DOUBLE")).sql() 994 'CAST(5 AS DOUBLE)' 995 996 Args: 997 name: the name of the function to build. 998 args: the args used to instantiate the function of interest. 999 copy: whether to copy the argument expressions. 1000 dialect: the source dialect. 1001 kwargs: the kwargs used to instantiate the function of interest. 1002 1003 Note: 1004 The arguments `args` and `kwargs` are mutually exclusive. 1005 1006 Returns: 1007 An instance of the function of interest, or an anonymous function, if `name` doesn't 1008 correspond to an existing `sqlglot.expressions.Func` class. 1009 """ 1010 if args and kwargs: 1011 raise ValueError("Can't use both args and kwargs to instantiate a function.") 1012 1013 from sqlglot.dialects.dialect import Dialect 1014 1015 dialect = Dialect.get_or_raise(dialect) 1016 1017 converted: list[Expr] = [maybe_parse(arg, dialect=dialect, copy=copy) for arg in args] 1018 kwargs = {key: maybe_parse(value, dialect=dialect, copy=copy) for key, value in kwargs.items()} 1019 1020 constructor = dialect.parser_class.FUNCTIONS.get(name.upper()) 1021 if constructor: 1022 if converted: 1023 try: 1024 function = constructor(converted) 1025 except TypeError: 1026 function = constructor(converted, dialect=dialect) 1027 elif constructor.__name__ == "from_arg_list": 1028 function = constructor.__self__(**kwargs) # type: ignore 1029 else: 1030 from sqlglot.expressions import FUNCTION_BY_NAME as _FUNCTION_BY_NAME 1031 1032 constructor = _FUNCTION_BY_NAME.get(name.upper()) 1033 if constructor: 1034 function = constructor(**kwargs) 1035 else: 1036 raise ValueError( 1037 f"Unable to convert '{name}' into a Func. Either manually construct " 1038 "the Func expression of interest or parse the function call." 1039 ) 1040 else: 1041 kwargs = kwargs or {"expressions": converted} 1042 function = Anonymous(this=name, **kwargs) 1043 1044 for error_message in function.error_messages(converted): 1045 raise ValueError(error_message) 1046 1047 return function 1048 1049 1050def case( 1051 expression: ExpOrStr | None = None, 1052 copy: bool = True, 1053 **opts: Unpack[ParserArgs], 1054) -> Case: 1055 """ 1056 Initialize a CASE statement. 1057 1058 Example: 1059 case().when("a = 1", "foo").else_("bar") 1060 1061 Args: 1062 expression: Optionally, the input expression (not all dialects support this) 1063 copy: whether to copy the argument expressions. 1064 **opts: Extra keyword arguments for parsing `expression` 1065 """ 1066 if expression is not None: 1067 this = maybe_parse(expression, copy=copy, **opts) 1068 else: 1069 this = None 1070 return Case(this=this, ifs=[]) 1071 1072 1073def array( 1074 *expressions: ExpOrStr, 1075 copy: bool = True, 1076 dialect: DialectType = None, 1077 **kwargs: Unpack[ParserNoDialectArgs], 1078) -> Array: 1079 """ 1080 Returns an array. 1081 1082 Examples: 1083 >>> array(1, 'x').sql() 1084 'ARRAY(1, x)' 1085 1086 Args: 1087 expressions: the expressions to add to the array. 1088 copy: whether to copy the argument expressions. 1089 dialect: the source dialect. 1090 kwargs: the kwargs used to instantiate the function of interest. 1091 1092 Returns: 1093 An array expression. 1094 """ 1095 return Array( 1096 expressions=[ 1097 maybe_parse(expression, copy=copy, dialect=dialect, **kwargs) 1098 for expression in expressions 1099 ] 1100 ) 1101 1102 1103def tuple_( 1104 *expressions: ExpOrStr, 1105 copy: bool = True, 1106 dialect: DialectType = None, 1107 **kwargs: Unpack[ParserNoDialectArgs], 1108) -> Tuple: 1109 """ 1110 Returns an tuple. 1111 1112 Examples: 1113 >>> tuple_(1, 'x').sql() 1114 '(1, x)' 1115 1116 Args: 1117 expressions: the expressions to add to the tuple. 1118 copy: whether to copy the argument expressions. 1119 dialect: the source dialect. 1120 kwargs: the kwargs used to instantiate the function of interest. 1121 1122 Returns: 1123 A tuple expression. 1124 """ 1125 return Tuple( 1126 expressions=[ 1127 maybe_parse(expression, copy=copy, dialect=dialect, **kwargs) 1128 for expression in expressions 1129 ] 1130 ) 1131 1132 1133def true() -> Boolean: 1134 """ 1135 Returns a true Boolean expression. 1136 """ 1137 return Boolean(this=True) 1138 1139 1140def false() -> Boolean: 1141 """ 1142 Returns a false Boolean expression. 1143 """ 1144 return Boolean(this=False) 1145 1146 1147def null() -> Null: 1148 """ 1149 Returns a Null expression. 1150 """ 1151 return Null() 1152 1153 1154def apply_index_offset( 1155 this: Expr, 1156 expressions: list[E], 1157 offset: int, 1158 dialect: DialectType = None, 1159) -> list[E]: 1160 if not offset or len(expressions) != 1: 1161 return expressions 1162 1163 expression = expressions[0] 1164 1165 from sqlglot.optimizer.annotate_types import annotate_types 1166 from sqlglot.optimizer.simplify import simplify 1167 1168 if not this.type: 1169 annotate_types(this, dialect=dialect) 1170 1171 if t.cast(DataType, this.type).this not in ( 1172 DType.UNKNOWN, 1173 DType.ARRAY, 1174 ): 1175 return expressions 1176 1177 if not expression.type: 1178 annotate_types(expression, dialect=dialect) 1179 1180 if t.cast(DataType, expression.type).this in DataType.INTEGER_TYPES: 1181 logger.info("Applying array index offset (%s)", offset) 1182 expression = simplify(expression + offset) 1183 return [expression] 1184 1185 return expressions 1186 1187 1188NONNULL_CONSTANTS = ( 1189 Literal, 1190 Boolean, 1191) 1192 1193CONSTANTS = ( 1194 Literal, 1195 Boolean, 1196 Null, 1197)
76def select( 77 *expressions: ExpOrStr, 78 dialect: DialectType = None, 79 copy: bool = True, 80 **opts: Unpack[ParserNoDialectArgs], 81) -> Select: 82 """ 83 Initializes a syntax tree from one or multiple SELECT expressions. 84 85 Example: 86 >>> select("col1", "col2").from_("tbl").sql() 87 'SELECT col1, col2 FROM tbl' 88 89 Args: 90 *expressions: the SQL code string to parse as the expressions of a 91 SELECT statement. If an Expr instance is passed, this is used as-is. 92 dialect: the dialect used to parse the input expressions (in the case that an 93 input expression is a SQL string). 94 **opts: other options to use to parse the input expressions (again, in the case 95 that an input expression is a SQL string). 96 97 Returns: 98 Select: the syntax tree for the SELECT statement. 99 """ 100 return Select().select(*expressions, dialect=dialect, copy=copy, **opts)
Initializes a syntax tree from one or multiple SELECT expressions.
Example:
>>> select("col1", "col2").from_("tbl").sql() 'SELECT col1, col2 FROM tbl'
Arguments:
- *expressions: the SQL code string to parse as the expressions of a SELECT statement. If an Expr instance is passed, this is used as-is.
- dialect: the dialect used to parse the input expressions (in the case that an input expression is a SQL string).
- **opts: other options to use to parse the input expressions (again, in the case that an input expression is a SQL string).
Returns:
Select: the syntax tree for the SELECT statement.
103def from_( 104 expression: ExpOrStr, 105 dialect: DialectType = None, 106 copy: bool = True, 107 **opts: Unpack[ParserNoDialectArgs], 108) -> Select: 109 """ 110 Initializes a syntax tree from a FROM expression. 111 112 Example: 113 >>> from_("tbl").select("col1", "col2").sql() 114 'SELECT col1, col2 FROM tbl' 115 116 Args: 117 *expression: the SQL code string to parse as the FROM expressions of a 118 SELECT statement. If an Expr instance is passed, this is used as-is. 119 dialect: the dialect used to parse the input expression (in the case that the 120 input expression is a SQL string). 121 **opts: other options to use to parse the input expressions (again, in the case 122 that the input expression is a SQL string). 123 124 Returns: 125 Select: the syntax tree for the SELECT statement. 126 """ 127 return Select().from_(expression, dialect=dialect, copy=copy, **opts)
Initializes a syntax tree from a FROM expression.
Example:
>>> from_("tbl").select("col1", "col2").sql() 'SELECT col1, col2 FROM tbl'
Arguments:
- *expression: the SQL code string to parse as the FROM expressions of a SELECT statement. If an Expr instance is passed, this is used as-is.
- dialect: the dialect used to parse the input expression (in the case that the input expression is a SQL string).
- **opts: other options to use to parse the input expressions (again, in the case that the input expression is a SQL string).
Returns:
Select: the syntax tree for the SELECT statement.
130def update( 131 table: str | Table, 132 properties: dict[str, object] | None = None, 133 where: ExpOrStr | None = None, 134 from_: ExpOrStr | None = None, 135 with_: dict[str, ExpOrStr] | None = None, 136 dialect: DialectType = None, 137 copy: bool = True, 138 **opts: Unpack[ParserNoDialectArgs], 139) -> Update: 140 """ 141 Creates an update statement. 142 143 Example: 144 >>> update("my_table", {"x": 1, "y": "2", "z": None}, from_="baz_cte", where="baz_cte.id > 1 and my_table.id = baz_cte.id", with_={"baz_cte": "SELECT id FROM foo"}).sql() 145 "WITH baz_cte AS (SELECT id FROM foo) UPDATE my_table SET x = 1, y = '2', z = NULL FROM baz_cte WHERE baz_cte.id > 1 AND my_table.id = baz_cte.id" 146 147 Args: 148 properties: dictionary of properties to SET which are 149 auto converted to sql objects eg None -> NULL 150 where: sql conditional parsed into a WHERE statement 151 from_: sql statement parsed into a FROM statement 152 with_: dictionary of CTE aliases / select statements to include in a WITH clause. 153 dialect: the dialect used to parse the input expressions. 154 copy: whether to copy the input expressions. 155 **opts: other options to use to parse the input expressions. 156 157 Returns: 158 Update: the syntax tree for the UPDATE statement. 159 """ 160 update_expr = Update(this=maybe_parse(table, into=Table, dialect=dialect, copy=copy)) 161 if properties: 162 update_expr.set( 163 "expressions", 164 [ 165 EQ(this=maybe_parse(k, dialect=dialect, copy=copy, **opts), expression=convert(v)) 166 for k, v in properties.items() 167 ], 168 ) 169 if from_: 170 update_expr.set( 171 "from_", 172 maybe_parse(from_, into=From, dialect=dialect, prefix="FROM", copy=copy, **opts), 173 ) 174 if isinstance(where, Condition): 175 where = Where(this=where) 176 if where: 177 update_expr.set( 178 "where", 179 maybe_parse(where, into=Where, dialect=dialect, prefix="WHERE", copy=copy, **opts), 180 ) 181 if with_: 182 cte_list = [ 183 alias_( 184 CTE(this=maybe_parse(qry, dialect=dialect, copy=copy, **opts)), alias, table=True 185 ) 186 for alias, qry in with_.items() 187 ] 188 update_expr.set( 189 "with_", 190 With(expressions=cte_list), 191 ) 192 return update_expr
Creates an update statement.
Example:
>>> update("my_table", {"x": 1, "y": "2", "z": None}, from_="baz_cte", where="baz_cte.id > 1 and my_table.id = baz_cte.id", with_={"baz_cte": "SELECT id FROM foo"}).sql() "WITH baz_cte AS (SELECT id FROM foo) UPDATE my_table SET x = 1, y = '2', z = NULL FROM baz_cte WHERE baz_cte.id > 1 AND my_table.id = baz_cte.id"
Arguments:
- properties: dictionary of properties to SET which are auto converted to sql objects eg None -> NULL
- where: sql conditional parsed into a WHERE statement
- from_: sql statement parsed into a FROM statement
- with_: dictionary of CTE aliases / select statements to include in a WITH clause.
- dialect: the dialect used to parse the input expressions.
- copy: whether to copy the input expressions.
- **opts: other options to use to parse the input expressions.
Returns:
Update: the syntax tree for the UPDATE statement.
195def delete( 196 table: ExpOrStr, 197 where: ExpOrStr | None = None, 198 returning: ExpOrStr | None = None, 199 dialect: DialectType = None, 200 **opts: Unpack[ParserNoDialectArgs], 201) -> Delete: 202 """ 203 Builds a delete statement. 204 205 Example: 206 >>> delete("my_table", where="id > 1").sql() 207 'DELETE FROM my_table WHERE id > 1' 208 209 Args: 210 where: sql conditional parsed into a WHERE statement 211 returning: sql conditional parsed into a RETURNING statement 212 dialect: the dialect used to parse the input expressions. 213 **opts: other options to use to parse the input expressions. 214 215 Returns: 216 Delete: the syntax tree for the DELETE statement. 217 """ 218 delete_expr = Delete().delete(table, dialect=dialect, copy=False, **opts) 219 if where: 220 delete_expr = delete_expr.where(where, dialect=dialect, copy=False, **opts) 221 if returning: 222 delete_expr = delete_expr.returning(returning, dialect=dialect, copy=False, **opts) 223 return delete_expr
Builds a delete statement.
Example:
>>> delete("my_table", where="id > 1").sql() 'DELETE FROM my_table WHERE id > 1'
Arguments:
- where: sql conditional parsed into a WHERE statement
- returning: sql conditional parsed into a RETURNING statement
- dialect: the dialect used to parse the input expressions.
- **opts: other options to use to parse the input expressions.
Returns:
Delete: the syntax tree for the DELETE statement.
226def insert( 227 expression: ExpOrStr, 228 into: str | Table, 229 columns: Sequence[str | Identifier] | None = None, 230 overwrite: bool | None = None, 231 returning: ExpOrStr | None = None, 232 dialect: DialectType = None, 233 copy: bool = True, 234 **opts: Unpack[ParserNoDialectArgs], 235) -> Insert: 236 """ 237 Builds an INSERT statement. 238 239 Example: 240 >>> insert("VALUES (1, 2, 3)", "tbl").sql() 241 'INSERT INTO tbl VALUES (1, 2, 3)' 242 243 Args: 244 expression: the sql string or expression of the INSERT statement 245 into: the tbl to insert data to. 246 columns: optionally the table's column names. 247 overwrite: whether to INSERT OVERWRITE or not. 248 returning: sql conditional parsed into a RETURNING statement 249 dialect: the dialect used to parse the input expressions. 250 copy: whether to copy the expression. 251 **opts: other options to use to parse the input expressions. 252 253 Returns: 254 Insert: the syntax tree for the INSERT statement. 255 """ 256 expr = maybe_parse(expression, dialect=dialect, copy=copy, **opts) 257 this: Table | Schema = maybe_parse(into, into=Table, dialect=dialect, copy=copy, **opts) 258 259 if columns: 260 this = Schema(this=this, expressions=[to_identifier(c, copy=copy) for c in columns]) 261 262 insert = Insert(this=this, expression=expr, overwrite=overwrite) 263 264 if returning: 265 insert = insert.returning(returning, dialect=dialect, copy=False, **opts) 266 267 return insert
Builds an INSERT statement.
Example:
>>> insert("VALUES (1, 2, 3)", "tbl").sql() 'INSERT INTO tbl VALUES (1, 2, 3)'
Arguments:
- expression: the sql string or expression of the INSERT statement
- into: the tbl to insert data to.
- columns: optionally the table's column names.
- overwrite: whether to INSERT OVERWRITE or not.
- returning: sql conditional parsed into a RETURNING statement
- dialect: the dialect used to parse the input expressions.
- copy: whether to copy the expression.
- **opts: other options to use to parse the input expressions.
Returns:
Insert: the syntax tree for the INSERT statement.
270def merge( 271 *when_exprs: ExpOrStr, 272 into: ExpOrStr, 273 using: ExpOrStr, 274 on: ExpOrStr, 275 returning: ExpOrStr | None = None, 276 dialect: DialectType = None, 277 copy: bool = True, 278 **opts: Unpack[ParserNoDialectArgs], 279) -> Merge: 280 """ 281 Builds a MERGE statement. 282 283 Example: 284 >>> merge("WHEN MATCHED THEN UPDATE SET col1 = source_table.col1", 285 ... "WHEN NOT MATCHED THEN INSERT (col1) VALUES (source_table.col1)", 286 ... into="my_table", 287 ... using="source_table", 288 ... on="my_table.id = source_table.id").sql() 289 'MERGE INTO my_table USING source_table ON my_table.id = source_table.id WHEN MATCHED THEN UPDATE SET col1 = source_table.col1 WHEN NOT MATCHED THEN INSERT (col1) VALUES (source_table.col1)' 290 291 Args: 292 *when_exprs: The WHEN clauses specifying actions for matched and unmatched rows. 293 into: The target table to merge data into. 294 using: The source table to merge data from. 295 on: The join condition for the merge. 296 returning: The columns to return from the merge. 297 dialect: The dialect used to parse the input expressions. 298 copy: Whether to copy the expression. 299 **opts: Other options to use to parse the input expressions. 300 301 Returns: 302 Merge: The syntax tree for the MERGE statement. 303 """ 304 expressions: list[Expr] = [] 305 for when_expr in when_exprs: 306 expression = maybe_parse(when_expr, dialect=dialect, copy=copy, into=Whens, **opts) 307 expressions.extend([expression] if isinstance(expression, When) else expression.expressions) 308 309 merge = Merge( 310 this=maybe_parse(into, dialect=dialect, copy=copy, **opts), 311 using=maybe_parse(using, dialect=dialect, copy=copy, **opts), 312 on=maybe_parse(on, dialect=dialect, copy=copy, **opts), 313 whens=Whens(expressions=expressions), 314 ) 315 if returning: 316 merge = merge.returning(returning, dialect=dialect, copy=False, **opts) 317 318 if isinstance(using_clause := merge.args.get("using"), Alias): 319 using_clause.replace(alias_(using_clause.this, using_clause.args["alias"], table=True)) 320 321 return merge
Builds a MERGE statement.
Example:
>>> merge("WHEN MATCHED THEN UPDATE SET col1 = source_table.col1", ... "WHEN NOT MATCHED THEN INSERT (col1) VALUES (source_table.col1)", ... into="my_table", ... using="source_table", ... on="my_table.id = source_table.id").sql() 'MERGE INTO my_table USING source_table ON my_table.id = source_table.id WHEN MATCHED THEN UPDATE SET col1 = source_table.col1 WHEN NOT MATCHED THEN INSERT (col1) VALUES (source_table.col1)'
Arguments:
- *when_exprs: The WHEN clauses specifying actions for matched and unmatched rows.
- into: The target table to merge data into.
- using: The source table to merge data from.
- on: The join condition for the merge.
- returning: The columns to return from the merge.
- dialect: The dialect used to parse the input expressions.
- copy: Whether to copy the expression.
- **opts: Other options to use to parse the input expressions.
Returns:
Merge: The syntax tree for the MERGE statement.
324def parse_identifier(name: str | Identifier, dialect: DialectType = None) -> Identifier: 325 """ 326 Parses a given string into an identifier. 327 328 Args: 329 name: The name to parse into an identifier. 330 dialect: The dialect to parse against. 331 332 Returns: 333 The identifier ast node. 334 """ 335 if isinstance(name, str) and SAFE_IDENTIFIER_RE.match(name): 336 # Simple names parse to a single unquoted identifier in all dialects, so we can 337 # avoid the tokenizer/parser round-trip for them. 338 return Identifier(this=name, quoted=False) 339 340 try: 341 expression = maybe_parse(name, dialect=dialect, into=Identifier) 342 except (ParseError, TokenError): 343 expression = to_identifier(name) 344 345 return expression
Parses a given string into an identifier.
Arguments:
- name: The name to parse into an identifier.
- dialect: The dialect to parse against.
Returns:
The identifier ast node.
356def to_interval(interval: str | Expr) -> Interval: 357 """Builds an interval expression from a string like '1 day' or '5 months'.""" 358 if isinstance(interval, Literal): 359 if not interval.is_string: 360 raise ValueError("Invalid interval string.") 361 362 interval = interval.this 363 364 interval = maybe_parse(f"INTERVAL {interval}") 365 assert isinstance(interval, Interval) 366 return interval
Builds an interval expression from a string like '1 day' or '5 months'.
369def to_table( 370 sql_path: str | Table, dialect: DialectType = None, copy: bool = True, **kwargs: object 371) -> Table: 372 """ 373 Create a table expression from a `[catalog].[schema].[table]` sql path. Catalog and schema are optional. 374 If a table is passed in then that table is returned. 375 376 Args: 377 sql_path: a `[catalog].[schema].[table]` string. 378 dialect: the source dialect according to which the table name will be parsed. 379 copy: Whether to copy a table if it is passed in. 380 kwargs: the kwargs to instantiate the resulting `Table` expression with. 381 382 Returns: 383 A table expression. 384 """ 385 if isinstance(sql_path, Table): 386 return maybe_copy(sql_path, copy=copy) 387 388 try: 389 table = maybe_parse(sql_path, into=Table, dialect=dialect) 390 except ParseError: 391 catalog, db, this = split_num_words(sql_path, ".", 3) 392 393 if not this: 394 raise 395 396 table = table_(this, db=db, catalog=catalog) 397 398 return table.set_kwargs(kwargs)
Create a table expression from a [catalog].[schema].[table] sql path. Catalog and schema are optional.
If a table is passed in then that table is returned.
Arguments:
- sql_path: a
[catalog].[schema].[table]string. - dialect: the source dialect according to which the table name will be parsed.
- copy: Whether to copy a table if it is passed in.
- kwargs: the kwargs to instantiate the resulting
Tableexpression with.
Returns:
A table expression.
401def to_column( 402 sql_path: str | Column, 403 quoted: bool | None = None, 404 dialect: DialectType = None, 405 copy: bool = True, 406 **kwargs: t.Any, 407) -> Column | Dot: 408 """ 409 Create a column from a `[table].[column]` sql path. Table is optional. 410 If a column is passed in then that column is returned. 411 412 Args: 413 sql_path: a `[table].[column]` string. 414 quoted: Whether or not to force quote identifiers. 415 dialect: the source dialect according to which the column name will be parsed. 416 copy: Whether to copy a column if it is passed in. 417 kwargs: the kwargs to instantiate the resulting `Column` expression with. 418 419 Returns: 420 A column expression. 421 """ 422 if isinstance(sql_path, Column): 423 return maybe_copy(sql_path, copy=copy) 424 425 try: 426 col = maybe_parse(sql_path, into=Column, dialect=dialect) 427 except ParseError: 428 return column(*reversed(sql_path.split(".")), quoted=quoted, **kwargs) 429 430 for k, v in kwargs.items(): 431 col.set(k, v) 432 433 if quoted: 434 for i in col.find_all(Identifier): 435 i.set("quoted", True) 436 437 return col
Create a column from a [table].[column] sql path. Table is optional.
If a column is passed in then that column is returned.
Arguments:
- sql_path: a
[table].[column]string. - quoted: Whether or not to force quote identifiers.
- dialect: the source dialect according to which the column name will be parsed.
- copy: Whether to copy a column if it is passed in.
- kwargs: the kwargs to instantiate the resulting
Columnexpression with.
Returns:
A column expression.
440def subquery( 441 expression: ExpOrStr, 442 alias: Identifier | str | None = None, 443 dialect: DialectType = None, 444 copy: bool = True, 445 **opts: Unpack[ParserNoDialectArgs], 446) -> Select: 447 """ 448 Build a subquery expression that's selected from. 449 450 Example: 451 >>> subquery('select x from tbl', 'bar').select('x').sql() 452 'SELECT x FROM (SELECT x FROM tbl) AS bar' 453 454 Args: 455 expression: the SQL code strings to parse. 456 If an Expr instance is passed, this is used as-is. 457 alias: the alias name to use. 458 dialect: the dialect used to parse the input expression. 459 **opts: other options to use to parse the input expressions. 460 461 Returns: 462 A new Select instance with the subquery expression included. 463 """ 464 expr = ( 465 maybe_parse(expression, dialect=dialect, **opts).assert_is(Query).subquery(alias, copy=copy) 466 ) 467 return Select().from_(expr, dialect=dialect, **opts)
Build a subquery expression that's selected from.
Example:
>>> subquery('select x from tbl', 'bar').select('x').sql() 'SELECT x FROM (SELECT x FROM tbl) AS bar'
Arguments:
- expression: the SQL code strings to parse. If an Expr instance is passed, this is used as-is.
- alias: the alias name to use.
- dialect: the dialect used to parse the input expression.
- **opts: other options to use to parse the input expressions.
Returns:
A new Select instance with the subquery expression included.
470def cast( 471 expression: ExpOrStr, 472 to: DATA_TYPE, 473 copy: bool = True, 474 dialect: DialectType = None, 475 **opts: Unpack[ParserNoDialectArgs], 476) -> Cast: 477 """Cast an expression to a data type. 478 479 Example: 480 >>> cast('x + 1', 'int').sql() 481 'CAST(x + 1 AS INT)' 482 483 Args: 484 expression: The expression to cast. 485 to: The datatype to cast to. 486 copy: Whether to copy the supplied expressions. 487 dialect: The target dialect. This is used to prevent a re-cast in the following scenario: 488 - The expression to be cast is already a exp.Cast expression 489 - The existing cast is to a type that is logically equivalent to new type 490 491 For example, if :expression='CAST(x as DATETIME)' and :to=Type.TIMESTAMP, 492 but in the target dialect DATETIME is mapped to TIMESTAMP, then we will NOT return `CAST(x (as DATETIME) as TIMESTAMP)` 493 and instead just return the original expression `CAST(x as DATETIME)`. 494 495 This is to prevent it being output as a double cast `CAST(x (as TIMESTAMP) as TIMESTAMP)` once the DATETIME -> TIMESTAMP 496 mapping is applied in the target dialect generator. 497 498 Returns: 499 The new Cast instance. 500 """ 501 expr = maybe_parse(expression, copy=copy, dialect=dialect, **opts) 502 data_type = DataType.build(to, copy=copy, dialect=dialect, **opts) 503 504 # dont re-cast if the expression is already a cast to the correct type 505 if isinstance(expr, Cast): 506 from sqlglot.dialects.dialect import Dialect 507 508 target_dialect = Dialect.get_or_raise(dialect) 509 type_mapping = target_dialect.generator_class.TYPE_MAPPING 510 511 existing_cast_type = expr.to.this 512 new_cast_type: DType = data_type.this 513 # `this` is only a plain type enum for simple types; complex ones such as 514 # INTERVAL nest another expression there, so the equivalence check is skipped. 515 types_are_equivalent = ( 516 isinstance(existing_cast_type, DType) 517 and isinstance(new_cast_type, DType) 518 and type_mapping.get(existing_cast_type, existing_cast_type.value) 519 == type_mapping.get(new_cast_type, new_cast_type.value) 520 ) 521 522 if expr.is_type(data_type) or types_are_equivalent: 523 return expr 524 525 expr = Cast(this=expr, to=data_type) 526 expr.type = data_type 527 528 return expr
Cast an expression to a data type.
Example:
>>> cast('x + 1', 'int').sql() 'CAST(x + 1 AS INT)'
Arguments:
- expression: The expression to cast.
- to: The datatype to cast to.
- copy: Whether to copy the supplied expressions.
dialect: The target dialect. This is used to prevent a re-cast in the following scenario:
- The expression to be cast is already a exp.Cast expression
- The existing cast is to a type that is logically equivalent to new type
For example, if :expression='CAST(x as DATETIME)' and :to=Type.TIMESTAMP, but in the target dialect DATETIME is mapped to TIMESTAMP, then we will NOT return
CAST(x (as DATETIME) as TIMESTAMP)and instead just return the original expressionCAST(x as DATETIME).This is to prevent it being output as a double cast
CAST(x (as TIMESTAMP) as TIMESTAMP)once the DATETIME -> TIMESTAMP mapping is applied in the target dialect generator.
Returns:
The new Cast instance.
531def table_( 532 table: Identifier | str | None, 533 db: Identifier | str | None = None, 534 catalog: Identifier | str | None = None, 535 quoted: bool | None = None, 536 alias: Identifier | str | None = None, 537) -> Table: 538 """Build a Table. 539 540 Args: 541 table: Table name. 542 db: Database name. 543 catalog: Catalog name. 544 quote: Whether to force quotes on the table's identifiers. 545 alias: Table's alias. 546 547 Returns: 548 The new Table instance. 549 """ 550 return Table( 551 this=to_identifier(table, quoted=quoted) if table else None, 552 db=to_identifier(db, quoted=quoted) if db else None, 553 catalog=to_identifier(catalog, quoted=quoted) if catalog else None, 554 alias=TableAlias(this=to_identifier(alias)) if alias else None, 555 )
Build a Table.
Arguments:
- table: Table name.
- db: Database name.
- catalog: Catalog name.
- quote: Whether to force quotes on the table's identifiers.
- alias: Table's alias.
Returns:
The new Table instance.
558def values( 559 values: Iterable[tuple[object, ...] | Tuple], 560 alias: str | None = None, 561 columns: Iterable[str] | dict[str, DataType] | None = None, 562) -> Values: 563 """Build VALUES statement. 564 565 Example: 566 >>> values([(1, '2')]).sql() 567 "VALUES (1, '2')" 568 569 Args: 570 values: values statements that will be converted to SQL 571 alias: optional alias 572 columns: Optional list of ordered column names or ordered dictionary of column names to types. 573 If either are provided then an alias is also required. 574 575 Returns: 576 Values: the Values expression object 577 """ 578 if columns and not alias: 579 raise ValueError("Alias is required when providing columns") 580 581 return Values( 582 expressions=[convert(tup) for tup in values], 583 alias=( 584 TableAlias(this=to_identifier(alias), columns=[to_identifier(x) for x in columns]) 585 if columns 586 else (TableAlias(this=to_identifier(alias)) if alias else None) 587 ), 588 )
Build VALUES statement.
Example:
>>> values([(1, '2')]).sql() "VALUES (1, '2')"
Arguments:
- values: values statements that will be converted to SQL
- alias: optional alias
- columns: Optional list of ordered column names or ordered dictionary of column names to types. If either are provided then an alias is also required.
Returns:
Values: the Values expression object
591def var(name: ExpOrStr | None) -> Var: 592 """Build a SQL variable. 593 594 Example: 595 >>> repr(var('x')) 596 'Var(this=x)' 597 598 >>> repr(var(column('x', table='y'))) 599 'Var(this=x)' 600 601 Args: 602 name: The name of the var or an expression who's name will become the var. 603 604 Returns: 605 The new variable node. 606 """ 607 if not name: 608 raise ValueError("Cannot convert empty name into var.") 609 610 if isinstance(name, Expr): 611 name = name.name 612 return Var(this=name)
Build a SQL variable.
Example:
>>> repr(var('x')) 'Var(this=x)'>>> repr(var(column('x', table='y'))) 'Var(this=x)'
Arguments:
- name: The name of the var or an expression who's name will become the var.
Returns:
The new variable node.
615def rename_table( 616 old_name: str | Table, 617 new_name: str | Table, 618 dialect: DialectType = None, 619) -> Alter: 620 """Build ALTER TABLE... RENAME... expression 621 622 Args: 623 old_name: The old name of the table 624 new_name: The new name of the table 625 dialect: The dialect to parse the table. 626 627 Returns: 628 Alter table expression 629 """ 630 old_table = to_table(old_name, dialect=dialect) 631 new_table = to_table(new_name, dialect=dialect) 632 return Alter( 633 this=old_table, 634 kind="TABLE", 635 actions=[ 636 AlterRename(this=new_table), 637 ], 638 )
Build ALTER TABLE... RENAME... expression
Arguments:
- old_name: The old name of the table
- new_name: The new name of the table
- dialect: The dialect to parse the table.
Returns:
Alter table expression
641def rename_column( 642 table_name: str | Table, 643 old_column_name: str | Column, 644 new_column_name: str | Column, 645 exists: bool | None = None, 646 dialect: DialectType = None, 647) -> Alter: 648 """Build ALTER TABLE... RENAME COLUMN... expression 649 650 Args: 651 table_name: Name of the table 652 old_column: The old name of the column 653 new_column: The new name of the column 654 exists: Whether to add the `IF EXISTS` clause 655 dialect: The dialect to parse the table/column. 656 657 Returns: 658 Alter table expression 659 """ 660 table = to_table(table_name, dialect=dialect) 661 old_column = to_column(old_column_name, dialect=dialect) 662 new_column = to_column(new_column_name, dialect=dialect) 663 return Alter( 664 this=table, 665 kind="TABLE", 666 actions=[ 667 RenameColumn(this=old_column, to=new_column, exists=exists), 668 ], 669 )
Build ALTER TABLE... RENAME COLUMN... expression
Arguments:
- table_name: Name of the table
- old_column: The old name of the column
- new_column: The new name of the column
- exists: Whether to add the
IF EXISTSclause - dialect: The dialect to parse the table/column.
Returns:
Alter table expression
672def replace_children( 673 expression: Expr, 674 fun: t.Callable[Concatenate[Expr, P], object], 675 *args: P.args, 676 **kwargs: P.kwargs, 677) -> None: 678 """ 679 Replace children of an expression with the result of a lambda fun(child) -> exp. 680 """ 681 for k, v in tuple(expression.args.items()): 682 is_list_arg = type(v) is list 683 684 child_nodes = v if is_list_arg else [v] 685 new_child_nodes = [] 686 687 for cn in child_nodes: 688 if isinstance(cn, Expr): 689 for child_node in ensure_collection(fun(cn, *args, **kwargs)): 690 new_child_nodes.append(child_node) 691 else: 692 new_child_nodes.append(cn) 693 694 if is_list_arg: 695 expression.set(k, new_child_nodes) 696 else: 697 expression.set(k, seq_get(new_child_nodes, 0))
Replace children of an expression with the result of a lambda fun(child) -> exp.
700def replace_tree( 701 expression: Expr, 702 fun: t.Callable[[Expr], Expr], 703 prune: t.Callable[[Expr], bool] | None = None, 704) -> Expr: 705 """ 706 Replace an entire tree with the result of function calls on each node. 707 708 This will be traversed in reverse dfs, so leaves first. 709 If new nodes are created as a result of function calls, they will also be traversed. 710 """ 711 stack = list(expression.dfs(prune=prune)) 712 713 while stack: 714 node = stack.pop() 715 new_node = fun(node) 716 717 if new_node is not node: 718 node.replace(new_node) 719 720 if isinstance(new_node, Expr): 721 stack.append(new_node) 722 723 return new_node
Replace an entire tree with the result of function calls on each node.
This will be traversed in reverse dfs, so leaves first. If new nodes are created as a result of function calls, they will also be traversed.
726def find_tables(expression: Expr) -> set[Table]: 727 """ 728 Find all tables referenced in a query. 729 730 Args: 731 expressions: The query to find the tables in. 732 733 Returns: 734 A set of all the tables. 735 """ 736 from sqlglot.optimizer.scope import traverse_scope 737 738 return { 739 table 740 for scope in traverse_scope(expression) 741 for table in scope.tables 742 if isinstance(table, Table) and table.name and table.name not in scope.cte_sources 743 }
Find all tables referenced in a query.
Arguments:
- expressions: The query to find the tables in.
Returns:
A set of all the tables.
746def column_table_names(expression: Expr, exclude: str = "") -> set[str]: 747 """ 748 Return all table names referenced through columns in an expression. 749 750 Example: 751 >>> import sqlglot 752 >>> sorted(column_table_names(sqlglot.parse_one("a.b AND c.d AND c.e"))) 753 ['a', 'c'] 754 755 Args: 756 expression: expression to find table names. 757 exclude: a table name to exclude 758 759 Returns: 760 A list of unique names. 761 """ 762 return { 763 table 764 for table in (column.table for column in expression.find_all(Column)) 765 if table and table != exclude 766 }
Return all table names referenced through columns in an expression.
Example:
>>> import sqlglot >>> sorted(column_table_names(sqlglot.parse_one("a.b AND c.d AND c.e"))) ['a', 'c']
Arguments:
- expression: expression to find table names.
- exclude: a table name to exclude
Returns:
A list of unique names.
769def table_name(table: Table | str, dialect: DialectType = None, identify: bool = False) -> str: 770 """Get the full name of a table as a string. 771 772 Args: 773 table: Table expression node or string. 774 dialect: The dialect to generate the table name for. 775 identify: Determines when an identifier should be quoted. Possible values are: 776 False (default): Never quote, except in cases where it's mandatory by the dialect. 777 True: Always quote. 778 779 Examples: 780 >>> from sqlglot import exp, parse_one 781 >>> table_name(parse_one("select * from a.b.c").find(exp.Table)) 782 'a.b.c' 783 784 Returns: 785 The table name. 786 """ 787 788 expr = maybe_parse(table, into=Table, dialect=dialect) 789 790 if not expr: 791 raise ValueError(f"Cannot parse {table}") 792 793 return ".".join( 794 ( 795 part.sql(dialect=dialect, identify=True, copy=False, comments=False) 796 if identify or not SAFE_IDENTIFIER_RE.match(part.name) 797 else part.name 798 ) 799 for part in expr.parts 800 )
Get the full name of a table as a string.
Arguments:
- table: Table expression node or string.
- dialect: The dialect to generate the table name for.
- 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.
Examples:
>>> from sqlglot import exp, parse_one >>> table_name(parse_one("select * from a.b.c").find(exp.Table)) 'a.b.c'
Returns:
The table name.
803def normalize_table_name(table: str | Table, dialect: DialectType = None, copy: bool = True) -> str: 804 """Returns a case normalized table name without quotes. 805 806 Args: 807 table: the table to normalize 808 dialect: the dialect to use for normalization rules 809 copy: whether to copy the expression. 810 811 Examples: 812 >>> normalize_table_name("`A-B`.c", dialect="bigquery") 813 'A-B.c' 814 """ 815 from sqlglot.optimizer.normalize_identifiers import normalize_identifiers 816 817 return ".".join( 818 p.name 819 for p in normalize_identifiers( 820 to_table(table, dialect=dialect, copy=copy), dialect=dialect 821 ).parts 822 )
Returns a case normalized table name without quotes.
Arguments:
- table: the table to normalize
- dialect: the dialect to use for normalization rules
- copy: whether to copy the expression.
Examples:
>>> normalize_table_name("`A-B`.c", dialect="bigquery") 'A-B.c'
825def replace_tables( 826 expression: E, mapping: dict[str, str], dialect: DialectType = None, copy: bool = True 827) -> E: 828 """Replace all tables in expression according to the mapping. 829 830 Args: 831 expression: expression node to be transformed and replaced. 832 mapping: mapping of table names. 833 dialect: the dialect of the mapping table 834 copy: whether to copy the expression. 835 836 Examples: 837 >>> from sqlglot import exp, parse_one 838 >>> replace_tables(parse_one("select * from a.b"), {"a.b": "c"}).sql() 839 'SELECT * FROM c /* a.b */' 840 841 Returns: 842 The mapped expression. 843 """ 844 845 mapping = {normalize_table_name(k, dialect=dialect): v for k, v in mapping.items()} 846 847 def _replace_tables(node: Expr) -> Expr: 848 if isinstance(node, Table) and node.meta_get("replace") is not False: 849 original = normalize_table_name(node, dialect=dialect) 850 new_name = mapping.get(original) 851 852 if new_name: 853 table = to_table( 854 new_name, 855 **{k: v for k, v in node.args.items() if k not in TABLE_PARTS}, 856 dialect=dialect, 857 ) 858 table.add_comments([original]) 859 return table 860 return node 861 862 return expression.transform(_replace_tables, copy=copy) # type: ignore
Replace all tables in expression according to the mapping.
Arguments:
- expression: expression node to be transformed and replaced.
- mapping: mapping of table names.
- dialect: the dialect of the mapping table
- copy: whether to copy the expression.
Examples:
>>> from sqlglot import exp, parse_one >>> replace_tables(parse_one("select * from a.b"), {"a.b": "c"}).sql() 'SELECT * FROM c /* a.b */'
Returns:
The mapped expression.
902def replace_placeholders(expression: Expr, *args: object, **kwargs: t.Any) -> Expr: 903 """Replace placeholders in an expression. 904 905 Args: 906 expression: expression node to be transformed and replaced. 907 args: positional names that will substitute unnamed placeholders in the given order. 908 kwargs: keyword arguments that will substitute named placeholders. 909 910 Examples: 911 >>> from sqlglot import exp, parse_one 912 >>> replace_placeholders( 913 ... parse_one("select * from :tbl where ? = ?"), 914 ... exp.to_identifier("str_col"), "b", tbl=exp.to_identifier("foo") 915 ... ).sql() 916 "SELECT * FROM foo WHERE str_col = 'b'" 917 918 Returns: 919 The mapped expression. 920 """ 921 922 def _replace_placeholders(node: Expr, args: Iterator[object], **kwargs: object) -> Expr: 923 if isinstance(node, Placeholder): 924 if node.this: 925 new_name = kwargs.get(node.this) 926 if new_name is not None: 927 return _replace_placeholder(node, convert(new_name)) 928 else: 929 try: 930 return _replace_placeholder(node, convert(next(args))) 931 except StopIteration: 932 pass 933 return node 934 935 return expression.transform(_replace_placeholders, iter(args), **kwargs)
Replace placeholders in an expression.
Arguments:
- expression: expression node to be transformed and replaced.
- args: positional names that will substitute unnamed placeholders in the given order.
- kwargs: keyword arguments that will substitute named placeholders.
Examples:
>>> from sqlglot import exp, parse_one >>> replace_placeholders( ... parse_one("select * from :tbl where ? = ?"), ... exp.to_identifier("str_col"), "b", tbl=exp.to_identifier("foo") ... ).sql() "SELECT * FROM foo WHERE str_col = 'b'"
Returns:
The mapped expression.
938def expand( 939 expression: Expr, 940 sources: dict[str, Query | t.Callable[[], Query]], 941 dialect: DialectType = None, 942 copy: bool = True, 943) -> Expr: 944 """Transforms an expression by expanding all referenced sources into subqueries. 945 946 Examples: 947 >>> from sqlglot import parse_one 948 >>> expand(parse_one("select * from x AS z"), {"x": parse_one("select * from y")}).sql() 949 'SELECT * FROM (SELECT * FROM y) AS z /* source: x */' 950 951 >>> expand(parse_one("select * from x AS z"), {"x": parse_one("select * from y"), "y": parse_one("select * from z")}).sql() 952 'SELECT * FROM (SELECT * FROM (SELECT * FROM z) AS y /* source: y */) AS z /* source: x */' 953 954 Args: 955 expression: The expression to expand. 956 sources: A dict of name to query or a callable that provides a query on demand. 957 dialect: The dialect of the sources dict or the callable. 958 copy: Whether to copy the expression during transformation. Defaults to True. 959 960 Returns: 961 The transformed expression. 962 """ 963 normalized_sources = {normalize_table_name(k, dialect=dialect): v for k, v in sources.items()} 964 965 def _expand(node: Expr): 966 if isinstance(node, Table): 967 name = normalize_table_name(node, dialect=dialect) 968 source = normalized_sources.get(name) 969 970 if source: 971 # Create a subquery with the same alias (or table name if no alias) 972 parsed_source = source() if callable(source) else source 973 subquery = parsed_source.subquery(node.alias or name) 974 subquery.comments = [f"source: {name}"] 975 976 # Continue expanding within the subquery 977 return subquery.transform(_expand, copy=False) 978 979 return node 980 981 return expression.transform(_expand, copy=copy)
Transforms an expression by expanding all referenced sources into subqueries.
Examples:
>>> from sqlglot import parse_one >>> expand(parse_one("select * from x AS z"), {"x": parse_one("select * from y")}).sql() 'SELECT * FROM (SELECT * FROM y) AS z /* source: x */'>>> expand(parse_one("select * from x AS z"), {"x": parse_one("select * from y"), "y": parse_one("select * from z")}).sql() 'SELECT * FROM (SELECT * FROM (SELECT * FROM z) AS y /* source: y */) AS z /* source: x */'
Arguments:
- expression: The expression to expand.
- sources: A dict of name to query or a callable that provides a query on demand.
- dialect: The dialect of the sources dict or the callable.
- copy: Whether to copy the expression during transformation. Defaults to True.
Returns:
The transformed expression.
984def func( 985 name: str, *args: t.Any, copy: bool = True, dialect: DialectType = None, **kwargs: t.Any 986) -> Func: 987 """ 988 Returns a Func expression. 989 990 Examples: 991 >>> func("abs", 5).sql() 992 'ABS(5)' 993 994 >>> func("cast", this=5, to=DataType.build("DOUBLE")).sql() 995 'CAST(5 AS DOUBLE)' 996 997 Args: 998 name: the name of the function to build. 999 args: the args used to instantiate the function of interest. 1000 copy: whether to copy the argument expressions. 1001 dialect: the source dialect. 1002 kwargs: the kwargs used to instantiate the function of interest. 1003 1004 Note: 1005 The arguments `args` and `kwargs` are mutually exclusive. 1006 1007 Returns: 1008 An instance of the function of interest, or an anonymous function, if `name` doesn't 1009 correspond to an existing `sqlglot.expressions.Func` class. 1010 """ 1011 if args and kwargs: 1012 raise ValueError("Can't use both args and kwargs to instantiate a function.") 1013 1014 from sqlglot.dialects.dialect import Dialect 1015 1016 dialect = Dialect.get_or_raise(dialect) 1017 1018 converted: list[Expr] = [maybe_parse(arg, dialect=dialect, copy=copy) for arg in args] 1019 kwargs = {key: maybe_parse(value, dialect=dialect, copy=copy) for key, value in kwargs.items()} 1020 1021 constructor = dialect.parser_class.FUNCTIONS.get(name.upper()) 1022 if constructor: 1023 if converted: 1024 try: 1025 function = constructor(converted) 1026 except TypeError: 1027 function = constructor(converted, dialect=dialect) 1028 elif constructor.__name__ == "from_arg_list": 1029 function = constructor.__self__(**kwargs) # type: ignore 1030 else: 1031 from sqlglot.expressions import FUNCTION_BY_NAME as _FUNCTION_BY_NAME 1032 1033 constructor = _FUNCTION_BY_NAME.get(name.upper()) 1034 if constructor: 1035 function = constructor(**kwargs) 1036 else: 1037 raise ValueError( 1038 f"Unable to convert '{name}' into a Func. Either manually construct " 1039 "the Func expression of interest or parse the function call." 1040 ) 1041 else: 1042 kwargs = kwargs or {"expressions": converted} 1043 function = Anonymous(this=name, **kwargs) 1044 1045 for error_message in function.error_messages(converted): 1046 raise ValueError(error_message) 1047 1048 return function
Returns a Func expression.
Examples:
>>> func("abs", 5).sql() 'ABS(5)'>>> func("cast", this=5, to=DataType.build("DOUBLE")).sql() 'CAST(5 AS DOUBLE)'
Arguments:
- name: the name of the function to build.
- args: the args used to instantiate the function of interest.
- copy: whether to copy the argument expressions.
- dialect: the source dialect.
- kwargs: the kwargs used to instantiate the function of interest.
Note:
The arguments
argsandkwargsare mutually exclusive.
Returns:
An instance of the function of interest, or an anonymous function, if
namedoesn't correspond to an existingsqlglot.expressions.Funcclass.
1051def case( 1052 expression: ExpOrStr | None = None, 1053 copy: bool = True, 1054 **opts: Unpack[ParserArgs], 1055) -> Case: 1056 """ 1057 Initialize a CASE statement. 1058 1059 Example: 1060 case().when("a = 1", "foo").else_("bar") 1061 1062 Args: 1063 expression: Optionally, the input expression (not all dialects support this) 1064 copy: whether to copy the argument expressions. 1065 **opts: Extra keyword arguments for parsing `expression` 1066 """ 1067 if expression is not None: 1068 this = maybe_parse(expression, copy=copy, **opts) 1069 else: 1070 this = None 1071 return Case(this=this, ifs=[])
Initialize a CASE statement.
Example:
case().when("a = 1", "foo").else_("bar")
Arguments:
- expression: Optionally, the input expression (not all dialects support this)
- copy: whether to copy the argument expressions.
- **opts: Extra keyword arguments for parsing
expression
1074def array( 1075 *expressions: ExpOrStr, 1076 copy: bool = True, 1077 dialect: DialectType = None, 1078 **kwargs: Unpack[ParserNoDialectArgs], 1079) -> Array: 1080 """ 1081 Returns an array. 1082 1083 Examples: 1084 >>> array(1, 'x').sql() 1085 'ARRAY(1, x)' 1086 1087 Args: 1088 expressions: the expressions to add to the array. 1089 copy: whether to copy the argument expressions. 1090 dialect: the source dialect. 1091 kwargs: the kwargs used to instantiate the function of interest. 1092 1093 Returns: 1094 An array expression. 1095 """ 1096 return Array( 1097 expressions=[ 1098 maybe_parse(expression, copy=copy, dialect=dialect, **kwargs) 1099 for expression in expressions 1100 ] 1101 )
Returns an array.
Examples:
>>> array(1, 'x').sql() 'ARRAY(1, x)'
Arguments:
- expressions: the expressions to add to the array.
- copy: whether to copy the argument expressions.
- dialect: the source dialect.
- kwargs: the kwargs used to instantiate the function of interest.
Returns:
An array expression.
1104def tuple_( 1105 *expressions: ExpOrStr, 1106 copy: bool = True, 1107 dialect: DialectType = None, 1108 **kwargs: Unpack[ParserNoDialectArgs], 1109) -> Tuple: 1110 """ 1111 Returns an tuple. 1112 1113 Examples: 1114 >>> tuple_(1, 'x').sql() 1115 '(1, x)' 1116 1117 Args: 1118 expressions: the expressions to add to the tuple. 1119 copy: whether to copy the argument expressions. 1120 dialect: the source dialect. 1121 kwargs: the kwargs used to instantiate the function of interest. 1122 1123 Returns: 1124 A tuple expression. 1125 """ 1126 return Tuple( 1127 expressions=[ 1128 maybe_parse(expression, copy=copy, dialect=dialect, **kwargs) 1129 for expression in expressions 1130 ] 1131 )
Returns an tuple.
Examples:
>>> tuple_(1, 'x').sql() '(1, x)'
Arguments:
- expressions: the expressions to add to the tuple.
- copy: whether to copy the argument expressions.
- dialect: the source dialect.
- kwargs: the kwargs used to instantiate the function of interest.
Returns:
A tuple expression.
1134def true() -> Boolean: 1135 """ 1136 Returns a true Boolean expression. 1137 """ 1138 return Boolean(this=True)
Returns a true Boolean expression.
1141def false() -> Boolean: 1142 """ 1143 Returns a false Boolean expression. 1144 """ 1145 return Boolean(this=False)
Returns a false Boolean expression.
Returns a Null expression.
1155def apply_index_offset( 1156 this: Expr, 1157 expressions: list[E], 1158 offset: int, 1159 dialect: DialectType = None, 1160) -> list[E]: 1161 if not offset or len(expressions) != 1: 1162 return expressions 1163 1164 expression = expressions[0] 1165 1166 from sqlglot.optimizer.annotate_types import annotate_types 1167 from sqlglot.optimizer.simplify import simplify 1168 1169 if not this.type: 1170 annotate_types(this, dialect=dialect) 1171 1172 if t.cast(DataType, this.type).this not in ( 1173 DType.UNKNOWN, 1174 DType.ARRAY, 1175 ): 1176 return expressions 1177 1178 if not expression.type: 1179 annotate_types(expression, dialect=dialect) 1180 1181 if t.cast(DataType, expression.type).this in DataType.INTEGER_TYPES: 1182 logger.info("Applying array index offset (%s)", offset) 1183 expression = simplify(expression + offset) 1184 return [expression] 1185 1186 return expressions