sqlglot 30.23.0__tar.gz → 30.24.0__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.23.0 → sqlglot-30.24.0}/CHANGELOG.md +65 -0
- {sqlglot-30.23.0/sqlglot.egg-info → sqlglot-30.24.0}/PKG-INFO +3 -3
- {sqlglot-30.23.0 → sqlglot-30.24.0}/sqlglot/_version.py +3 -3
- {sqlglot-30.23.0 → sqlglot-30.24.0}/sqlglot/dialects/clickhouse.py +1 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/sqlglot/dialects/dialect.py +15 -1
- {sqlglot-30.23.0 → sqlglot-30.24.0}/sqlglot/dialects/oracle.py +1 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/sqlglot/dialects/postgres.py +4 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/sqlglot/dialects/starrocks.py +17 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/sqlglot/expressions/array.py +1 -5
- {sqlglot-30.23.0 → sqlglot-30.24.0}/sqlglot/expressions/query.py +8 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/sqlglot/generator.py +31 -1
- {sqlglot-30.23.0 → sqlglot-30.24.0}/sqlglot/generators/bigquery.py +142 -1
- {sqlglot-30.23.0 → sqlglot-30.24.0}/sqlglot/generators/clickhouse.py +2 -1
- {sqlglot-30.23.0 → sqlglot-30.24.0}/sqlglot/generators/duckdb.py +36 -40
- {sqlglot-30.23.0 → sqlglot-30.24.0}/sqlglot/generators/fabric.py +5 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/sqlglot/generators/hive.py +4 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/sqlglot/generators/mysql.py +3 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/sqlglot/generators/postgres.py +8 -3
- {sqlglot-30.23.0 → sqlglot-30.24.0}/sqlglot/generators/presto.py +14 -7
- {sqlglot-30.23.0 → sqlglot-30.24.0}/sqlglot/generators/snowflake.py +15 -7
- {sqlglot-30.23.0 → sqlglot-30.24.0}/sqlglot/generators/spark2.py +22 -1
- {sqlglot-30.23.0 → sqlglot-30.24.0}/sqlglot/generators/starrocks.py +35 -4
- {sqlglot-30.23.0 → sqlglot-30.24.0}/sqlglot/generators/teradata.py +11 -1
- {sqlglot-30.23.0 → sqlglot-30.24.0}/sqlglot/helper.py +17 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/sqlglot/optimizer/annotate_types.py +24 -16
- {sqlglot-30.23.0 → sqlglot-30.24.0}/sqlglot/optimizer/merge_subqueries.py +4 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/sqlglot/optimizer/optimize_joins.py +5 -1
- {sqlglot-30.23.0 → sqlglot-30.24.0}/sqlglot/optimizer/qualify_columns.py +33 -9
- {sqlglot-30.23.0 → sqlglot-30.24.0}/sqlglot/optimizer/scope.py +8 -7
- {sqlglot-30.23.0 → sqlglot-30.24.0}/sqlglot/optimizer/simplify.py +23 -5
- {sqlglot-30.23.0 → sqlglot-30.24.0}/sqlglot/optimizer/unnest_subqueries.py +29 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/sqlglot/parser.py +145 -32
- {sqlglot-30.23.0 → sqlglot-30.24.0}/sqlglot/parsers/clickhouse.py +6 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/sqlglot/parsers/doris.py +3 -3
- {sqlglot-30.23.0 → sqlglot-30.24.0}/sqlglot/parsers/dremio.py +3 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/sqlglot/parsers/drill.py +3 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/sqlglot/parsers/duckdb.py +34 -8
- {sqlglot-30.23.0 → sqlglot-30.24.0}/sqlglot/parsers/hive.py +13 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/sqlglot/parsers/mysql.py +71 -3
- {sqlglot-30.23.0 → sqlglot-30.24.0}/sqlglot/parsers/oracle.py +3 -1
- {sqlglot-30.23.0 → sqlglot-30.24.0}/sqlglot/parsers/postgres.py +3 -1
- {sqlglot-30.23.0 → sqlglot-30.24.0}/sqlglot/parsers/presto.py +2 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/sqlglot/parsers/prql.py +2 -8
- {sqlglot-30.23.0 → sqlglot-30.24.0}/sqlglot/parsers/redshift.py +3 -1
- {sqlglot-30.23.0 → sqlglot-30.24.0}/sqlglot/parsers/singlestore.py +3 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/sqlglot/parsers/snowflake.py +4 -4
- {sqlglot-30.23.0 → sqlglot-30.24.0}/sqlglot/parsers/spark2.py +4 -1
- {sqlglot-30.23.0 → sqlglot-30.24.0}/sqlglot/parsers/sqlite.py +14 -1
- {sqlglot-30.23.0 → sqlglot-30.24.0}/sqlglot/parsers/starrocks.py +73 -10
- {sqlglot-30.23.0 → sqlglot-30.24.0}/sqlglot/parsers/teradata.py +15 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/sqlglot/parsers/trino.py +6 -1
- {sqlglot-30.23.0 → sqlglot-30.24.0}/sqlglot/tokenizer_core.py +1 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/sqlglot/transforms.py +3 -3
- {sqlglot-30.23.0 → sqlglot-30.24.0}/sqlglot/typing/__init__.py +1 -1
- {sqlglot-30.23.0 → sqlglot-30.24.0/sqlglot.egg-info}/PKG-INFO +3 -3
- {sqlglot-30.23.0 → sqlglot-30.24.0}/sqlglot.egg-info/SOURCES.txt +1 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/sqlglot.egg-info/requires.txt +2 -2
- {sqlglot-30.23.0 → sqlglot-30.24.0}/sqlglot.egg-info/scm_file_list.json +1 -0
- sqlglot-30.24.0/sqlglot.egg-info/scm_version.json +8 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/sqlglotc/setup.py +17 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/tests/dialects/test_bigquery.py +73 -1
- {sqlglot-30.23.0 → sqlglot-30.24.0}/tests/dialects/test_clickhouse.py +4 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/tests/dialects/test_dialect.py +193 -9
- {sqlglot-30.23.0 → sqlglot-30.24.0}/tests/dialects/test_duckdb.py +64 -30
- {sqlglot-30.23.0 → sqlglot-30.24.0}/tests/dialects/test_fabric.py +7 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/tests/dialects/test_hive.py +32 -13
- {sqlglot-30.23.0 → sqlglot-30.24.0}/tests/dialects/test_mysql.py +102 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/tests/dialects/test_oracle.py +12 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/tests/dialects/test_postgres.py +90 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/tests/dialects/test_presto.py +10 -16
- {sqlglot-30.23.0 → sqlglot-30.24.0}/tests/dialects/test_snowflake.py +8 -17
- {sqlglot-30.23.0 → sqlglot-30.24.0}/tests/dialects/test_spark.py +28 -11
- {sqlglot-30.23.0 → sqlglot-30.24.0}/tests/dialects/test_sqlite.py +40 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/tests/dialects/test_starrocks.py +116 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/tests/dialects/test_teradata.py +38 -1
- {sqlglot-30.23.0 → sqlglot-30.24.0}/tests/dialects/test_trino.py +125 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/tests/fixtures/optimizer/merge_subqueries.sql +48 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/tests/fixtures/optimizer/qualify_columns.sql +11 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/tests/fixtures/optimizer/simplify.sql +64 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/tests/test_build.py +2 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/tests/test_generator.py +9 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/tests/test_helper.py +21 -1
- {sqlglot-30.23.0 → sqlglot-30.24.0}/tests/test_optimizer.py +197 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/tests/test_parser.py +131 -6
- sqlglot-30.24.0/tests/test_sqlglotc.py +113 -0
- sqlglot-30.23.0/sqlglot.egg-info/scm_version.json +0 -8
- {sqlglot-30.23.0 → sqlglot-30.24.0}/.gitignore +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/.gitmodules +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/.gitpod.yml +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/.pre-commit-config.yaml +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/AGENTS.md +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/CLAUDE.md +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/CONTRIBUTING.md +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/LICENSE +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/MANIFEST.in +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/Makefile +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/README.md +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/pyproject.toml +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/setup.cfg +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/setup.py +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/sqlglot/__init__.py +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/sqlglot/__main__.py +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/sqlglot/_typing.py +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/sqlglot/anonymize.py +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/sqlglot/dialects/__init__.py +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/sqlglot/dialects/athena.py +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/sqlglot/dialects/bigquery.py +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/sqlglot/dialects/databricks.py +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/sqlglot/dialects/dax.py +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/sqlglot/dialects/doris.py +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/sqlglot/dialects/dremio.py +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/sqlglot/dialects/drill.py +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/sqlglot/dialects/druid.py +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/sqlglot/dialects/duckdb.py +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/sqlglot/dialects/dune.py +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/sqlglot/dialects/exasol.py +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/sqlglot/dialects/fabric.py +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/sqlglot/dialects/hive.py +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/sqlglot/dialects/materialize.py +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/sqlglot/dialects/mysql.py +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/sqlglot/dialects/presto.py +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/sqlglot/dialects/prql.py +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/sqlglot/dialects/redshift.py +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/sqlglot/dialects/risingwave.py +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/sqlglot/dialects/singlestore.py +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/sqlglot/dialects/snowflake.py +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/sqlglot/dialects/solr.py +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/sqlglot/dialects/spark.py +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/sqlglot/dialects/spark2.py +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/sqlglot/dialects/sqlite.py +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/sqlglot/dialects/tableau.py +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/sqlglot/dialects/teradata.py +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/sqlglot/dialects/trino.py +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/sqlglot/dialects/tsql.py +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/sqlglot/diff.py +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/sqlglot/errors.py +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/sqlglot/executor/__init__.py +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/sqlglot/executor/context.py +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/sqlglot/executor/env.py +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/sqlglot/executor/python.py +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/sqlglot/executor/table.py +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/sqlglot/expressions/__init__.py +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/sqlglot/expressions/aggregate.py +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/sqlglot/expressions/builders.py +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/sqlglot/expressions/constraints.py +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/sqlglot/expressions/core.py +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/sqlglot/expressions/datatypes.py +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/sqlglot/expressions/ddl.py +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/sqlglot/expressions/dml.py +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/sqlglot/expressions/functions.py +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/sqlglot/expressions/json.py +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/sqlglot/expressions/math.py +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/sqlglot/expressions/properties.py +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/sqlglot/expressions/string.py +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/sqlglot/expressions/temporal.py +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/sqlglot/generators/__init__.py +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/sqlglot/generators/athena.py +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/sqlglot/generators/databricks.py +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/sqlglot/generators/dax.py +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/sqlglot/generators/doris.py +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/sqlglot/generators/dremio.py +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/sqlglot/generators/drill.py +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/sqlglot/generators/druid.py +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/sqlglot/generators/dune.py +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/sqlglot/generators/exasol.py +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/sqlglot/generators/materialize.py +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/sqlglot/generators/oracle.py +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/sqlglot/generators/prql.py +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/sqlglot/generators/python.py +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/sqlglot/generators/redshift.py +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/sqlglot/generators/risingwave.py +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/sqlglot/generators/singlestore.py +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/sqlglot/generators/solr.py +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/sqlglot/generators/spark.py +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/sqlglot/generators/sqlite.py +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/sqlglot/generators/tableau.py +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/sqlglot/generators/trino.py +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/sqlglot/generators/tsql.py +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/sqlglot/jsonpath.py +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/sqlglot/lineage.py +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/sqlglot/optimizer/__init__.py +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/sqlglot/optimizer/canonicalize.py +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/sqlglot/optimizer/canonicalize_internal_names.py +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/sqlglot/optimizer/eliminate_ctes.py +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/sqlglot/optimizer/eliminate_joins.py +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/sqlglot/optimizer/eliminate_subqueries.py +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/sqlglot/optimizer/helpers.py +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/sqlglot/optimizer/isolate_table_selects.py +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/sqlglot/optimizer/journal.py +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/sqlglot/optimizer/normalize.py +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/sqlglot/optimizer/normalize_identifiers.py +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/sqlglot/optimizer/optimizer.py +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/sqlglot/optimizer/pushdown_predicates.py +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/sqlglot/optimizer/pushdown_projections.py +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/sqlglot/optimizer/qualify.py +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/sqlglot/optimizer/qualify_tables.py +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/sqlglot/optimizer/resolver.py +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/sqlglot/parsers/__init__.py +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/sqlglot/parsers/athena.py +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/sqlglot/parsers/base.py +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/sqlglot/parsers/bigquery.py +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/sqlglot/parsers/databricks.py +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/sqlglot/parsers/dax.py +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/sqlglot/parsers/druid.py +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/sqlglot/parsers/dune.py +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/sqlglot/parsers/exasol.py +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/sqlglot/parsers/fabric.py +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/sqlglot/parsers/materialize.py +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/sqlglot/parsers/risingwave.py +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/sqlglot/parsers/solr.py +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/sqlglot/parsers/spark.py +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/sqlglot/parsers/tableau.py +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/sqlglot/parsers/tsql.py +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/sqlglot/planner.py +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/sqlglot/py.typed +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/sqlglot/schema.py +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/sqlglot/serde.py +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/sqlglot/time.py +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/sqlglot/tokens.py +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/sqlglot/trie.py +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/sqlglot/typing/bigquery.py +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/sqlglot/typing/clickhouse.py +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/sqlglot/typing/databricks.py +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/sqlglot/typing/duckdb.py +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/sqlglot/typing/hive.py +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/sqlglot/typing/mysql.py +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/sqlglot/typing/postgres.py +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/sqlglot/typing/presto.py +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/sqlglot/typing/redshift.py +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/sqlglot/typing/snowflake.py +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/sqlglot/typing/spark.py +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/sqlglot/typing/spark2.py +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/sqlglot/typing/tsql.py +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/sqlglot.egg-info/dependency_links.txt +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/sqlglot.egg-info/top_level.txt +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/sqlglot.png +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/sqlglotc/MANIFEST.in +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/sqlglotc/pyproject.toml +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/tests/__init__.py +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/tests/dialects/__init__.py +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/tests/dialects/test_athena.py +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/tests/dialects/test_databricks.py +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/tests/dialects/test_dax.py +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/tests/dialects/test_doris.py +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/tests/dialects/test_dremio.py +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/tests/dialects/test_drill.py +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/tests/dialects/test_druid.py +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/tests/dialects/test_dune.py +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/tests/dialects/test_exasol.py +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/tests/dialects/test_materialize.py +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/tests/dialects/test_pipe_syntax.py +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/tests/dialects/test_prql.py +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/tests/dialects/test_redshift.py +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/tests/dialects/test_risingwave.py +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/tests/dialects/test_singlestore.py +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/tests/dialects/test_solr.py +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/tests/dialects/test_tableau.py +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/tests/dialects/test_tsql.py +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/tests/fixtures/identity.sql +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/tests/fixtures/jsonpath/LICENSE +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/tests/fixtures/jsonpath/cts.json +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/tests/fixtures/optimizer/annotate_functions.sql +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/tests/fixtures/optimizer/annotate_types.sql +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/tests/fixtures/optimizer/canonicalize.sql +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/tests/fixtures/optimizer/canonicalize_internal_names.sql +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/tests/fixtures/optimizer/eliminate_ctes.sql +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/tests/fixtures/optimizer/eliminate_joins.sql +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/tests/fixtures/optimizer/eliminate_subqueries.sql +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/tests/fixtures/optimizer/isolate_table_selects.sql +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/tests/fixtures/optimizer/normalize.sql +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/tests/fixtures/optimizer/normalize_identifiers.sql +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/tests/fixtures/optimizer/optimize_joins.sql +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/tests/fixtures/optimizer/optimizer.sql +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/tests/fixtures/optimizer/pushdown_cte_alias_columns.sql +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/tests/fixtures/optimizer/pushdown_predicates.sql +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/tests/fixtures/optimizer/pushdown_projections.sql +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/tests/fixtures/optimizer/qualify_columns__invalid.sql +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/tests/fixtures/optimizer/qualify_columns__with_invisible.sql +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/tests/fixtures/optimizer/qualify_columns_ddl.sql +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/tests/fixtures/optimizer/qualify_tables.sql +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/tests/fixtures/optimizer/quote_identifiers.sql +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/tests/fixtures/optimizer/tpc-ds/call_center.csv.gz +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/tests/fixtures/optimizer/tpc-ds/catalog_page.csv.gz +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/tests/fixtures/optimizer/tpc-ds/catalog_returns.csv.gz +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/tests/fixtures/optimizer/tpc-ds/catalog_sales.csv.gz +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/tests/fixtures/optimizer/tpc-ds/customer.csv.gz +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/tests/fixtures/optimizer/tpc-ds/customer_address.csv.gz +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/tests/fixtures/optimizer/tpc-ds/customer_demographics.csv.gz +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/tests/fixtures/optimizer/tpc-ds/date_dim.csv.gz +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/tests/fixtures/optimizer/tpc-ds/household_demographics.csv.gz +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/tests/fixtures/optimizer/tpc-ds/income_band.csv.gz +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/tests/fixtures/optimizer/tpc-ds/inventory.csv.gz +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/tests/fixtures/optimizer/tpc-ds/item.csv.gz +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/tests/fixtures/optimizer/tpc-ds/promotion.csv.gz +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/tests/fixtures/optimizer/tpc-ds/reason.csv.gz +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/tests/fixtures/optimizer/tpc-ds/ship_mode.csv.gz +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/tests/fixtures/optimizer/tpc-ds/store.csv.gz +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/tests/fixtures/optimizer/tpc-ds/store_returns.csv.gz +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/tests/fixtures/optimizer/tpc-ds/store_sales.csv.gz +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/tests/fixtures/optimizer/tpc-ds/time_dim.csv.gz +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/tests/fixtures/optimizer/tpc-ds/tpc-ds.sql +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/tests/fixtures/optimizer/tpc-ds/warehouse.csv.gz +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/tests/fixtures/optimizer/tpc-ds/web_page.csv.gz +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/tests/fixtures/optimizer/tpc-ds/web_returns.csv.gz +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/tests/fixtures/optimizer/tpc-ds/web_sales.csv.gz +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/tests/fixtures/optimizer/tpc-ds/web_site.csv.gz +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/tests/fixtures/optimizer/tpc-h/customer.csv.gz +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/tests/fixtures/optimizer/tpc-h/lineitem.csv.gz +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/tests/fixtures/optimizer/tpc-h/nation.csv.gz +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/tests/fixtures/optimizer/tpc-h/orders.csv.gz +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/tests/fixtures/optimizer/tpc-h/part.csv.gz +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/tests/fixtures/optimizer/tpc-h/partsupp.csv.gz +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/tests/fixtures/optimizer/tpc-h/region.csv.gz +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/tests/fixtures/optimizer/tpc-h/supplier.csv.gz +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/tests/fixtures/optimizer/tpc-h/tpc-h.sql +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/tests/fixtures/optimizer/unnest_subqueries.sql +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/tests/fixtures/partial.sql +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/tests/fixtures/pretty.sql +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/tests/gen_fixtures.py +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/tests/helpers.py +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/tests/leakcheck.py +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/tests/sqlglot/__init__.py +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/tests/test_anonymize.py +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/tests/test_dialect_entry_points.py +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/tests/test_dialect_imports.py +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/tests/test_diff.py +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/tests/test_docs.py +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/tests/test_errors.py +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/tests/test_executor.py +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/tests/test_expressions.py +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/tests/test_integration_loader.py +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/tests/test_jsonpath.py +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/tests/test_lineage.py +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/tests/test_schema.py +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/tests/test_serde.py +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/tests/test_time.py +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/tests/test_tokens.py +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/tests/test_transforms.py +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/tests/test_transpile.py +0 -0
- {sqlglot-30.23.0 → sqlglot-30.24.0}/tests/test_typing.py +0 -0
|
@@ -1,6 +1,70 @@
|
|
|
1
1
|
Changelog
|
|
2
2
|
=========
|
|
3
3
|
|
|
4
|
+
## [v30.23.0] - 2026-10-14
|
|
5
|
+
### :boom: BREAKING CHANGES
|
|
6
|
+
- due to [`cf39265`](https://github.com/tobymao/sqlglot/commit/cf39265a3e8efd8c32bab7f9c9b4f123fdfbf682) - hash flag for case-sensitive nodes [CLAUDE] *(PR [#8599](https://github.com/tobymao/sqlglot/pull/8599) by [@laravioli](https://github.com/laravioli))*:
|
|
7
|
+
|
|
8
|
+
hash flag for case-sensitive nodes [CLAUDE] (#8599)
|
|
9
|
+
|
|
10
|
+
- due to [`4d7d7ca`](https://github.com/tobymao/sqlglot/commit/4d7d7ca94250269dc1903d7175b7b8aa96e9a480) - generate JSONExtractRaw for JSON-valued extraction *(PR [#8601](https://github.com/tobymao/sqlglot/pull/8601) by [@ebarkhordar](https://github.com/ebarkhordar))*:
|
|
11
|
+
|
|
12
|
+
generate JSONExtractRaw for JSON-valued extraction (#8601)
|
|
13
|
+
|
|
14
|
+
- due to [`623dc88`](https://github.com/tobymao/sqlglot/commit/623dc8889ba7bffa9b006fd1d1641715b73d5ce4) - infer correct types for temporal interval arithmetic *(PR [#8622](https://github.com/tobymao/sqlglot/pull/8622) by [@georgesittas](https://github.com/georgesittas))*:
|
|
15
|
+
|
|
16
|
+
infer correct types for temporal interval arithmetic (#8622)
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
### :sparkles: New Features
|
|
20
|
+
- [`8abe7f8`](https://github.com/tobymao/sqlglot/commit/8abe7f8382c80f95cb1e5a8a985969f6c11fd03a) - **starrocks**: parse TIME_SLICE into exp.TimeSlice [CLAUDE] *(PR [#8555](https://github.com/tobymao/sqlglot/pull/8555) by [@nytai](https://github.com/nytai))*
|
|
21
|
+
- [`f3a6eb9`](https://github.com/tobymao/sqlglot/commit/f3a6eb95e424ef03bf20fca05a0431a666946e90) - **doris**: parse full-text search operators [CLAUDE] *(PR [#8585](https://github.com/tobymao/sqlglot/pull/8585) by [@kaya-abdullah](https://github.com/kaya-abdullah))*
|
|
22
|
+
- :arrow_lower_right: *addresses issue [#8584](https://github.com/tobymao/sqlglot/issues/8584) opened by [@kaya-abdullah](https://github.com/kaya-abdullah)*
|
|
23
|
+
- [`3ba19ee`](https://github.com/tobymao/sqlglot/commit/3ba19eedd7b381f990f9926266457eda7a60095b) - **starrocks**: support AGGREGATE KEY tables [CLAUDE] *(PR [#8591](https://github.com/tobymao/sqlglot/pull/8591) by [@nytai](https://github.com/nytai))*
|
|
24
|
+
- [`9114355`](https://github.com/tobymao/sqlglot/commit/9114355463fd02a9b505c869edb0561503a07b19) - **mysql**: Allow constraints without names. *(PR [#8600](https://github.com/tobymao/sqlglot/pull/8600) by [@burnison](https://github.com/burnison))*
|
|
25
|
+
- [`6202d94`](https://github.com/tobymao/sqlglot/commit/6202d94764305621117dc6229cda79575ca103e5) - **starrocks**: support HLL columns and the HLL_UNION aggregation type [CLAUDE] *(PR [#8612](https://github.com/tobymao/sqlglot/pull/8612) by [@nytai](https://github.com/nytai))*
|
|
26
|
+
- [`0b00178`](https://github.com/tobymao/sqlglot/commit/0b0017821590b08497529d37387396adb6c3aa5b) - **spark**: parse all ALTER TABLE DROP COLUMN[S] forms [CLAUDE] *(PR [#8611](https://github.com/tobymao/sqlglot/pull/8611) by [@tsamaras](https://github.com/tsamaras))*
|
|
27
|
+
- [`59a96d8`](https://github.com/tobymao/sqlglot/commit/59a96d868a6b8ed114ac3e216201106fea8bc351) - **starrocks**: support REFRESH MATERIALIZED VIEW options [CLAUDE] *(PR [#8613](https://github.com/tobymao/sqlglot/pull/8613) by [@nytai](https://github.com/nytai))*
|
|
28
|
+
- [`676ba36`](https://github.com/tobymao/sqlglot/commit/676ba365497215dadf89c3fa57f4872529745650) - **mysql**: Support named `FOREIGN KEY` indexes. *(PR [#8615](https://github.com/tobymao/sqlglot/pull/8615) by [@burnison](https://github.com/burnison))*
|
|
29
|
+
- [`b679d0c`](https://github.com/tobymao/sqlglot/commit/b679d0cf8cad5bab7bb5004d9b8f8ce51d542b42) - **databricks**: match_recognize support closes [#8617](https://github.com/tobymao/sqlglot/pull/8617) *(commit by [@georgesittas](https://github.com/georgesittas))*
|
|
30
|
+
|
|
31
|
+
### :bug: Bug Fixes
|
|
32
|
+
- [`a00dc2e`](https://github.com/tobymao/sqlglot/commit/a00dc2e5c489214bea53bacbbeba8713f21ebce1) - **postgres**: improve json_value support closes [#8579](https://github.com/tobymao/sqlglot/pull/8579) *(commit by [@georgesittas](https://github.com/georgesittas))*
|
|
33
|
+
- [`ffb9721`](https://github.com/tobymao/sqlglot/commit/ffb9721df98984c62817701ec8cd895cb3b1ee82) - **oracle**: tokenize q'...' quoted string literals [CLAUDE] *(PR [#8582](https://github.com/tobymao/sqlglot/pull/8582) by [@DylanMerigaud](https://github.com/DylanMerigaud))*
|
|
34
|
+
- [`e237d59`](https://github.com/tobymao/sqlglot/commit/e237d5980e8084cd2eceb874280efc3f3369c0ba) - **optimizer**: keep the alias outside of COALESCE when unnesting a COUNT subquery [CLAUDE] *(PR [#8589](https://github.com/tobymao/sqlglot/pull/8589) by [@anishmehta24](https://github.com/anishmehta24))*
|
|
35
|
+
- [`98bedf6`](https://github.com/tobymao/sqlglot/commit/98bedf649b244d321782a213944320d54f7cc868) - **oracle**: parse partition clauses and flashback queries [CODEX] *(PR [#8588](https://github.com/tobymao/sqlglot/pull/8588) by [@yousefissa](https://github.com/yousefissa))*
|
|
36
|
+
- :arrow_lower_right: *fixes issue [#8587](https://github.com/tobymao/sqlglot/issues/8587) opened by [@cofin](https://github.com/cofin)*
|
|
37
|
+
- [`09481ce`](https://github.com/tobymao/sqlglot/commit/09481cec085106bc77fb584e4d322f7e179a5a11) - **optimizer**: qualify bare USING columns after SEMI/ANTI JOIN closes [#8590](https://github.com/tobymao/sqlglot/pull/8590) *(PR [#8592](https://github.com/tobymao/sqlglot/pull/8592) by [@ansh-rohilla](https://github.com/ansh-rohilla))*
|
|
38
|
+
- :arrow_lower_right: *fixes issue [#8590](https://github.com/tobymao/sqlglot/issues/8590) opened by [@jackr-xceleration](https://github.com/jackr-xceleration)*
|
|
39
|
+
- [`df0a300`](https://github.com/tobymao/sqlglot/commit/df0a3006c485010e2bde4f2b6ce16594885772f0) - **duckdb**: append on 1-based ARRAY_INSERT -1 *(PR [#8597](https://github.com/tobymao/sqlglot/pull/8597) by [@siddharthsarda](https://github.com/siddharthsarda))*
|
|
40
|
+
- [`7d9a6cd`](https://github.com/tobymao/sqlglot/commit/7d9a6cd599c41e4bd886c757e1b9e60b39bef70c) - allow `EXTERNAL FUNCTION` in Athena `CTAS` *(PR [#8602](https://github.com/tobymao/sqlglot/pull/8602) by [@matthias-Q](https://github.com/matthias-Q))*
|
|
41
|
+
- [`e38929e`](https://github.com/tobymao/sqlglot/commit/e38929edd78a20f74fc19fee819e14ac23add687) - **teradata**: default window aggregate frame to the whole partition [CLAUDE] *(PR [#8596](https://github.com/tobymao/sqlglot/pull/8596) by [@bhuvan-uda](https://github.com/bhuvan-uda))*
|
|
42
|
+
- :arrow_lower_right: *fixes issue [#8595](https://github.com/tobymao/sqlglot/issues/8595) opened by [@bhuvan-uda](https://github.com/bhuvan-uda)*
|
|
43
|
+
- [`cf39265`](https://github.com/tobymao/sqlglot/commit/cf39265a3e8efd8c32bab7f9c9b4f123fdfbf682) - **expressions**: hash flag for case-sensitive nodes [CLAUDE] *(PR [#8599](https://github.com/tobymao/sqlglot/pull/8599) by [@laravioli](https://github.com/laravioli))*
|
|
44
|
+
- :arrow_lower_right: *fixes issue [#8598](https://github.com/tobymao/sqlglot/issues/8598) opened by [@laravioli](https://github.com/laravioli)*
|
|
45
|
+
- [`ab0a291`](https://github.com/tobymao/sqlglot/commit/ab0a291f91f1ba8c32058340bf76738c4ea685ea) - **oracle**: normalize flashback timestamps and simplify parsing *(PR [#8608](https://github.com/tobymao/sqlglot/pull/8608) by [@georgesittas](https://github.com/georgesittas))*
|
|
46
|
+
- [`a0cc28b`](https://github.com/tobymao/sqlglot/commit/a0cc28b91c3d186801d478e83967e967b86c90dd) - **doris**: round-trip MATCH operands and quoted analyzers *(PR [#8607](https://github.com/tobymao/sqlglot/pull/8607) by [@georgesittas](https://github.com/georgesittas))*
|
|
47
|
+
- [`4d7d7ca`](https://github.com/tobymao/sqlglot/commit/4d7d7ca94250269dc1903d7175b7b8aa96e9a480) - **clickhouse**: generate JSONExtractRaw for JSON-valued extraction *(PR [#8601](https://github.com/tobymao/sqlglot/pull/8601) by [@ebarkhordar](https://github.com/ebarkhordar))*
|
|
48
|
+
- [`1f8d15b`](https://github.com/tobymao/sqlglot/commit/1f8d15bbd68586704666533b21a5b35d710d68f0) - convert DuckDB ARRAY_SLICE endpoints to SLICE lengths *(PR [#8609](https://github.com/tobymao/sqlglot/pull/8609) by [@georgesittas](https://github.com/georgesittas))*
|
|
49
|
+
- [`61c3ca4`](https://github.com/tobymao/sqlglot/commit/61c3ca4479c167d9c90d51f73184568769fa0635) - **oracle**: parse CREATE TABLE TABLESPACE *(PR [#8605](https://github.com/tobymao/sqlglot/pull/8605) by [@cmodiano](https://github.com/cmodiano))*
|
|
50
|
+
- [`08f2405`](https://github.com/tobymao/sqlglot/commit/08f2405cfddc874f4366cbcca9e25233fcb11281) - **oracle**: expand alternative quoting and support national literals *(PR [#8606](https://github.com/tobymao/sqlglot/pull/8606) by [@georgesittas](https://github.com/georgesittas))*
|
|
51
|
+
- :arrow_lower_right: *fixes issue [#8580](https://github.com/tobymao/sqlglot/issues/8580) opened by [@cmodiano](https://github.com/cmodiano)*
|
|
52
|
+
- [`5b949bd`](https://github.com/tobymao/sqlglot/commit/5b949bd6b7f1db1474a87ac34d3a9246fa7de237) - **oracle**: parse CREATE TABLE physical attributes and storage clauses closes [#8581](https://github.com/tobymao/sqlglot/pull/8581) *(commit by [@georgesittas](https://github.com/georgesittas))*
|
|
53
|
+
- [`ba643d3`](https://github.com/tobymao/sqlglot/commit/ba643d33285475774c3253551e1ed18ac89e6c22) - **clickhouse**: transpile RegexpCount to countMatches [CLAUDE] *(PR [#8616](https://github.com/tobymao/sqlglot/pull/8616) by [@ekut](https://github.com/ekut))*
|
|
54
|
+
- [`623dc88`](https://github.com/tobymao/sqlglot/commit/623dc8889ba7bffa9b006fd1d1641715b73d5ce4) - **duckdb**: infer correct types for temporal interval arithmetic *(PR [#8622](https://github.com/tobymao/sqlglot/pull/8622) by [@georgesittas](https://github.com/georgesittas))*
|
|
55
|
+
- [`b1b244b`](https://github.com/tobymao/sqlglot/commit/b1b244b1f38a3000c94a7b21ee6dfae1959dd4b2) - **optimizer**: qualify columns for SPLIT_TO_TABLE *(PR [#8625](https://github.com/tobymao/sqlglot/pull/8625) by [@andrjohns](https://github.com/andrjohns))*
|
|
56
|
+
- [`e92c222`](https://github.com/tobymao/sqlglot/commit/e92c22287ff73a66e9dece115acedb81133f0dbf) - **duckdb**: cast array elements to text before applying the ARRAY_TO_STRING null replacement [CLAUDE] *(PR [#8627](https://github.com/tobymao/sqlglot/pull/8627) by [@anishmehta24](https://github.com/anishmehta24))*
|
|
57
|
+
- [`fbda0b9`](https://github.com/tobymao/sqlglot/commit/fbda0b91481d679f17844af15fb998cc559533be) - **parser**: keep the whole statement when REFRESH falls back to a cmd *(PR [#8621](https://github.com/tobymao/sqlglot/pull/8621) by [@nytai](https://github.com/nytai))*
|
|
58
|
+
- [`fdba492`](https://github.com/tobymao/sqlglot/commit/fdba492cec5a1fbe012add7f1aed18f46739c2a3) - **optimizer**: include semi/anti join refs when identifying alias collisions *(PR [#8623](https://github.com/tobymao/sqlglot/pull/8623) by [@treysp](https://github.com/treysp))*
|
|
59
|
+
- [`2c7b928`](https://github.com/tobymao/sqlglot/commit/2c7b928071ed32e72b218011a1a3c011dba26b24) - **athena**: route by each engine's rules when the combined tokenizer fails [CLAUDE] *(PR [#8629](https://github.com/tobymao/sqlglot/pull/8629) by [@masiljangajji](https://github.com/masiljangajji))*
|
|
60
|
+
- :arrow_lower_right: *fixes issue [#8628](https://github.com/tobymao/sqlglot/issues/8628) opened by [@masiljangajji](https://github.com/masiljangajji)*
|
|
61
|
+
- [`ad8764a`](https://github.com/tobymao/sqlglot/commit/ad8764a0436a7b5c500b783ebe50dbf20c1e477c) - keep a replacement's grouping in replace_placeholders *(PR [#8624](https://github.com/tobymao/sqlglot/pull/8624) by [@tobymao](https://github.com/tobymao))*
|
|
62
|
+
|
|
63
|
+
### :wrench: Chores
|
|
64
|
+
- [`579789d`](https://github.com/tobymao/sqlglot/commit/579789dc3d368daf6aa0919ed5c0994187472a4b) - add support for Python 3.15 *(PR [#8586](https://github.com/tobymao/sqlglot/pull/8586) by [@Viicos](https://github.com/Viicos))*
|
|
65
|
+
- [`c0a9457`](https://github.com/tobymao/sqlglot/commit/c0a945740e55facdc7120c17cda2771dc55c7903) - **mysql**: tests for named FOREIGN KEY indexes *(commit by [@geooo109](https://github.com/geooo109))*
|
|
66
|
+
|
|
67
|
+
|
|
4
68
|
## [v30.22.0] - 2026-10-09
|
|
5
69
|
### :boom: BREAKING CHANGES
|
|
6
70
|
- due to [`5d997d9`](https://github.com/tobymao/sqlglot/commit/5d997d94d8041ed12db5abe7a1155b30df057b43) - Parse bare `ALTER TABLE ... DROP c`. *(PR [#8432](https://github.com/tobymao/sqlglot/pull/8432) by [@burnison](https://github.com/burnison))*:
|
|
@@ -16239,3 +16303,4 @@ pip install "sqlglot[c]" # compiled — faster, but no subclassing
|
|
|
16239
16303
|
[v30.20.0]: https://github.com/tobymao/sqlglot/compare/v30.19.0...v30.20.0
|
|
16240
16304
|
[v30.21.0]: https://github.com/tobymao/sqlglot/compare/v30.20.0...v30.21.0
|
|
16241
16305
|
[v30.22.0]: https://github.com/tobymao/sqlglot/compare/v30.21.0...v30.22.0
|
|
16306
|
+
[v30.23.0]: https://github.com/tobymao/sqlglot/compare/v30.22.0...v30.23.0
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: sqlglot
|
|
3
|
-
Version: 30.
|
|
3
|
+
Version: 30.24.0
|
|
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
|
|
@@ -34,10 +34,10 @@ Requires-Dist: types-pytz; extra == "dev"
|
|
|
34
34
|
Requires-Dist: typing_extensions; extra == "dev"
|
|
35
35
|
Requires-Dist: pyperf; extra == "dev"
|
|
36
36
|
Provides-Extra: c
|
|
37
|
-
Requires-Dist: sqlglotc==30.
|
|
37
|
+
Requires-Dist: sqlglotc==30.24.0; python_version >= "3.10" and extra == "c"
|
|
38
38
|
Provides-Extra: rs
|
|
39
39
|
Requires-Dist: sqlglotrs==0.13.0; extra == "rs"
|
|
40
|
-
Requires-Dist: sqlglotc==30.
|
|
40
|
+
Requires-Dist: sqlglotc==30.24.0; python_version >= "3.10" and extra == "rs"
|
|
41
41
|
Dynamic: license-file
|
|
42
42
|
Dynamic: provides-extra
|
|
43
43
|
|
|
@@ -18,7 +18,7 @@ version_tuple: tuple[int | str, ...]
|
|
|
18
18
|
commit_id: str | None
|
|
19
19
|
__commit_id__: str | None
|
|
20
20
|
|
|
21
|
-
__version__ = version = '30.
|
|
22
|
-
__version_tuple__ = version_tuple = (30,
|
|
21
|
+
__version__ = version = '30.24.0'
|
|
22
|
+
__version_tuple__ = version_tuple = (30, 24, 0)
|
|
23
23
|
|
|
24
|
-
__commit_id__ = commit_id = '
|
|
24
|
+
__commit_id__ = commit_id = 'g5d588c0f3'
|
|
@@ -2140,7 +2140,10 @@ def is_parse_json(expression: exp.Expr) -> bool:
|
|
|
2140
2140
|
|
|
2141
2141
|
|
|
2142
2142
|
def isnull_to_is_null(args: BuilderArgs) -> exp.Expr:
|
|
2143
|
-
|
|
2143
|
+
this = seq_get(args, 0)
|
|
2144
|
+
if isinstance(this, (exp.Predicate, exp.Connector, exp.Not)):
|
|
2145
|
+
this = exp.Paren(this=this)
|
|
2146
|
+
return exp.Paren(this=exp.Is(this=this, expression=exp.null()))
|
|
2144
2147
|
|
|
2145
2148
|
|
|
2146
2149
|
def generatedasidentitycolumnconstraint_sql(
|
|
@@ -2774,6 +2777,17 @@ def build_timetostr_or_tochar(
|
|
|
2774
2777
|
return exp.ToChar.from_arg_list(args)
|
|
2775
2778
|
|
|
2776
2779
|
|
|
2780
|
+
def array_sort_order(expression: exp.ArraySort) -> tuple[bool, bool | None] | None:
|
|
2781
|
+
"""Whether an ArraySort is ascending and puts NULLs first, or None if either isn't a literal."""
|
|
2782
|
+
asc = expression.args.get("asc") or exp.true()
|
|
2783
|
+
nulls_first = expression.args.get("nulls_first")
|
|
2784
|
+
if not isinstance(asc, exp.Boolean):
|
|
2785
|
+
return None
|
|
2786
|
+
if nulls_first is None:
|
|
2787
|
+
return asc.this, None
|
|
2788
|
+
return (asc.this, nulls_first.this) if isinstance(nulls_first, exp.Boolean) else None
|
|
2789
|
+
|
|
2790
|
+
|
|
2777
2791
|
def build_replace_with_optional_replacement(args: BuilderArgs) -> exp.Replace:
|
|
2778
2792
|
return exp.Replace(
|
|
2779
2793
|
this=seq_get(args, 0),
|
|
@@ -37,6 +37,7 @@ class Oracle(Dialect):
|
|
|
37
37
|
"HH12": "%I", # alias for HH
|
|
38
38
|
"HH24": "%H", # Hour of day (0-23)
|
|
39
39
|
"IW": "%V", # Calendar week of year (1-52 or 1-53), as defined by the ISO 8601 standard
|
|
40
|
+
"IYYY": "%G", # 4-digit year of the ISO 8601 week-numbering calendar
|
|
40
41
|
"MI": "%M", # Minute (0-59)
|
|
41
42
|
"MM": "%m", # Month (01-12; January = 01)
|
|
42
43
|
"MON": "%b", # Abbreviated name of month
|
|
@@ -44,6 +44,10 @@ class Postgres(Dialect):
|
|
|
44
44
|
"FMSS": "%-S", # Second
|
|
45
45
|
"HH12": "%I", # 09
|
|
46
46
|
"HH24": "%H", # 09
|
|
47
|
+
"iw": "%V", # ISO 8601 week of year
|
|
48
|
+
"IW": "%V", # ISO 8601 week of year
|
|
49
|
+
"iyyy": "%G", # ISO 8601 week-numbering year
|
|
50
|
+
"IYYY": "%G", # ISO 8601 week-numbering year
|
|
47
51
|
"mi": "%M", # zero padded minute
|
|
48
52
|
"MI": "%M", # zero padded minute
|
|
49
53
|
"mm": "%m", # 01
|
|
@@ -18,16 +18,33 @@ class StarRocks(MySQL):
|
|
|
18
18
|
}
|
|
19
19
|
|
|
20
20
|
class Tokenizer(MySQL.Tokenizer):
|
|
21
|
+
# Unlike MySQL, "#" doesn't start a comment
|
|
22
|
+
COMMENTS = ["--", ("/*", "*/")]
|
|
21
23
|
DASH_COMMENT_REQUIRES_BOUNDARY = False
|
|
22
24
|
COMMENTS_TERMINATE_AT_NEWLINE_ONLY = False
|
|
23
25
|
|
|
24
26
|
KEYWORDS = {
|
|
25
27
|
**MySQL.Tokenizer.KEYWORDS,
|
|
28
|
+
"ADMIN": TokenType.COMMAND,
|
|
29
|
+
"BACKUP": TokenType.COMMAND,
|
|
30
|
+
"CANCEL": TokenType.COMMAND,
|
|
31
|
+
"DEALLOCATE": TokenType.COMMAND,
|
|
32
|
+
"EXPORT": TokenType.COMMAND,
|
|
26
33
|
"HLL": TokenType.HLLSKETCH,
|
|
34
|
+
"INSTALL": TokenType.COMMAND,
|
|
27
35
|
"LARGEINT": TokenType.INT128,
|
|
36
|
+
"PAUSE": TokenType.COMMAND,
|
|
37
|
+
"RECOVER": TokenType.COMMAND,
|
|
28
38
|
"REFRESH": TokenType.REFRESH,
|
|
39
|
+
"RESTORE": TokenType.COMMAND,
|
|
40
|
+
"RESUME": TokenType.COMMAND,
|
|
41
|
+
"STOP": TokenType.COMMAND,
|
|
42
|
+
"SUBMIT": TokenType.COMMAND,
|
|
43
|
+
"UNINSTALL": TokenType.COMMAND,
|
|
29
44
|
}
|
|
30
45
|
KEYWORDS.pop("IGNORE")
|
|
46
|
+
KEYWORDS.pop("#>")
|
|
47
|
+
KEYWORDS.pop("#>>")
|
|
31
48
|
|
|
32
49
|
Parser = StarRocksParser
|
|
33
50
|
|
|
@@ -98,17 +98,13 @@ class ArraySlice(Expression, Func):
|
|
|
98
98
|
|
|
99
99
|
|
|
100
100
|
class ArraySort(Expression, Func):
|
|
101
|
-
arg_types = {"this": True, "expression": False}
|
|
101
|
+
arg_types = {"this": True, "expression": False, "asc": False, "nulls_first": False}
|
|
102
102
|
|
|
103
103
|
|
|
104
104
|
class Shuffle(Expression, Func):
|
|
105
105
|
pass
|
|
106
106
|
|
|
107
107
|
|
|
108
|
-
class SortArray(Expression, Func):
|
|
109
|
-
arg_types = {"this": True, "asc": False, "nulls_first": False}
|
|
110
|
-
|
|
111
|
-
|
|
112
108
|
# Array predicates / search
|
|
113
109
|
|
|
114
110
|
|
|
@@ -1938,6 +1938,10 @@ class WindowSpec(Expression):
|
|
|
1938
1938
|
}
|
|
1939
1939
|
|
|
1940
1940
|
|
|
1941
|
+
class PartitionByExcluding(Expression):
|
|
1942
|
+
arg_types = {"expressions": True}
|
|
1943
|
+
|
|
1944
|
+
|
|
1941
1945
|
class PreWhere(Expression):
|
|
1942
1946
|
pass
|
|
1943
1947
|
|
|
@@ -2020,6 +2024,10 @@ class DropPartition(Expression):
|
|
|
2020
2024
|
arg_types = {"expressions": True, "exists": False}
|
|
2021
2025
|
|
|
2022
2026
|
|
|
2027
|
+
class ReplaceColumns(Expression):
|
|
2028
|
+
arg_types = {"expressions": True}
|
|
2029
|
+
|
|
2030
|
+
|
|
2023
2031
|
class ReplacePartition(Expression):
|
|
2024
2032
|
arg_types = {"expression": True, "source": True}
|
|
2025
2033
|
|
|
@@ -2178,6 +2178,7 @@ class Generator:
|
|
|
2178
2178
|
property_name = exp.Properties.PROPERTY_TO_NAME.get(property_cls)
|
|
2179
2179
|
if not property_name:
|
|
2180
2180
|
self.unsupported(f"Unsupported property {expression.key}")
|
|
2181
|
+
return ""
|
|
2181
2182
|
|
|
2182
2183
|
return f"{property_name}={self.sql(expression, 'this')}"
|
|
2183
2184
|
|
|
@@ -2319,6 +2320,10 @@ class Generator:
|
|
|
2319
2320
|
override = " OVERRIDE" if expression.args.get("override") else ""
|
|
2320
2321
|
return f"LOCKING {kind}{this}{for_or_in} {lock_type}{override}"
|
|
2321
2322
|
|
|
2323
|
+
def lockingstatement_sql(self, expression: exp.LockingStatement) -> str:
|
|
2324
|
+
self.unsupported("LOCKING request modifier is not supported")
|
|
2325
|
+
return self.sql(expression, "expression")
|
|
2326
|
+
|
|
2322
2327
|
def withdataproperty_sql(self, expression: exp.WithDataProperty) -> str:
|
|
2323
2328
|
data_sql = f"WITH {'NO ' if expression.args.get('no') else ''}DATA"
|
|
2324
2329
|
statistics = expression.args.get("statistics")
|
|
@@ -2561,6 +2566,10 @@ class Generator:
|
|
|
2561
2566
|
expression: exp.TableSample,
|
|
2562
2567
|
tablesample_keyword: str | None = None,
|
|
2563
2568
|
) -> str:
|
|
2569
|
+
if expression.expressions:
|
|
2570
|
+
self.unsupported("Multiple sample sets are not supported")
|
|
2571
|
+
return ""
|
|
2572
|
+
|
|
2564
2573
|
method = self.sql(expression, "method")
|
|
2565
2574
|
method = f"{method} " if method and self.TABLESAMPLE_WITH_METHOD else ""
|
|
2566
2575
|
numerator = self.sql(expression, "bucket_numerator")
|
|
@@ -3638,6 +3647,9 @@ class Generator:
|
|
|
3638
3647
|
partition = self.expressions(expression, key="partition_by", flat=True)
|
|
3639
3648
|
return f"PARTITION BY {partition}" if partition else ""
|
|
3640
3649
|
|
|
3650
|
+
def partitionbyexcluding_sql(self, expression: exp.PartitionByExcluding) -> str:
|
|
3651
|
+
return f"EXCLUDING {self.expressions(expression, flat=True)}"
|
|
3652
|
+
|
|
3641
3653
|
def windowspec_sql(self, expression: exp.WindowSpec) -> str:
|
|
3642
3654
|
kind = self.sql(expression, "kind")
|
|
3643
3655
|
start = csv(self.sql(expression, "start"), self.sql(expression, "start_side"), sep=" ")
|
|
@@ -4517,6 +4529,9 @@ class Generator:
|
|
|
4517
4529
|
def addconstraint_sql(self, expression: exp.AddConstraint) -> str:
|
|
4518
4530
|
return f"ADD {self.expressions(expression, indent=False)}"
|
|
4519
4531
|
|
|
4532
|
+
def replacecolumns_sql(self, expression: exp.ReplaceColumns) -> str:
|
|
4533
|
+
return f"REPLACE COLUMNS ({self.expressions(expression, flat=True)})"
|
|
4534
|
+
|
|
4520
4535
|
def addpartition_sql(self, expression: exp.AddPartition) -> str:
|
|
4521
4536
|
exists = "IF NOT EXISTS " if expression.args.get("exists") else ""
|
|
4522
4537
|
location = self.sql(expression, "location")
|
|
@@ -4771,14 +4786,22 @@ class Generator:
|
|
|
4771
4786
|
sqls: list[str] = []
|
|
4772
4787
|
stack: list[None | str | exp.Expr] = [expression]
|
|
4773
4788
|
binary_type = type(expression)
|
|
4789
|
+
is_is = binary_type is exp.Is and op in ("IS", "IS NOT")
|
|
4790
|
+
negate = expression.args.get("negate")
|
|
4774
4791
|
|
|
4775
4792
|
while stack:
|
|
4776
4793
|
node = stack.pop()
|
|
4777
4794
|
|
|
4778
|
-
if type(node) is binary_type
|
|
4795
|
+
if type(node) is binary_type and (
|
|
4796
|
+
node is expression
|
|
4797
|
+
or (is_is and not isinstance(node.expression, exp.Boolean))
|
|
4798
|
+
or node.args.get("negate") == negate
|
|
4799
|
+
):
|
|
4779
4800
|
op_func = node.args.get("operator")
|
|
4780
4801
|
if op_func:
|
|
4781
4802
|
op = f"OPERATOR({self.sql(op_func)})"
|
|
4803
|
+
elif is_is:
|
|
4804
|
+
op = "IS NOT" if node.args.get("negate") else "IS"
|
|
4782
4805
|
|
|
4783
4806
|
stack.append(node.args.get("expression"))
|
|
4784
4807
|
stack.append(f" {self.maybe_comment(op, comments=node.comments)} ")
|
|
@@ -6053,6 +6076,13 @@ class Generator:
|
|
|
6053
6076
|
exp.TimestampDiff(this=expression.this, expression=start_ts, unit=exp.var("SECONDS"))
|
|
6054
6077
|
)
|
|
6055
6078
|
|
|
6079
|
+
def arraysort_sql(self, expression: exp.ArraySort) -> str:
|
|
6080
|
+
asc = expression.args.get("asc")
|
|
6081
|
+
nulls_first = expression.args.get("nulls_first")
|
|
6082
|
+
if (asc and asc != exp.true()) or (nulls_first and nulls_first != exp.false()):
|
|
6083
|
+
self.unsupported("ARRAY_SORT only sorts ascending with NULLs last")
|
|
6084
|
+
return self.func("ARRAY_SORT", expression.this, expression.expression)
|
|
6085
|
+
|
|
6056
6086
|
def arraysize_sql(self, expression: exp.ArraySize) -> str:
|
|
6057
6087
|
dim = expression.expression
|
|
6058
6088
|
|
|
@@ -3,10 +3,13 @@ from __future__ import annotations
|
|
|
3
3
|
import logging
|
|
4
4
|
import re
|
|
5
5
|
import typing as t
|
|
6
|
+
from decimal import Decimal
|
|
7
|
+
from fractions import Fraction
|
|
6
8
|
|
|
7
9
|
from sqlglot import exp, generator, transforms
|
|
8
10
|
from sqlglot.dialects.dialect import (
|
|
9
11
|
arg_max_or_min_no_count,
|
|
12
|
+
array_sort_order,
|
|
10
13
|
date_add_interval_sql,
|
|
11
14
|
datestrtodate_sql,
|
|
12
15
|
filter_array_using_unnest,
|
|
@@ -176,6 +179,90 @@ def _array_contains_sql(self: BigQueryGenerator, expression: exp.ArrayContains)
|
|
|
176
179
|
)
|
|
177
180
|
|
|
178
181
|
|
|
182
|
+
def _widen_decimal(expression: exp.Expr) -> exp.Expr:
|
|
183
|
+
# NUMERIC holds at most 29 integer and 9 fractional digits, e.g. DECIMAL(38, 0) needs BIGNUMERIC
|
|
184
|
+
for node in expression.find_all(exp.DataType):
|
|
185
|
+
if node.is_type(exp.DType.DECIMAL) and node.expressions:
|
|
186
|
+
precision, *rest = (param.this for param in node.expressions)
|
|
187
|
+
scale = rest[0] if rest else exp.Literal.number(0)
|
|
188
|
+
if precision.is_int and scale.is_int:
|
|
189
|
+
scale_digits = int(scale.name)
|
|
190
|
+
if int(precision.name) - scale_digits > 29 or scale_digits > 9:
|
|
191
|
+
node.set("this", exp.DType.BIGDECIMAL)
|
|
192
|
+
return expression
|
|
193
|
+
|
|
194
|
+
|
|
195
|
+
def _extract_part(part: str) -> t.Callable[[BigQueryGenerator, exp.Func], str]:
|
|
196
|
+
return lambda self, e: self.sql(exp.func("EXTRACT", exp.var(part), e.this, copy=False))
|
|
197
|
+
|
|
198
|
+
|
|
199
|
+
def _day_of_week_iso_sql(self: BigQueryGenerator, expression: exp.DayOfWeekIso) -> str:
|
|
200
|
+
# DAYOFWEEK is Sunday=1..Saturday=7, ISO is Monday=1..Sunday=7
|
|
201
|
+
template: exp.Expr = exp.maybe_parse("(MOD(EXTRACT(DAYOFWEEK FROM :this) + 5, 7) + 1)")
|
|
202
|
+
return self.sql(exp.replace_placeholders(template, this=expression.this))
|
|
203
|
+
|
|
204
|
+
|
|
205
|
+
def _array_agg_fold_sql(
|
|
206
|
+
self: BigQueryGenerator, expression: exp.ArrayDistinct | exp.ArraySort
|
|
207
|
+
) -> str:
|
|
208
|
+
distinct = False
|
|
209
|
+
ignore_nulls = False
|
|
210
|
+
sort: exp.ArraySort | None = None
|
|
211
|
+
agg: exp.Expr = expression
|
|
212
|
+
while isinstance(agg, (exp.ArrayDistinct, exp.ArraySort)) and not agg.expression:
|
|
213
|
+
if isinstance(agg, exp.ArrayDistinct):
|
|
214
|
+
distinct = True
|
|
215
|
+
ignore_nulls |= agg.args.get("check_null") is False
|
|
216
|
+
elif sort is None:
|
|
217
|
+
sort = agg
|
|
218
|
+
agg = agg.this
|
|
219
|
+
|
|
220
|
+
order = array_sort_order(sort) if sort else None
|
|
221
|
+
|
|
222
|
+
# An ARRAY_AGG with its own ORDER BY or LIMIT can't take another
|
|
223
|
+
if (
|
|
224
|
+
not isinstance(agg, exp.ArrayAgg)
|
|
225
|
+
or isinstance(agg.this, (exp.Order, exp.Limit))
|
|
226
|
+
or (sort is not None and order is None)
|
|
227
|
+
):
|
|
228
|
+
self.unsupported(
|
|
229
|
+
f"{expression.sql_name()} is only supported on an ARRAY_AGG without ORDER BY or LIMIT and with a literal order"
|
|
230
|
+
)
|
|
231
|
+
return self.func(expression.sql_name(), expression.this, expression.expression)
|
|
232
|
+
|
|
233
|
+
value = agg.this
|
|
234
|
+
if isinstance(value, exp.Distinct):
|
|
235
|
+
distinct, value = True, value.expressions[0]
|
|
236
|
+
|
|
237
|
+
folded: exp.Expr = exp.Distinct(expressions=[value]) if distinct else value
|
|
238
|
+
if order is not None:
|
|
239
|
+
asc, nulls_first = order
|
|
240
|
+
keys = [exp.Ordered(this=value.copy(), desc=not asc or None, nulls_first=asc)]
|
|
241
|
+
|
|
242
|
+
# Aggregate ORDER BY only puts NULLs first when ascending, so other placements need a key
|
|
243
|
+
if not ignore_nulls and nulls_first is not None and nulls_first != asc:
|
|
244
|
+
if distinct:
|
|
245
|
+
self.unsupported("ARRAY_AGG(DISTINCT) only puts NULLs first when ascending")
|
|
246
|
+
else:
|
|
247
|
+
is_null = value.copy().is_(exp.null())
|
|
248
|
+
keys.insert(
|
|
249
|
+
0,
|
|
250
|
+
exp.Ordered(
|
|
251
|
+
this=is_null, desc=nulls_first or None, nulls_first=not nulls_first
|
|
252
|
+
),
|
|
253
|
+
)
|
|
254
|
+
folded = exp.Order(this=folded, expressions=keys)
|
|
255
|
+
agg.set("this", folded)
|
|
256
|
+
if ignore_nulls:
|
|
257
|
+
# All-NULL input yields [], but an empty input still yields NULL.
|
|
258
|
+
agg = exp.If(
|
|
259
|
+
this=exp.Count(this=exp.Star()).eq(0),
|
|
260
|
+
true=exp.null(),
|
|
261
|
+
false=exp.func("COALESCE", exp.IgnoreNulls(this=agg), exp.array()),
|
|
262
|
+
)
|
|
263
|
+
return self.sql(agg)
|
|
264
|
+
|
|
265
|
+
|
|
179
266
|
def _ts_or_ds_add_sql(self: BigQueryGenerator, expression: exp.TsOrDsAdd) -> str:
|
|
180
267
|
return date_add_interval_sql("DATE", "ADD")(self, ts_or_ds_add_cast(expression))
|
|
181
268
|
|
|
@@ -311,6 +398,8 @@ class BigQueryGenerator(generator.Generator):
|
|
|
311
398
|
exp.ArgMin: arg_max_or_min_no_count("MIN_BY"),
|
|
312
399
|
exp.Array: inline_array_unless_query,
|
|
313
400
|
exp.ArrayContains: _array_contains_sql,
|
|
401
|
+
exp.ArrayDistinct: _array_agg_fold_sql,
|
|
402
|
+
exp.ArraySort: _array_agg_fold_sql,
|
|
314
403
|
exp.ArrayFilter: filter_array_using_unnest,
|
|
315
404
|
exp.ArrayRemove: filter_array_using_unnest,
|
|
316
405
|
exp.BitwiseAndAgg: rename_func("BIT_AND"),
|
|
@@ -318,7 +407,9 @@ class BigQueryGenerator(generator.Generator):
|
|
|
318
407
|
exp.BitwiseXorAgg: rename_func("BIT_XOR"),
|
|
319
408
|
exp.BitwiseCount: rename_func("BIT_COUNT"),
|
|
320
409
|
exp.ByteLength: rename_func("BYTE_LENGTH"),
|
|
321
|
-
exp.Cast: transforms.preprocess(
|
|
410
|
+
exp.Cast: transforms.preprocess(
|
|
411
|
+
[_widen_decimal, transforms.remove_precision_parameterized_types]
|
|
412
|
+
),
|
|
322
413
|
exp.CollateProperty: lambda self, e: (
|
|
323
414
|
f"DEFAULT COLLATE {self.sql(e, 'this')}"
|
|
324
415
|
if e.args.get("default")
|
|
@@ -336,6 +427,10 @@ class BigQueryGenerator(generator.Generator):
|
|
|
336
427
|
exp.DatetimeAdd: date_add_interval_sql("DATETIME", "ADD"),
|
|
337
428
|
exp.DatetimeSub: date_add_interval_sql("DATETIME", "SUB"),
|
|
338
429
|
exp.DateFromUnixDate: rename_func("DATE_FROM_UNIX_DATE"),
|
|
430
|
+
exp.Day: _extract_part("DAY"),
|
|
431
|
+
exp.DayOfMonth: _extract_part("DAY"),
|
|
432
|
+
exp.DayOfWeekIso: _day_of_week_iso_sql,
|
|
433
|
+
exp.DayOfYear: _extract_part("DAYOFYEAR"),
|
|
339
434
|
exp.Filter: no_filter_sql,
|
|
340
435
|
exp.FromTimeZone: lambda self, e: self.func(
|
|
341
436
|
"DATETIME", self.func("TIMESTAMP", e.this, e.args.get("zone")), "'UTC'"
|
|
@@ -346,6 +441,7 @@ class BigQueryGenerator(generator.Generator):
|
|
|
346
441
|
),
|
|
347
442
|
exp.Hex: lambda self, e: self.func("UPPER", self.func("TO_HEX", self.sql(e, "this"))),
|
|
348
443
|
exp.HexString: lambda self, e: self.hexstring_sql(e, binary_function_repr="FROM_HEX"),
|
|
444
|
+
exp.Hour: _extract_part("HOUR"),
|
|
349
445
|
exp.If: if_sql(false_value="NULL"),
|
|
350
446
|
exp.ILike: no_ilike_sql,
|
|
351
447
|
exp.IntDiv: rename_func("DIV"),
|
|
@@ -366,12 +462,14 @@ class BigQueryGenerator(generator.Generator):
|
|
|
366
462
|
exp.MD5: lambda self, e: self.func("TO_HEX", self.func("MD5", e.this)),
|
|
367
463
|
exp.MD5Digest: rename_func("MD5"),
|
|
368
464
|
exp.Min: min_or_least,
|
|
465
|
+
exp.Month: _extract_part("MONTH"),
|
|
369
466
|
exp.Normalize: lambda self, e: self.func(
|
|
370
467
|
"NORMALIZE_AND_CASEFOLD" if e.args.get("is_casefold") else "NORMALIZE",
|
|
371
468
|
e.this,
|
|
372
469
|
e.args.get("form"),
|
|
373
470
|
),
|
|
374
471
|
exp.PartitionedByProperty: lambda self, e: f"PARTITION BY {self.sql(e, 'this')}",
|
|
472
|
+
exp.Quarter: _extract_part("QUARTER"),
|
|
375
473
|
exp.RegexpExtract: lambda self, e: self.func(
|
|
376
474
|
"REGEXP_EXTRACT",
|
|
377
475
|
e.this,
|
|
@@ -431,6 +529,8 @@ class BigQueryGenerator(generator.Generator):
|
|
|
431
529
|
exp.Uuid: lambda *_: "GENERATE_UUID()",
|
|
432
530
|
exp.Values: _derived_table_values_to_unnest,
|
|
433
531
|
exp.VariancePop: rename_func("VAR_POP"),
|
|
532
|
+
exp.WeekOfYear: _extract_part("ISOWEEK"),
|
|
533
|
+
exp.Year: _extract_part("YEAR"),
|
|
434
534
|
exp.SafeDivide: rename_func("SAFE_DIVIDE"),
|
|
435
535
|
}
|
|
436
536
|
|
|
@@ -582,6 +682,47 @@ class BigQueryGenerator(generator.Generator):
|
|
|
582
682
|
"within",
|
|
583
683
|
}
|
|
584
684
|
|
|
685
|
+
def frombase_sql(self, expression: exp.FromBase) -> str:
|
|
686
|
+
# Hex is the only base BigQuery can cast from, and the sign goes before the prefix, e.g. -0xff
|
|
687
|
+
if expression.expression.name != "16":
|
|
688
|
+
self.unsupported("FROM_BASE is only supported for base 16")
|
|
689
|
+
return self.function_fallback_sql(expression)
|
|
690
|
+
|
|
691
|
+
prefixed = exp.func(
|
|
692
|
+
"REGEXP_REPLACE",
|
|
693
|
+
expression.this,
|
|
694
|
+
exp.Literal.string("^([+-]?)"),
|
|
695
|
+
exp.Literal.string("\\10x"),
|
|
696
|
+
copy=False,
|
|
697
|
+
)
|
|
698
|
+
return self.sql(exp.cast(prefixed, exp.DType.BIGINT, copy=False))
|
|
699
|
+
|
|
700
|
+
def approxquantile_sql(self, expression: exp.ApproxQuantile) -> str:
|
|
701
|
+
node: exp.Expr = expression
|
|
702
|
+
while node.parent and not isinstance(node.parent, (exp.Window, exp.AggFunc, exp.Select)):
|
|
703
|
+
node = node.parent
|
|
704
|
+
if isinstance(node.parent, exp.Window) and node.arg_key == "this":
|
|
705
|
+
self.unsupported("APPROX_QUANTILES does not support window functions")
|
|
706
|
+
return self.function_fallback_sql(expression)
|
|
707
|
+
|
|
708
|
+
# The k/n quantile is APPROX_QUANTILES(x, n)[k], e.g. 0.95 -> n = 20, k = 19. n is at most
|
|
709
|
+
# 100,000, so the quantile has at most 5 decimal places, and Decimal comparisons are exact
|
|
710
|
+
quantile = expression.args["quantile"]
|
|
711
|
+
weight = expression.args.get("weight")
|
|
712
|
+
value = Decimal(quantile.to_py()) if quantile.is_number else None
|
|
713
|
+
if (
|
|
714
|
+
value is None
|
|
715
|
+
or not 0 <= value <= 1
|
|
716
|
+
or round(value, 5) != value
|
|
717
|
+
or (weight and (not weight.is_number or weight.to_py() != 1))
|
|
718
|
+
):
|
|
719
|
+
self.unsupported("APPROX_QUANTILE needs a literal quantile and no weight")
|
|
720
|
+
return self.function_fallback_sql(expression)
|
|
721
|
+
|
|
722
|
+
fraction = Fraction(value)
|
|
723
|
+
quantiles = exp.func("APPROX_QUANTILES", expression.this, fraction.denominator, copy=False)
|
|
724
|
+
return self.sql(quantiles[fraction.numerator])
|
|
725
|
+
|
|
585
726
|
def weekstart_sql(self, expression: exp.WeekStart) -> str:
|
|
586
727
|
if expression.this.name.upper() == "SUNDAY":
|
|
587
728
|
# BigQuery specific optimization since WEEK(SUNDAY) == WEEK
|
|
@@ -688,7 +688,8 @@ class ClickHouseGenerator(generator.Generator):
|
|
|
688
688
|
comment_prop = expression.find(exp.SchemaCommentProperty)
|
|
689
689
|
if comment_prop:
|
|
690
690
|
comment_prop.pop()
|
|
691
|
-
query
|
|
691
|
+
if not isinstance(query, exp.Subquery):
|
|
692
|
+
query.replace(exp.paren(query))
|
|
692
693
|
else:
|
|
693
694
|
comment_prop = None
|
|
694
695
|
|