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