sqlglot

    A SQL parser, transpiler and optimizer: a MoonBit port of sqlglot

    sql
    parser
    transpiler
    Download zip
    Author
    Version
    0.1.0
    License
    MIT
    Last updated
    21 hours ago
    Downloads
    2

    #sqlglot.mbt

    A MoonBit port of sqlglot, the SQL parser, transpiler and optimizer. The port aims to match the Python library's behaviour exactly. Its test suites are generated from the Python implementation and test-suite.

    let sql = @sqlglot.transpile(
    "SELECT EPOCH_MS(1618088028295)",
    read="duckdb",
    write="hive",
    )[0]
    // SELECT FROM_UNIXTIME(1618088028295 / POW(10, 3))

    let ast = @sqlglot.parse_one("SELECT a FROM t WHERE b > 1", read="postgres")
    let out = @sqlglot.generate(ast, dialect="snowflake", pretty=true)

    #Status

    ComponentStatus
    Tokenizer, parser, generator (base dialect)Complete: identical ASTs and SQL to Python on all base fixtures (5,501 ASTs, 5,962 round trips)
    Dialects (34)Complete: all 16,070 Validator cases and 75 error cases (class and message) extracted from tests/dialects match Python; the direct assertions of all 249 test methods that make them are hand-ported (src/dialect_unit_tests, coverage in docs/dialect-test-manifest.md)
    Optimizer (qualify, annotate_types, simplify, all rules), schemaComplete: all optimizer fixtures, TPC-H and TPC-DS match Python, including error classes and messages
    Lineage, diff, plannerComplete: lineage 80/80, diff 24/24, planner 27/27 recorded Python results, plus hand-ported identity, callback, copy= and matchings tests
    Expression API, builders, transformsComplete: unit tests ported from test_expressions, test_build, test_transforms, test_parser, test_transpile, test_errors, test_tokens, test_jsonpath and others
    ExecutorComplete: generates Python code like sqlglot and evaluates it with a built-in interpreter; test_executor (445 recorded cases) and 57 TPC-DS queries match Python
    Serde, anonymize, CLIComplete (src/core/serde.mbt, src/anonymize, src/cli, native binary in src/cmd/sqlglot)

    #Known differences

    • Integers are 64-bit (Python's are unbounded).
    • Things that need Python runtime features aren't supported, such as defining new expression classes at runtime.
    • The port stores no None argument values in Expr::args. An argument given as None at construction (mk(Column, [("db", null_arg)])) is remembered only as a key. Python's "db" in e.args is Expr::has_key, and list(e.args) is Expr::arg_keys. get, has, equality, hashing, serde and SQL generation ignore the key, as Python ignores None values. set(key, None) removes the key, as in Python. Use has for Python's truthiness of e.args.get(key), get(key) is None for is None, and has_key for in. False, 0, "" and [] are stored and behave as in Python: False and [] compare equal to a missing argument, while 0 and "" don't (except in Literal and Identifier, which hash raw values).
    • None elements of list arguments are dropped (Array[Expr?] arguments lose their None entries). Python keeps them, which changes equality, serde and SQL. Python's generator skips a None element but still writes the separator before it, so Tuple(expressions=[1, None]) is (1, ) in Python and (1) in the port. List elements that generate no SQL but aren't None, such as "", degrade exactly as in Python.
    • A Literal without its required is_string argument is generated as a number. Python raises KeyError.
    • Errors are variants of SqlglotError. Python raises some builtin exceptions instead (for example AttributeError from Dialect.get_or_raise, or a plain SqlglotError from lineage). The port raises its closest variant, usually ValueError, with Python's message.

    The argument-value differences are checked against recorded Python behaviour (missing, None, False, True, 0, 1, "", [] and SQL NULL, through construction, set, has/get, text, equality, hashing, copy, serde and SQL generation) by src/unit_tests_b/none_matrix_test.mbt. The expected values are generated by tools/gen_none_matrix.py.

    #Layout

    • src/core: the AST (Expr, with a generated Kind enum for every Python expression class), tokenizer, parser, generator, transforms, builders, and the dialect infrastructure and shared dialect helpers (the module-level functions in dialects/dialect.py).
    • src/dialects/<name>: one package per dialect.
      • gen_config.mbt (generated) holds the dialect's data class attributes, stored as diffs from the parent dialect.
      • tokenizer.mbt, parser.mbt and generator.mbt hold the hand-ported callables and method overrides.
      • dialect.mbt (generated) derives the dialect from its parent and registers it.
    • src/optimizer: schema, scope, the optimizer rules, optimize, and per-dialect type annotators (sqlglot/typing). It installs the real annotate_types and simplify into core's hooks.
    • src/lineage, src/diff, src/planner, src/executor, src/anonymize: ports of the corresponding Python modules. src/cli and src/cmd/sqlglot provide the command-line tool.
    • src/ (package bobzhang/sqlglot): the facade (transpile, parse_one, parse, generate, dialect). It imports and registers all dialects.
    • src/tests, src/generator_tests, src/dialect_tests: conformance suites generated from Python. src/dialect_tests is generated by tools/extract_dialect_tests.py (run with --manifest) followed by tools/gen_dialect_fixtures.py cases.jsonl manifest.json. The extraction fails if any Python test fails under instrumentation. The generation fails if a test method's direct assertions are neither ported to src/dialect_unit_tests nor excluded.
    • tools/: generators for metadata, configuration and fixtures. They run against the Python checkout in .repos/sqlglot.

    #How Python features map to MoonBit

    • Expression subclasses become a single dynamic Expr { kind, args }.
      • Python isinstance(e, exp.Foo) becomes e.kind.is_a(Foo), which follows the generated MRO tables.
      • Python type(e) is exp.Foo becomes e.kind == Foo.
    • Dialect subclassing: Dialect::subclass(parent, name, configure) copies the parent's configuration and its function tables (FUNCTIONS, *_PARSERS, TRANSFORMS, method overrides), then applies the child's changes.
    • Overridden methods go through typed hook tables, ParserHooks and GeneratorHooks.
    • super(): a child dialect captures its parent's implementation when it is configured. See docs/review-02-dialects.md.
    • Unicode: str.upper/lower/casefold (full mappings, ß -> SS, Final_Sigma) and the str.is* / re (\w, \d, \s, re.IGNORECASE) character classes use tables generated from Python's Unicode database (tools/gen_unicode_tables.py -> src/core/gen_unicode.mbt, helpers in src/core/unicode.mbt). Strings are indexed by code point, as in Python.
    • Integers: SQL number literals stay text, and constant folding uses big integers (as do relativedelta date shifts), so they behave like Python at any size. Integers that are stored as host values are Int64: AST arguments (Value::Int, e.g. JSON path subscripts and serde payloads), PyInt (Expr.to_py()) and the executor's ints. Where Python would hold an integer outside Int64 there, the port raises an error whose message mentions "Int64 range" (@core.int64_range_error; an OverflowError in the executor) instead of wrapping. src/robust_tests checks both against Python (tools/gen_unicode_fixtures.py, tools/gen_numeric_fixtures.py).

    #Development

    moon check moon test -p bobzhang/sqlglot/tests # base parser/generator conformance moon test -p bobzhang/sqlglot/generator_tests # generator conformance moon test -p bobzhang/sqlglot/dialect_tests # per-dialect conformance (prints DIALECT <module>: ...) moon test -p bobzhang/sqlglot/dialect_tests -F "*dialect snowflake*" moon test # everything (845 tests)

    Scaling benchmarks (not part of moon test) time adversarial shapes at doubling sizes (wide AND/OR, long IN lists, deep nesting, many CTEs, long literals, huge SELECT lists, pretty printing, ...) and print the growth ratio per doubling:

    moon run src/bench --release [--target native] -- [case] [op] [size] moon run src/bench --release -- many_ctes rules 512 # per optimizer rule

    Regenerate fixtures and configuration with the scripts in tools/. Each script's docstring describes its inputs. They need a Python environment with sqlglot's test dependencies, such as pytz for the BigQuery tests.

    #bobzhang/sqlglot

    The facade package of the MoonBit port of sqlglot: a SQL parser, transpiler, optimizer and engine. Importing only this package is enough for the common workflows below: it registers all built-in dialects and re-exports the principal types (Expr, Kind, Dialect, ErrorLevel, SqlglotError, DType, Generator, IntoPy, MappingSchema, SchemaNode, Table, TableData, ...).

    import { "bobzhang/sqlglot", }

    Every example in this file is compiled and run by moon test.

    #Transpiling

    transpile parses SQL in one dialect (read) and generates it in another (write):

    ///|
    test "transpile between dialects" {
    inspect(
    @sqlglot.transpile(
    "SELECT EPOCH_MS(1618088028295)",
    read="duckdb",
    write="hive",
    )[0],
    content="SELECT FROM_UNIXTIME(1618088028295 / POW(10, 3))",
    )
    inspect(
    @sqlglot.transpile(
    "SELECT STRFTIME(x, '%y-%-m-%S')",
    read="duckdb",
    write="hive",
    )[0],
    content="SELECT DATE_FORMAT(x, 'yy-M-ss')",
    )
    }

    Generator options are labelled arguments; identify and normalize_functions take the Identify and NormalizeFunctions enums:

    ///|
    test "generator options" {
    inspect(
    @sqlglot.transpile("SELECT a FROM t WHERE b = 1", write="spark", identify=Always)[0],
    content="SELECT `a` FROM `t` WHERE `b` = 1",
    )
    inspect(
    @sqlglot.transpile(
    "SELECT cardinality(x) FROM t",
    read="presto",
    write="presto",
    normalize_functions=Lower,
    )[0],
    content="SELECT cardinality(x) FROM t",
    )
    inspect(
    @sqlglot.transpile(
    "WITH baz AS (SELECT a, c FROM foo WHERE a = 1) SELECT f.a, b.b, baz.c, CAST(\"b\".\"a\" AS REAL) d FROM foo f JOIN bar b ON f.a = b.a LEFT JOIN baz ON f.a = baz.a",
    write="spark",
    identify=Always,
    pretty=true,
    )[0],
    content=(
    #|WITH `baz` AS (
    #| SELECT
    #| `a`,
    #| `c`
    #| FROM `foo`
    #| WHERE
    #| `a` = 1
    #|)
    #|SELECT
    #| `f`.`a`,
    #| `b`.`b`,
    #| `baz`.`c`,
    #| CAST(`b`.`a` AS FLOAT) AS `d`
    #|FROM `foo` AS `f`
    #|JOIN `bar` AS `b`
    #| ON `f`.`a` = `b`.`a`
    #|LEFT JOIN `baz`
    #| ON `f`.`a` = `baz`.`a`
    ),
    )
    }

    #Parsing and errors

    parse_one returns the syntax tree (Expr) of a statement; generate turns it back into SQL. Errors are SqlglotErrors:

    ///|
    test "parse, inspect and generate" {
    let ast : @sqlglot.Expr = @sqlglot.parse_one(
    "SELECT a, b + 1 AS c FROM t WHERE a > 1",
    )
    inspect(
    ast.find_all([Column]).map(c => c.name()).collect().join(", "),
    content="a, b, a",
    )
    inspect(
    @sqlglot.generate(ast, dialect="spark"),
    content="SELECT a, b + 1 AS c FROM t WHERE a > 1",
    )
    }

    ///|
    test "parse errors" {
    try @sqlglot.parse_one("SELECT foo FROM (SELECT baz FROM t") catch {
    @sqlglot.SqlglotError::ParseError(_, errors) => {
    let e = errors[0]
    inspect("\{e.description} at \{e.line}:\{e.col}", content="Expecting ) at 1:34")
    }
    _ => fail("expected a parse error")
    } noraise {
    _ => fail("expected a parse error")
    }
    }

    #Building queries

    Builders take SQL strings or expressions; mixed arguments are passed as Array[&@sqlglot.IntoPy]. Like Python, builder methods return a modified copy (pass copy=false to modify in place), so several queries can be derived from one base:

    ///|
    test "build queries" {
    let columns : Array[&@sqlglot.IntoPy] = [@sqlglot.column("a"), "b + 1 AS c"]
    let base = @sqlglot.select(columns).from_("t")
    let q1 = base.where_(["a > 1"])
    let conditions : Array[&@sqlglot.IntoPy] = [
    @sqlglot.condition("a < 0"),
    "c IS NOT NULL",
    ]
    let q2 = base
    .where_([@sqlglot.and_(conditions)])
    .order_by(["c"])
    .limit_(10)
    inspect(@sqlglot.generate(base), content="SELECT a, b + 1 AS c FROM t")
    inspect(@sqlglot.generate(q1), content="SELECT a, b + 1 AS c FROM t WHERE a > 1")
    inspect(
    @sqlglot.generate(q2),
    content="SELECT a, b + 1 AS c FROM t WHERE a < 0 AND NOT c IS NULL ORDER BY c LIMIT 10",
    )
    let x = @sqlglot.column("x").eq_(1).or_(["y = 2"])
    inspect(
    @sqlglot.generate(
    @sqlglot.select(["x"]).from_("tbl").where_([x]),
    dialect="duckdb",
    ),
    content="SELECT x FROM tbl WHERE x = 1 OR y = 2",
    )
    }

    #Optimizing

    optimize qualifies, normalizes and simplifies a query given a schema:

    ///|
    test "optimize" {
    let schema : Map[String, @sqlglot.SchemaNode] = {
    "x": Dict({
    "A": Type("INT"),
    "B": Type("INT"),
    "C": Type("INT"),
    "D": Type("INT"),
    "Z": Type("STRING"),
    }),
    }
    let optimized = @sqlglot.optimize(
    "SELECT A OR (B OR (C AND D)) FROM x WHERE Z = date '2021-01-01' + INTERVAL '1' month OR 1 = 0",
    schema~,
    )
    inspect(
    @sqlglot.generate(optimized, pretty=true),
    content=(
    #|SELECT
    #| (
    #| "x"."a" <> 0 OR "x"."b" <> 0 OR "x"."c" <> 0
    #| )
    #| AND (
    #| "x"."a" <> 0 OR "x"."b" <> 0 OR "x"."d" <> 0
    #| ) AS "_col_0"
    #|FROM "x" AS "x"
    #|WHERE
    #| CAST("x"."z" AS DATE) = CAST('2021-02-01' AS DATE)
    ),
    )
    }

    #Executing

    execute runs a query against in-memory tables (Python value semantics):

    ///|
    test "execute" {
    let tables : Map[String, @sqlglot.TableData] = {
    "sushi": Records([[("id", Int(1)), ("price", Float(1.0))], [("id", Int(2)), ("price", Float(2.0))]]),
    "order_items": Records([
    [("sushi_id", Int(1)), ("order_id", Int(1))],
    [("sushi_id", Int(1)), ("order_id", Int(1))],
    [("sushi_id", Int(2)), ("order_id", Int(1))],
    [("sushi_id", Int(2)), ("order_id", Int(2))],
    ]),
    "orders": Records([
    [("id", Int(1)), ("user_id", Int(1))],
    [("id", Int(2)), ("user_id", Int(2))],
    ]),
    }
    let result : @sqlglot.Table = @sqlglot.execute(
    (
    #|SELECT o.user_id, SUM(s.price) AS price
    #|FROM orders o
    #|JOIN order_items i ON o.id = i.order_id
    #|JOIN sushi s ON i.sushi_id = s.id
    #|GROUP BY o.user_id
    #|ORDER BY o.user_id
    ),
    tables~,
    )
    inspect(result.columns.join(", "), content="user_id, price")
    inspect(
    result,
    content=(
    #|user_id price
    #| 1 4.0
    #| 2 2.0
    ),
    )
    }

    DType

    Dialect

    A SQL dialect: the Python Dialect class plus its Tokenizer, Parser and Generator configuration.

    ErrorLevel

    ExecuteError

    Raised when the execution of a plan fails (Python sqlglot.errors.ExecuteError); cause is the underlying error (Python __cause__).

    ExecutorValue

    using @bobzhang/sqlglot/executor { type Value as ExecutorValue }

    A value of a table row in the executor (Python value semantics).

    Expr

    A node of the SQL syntax tree.

    Generator

    Converts a given syntax tree to the corresponding SQL string.

    IntoPy

    Conversion of MoonBit values into host values (PyObj).

    Kind

    Every expression class of sqlglot, including abstract traits.

    MappingSchema

    Schema based on a nested mapping (Python MappingSchema).

    ParseErrorInfo

    Details of a single parse error.

    PyObj

    A host value, mirroring the Python objects that sqlglot's builder API accepts (ExpOrStr, and the values understood by exp.convert).

    SchemaNode

    A node of a nested schema mapping (Python's nested dicts of the schema).

    SqlglotError

    Errors raised by sqlglot.

    Table

    A simple columnar data structure: column names and rows of values.

    TableData

    The input data of execute: rows given as records, a Table, or a nested mapping of {db: {table: ...}}.

    Value

    An argument value of an expression.

    Identify

    pub(all) enum Identify {
    Never
    Always
    Safe
    Unsafe
    } derive(Eq,
    Debug
    )

    When identifiers should be quoted by the generator (Python identify).

    NormalizeFunctions

    pub(all) enum NormalizeFunctions {
    Upper
    Lower
    Keep
    } derive(Eq,
    Debug
    )

    How the generator normalizes function names (Python normalize_functions).

    alias_

    fn[T :
    IntoPy
    , A :
    IntoPy
    ] alias_(expression : T, alias : A, table? : Bool, table_columns? : Array[String], quoted? : Bool, dialect? : String, copy? : Bool) ->
    Expr
    raise
    SqlglotError

    exp.alias_(expression, alias, table=..., quoted=...). table creates a table alias; table_columns adds its column names (Python table=[...]).

    and_

    fn[T :
    IntoPy
    ] and_(expressions : Array[T], dialect? : String, copy? : Bool, wrap? : Bool) ->
    Expr
    raise
    SqlglotError

    exp.and_(*expressions)

    array

    exp.array(*expressions)

    case

    exp.case(expression)

    cast

    exp.cast(expression, to)

    column

    exp.column(col, table, db, catalog, fields=..., quoted=...)

    condition

    fn[T :
    IntoPy
    ] condition(expression : T, dialect? : String, copy? : Bool) ->
    Expr
    raise
    SqlglotError

    exp.condition(expression)

    datatype_build

    fn[T :
    IntoPy
    ] datatype_build(dtype : T, dialect? : String, udt? : Bool, copy? : Bool) ->
    Expr
    raise
    SqlglotError

    exp.DataType.build(dtype, dialect=..., udt=...): dtype may be a type string, a DataType expression or a DType (as @core.datatype_of(dtype)).

    datatype_is_type

    fn[T :
    IntoPy
    ] datatype_is_type(dt :
    Expr
    , dtypes : Array[T], check_nullable? : Bool) -> Bool raise
    SqlglotError

    DataType.is_type(*dtypes, check_nullable=...) for a DataType expression, with the types given as type strings or DataType expressions.

    delete

    exp.delete(table, where=..., returning=...)

    dialect

    Looks up a dialect by name ("" is the base sqlglot dialect).

    dialect_names

    let dialect_names : Array[String]

    Names of all built-in dialects.

    except_

    fn[T :
    IntoPy
    ] except_(expressions : Array[T], distinct? : Bool, dialect? : String, copy? : Bool) ->
    Expr
    raise
    SqlglotError

    exp.except_(*expressions, distinct=...)

    execute

    Run a sql query against data.

    • sql: a SQL statement (a string or an expression).
    • schema: the database schema, in one of the forms {table: {col: type}}, {db: {table: {col: type}}} or {catalog: {db: {table: {col: type}}}}. When it is omitted or empty, it is inferred from the first row of each table.
    • mapping_schema: the schema as a MappingSchema (takes precedence over schema).
    • dialect: the SQL dialect to apply during parsing (eg. "spark", "hive", "presto"); read is an alias of it.
    • tables: the tables to register.

    Returns a simple columnar data structure.

    expand

    exp.expand(expression, sources, dialect=...): expands all referenced sources into subqueries. Each source is given as a function providing the query on demand.

    from_

    exp.from_(expression)

    func

    exp.func(name, *args, **kwargs): an instance of the function name, or an anonymous function if name doesn't correspond to a known function.

    generate

    fn generate(expression :
    Expr
    , dialect? : String, copy? : Bool, pretty? : Bool, identify? : Identify, normalize? : Bool, pad? : Int, indent? : Int, normalize_functions? : NormalizeFunctions, unsupported_level? :
    ErrorLevel
    , max_unsupported? : Int, leading_comma? : Bool, max_text_width? : Int, comments? : Bool) -> String raise
    SqlglotError

    Generates SQL for expression in dialect dialect (Python Expr.sql).

    • pretty: whether to format the produced SQL (default: @core.default_pretty).
    • identify: when to quote identifiers (default: Never).
    • normalize: whether to normalize identifiers to lowercase.
    • pad, indent: indentation sizes of the pretty output.
    • normalize_functions: how to normalize function names (default: the dialect's).
    • unsupported_level, max_unsupported: how unsupported expressions are reported.
    • leading_comma, max_text_width, comments: further formatting options.

    insert

    fn[T :
    IntoPy
    , I :
    IntoPy
    ] insert(expression : T, into : I, columns? : Array[String], overwrite? : Bool, returning? : &
    IntoPy
    , dialect? : String, copy? : Bool) ->
    Expr
    raise
    SqlglotError

    exp.insert(expression, into, columns=..., overwrite=..., returning=...)

    intersect

    fn[T :
    IntoPy
    ] intersect(expressions : Array[T], distinct? : Bool, dialect? : String, copy? : Bool) ->
    Expr
    raise
    SqlglotError

    exp.intersect(*expressions, distinct=...)

    is_type

    fn[T :
    IntoPy
    ] is_type(expression :
    Expr
    , dtypes : Array[T], check_nullable? : Bool) -> Bool raise
    SqlglotError

    Expr.is_type(*dtypes): whether the type of expression (a DataType, the target type of a cast, or its annotated type) matches one of dtypes.

    maybe_parse

    fn[T :
    IntoPy
    ] maybe_parse(sql_or_expression : T, into? : Array[
    Kind
    ], dialect? : String, prefix? : String, copy? : Bool) ->
    Expr
    raise
    SqlglotError

    exp.maybe_parse(sql_or_expression, into=..., dialect=..., prefix=..., copy=...)

    merge

    exp.merge(*when_exprs, into=..., using=..., on=..., returning=...)

    normalize_table_name

    fn[T :
    IntoPy
    ] normalize_table_name(table : T, dialect? : String, copy? : Bool) -> String raise
    SqlglotError

    exp.normalize_table_name(table, dialect=...): a case normalized table name without quotes.

    not_

    exp.not_(expression)

    optimize

    fn[T :
    IntoPy
    ] optimize(expression : T, schema? : Map[String,
    SchemaNode
    ], mapping_schema? :
    MappingSchema
    , db? : String, catalog? : String, dialect? : String, infer_schema? : Bool, identify? : Bool, leave_tables_isolated? : Bool, validate_qualify_columns? : Bool, expand_stars? : Bool) ->
    Expr
    raise
    SqlglotError

    Rewrites expression (an expression, or SQL parsed in dialect) into an optimized form (Python sqlglot.optimizer.optimize). The expression is copied, not modified.

    • schema: the database schema, as {table: {col: type}}, {db: {table: {col: type}}} or {catalog: {db: {table: {col: type}}}} (see SchemaNode).
    • mapping_schema: the schema as a MappingSchema (takes precedence over schema).
    • db, catalog: the default database and catalog of unqualified tables.
    • identify: whether the final quote_identifiers rule quotes every identifier.
    • The other options are those of the optimizer rules (see @optimizer.optimize).

    or_

    fn[T :
    IntoPy
    ] or_(expressions : Array[T], dialect? : String, copy? : Bool, wrap? : Bool) ->
    Expr
    raise
    SqlglotError

    exp.or_(*expressions)

    paren

    exp.paren(expression)

    parse

    fn parse(sql : String, read? : String, error_level? :
    ErrorLevel
    , error_message_context? : Int, max_errors? : Int, max_nodes? : Int) -> Array[
    Expr
    ?] raise
    SqlglotError

    Parses all statements of sql in dialect read (Python sqlglot.parse).

    parse_identifier

    fn parse_identifier(name : String, dialect? : String) ->
    Expr
    raise
    SqlglotError

    exp.parse_identifier(name, dialect)

    parse_one

    fn parse_one(sql : String, read? : String, into? :
    Kind
    , into_any? : Array[
    Kind
    ], error_level? :
    ErrorLevel
    , error_message_context? : Int, max_errors? : Int, max_nodes? : Int) ->
    Expr
    raise
    SqlglotError

    Parses a single SQL statement in dialect read (Python sqlglot.parse_one). into (Python into=exp.X) parses into the given expression type; into_any (Python into=[exp.X, exp.Y]) tries each type in turn.

    register_dialects

    fn register_dialects() -> Unit

    Registers all built-in dialects with the core dialect registry. Called automatically when this package is initialized; safe to call again.

    rename_column

    fn[T :
    IntoPy
    , O :
    IntoPy
    , N :
    IntoPy
    ] rename_column(table_name : T, old_column_name : O, new_column_name : N, exists? : Bool, dialect? : String) ->
    Expr
    raise
    SqlglotError

    exp.rename_column(table_name, old_column_name, new_column_name, exists=...)

    rename_table

    exp.rename_table(old_name, new_name)

    replace_placeholders

    exp.replace_placeholders(expression, *args, **kwargs): replaces unnamed placeholders with args (in order) and named placeholders with kwargs.

    replace_tables

    fn replace_tables(expression :
    Expr
    , mapping : Map[String, String], dialect? : String, copy? : Bool) ->
    Expr
    raise
    SqlglotError

    exp.replace_tables(expression, mapping, dialect=...): replaces all tables in expression according to mapping.

    select

    exp.select(*expressions)

    subquery

    fn[T :
    IntoPy
    ] subquery(expression : T, alias? : String, dialect? : String, copy? : Bool) ->
    Expr
    raise
    SqlglotError

    exp.subquery(expression, alias): a new Select from the given query as a subquery.

    table_

    fn table_(table : String, db? : String, catalog? : String, quoted? : Bool, alias? : String) ->
    Expr

    exp.table_(table, db=..., catalog=..., quoted=..., alias=...)

    table_name

    fn[T :
    IntoPy
    ] table_name(table : T, dialect? : String, identify? : Bool) -> String raise
    SqlglotError

    exp.table_name(table, dialect=..., identify=...): the full name of a table.

    to_column

    fn[T :
    IntoPy
    ] to_column(sql_path : T, quoted? : Bool, dialect? : String, copy? : Bool, kwargs? : Map[String,
    Value
    ]) ->
    Expr
    raise
    SqlglotError

    exp.to_column(sql_path, quoted=..., dialect=..., **kwargs)

    to_identifier

    Python to_identifier(name, quoted, copy) for a host value: strings become identifiers (quoted when they aren't safe identifiers, unless quoted is given), identifiers are copied, None stays None.

    to_interval

    exp.to_interval(interval): builds an interval expression from a string like '1 day'.

    to_table

    exp.to_table(sql_path, dialect=..., **kwargs): a table expression from a [catalog].[schema].[table] sql path, or a copy of the given table.

    transpile

    fn transpile(sql : String, read? : String, write? : String, identity? : Bool, error_level? :
    ErrorLevel
    , error_message_context? : Int, max_errors? : Int, max_nodes? : Int, pretty? : Bool, identify? : Identify, normalize? : Bool, pad? : Int, indent? : Int, normalize_functions? : NormalizeFunctions, unsupported_level? :
    ErrorLevel
    , max_unsupported? : Int, leading_comma? : Bool, max_text_width? : Int, comments? : Bool) -> Array[String] raise
    SqlglotError

    Parses sql (possibly several statements) in dialect read and generates it in dialect write (Python sqlglot.transpile). When identity is true (the default) and write is omitted, write defaults to read; otherwise to the base dialect. error_level, error_message_context, max_errors and max_nodes are the parser options (see parse); the remaining options are the generator options (see generate).

    tuple_

    exp.tuple_(*expressions)

    union

    fn[T :
    IntoPy
    ] union(expressions : Array[T], distinct? : Bool, dialect? : String, copy? : Bool) ->
    Expr
    raise
    SqlglotError

    exp.union(*expressions, distinct=...)

    update

    exp.update(table, properties, where=..., from_=..., with_=...)

    values

    exp.values(values, alias=..., columns=...): builds a VALUES statement.

    xor

    fn[T :
    IntoPy
    ] xor(expressions : Array[T], dialect? : String, copy? : Bool, wrap? : Bool) ->
    Expr
    raise
    SqlglotError

    exp.xor(*expressions)