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 FROM sources (tables, views, table functions...) 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 call = node.this 849 if isinstance(call, Func) and not isinstance(call, Anonymous): 850 return node 851 852 original = normalize_table_name(node, dialect=dialect) 853 new_name = mapping.get(original) 854 855 if new_name: 856 table = to_table( 857 new_name, 858 **{k: v for k, v in node.args.items() if k not in TABLE_PARTS}, 859 dialect=dialect, 860 ) 861 if isinstance(call, Anonymous): 862 call.set("this", table.this) 863 table.set("this", call) 864 table.add_comments([original]) 865 return table 866 return node 867 868 return expression.transform(_replace_tables, copy=copy) # type: ignore 869 870 871OPERATORS = (AtTimeZone, Between, Binary, BitwiseNot, In, Neg, Not) 872 873 874def _is_operand(placeholder: Placeholder) -> bool: 875 parent = placeholder.parent 876 if isinstance(parent, (Bracket, In)): 877 return placeholder.arg_key == "this" 878 return isinstance(parent, OPERATORS) 879 880 881def _takes_query(placeholder: Placeholder) -> bool: 882 parent = placeholder.parent 883 if isinstance(parent, In): 884 return placeholder.arg_key == "expressions" and len(parent.expressions) == 1 885 if isinstance(parent, Func): 886 return len(list(parent.iter_expressions())) == 1 887 if isinstance(parent, Table): 888 return isinstance(parent.parent, (Create, Subquery)) 889 return not parent or isinstance(parent, (CTE, Paren, SetOperation)) 890 891 892def _replace_placeholder(placeholder: Placeholder, expression: Expr) -> Expr: 893 if ( 894 isinstance(expression, Query) 895 and not isinstance(expression, Subquery) 896 and not _takes_query(placeholder) 897 ): 898 return expression.subquery(copy=False) 899 if ( 900 _is_operand(placeholder) 901 and isinstance(expression, OPERATORS) 902 and not isinstance(expression, Dot) 903 ): 904 return Paren(this=expression) 905 return expression 906 907 908def replace_placeholders(expression: Expr, *args: object, **kwargs: t.Any) -> Expr: 909 """Replace placeholders in an expression. 910 911 Args: 912 expression: expression node to be transformed and replaced. 913 args: positional names that will substitute unnamed placeholders in the given order. 914 kwargs: keyword arguments that will substitute named placeholders. 915 916 Examples: 917 >>> from sqlglot import exp, parse_one 918 >>> replace_placeholders( 919 ... parse_one("select * from :tbl where ? = ?"), 920 ... exp.to_identifier("str_col"), "b", tbl=exp.to_identifier("foo") 921 ... ).sql() 922 "SELECT * FROM foo WHERE str_col = 'b'" 923 924 Returns: 925 The mapped expression. 926 """ 927 928 def _replace_placeholders(node: Expr, args: Iterator[object], **kwargs: object) -> Expr: 929 if isinstance(node, Placeholder): 930 if node.this: 931 new_name = kwargs.get(node.name) 932 if new_name is not None: 933 return _replace_placeholder(node, convert(new_name)) 934 else: 935 try: 936 return _replace_placeholder(node, convert(next(args))) 937 except StopIteration: 938 pass 939 return node 940 941 return expression.transform(_replace_placeholders, iter(args), **kwargs) 942 943 944def expand( 945 expression: Expr, 946 sources: dict[str, Query | t.Callable[[], Query]], 947 dialect: DialectType = None, 948 copy: bool = True, 949) -> Expr: 950 """Transforms an expression by expanding all referenced sources into subqueries. 951 952 Examples: 953 >>> from sqlglot import parse_one 954 >>> expand(parse_one("select * from x AS z"), {"x": parse_one("select * from y")}).sql() 955 'SELECT * FROM (SELECT * FROM y) AS z /* source: x */' 956 957 >>> expand(parse_one("select * from x AS z"), {"x": parse_one("select * from y"), "y": parse_one("select * from z")}).sql() 958 'SELECT * FROM (SELECT * FROM (SELECT * FROM z) AS y /* source: y */) AS z /* source: x */' 959 960 Args: 961 expression: The expression to expand. 962 sources: A dict of name to query or a callable that provides a query on demand. 963 dialect: The dialect of the sources dict or the callable. 964 copy: Whether to copy the expression during transformation. Defaults to True. 965 966 Returns: 967 The transformed expression. 968 """ 969 normalized_sources = {normalize_table_name(k, dialect=dialect): v for k, v in sources.items()} 970 971 def _expand(node: Expr): 972 if isinstance(node, Table): 973 name = normalize_table_name(node, dialect=dialect) 974 source = normalized_sources.get(name) 975 976 if source: 977 # Create a subquery with the same alias (or table name if no alias) 978 parsed_source = source() if callable(source) else source 979 subquery = parsed_source.subquery(node.alias or name) 980 subquery.comments = [f"source: {name}"] 981 982 # Continue expanding within the subquery 983 return subquery.transform(_expand, copy=False) 984 985 return node 986 987 return expression.transform(_expand, copy=copy) 988 989 990def func( 991 name: str, *args: t.Any, copy: bool = True, dialect: DialectType = None, **kwargs: t.Any 992) -> Func: 993 """ 994 Returns a Func expression. 995 996 Examples: 997 >>> func("abs", 5).sql() 998 'ABS(5)' 999 1000 >>> func("cast", this=5, to=DataType.build("DOUBLE")).sql() 1001 'CAST(5 AS DOUBLE)' 1002 1003 Args: 1004 name: the name of the function to build. 1005 args: the args used to instantiate the function of interest. 1006 copy: whether to copy the argument expressions. 1007 dialect: the source dialect. 1008 kwargs: the kwargs used to instantiate the function of interest. 1009 1010 Note: 1011 The arguments `args` and `kwargs` are mutually exclusive. 1012 1013 Returns: 1014 An instance of the function of interest, or an anonymous function, if `name` doesn't 1015 correspond to an existing `sqlglot.expressions.Func` class. 1016 """ 1017 if args and kwargs: 1018 raise ValueError("Can't use both args and kwargs to instantiate a function.") 1019 1020 from sqlglot.dialects.dialect import Dialect 1021 1022 dialect = Dialect.get_or_raise(dialect) 1023 1024 converted: list[Expr] = [maybe_parse(arg, dialect=dialect, copy=copy) for arg in args] 1025 kwargs = {key: maybe_parse(value, dialect=dialect, copy=copy) for key, value in kwargs.items()} 1026 1027 constructor = dialect.parser_class.FUNCTIONS.get(name.upper()) 1028 if constructor: 1029 if converted: 1030 try: 1031 function = constructor(converted) 1032 except TypeError: 1033 function = constructor(converted, dialect=dialect) 1034 elif constructor.__name__ == "from_arg_list": 1035 function = constructor.__self__(**kwargs) # type: ignore 1036 else: 1037 from sqlglot.expressions import FUNCTION_BY_NAME as _FUNCTION_BY_NAME 1038 1039 constructor = _FUNCTION_BY_NAME.get(name.upper()) 1040 if constructor: 1041 function = constructor(**kwargs) 1042 else: 1043 raise ValueError( 1044 f"Unable to convert '{name}' into a Func. Either manually construct " 1045 "the Func expression of interest or parse the function call." 1046 ) 1047 else: 1048 kwargs = kwargs or {"expressions": converted} 1049 function = Anonymous(this=name, **kwargs) 1050 1051 for error_message in function.error_messages(converted): 1052 raise ValueError(error_message) 1053 1054 return function 1055 1056 1057def case( 1058 expression: ExpOrStr | None = None, 1059 copy: bool = True, 1060 **opts: Unpack[ParserArgs], 1061) -> Case: 1062 """ 1063 Initialize a CASE statement. 1064 1065 Example: 1066 case().when("a = 1", "foo").else_("bar") 1067 1068 Args: 1069 expression: Optionally, the input expression (not all dialects support this) 1070 copy: whether to copy the argument expressions. 1071 **opts: Extra keyword arguments for parsing `expression` 1072 """ 1073 if expression is not None: 1074 this = maybe_parse(expression, copy=copy, **opts) 1075 else: 1076 this = None 1077 return Case(this=this, ifs=[]) 1078 1079 1080def array( 1081 *expressions: ExpOrStr, 1082 copy: bool = True, 1083 dialect: DialectType = None, 1084 **kwargs: Unpack[ParserNoDialectArgs], 1085) -> Array: 1086 """ 1087 Returns an array. 1088 1089 Examples: 1090 >>> array(1, 'x').sql() 1091 'ARRAY(1, x)' 1092 1093 Args: 1094 expressions: the expressions to add to the array. 1095 copy: whether to copy the argument expressions. 1096 dialect: the source dialect. 1097 kwargs: the kwargs used to instantiate the function of interest. 1098 1099 Returns: 1100 An array expression. 1101 """ 1102 return Array( 1103 expressions=[ 1104 maybe_parse(expression, copy=copy, dialect=dialect, **kwargs) 1105 for expression in expressions 1106 ] 1107 ) 1108 1109 1110def tuple_( 1111 *expressions: ExpOrStr, 1112 copy: bool = True, 1113 dialect: DialectType = None, 1114 **kwargs: Unpack[ParserNoDialectArgs], 1115) -> Tuple: 1116 """ 1117 Returns an tuple. 1118 1119 Examples: 1120 >>> tuple_(1, 'x').sql() 1121 '(1, x)' 1122 1123 Args: 1124 expressions: the expressions to add to the tuple. 1125 copy: whether to copy the argument expressions. 1126 dialect: the source dialect. 1127 kwargs: the kwargs used to instantiate the function of interest. 1128 1129 Returns: 1130 A tuple expression. 1131 """ 1132 return Tuple( 1133 expressions=[ 1134 maybe_parse(expression, copy=copy, dialect=dialect, **kwargs) 1135 for expression in expressions 1136 ] 1137 ) 1138 1139 1140def true() -> Boolean: 1141 """ 1142 Returns a true Boolean expression. 1143 """ 1144 return Boolean(this=True) 1145 1146 1147def false() -> Boolean: 1148 """ 1149 Returns a false Boolean expression. 1150 """ 1151 return Boolean(this=False) 1152 1153 1154def null() -> Null: 1155 """ 1156 Returns a Null expression. 1157 """ 1158 return Null() 1159 1160 1161def apply_index_offset( 1162 this: Expr, 1163 expressions: list[E], 1164 offset: int, 1165 dialect: DialectType = None, 1166) -> list[E]: 1167 if not offset or len(expressions) != 1: 1168 return expressions 1169 1170 expression = expressions[0] 1171 1172 from sqlglot.optimizer.annotate_types import annotate_types 1173 from sqlglot.optimizer.simplify import simplify 1174 1175 if not this.type: 1176 annotate_types(this, dialect=dialect) 1177 1178 if t.cast(DataType, this.type).this not in ( 1179 DType.UNKNOWN, 1180 DType.ARRAY, 1181 ): 1182 return expressions 1183 1184 if not expression.type: 1185 annotate_types(expression, dialect=dialect) 1186 1187 if t.cast(DataType, expression.type).this in DataType.INTEGER_TYPES: 1188 logger.info("Applying array index offset (%s)", offset) 1189 expression = simplify(expression + offset) 1190 return [expression] 1191 1192 return expressions 1193 1194 1195NONNULL_CONSTANTS = ( 1196 Literal, 1197 Boolean, 1198) 1199 1200CONSTANTS = ( 1201 Literal, 1202 Boolean, 1203 Null, 1204)
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 FROM sources (tables, views, table functions...) 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 call = node.this 850 if isinstance(call, Func) and not isinstance(call, Anonymous): 851 return node 852 853 original = normalize_table_name(node, dialect=dialect) 854 new_name = mapping.get(original) 855 856 if new_name: 857 table = to_table( 858 new_name, 859 **{k: v for k, v in node.args.items() if k not in TABLE_PARTS}, 860 dialect=dialect, 861 ) 862 if isinstance(call, Anonymous): 863 call.set("this", table.this) 864 table.set("this", call) 865 table.add_comments([original]) 866 return table 867 return node 868 869 return expression.transform(_replace_tables, copy=copy) # type: ignore
Replace all FROM sources (tables, views, table functions...) 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.
909def replace_placeholders(expression: Expr, *args: object, **kwargs: t.Any) -> Expr: 910 """Replace placeholders in an expression. 911 912 Args: 913 expression: expression node to be transformed and replaced. 914 args: positional names that will substitute unnamed placeholders in the given order. 915 kwargs: keyword arguments that will substitute named placeholders. 916 917 Examples: 918 >>> from sqlglot import exp, parse_one 919 >>> replace_placeholders( 920 ... parse_one("select * from :tbl where ? = ?"), 921 ... exp.to_identifier("str_col"), "b", tbl=exp.to_identifier("foo") 922 ... ).sql() 923 "SELECT * FROM foo WHERE str_col = 'b'" 924 925 Returns: 926 The mapped expression. 927 """ 928 929 def _replace_placeholders(node: Expr, args: Iterator[object], **kwargs: object) -> Expr: 930 if isinstance(node, Placeholder): 931 if node.this: 932 new_name = kwargs.get(node.name) 933 if new_name is not None: 934 return _replace_placeholder(node, convert(new_name)) 935 else: 936 try: 937 return _replace_placeholder(node, convert(next(args))) 938 except StopIteration: 939 pass 940 return node 941 942 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.
945def expand( 946 expression: Expr, 947 sources: dict[str, Query | t.Callable[[], Query]], 948 dialect: DialectType = None, 949 copy: bool = True, 950) -> Expr: 951 """Transforms an expression by expanding all referenced sources into subqueries. 952 953 Examples: 954 >>> from sqlglot import parse_one 955 >>> expand(parse_one("select * from x AS z"), {"x": parse_one("select * from y")}).sql() 956 'SELECT * FROM (SELECT * FROM y) AS z /* source: x */' 957 958 >>> expand(parse_one("select * from x AS z"), {"x": parse_one("select * from y"), "y": parse_one("select * from z")}).sql() 959 'SELECT * FROM (SELECT * FROM (SELECT * FROM z) AS y /* source: y */) AS z /* source: x */' 960 961 Args: 962 expression: The expression to expand. 963 sources: A dict of name to query or a callable that provides a query on demand. 964 dialect: The dialect of the sources dict or the callable. 965 copy: Whether to copy the expression during transformation. Defaults to True. 966 967 Returns: 968 The transformed expression. 969 """ 970 normalized_sources = {normalize_table_name(k, dialect=dialect): v for k, v in sources.items()} 971 972 def _expand(node: Expr): 973 if isinstance(node, Table): 974 name = normalize_table_name(node, dialect=dialect) 975 source = normalized_sources.get(name) 976 977 if source: 978 # Create a subquery with the same alias (or table name if no alias) 979 parsed_source = source() if callable(source) else source 980 subquery = parsed_source.subquery(node.alias or name) 981 subquery.comments = [f"source: {name}"] 982 983 # Continue expanding within the subquery 984 return subquery.transform(_expand, copy=False) 985 986 return node 987 988 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.
991def func( 992 name: str, *args: t.Any, copy: bool = True, dialect: DialectType = None, **kwargs: t.Any 993) -> Func: 994 """ 995 Returns a Func expression. 996 997 Examples: 998 >>> func("abs", 5).sql() 999 'ABS(5)' 1000 1001 >>> func("cast", this=5, to=DataType.build("DOUBLE")).sql() 1002 'CAST(5 AS DOUBLE)' 1003 1004 Args: 1005 name: the name of the function to build. 1006 args: the args used to instantiate the function of interest. 1007 copy: whether to copy the argument expressions. 1008 dialect: the source dialect. 1009 kwargs: the kwargs used to instantiate the function of interest. 1010 1011 Note: 1012 The arguments `args` and `kwargs` are mutually exclusive. 1013 1014 Returns: 1015 An instance of the function of interest, or an anonymous function, if `name` doesn't 1016 correspond to an existing `sqlglot.expressions.Func` class. 1017 """ 1018 if args and kwargs: 1019 raise ValueError("Can't use both args and kwargs to instantiate a function.") 1020 1021 from sqlglot.dialects.dialect import Dialect 1022 1023 dialect = Dialect.get_or_raise(dialect) 1024 1025 converted: list[Expr] = [maybe_parse(arg, dialect=dialect, copy=copy) for arg in args] 1026 kwargs = {key: maybe_parse(value, dialect=dialect, copy=copy) for key, value in kwargs.items()} 1027 1028 constructor = dialect.parser_class.FUNCTIONS.get(name.upper()) 1029 if constructor: 1030 if converted: 1031 try: 1032 function = constructor(converted) 1033 except TypeError: 1034 function = constructor(converted, dialect=dialect) 1035 elif constructor.__name__ == "from_arg_list": 1036 function = constructor.__self__(**kwargs) # type: ignore 1037 else: 1038 from sqlglot.expressions import FUNCTION_BY_NAME as _FUNCTION_BY_NAME 1039 1040 constructor = _FUNCTION_BY_NAME.get(name.upper()) 1041 if constructor: 1042 function = constructor(**kwargs) 1043 else: 1044 raise ValueError( 1045 f"Unable to convert '{name}' into a Func. Either manually construct " 1046 "the Func expression of interest or parse the function call." 1047 ) 1048 else: 1049 kwargs = kwargs or {"expressions": converted} 1050 function = Anonymous(this=name, **kwargs) 1051 1052 for error_message in function.error_messages(converted): 1053 raise ValueError(error_message) 1054 1055 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.
1058def case( 1059 expression: ExpOrStr | None = None, 1060 copy: bool = True, 1061 **opts: Unpack[ParserArgs], 1062) -> Case: 1063 """ 1064 Initialize a CASE statement. 1065 1066 Example: 1067 case().when("a = 1", "foo").else_("bar") 1068 1069 Args: 1070 expression: Optionally, the input expression (not all dialects support this) 1071 copy: whether to copy the argument expressions. 1072 **opts: Extra keyword arguments for parsing `expression` 1073 """ 1074 if expression is not None: 1075 this = maybe_parse(expression, copy=copy, **opts) 1076 else: 1077 this = None 1078 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
1081def array( 1082 *expressions: ExpOrStr, 1083 copy: bool = True, 1084 dialect: DialectType = None, 1085 **kwargs: Unpack[ParserNoDialectArgs], 1086) -> Array: 1087 """ 1088 Returns an array. 1089 1090 Examples: 1091 >>> array(1, 'x').sql() 1092 'ARRAY(1, x)' 1093 1094 Args: 1095 expressions: the expressions to add to the array. 1096 copy: whether to copy the argument expressions. 1097 dialect: the source dialect. 1098 kwargs: the kwargs used to instantiate the function of interest. 1099 1100 Returns: 1101 An array expression. 1102 """ 1103 return Array( 1104 expressions=[ 1105 maybe_parse(expression, copy=copy, dialect=dialect, **kwargs) 1106 for expression in expressions 1107 ] 1108 )
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.
1111def tuple_( 1112 *expressions: ExpOrStr, 1113 copy: bool = True, 1114 dialect: DialectType = None, 1115 **kwargs: Unpack[ParserNoDialectArgs], 1116) -> Tuple: 1117 """ 1118 Returns an tuple. 1119 1120 Examples: 1121 >>> tuple_(1, 'x').sql() 1122 '(1, x)' 1123 1124 Args: 1125 expressions: the expressions to add to the tuple. 1126 copy: whether to copy the argument expressions. 1127 dialect: the source dialect. 1128 kwargs: the kwargs used to instantiate the function of interest. 1129 1130 Returns: 1131 A tuple expression. 1132 """ 1133 return Tuple( 1134 expressions=[ 1135 maybe_parse(expression, copy=copy, dialect=dialect, **kwargs) 1136 for expression in expressions 1137 ] 1138 )
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.
1141def true() -> Boolean: 1142 """ 1143 Returns a true Boolean expression. 1144 """ 1145 return Boolean(this=True)
Returns a true Boolean expression.
1148def false() -> Boolean: 1149 """ 1150 Returns a false Boolean expression. 1151 """ 1152 return Boolean(this=False)
Returns a false Boolean expression.
Returns a Null expression.
1162def apply_index_offset( 1163 this: Expr, 1164 expressions: list[E], 1165 offset: int, 1166 dialect: DialectType = None, 1167) -> list[E]: 1168 if not offset or len(expressions) != 1: 1169 return expressions 1170 1171 expression = expressions[0] 1172 1173 from sqlglot.optimizer.annotate_types import annotate_types 1174 from sqlglot.optimizer.simplify import simplify 1175 1176 if not this.type: 1177 annotate_types(this, dialect=dialect) 1178 1179 if t.cast(DataType, this.type).this not in ( 1180 DType.UNKNOWN, 1181 DType.ARRAY, 1182 ): 1183 return expressions 1184 1185 if not expression.type: 1186 annotate_types(expression, dialect=dialect) 1187 1188 if t.cast(DataType, expression.type).this in DataType.INTEGER_TYPES: 1189 logger.info("Applying array index offset (%s)", offset) 1190 expression = simplify(expression + offset) 1191 return [expression] 1192 1193 return expressions