sqlglot 30.0.1__tar.gz → 30.0.2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {sqlglot-30.0.1 → sqlglot-30.0.2}/CHANGELOG.md +138 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/Makefile +6 -3
- {sqlglot-30.0.1 → sqlglot-30.0.2}/PKG-INFO +19 -19
- {sqlglot-30.0.1 → sqlglot-30.0.2}/README.md +16 -16
- {sqlglot-30.0.1 → sqlglot-30.0.2}/pyproject.toml +3 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/__init__.py +18 -1
- {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/_version.py +3 -3
- {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/dialects/databricks.py +1 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/dialects/duckdb.py +158 -10
- {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/dialects/snowflake.py +3 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/expressions/array.py +7 -1
- {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/expressions/core.py +2 -2
- {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/expressions/string.py +8 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/generator.py +6 -3
- {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/parser.py +304 -78
- {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/parsers/bigquery.py +10 -3
- {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/parsers/materialize.py +2 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/parsers/prql.py +7 -1
- {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/parsers/snowflake.py +24 -17
- {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/tokenizer_core.py +15 -3
- {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/typing/snowflake.py +1 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot.egg-info/PKG-INFO +19 -19
- {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot.egg-info/requires.txt +2 -2
- {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglotc/setup.py +8 -6
- {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/dialects/test_bigquery.py +1 -1
- {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/dialects/test_dialect.py +2 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/dialects/test_duckdb.py +10 -1
- {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/dialects/test_mysql.py +1 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/dialects/test_oracle.py +1 -1
- {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/dialects/test_snowflake.py +55 -13
- {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/fixtures/identity.sql +0 -2
- {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/test_executor.py +5 -8
- {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/test_expressions.py +10 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/test_transpile.py +26 -1
- {sqlglot-30.0.1 → sqlglot-30.0.2}/.gitignore +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/.gitmodules +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/.gitpod.yml +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/.pre-commit-config.yaml +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/CLAUDE.md +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/CONTRIBUTING.md +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/LICENSE +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/MANIFEST.in +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/setup.cfg +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/setup.py +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/__main__.py +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/_typing.py +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/dialects/__init__.py +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/dialects/athena.py +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/dialects/bigquery.py +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/dialects/clickhouse.py +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/dialects/dialect.py +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/dialects/doris.py +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/dialects/dremio.py +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/dialects/drill.py +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/dialects/druid.py +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/dialects/dune.py +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/dialects/exasol.py +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/dialects/fabric.py +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/dialects/hive.py +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/dialects/materialize.py +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/dialects/mysql.py +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/dialects/oracle.py +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/dialects/postgres.py +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/dialects/presto.py +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/dialects/prql.py +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/dialects/redshift.py +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/dialects/risingwave.py +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/dialects/singlestore.py +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/dialects/solr.py +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/dialects/spark.py +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/dialects/spark2.py +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/dialects/sqlite.py +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/dialects/starrocks.py +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/dialects/tableau.py +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/dialects/teradata.py +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/dialects/trino.py +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/dialects/tsql.py +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/diff.py +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/errors.py +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/executor/__init__.py +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/executor/context.py +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/executor/env.py +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/executor/python.py +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/executor/table.py +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/expressions/__init__.py +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/expressions/aggregate.py +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/expressions/builders.py +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/expressions/constraints.py +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/expressions/datatypes.py +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/expressions/ddl.py +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/expressions/dml.py +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/expressions/functions.py +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/expressions/json.py +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/expressions/math.py +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/expressions/properties.py +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/expressions/query.py +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/expressions/temporal.py +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/helper.py +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/jsonpath.py +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/lineage.py +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/optimizer/__init__.py +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/optimizer/annotate_types.py +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/optimizer/canonicalize.py +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/optimizer/eliminate_ctes.py +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/optimizer/eliminate_joins.py +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/optimizer/eliminate_subqueries.py +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/optimizer/isolate_table_selects.py +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/optimizer/merge_subqueries.py +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/optimizer/normalize.py +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/optimizer/normalize_identifiers.py +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/optimizer/optimize_joins.py +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/optimizer/optimizer.py +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/optimizer/pushdown_predicates.py +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/optimizer/pushdown_projections.py +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/optimizer/qualify.py +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/optimizer/qualify_columns.py +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/optimizer/qualify_tables.py +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/optimizer/resolver.py +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/optimizer/scope.py +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/optimizer/simplify.py +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/optimizer/unnest_subqueries.py +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/parsers/__init__.py +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/parsers/athena.py +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/parsers/base.py +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/parsers/clickhouse.py +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/parsers/databricks.py +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/parsers/doris.py +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/parsers/dremio.py +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/parsers/drill.py +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/parsers/druid.py +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/parsers/duckdb.py +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/parsers/dune.py +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/parsers/exasol.py +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/parsers/fabric.py +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/parsers/hive.py +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/parsers/mysql.py +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/parsers/oracle.py +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/parsers/postgres.py +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/parsers/presto.py +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/parsers/redshift.py +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/parsers/risingwave.py +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/parsers/singlestore.py +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/parsers/solr.py +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/parsers/spark.py +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/parsers/spark2.py +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/parsers/sqlite.py +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/parsers/starrocks.py +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/parsers/tableau.py +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/parsers/teradata.py +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/parsers/trino.py +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/parsers/tsql.py +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/planner.py +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/py.typed +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/schema.py +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/serde.py +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/time.py +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/tokens.py +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/transforms.py +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/trie.py +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/typing/__init__.py +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/typing/bigquery.py +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/typing/clickhouse.py +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/typing/duckdb.py +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/typing/hive.py +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/typing/mysql.py +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/typing/presto.py +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/typing/redshift.py +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/typing/spark.py +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/typing/spark2.py +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/typing/tsql.py +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot.egg-info/SOURCES.txt +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot.egg-info/dependency_links.txt +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot.egg-info/top_level.txt +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot.png +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglotc/MANIFEST.in +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglotc/pyproject.toml +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/__init__.py +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/dialects/__init__.py +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/dialects/test_athena.py +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/dialects/test_clickhouse.py +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/dialects/test_databricks.py +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/dialects/test_doris.py +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/dialects/test_dremio.py +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/dialects/test_drill.py +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/dialects/test_druid.py +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/dialects/test_dune.py +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/dialects/test_exasol.py +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/dialects/test_fabric.py +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/dialects/test_hive.py +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/dialects/test_materialize.py +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/dialects/test_pipe_syntax.py +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/dialects/test_postgres.py +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/dialects/test_presto.py +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/dialects/test_prql.py +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/dialects/test_redshift.py +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/dialects/test_risingwave.py +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/dialects/test_singlestore.py +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/dialects/test_solr.py +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/dialects/test_spark.py +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/dialects/test_sqlite.py +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/dialects/test_starrocks.py +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/dialects/test_tableau.py +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/dialects/test_teradata.py +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/dialects/test_trino.py +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/dialects/test_tsql.py +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/fixtures/jsonpath/LICENSE +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/fixtures/jsonpath/cts.json +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/fixtures/optimizer/annotate_functions.sql +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/fixtures/optimizer/annotate_types.sql +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/fixtures/optimizer/canonicalize.sql +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/fixtures/optimizer/eliminate_ctes.sql +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/fixtures/optimizer/eliminate_joins.sql +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/fixtures/optimizer/eliminate_subqueries.sql +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/fixtures/optimizer/isolate_table_selects.sql +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/fixtures/optimizer/merge_subqueries.sql +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/fixtures/optimizer/normalize.sql +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/fixtures/optimizer/normalize_identifiers.sql +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/fixtures/optimizer/optimize_joins.sql +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/fixtures/optimizer/optimizer.sql +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/fixtures/optimizer/pushdown_cte_alias_columns.sql +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/fixtures/optimizer/pushdown_predicates.sql +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/fixtures/optimizer/pushdown_projections.sql +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/fixtures/optimizer/qualify_columns.sql +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/fixtures/optimizer/qualify_columns__invalid.sql +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/fixtures/optimizer/qualify_columns__with_invisible.sql +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/fixtures/optimizer/qualify_columns_ddl.sql +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/fixtures/optimizer/qualify_tables.sql +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/fixtures/optimizer/quote_identifiers.sql +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/fixtures/optimizer/simplify.sql +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/fixtures/optimizer/tpc-ds/call_center.csv.gz +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/fixtures/optimizer/tpc-ds/catalog_page.csv.gz +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/fixtures/optimizer/tpc-ds/catalog_returns.csv.gz +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/fixtures/optimizer/tpc-ds/catalog_sales.csv.gz +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/fixtures/optimizer/tpc-ds/customer.csv.gz +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/fixtures/optimizer/tpc-ds/customer_address.csv.gz +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/fixtures/optimizer/tpc-ds/customer_demographics.csv.gz +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/fixtures/optimizer/tpc-ds/date_dim.csv.gz +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/fixtures/optimizer/tpc-ds/household_demographics.csv.gz +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/fixtures/optimizer/tpc-ds/income_band.csv.gz +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/fixtures/optimizer/tpc-ds/inventory.csv.gz +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/fixtures/optimizer/tpc-ds/item.csv.gz +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/fixtures/optimizer/tpc-ds/promotion.csv.gz +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/fixtures/optimizer/tpc-ds/reason.csv.gz +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/fixtures/optimizer/tpc-ds/ship_mode.csv.gz +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/fixtures/optimizer/tpc-ds/store.csv.gz +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/fixtures/optimizer/tpc-ds/store_returns.csv.gz +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/fixtures/optimizer/tpc-ds/store_sales.csv.gz +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/fixtures/optimizer/tpc-ds/time_dim.csv.gz +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/fixtures/optimizer/tpc-ds/tpc-ds.sql +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/fixtures/optimizer/tpc-ds/warehouse.csv.gz +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/fixtures/optimizer/tpc-ds/web_page.csv.gz +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/fixtures/optimizer/tpc-ds/web_returns.csv.gz +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/fixtures/optimizer/tpc-ds/web_sales.csv.gz +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/fixtures/optimizer/tpc-ds/web_site.csv.gz +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/fixtures/optimizer/tpc-h/customer.csv.gz +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/fixtures/optimizer/tpc-h/lineitem.csv.gz +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/fixtures/optimizer/tpc-h/nation.csv.gz +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/fixtures/optimizer/tpc-h/orders.csv.gz +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/fixtures/optimizer/tpc-h/part.csv.gz +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/fixtures/optimizer/tpc-h/partsupp.csv.gz +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/fixtures/optimizer/tpc-h/region.csv.gz +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/fixtures/optimizer/tpc-h/supplier.csv.gz +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/fixtures/optimizer/tpc-h/tpc-h.sql +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/fixtures/optimizer/unnest_subqueries.sql +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/fixtures/partial.sql +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/fixtures/pretty.sql +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/gen_fixtures.py +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/helpers.py +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/test_build.py +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/test_dialect_entry_points.py +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/test_dialect_imports.py +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/test_diff.py +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/test_docs.py +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/test_errors.py +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/test_generator.py +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/test_helper.py +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/test_integration_loader.py +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/test_jsonpath.py +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/test_lineage.py +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/test_optimizer.py +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/test_parser.py +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/test_schema.py +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/test_serde.py +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/test_time.py +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/test_tokens.py +0 -0
- {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/test_transforms.py +0 -0
|
@@ -1,7 +1,144 @@
|
|
|
1
1
|
Changelog
|
|
2
2
|
=========
|
|
3
3
|
|
|
4
|
+
## [v30.0.1] - 2026-03-16
|
|
5
|
+
### :bug: Bug Fixes
|
|
6
|
+
- [`7bcad5c`](https://github.com/tobymao/sqlglot/commit/7bcad5c61673a8567e9c22d059ed4326e6698457) - auto pin sqlglotc version to sqlglot so there's no version mismatch closes [#7304](https://github.com/tobymao/sqlglot/pull/7304) *(commit by [@tobymao](https://github.com/tobymao))*
|
|
7
|
+
|
|
8
|
+
|
|
4
9
|
## [v30.0.0] - 2026-03-16
|
|
10
|
+
|
|
11
|
+
SQLGlot v30 is a major release focused on performance and compilation. Some of the core components of the library are now fully compilable by [mypyc](https://mypyc.readthedocs.io/), delivering significant speedups when installed with the `[c]` extra. This required restructuring several internal modules, which introduces breaking changes for users who depend on internal APIs, subclass parsers, or import from internal paths.
|
|
12
|
+
|
|
13
|
+
> **If you only use the public API** (`sqlglot.parse`, `sqlglot.parse_one`, `sqlglot.transpile`, `sqlglot.exp.*`, `sqlglot.optimizer.*`), most code will work without changes.
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
## Migration Guide
|
|
17
|
+
|
|
18
|
+
### 1. Rust tokenizer removed — use `[c]` instead of `[rs]`
|
|
19
|
+
|
|
20
|
+
The Rust-based tokenizer (`sqlglotrs`) has been removed (since v29) and replaced with a mypyc-compiled C extension (`sqlglotc`).
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
# Before
|
|
24
|
+
pip install "sqlglot[rs]"
|
|
25
|
+
|
|
26
|
+
# After
|
|
27
|
+
pip install "sqlglot[c]"
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
The `[rs]` extra still installs but is now a deprecated no-op stub. The following APIs are removed:
|
|
31
|
+
- `use_rs_tokenizer` parameter and attribute on `Tokenizer`
|
|
32
|
+
- `RsTokenizer`, `RsTokenizerSettings`, `RsTokenTypeSettings` imports
|
|
33
|
+
- `USE_RS_TOKENIZER` constant from `tokens.py`
|
|
34
|
+
|
|
35
|
+
### 2. `expressions.py` split into a package
|
|
36
|
+
|
|
37
|
+
The monolithic `sqlglot/expressions.py` has been split into `sqlglot/expressions/` with submodules:
|
|
38
|
+
|
|
39
|
+
| Module | Contents |
|
|
40
|
+
|---|---|
|
|
41
|
+
| `core.py` | `Expr`, `Expression`, `Condition`, `Func`, `AggFunc`, `Column`, `Literal`, etc. |
|
|
42
|
+
| `datatypes.py` | `DataType`, `DType`, `DataTypeParam`, `Interval` |
|
|
43
|
+
| `query.py` | `Select`, `Query`, `SetOperation`, `UDTF`, `Subquery` |
|
|
44
|
+
| `ddl.py` | `Create`, `Alter`, `Drop`, DDL statements |
|
|
45
|
+
| `dml.py` | `Insert`, `Update`, `Delete`, `Merge` |
|
|
46
|
+
| `properties.py` | All `*Property` classes, `PropertiesLocation` |
|
|
47
|
+
| `constraints.py` | All `*ColumnConstraint` classes |
|
|
48
|
+
| `math.py` | Arithmetic operators (`Add`, `Sub`, `Mul`, `Div`, etc.) |
|
|
49
|
+
| `string.py` | String functions (`Concat`, `Length`, `Upper`, etc.) |
|
|
50
|
+
| `temporal.py` | Date/time functions (`DateAdd`, `DateDiff`, etc.) |
|
|
51
|
+
| `aggregate.py` | Aggregate functions (`Count`, `Sum`, `Avg`, etc.) |
|
|
52
|
+
| `array.py` | Array functions (`ArrayAgg`, `Explode`, etc.) |
|
|
53
|
+
| `json.py` | JSON functions (`JSONExtract`, etc.) |
|
|
54
|
+
| `functions.py` | Other functions (`Coalesce`, `If`, `Case`, `Cast`, etc.) |
|
|
55
|
+
| `builders.py` | Builder helpers (`select()`, `from_()`, `condition()`, etc.) |
|
|
56
|
+
|
|
57
|
+
**Backwards-compatibility:** `from sqlglot.expressions import *` and `from sqlglot import expressions as exp` still work, because everything is re-exported from `expressions/__init__.py`. However, if you were importing from `sqlglot.expressions` by relying on it being a single file (e.g., inspecting `__file__`), that will break.
|
|
58
|
+
|
|
59
|
+
### 3. `Parser.expression()` no longer accepts `**kwargs`
|
|
60
|
+
|
|
61
|
+
This affects anyone subclassing `Parser` or calling `self.expression()` in custom parse methods.
|
|
62
|
+
|
|
63
|
+
```python
|
|
64
|
+
# Before
|
|
65
|
+
self.expression(exp.Select, distinct=True, expressions=cols)
|
|
66
|
+
|
|
67
|
+
# After
|
|
68
|
+
self.expression(exp.Select(distinct=True, expressions=cols))
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
The expression instance is now constructed by the caller and passed directly. This eliminates `**kwargs` dict allocation overhead.
|
|
72
|
+
|
|
73
|
+
### 4. Scope traversal: `bfs` parameter removed
|
|
74
|
+
|
|
75
|
+
The `bfs` parameter has been removed from all scope traversal functions. Traversal is now always depth-first (DFS).
|
|
76
|
+
|
|
77
|
+
```python
|
|
78
|
+
# Before
|
|
79
|
+
scope.walk(bfs=True)
|
|
80
|
+
scope.find(exp.Column, bfs=False)
|
|
81
|
+
walk_in_scope(expr, bfs=True)
|
|
82
|
+
|
|
83
|
+
# After
|
|
84
|
+
scope.walk()
|
|
85
|
+
scope.find(exp.Column)
|
|
86
|
+
walk_in_scope(expr)
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
**Behavioral change:** The old default was `bfs=True`. Now traversal is always DFS. Code that depended on BFS ordering from these functions will get results in a different order.
|
|
90
|
+
|
|
91
|
+
Affected functions: `Scope.walk()`, `Scope.find()`, `Scope.find_all()`, `walk_in_scope()`, `find_in_scope()`, `find_all_in_scope()`.
|
|
92
|
+
|
|
93
|
+
### 5. Dialect metaclass no longer mutates Parser token sets
|
|
94
|
+
|
|
95
|
+
Previously, the `_Dialect` metaclass dynamically modified parser token sets (`ID_VAR_TOKENS`, `TABLE_ALIAS_TOKENS`, `NO_PAREN_FUNCTIONS`) at class creation time based on dialect flags like `SUPPORTS_SEMI_ANTI_JOIN`. These mutations are removed — each parser now declares its token sets statically.
|
|
96
|
+
|
|
97
|
+
- `Dialect.SUPPORTS_SEMI_ANTI_JOIN` has been removed.
|
|
98
|
+
- `SHOW_TRIE` / `SET_TRIE` are no longer auto-computed from `SHOW_PARSERS` / `SET_PARSERS`.
|
|
99
|
+
|
|
100
|
+
### 6. Use `Expr` instead of `Expression` for generic `isinstance` checks
|
|
101
|
+
|
|
102
|
+
Base classes like `Func`, `Condition`, `Binary`, and other traits now inherit from `Expr` directly, not from `Expression`. This means `isinstance(node, exp.Expression)` will **not** match these trait classes. If your code uses `isinstance` to check for "any AST node", switch to `exp.Expr`:
|
|
103
|
+
|
|
104
|
+
```python
|
|
105
|
+
# Before
|
|
106
|
+
isinstance(node, exp.Expression)
|
|
107
|
+
|
|
108
|
+
# After
|
|
109
|
+
isinstance(node, exp.Expr)
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
### 7. Compiled classes cannot be subclassed (when using `[c]`)
|
|
113
|
+
|
|
114
|
+
When `sqlglot[c]` is installed, many core classes are compiled via mypyc. **Compiled classes cannot be subclassed at runtime** — class definition succeeds, but instantiation raises `TypeError: interpreted classes cannot inherit from compiled`.
|
|
115
|
+
|
|
116
|
+
**Affected classes (compiled):**
|
|
117
|
+
|
|
118
|
+
| Class | Subclassable? |
|
|
119
|
+
|---|---|
|
|
120
|
+
| All parsers (`BigQueryParser`, `SnowflakeParser`, etc.) | No |
|
|
121
|
+
| `Parser` (base) | No |
|
|
122
|
+
| `Expression`, `Expr`, and all AST nodes (`Select`, `Column`, `Func`, etc.) | No |
|
|
123
|
+
| `MappingSchema`, `AbstractMappingSchema` | No |
|
|
124
|
+
| `Scope` | No |
|
|
125
|
+
| Optimizer rules (`scope.py`, `qualify.py`, `qualify_columns.py`, etc.) | No |
|
|
126
|
+
|
|
127
|
+
**Not compiled (still subclassable):**
|
|
128
|
+
|
|
129
|
+
| Class | Subclassable? |
|
|
130
|
+
|---|---|
|
|
131
|
+
| `Generator` and all dialect generators | Yes |
|
|
132
|
+
| `Tokenizer` and all dialect tokenizers | Yes |
|
|
133
|
+
| `Dialect` and all dialect classes | Yes |
|
|
134
|
+
|
|
135
|
+
If you need to subclass compiled classes (parsers, expressions, schema, etc.), install the pure Python version instead:
|
|
136
|
+
|
|
137
|
+
```bash
|
|
138
|
+
pip install sqlglot # pure Python — full subclassing support
|
|
139
|
+
pip install "sqlglot[c]" # compiled — faster, but no subclassing
|
|
140
|
+
```
|
|
141
|
+
|
|
5
142
|
### :boom: BREAKING CHANGES
|
|
6
143
|
- due to [`8ee0646`](https://github.com/tobymao/sqlglot/commit/8ee0646baa6dfae7e96ca86e2c1af5d53fc04290) - Transpile numeric literals with underscores from ClickHouse to other dialects *(PR [#7132](https://github.com/tobymao/sqlglot/pull/7132) by [@fivetran-amrutabhimsenayachit](https://github.com/fivetran-amrutabhimsenayachit))*:
|
|
7
144
|
|
|
@@ -13663,3 +13800,4 @@ Changelog
|
|
|
13663
13800
|
[v29.0.0]: https://github.com/tobymao/sqlglot/compare/v28.10.1...v29.0.0
|
|
13664
13801
|
[v29.0.1]: https://github.com/tobymao/sqlglot/compare/v29.0.0...v29.0.1
|
|
13665
13802
|
[v30.0.0]: https://github.com/tobymao/sqlglot/compare/v29.0.1...v30.0.0
|
|
13803
|
+
[v30.0.1]: https://github.com/tobymao/sqlglot/compare/v30.0.0...v30.0.1
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
.PHONY: install install-dev install-devc install-devc-release install-pre-commit bench bench-parse bench-optimize test test-fast unit testc unitc style check docs docs-serve hidec showc clean resolve-integration-conflicts
|
|
1
|
+
.PHONY: install install-dev install-devc install-devc-release install-pre-commit bench bench-parse bench-optimize test test-fast unit testc unitc style check docs docs-serve hidec showc clean resolve-integration-conflicts update-fixtures
|
|
2
2
|
|
|
3
3
|
ifdef UV
|
|
4
4
|
PIP := uv pip
|
|
@@ -7,7 +7,7 @@ else
|
|
|
7
7
|
endif
|
|
8
8
|
|
|
9
9
|
SO_BACKUP := /tmp/sqlglot_so_backup
|
|
10
|
-
FIND_SO := find
|
|
10
|
+
FIND_SO := find sqlglot -name "*.so"
|
|
11
11
|
|
|
12
12
|
hidec:
|
|
13
13
|
rm -rf $(SO_BACKUP) && $(FIND_SO) | tar cf $(SO_BACKUP) -T - 2>/dev/null && $(FIND_SO) -delete; true
|
|
@@ -41,7 +41,7 @@ install-devc:
|
|
|
41
41
|
cd sqlglotc && MYPYC_OPT=0 python setup.py build_ext --inplace
|
|
42
42
|
|
|
43
43
|
install-devc-release: clean
|
|
44
|
-
cd sqlglotc &&
|
|
44
|
+
cd sqlglotc && python setup.py build_ext --inplace
|
|
45
45
|
|
|
46
46
|
install-pre-commit:
|
|
47
47
|
pre-commit install
|
|
@@ -87,3 +87,6 @@ docs-serve:
|
|
|
87
87
|
|
|
88
88
|
resolve-integration-conflicts:
|
|
89
89
|
cd sqlglot-integration-tests && git pull --rebase --autostash
|
|
90
|
+
|
|
91
|
+
update-fixtures:
|
|
92
|
+
python sqlglot-integration-tests/scripts/update_dbt_fixtures.py
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: sqlglot
|
|
3
|
-
Version: 30.0.
|
|
3
|
+
Version: 30.0.2
|
|
4
4
|
Summary: An easily customizable SQL parser and transpiler
|
|
5
5
|
Author-email: Toby Mao <toby.mao@gmail.com>
|
|
6
6
|
License-Expression: MIT
|
|
@@ -33,10 +33,10 @@ Requires-Dist: types-pytz; extra == "dev"
|
|
|
33
33
|
Requires-Dist: typing_extensions; extra == "dev"
|
|
34
34
|
Requires-Dist: pyperf; extra == "dev"
|
|
35
35
|
Provides-Extra: c
|
|
36
|
-
Requires-Dist: sqlglotc==30.0.
|
|
36
|
+
Requires-Dist: sqlglotc==30.0.2; extra == "c"
|
|
37
37
|
Provides-Extra: rs
|
|
38
38
|
Requires-Dist: sqlglotrs==0.13.0; extra == "rs"
|
|
39
|
-
Requires-Dist: sqlglotc==30.0.
|
|
39
|
+
Requires-Dist: sqlglotc==30.0.2; extra == "rs"
|
|
40
40
|
Dynamic: license-file
|
|
41
41
|
Dynamic: provides-extra
|
|
42
42
|
|
|
@@ -590,22 +590,22 @@ sqlglot, sqltree, sqlparse, and sqlfluff are python based whereas sqloxide and p
|
|
|
590
590
|
|
|
591
591
|
| Query | sqlglot | sqlglot[c] | sqltree | sqlparse | sqlfluff | sqloxide | polyglot-sql |
|
|
592
592
|
| ----------------- | --------------- | --------------- | --------------- | ---------------- | ----------------- | --------------- | --------------- |
|
|
593
|
-
| tpch | 0.
|
|
594
|
-
| short | 0.
|
|
595
|
-
| deep_arithmetic | 0.
|
|
596
|
-
| large_in | 0.
|
|
597
|
-
| values | 0.
|
|
598
|
-
| many_joins | 0.
|
|
599
|
-
| many_unions | 0.
|
|
600
|
-
| nested_subqueries | 0.
|
|
601
|
-
| many_columns | 0.
|
|
602
|
-
| large_case | 0.
|
|
603
|
-
| complex_where | 0.
|
|
604
|
-
| many_ctes | 0.
|
|
605
|
-
| many_windows | 0.
|
|
606
|
-
| nested_functions | 0.
|
|
607
|
-
| large_strings | 0.
|
|
608
|
-
| many_numbers | 0.
|
|
593
|
+
| tpch | 0.002646 (1.00) | 0.000776 (0.29) | 0.002171 (0.82) | 0.014029 (5.30) | 0.247869 (93.68) | 0.000567 (0.21) | 0.000565 (0.21) |
|
|
594
|
+
| short | 0.000221 (1.00) | 0.000077 (0.35) | 0.000169 (0.76) | 0.000891 (4.03) | 0.032397 (146.59) | 0.000036 (0.16) | 0.000100 (0.45) |
|
|
595
|
+
| deep_arithmetic | 0.007739 (1.00) | 0.002249 (0.29) | 0.006108 (0.79) | N/A | 1.404935 (181.54) | 0.002756 (0.36) | 0.002376 (0.31) |
|
|
596
|
+
| large_in | 0.426694 (1.00) | 0.104540 (0.24) | 0.481306 (1.13) | N/A | N/A | 0.118200 (0.28) | 0.109950 (0.26) |
|
|
597
|
+
| values | 0.470626 (1.00) | 0.114497 (0.24) | 0.547718 (1.16) | N/A | N/A | 0.118737 (0.25) | 0.113932 (0.24) |
|
|
598
|
+
| many_joins | 0.012012 (1.00) | 0.002515 (0.21) | 0.010995 (0.92) | 0.057475 (4.78) | 1.354047 (112.72) | 0.002927 (0.24) | 0.002988 (0.25) |
|
|
599
|
+
| many_unions | 0.048105 (1.00) | 0.008505 (0.18) | 0.038477 (0.80) | N/A | 1.894275 (39.38) | 0.012482 (0.26) | 0.014072 (0.29) |
|
|
600
|
+
| nested_subqueries | 0.001377 (1.00) | 0.000238 (0.17) | N/A | 0.003820 (2.77) | 0.092038 (66.84) | 0.000231 (0.17) | 0.000272 (0.20) |
|
|
601
|
+
| many_columns | 0.012463 (1.00) | 0.002794 (0.22) | 0.012433 (1.00) | 0.240845 (19.32) | 1.097327 (88.05) | 0.002403 (0.19) | 0.003731 (0.30) |
|
|
602
|
+
| large_case | 0.043128 (1.00) | 0.008559 (0.20) | 0.034192 (0.79) | N/A | 4.794309 (111.16) | 0.009326 (0.22) | 0.009723 (0.23) |
|
|
603
|
+
| complex_where | 0.032286 (1.00) | 0.006645 (0.21) | N/A | 0.136158 (4.22) | 2.623021 (81.24) | 0.005642 (0.17) | 0.007409 (0.23) |
|
|
604
|
+
| many_ctes | 0.018625 (1.00) | 0.003961 (0.21) | 0.012569 (0.67) | 0.125719 (6.75) | 0.680498 (36.54) | 0.004813 (0.26) | 0.003537 (0.19) |
|
|
605
|
+
| many_windows | 0.021923 (1.00) | 0.005856 (0.27) | N/A | 0.205469 (9.37) | 1.465070 (66.83) | 0.003638 (0.17) | 0.004376 (0.20) |
|
|
606
|
+
| nested_functions | 0.000816 (1.00) | 0.000195 (0.24) | 0.000703 (0.86) | 0.005044 (6.18) | 0.093864 (115.03) | 0.000170 (0.21) | 0.000188 (0.23) |
|
|
607
|
+
| large_strings | 0.005391 (1.00) | 0.001474 (0.27) | 0.014024 (2.60) | 0.050929 (9.45) | 0.335191 (62.18) | 0.001559 (0.29) | 0.002095 (0.39) |
|
|
608
|
+
| many_numbers | 0.107804 (1.00) | 0.025544 (0.24) | 0.122202 (1.13) | N/A | N/A | 0.029262 (0.27) | 0.026409 (0.24) |
|
|
609
609
|
|
|
610
610
|
```
|
|
611
611
|
make bench # Run parsing benchmark
|
|
@@ -548,22 +548,22 @@ sqlglot, sqltree, sqlparse, and sqlfluff are python based whereas sqloxide and p
|
|
|
548
548
|
|
|
549
549
|
| Query | sqlglot | sqlglot[c] | sqltree | sqlparse | sqlfluff | sqloxide | polyglot-sql |
|
|
550
550
|
| ----------------- | --------------- | --------------- | --------------- | ---------------- | ----------------- | --------------- | --------------- |
|
|
551
|
-
| tpch | 0.
|
|
552
|
-
| short | 0.
|
|
553
|
-
| deep_arithmetic | 0.
|
|
554
|
-
| large_in | 0.
|
|
555
|
-
| values | 0.
|
|
556
|
-
| many_joins | 0.
|
|
557
|
-
| many_unions | 0.
|
|
558
|
-
| nested_subqueries | 0.
|
|
559
|
-
| many_columns | 0.
|
|
560
|
-
| large_case | 0.
|
|
561
|
-
| complex_where | 0.
|
|
562
|
-
| many_ctes | 0.
|
|
563
|
-
| many_windows | 0.
|
|
564
|
-
| nested_functions | 0.
|
|
565
|
-
| large_strings | 0.
|
|
566
|
-
| many_numbers | 0.
|
|
551
|
+
| tpch | 0.002646 (1.00) | 0.000776 (0.29) | 0.002171 (0.82) | 0.014029 (5.30) | 0.247869 (93.68) | 0.000567 (0.21) | 0.000565 (0.21) |
|
|
552
|
+
| short | 0.000221 (1.00) | 0.000077 (0.35) | 0.000169 (0.76) | 0.000891 (4.03) | 0.032397 (146.59) | 0.000036 (0.16) | 0.000100 (0.45) |
|
|
553
|
+
| deep_arithmetic | 0.007739 (1.00) | 0.002249 (0.29) | 0.006108 (0.79) | N/A | 1.404935 (181.54) | 0.002756 (0.36) | 0.002376 (0.31) |
|
|
554
|
+
| large_in | 0.426694 (1.00) | 0.104540 (0.24) | 0.481306 (1.13) | N/A | N/A | 0.118200 (0.28) | 0.109950 (0.26) |
|
|
555
|
+
| values | 0.470626 (1.00) | 0.114497 (0.24) | 0.547718 (1.16) | N/A | N/A | 0.118737 (0.25) | 0.113932 (0.24) |
|
|
556
|
+
| many_joins | 0.012012 (1.00) | 0.002515 (0.21) | 0.010995 (0.92) | 0.057475 (4.78) | 1.354047 (112.72) | 0.002927 (0.24) | 0.002988 (0.25) |
|
|
557
|
+
| many_unions | 0.048105 (1.00) | 0.008505 (0.18) | 0.038477 (0.80) | N/A | 1.894275 (39.38) | 0.012482 (0.26) | 0.014072 (0.29) |
|
|
558
|
+
| nested_subqueries | 0.001377 (1.00) | 0.000238 (0.17) | N/A | 0.003820 (2.77) | 0.092038 (66.84) | 0.000231 (0.17) | 0.000272 (0.20) |
|
|
559
|
+
| many_columns | 0.012463 (1.00) | 0.002794 (0.22) | 0.012433 (1.00) | 0.240845 (19.32) | 1.097327 (88.05) | 0.002403 (0.19) | 0.003731 (0.30) |
|
|
560
|
+
| large_case | 0.043128 (1.00) | 0.008559 (0.20) | 0.034192 (0.79) | N/A | 4.794309 (111.16) | 0.009326 (0.22) | 0.009723 (0.23) |
|
|
561
|
+
| complex_where | 0.032286 (1.00) | 0.006645 (0.21) | N/A | 0.136158 (4.22) | 2.623021 (81.24) | 0.005642 (0.17) | 0.007409 (0.23) |
|
|
562
|
+
| many_ctes | 0.018625 (1.00) | 0.003961 (0.21) | 0.012569 (0.67) | 0.125719 (6.75) | 0.680498 (36.54) | 0.004813 (0.26) | 0.003537 (0.19) |
|
|
563
|
+
| many_windows | 0.021923 (1.00) | 0.005856 (0.27) | N/A | 0.205469 (9.37) | 1.465070 (66.83) | 0.003638 (0.17) | 0.004376 (0.20) |
|
|
564
|
+
| nested_functions | 0.000816 (1.00) | 0.000195 (0.24) | 0.000703 (0.86) | 0.005044 (6.18) | 0.093864 (115.03) | 0.000170 (0.21) | 0.000188 (0.23) |
|
|
565
|
+
| large_strings | 0.005391 (1.00) | 0.001474 (0.27) | 0.014024 (2.60) | 0.050929 (9.45) | 0.335191 (62.18) | 0.001559 (0.29) | 0.002095 (0.39) |
|
|
566
|
+
| many_numbers | 0.107804 (1.00) | 0.025544 (0.24) | 0.122202 (1.13) | N/A | N/A | 0.029262 (0.27) | 0.026409 (0.24) |
|
|
567
567
|
|
|
568
568
|
```
|
|
569
569
|
make bench # Run parsing benchmark
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# ruff: noqa: F401
|
|
1
|
+
# ruff: noqa: F401, E402
|
|
2
2
|
"""
|
|
3
3
|
.. include:: ../README.md
|
|
4
4
|
|
|
@@ -7,6 +7,23 @@
|
|
|
7
7
|
|
|
8
8
|
from __future__ import annotations
|
|
9
9
|
|
|
10
|
+
# bootstrap mypyc runtime: compiled .so modules do a top-level `import HASH__mypyc`,
|
|
11
|
+
# but the runtime .so lives inside sqlglot/. Pre-load it into sys.modules.
|
|
12
|
+
# this is only needed for editable builds
|
|
13
|
+
import sys
|
|
14
|
+
from pathlib import Path
|
|
15
|
+
|
|
16
|
+
for path in Path(__file__).parent.glob("*__mypyc*.so"):
|
|
17
|
+
name = path.stem.split(".")[0]
|
|
18
|
+
if name not in sys.modules:
|
|
19
|
+
import importlib.util
|
|
20
|
+
|
|
21
|
+
spec = importlib.util.spec_from_file_location(name, path)
|
|
22
|
+
if spec and spec.loader:
|
|
23
|
+
mod = importlib.util.module_from_spec(spec)
|
|
24
|
+
sys.modules[name] = mod
|
|
25
|
+
spec.loader.exec_module(mod)
|
|
26
|
+
|
|
10
27
|
import logging
|
|
11
28
|
import typing as t
|
|
12
29
|
|
|
@@ -28,7 +28,7 @@ version_tuple: VERSION_TUPLE
|
|
|
28
28
|
commit_id: COMMIT_ID
|
|
29
29
|
__commit_id__: COMMIT_ID
|
|
30
30
|
|
|
31
|
-
__version__ = version = '30.0.
|
|
32
|
-
__version_tuple__ = version_tuple = (30, 0,
|
|
31
|
+
__version__ = version = '30.0.2'
|
|
32
|
+
__version_tuple__ = version_tuple = (30, 0, 2)
|
|
33
33
|
|
|
34
|
-
__commit_id__ = commit_id = '
|
|
34
|
+
__commit_id__ = commit_id = 'g64509a2a3'
|
|
@@ -2202,6 +2202,58 @@ class DuckDB(Dialect):
|
|
|
2202
2202
|
"""
|
|
2203
2203
|
)
|
|
2204
2204
|
|
|
2205
|
+
# Template for STRTOK function transpilation
|
|
2206
|
+
#
|
|
2207
|
+
# DuckDB itself doesn't have a strtok function. This handles the transpilation from Snowflake to DuckDB.
|
|
2208
|
+
# We may need to adjust this if we want to support transpilation from other dialects
|
|
2209
|
+
#
|
|
2210
|
+
# CASE
|
|
2211
|
+
# -- Snowflake: empty delimiter + empty input string → NULL
|
|
2212
|
+
# WHEN delimiter = '' AND input_str = '' THEN NULL
|
|
2213
|
+
#
|
|
2214
|
+
# -- Snowflake: empty delimiter + non-empty input string → treats whole input as 1 token → return input string if index is 1
|
|
2215
|
+
# WHEN delimiter = '' AND index = 1 THEN input_str
|
|
2216
|
+
#
|
|
2217
|
+
# -- Snowflake: empty delimiter + non-empty input string → treats whole input as 1 token → return NULL if index is not 1
|
|
2218
|
+
# WHEN delimiter = '' THEN NULL
|
|
2219
|
+
#
|
|
2220
|
+
# -- Snowflake: negative indices return NULL
|
|
2221
|
+
# WHEN index < 0 THEN NULL
|
|
2222
|
+
#
|
|
2223
|
+
# -- Snowflake: return NULL if any argument is NULL
|
|
2224
|
+
# WHEN input_str IS NULL OR delimiter IS NULL OR index IS NULL THEN NULL
|
|
2225
|
+
#
|
|
2226
|
+
#
|
|
2227
|
+
# ELSE LIST_FILTER(
|
|
2228
|
+
# REGEXP_SPLIT_TO_ARRAY(
|
|
2229
|
+
# input_str,
|
|
2230
|
+
# CASE
|
|
2231
|
+
# -- if delimiter is '', we don't want to surround it with '[' and ']' as '[]' is invalid for DuckDB
|
|
2232
|
+
# WHEN delimiter = '' THEN ''
|
|
2233
|
+
#
|
|
2234
|
+
# -- handle problematic regex characters in delimiter with REGEXP_REPLACE
|
|
2235
|
+
# -- turn delimiter into a regex char set, otherwise DuckDB will match in order, which we don't want
|
|
2236
|
+
# ELSE '[' || REGEXP_REPLACE(delimiter, problematic_char_set, '\\\1', 'g') || ']'
|
|
2237
|
+
# END
|
|
2238
|
+
# ),
|
|
2239
|
+
#
|
|
2240
|
+
# -- Snowflake: don't return empty strings
|
|
2241
|
+
# x -> NOT x = ''
|
|
2242
|
+
# )[index]
|
|
2243
|
+
# END
|
|
2244
|
+
STRTOK_TEMPLATE: exp.Expr = exp.maybe_parse(
|
|
2245
|
+
"""
|
|
2246
|
+
CASE
|
|
2247
|
+
WHEN :delimiter = '' AND :string = '' THEN NULL
|
|
2248
|
+
WHEN :delimiter = '' AND :part_index = 1 THEN :string
|
|
2249
|
+
WHEN :delimiter = '' THEN NULL
|
|
2250
|
+
WHEN :part_index < 0 THEN NULL
|
|
2251
|
+
WHEN :string IS NULL OR :delimiter IS NULL OR :part_index IS NULL THEN NULL
|
|
2252
|
+
ELSE :base_func
|
|
2253
|
+
END
|
|
2254
|
+
"""
|
|
2255
|
+
)
|
|
2256
|
+
|
|
2205
2257
|
def _array_bag_sql(self, condition: exp.Expr, arr1: exp.Expr, arr2: exp.Expr) -> str:
|
|
2206
2258
|
cond = exp.Paren(this=exp.replace_placeholders(condition, arr1=arr1, arr2=arr2))
|
|
2207
2259
|
return self.sql(
|
|
@@ -3642,14 +3694,14 @@ class DuckDB(Dialect):
|
|
|
3642
3694
|
"""
|
|
3643
3695
|
Output looks something like this:
|
|
3644
3696
|
|
|
3645
|
-
CASE
|
|
3646
|
-
WHEN delimiter is '' THEN
|
|
3697
|
+
CASE
|
|
3698
|
+
WHEN delimiter is '' THEN
|
|
3647
3699
|
(
|
|
3648
|
-
CASE
|
|
3700
|
+
CASE
|
|
3649
3701
|
WHEN adjusted_part_index = 1 OR adjusted_part_index = -1 THEN input
|
|
3650
3702
|
ELSE '' END
|
|
3651
|
-
)
|
|
3652
|
-
ELSE SPLIT_PART(input, delimiter, adjusted_part_index)
|
|
3703
|
+
)
|
|
3704
|
+
ELSE SPLIT_PART(input, delimiter, adjusted_part_index)
|
|
3653
3705
|
END
|
|
3654
3706
|
|
|
3655
3707
|
"""
|
|
@@ -3667,13 +3719,46 @@ class DuckDB(Dialect):
|
|
|
3667
3719
|
return self.sql(expression, "this")
|
|
3668
3720
|
|
|
3669
3721
|
def arraytostring_sql(self, expression: exp.ArrayToString) -> str:
|
|
3670
|
-
|
|
3671
|
-
|
|
3722
|
+
null = expression.args.get("null")
|
|
3723
|
+
|
|
3724
|
+
if expression.args.get("null_is_empty"):
|
|
3725
|
+
x = exp.to_identifier("x")
|
|
3726
|
+
list_transform = exp.Transform(
|
|
3727
|
+
this=expression.this.copy(),
|
|
3728
|
+
expression=exp.Lambda(
|
|
3729
|
+
this=exp.Coalesce(
|
|
3730
|
+
this=exp.cast(x, "TEXT"), expressions=[exp.Literal.string("")]
|
|
3731
|
+
),
|
|
3732
|
+
expressions=[x],
|
|
3733
|
+
),
|
|
3734
|
+
)
|
|
3735
|
+
array_to_string = exp.ArrayToString(
|
|
3736
|
+
this=list_transform, expression=expression.expression
|
|
3737
|
+
)
|
|
3738
|
+
if expression.args.get("null_delim_is_null"):
|
|
3739
|
+
return self.sql(
|
|
3740
|
+
exp.case()
|
|
3741
|
+
.when(expression.expression.copy().is_(exp.null()), exp.null())
|
|
3742
|
+
.else_(array_to_string)
|
|
3743
|
+
)
|
|
3744
|
+
return self.sql(array_to_string)
|
|
3672
3745
|
|
|
3673
|
-
if
|
|
3674
|
-
|
|
3746
|
+
if null:
|
|
3747
|
+
x = exp.to_identifier("x")
|
|
3748
|
+
return self.sql(
|
|
3749
|
+
exp.ArrayToString(
|
|
3750
|
+
this=exp.Transform(
|
|
3751
|
+
this=expression.this,
|
|
3752
|
+
expression=exp.Lambda(
|
|
3753
|
+
this=exp.Coalesce(this=x, expressions=[null]),
|
|
3754
|
+
expressions=[x],
|
|
3755
|
+
),
|
|
3756
|
+
),
|
|
3757
|
+
expression=expression.expression,
|
|
3758
|
+
)
|
|
3759
|
+
)
|
|
3675
3760
|
|
|
3676
|
-
return self.func("ARRAY_TO_STRING", this, expression.expression)
|
|
3761
|
+
return self.func("ARRAY_TO_STRING", expression.this, expression.expression)
|
|
3677
3762
|
|
|
3678
3763
|
def _regexp_extract_sql(self, expression: exp.RegexpExtract | exp.RegexpExtractAll) -> str:
|
|
3679
3764
|
this = expression.this
|
|
@@ -4033,6 +4118,69 @@ class DuckDB(Dialect):
|
|
|
4033
4118
|
|
|
4034
4119
|
return self.func(func, this, decimals, truncate)
|
|
4035
4120
|
|
|
4121
|
+
def strtok_sql(self, expression: exp.Strtok) -> str:
|
|
4122
|
+
string_arg = expression.this
|
|
4123
|
+
delimiter_arg = expression.args.get("delimiter")
|
|
4124
|
+
part_index_arg = expression.args.get("part_index")
|
|
4125
|
+
|
|
4126
|
+
if delimiter_arg and part_index_arg:
|
|
4127
|
+
# Escape regex chars and build character class at runtime using REGEXP_REPLACE
|
|
4128
|
+
escaped_delimiter = exp.Anonymous(
|
|
4129
|
+
this="REGEXP_REPLACE",
|
|
4130
|
+
expressions=[
|
|
4131
|
+
delimiter_arg,
|
|
4132
|
+
exp.Literal.string(
|
|
4133
|
+
r"([\[\]^.\-*+?(){}|$\\])"
|
|
4134
|
+
), # Escape problematic regex chars
|
|
4135
|
+
exp.Literal.string(
|
|
4136
|
+
r"\\\1"
|
|
4137
|
+
), # Replace with escaped version using $1 backreference
|
|
4138
|
+
exp.Literal.string("g"), # Global flag
|
|
4139
|
+
],
|
|
4140
|
+
)
|
|
4141
|
+
# CASE WHEN delimiter = '' THEN '' ELSE CONCAT('[', escaped_delimiter, ']') END
|
|
4142
|
+
regex_pattern = (
|
|
4143
|
+
exp.case()
|
|
4144
|
+
.when(delimiter_arg.eq(exp.Literal.string("")), exp.Literal.string(""))
|
|
4145
|
+
.else_(
|
|
4146
|
+
exp.func(
|
|
4147
|
+
"CONCAT",
|
|
4148
|
+
exp.Literal.string("["),
|
|
4149
|
+
escaped_delimiter,
|
|
4150
|
+
exp.Literal.string("]"),
|
|
4151
|
+
)
|
|
4152
|
+
)
|
|
4153
|
+
)
|
|
4154
|
+
|
|
4155
|
+
# STRTOK skips empty strings, so we need to filter them out
|
|
4156
|
+
# LIST_FILTER(REGEXP_SPLIT_TO_ARRAY(string, pattern), x -> x != '')[index]
|
|
4157
|
+
split_array = exp.func("REGEXP_SPLIT_TO_ARRAY", string_arg, regex_pattern)
|
|
4158
|
+
x = exp.to_identifier("x")
|
|
4159
|
+
is_empty = x.eq(exp.Literal.string(""))
|
|
4160
|
+
filtered_array = exp.func(
|
|
4161
|
+
"LIST_FILTER",
|
|
4162
|
+
split_array,
|
|
4163
|
+
exp.Lambda(this=exp.not_(is_empty.copy()), expressions=[x.copy()]),
|
|
4164
|
+
)
|
|
4165
|
+
base_func = exp.Bracket(
|
|
4166
|
+
this=filtered_array,
|
|
4167
|
+
expressions=[part_index_arg],
|
|
4168
|
+
offset=1,
|
|
4169
|
+
)
|
|
4170
|
+
|
|
4171
|
+
# Use template with the built regex pattern
|
|
4172
|
+
result = exp.replace_placeholders(
|
|
4173
|
+
self.STRTOK_TEMPLATE.copy(),
|
|
4174
|
+
string=string_arg,
|
|
4175
|
+
delimiter=delimiter_arg,
|
|
4176
|
+
part_index=part_index_arg,
|
|
4177
|
+
base_func=base_func,
|
|
4178
|
+
)
|
|
4179
|
+
|
|
4180
|
+
return self.sql(result)
|
|
4181
|
+
|
|
4182
|
+
return self.function_fallback_sql(expression)
|
|
4183
|
+
|
|
4036
4184
|
def approxquantile_sql(self, expression: exp.ApproxQuantile) -> str:
|
|
4037
4185
|
result = self.func("APPROX_QUANTILE", expression.this, expression.args.get("quantile"))
|
|
4038
4186
|
|
|
@@ -1201,6 +1201,9 @@ class Snowflake(Dialect):
|
|
|
1201
1201
|
|
|
1202
1202
|
return expr_sql
|
|
1203
1203
|
|
|
1204
|
+
def arraytostring_sql(self, expression: exp.ArrayToString) -> str:
|
|
1205
|
+
return self.func("ARRAY_TO_STRING", expression.this, expression.expression)
|
|
1206
|
+
|
|
1204
1207
|
def array_sql(self, expression: exp.Array) -> str:
|
|
1205
1208
|
expressions = expression.expressions
|
|
1206
1209
|
|
|
@@ -174,7 +174,13 @@ class ArraysZip(Expression, Func):
|
|
|
174
174
|
|
|
175
175
|
|
|
176
176
|
class ArrayToString(Expression, Func):
|
|
177
|
-
arg_types = {
|
|
177
|
+
arg_types = {
|
|
178
|
+
"this": True,
|
|
179
|
+
"expression": True,
|
|
180
|
+
"null": False,
|
|
181
|
+
"null_is_empty": False,
|
|
182
|
+
"null_delim_is_null": False,
|
|
183
|
+
}
|
|
178
184
|
_sql_names = ["ARRAY_TO_STRING", "ARRAY_JOIN"]
|
|
179
185
|
|
|
180
186
|
|
|
@@ -617,8 +617,8 @@ class Expression(Expr):
|
|
|
617
617
|
Returns the alias of the expression, or an empty string if it's not aliased.
|
|
618
618
|
"""
|
|
619
619
|
alias = self.args.get("alias")
|
|
620
|
-
if
|
|
621
|
-
return alias.name
|
|
620
|
+
if isinstance(alias, Expression):
|
|
621
|
+
return alias.name
|
|
622
622
|
return self.text("alias")
|
|
623
623
|
|
|
624
624
|
@property
|
|
@@ -177,6 +177,14 @@ class SplitPart(Expression, Func):
|
|
|
177
177
|
}
|
|
178
178
|
|
|
179
179
|
|
|
180
|
+
class Strtok(Expression, Func):
|
|
181
|
+
arg_types = {
|
|
182
|
+
"this": True,
|
|
183
|
+
"delimiter": False,
|
|
184
|
+
"part_index": False,
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
|
|
180
188
|
class StartsWith(Expression, Func):
|
|
181
189
|
_sql_names = ["STARTS_WITH", "STARTSWITH"]
|
|
182
190
|
arg_types = {"this": True, "expression": True}
|
|
@@ -933,9 +933,10 @@ class Generator(metaclass=_Generator):
|
|
|
933
933
|
comment = " " + comment if comment[0].strip() else comment
|
|
934
934
|
comment = comment + " " if comment[-1].strip() else comment
|
|
935
935
|
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
936
|
+
# Escape block comment markers to prevent premature closure or unintended nesting.
|
|
937
|
+
# This is necessary because single-line comments (--) are converted to block comments
|
|
938
|
+
# (/* */) on output, and any */ in the original text would close the comment early.
|
|
939
|
+
comment = comment.replace("*/", "* /").replace("/*", "/ *")
|
|
939
940
|
|
|
940
941
|
return comment
|
|
941
942
|
|
|
@@ -4086,6 +4087,8 @@ class Generator(metaclass=_Generator):
|
|
|
4086
4087
|
|
|
4087
4088
|
if isinstance(exprs, exp.Tuple):
|
|
4088
4089
|
exprs = exprs.expressions
|
|
4090
|
+
else:
|
|
4091
|
+
exprs = [exprs]
|
|
4089
4092
|
|
|
4090
4093
|
connective = exp.or_ if isinstance(rhs, exp.Any) else exp.and_
|
|
4091
4094
|
|