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

Parses a given string into an identifier.

Arguments:
  • name: The name to parse into an identifier.
  • dialect: The dialect to parse against.
Returns:

The identifier ast node.

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:
339def to_interval(interval: str | Expr) -> Interval:
340    """Builds an interval expression from a string like '1 day' or '5 months'."""
341    if isinstance(interval, Literal):
342        if not interval.is_string:
343            raise ValueError("Invalid interval string.")
344
345        interval = interval.this
346
347    interval = maybe_parse(f"INTERVAL {interval}")
348    assert isinstance(interval, Interval)
349    return interval

Builds an interval expression from a string like '1 day' or '5 months'.

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:
352def to_table(
353    sql_path: str | Table, dialect: DialectType = None, copy: bool = True, **kwargs: object
354) -> Table:
355    """
356    Create a table expression from a `[catalog].[schema].[table]` sql path. Catalog and schema are optional.
357    If a table is passed in then that table is returned.
358
359    Args:
360        sql_path: a `[catalog].[schema].[table]` string.
361        dialect: the source dialect according to which the table name will be parsed.
362        copy: Whether to copy a table if it is passed in.
363        kwargs: the kwargs to instantiate the resulting `Table` expression with.
364
365    Returns:
366        A table expression.
367    """
368    if isinstance(sql_path, Table):
369        return maybe_copy(sql_path, copy=copy)
370
371    try:
372        table = maybe_parse(sql_path, into=Table, dialect=dialect)
373    except ParseError:
374        catalog, db, this = split_num_words(sql_path, ".", 3)
375
376        if not this:
377            raise
378
379        table = table_(this, db=db, catalog=catalog)
380
381    return table.set_kwargs(kwargs)

Create a table expression from a [catalog].[schema].[table] sql path. Catalog and schema are optional. If a table is passed in then that table is returned.

Arguments:
  • sql_path: a [catalog].[schema].[table] string.
  • dialect: the source dialect according to which the table name will be parsed.
  • copy: Whether to copy a table if it is passed in.
  • kwargs: the kwargs to instantiate the resulting 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:
384def to_column(
385    sql_path: str | Column,
386    quoted: bool | None = None,
387    dialect: DialectType = None,
388    copy: bool = True,
389    **kwargs: t.Any,
390) -> Column | Dot:
391    """
392    Create a column from a `[table].[column]` sql path. Table is optional.
393    If a column is passed in then that column is returned.
394
395    Args:
396        sql_path: a `[table].[column]` string.
397        quoted: Whether or not to force quote identifiers.
398        dialect: the source dialect according to which the column name will be parsed.
399        copy: Whether to copy a column if it is passed in.
400        kwargs: the kwargs to instantiate the resulting `Column` expression with.
401
402    Returns:
403        A column expression.
404    """
405    if isinstance(sql_path, Column):
406        return maybe_copy(sql_path, copy=copy)
407
408    try:
409        col = maybe_parse(sql_path, into=Column, dialect=dialect)
410    except ParseError:
411        return column(*reversed(sql_path.split(".")), quoted=quoted, **kwargs)
412
413    for k, v in kwargs.items():
414        col.set(k, v)
415
416    if quoted:
417        for i in col.find_all(Identifier):
418            i.set("quoted", True)
419
420    return col

Create a column from a [table].[column] sql path. Table is optional. If a column is passed in then that column is returned.

Arguments:
  • sql_path: a [table].[column] string.
  • quoted: Whether or not to force quote identifiers.
  • dialect: the source dialect according to which the column name will be parsed.
  • copy: Whether to copy a column if it is passed in.
  • kwargs: the kwargs to instantiate the resulting 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:
423def subquery(
424    expression: ExpOrStr,
425    alias: Identifier | str | None = None,
426    dialect: DialectType = None,
427    copy: bool = True,
428    **opts: Unpack[ParserNoDialectArgs],
429) -> Select:
430    """
431    Build a subquery expression that's selected from.
432
433    Example:
434        >>> subquery('select x from tbl', 'bar').select('x').sql()
435        'SELECT x FROM (SELECT x FROM tbl) AS bar'
436
437    Args:
438        expression: the SQL code strings to parse.
439            If an Expr instance is passed, this is used as-is.
440        alias: the alias name to use.
441        dialect: the dialect used to parse the input expression.
442        **opts: other options to use to parse the input expressions.
443
444    Returns:
445        A new Select instance with the subquery expression included.
446    """
447    expr = (
448        maybe_parse(expression, dialect=dialect, **opts).assert_is(Query).subquery(alias, copy=copy)
449    )
450    return Select().from_(expr, dialect=dialect, **opts)

Build a subquery expression that's selected from.

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

A new Select instance with the subquery expression included.

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

Cast an expression to a data type.

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

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

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

Build a Table.

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

The new Table instance.

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

Build VALUES statement.

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

Values: the Values expression object

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

Build a SQL variable.

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

The new variable node.

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

Build ALTER TABLE... RENAME... expression

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

Alter table expression

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

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

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

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

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

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

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

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

Find all tables referenced in a query.

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

A set of all the tables.

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

Return all table names referenced through columns in an expression.

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

A list of unique names.

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

Get the full name of a table as a string.

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

The table name.

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

Returns a case normalized table name without quotes.

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

Replace all tables in expression according to the mapping.

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

The mapped expression.

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

Replace placeholders in an expression.

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

The mapped expression.

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

Transforms an expression by expanding all referenced sources into subqueries.

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

The transformed expression.

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

Returns a Func expression.

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

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

Initialize a CASE statement.

Example:

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

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

Returns an array.

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

An array expression.

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

Returns an tuple.

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

A tuple expression.

def true() -> sqlglot.expressions.core.Boolean:
1075def true() -> Boolean:
1076    """
1077    Returns a true Boolean expression.
1078    """
1079    return Boolean(this=True)

Returns a true Boolean expression.

def false() -> sqlglot.expressions.core.Boolean:
1082def false() -> Boolean:
1083    """
1084    Returns a false Boolean expression.
1085    """
1086    return Boolean(this=False)

Returns a false Boolean expression.

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