Edit on GitHub

sqlglot expressions builders.

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

def from_( expression: Union[int, str, sqlglot.expressions.core.Expr], dialect: Union[str, sqlglot.dialects.Dialect, type[sqlglot.dialects.Dialect], NoneType] = None, copy: bool = True, **opts: typing_extensions.Unpack[sqlglot._typing.ParserNoDialectArgs]) -> sqlglot.expressions.query.Select:
 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.

def update( table: str | sqlglot.expressions.query.Table, properties: dict[str, object] | None = None, where: Union[int, str, sqlglot.expressions.core.Expr, NoneType] = None, from_: Union[int, str, sqlglot.expressions.core.Expr, NoneType] = None, with_: dict[str, typing.Union[int, str, sqlglot.expressions.core.Expr]] | None = None, dialect: Union[str, sqlglot.dialects.Dialect, type[sqlglot.dialects.Dialect], NoneType] = None, copy: bool = True, **opts: typing_extensions.Unpack[sqlglot._typing.ParserNoDialectArgs]) -> sqlglot.expressions.dml.Update:
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.

def delete( table: Union[int, str, sqlglot.expressions.core.Expr], where: Union[int, str, sqlglot.expressions.core.Expr, NoneType] = None, returning: Union[int, str, sqlglot.expressions.core.Expr, NoneType] = None, dialect: Union[str, sqlglot.dialects.Dialect, type[sqlglot.dialects.Dialect], NoneType] = None, **opts: typing_extensions.Unpack[sqlglot._typing.ParserNoDialectArgs]) -> sqlglot.expressions.dml.Delete:
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.

def insert( expression: Union[int, str, sqlglot.expressions.core.Expr], into: str | sqlglot.expressions.query.Table, columns: Sequence[str | sqlglot.expressions.core.Identifier] | None = None, overwrite: bool | None = None, returning: Union[int, str, sqlglot.expressions.core.Expr, NoneType] = None, dialect: Union[str, sqlglot.dialects.Dialect, type[sqlglot.dialects.Dialect], NoneType] = None, copy: bool = True, **opts: typing_extensions.Unpack[sqlglot._typing.ParserNoDialectArgs]) -> sqlglot.expressions.dml.Insert:
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.

def merge( *when_exprs: Union[int, str, sqlglot.expressions.core.Expr], into: Union[int, str, sqlglot.expressions.core.Expr], using: Union[int, str, sqlglot.expressions.core.Expr], on: Union[int, str, sqlglot.expressions.core.Expr], returning: Union[int, str, sqlglot.expressions.core.Expr, NoneType] = None, dialect: Union[str, sqlglot.dialects.Dialect, type[sqlglot.dialects.Dialect], NoneType] = None, copy: bool = True, **opts: typing_extensions.Unpack[sqlglot._typing.ParserNoDialectArgs]) -> sqlglot.expressions.dml.Merge:
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.

def parse_identifier( name: str | sqlglot.expressions.core.Identifier, dialect: Union[str, sqlglot.dialects.Dialect, type[sqlglot.dialects.Dialect], NoneType] = None) -> sqlglot.expressions.core.Identifier:
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.

INTERVAL_STRING_RE = re.compile('\\s*(-?[0-9]+(?:\\.[0-9]+)?)\\s*([a-zA-Z]+)\\s*')
INTERVAL_DAY_TIME_RE = re.compile('\\s*-?\\s*\\d+(?:\\.\\d+)?\\s+(?:-?(?:\\d+:)?\\d+:\\d+(?:\\.\\d+)?|-?(?:\\d+:){1,2}|:)\\s*')
def to_interval( interval: str | sqlglot.expressions.core.Expr) -> sqlglot.expressions.datatypes.Interval:
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'.

def to_table( sql_path: str | sqlglot.expressions.query.Table, dialect: Union[str, sqlglot.dialects.Dialect, type[sqlglot.dialects.Dialect], NoneType] = None, copy: bool = True, **kwargs: object) -> sqlglot.expressions.query.Table:
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 Table expression with.
Returns:

A table expression.

def to_column( sql_path: str | sqlglot.expressions.core.Column, quoted: bool | None = None, dialect: Union[str, sqlglot.dialects.Dialect, type[sqlglot.dialects.Dialect], NoneType] = None, copy: bool = True, **kwargs: Any) -> sqlglot.expressions.core.Column | sqlglot.expressions.core.Dot:
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 Column expression with.
Returns:

A column expression.

def subquery( expression: Union[int, str, sqlglot.expressions.core.Expr], alias: sqlglot.expressions.core.Identifier | str | None = None, dialect: Union[str, sqlglot.dialects.Dialect, type[sqlglot.dialects.Dialect], NoneType] = None, copy: bool = True, **opts: typing_extensions.Unpack[sqlglot._typing.ParserNoDialectArgs]) -> sqlglot.expressions.query.Select:
428def subquery(
429    expression: ExpOrStr,
430    alias: Identifier | str | None = None,
431    dialect: DialectType = None,
432    copy: bool = True,
433    **opts: Unpack[ParserNoDialectArgs],
434) -> Select:
435    """
436    Build a subquery expression that's selected from.
437
438    Example:
439        >>> subquery('select x from tbl', 'bar').select('x').sql()
440        'SELECT x FROM (SELECT x FROM tbl) AS bar'
441
442    Args:
443        expression: the SQL code strings to parse.
444            If an Expr instance is passed, this is used as-is.
445        alias: the alias name to use.
446        dialect: the dialect used to parse the input expression.
447        **opts: other options to use to parse the input expressions.
448
449    Returns:
450        A new Select instance with the subquery expression included.
451    """
452    expr = (
453        maybe_parse(expression, dialect=dialect, **opts).assert_is(Query).subquery(alias, copy=copy)
454    )
455    return Select().from_(expr, dialect=dialect, **opts)

Build a subquery expression that's selected from.

Example:
>>> subquery('select x from tbl', 'bar').select('x').sql()
'SELECT x FROM (SELECT x FROM tbl) AS bar'
Arguments:
  • expression: the SQL code strings to parse. If an Expr instance is passed, this is used as-is.
  • alias: the alias name to use.
  • dialect: the dialect used to parse the input expression.
  • **opts: other options to use to parse the input expressions.
Returns:

A new Select instance with the subquery expression included.

458def cast(
459    expression: ExpOrStr,
460    to: DATA_TYPE,
461    copy: bool = True,
462    dialect: DialectType = None,
463    **opts: Unpack[ParserNoDialectArgs],
464) -> Cast:
465    """Cast an expression to a data type.
466
467    Example:
468        >>> cast('x + 1', 'int').sql()
469        'CAST(x + 1 AS INT)'
470
471    Args:
472        expression: The expression to cast.
473        to: The datatype to cast to.
474        copy: Whether to copy the supplied expressions.
475        dialect: The target dialect. This is used to prevent a re-cast in the following scenario:
476            - The expression to be cast is already a exp.Cast expression
477            - The existing cast is to a type that is logically equivalent to new type
478
479            For example, if :expression='CAST(x as DATETIME)' and :to=Type.TIMESTAMP,
480            but in the target dialect DATETIME is mapped to TIMESTAMP, then we will NOT return `CAST(x (as DATETIME) as TIMESTAMP)`
481            and instead just return the original expression `CAST(x as DATETIME)`.
482
483            This is to prevent it being output as a double cast `CAST(x (as TIMESTAMP) as TIMESTAMP)` once the DATETIME -> TIMESTAMP
484            mapping is applied in the target dialect generator.
485
486    Returns:
487        The new Cast instance.
488    """
489    expr = maybe_parse(expression, copy=copy, dialect=dialect, **opts)
490    data_type = DataType.build(to, copy=copy, dialect=dialect, **opts)
491
492    # dont re-cast if the expression is already a cast to the correct type
493    if isinstance(expr, Cast):
494        from sqlglot.dialects.dialect import Dialect
495
496        target_dialect = Dialect.get_or_raise(dialect)
497        type_mapping = target_dialect.generator_class.TYPE_MAPPING
498
499        existing_cast_type = expr.to.this
500        new_cast_type: DType = data_type.this
501        # `this` is only a plain type enum for simple types; complex ones such as
502        # INTERVAL nest another expression there, so the equivalence check is skipped.
503        types_are_equivalent = (
504            isinstance(existing_cast_type, DType)
505            and isinstance(new_cast_type, DType)
506            and type_mapping.get(existing_cast_type, existing_cast_type.value)
507            == type_mapping.get(new_cast_type, new_cast_type.value)
508        )
509
510        if expr.is_type(data_type) or types_are_equivalent:
511            return expr
512
513    expr = Cast(this=expr, to=data_type)
514    expr.type = data_type
515
516    return expr

Cast an expression to a data type.

Example:
>>> cast('x + 1', 'int').sql()
'CAST(x + 1 AS INT)'
Arguments:
  • expression: The expression to cast.
  • to: The datatype to cast to.
  • copy: Whether to copy the supplied expressions.
  • dialect: The target dialect. This is used to prevent a re-cast in the following scenario:

    • The expression to be cast is already a exp.Cast expression
    • The existing cast is to a type that is logically equivalent to new type

    For example, if :expression='CAST(x as DATETIME)' and :to=Type.TIMESTAMP, but in the target dialect DATETIME is mapped to TIMESTAMP, then we will NOT return CAST(x (as DATETIME) as TIMESTAMP) and instead just return the original expression CAST(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.

def table_( table: sqlglot.expressions.core.Identifier | str, db: sqlglot.expressions.core.Identifier | str | None = None, catalog: sqlglot.expressions.core.Identifier | str | None = None, quoted: bool | None = None, alias: sqlglot.expressions.core.Identifier | str | None = None) -> sqlglot.expressions.query.Table:
519def table_(
520    table: Identifier | str,
521    db: Identifier | str | None = None,
522    catalog: Identifier | str | None = None,
523    quoted: bool | None = None,
524    alias: Identifier | str | None = None,
525) -> Table:
526    """Build a Table.
527
528    Args:
529        table: Table name.
530        db: Database name.
531        catalog: Catalog name.
532        quote: Whether to force quotes on the table's identifiers.
533        alias: Table's alias.
534
535    Returns:
536        The new Table instance.
537    """
538    return Table(
539        this=to_identifier(table, quoted=quoted) if table else None,
540        db=to_identifier(db, quoted=quoted) if db else None,
541        catalog=to_identifier(catalog, quoted=quoted) if catalog else None,
542        alias=TableAlias(this=to_identifier(alias)) if alias else None,
543    )

Build a Table.

Arguments:
  • table: Table name.
  • db: Database name.
  • catalog: Catalog name.
  • quote: Whether to force quotes on the table's identifiers.
  • alias: Table's alias.
Returns:

The new Table instance.

def values( values: Iterable[tuple[object, ...] | sqlglot.expressions.query.Tuple], alias: str | None = None, columns: Iterable[str] | dict[str, sqlglot.expressions.datatypes.DataType] | None = None) -> sqlglot.expressions.query.Values:
546def values(
547    values: Iterable[tuple[object, ...] | Tuple],
548    alias: str | None = None,
549    columns: Iterable[str] | dict[str, DataType] | None = None,
550) -> Values:
551    """Build VALUES statement.
552
553    Example:
554        >>> values([(1, '2')]).sql()
555        "VALUES (1, '2')"
556
557    Args:
558        values: values statements that will be converted to SQL
559        alias: optional alias
560        columns: Optional list of ordered column names or ordered dictionary of column names to types.
561         If either are provided then an alias is also required.
562
563    Returns:
564        Values: the Values expression object
565    """
566    if columns and not alias:
567        raise ValueError("Alias is required when providing columns")
568
569    return Values(
570        expressions=[convert(tup) for tup in values],
571        alias=(
572            TableAlias(this=to_identifier(alias), columns=[to_identifier(x) for x in columns])
573            if columns
574            else (TableAlias(this=to_identifier(alias)) if alias else None)
575        ),
576    )

Build VALUES statement.

Example:
>>> values([(1, '2')]).sql()
"VALUES (1, '2')"
Arguments:
  • values: values statements that will be converted to SQL
  • alias: optional alias
  • columns: Optional list of ordered column names or ordered dictionary of column names to types. If either are provided then an alias is also required.
Returns:

Values: the Values expression object

def var( name: Union[int, str, sqlglot.expressions.core.Expr, NoneType]) -> sqlglot.expressions.core.Var:
579def var(name: ExpOrStr | None) -> Var:
580    """Build a SQL variable.
581
582    Example:
583        >>> repr(var('x'))
584        'Var(this=x)'
585
586        >>> repr(var(column('x', table='y')))
587        'Var(this=x)'
588
589    Args:
590        name: The name of the var or an expression who's name will become the var.
591
592    Returns:
593        The new variable node.
594    """
595    if not name:
596        raise ValueError("Cannot convert empty name into var.")
597
598    if isinstance(name, Expr):
599        name = name.name
600    return Var(this=name)

Build a SQL variable.

Example:
>>> repr(var('x'))
'Var(this=x)'
>>> repr(var(column('x', table='y')))
'Var(this=x)'
Arguments:
  • name: The name of the var or an expression who's name will become the var.
Returns:

The new variable node.

def rename_table( old_name: str | sqlglot.expressions.query.Table, new_name: str | sqlglot.expressions.query.Table, dialect: Union[str, sqlglot.dialects.Dialect, type[sqlglot.dialects.Dialect], NoneType] = None) -> sqlglot.expressions.ddl.Alter:
603def rename_table(
604    old_name: str | Table,
605    new_name: str | Table,
606    dialect: DialectType = None,
607) -> Alter:
608    """Build ALTER TABLE... RENAME... expression
609
610    Args:
611        old_name: The old name of the table
612        new_name: The new name of the table
613        dialect: The dialect to parse the table.
614
615    Returns:
616        Alter table expression
617    """
618    old_table = to_table(old_name, dialect=dialect)
619    new_table = to_table(new_name, dialect=dialect)
620    return Alter(
621        this=old_table,
622        kind="TABLE",
623        actions=[
624            AlterRename(this=new_table),
625        ],
626    )

Build ALTER TABLE... RENAME... expression

Arguments:
  • old_name: The old name of the table
  • new_name: The new name of the table
  • dialect: The dialect to parse the table.
Returns:

Alter table expression

def rename_column( table_name: str | sqlglot.expressions.query.Table, old_column_name: str | sqlglot.expressions.core.Column, new_column_name: str | sqlglot.expressions.core.Column, exists: bool | None = None, dialect: Union[str, sqlglot.dialects.Dialect, type[sqlglot.dialects.Dialect], NoneType] = None) -> sqlglot.expressions.ddl.Alter:
629def rename_column(
630    table_name: str | Table,
631    old_column_name: str | Column,
632    new_column_name: str | Column,
633    exists: bool | None = None,
634    dialect: DialectType = None,
635) -> Alter:
636    """Build ALTER TABLE... RENAME COLUMN... expression
637
638    Args:
639        table_name: Name of the table
640        old_column: The old name of the column
641        new_column: The new name of the column
642        exists: Whether to add the `IF EXISTS` clause
643        dialect: The dialect to parse the table/column.
644
645    Returns:
646        Alter table expression
647    """
648    table = to_table(table_name, dialect=dialect)
649    old_column = to_column(old_column_name, dialect=dialect)
650    new_column = to_column(new_column_name, dialect=dialect)
651    return Alter(
652        this=table,
653        kind="TABLE",
654        actions=[
655            RenameColumn(this=old_column, to=new_column, exists=exists),
656        ],
657    )

Build ALTER TABLE... RENAME COLUMN... expression

Arguments:
  • table_name: Name of the table
  • old_column: The old name of the column
  • new_column: The new name of the column
  • exists: Whether to add the IF EXISTS clause
  • dialect: The dialect to parse the table/column.
Returns:

Alter table expression

def replace_children( expression: sqlglot.expressions.core.Expr, fun: Callable[typing_extensions.Concatenate[sqlglot.expressions.core.Expr, ~P], object], *args: P.args, **kwargs: P.kwargs) -> None:
660def replace_children(
661    expression: Expr,
662    fun: t.Callable[Concatenate[Expr, P], object],
663    *args: P.args,
664    **kwargs: P.kwargs,
665) -> None:
666    """
667    Replace children of an expression with the result of a lambda fun(child) -> exp.
668    """
669    for k, v in tuple(expression.args.items()):
670        is_list_arg = type(v) is list
671
672        child_nodes = v if is_list_arg else [v]
673        new_child_nodes = []
674
675        for cn in child_nodes:
676            if isinstance(cn, Expr):
677                for child_node in ensure_collection(fun(cn, *args, **kwargs)):
678                    new_child_nodes.append(child_node)
679            else:
680                new_child_nodes.append(cn)
681
682        if is_list_arg:
683            expression.set(k, new_child_nodes)
684        else:
685            expression.set(k, seq_get(new_child_nodes, 0))

Replace children of an expression with the result of a lambda fun(child) -> exp.

def replace_tree( expression: sqlglot.expressions.core.Expr, fun: Callable[[sqlglot.expressions.core.Expr], sqlglot.expressions.core.Expr], prune: Optional[Callable[[sqlglot.expressions.core.Expr], bool]] = None) -> sqlglot.expressions.core.Expr:
688def replace_tree(
689    expression: Expr,
690    fun: t.Callable[[Expr], Expr],
691    prune: t.Callable[[Expr], bool] | None = None,
692) -> Expr:
693    """
694    Replace an entire tree with the result of function calls on each node.
695
696    This will be traversed in reverse dfs, so leaves first.
697    If new nodes are created as a result of function calls, they will also be traversed.
698    """
699    stack = list(expression.dfs(prune=prune))
700
701    while stack:
702        node = stack.pop()
703        new_node = fun(node)
704
705        if new_node is not node:
706            node.replace(new_node)
707
708            if isinstance(new_node, Expr):
709                stack.append(new_node)
710
711    return new_node

Replace an entire tree with the result of function calls on each node.

This will be traversed in reverse dfs, so leaves first. If new nodes are created as a result of function calls, they will also be traversed.

def find_tables( expression: sqlglot.expressions.core.Expr) -> set[sqlglot.expressions.query.Table]:
714def find_tables(expression: Expr) -> set[Table]:
715    """
716    Find all tables referenced in a query.
717
718    Args:
719        expressions: The query to find the tables in.
720
721    Returns:
722        A set of all the tables.
723    """
724    from sqlglot.optimizer.scope import traverse_scope
725
726    return {
727        table
728        for scope in traverse_scope(expression)
729        for table in scope.tables
730        if isinstance(table, Table) and table.name and table.name not in scope.cte_sources
731    }

Find all tables referenced in a query.

Arguments:
  • expressions: The query to find the tables in.
Returns:

A set of all the tables.

def column_table_names(expression: sqlglot.expressions.core.Expr, exclude: str = '') -> set[str]:
734def column_table_names(expression: Expr, exclude: str = "") -> set[str]:
735    """
736    Return all table names referenced through columns in an expression.
737
738    Example:
739        >>> import sqlglot
740        >>> sorted(column_table_names(sqlglot.parse_one("a.b AND c.d AND c.e")))
741        ['a', 'c']
742
743    Args:
744        expression: expression to find table names.
745        exclude: a table name to exclude
746
747    Returns:
748        A list of unique names.
749    """
750    return {
751        table
752        for table in (column.table for column in expression.find_all(Column))
753        if table and table != exclude
754    }

Return all table names referenced through columns in an expression.

Example:
>>> import sqlglot
>>> sorted(column_table_names(sqlglot.parse_one("a.b AND c.d AND c.e")))
['a', 'c']
Arguments:
  • expression: expression to find table names.
  • exclude: a table name to exclude
Returns:

A list of unique names.

def table_name( table: sqlglot.expressions.query.Table | str, dialect: Union[str, sqlglot.dialects.Dialect, type[sqlglot.dialects.Dialect], NoneType] = None, identify: bool = False) -> str:
757def table_name(table: Table | str, dialect: DialectType = None, identify: bool = False) -> str:
758    """Get the full name of a table as a string.
759
760    Args:
761        table: Table expression node or string.
762        dialect: The dialect to generate the table name for.
763        identify: Determines when an identifier should be quoted. Possible values are:
764            False (default): Never quote, except in cases where it's mandatory by the dialect.
765            True: Always quote.
766
767    Examples:
768        >>> from sqlglot import exp, parse_one
769        >>> table_name(parse_one("select * from a.b.c").find(exp.Table))
770        'a.b.c'
771
772    Returns:
773        The table name.
774    """
775
776    expr = maybe_parse(table, into=Table, dialect=dialect)
777
778    if not expr:
779        raise ValueError(f"Cannot parse {table}")
780
781    return ".".join(
782        (
783            part.sql(dialect=dialect, identify=True, copy=False, comments=False)
784            if identify or not SAFE_IDENTIFIER_RE.match(part.name)
785            else part.name
786        )
787        for part in expr.parts
788    )

Get the full name of a table as a string.

Arguments:
  • table: Table expression node or string.
  • dialect: The dialect to generate the table name for.
  • identify: Determines when an identifier should be quoted. Possible values are: False (default): Never quote, except in cases where it's mandatory by the dialect. True: Always quote.
Examples:
>>> from sqlglot import exp, parse_one
>>> table_name(parse_one("select * from a.b.c").find(exp.Table))
'a.b.c'
Returns:

The table name.

def normalize_table_name( table: str | sqlglot.expressions.query.Table, dialect: Union[str, sqlglot.dialects.Dialect, type[sqlglot.dialects.Dialect], NoneType] = None, copy: bool = True) -> str:
791def normalize_table_name(table: str | Table, dialect: DialectType = None, copy: bool = True) -> str:
792    """Returns a case normalized table name without quotes.
793
794    Args:
795        table: the table to normalize
796        dialect: the dialect to use for normalization rules
797        copy: whether to copy the expression.
798
799    Examples:
800        >>> normalize_table_name("`A-B`.c", dialect="bigquery")
801        'A-B.c'
802    """
803    from sqlglot.optimizer.normalize_identifiers import normalize_identifiers
804
805    return ".".join(
806        p.name
807        for p in normalize_identifiers(
808            to_table(table, dialect=dialect, copy=copy), dialect=dialect
809        ).parts
810    )

Returns a case normalized table name without quotes.

Arguments:
  • table: the table to normalize
  • dialect: the dialect to use for normalization rules
  • copy: whether to copy the expression.
Examples:
>>> normalize_table_name("`A-B`.c", dialect="bigquery")
'A-B.c'
def replace_tables( expression: ~E, mapping: dict[str, str], dialect: Union[str, sqlglot.dialects.Dialect, type[sqlglot.dialects.Dialect], NoneType] = None, copy: bool = True) -> ~E:
813def replace_tables(
814    expression: E, mapping: dict[str, str], dialect: DialectType = None, copy: bool = True
815) -> E:
816    """Replace all tables in expression according to the mapping.
817
818    Args:
819        expression: expression node to be transformed and replaced.
820        mapping: mapping of table names.
821        dialect: the dialect of the mapping table
822        copy: whether to copy the expression.
823
824    Examples:
825        >>> from sqlglot import exp, parse_one
826        >>> replace_tables(parse_one("select * from a.b"), {"a.b": "c"}).sql()
827        'SELECT * FROM c /* a.b */'
828
829    Returns:
830        The mapped expression.
831    """
832
833    mapping = {normalize_table_name(k, dialect=dialect): v for k, v in mapping.items()}
834
835    def _replace_tables(node: Expr) -> Expr:
836        if isinstance(node, Table) and node.meta_get("replace") is not False:
837            original = normalize_table_name(node, dialect=dialect)
838            new_name = mapping.get(original)
839
840            if new_name:
841                table = to_table(
842                    new_name,
843                    **{k: v for k, v in node.args.items() if k not in TABLE_PARTS},
844                    dialect=dialect,
845                )
846                table.add_comments([original])
847                return table
848        return node
849
850    return expression.transform(_replace_tables, copy=copy)  # type: ignore

Replace all tables in expression according to the mapping.

Arguments:
  • expression: expression node to be transformed and replaced.
  • mapping: mapping of table names.
  • dialect: the dialect of the mapping table
  • copy: whether to copy the expression.
Examples:
>>> from sqlglot import exp, parse_one
>>> replace_tables(parse_one("select * from a.b"), {"a.b": "c"}).sql()
'SELECT * FROM c /* a.b */'
Returns:

The mapped expression.

def replace_placeholders( expression: sqlglot.expressions.core.Expr, *args: object, **kwargs: Any) -> sqlglot.expressions.core.Expr:
853def replace_placeholders(expression: Expr, *args: object, **kwargs: t.Any) -> Expr:
854    """Replace placeholders in an expression.
855
856    Args:
857        expression: expression node to be transformed and replaced.
858        args: positional names that will substitute unnamed placeholders in the given order.
859        kwargs: keyword arguments that will substitute named placeholders.
860
861    Examples:
862        >>> from sqlglot import exp, parse_one
863        >>> replace_placeholders(
864        ...     parse_one("select * from :tbl where ? = ?"),
865        ...     exp.to_identifier("str_col"), "b", tbl=exp.to_identifier("foo")
866        ... ).sql()
867        "SELECT * FROM foo WHERE str_col = 'b'"
868
869    Returns:
870        The mapped expression.
871    """
872
873    def _replace_placeholders(node: Expr, args: Iterator[object], **kwargs: object) -> Expr:
874        if isinstance(node, Placeholder):
875            if node.this:
876                new_name = kwargs.get(node.this)
877                if new_name is not None:
878                    return convert(new_name)
879            else:
880                try:
881                    return convert(next(args))
882                except StopIteration:
883                    pass
884        return node
885
886    return expression.transform(_replace_placeholders, iter(args), **kwargs)

Replace placeholders in an expression.

Arguments:
  • expression: expression node to be transformed and replaced.
  • args: positional names that will substitute unnamed placeholders in the given order.
  • kwargs: keyword arguments that will substitute named placeholders.
Examples:
>>> from sqlglot import exp, parse_one
>>> replace_placeholders(
...     parse_one("select * from :tbl where ? = ?"),
...     exp.to_identifier("str_col"), "b", tbl=exp.to_identifier("foo")
... ).sql()
"SELECT * FROM foo WHERE str_col = 'b'"
Returns:

The mapped expression.

def expand( expression: sqlglot.expressions.core.Expr, sources: dict[str, typing.Union[sqlglot.expressions.query.Query, typing.Callable[[], sqlglot.expressions.query.Query]]], dialect: Union[str, sqlglot.dialects.Dialect, type[sqlglot.dialects.Dialect], NoneType] = None, copy: bool = True) -> sqlglot.expressions.core.Expr:
889def expand(
890    expression: Expr,
891    sources: dict[str, Query | t.Callable[[], Query]],
892    dialect: DialectType = None,
893    copy: bool = True,
894) -> Expr:
895    """Transforms an expression by expanding all referenced sources into subqueries.
896
897    Examples:
898        >>> from sqlglot import parse_one
899        >>> expand(parse_one("select * from x AS z"), {"x": parse_one("select * from y")}).sql()
900        'SELECT * FROM (SELECT * FROM y) AS z /* source: x */'
901
902        >>> expand(parse_one("select * from x AS z"), {"x": parse_one("select * from y"), "y": parse_one("select * from z")}).sql()
903        'SELECT * FROM (SELECT * FROM (SELECT * FROM z) AS y /* source: y */) AS z /* source: x */'
904
905    Args:
906        expression: The expression to expand.
907        sources: A dict of name to query or a callable that provides a query on demand.
908        dialect: The dialect of the sources dict or the callable.
909        copy: Whether to copy the expression during transformation. Defaults to True.
910
911    Returns:
912        The transformed expression.
913    """
914    normalized_sources = {normalize_table_name(k, dialect=dialect): v for k, v in sources.items()}
915
916    def _expand(node: Expr):
917        if isinstance(node, Table):
918            name = normalize_table_name(node, dialect=dialect)
919            source = normalized_sources.get(name)
920
921            if source:
922                # Create a subquery with the same alias (or table name if no alias)
923                parsed_source = source() if callable(source) else source
924                subquery = parsed_source.subquery(node.alias or name)
925                subquery.comments = [f"source: {name}"]
926
927                # Continue expanding within the subquery
928                return subquery.transform(_expand, copy=False)
929
930        return node
931
932    return expression.transform(_expand, copy=copy)

Transforms an expression by expanding all referenced sources into subqueries.

Examples:
>>> from sqlglot import parse_one
>>> expand(parse_one("select * from x AS z"), {"x": parse_one("select * from y")}).sql()
'SELECT * FROM (SELECT * FROM y) AS z /* source: x */'
>>> expand(parse_one("select * from x AS z"), {"x": parse_one("select * from y"), "y": parse_one("select * from z")}).sql()
'SELECT * FROM (SELECT * FROM (SELECT * FROM z) AS y /* source: y */) AS z /* source: x */'
Arguments:
  • expression: The expression to expand.
  • sources: A dict of name to query or a callable that provides a query on demand.
  • dialect: The dialect of the sources dict or the callable.
  • copy: Whether to copy the expression during transformation. Defaults to True.
Returns:

The transformed expression.

def func( name: str, *args: Any, copy: bool = True, dialect: Union[str, sqlglot.dialects.Dialect, type[sqlglot.dialects.Dialect], NoneType] = None, **kwargs: Any) -> sqlglot.expressions.core.Func:
935def func(
936    name: str, *args: t.Any, copy: bool = True, dialect: DialectType = None, **kwargs: t.Any
937) -> Func:
938    """
939    Returns a Func expression.
940
941    Examples:
942        >>> func("abs", 5).sql()
943        'ABS(5)'
944
945        >>> func("cast", this=5, to=DataType.build("DOUBLE")).sql()
946        'CAST(5 AS DOUBLE)'
947
948    Args:
949        name: the name of the function to build.
950        args: the args used to instantiate the function of interest.
951        copy: whether to copy the argument expressions.
952        dialect: the source dialect.
953        kwargs: the kwargs used to instantiate the function of interest.
954
955    Note:
956        The arguments `args` and `kwargs` are mutually exclusive.
957
958    Returns:
959        An instance of the function of interest, or an anonymous function, if `name` doesn't
960        correspond to an existing `sqlglot.expressions.Func` class.
961    """
962    if args and kwargs:
963        raise ValueError("Can't use both args and kwargs to instantiate a function.")
964
965    from sqlglot.dialects.dialect import Dialect
966
967    dialect = Dialect.get_or_raise(dialect)
968
969    converted: list[Expr] = [maybe_parse(arg, dialect=dialect, copy=copy) for arg in args]
970    kwargs = {key: maybe_parse(value, dialect=dialect, copy=copy) for key, value in kwargs.items()}
971
972    constructor = dialect.parser_class.FUNCTIONS.get(name.upper())
973    if constructor:
974        if converted:
975            try:
976                function = constructor(converted)
977            except TypeError:
978                function = constructor(converted, dialect=dialect)
979        elif constructor.__name__ == "from_arg_list":
980            function = constructor.__self__(**kwargs)  # type: ignore
981        else:
982            from sqlglot.expressions import FUNCTION_BY_NAME as _FUNCTION_BY_NAME
983
984            constructor = _FUNCTION_BY_NAME.get(name.upper())
985            if constructor:
986                function = constructor(**kwargs)
987            else:
988                raise ValueError(
989                    f"Unable to convert '{name}' into a Func. Either manually construct "
990                    "the Func expression of interest or parse the function call."
991                )
992    else:
993        kwargs = kwargs or {"expressions": converted}
994        function = Anonymous(this=name, **kwargs)
995
996    for error_message in function.error_messages(converted):
997        raise ValueError(error_message)
998
999    return function

Returns a Func expression.

Examples:
>>> func("abs", 5).sql()
'ABS(5)'
>>> func("cast", this=5, to=DataType.build("DOUBLE")).sql()
'CAST(5 AS DOUBLE)'
Arguments:
  • name: the name of the function to build.
  • args: the args used to instantiate the function of interest.
  • copy: whether to copy the argument expressions.
  • dialect: the source dialect.
  • kwargs: the kwargs used to instantiate the function of interest.
Note:

The arguments args and kwargs are mutually exclusive.

Returns:

An instance of the function of interest, or an anonymous function, if name doesn't correspond to an existing sqlglot.expressions.Func class.

def case( expression: Union[int, str, sqlglot.expressions.core.Expr, NoneType] = None, copy: bool = True, **opts: typing_extensions.Unpack[sqlglot._typing.ParserArgs]) -> sqlglot.expressions.functions.Case:
1002def case(
1003    expression: ExpOrStr | None = None,
1004    copy: bool = True,
1005    **opts: Unpack[ParserArgs],
1006) -> Case:
1007    """
1008    Initialize a CASE statement.
1009
1010    Example:
1011        case().when("a = 1", "foo").else_("bar")
1012
1013    Args:
1014        expression: Optionally, the input expression (not all dialects support this)
1015        copy: whether to copy the argument expressions.
1016        **opts: Extra keyword arguments for parsing `expression`
1017    """
1018    if expression is not None:
1019        this = maybe_parse(expression, copy=copy, **opts)
1020    else:
1021        this = None
1022    return Case(this=this, ifs=[])

Initialize a CASE statement.

Example:

case().when("a = 1", "foo").else_("bar")

Arguments:
  • expression: Optionally, the input expression (not all dialects support this)
  • copy: whether to copy the argument expressions.
  • **opts: Extra keyword arguments for parsing expression
def array( *expressions: Union[int, str, sqlglot.expressions.core.Expr], copy: bool = True, dialect: Union[str, sqlglot.dialects.Dialect, type[sqlglot.dialects.Dialect], NoneType] = None, **kwargs: typing_extensions.Unpack[sqlglot._typing.ParserNoDialectArgs]) -> sqlglot.expressions.array.Array:
1025def array(
1026    *expressions: ExpOrStr,
1027    copy: bool = True,
1028    dialect: DialectType = None,
1029    **kwargs: Unpack[ParserNoDialectArgs],
1030) -> Array:
1031    """
1032    Returns an array.
1033
1034    Examples:
1035        >>> array(1, 'x').sql()
1036        'ARRAY(1, x)'
1037
1038    Args:
1039        expressions: the expressions to add to the array.
1040        copy: whether to copy the argument expressions.
1041        dialect: the source dialect.
1042        kwargs: the kwargs used to instantiate the function of interest.
1043
1044    Returns:
1045        An array expression.
1046    """
1047    return Array(
1048        expressions=[
1049            maybe_parse(expression, copy=copy, dialect=dialect, **kwargs)
1050            for expression in expressions
1051        ]
1052    )

Returns an array.

Examples:
>>> array(1, 'x').sql()
'ARRAY(1, x)'
Arguments:
  • expressions: the expressions to add to the array.
  • copy: whether to copy the argument expressions.
  • dialect: the source dialect.
  • kwargs: the kwargs used to instantiate the function of interest.
Returns:

An array expression.

def tuple_( *expressions: Union[int, str, sqlglot.expressions.core.Expr], copy: bool = True, dialect: Union[str, sqlglot.dialects.Dialect, type[sqlglot.dialects.Dialect], NoneType] = None, **kwargs: typing_extensions.Unpack[sqlglot._typing.ParserNoDialectArgs]) -> sqlglot.expressions.query.Tuple:
1055def tuple_(
1056    *expressions: ExpOrStr,
1057    copy: bool = True,
1058    dialect: DialectType = None,
1059    **kwargs: Unpack[ParserNoDialectArgs],
1060) -> Tuple:
1061    """
1062    Returns an tuple.
1063
1064    Examples:
1065        >>> tuple_(1, 'x').sql()
1066        '(1, x)'
1067
1068    Args:
1069        expressions: the expressions to add to the tuple.
1070        copy: whether to copy the argument expressions.
1071        dialect: the source dialect.
1072        kwargs: the kwargs used to instantiate the function of interest.
1073
1074    Returns:
1075        A tuple expression.
1076    """
1077    return Tuple(
1078        expressions=[
1079            maybe_parse(expression, copy=copy, dialect=dialect, **kwargs)
1080            for expression in expressions
1081        ]
1082    )

Returns an tuple.

Examples:
>>> tuple_(1, 'x').sql()
'(1, x)'
Arguments:
  • expressions: the expressions to add to the tuple.
  • copy: whether to copy the argument expressions.
  • dialect: the source dialect.
  • kwargs: the kwargs used to instantiate the function of interest.
Returns:

A tuple expression.

def true() -> sqlglot.expressions.core.Boolean:
1085def true() -> Boolean:
1086    """
1087    Returns a true Boolean expression.
1088    """
1089    return Boolean(this=True)

Returns a true Boolean expression.

def false() -> sqlglot.expressions.core.Boolean:
1092def false() -> Boolean:
1093    """
1094    Returns a false Boolean expression.
1095    """
1096    return Boolean(this=False)

Returns a false Boolean expression.

def null() -> sqlglot.expressions.core.Null:
1099def null() -> Null:
1100    """
1101    Returns a Null expression.
1102    """
1103    return Null()

Returns a Null expression.

def apply_index_offset( this: sqlglot.expressions.core.Expr, expressions: list[~E], offset: int, dialect: Union[str, sqlglot.dialects.Dialect, type[sqlglot.dialects.Dialect], NoneType] = None) -> list[~E]:
1106def apply_index_offset(
1107    this: Expr,
1108    expressions: list[E],
1109    offset: int,
1110    dialect: DialectType = None,
1111) -> list[E]:
1112    if not offset or len(expressions) != 1:
1113        return expressions
1114
1115    expression = expressions[0]
1116
1117    from sqlglot.optimizer.annotate_types import annotate_types
1118    from sqlglot.optimizer.simplify import simplify
1119
1120    if not this.type:
1121        annotate_types(this, dialect=dialect)
1122
1123    if t.cast(DataType, this.type).this not in (
1124        DType.UNKNOWN,
1125        DType.ARRAY,
1126    ):
1127        return expressions
1128
1129    if not expression.type:
1130        annotate_types(expression, dialect=dialect)
1131
1132    if t.cast(DataType, expression.type).this in DataType.INTEGER_TYPES:
1133        logger.info("Applying array index offset (%s)", offset)
1134        expression = simplify(expression + offset)
1135        return [expression]
1136
1137    return expressions
NONNULL_CONSTANTS = (<class 'sqlglot.expressions.core.Literal'>, <class 'sqlglot.expressions.core.Boolean'>)