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

Cast an expression to a data type.

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

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

    For example, if :expression='CAST(x as DATETIME)' and :to=Type.TIMESTAMP, but in the target dialect DATETIME is mapped to TIMESTAMP, then we will NOT return CAST(x (as DATETIME) as TIMESTAMP) and instead just return the original 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:
514def table_(
515    table: Identifier | str,
516    db: Identifier | str | None = None,
517    catalog: Identifier | str | None = None,
518    quoted: bool | None = None,
519    alias: Identifier | str | None = None,
520) -> Table:
521    """Build a Table.
522
523    Args:
524        table: Table name.
525        db: Database name.
526        catalog: Catalog name.
527        quote: Whether to force quotes on the table's identifiers.
528        alias: Table's alias.
529
530    Returns:
531        The new Table instance.
532    """
533    return Table(
534        this=to_identifier(table, quoted=quoted) if table else None,
535        db=to_identifier(db, quoted=quoted) if db else None,
536        catalog=to_identifier(catalog, quoted=quoted) if catalog else None,
537        alias=TableAlias(this=to_identifier(alias)) if alias else None,
538    )

Build a Table.

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

The new Table instance.

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

Build VALUES statement.

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

Values: the Values expression object

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

Build a SQL variable.

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

The new variable node.

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:
598def rename_table(
599    old_name: str | Table,
600    new_name: str | Table,
601    dialect: DialectType = None,
602) -> Alter:
603    """Build ALTER TABLE... RENAME... expression
604
605    Args:
606        old_name: The old name of the table
607        new_name: The new name of the table
608        dialect: The dialect to parse the table.
609
610    Returns:
611        Alter table expression
612    """
613    old_table = to_table(old_name, dialect=dialect)
614    new_table = to_table(new_name, dialect=dialect)
615    return Alter(
616        this=old_table,
617        kind="TABLE",
618        actions=[
619            AlterRename(this=new_table),
620        ],
621    )

Build ALTER TABLE... RENAME... expression

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

Alter table expression

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:
624def rename_column(
625    table_name: str | Table,
626    old_column_name: str | Column,
627    new_column_name: str | Column,
628    exists: bool | None = None,
629    dialect: DialectType = None,
630) -> Alter:
631    """Build ALTER TABLE... RENAME COLUMN... expression
632
633    Args:
634        table_name: Name of the table
635        old_column: The old name of the column
636        new_column: The new name of the column
637        exists: Whether to add the `IF EXISTS` clause
638        dialect: The dialect to parse the table/column.
639
640    Returns:
641        Alter table expression
642    """
643    table = to_table(table_name, dialect=dialect)
644    old_column = to_column(old_column_name, dialect=dialect)
645    new_column = to_column(new_column_name, dialect=dialect)
646    return Alter(
647        this=table,
648        kind="TABLE",
649        actions=[
650            RenameColumn(this=old_column, to=new_column, exists=exists),
651        ],
652    )

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

Arguments:
  • table_name: Name of the table
  • old_column: The old name of the column
  • new_column: The new name of the column
  • exists: Whether to add the IF 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:
655def replace_children(
656    expression: Expr,
657    fun: t.Callable[Concatenate[Expr, P], object],
658    *args: P.args,
659    **kwargs: P.kwargs,
660) -> None:
661    """
662    Replace children of an expression with the result of a lambda fun(child) -> exp.
663    """
664    for k, v in tuple(expression.args.items()):
665        is_list_arg = type(v) is list
666
667        child_nodes = v if is_list_arg else [v]
668        new_child_nodes = []
669
670        for cn in child_nodes:
671            if isinstance(cn, Expr):
672                for child_node in ensure_collection(fun(cn, *args, **kwargs)):
673                    new_child_nodes.append(child_node)
674            else:
675                new_child_nodes.append(cn)
676
677        if is_list_arg:
678            expression.set(k, new_child_nodes)
679        else:
680            expression.set(k, seq_get(new_child_nodes, 0))

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

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

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

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

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

Find all tables referenced in a query.

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

A set of all the tables.

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

Return all table names referenced through columns in an expression.

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

A list of unique names.

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

Get the full name of a table as a string.

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

The table name.

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:
786def normalize_table_name(table: str | Table, dialect: DialectType = None, copy: bool = True) -> str:
787    """Returns a case normalized table name without quotes.
788
789    Args:
790        table: the table to normalize
791        dialect: the dialect to use for normalization rules
792        copy: whether to copy the expression.
793
794    Examples:
795        >>> normalize_table_name("`A-B`.c", dialect="bigquery")
796        'A-B.c'
797    """
798    from sqlglot.optimizer.normalize_identifiers import normalize_identifiers
799
800    return ".".join(
801        p.name
802        for p in normalize_identifiers(
803            to_table(table, dialect=dialect, copy=copy), dialect=dialect
804        ).parts
805    )

Returns a case normalized table name without quotes.

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

Replace all tables in expression according to the mapping.

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

The mapped expression.

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

Replace placeholders in an expression.

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

The mapped expression.

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

Transforms an expression by expanding all referenced sources into subqueries.

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

The transformed expression.

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

Returns a Func expression.

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

The arguments 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:
 997def case(
 998    expression: ExpOrStr | None = None,
 999    copy: bool = True,
1000    **opts: Unpack[ParserArgs],
1001) -> Case:
1002    """
1003    Initialize a CASE statement.
1004
1005    Example:
1006        case().when("a = 1", "foo").else_("bar")
1007
1008    Args:
1009        expression: Optionally, the input expression (not all dialects support this)
1010        copy: whether to copy the argument expressions.
1011        **opts: Extra keyword arguments for parsing `expression`
1012    """
1013    if expression is not None:
1014        this = maybe_parse(expression, copy=copy, **opts)
1015    else:
1016        this = None
1017    return Case(this=this, ifs=[])

Initialize a CASE statement.

Example:

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

Arguments:
  • expression: Optionally, the input expression (not all dialects support this)
  • copy: whether to copy the argument expressions.
  • **opts: Extra keyword arguments for parsing expression
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:
1020def array(
1021    *expressions: ExpOrStr,
1022    copy: bool = True,
1023    dialect: DialectType = None,
1024    **kwargs: Unpack[ParserNoDialectArgs],
1025) -> Array:
1026    """
1027    Returns an array.
1028
1029    Examples:
1030        >>> array(1, 'x').sql()
1031        'ARRAY(1, x)'
1032
1033    Args:
1034        expressions: the expressions to add to the array.
1035        copy: whether to copy the argument expressions.
1036        dialect: the source dialect.
1037        kwargs: the kwargs used to instantiate the function of interest.
1038
1039    Returns:
1040        An array expression.
1041    """
1042    return Array(
1043        expressions=[
1044            maybe_parse(expression, copy=copy, dialect=dialect, **kwargs)
1045            for expression in expressions
1046        ]
1047    )

Returns an array.

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

An array expression.

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:
1050def tuple_(
1051    *expressions: ExpOrStr,
1052    copy: bool = True,
1053    dialect: DialectType = None,
1054    **kwargs: Unpack[ParserNoDialectArgs],
1055) -> Tuple:
1056    """
1057    Returns an tuple.
1058
1059    Examples:
1060        >>> tuple_(1, 'x').sql()
1061        '(1, x)'
1062
1063    Args:
1064        expressions: the expressions to add to the tuple.
1065        copy: whether to copy the argument expressions.
1066        dialect: the source dialect.
1067        kwargs: the kwargs used to instantiate the function of interest.
1068
1069    Returns:
1070        A tuple expression.
1071    """
1072    return Tuple(
1073        expressions=[
1074            maybe_parse(expression, copy=copy, dialect=dialect, **kwargs)
1075            for expression in expressions
1076        ]
1077    )

Returns an tuple.

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

A tuple expression.

def true() -> sqlglot.expressions.core.Boolean:
1080def true() -> Boolean:
1081    """
1082    Returns a true Boolean expression.
1083    """
1084    return Boolean(this=True)

Returns a true Boolean expression.

def false() -> sqlglot.expressions.core.Boolean:
1087def false() -> Boolean:
1088    """
1089    Returns a false Boolean expression.
1090    """
1091    return Boolean(this=False)

Returns a false Boolean expression.

def null() -> sqlglot.expressions.core.Null:
1094def null() -> Null:
1095    """
1096    Returns a Null expression.
1097    """
1098    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]:
1101def apply_index_offset(
1102    this: Expr,
1103    expressions: list[E],
1104    offset: int,
1105    dialect: DialectType = None,
1106) -> list[E]:
1107    if not offset or len(expressions) != 1:
1108        return expressions
1109
1110    expression = expressions[0]
1111
1112    from sqlglot.optimizer.annotate_types import annotate_types
1113    from sqlglot.optimizer.simplify import simplify
1114
1115    if not this.type:
1116        annotate_types(this, dialect=dialect)
1117
1118    if t.cast(DataType, this.type).this not in (
1119        DType.UNKNOWN,
1120        DType.ARRAY,
1121    ):
1122        return expressions
1123
1124    if not expression.type:
1125        annotate_types(expression, dialect=dialect)
1126
1127    if t.cast(DataType, expression.type).this in DataType.INTEGER_TYPES:
1128        logger.info("Applying array index offset (%s)", offset)
1129        expression = simplify(expression + offset)
1130        return [expression]
1131
1132    return expressions
NONNULL_CONSTANTS = (<class 'sqlglot.expressions.core.Literal'>, <class 'sqlglot.expressions.core.Boolean'>)