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: DType = expr.to.this 499 new_cast_type: DType = data_type.this 500 types_are_equivalent = type_mapping.get( 501 existing_cast_type, existing_cast_type.value 502 ) == type_mapping.get(new_cast_type, new_cast_type.value) 503 504 if expr.is_type(data_type) or types_are_equivalent: 505 return expr 506 507 expr = Cast(this=expr, to=data_type) 508 expr.type = data_type 509 510 return expr 511 512 513def table_( 514 table: Identifier | str, 515 db: Identifier | str | None = None, 516 catalog: Identifier | str | None = None, 517 quoted: bool | None = None, 518 alias: Identifier | str | None = None, 519) -> Table: 520 """Build a Table. 521 522 Args: 523 table: Table name. 524 db: Database name. 525 catalog: Catalog name. 526 quote: Whether to force quotes on the table's identifiers. 527 alias: Table's alias. 528 529 Returns: 530 The new Table instance. 531 """ 532 return Table( 533 this=to_identifier(table, quoted=quoted) if table else None, 534 db=to_identifier(db, quoted=quoted) if db else None, 535 catalog=to_identifier(catalog, quoted=quoted) if catalog else None, 536 alias=TableAlias(this=to_identifier(alias)) if alias else None, 537 ) 538 539 540def values( 541 values: Iterable[tuple[object, ...] | Tuple], 542 alias: str | None = None, 543 columns: Iterable[str] | dict[str, DataType] | None = None, 544) -> Values: 545 """Build VALUES statement. 546 547 Example: 548 >>> values([(1, '2')]).sql() 549 "VALUES (1, '2')" 550 551 Args: 552 values: values statements that will be converted to SQL 553 alias: optional alias 554 columns: Optional list of ordered column names or ordered dictionary of column names to types. 555 If either are provided then an alias is also required. 556 557 Returns: 558 Values: the Values expression object 559 """ 560 if columns and not alias: 561 raise ValueError("Alias is required when providing columns") 562 563 return Values( 564 expressions=[convert(tup) for tup in values], 565 alias=( 566 TableAlias(this=to_identifier(alias), columns=[to_identifier(x) for x in columns]) 567 if columns 568 else (TableAlias(this=to_identifier(alias)) if alias else None) 569 ), 570 ) 571 572 573def var(name: ExpOrStr | None) -> Var: 574 """Build a SQL variable. 575 576 Example: 577 >>> repr(var('x')) 578 'Var(this=x)' 579 580 >>> repr(var(column('x', table='y'))) 581 'Var(this=x)' 582 583 Args: 584 name: The name of the var or an expression who's name will become the var. 585 586 Returns: 587 The new variable node. 588 """ 589 if not name: 590 raise ValueError("Cannot convert empty name into var.") 591 592 if isinstance(name, Expr): 593 name = name.name 594 return Var(this=name) 595 596 597def rename_table( 598 old_name: str | Table, 599 new_name: str | Table, 600 dialect: DialectType = None, 601) -> Alter: 602 """Build ALTER TABLE... RENAME... expression 603 604 Args: 605 old_name: The old name of the table 606 new_name: The new name of the table 607 dialect: The dialect to parse the table. 608 609 Returns: 610 Alter table expression 611 """ 612 old_table = to_table(old_name, dialect=dialect) 613 new_table = to_table(new_name, dialect=dialect) 614 return Alter( 615 this=old_table, 616 kind="TABLE", 617 actions=[ 618 AlterRename(this=new_table), 619 ], 620 ) 621 622 623def rename_column( 624 table_name: str | Table, 625 old_column_name: str | Column, 626 new_column_name: str | Column, 627 exists: bool | None = None, 628 dialect: DialectType = None, 629) -> Alter: 630 """Build ALTER TABLE... RENAME COLUMN... expression 631 632 Args: 633 table_name: Name of the table 634 old_column: The old name of the column 635 new_column: The new name of the column 636 exists: Whether to add the `IF EXISTS` clause 637 dialect: The dialect to parse the table/column. 638 639 Returns: 640 Alter table expression 641 """ 642 table = to_table(table_name, dialect=dialect) 643 old_column = to_column(old_column_name, dialect=dialect) 644 new_column = to_column(new_column_name, dialect=dialect) 645 return Alter( 646 this=table, 647 kind="TABLE", 648 actions=[ 649 RenameColumn(this=old_column, to=new_column, exists=exists), 650 ], 651 ) 652 653 654def replace_children( 655 expression: Expr, 656 fun: t.Callable[Concatenate[Expr, P], object], 657 *args: P.args, 658 **kwargs: P.kwargs, 659) -> None: 660 """ 661 Replace children of an expression with the result of a lambda fun(child) -> exp. 662 """ 663 for k, v in tuple(expression.args.items()): 664 is_list_arg = type(v) is list 665 666 child_nodes = v if is_list_arg else [v] 667 new_child_nodes = [] 668 669 for cn in child_nodes: 670 if isinstance(cn, Expr): 671 for child_node in ensure_collection(fun(cn, *args, **kwargs)): 672 new_child_nodes.append(child_node) 673 else: 674 new_child_nodes.append(cn) 675 676 if is_list_arg: 677 expression.set(k, new_child_nodes) 678 else: 679 expression.set(k, seq_get(new_child_nodes, 0)) 680 681 682def replace_tree( 683 expression: Expr, 684 fun: t.Callable[[Expr], Expr], 685 prune: t.Callable[[Expr], bool] | None = None, 686) -> Expr: 687 """ 688 Replace an entire tree with the result of function calls on each node. 689 690 This will be traversed in reverse dfs, so leaves first. 691 If new nodes are created as a result of function calls, they will also be traversed. 692 """ 693 stack = list(expression.dfs(prune=prune)) 694 695 while stack: 696 node = stack.pop() 697 new_node = fun(node) 698 699 if new_node is not node: 700 node.replace(new_node) 701 702 if isinstance(new_node, Expr): 703 stack.append(new_node) 704 705 return new_node 706 707 708def find_tables(expression: Expr) -> set[Table]: 709 """ 710 Find all tables referenced in a query. 711 712 Args: 713 expressions: The query to find the tables in. 714 715 Returns: 716 A set of all the tables. 717 """ 718 from sqlglot.optimizer.scope import traverse_scope 719 720 return { 721 table 722 for scope in traverse_scope(expression) 723 for table in scope.tables 724 if isinstance(table, Table) and table.name and table.name not in scope.cte_sources 725 } 726 727 728def column_table_names(expression: Expr, exclude: str = "") -> set[str]: 729 """ 730 Return all table names referenced through columns in an expression. 731 732 Example: 733 >>> import sqlglot 734 >>> sorted(column_table_names(sqlglot.parse_one("a.b AND c.d AND c.e"))) 735 ['a', 'c'] 736 737 Args: 738 expression: expression to find table names. 739 exclude: a table name to exclude 740 741 Returns: 742 A list of unique names. 743 """ 744 return { 745 table 746 for table in (column.table for column in expression.find_all(Column)) 747 if table and table != exclude 748 } 749 750 751def table_name(table: Table | str, dialect: DialectType = None, identify: bool = False) -> str: 752 """Get the full name of a table as a string. 753 754 Args: 755 table: Table expression node or string. 756 dialect: The dialect to generate the table name for. 757 identify: Determines when an identifier should be quoted. Possible values are: 758 False (default): Never quote, except in cases where it's mandatory by the dialect. 759 True: Always quote. 760 761 Examples: 762 >>> from sqlglot import exp, parse_one 763 >>> table_name(parse_one("select * from a.b.c").find(exp.Table)) 764 'a.b.c' 765 766 Returns: 767 The table name. 768 """ 769 770 expr = maybe_parse(table, into=Table, dialect=dialect) 771 772 if not expr: 773 raise ValueError(f"Cannot parse {table}") 774 775 return ".".join( 776 ( 777 part.sql(dialect=dialect, identify=True, copy=False, comments=False) 778 if identify or not SAFE_IDENTIFIER_RE.match(part.name) 779 else part.name 780 ) 781 for part in expr.parts 782 ) 783 784 785def normalize_table_name(table: str | Table, dialect: DialectType = None, copy: bool = True) -> str: 786 """Returns a case normalized table name without quotes. 787 788 Args: 789 table: the table to normalize 790 dialect: the dialect to use for normalization rules 791 copy: whether to copy the expression. 792 793 Examples: 794 >>> normalize_table_name("`A-B`.c", dialect="bigquery") 795 'A-B.c' 796 """ 797 from sqlglot.optimizer.normalize_identifiers import normalize_identifiers 798 799 return ".".join( 800 p.name 801 for p in normalize_identifiers( 802 to_table(table, dialect=dialect, copy=copy), dialect=dialect 803 ).parts 804 ) 805 806 807def replace_tables( 808 expression: E, mapping: dict[str, str], dialect: DialectType = None, copy: bool = True 809) -> E: 810 """Replace all tables in expression according to the mapping. 811 812 Args: 813 expression: expression node to be transformed and replaced. 814 mapping: mapping of table names. 815 dialect: the dialect of the mapping table 816 copy: whether to copy the expression. 817 818 Examples: 819 >>> from sqlglot import exp, parse_one 820 >>> replace_tables(parse_one("select * from a.b"), {"a.b": "c"}).sql() 821 'SELECT * FROM c /* a.b */' 822 823 Returns: 824 The mapped expression. 825 """ 826 827 mapping = {normalize_table_name(k, dialect=dialect): v for k, v in mapping.items()} 828 829 def _replace_tables(node: Expr) -> Expr: 830 if isinstance(node, Table) and node.meta_get("replace") is not False: 831 original = normalize_table_name(node, dialect=dialect) 832 new_name = mapping.get(original) 833 834 if new_name: 835 table = to_table( 836 new_name, 837 **{k: v for k, v in node.args.items() if k not in TABLE_PARTS}, 838 dialect=dialect, 839 ) 840 table.add_comments([original]) 841 return table 842 return node 843 844 return expression.transform(_replace_tables, copy=copy) # type: ignore 845 846 847def replace_placeholders(expression: Expr, *args: object, **kwargs: t.Any) -> Expr: 848 """Replace placeholders in an expression. 849 850 Args: 851 expression: expression node to be transformed and replaced. 852 args: positional names that will substitute unnamed placeholders in the given order. 853 kwargs: keyword arguments that will substitute named placeholders. 854 855 Examples: 856 >>> from sqlglot import exp, parse_one 857 >>> replace_placeholders( 858 ... parse_one("select * from :tbl where ? = ?"), 859 ... exp.to_identifier("str_col"), "b", tbl=exp.to_identifier("foo") 860 ... ).sql() 861 "SELECT * FROM foo WHERE str_col = 'b'" 862 863 Returns: 864 The mapped expression. 865 """ 866 867 def _replace_placeholders(node: Expr, args: Iterator[object], **kwargs: object) -> Expr: 868 if isinstance(node, Placeholder): 869 if node.this: 870 new_name = kwargs.get(node.this) 871 if new_name is not None: 872 return convert(new_name) 873 else: 874 try: 875 return convert(next(args)) 876 except StopIteration: 877 pass 878 return node 879 880 return expression.transform(_replace_placeholders, iter(args), **kwargs) 881 882 883def expand( 884 expression: Expr, 885 sources: dict[str, Query | t.Callable[[], Query]], 886 dialect: DialectType = None, 887 copy: bool = True, 888) -> Expr: 889 """Transforms an expression by expanding all referenced sources into subqueries. 890 891 Examples: 892 >>> from sqlglot import parse_one 893 >>> expand(parse_one("select * from x AS z"), {"x": parse_one("select * from y")}).sql() 894 'SELECT * FROM (SELECT * FROM y) AS z /* source: x */' 895 896 >>> expand(parse_one("select * from x AS z"), {"x": parse_one("select * from y"), "y": parse_one("select * from z")}).sql() 897 'SELECT * FROM (SELECT * FROM (SELECT * FROM z) AS y /* source: y */) AS z /* source: x */' 898 899 Args: 900 expression: The expression to expand. 901 sources: A dict of name to query or a callable that provides a query on demand. 902 dialect: The dialect of the sources dict or the callable. 903 copy: Whether to copy the expression during transformation. Defaults to True. 904 905 Returns: 906 The transformed expression. 907 """ 908 normalized_sources = {normalize_table_name(k, dialect=dialect): v for k, v in sources.items()} 909 910 def _expand(node: Expr): 911 if isinstance(node, Table): 912 name = normalize_table_name(node, dialect=dialect) 913 source = normalized_sources.get(name) 914 915 if source: 916 # Create a subquery with the same alias (or table name if no alias) 917 parsed_source = source() if callable(source) else source 918 subquery = parsed_source.subquery(node.alias or name) 919 subquery.comments = [f"source: {name}"] 920 921 # Continue expanding within the subquery 922 return subquery.transform(_expand, copy=False) 923 924 return node 925 926 return expression.transform(_expand, copy=copy) 927 928 929def func( 930 name: str, *args: t.Any, copy: bool = True, dialect: DialectType = None, **kwargs: t.Any 931) -> Func: 932 """ 933 Returns a Func expression. 934 935 Examples: 936 >>> func("abs", 5).sql() 937 'ABS(5)' 938 939 >>> func("cast", this=5, to=DataType.build("DOUBLE")).sql() 940 'CAST(5 AS DOUBLE)' 941 942 Args: 943 name: the name of the function to build. 944 args: the args used to instantiate the function of interest. 945 copy: whether to copy the argument expressions. 946 dialect: the source dialect. 947 kwargs: the kwargs used to instantiate the function of interest. 948 949 Note: 950 The arguments `args` and `kwargs` are mutually exclusive. 951 952 Returns: 953 An instance of the function of interest, or an anonymous function, if `name` doesn't 954 correspond to an existing `sqlglot.expressions.Func` class. 955 """ 956 if args and kwargs: 957 raise ValueError("Can't use both args and kwargs to instantiate a function.") 958 959 from sqlglot.dialects.dialect import Dialect 960 961 dialect = Dialect.get_or_raise(dialect) 962 963 converted: list[Expr] = [maybe_parse(arg, dialect=dialect, copy=copy) for arg in args] 964 kwargs = {key: maybe_parse(value, dialect=dialect, copy=copy) for key, value in kwargs.items()} 965 966 constructor = dialect.parser_class.FUNCTIONS.get(name.upper()) 967 if constructor: 968 if converted: 969 try: 970 function = constructor(converted) 971 except TypeError: 972 function = constructor(converted, dialect=dialect) 973 elif constructor.__name__ == "from_arg_list": 974 function = constructor.__self__(**kwargs) # type: ignore 975 else: 976 from sqlglot.expressions import FUNCTION_BY_NAME as _FUNCTION_BY_NAME 977 978 constructor = _FUNCTION_BY_NAME.get(name.upper()) 979 if constructor: 980 function = constructor(**kwargs) 981 else: 982 raise ValueError( 983 f"Unable to convert '{name}' into a Func. Either manually construct " 984 "the Func expression of interest or parse the function call." 985 ) 986 else: 987 kwargs = kwargs or {"expressions": converted} 988 function = Anonymous(this=name, **kwargs) 989 990 for error_message in function.error_messages(converted): 991 raise ValueError(error_message) 992 993 return function 994 995 996def case( 997 expression: ExpOrStr | None = None, 998 copy: bool = True, 999 **opts: Unpack[ParserArgs], 1000) -> Case: 1001 """ 1002 Initialize a CASE statement. 1003 1004 Example: 1005 case().when("a = 1", "foo").else_("bar") 1006 1007 Args: 1008 expression: Optionally, the input expression (not all dialects support this) 1009 copy: whether to copy the argument expressions. 1010 **opts: Extra keyword arguments for parsing `expression` 1011 """ 1012 if expression is not None: 1013 this = maybe_parse(expression, copy=copy, **opts) 1014 else: 1015 this = None 1016 return Case(this=this, ifs=[]) 1017 1018 1019def array( 1020 *expressions: ExpOrStr, 1021 copy: bool = True, 1022 dialect: DialectType = None, 1023 **kwargs: Unpack[ParserNoDialectArgs], 1024) -> Array: 1025 """ 1026 Returns an array. 1027 1028 Examples: 1029 >>> array(1, 'x').sql() 1030 'ARRAY(1, x)' 1031 1032 Args: 1033 expressions: the expressions to add to the array. 1034 copy: whether to copy the argument expressions. 1035 dialect: the source dialect. 1036 kwargs: the kwargs used to instantiate the function of interest. 1037 1038 Returns: 1039 An array expression. 1040 """ 1041 return Array( 1042 expressions=[ 1043 maybe_parse(expression, copy=copy, dialect=dialect, **kwargs) 1044 for expression in expressions 1045 ] 1046 ) 1047 1048 1049def tuple_( 1050 *expressions: ExpOrStr, 1051 copy: bool = True, 1052 dialect: DialectType = None, 1053 **kwargs: Unpack[ParserNoDialectArgs], 1054) -> Tuple: 1055 """ 1056 Returns an tuple. 1057 1058 Examples: 1059 >>> tuple_(1, 'x').sql() 1060 '(1, x)' 1061 1062 Args: 1063 expressions: the expressions to add to the tuple. 1064 copy: whether to copy the argument expressions. 1065 dialect: the source dialect. 1066 kwargs: the kwargs used to instantiate the function of interest. 1067 1068 Returns: 1069 A tuple expression. 1070 """ 1071 return Tuple( 1072 expressions=[ 1073 maybe_parse(expression, copy=copy, dialect=dialect, **kwargs) 1074 for expression in expressions 1075 ] 1076 ) 1077 1078 1079def true() -> Boolean: 1080 """ 1081 Returns a true Boolean expression. 1082 """ 1083 return Boolean(this=True) 1084 1085 1086def false() -> Boolean: 1087 """ 1088 Returns a false Boolean expression. 1089 """ 1090 return Boolean(this=False) 1091 1092 1093def null() -> Null: 1094 """ 1095 Returns a Null expression. 1096 """ 1097 return Null() 1098 1099 1100def apply_index_offset( 1101 this: Expr, 1102 expressions: list[E], 1103 offset: int, 1104 dialect: DialectType = None, 1105) -> list[E]: 1106 if not offset or len(expressions) != 1: 1107 return expressions 1108 1109 expression = expressions[0] 1110 1111 from sqlglot.optimizer.annotate_types import annotate_types 1112 from sqlglot.optimizer.simplify import simplify 1113 1114 if not this.type: 1115 annotate_types(this, dialect=dialect) 1116 1117 if t.cast(DataType, this.type).this not in ( 1118 DType.UNKNOWN, 1119 DType.ARRAY, 1120 ): 1121 return expressions 1122 1123 if not expression.type: 1124 annotate_types(expression, dialect=dialect) 1125 1126 if t.cast(DataType, expression.type).this in DataType.INTEGER_TYPES: 1127 logger.info("Applying array index offset (%s)", offset) 1128 expression = simplify(expression + offset) 1129 return [expression] 1130 1131 return expressions 1132 1133 1134NONNULL_CONSTANTS = ( 1135 Literal, 1136 Boolean, 1137) 1138 1139CONSTANTS = ( 1140 Literal, 1141 Boolean, 1142 Null, 1143)
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: DType = expr.to.this 500 new_cast_type: DType = data_type.this 501 types_are_equivalent = type_mapping.get( 502 existing_cast_type, existing_cast_type.value 503 ) == type_mapping.get(new_cast_type, new_cast_type.value) 504 505 if expr.is_type(data_type) or types_are_equivalent: 506 return expr 507 508 expr = Cast(this=expr, to=data_type) 509 expr.type = data_type 510 511 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.
514def table_( 515 table: Identifier | str, 516 db: Identifier | str | None = None, 517 catalog: Identifier | str | None = None, 518 quoted: bool | None = None, 519 alias: Identifier | str | None = None, 520) -> Table: 521 """Build a Table. 522 523 Args: 524 table: Table name. 525 db: Database name. 526 catalog: Catalog name. 527 quote: Whether to force quotes on the table's identifiers. 528 alias: Table's alias. 529 530 Returns: 531 The new Table instance. 532 """ 533 return Table( 534 this=to_identifier(table, quoted=quoted) if table else None, 535 db=to_identifier(db, quoted=quoted) if db else None, 536 catalog=to_identifier(catalog, quoted=quoted) if catalog else None, 537 alias=TableAlias(this=to_identifier(alias)) if alias else None, 538 )
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.
541def values( 542 values: Iterable[tuple[object, ...] | Tuple], 543 alias: str | None = None, 544 columns: Iterable[str] | dict[str, DataType] | None = None, 545) -> Values: 546 """Build VALUES statement. 547 548 Example: 549 >>> values([(1, '2')]).sql() 550 "VALUES (1, '2')" 551 552 Args: 553 values: values statements that will be converted to SQL 554 alias: optional alias 555 columns: Optional list of ordered column names or ordered dictionary of column names to types. 556 If either are provided then an alias is also required. 557 558 Returns: 559 Values: the Values expression object 560 """ 561 if columns and not alias: 562 raise ValueError("Alias is required when providing columns") 563 564 return Values( 565 expressions=[convert(tup) for tup in values], 566 alias=( 567 TableAlias(this=to_identifier(alias), columns=[to_identifier(x) for x in columns]) 568 if columns 569 else (TableAlias(this=to_identifier(alias)) if alias else None) 570 ), 571 )
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
574def var(name: ExpOrStr | None) -> Var: 575 """Build a SQL variable. 576 577 Example: 578 >>> repr(var('x')) 579 'Var(this=x)' 580 581 >>> repr(var(column('x', table='y'))) 582 'Var(this=x)' 583 584 Args: 585 name: The name of the var or an expression who's name will become the var. 586 587 Returns: 588 The new variable node. 589 """ 590 if not name: 591 raise ValueError("Cannot convert empty name into var.") 592 593 if isinstance(name, Expr): 594 name = name.name 595 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.
598def rename_table( 599 old_name: str | Table, 600 new_name: str | Table, 601 dialect: DialectType = None, 602) -> Alter: 603 """Build ALTER TABLE... RENAME... expression 604 605 Args: 606 old_name: The old name of the table 607 new_name: The new name of the table 608 dialect: The dialect to parse the table. 609 610 Returns: 611 Alter table expression 612 """ 613 old_table = to_table(old_name, dialect=dialect) 614 new_table = to_table(new_name, dialect=dialect) 615 return Alter( 616 this=old_table, 617 kind="TABLE", 618 actions=[ 619 AlterRename(this=new_table), 620 ], 621 )
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
624def rename_column( 625 table_name: str | Table, 626 old_column_name: str | Column, 627 new_column_name: str | Column, 628 exists: bool | None = None, 629 dialect: DialectType = None, 630) -> Alter: 631 """Build ALTER TABLE... RENAME COLUMN... expression 632 633 Args: 634 table_name: Name of the table 635 old_column: The old name of the column 636 new_column: The new name of the column 637 exists: Whether to add the `IF EXISTS` clause 638 dialect: The dialect to parse the table/column. 639 640 Returns: 641 Alter table expression 642 """ 643 table = to_table(table_name, dialect=dialect) 644 old_column = to_column(old_column_name, dialect=dialect) 645 new_column = to_column(new_column_name, dialect=dialect) 646 return Alter( 647 this=table, 648 kind="TABLE", 649 actions=[ 650 RenameColumn(this=old_column, to=new_column, exists=exists), 651 ], 652 )
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
655def replace_children( 656 expression: Expr, 657 fun: t.Callable[Concatenate[Expr, P], object], 658 *args: P.args, 659 **kwargs: P.kwargs, 660) -> None: 661 """ 662 Replace children of an expression with the result of a lambda fun(child) -> exp. 663 """ 664 for k, v in tuple(expression.args.items()): 665 is_list_arg = type(v) is list 666 667 child_nodes = v if is_list_arg else [v] 668 new_child_nodes = [] 669 670 for cn in child_nodes: 671 if isinstance(cn, Expr): 672 for child_node in ensure_collection(fun(cn, *args, **kwargs)): 673 new_child_nodes.append(child_node) 674 else: 675 new_child_nodes.append(cn) 676 677 if is_list_arg: 678 expression.set(k, new_child_nodes) 679 else: 680 expression.set(k, seq_get(new_child_nodes, 0))
Replace children of an expression with the result of a lambda fun(child) -> exp.
683def replace_tree( 684 expression: Expr, 685 fun: t.Callable[[Expr], Expr], 686 prune: t.Callable[[Expr], bool] | None = None, 687) -> Expr: 688 """ 689 Replace an entire tree with the result of function calls on each node. 690 691 This will be traversed in reverse dfs, so leaves first. 692 If new nodes are created as a result of function calls, they will also be traversed. 693 """ 694 stack = list(expression.dfs(prune=prune)) 695 696 while stack: 697 node = stack.pop() 698 new_node = fun(node) 699 700 if new_node is not node: 701 node.replace(new_node) 702 703 if isinstance(new_node, Expr): 704 stack.append(new_node) 705 706 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.
709def find_tables(expression: Expr) -> set[Table]: 710 """ 711 Find all tables referenced in a query. 712 713 Args: 714 expressions: The query to find the tables in. 715 716 Returns: 717 A set of all the tables. 718 """ 719 from sqlglot.optimizer.scope import traverse_scope 720 721 return { 722 table 723 for scope in traverse_scope(expression) 724 for table in scope.tables 725 if isinstance(table, Table) and table.name and table.name not in scope.cte_sources 726 }
Find all tables referenced in a query.
Arguments:
- expressions: The query to find the tables in.
Returns:
A set of all the tables.
729def column_table_names(expression: Expr, exclude: str = "") -> set[str]: 730 """ 731 Return all table names referenced through columns in an expression. 732 733 Example: 734 >>> import sqlglot 735 >>> sorted(column_table_names(sqlglot.parse_one("a.b AND c.d AND c.e"))) 736 ['a', 'c'] 737 738 Args: 739 expression: expression to find table names. 740 exclude: a table name to exclude 741 742 Returns: 743 A list of unique names. 744 """ 745 return { 746 table 747 for table in (column.table for column in expression.find_all(Column)) 748 if table and table != exclude 749 }
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.
752def table_name(table: Table | str, dialect: DialectType = None, identify: bool = False) -> str: 753 """Get the full name of a table as a string. 754 755 Args: 756 table: Table expression node or string. 757 dialect: The dialect to generate the table name for. 758 identify: Determines when an identifier should be quoted. Possible values are: 759 False (default): Never quote, except in cases where it's mandatory by the dialect. 760 True: Always quote. 761 762 Examples: 763 >>> from sqlglot import exp, parse_one 764 >>> table_name(parse_one("select * from a.b.c").find(exp.Table)) 765 'a.b.c' 766 767 Returns: 768 The table name. 769 """ 770 771 expr = maybe_parse(table, into=Table, dialect=dialect) 772 773 if not expr: 774 raise ValueError(f"Cannot parse {table}") 775 776 return ".".join( 777 ( 778 part.sql(dialect=dialect, identify=True, copy=False, comments=False) 779 if identify or not SAFE_IDENTIFIER_RE.match(part.name) 780 else part.name 781 ) 782 for part in expr.parts 783 )
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.
786def normalize_table_name(table: str | Table, dialect: DialectType = None, copy: bool = True) -> str: 787 """Returns a case normalized table name without quotes. 788 789 Args: 790 table: the table to normalize 791 dialect: the dialect to use for normalization rules 792 copy: whether to copy the expression. 793 794 Examples: 795 >>> normalize_table_name("`A-B`.c", dialect="bigquery") 796 'A-B.c' 797 """ 798 from sqlglot.optimizer.normalize_identifiers import normalize_identifiers 799 800 return ".".join( 801 p.name 802 for p in normalize_identifiers( 803 to_table(table, dialect=dialect, copy=copy), dialect=dialect 804 ).parts 805 )
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'
808def replace_tables( 809 expression: E, mapping: dict[str, str], dialect: DialectType = None, copy: bool = True 810) -> E: 811 """Replace all tables in expression according to the mapping. 812 813 Args: 814 expression: expression node to be transformed and replaced. 815 mapping: mapping of table names. 816 dialect: the dialect of the mapping table 817 copy: whether to copy the expression. 818 819 Examples: 820 >>> from sqlglot import exp, parse_one 821 >>> replace_tables(parse_one("select * from a.b"), {"a.b": "c"}).sql() 822 'SELECT * FROM c /* a.b */' 823 824 Returns: 825 The mapped expression. 826 """ 827 828 mapping = {normalize_table_name(k, dialect=dialect): v for k, v in mapping.items()} 829 830 def _replace_tables(node: Expr) -> Expr: 831 if isinstance(node, Table) and node.meta_get("replace") is not False: 832 original = normalize_table_name(node, dialect=dialect) 833 new_name = mapping.get(original) 834 835 if new_name: 836 table = to_table( 837 new_name, 838 **{k: v for k, v in node.args.items() if k not in TABLE_PARTS}, 839 dialect=dialect, 840 ) 841 table.add_comments([original]) 842 return table 843 return node 844 845 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.
848def replace_placeholders(expression: Expr, *args: object, **kwargs: t.Any) -> Expr: 849 """Replace placeholders in an expression. 850 851 Args: 852 expression: expression node to be transformed and replaced. 853 args: positional names that will substitute unnamed placeholders in the given order. 854 kwargs: keyword arguments that will substitute named placeholders. 855 856 Examples: 857 >>> from sqlglot import exp, parse_one 858 >>> replace_placeholders( 859 ... parse_one("select * from :tbl where ? = ?"), 860 ... exp.to_identifier("str_col"), "b", tbl=exp.to_identifier("foo") 861 ... ).sql() 862 "SELECT * FROM foo WHERE str_col = 'b'" 863 864 Returns: 865 The mapped expression. 866 """ 867 868 def _replace_placeholders(node: Expr, args: Iterator[object], **kwargs: object) -> Expr: 869 if isinstance(node, Placeholder): 870 if node.this: 871 new_name = kwargs.get(node.this) 872 if new_name is not None: 873 return convert(new_name) 874 else: 875 try: 876 return convert(next(args)) 877 except StopIteration: 878 pass 879 return node 880 881 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.
884def expand( 885 expression: Expr, 886 sources: dict[str, Query | t.Callable[[], Query]], 887 dialect: DialectType = None, 888 copy: bool = True, 889) -> Expr: 890 """Transforms an expression by expanding all referenced sources into subqueries. 891 892 Examples: 893 >>> from sqlglot import parse_one 894 >>> expand(parse_one("select * from x AS z"), {"x": parse_one("select * from y")}).sql() 895 'SELECT * FROM (SELECT * FROM y) AS z /* source: x */' 896 897 >>> expand(parse_one("select * from x AS z"), {"x": parse_one("select * from y"), "y": parse_one("select * from z")}).sql() 898 'SELECT * FROM (SELECT * FROM (SELECT * FROM z) AS y /* source: y */) AS z /* source: x */' 899 900 Args: 901 expression: The expression to expand. 902 sources: A dict of name to query or a callable that provides a query on demand. 903 dialect: The dialect of the sources dict or the callable. 904 copy: Whether to copy the expression during transformation. Defaults to True. 905 906 Returns: 907 The transformed expression. 908 """ 909 normalized_sources = {normalize_table_name(k, dialect=dialect): v for k, v in sources.items()} 910 911 def _expand(node: Expr): 912 if isinstance(node, Table): 913 name = normalize_table_name(node, dialect=dialect) 914 source = normalized_sources.get(name) 915 916 if source: 917 # Create a subquery with the same alias (or table name if no alias) 918 parsed_source = source() if callable(source) else source 919 subquery = parsed_source.subquery(node.alias or name) 920 subquery.comments = [f"source: {name}"] 921 922 # Continue expanding within the subquery 923 return subquery.transform(_expand, copy=False) 924 925 return node 926 927 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.
930def func( 931 name: str, *args: t.Any, copy: bool = True, dialect: DialectType = None, **kwargs: t.Any 932) -> Func: 933 """ 934 Returns a Func expression. 935 936 Examples: 937 >>> func("abs", 5).sql() 938 'ABS(5)' 939 940 >>> func("cast", this=5, to=DataType.build("DOUBLE")).sql() 941 'CAST(5 AS DOUBLE)' 942 943 Args: 944 name: the name of the function to build. 945 args: the args used to instantiate the function of interest. 946 copy: whether to copy the argument expressions. 947 dialect: the source dialect. 948 kwargs: the kwargs used to instantiate the function of interest. 949 950 Note: 951 The arguments `args` and `kwargs` are mutually exclusive. 952 953 Returns: 954 An instance of the function of interest, or an anonymous function, if `name` doesn't 955 correspond to an existing `sqlglot.expressions.Func` class. 956 """ 957 if args and kwargs: 958 raise ValueError("Can't use both args and kwargs to instantiate a function.") 959 960 from sqlglot.dialects.dialect import Dialect 961 962 dialect = Dialect.get_or_raise(dialect) 963 964 converted: list[Expr] = [maybe_parse(arg, dialect=dialect, copy=copy) for arg in args] 965 kwargs = {key: maybe_parse(value, dialect=dialect, copy=copy) for key, value in kwargs.items()} 966 967 constructor = dialect.parser_class.FUNCTIONS.get(name.upper()) 968 if constructor: 969 if converted: 970 try: 971 function = constructor(converted) 972 except TypeError: 973 function = constructor(converted, dialect=dialect) 974 elif constructor.__name__ == "from_arg_list": 975 function = constructor.__self__(**kwargs) # type: ignore 976 else: 977 from sqlglot.expressions import FUNCTION_BY_NAME as _FUNCTION_BY_NAME 978 979 constructor = _FUNCTION_BY_NAME.get(name.upper()) 980 if constructor: 981 function = constructor(**kwargs) 982 else: 983 raise ValueError( 984 f"Unable to convert '{name}' into a Func. Either manually construct " 985 "the Func expression of interest or parse the function call." 986 ) 987 else: 988 kwargs = kwargs or {"expressions": converted} 989 function = Anonymous(this=name, **kwargs) 990 991 for error_message in function.error_messages(converted): 992 raise ValueError(error_message) 993 994 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.
997def case( 998 expression: ExpOrStr | None = None, 999 copy: bool = True, 1000 **opts: Unpack[ParserArgs], 1001) -> Case: 1002 """ 1003 Initialize a CASE statement. 1004 1005 Example: 1006 case().when("a = 1", "foo").else_("bar") 1007 1008 Args: 1009 expression: Optionally, the input expression (not all dialects support this) 1010 copy: whether to copy the argument expressions. 1011 **opts: Extra keyword arguments for parsing `expression` 1012 """ 1013 if expression is not None: 1014 this = maybe_parse(expression, copy=copy, **opts) 1015 else: 1016 this = None 1017 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
1020def array( 1021 *expressions: ExpOrStr, 1022 copy: bool = True, 1023 dialect: DialectType = None, 1024 **kwargs: Unpack[ParserNoDialectArgs], 1025) -> Array: 1026 """ 1027 Returns an array. 1028 1029 Examples: 1030 >>> array(1, 'x').sql() 1031 'ARRAY(1, x)' 1032 1033 Args: 1034 expressions: the expressions to add to the array. 1035 copy: whether to copy the argument expressions. 1036 dialect: the source dialect. 1037 kwargs: the kwargs used to instantiate the function of interest. 1038 1039 Returns: 1040 An array expression. 1041 """ 1042 return Array( 1043 expressions=[ 1044 maybe_parse(expression, copy=copy, dialect=dialect, **kwargs) 1045 for expression in expressions 1046 ] 1047 )
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.
1050def tuple_( 1051 *expressions: ExpOrStr, 1052 copy: bool = True, 1053 dialect: DialectType = None, 1054 **kwargs: Unpack[ParserNoDialectArgs], 1055) -> Tuple: 1056 """ 1057 Returns an tuple. 1058 1059 Examples: 1060 >>> tuple_(1, 'x').sql() 1061 '(1, x)' 1062 1063 Args: 1064 expressions: the expressions to add to the tuple. 1065 copy: whether to copy the argument expressions. 1066 dialect: the source dialect. 1067 kwargs: the kwargs used to instantiate the function of interest. 1068 1069 Returns: 1070 A tuple expression. 1071 """ 1072 return Tuple( 1073 expressions=[ 1074 maybe_parse(expression, copy=copy, dialect=dialect, **kwargs) 1075 for expression in expressions 1076 ] 1077 )
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.
1080def true() -> Boolean: 1081 """ 1082 Returns a true Boolean expression. 1083 """ 1084 return Boolean(this=True)
Returns a true Boolean expression.
1087def false() -> Boolean: 1088 """ 1089 Returns a false Boolean expression. 1090 """ 1091 return Boolean(this=False)
Returns a false Boolean expression.
Returns a Null expression.
1101def apply_index_offset( 1102 this: Expr, 1103 expressions: list[E], 1104 offset: int, 1105 dialect: DialectType = None, 1106) -> list[E]: 1107 if not offset or len(expressions) != 1: 1108 return expressions 1109 1110 expression = expressions[0] 1111 1112 from sqlglot.optimizer.annotate_types import annotate_types 1113 from sqlglot.optimizer.simplify import simplify 1114 1115 if not this.type: 1116 annotate_types(this, dialect=dialect) 1117 1118 if t.cast(DataType, this.type).this not in ( 1119 DType.UNKNOWN, 1120 DType.ARRAY, 1121 ): 1122 return expressions 1123 1124 if not expression.type: 1125 annotate_types(expression, dialect=dialect) 1126 1127 if t.cast(DataType, expression.type).this in DataType.INTEGER_TYPES: 1128 logger.info("Applying array index offset (%s)", offset) 1129 expression = simplify(expression + offset) 1130 return [expression] 1131 1132 return expressions