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