sqlglot 30.14.0__tar.gz → 30.16.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.14.0 → sqlglot-30.16.0}/.gitignore +6 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/CHANGELOG.md +108 -0
- {sqlglot-30.14.0/sqlglot.egg-info → sqlglot-30.16.0}/PKG-INFO +3 -3
- {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/_version.py +3 -3
- sqlglot-30.16.0/sqlglot/anonymize.py +307 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/dialects/bigquery.py +0 -3
- {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/dialects/clickhouse.py +0 -1
- {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/dialects/dialect.py +47 -5
- {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/dialects/dremio.py +0 -6
- {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/dialects/duckdb.py +0 -1
- {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/dialects/hive.py +0 -2
- {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/dialects/mysql.py +0 -1
- {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/dialects/starrocks.py +1 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/dialects/trino.py +4 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/dialects/tsql.py +3 -1
- {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/errors.py +15 -1
- {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/executor/env.py +52 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/executor/python.py +109 -31
- {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/expressions/array.py +6 -4
- {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/expressions/core.py +20 -14
- {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/expressions/datatypes.py +12 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/expressions/ddl.py +2 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/expressions/dml.py +1 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/expressions/json.py +4 -3
- {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/expressions/math.py +4 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/expressions/properties.py +9 -1
- {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/expressions/query.py +24 -3
- {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/expressions/string.py +7 -3
- {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/expressions/temporal.py +1 -1
- {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/generator.py +134 -40
- {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/generators/bigquery.py +8 -1
- {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/generators/clickhouse.py +32 -5
- {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/generators/doris.py +12 -5
- {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/generators/duckdb.py +88 -48
- {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/generators/exasol.py +9 -4
- {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/generators/fabric.py +2 -1
- {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/generators/hive.py +11 -5
- {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/generators/mysql.py +32 -36
- {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/generators/oracle.py +2 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/generators/postgres.py +23 -1
- {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/generators/python.py +4 -4
- {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/generators/singlestore.py +5 -3
- {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/generators/snowflake.py +1 -1
- {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/generators/spark2.py +12 -24
- {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/generators/sqlite.py +9 -2
- {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/generators/starrocks.py +10 -5
- {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/generators/trino.py +50 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/generators/tsql.py +7 -1
- {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/lineage.py +78 -33
- {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/optimizer/annotate_types.py +101 -82
- {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/optimizer/canonicalize_internal_names.py +19 -6
- {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/optimizer/eliminate_ctes.py +6 -1
- sqlglot-30.16.0/sqlglot/optimizer/journal.py +32 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/optimizer/pushdown_predicates.py +20 -6
- {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/optimizer/pushdown_projections.py +52 -6
- {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/optimizer/qualify_columns.py +95 -17
- {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/optimizer/qualify_tables.py +11 -3
- {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/optimizer/scope.py +7 -1
- {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/optimizer/simplify.py +66 -24
- {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/optimizer/unnest_subqueries.py +20 -10
- {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/parser.py +223 -56
- {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/parsers/bigquery.py +33 -19
- {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/parsers/clickhouse.py +80 -17
- {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/parsers/dremio.py +6 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/parsers/duckdb.py +11 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/parsers/mysql.py +17 -7
- {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/parsers/postgres.py +16 -1
- {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/parsers/prql.py +1 -1
- {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/parsers/snowflake.py +11 -4
- {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/parsers/spark.py +0 -1
- {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/parsers/sqlite.py +79 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/parsers/teradata.py +1 -1
- sqlglot-30.16.0/sqlglot/parsers/trino.py +222 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/parsers/tsql.py +24 -3
- {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/planner.py +3 -2
- {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/schema.py +2 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/tokenizer_core.py +1 -3
- {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/tokens.py +0 -4
- {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/transforms.py +17 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/typing/__init__.py +2 -2
- {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/typing/bigquery.py +0 -2
- {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/typing/databricks.py +7 -2
- {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/typing/hive.py +6 -5
- sqlglot-30.16.0/sqlglot/typing/mysql.py +205 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/typing/snowflake.py +0 -3
- {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/typing/spark.py +18 -10
- {sqlglot-30.14.0 → sqlglot-30.16.0/sqlglot.egg-info}/PKG-INFO +3 -3
- {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot.egg-info/SOURCES.txt +4 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot.egg-info/requires.txt +2 -2
- {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot.egg-info/scm_file_list.json +322 -318
- sqlglot-30.16.0/sqlglot.egg-info/scm_version.json +8 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglotc/setup.py +1 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/dialects/test_bigquery.py +174 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/dialects/test_clickhouse.py +72 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/dialects/test_databricks.py +15 -1
- {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/dialects/test_doris.py +3 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/dialects/test_duckdb.py +13 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/dialects/test_mysql.py +12 -6
- {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/dialects/test_oracle.py +31 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/dialects/test_postgres.py +90 -3
- {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/dialects/test_snowflake.py +28 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/dialects/test_spark.py +2 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/dialects/test_sqlite.py +69 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/dialects/test_starrocks.py +11 -0
- sqlglot-30.16.0/tests/dialects/test_trino.py +425 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/dialects/test_tsql.py +58 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/fixtures/optimizer/annotate_functions.sql +475 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/fixtures/optimizer/canonicalize_internal_names.sql +20 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/fixtures/optimizer/pushdown_predicates.sql +20 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/fixtures/optimizer/pushdown_projections.sql +12 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/fixtures/optimizer/qualify_columns.sql +98 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/fixtures/optimizer/qualify_columns__invalid.sql +3 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/fixtures/optimizer/qualify_tables.sql +14 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/fixtures/optimizer/simplify.sql +207 -19
- {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/fixtures/optimizer/unnest_subqueries.sql +12 -0
- sqlglot-30.16.0/tests/test_anonymize.py +514 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/test_executor.py +147 -1
- {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/test_expressions.py +24 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/test_lineage.py +126 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/test_optimizer.py +241 -2
- {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/test_parser.py +14 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/test_tokens.py +6 -2
- sqlglot-30.16.0/tests/test_typing.py +83 -0
- sqlglot-30.14.0/sqlglot/parsers/trino.py +0 -63
- sqlglot-30.14.0/sqlglot/typing/mysql.py +0 -96
- sqlglot-30.14.0/sqlglot.egg-info/scm_version.json +0 -8
- sqlglot-30.14.0/tests/dialects/test_trino.py +0 -178
- {sqlglot-30.14.0 → sqlglot-30.16.0}/.gitmodules +0 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/.gitpod.yml +0 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/.pre-commit-config.yaml +0 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/AGENTS.md +0 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/CLAUDE.md +0 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/CONTRIBUTING.md +0 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/LICENSE +0 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/MANIFEST.in +0 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/Makefile +0 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/README.md +0 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/pyproject.toml +0 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/setup.cfg +0 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/setup.py +0 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/__init__.py +0 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/__main__.py +0 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/_typing.py +0 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/dialects/__init__.py +0 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/dialects/athena.py +0 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/dialects/databricks.py +0 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/dialects/dax.py +0 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/dialects/doris.py +0 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/dialects/drill.py +0 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/dialects/druid.py +0 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/dialects/dune.py +0 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/dialects/exasol.py +0 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/dialects/fabric.py +0 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/dialects/materialize.py +0 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/dialects/oracle.py +0 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/dialects/postgres.py +0 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/dialects/presto.py +0 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/dialects/prql.py +0 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/dialects/redshift.py +0 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/dialects/risingwave.py +0 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/dialects/singlestore.py +0 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/dialects/snowflake.py +0 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/dialects/solr.py +0 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/dialects/spark.py +0 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/dialects/spark2.py +0 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/dialects/sqlite.py +0 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/dialects/tableau.py +0 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/dialects/teradata.py +0 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/diff.py +0 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/executor/__init__.py +0 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/executor/context.py +0 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/executor/table.py +0 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/expressions/__init__.py +0 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/expressions/aggregate.py +0 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/expressions/builders.py +0 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/expressions/constraints.py +0 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/expressions/functions.py +0 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/generators/__init__.py +0 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/generators/athena.py +0 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/generators/databricks.py +0 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/generators/dax.py +0 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/generators/dremio.py +0 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/generators/drill.py +0 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/generators/druid.py +0 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/generators/dune.py +0 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/generators/materialize.py +0 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/generators/presto.py +0 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/generators/prql.py +0 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/generators/redshift.py +0 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/generators/risingwave.py +0 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/generators/solr.py +0 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/generators/spark.py +0 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/generators/tableau.py +0 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/generators/teradata.py +0 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/helper.py +0 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/jsonpath.py +0 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/optimizer/__init__.py +0 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/optimizer/canonicalize.py +0 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/optimizer/eliminate_joins.py +0 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/optimizer/eliminate_subqueries.py +0 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/optimizer/isolate_table_selects.py +0 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/optimizer/merge_subqueries.py +0 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/optimizer/normalize.py +0 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/optimizer/normalize_identifiers.py +0 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/optimizer/optimize_joins.py +0 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/optimizer/optimizer.py +0 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/optimizer/qualify.py +0 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/optimizer/resolver.py +0 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/parsers/__init__.py +0 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/parsers/athena.py +0 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/parsers/base.py +0 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/parsers/databricks.py +0 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/parsers/dax.py +0 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/parsers/doris.py +0 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/parsers/drill.py +0 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/parsers/druid.py +0 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/parsers/dune.py +0 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/parsers/exasol.py +0 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/parsers/fabric.py +0 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/parsers/hive.py +0 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/parsers/materialize.py +0 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/parsers/oracle.py +0 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/parsers/presto.py +0 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/parsers/redshift.py +0 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/parsers/risingwave.py +0 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/parsers/singlestore.py +0 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/parsers/solr.py +0 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/parsers/spark2.py +0 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/parsers/starrocks.py +0 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/parsers/tableau.py +0 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/py.typed +0 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/serde.py +0 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/time.py +0 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/trie.py +0 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/typing/clickhouse.py +0 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/typing/duckdb.py +0 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/typing/postgres.py +0 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/typing/presto.py +0 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/typing/redshift.py +0 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/typing/spark2.py +0 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/typing/tsql.py +0 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot.egg-info/dependency_links.txt +0 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot.egg-info/top_level.txt +0 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot.png +0 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglotc/MANIFEST.in +0 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglotc/pyproject.toml +0 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/__init__.py +0 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/dialects/__init__.py +0 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/dialects/test_athena.py +0 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/dialects/test_dax.py +0 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/dialects/test_dialect.py +0 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/dialects/test_dremio.py +0 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/dialects/test_drill.py +0 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/dialects/test_druid.py +0 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/dialects/test_dune.py +0 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/dialects/test_exasol.py +0 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/dialects/test_fabric.py +0 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/dialects/test_hive.py +0 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/dialects/test_materialize.py +0 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/dialects/test_pipe_syntax.py +0 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/dialects/test_presto.py +0 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/dialects/test_prql.py +0 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/dialects/test_redshift.py +0 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/dialects/test_risingwave.py +0 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/dialects/test_singlestore.py +0 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/dialects/test_solr.py +0 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/dialects/test_tableau.py +0 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/dialects/test_teradata.py +0 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/fixtures/identity.sql +0 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/fixtures/jsonpath/LICENSE +0 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/fixtures/jsonpath/cts.json +0 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/fixtures/optimizer/annotate_types.sql +0 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/fixtures/optimizer/canonicalize.sql +0 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/fixtures/optimizer/eliminate_ctes.sql +0 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/fixtures/optimizer/eliminate_joins.sql +0 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/fixtures/optimizer/eliminate_subqueries.sql +0 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/fixtures/optimizer/isolate_table_selects.sql +0 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/fixtures/optimizer/merge_subqueries.sql +0 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/fixtures/optimizer/normalize.sql +0 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/fixtures/optimizer/normalize_identifiers.sql +0 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/fixtures/optimizer/optimize_joins.sql +0 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/fixtures/optimizer/optimizer.sql +0 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/fixtures/optimizer/pushdown_cte_alias_columns.sql +0 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/fixtures/optimizer/qualify_columns__with_invisible.sql +0 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/fixtures/optimizer/qualify_columns_ddl.sql +0 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/fixtures/optimizer/quote_identifiers.sql +0 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/fixtures/optimizer/tpc-ds/call_center.csv.gz +0 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/fixtures/optimizer/tpc-ds/catalog_page.csv.gz +0 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/fixtures/optimizer/tpc-ds/catalog_returns.csv.gz +0 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/fixtures/optimizer/tpc-ds/catalog_sales.csv.gz +0 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/fixtures/optimizer/tpc-ds/customer.csv.gz +0 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/fixtures/optimizer/tpc-ds/customer_address.csv.gz +0 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/fixtures/optimizer/tpc-ds/customer_demographics.csv.gz +0 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/fixtures/optimizer/tpc-ds/date_dim.csv.gz +0 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/fixtures/optimizer/tpc-ds/household_demographics.csv.gz +0 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/fixtures/optimizer/tpc-ds/income_band.csv.gz +0 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/fixtures/optimizer/tpc-ds/inventory.csv.gz +0 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/fixtures/optimizer/tpc-ds/item.csv.gz +0 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/fixtures/optimizer/tpc-ds/promotion.csv.gz +0 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/fixtures/optimizer/tpc-ds/reason.csv.gz +0 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/fixtures/optimizer/tpc-ds/ship_mode.csv.gz +0 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/fixtures/optimizer/tpc-ds/store.csv.gz +0 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/fixtures/optimizer/tpc-ds/store_returns.csv.gz +0 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/fixtures/optimizer/tpc-ds/store_sales.csv.gz +0 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/fixtures/optimizer/tpc-ds/time_dim.csv.gz +0 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/fixtures/optimizer/tpc-ds/tpc-ds.sql +0 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/fixtures/optimizer/tpc-ds/warehouse.csv.gz +0 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/fixtures/optimizer/tpc-ds/web_page.csv.gz +0 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/fixtures/optimizer/tpc-ds/web_returns.csv.gz +0 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/fixtures/optimizer/tpc-ds/web_sales.csv.gz +0 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/fixtures/optimizer/tpc-ds/web_site.csv.gz +0 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/fixtures/optimizer/tpc-h/customer.csv.gz +0 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/fixtures/optimizer/tpc-h/lineitem.csv.gz +0 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/fixtures/optimizer/tpc-h/nation.csv.gz +0 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/fixtures/optimizer/tpc-h/orders.csv.gz +0 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/fixtures/optimizer/tpc-h/part.csv.gz +0 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/fixtures/optimizer/tpc-h/partsupp.csv.gz +0 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/fixtures/optimizer/tpc-h/region.csv.gz +0 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/fixtures/optimizer/tpc-h/supplier.csv.gz +0 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/fixtures/optimizer/tpc-h/tpc-h.sql +0 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/fixtures/partial.sql +0 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/fixtures/pretty.sql +0 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/gen_fixtures.py +0 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/helpers.py +0 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/leakcheck.py +0 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/sqlglot/__init__.py +0 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/test_build.py +0 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/test_dialect_entry_points.py +0 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/test_dialect_imports.py +0 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/test_diff.py +0 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/test_docs.py +0 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/test_errors.py +0 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/test_generator.py +0 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/test_helper.py +0 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/test_integration_loader.py +0 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/test_jsonpath.py +0 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/test_schema.py +0 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/test_serde.py +0 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/test_time.py +0 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/test_transforms.py +0 -0
- {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/test_transpile.py +0 -0
|
@@ -1,6 +1,113 @@
|
|
|
1
1
|
Changelog
|
|
2
2
|
=========
|
|
3
3
|
|
|
4
|
+
## [v30.14.0] - 2026-07-27
|
|
5
|
+
### :boom: BREAKING CHANGES
|
|
6
|
+
- due to [`a715f9f`](https://github.com/tobymao/sqlglot/commit/a715f9f9aa1ba640f558c7602af9a63fc35d8697) - type annotation for databricks NANVL, SIGN, SHIFTLEFT, SIGNUM, SHUFFLE *(PR [#7896](https://github.com/tobymao/sqlglot/pull/7896) by [@fivetran-amrutabhimsenayachit](https://github.com/fivetran-amrutabhimsenayachit))*:
|
|
7
|
+
|
|
8
|
+
type annotation for databricks NANVL, SIGN, SHIFTLEFT, SIGNUM, SHUFFLE (#7896)
|
|
9
|
+
|
|
10
|
+
- due to [`acb635a`](https://github.com/tobymao/sqlglot/commit/acb635a9d5a1e2bdcd4d18e44a63830f10583240) - don't normalize quoted derived output aliases in qualify_outputs *(PR [#7921](https://github.com/tobymao/sqlglot/pull/7921) by [@georgesittas](https://github.com/georgesittas))*:
|
|
11
|
+
|
|
12
|
+
don't normalize quoted derived output aliases in qualify_outputs (#7921)
|
|
13
|
+
|
|
14
|
+
- due to [`c090f35`](https://github.com/tobymao/sqlglot/commit/c090f35c8625d5bb1371a1c0c75ba434f4df6b95) - dedupe colliding star expanded aliases *(PR [#7872](https://github.com/tobymao/sqlglot/pull/7872) by [@fivetran-kwoodbeck](https://github.com/fivetran-kwoodbeck))*:
|
|
15
|
+
|
|
16
|
+
dedupe colliding star expanded aliases (#7872)
|
|
17
|
+
|
|
18
|
+
- due to [`1b442c9`](https://github.com/tobymao/sqlglot/commit/1b442c97deafa067733ff0590f7a612e66ae8aed) - handle non-literal star ILIKE patterns and Snowflake backslash escapes *(PR [#7918](https://github.com/tobymao/sqlglot/pull/7918) by [@georgesittas](https://github.com/georgesittas))*:
|
|
19
|
+
|
|
20
|
+
handle non-literal star ILIKE patterns and Snowflake backslash escapes (#7918)
|
|
21
|
+
|
|
22
|
+
- due to [`66316e3`](https://github.com/tobymao/sqlglot/commit/66316e335fd617d2f3ab8c412ae7a87356431c97) - parse single-digit hour/minute/second without padding CLAUDE *(PR [#7925](https://github.com/tobymao/sqlglot/pull/7925) by [@deepyaman](https://github.com/deepyaman))*:
|
|
23
|
+
|
|
24
|
+
parse single-digit hour/minute/second without padding CLAUDE (#7925)
|
|
25
|
+
|
|
26
|
+
- due to [`c75b7b6`](https://github.com/tobymao/sqlglot/commit/c75b7b610e182fedba20758853d227b81bc1cb34) - annotate unhex for duckdb *(PR [#7930](https://github.com/tobymao/sqlglot/pull/7930) by [@vaishnavi-polekar](https://github.com/vaishnavi-polekar))*:
|
|
27
|
+
|
|
28
|
+
annotate unhex for duckdb (#7930)
|
|
29
|
+
|
|
30
|
+
- due to [`88c4b4a`](https://github.com/tobymao/sqlglot/commit/88c4b4a6f0372978f8ec58c872f0a7f26570bfe3) - parse and annotate duckdb FROM_HEX *(PR [#7931](https://github.com/tobymao/sqlglot/pull/7931) by [@geooo109](https://github.com/geooo109))*:
|
|
31
|
+
|
|
32
|
+
parse and annotate duckdb FROM_HEX (#7931)
|
|
33
|
+
|
|
34
|
+
- due to [`a7725f2`](https://github.com/tobymao/sqlglot/commit/a7725f2a1944bc853deddf8acec29a01946615dd) - annotate convert_tz for mysql *(PR [#7932](https://github.com/tobymao/sqlglot/pull/7932) by [@PiyaDaswadkar](https://github.com/PiyaDaswadkar))*:
|
|
35
|
+
|
|
36
|
+
annotate convert_tz for mysql (#7932)
|
|
37
|
+
|
|
38
|
+
- due to [`85e0b7c`](https://github.com/tobymao/sqlglot/commit/85e0b7c89f3009fe4fbde381df30a1931a975fb4) - annotate UTC_DATE for MySQL *(PR [#7935](https://github.com/tobymao/sqlglot/pull/7935) by [@PiyaDaswadkar](https://github.com/PiyaDaswadkar))*:
|
|
39
|
+
|
|
40
|
+
annotate UTC_DATE for MySQL (#7935)
|
|
41
|
+
|
|
42
|
+
- due to [`7fbb14f`](https://github.com/tobymao/sqlglot/commit/7fbb14f804e601598f3b398276e9d07b9a2d6dbc) - annotate utc_time for mysql *(PR [#7936](https://github.com/tobymao/sqlglot/pull/7936) by [@PiyaDaswadkar](https://github.com/PiyaDaswadkar))*:
|
|
43
|
+
|
|
44
|
+
annotate utc_time for mysql (#7936)
|
|
45
|
+
|
|
46
|
+
- due to [`212fe55`](https://github.com/tobymao/sqlglot/commit/212fe552375e5ef8432a5ed0dd107278075922e8) - annotate utc_timestamp for mysql *(PR [#7937](https://github.com/tobymao/sqlglot/pull/7937) by [@PiyaDaswadkar](https://github.com/PiyaDaswadkar))*:
|
|
47
|
+
|
|
48
|
+
annotate utc_timestamp for mysql (#7937)
|
|
49
|
+
|
|
50
|
+
- due to [`166cd4d`](https://github.com/tobymao/sqlglot/commit/166cd4de90e272c89f14eb7d04d2989d75ef6742) - annotate substringindex for mysql *(PR [#7945](https://github.com/tobymao/sqlglot/pull/7945) by [@PiyaDaswadkar](https://github.com/PiyaDaswadkar))*:
|
|
51
|
+
|
|
52
|
+
annotate substringindex for mysql (#7945)
|
|
53
|
+
|
|
54
|
+
- due to [`26078eb`](https://github.com/tobymao/sqlglot/commit/26078eb7ca56645521fe6f9d60da67d7e9f7e82b) - annotate unhex for mysql *(PR [#7944](https://github.com/tobymao/sqlglot/pull/7944) by [@PiyaDaswadkar](https://github.com/PiyaDaswadkar))*:
|
|
55
|
+
|
|
56
|
+
annotate unhex for mysql (#7944)
|
|
57
|
+
|
|
58
|
+
- due to [`33de21f`](https://github.com/tobymao/sqlglot/commit/33de21fc21cdc05755a2de39318b292c10ccec0f) - annotate regexpsubstr for mysql *(PR [#7946](https://github.com/tobymao/sqlglot/pull/7946) by [@PiyaDaswadkar](https://github.com/PiyaDaswadkar))*:
|
|
59
|
+
|
|
60
|
+
annotate regexpsubstr for mysql (#7946)
|
|
61
|
+
|
|
62
|
+
- due to [`2aae7f7`](https://github.com/tobymao/sqlglot/commit/2aae7f7605ed38fe0950d004cb9defc1dd9621e5) - preserve x IS NOT NULL instead of normalizing to NOT x IS NULL *(PR [#7938](https://github.com/tobymao/sqlglot/pull/7938) by [@geooo109](https://github.com/geooo109))*:
|
|
63
|
+
|
|
64
|
+
preserve x IS NOT NULL instead of normalizing to NOT x IS NULL (#7938)
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
### :sparkles: New Features
|
|
68
|
+
- [`c402094`](https://github.com/tobymao/sqlglot/commit/c4020942b711eb0f5c8a182ff580b31541aed07f) - **duckdb**: transpile BigQuery ARRAY_CONCAT_AGG to DuckDB *(PR [#7891](https://github.com/tobymao/sqlglot/pull/7891) by [@sirockin](https://github.com/sirockin))*
|
|
69
|
+
- [`8be76d2`](https://github.com/tobymao/sqlglot/commit/8be76d20a133ee818cffd52e04366fdc74d6a89e) - **duckdb**: convert ARRAY_AGG IGNORE NULLS to FILTER clause *(PR [#7893](https://github.com/tobymao/sqlglot/pull/7893) by [@sirockin](https://github.com/sirockin))*
|
|
70
|
+
- [`a715f9f`](https://github.com/tobymao/sqlglot/commit/a715f9f9aa1ba640f558c7602af9a63fc35d8697) - **optimizer**: type annotation for databricks NANVL, SIGN, SHIFTLEFT, SIGNUM, SHUFFLE *(PR [#7896](https://github.com/tobymao/sqlglot/pull/7896) by [@fivetran-amrutabhimsenayachit](https://github.com/fivetran-amrutabhimsenayachit))*
|
|
71
|
+
- [`ee5a989`](https://github.com/tobymao/sqlglot/commit/ee5a989cd5b756c10068837887f34ffe8606ce7f) - **mysql**: support INSERT ... SET ... syntax closes [#7927](https://github.com/tobymao/sqlglot/pull/7927) *(PR [#7929](https://github.com/tobymao/sqlglot/pull/7929) by [@georgesittas](https://github.com/georgesittas))*
|
|
72
|
+
- :arrow_lower_right: *addresses issue [#7927](https://github.com/tobymao/sqlglot/issues/7927) opened by [@samerdokas](https://github.com/samerdokas)*
|
|
73
|
+
- [`c75b7b6`](https://github.com/tobymao/sqlglot/commit/c75b7b610e182fedba20758853d227b81bc1cb34) - **optimizer**: annotate unhex for duckdb *(PR [#7930](https://github.com/tobymao/sqlglot/pull/7930) by [@vaishnavi-polekar](https://github.com/vaishnavi-polekar))*
|
|
74
|
+
- [`88c4b4a`](https://github.com/tobymao/sqlglot/commit/88c4b4a6f0372978f8ec58c872f0a7f26570bfe3) - **optimizer**: parse and annotate duckdb FROM_HEX *(PR [#7931](https://github.com/tobymao/sqlglot/pull/7931) by [@geooo109](https://github.com/geooo109))*
|
|
75
|
+
- [`3cd3e58`](https://github.com/tobymao/sqlglot/commit/3cd3e58e10dcdf941f14765889641a5974e550ae) - **duckdb**: transpile BigQuery IN UNNEST(array) to ARRAY_CONTAINS *(PR [#7892](https://github.com/tobymao/sqlglot/pull/7892) by [@sirockin](https://github.com/sirockin))*
|
|
76
|
+
- [`a7725f2`](https://github.com/tobymao/sqlglot/commit/a7725f2a1944bc853deddf8acec29a01946615dd) - **optimizer**: annotate convert_tz for mysql *(PR [#7932](https://github.com/tobymao/sqlglot/pull/7932) by [@PiyaDaswadkar](https://github.com/PiyaDaswadkar))*
|
|
77
|
+
- [`85e0b7c`](https://github.com/tobymao/sqlglot/commit/85e0b7c89f3009fe4fbde381df30a1931a975fb4) - **optimizer**: annotate UTC_DATE for MySQL *(PR [#7935](https://github.com/tobymao/sqlglot/pull/7935) by [@PiyaDaswadkar](https://github.com/PiyaDaswadkar))*
|
|
78
|
+
- [`7fbb14f`](https://github.com/tobymao/sqlglot/commit/7fbb14f804e601598f3b398276e9d07b9a2d6dbc) - **optimizer**: annotate utc_time for mysql *(PR [#7936](https://github.com/tobymao/sqlglot/pull/7936) by [@PiyaDaswadkar](https://github.com/PiyaDaswadkar))*
|
|
79
|
+
- [`212fe55`](https://github.com/tobymao/sqlglot/commit/212fe552375e5ef8432a5ed0dd107278075922e8) - **optimizer**: annotate utc_timestamp for mysql *(PR [#7937](https://github.com/tobymao/sqlglot/pull/7937) by [@PiyaDaswadkar](https://github.com/PiyaDaswadkar))*
|
|
80
|
+
- [`6bb78c9`](https://github.com/tobymao/sqlglot/commit/6bb78c9aa8982b1c69378f797f02c8f248af97b4) - **snowflake**: add support for input => select ... kwarg syntax *(commit by [@georgesittas](https://github.com/georgesittas))*
|
|
81
|
+
- [`166cd4d`](https://github.com/tobymao/sqlglot/commit/166cd4de90e272c89f14eb7d04d2989d75ef6742) - **optimizer**: annotate substringindex for mysql *(PR [#7945](https://github.com/tobymao/sqlglot/pull/7945) by [@PiyaDaswadkar](https://github.com/PiyaDaswadkar))*
|
|
82
|
+
- [`26078eb`](https://github.com/tobymao/sqlglot/commit/26078eb7ca56645521fe6f9d60da67d7e9f7e82b) - **optimizer**: annotate unhex for mysql *(PR [#7944](https://github.com/tobymao/sqlglot/pull/7944) by [@PiyaDaswadkar](https://github.com/PiyaDaswadkar))*
|
|
83
|
+
- [`33de21f`](https://github.com/tobymao/sqlglot/commit/33de21fc21cdc05755a2de39318b292c10ccec0f) - **optimizer**: annotate regexpsubstr for mysql *(PR [#7946](https://github.com/tobymao/sqlglot/pull/7946) by [@PiyaDaswadkar](https://github.com/PiyaDaswadkar))*
|
|
84
|
+
- [`2aae7f7`](https://github.com/tobymao/sqlglot/commit/2aae7f7605ed38fe0950d004cb9defc1dd9621e5) - **postgres**: preserve x IS NOT NULL instead of normalizing to NOT x IS NULL *(PR [#7938](https://github.com/tobymao/sqlglot/pull/7938) by [@geooo109](https://github.com/geooo109))*
|
|
85
|
+
- :arrow_lower_right: *addresses issue [#7909](https://github.com/tobymao/sqlglot/issues/7909) opened by [@tonywasson](https://github.com/tonywasson)*
|
|
86
|
+
|
|
87
|
+
### :bug: Bug Fixes
|
|
88
|
+
- [`c368c5e`](https://github.com/tobymao/sqlglot/commit/c368c5eb2d84133a18f38ff98946b112c81f060d) - **duckdb**: handle ORDER BY and LIMIT for bq ARRAY_CONCAT_AGG *(PR [#7920](https://github.com/tobymao/sqlglot/pull/7920) by [@geooo109](https://github.com/geooo109))*
|
|
89
|
+
- [`acb635a`](https://github.com/tobymao/sqlglot/commit/acb635a9d5a1e2bdcd4d18e44a63830f10583240) - **optimizer**: don't normalize quoted derived output aliases in qualify_outputs *(PR [#7921](https://github.com/tobymao/sqlglot/pull/7921) by [@georgesittas](https://github.com/georgesittas))*
|
|
90
|
+
- :arrow_lower_right: *fixes issue [#7919](https://github.com/tobymao/sqlglot/issues/7919) opened by [@baruchoxman](https://github.com/baruchoxman)*
|
|
91
|
+
- [`c090f35`](https://github.com/tobymao/sqlglot/commit/c090f35c8625d5bb1371a1c0c75ba434f4df6b95) - **optimizer**: dedupe colliding star expanded aliases *(PR [#7872](https://github.com/tobymao/sqlglot/pull/7872) by [@fivetran-kwoodbeck](https://github.com/fivetran-kwoodbeck))*
|
|
92
|
+
- [`1b442c9`](https://github.com/tobymao/sqlglot/commit/1b442c97deafa067733ff0590f7a612e66ae8aed) - handle non-literal star ILIKE patterns and Snowflake backslash escapes *(PR [#7918](https://github.com/tobymao/sqlglot/pull/7918) by [@georgesittas](https://github.com/georgesittas))*
|
|
93
|
+
- [`66316e3`](https://github.com/tobymao/sqlglot/commit/66316e335fd617d2f3ab8c412ae7a87356431c97) - **hive**: parse single-digit hour/minute/second without padding CLAUDE *(PR [#7925](https://github.com/tobymao/sqlglot/pull/7925) by [@deepyaman](https://github.com/deepyaman))*
|
|
94
|
+
- [`e265dca`](https://github.com/tobymao/sqlglot/commit/e265dcafd6a28bdfb43a6491777b433b49a1ebd7) - **optimizer**: canonicalize unaliased scalar subquery projections *(PR [#7928](https://github.com/tobymao/sqlglot/pull/7928) by [@fivetran-kwoodbeck](https://github.com/fivetran-kwoodbeck))*
|
|
95
|
+
- [`b0a8635`](https://github.com/tobymao/sqlglot/commit/b0a8635ff3fcd769743c4848651497cce6acee19) - **parser**: treat `TokenType.OUT` as an identifier token *(PR [#7933](https://github.com/tobymao/sqlglot/pull/7933) by [@georgesittas](https://github.com/georgesittas))*
|
|
96
|
+
- [`ba0bff3`](https://github.com/tobymao/sqlglot/commit/ba0bff3d9164217f06cfcf9fadbdfd35ae84eefe) - **jsonpath**: preserve falsey union members *(PR [#7957](https://github.com/tobymao/sqlglot/pull/7957) by [@dev-willbird1936](https://github.com/dev-willbird1936))*
|
|
97
|
+
- :arrow_lower_right: *fixes issue [#7956](https://github.com/tobymao/sqlglot/issues/7956) opened by [@dev-willbird1936](https://github.com/dev-willbird1936)*
|
|
98
|
+
- [`b9fd4c9`](https://github.com/tobymao/sqlglot/commit/b9fd4c9a5d3e5aa4ccc5dff395cbde3227f18e5a) - **typing**: on_qualify expects a `Table` argument *(commit by [@georgesittas](https://github.com/georgesittas))*
|
|
99
|
+
|
|
100
|
+
### :zap: Performance Improvements
|
|
101
|
+
- [`1a38c05`](https://github.com/tobymao/sqlglot/commit/1a38c056a1f47cfc07c9bef4ed11b795a91f947e) - **optimizer**: speed up merge_subqueries *(PR [#7924](https://github.com/tobymao/sqlglot/pull/7924) by [@fivetran-kwoodbeck](https://github.com/fivetran-kwoodbeck))*
|
|
102
|
+
- [`b8180fd`](https://github.com/tobymao/sqlglot/commit/b8180fdb8c2617b7e51e1c9491a76cae852eb87b) - **optimizer**: speed up merge_subqueries *(PR [#7924](https://github.com/tobymao/sqlglot/pull/7924) by [@fivetran-kwoodbeck](https://github.com/fivetran-kwoodbeck))*
|
|
103
|
+
|
|
104
|
+
### :wrench: Chores
|
|
105
|
+
- [`cda0147`](https://github.com/tobymao/sqlglot/commit/cda0147754257779c4c103d617c04d2deb6979b9) - **generator**: refactor ARRAY_AGG tests and bq -> duckdb transpilation *(PR [#7922](https://github.com/tobymao/sqlglot/pull/7922) by [@geooo109](https://github.com/geooo109))*
|
|
106
|
+
- [`f37d1b5`](https://github.com/tobymao/sqlglot/commit/f37d1b5d6305ff293f7b1757ce1253c3299d8e88) - **duckdb**: refactor transpilation of IN UNNEST *(commit by [@geooo109](https://github.com/geooo109))*
|
|
107
|
+
- [`296d8b0`](https://github.com/tobymao/sqlglot/commit/296d8b02e7f7b4d0634194ed367ac3ce49a03714) - polish README file *(PR [#7947](https://github.com/tobymao/sqlglot/pull/7947) by [@georgesittas](https://github.com/georgesittas))*
|
|
108
|
+
- [`29c651b`](https://github.com/tobymao/sqlglot/commit/29c651b85309693924b8c034501e6a2733d14588) - retrigger v30.14.0 release *(commit by [@georgesittas](https://github.com/georgesittas))*
|
|
109
|
+
|
|
110
|
+
|
|
4
111
|
## [v30.13.0] - 2026-07-20
|
|
5
112
|
### :boom: BREAKING CHANGES
|
|
6
113
|
- due to [`58f5bf9`](https://github.com/tobymao/sqlglot/commit/58f5bf9b40dda34784bcb2d3bf0a04f02490de12) - databricks type annotation for REGEXP_COUNT, REGEXP_EXTRACT_ALL *(PR [#7797](https://github.com/tobymao/sqlglot/pull/7797) by [@fivetran-amrutabhimsenayachit](https://github.com/fivetran-amrutabhimsenayachit))*:
|
|
@@ -15078,3 +15185,4 @@ pip install "sqlglot[c]" # compiled — faster, but no subclassing
|
|
|
15078
15185
|
[v30.11.0]: https://github.com/tobymao/sqlglot/compare/v30.10.0...v30.11.0
|
|
15079
15186
|
[v30.12.0]: https://github.com/tobymao/sqlglot/compare/v30.11.0...v30.12.0
|
|
15080
15187
|
[v30.13.0]: https://github.com/tobymao/sqlglot/compare/v30.12.0...v30.13.0
|
|
15188
|
+
[v30.14.0]: https://github.com/tobymao/sqlglot/compare/v30.13.0...v30.14.0
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: sqlglot
|
|
3
|
-
Version: 30.
|
|
3
|
+
Version: 30.16.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.16.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.16.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.16.0'
|
|
22
|
+
__version_tuple__ = version_tuple = (30, 16, 0)
|
|
23
23
|
|
|
24
|
-
__commit_id__ = commit_id = '
|
|
24
|
+
__commit_id__ = commit_id = 'gbbfb497f1'
|
|
@@ -0,0 +1,307 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import string
|
|
4
|
+
|
|
5
|
+
from sqlglot.dialects.dialect import Dialect, DialectType
|
|
6
|
+
from sqlglot.errors import TokenError
|
|
7
|
+
from sqlglot.tokens import Token, TokenType
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
ALPHABET = string.ascii_lowercase
|
|
11
|
+
ALPHABET_SIZE = len(ALPHABET)
|
|
12
|
+
ANONYMIZED_TYPES = {
|
|
13
|
+
TokenType.BIT_STRING,
|
|
14
|
+
TokenType.BYTE_STRING,
|
|
15
|
+
TokenType.HEX_STRING,
|
|
16
|
+
TokenType.HEREDOC_STRING,
|
|
17
|
+
TokenType.IDENTIFIER,
|
|
18
|
+
TokenType.NATIONAL_STRING,
|
|
19
|
+
TokenType.NUMBER,
|
|
20
|
+
TokenType.RAW_STRING,
|
|
21
|
+
TokenType.STRING,
|
|
22
|
+
TokenType.UNICODE_STRING,
|
|
23
|
+
TokenType.VAR,
|
|
24
|
+
}
|
|
25
|
+
QUOTED_TYPES = ANONYMIZED_TYPES - {TokenType.NUMBER, TokenType.VAR}
|
|
26
|
+
REWRITTEN_TYPES = {TokenType.HINT, TokenType.UNKNOWN}
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def anonymize(
|
|
30
|
+
sql_or_tokens: list[Token] | str,
|
|
31
|
+
dialect: DialectType = None,
|
|
32
|
+
) -> list[Token]:
|
|
33
|
+
"""Replaces sensitive tokens (identifiers, strings, numbers) with fixed-width,
|
|
34
|
+
length-preserving, consistent aliases, and blanks out comments and hint bodies. When a
|
|
35
|
+
SQL string is given, it is tokenized with `dialect` first; any un-tokenized remainder
|
|
36
|
+
(e.g. an unterminated literal) is appended as a blanked UNKNOWN token. Mutates and
|
|
37
|
+
returns `sql_or_tokens`.
|
|
38
|
+
|
|
39
|
+
Args:
|
|
40
|
+
sql_or_tokens: The SQL string to anonymize, or its token list.
|
|
41
|
+
dialect: The dialect used to tokenize a SQL string.
|
|
42
|
+
"""
|
|
43
|
+
dialect = Dialect.get_or_raise(dialect)
|
|
44
|
+
tokenizer_class = dialect.tokenizer_class
|
|
45
|
+
parser_class = dialect.parser_class
|
|
46
|
+
|
|
47
|
+
errored = False
|
|
48
|
+
if isinstance(sql_or_tokens, str):
|
|
49
|
+
sql = sql_or_tokens
|
|
50
|
+
tokenizer = dialect.tokenizer()
|
|
51
|
+
try:
|
|
52
|
+
tokens = tokenizer.tokenize(sql)
|
|
53
|
+
except TokenError:
|
|
54
|
+
tokens = tokenizer.tokens
|
|
55
|
+
errored = True
|
|
56
|
+
else:
|
|
57
|
+
tokens = sql_or_tokens
|
|
58
|
+
sql = None
|
|
59
|
+
|
|
60
|
+
hint_start = tokenizer_class.HINT_START
|
|
61
|
+
hint_end = tokenizer_class._COMMENTS.get(hint_start)
|
|
62
|
+
nested = tokenizer_class.NESTED_COMMENTS
|
|
63
|
+
|
|
64
|
+
seen: dict[tuple[bool, str], str] = {}
|
|
65
|
+
counter = 0
|
|
66
|
+
|
|
67
|
+
for i, token in enumerate(tokens):
|
|
68
|
+
token.comments = [_blank(comment) for comment in token.comments]
|
|
69
|
+
|
|
70
|
+
if token.token_type == TokenType.HINT:
|
|
71
|
+
# A hint's text is the whole /*+ ... */ comment, so its body is blanked as well
|
|
72
|
+
text, stop = _blank_comment(token.text, 0, hint_start, hint_end, nested)
|
|
73
|
+
token.text = text + _blank(token.text[stop:])
|
|
74
|
+
continue
|
|
75
|
+
|
|
76
|
+
if (
|
|
77
|
+
token.token_type == TokenType.VAR
|
|
78
|
+
and i + 1 < len(tokens)
|
|
79
|
+
and tokens[i + 1].token_type == TokenType.L_PAREN
|
|
80
|
+
):
|
|
81
|
+
# A function name can live in either registry, e.g. JSON_OBJECT is only in
|
|
82
|
+
# FUNCTION_PARSERS. They're consulted separately to avoid building their union
|
|
83
|
+
name = token.text.upper()
|
|
84
|
+
if name in parser_class.FUNCTIONS or name in parser_class.FUNCTION_PARSERS:
|
|
85
|
+
continue
|
|
86
|
+
if token.token_type not in ANONYMIZED_TYPES:
|
|
87
|
+
continue
|
|
88
|
+
if not token.text:
|
|
89
|
+
continue
|
|
90
|
+
|
|
91
|
+
is_number = token.token_type == TokenType.NUMBER
|
|
92
|
+
key = (is_number, token.text)
|
|
93
|
+
alias = seen.get(key)
|
|
94
|
+
if alias is None:
|
|
95
|
+
seen[key] = (
|
|
96
|
+
_number_alias(counter, token.text) if is_number else _alias(counter, token.text)
|
|
97
|
+
)
|
|
98
|
+
counter += 1
|
|
99
|
+
token.text = seen[key]
|
|
100
|
+
|
|
101
|
+
if sql is not None and errored:
|
|
102
|
+
start = tokens[-1].end + 1 if tokens else 0
|
|
103
|
+
length = len(sql)
|
|
104
|
+
while start < length and sql[start].isspace():
|
|
105
|
+
start += 1
|
|
106
|
+
if start < length:
|
|
107
|
+
# The first two characters are kept so that the delimiter the tokenizer choked
|
|
108
|
+
# on is still visible, e.g. 'u, /*, $$, `u
|
|
109
|
+
tokens.append(
|
|
110
|
+
Token(
|
|
111
|
+
TokenType.UNKNOWN,
|
|
112
|
+
sql[start : start + 2] + "." * (length - start - 2),
|
|
113
|
+
start=start,
|
|
114
|
+
end=length - 1,
|
|
115
|
+
line=sql.count("\n", 0, start) + 1,
|
|
116
|
+
col=start - sql.rfind("\n", 0, start),
|
|
117
|
+
)
|
|
118
|
+
)
|
|
119
|
+
|
|
120
|
+
return tokens
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
def render(sql: str, tokens: list[Token], dialect: DialectType = None) -> str:
|
|
124
|
+
"""Recreates the (anonymized) SQL string from the original `sql` and token positions.
|
|
125
|
+
|
|
126
|
+
Every token is rendered over its own source span, so the result is always as long as
|
|
127
|
+
`sql`: a token that wasn't anonymized is emitted verbatim, keeping the spelling the
|
|
128
|
+
tokenizer normalized away, and an anonymized one has its alias fitted between the
|
|
129
|
+
quotes of its span. The gaps between tokens hold only whitespace and comments, so
|
|
130
|
+
they're redacted rather than reconstructed: comment markers and whitespace survive,
|
|
131
|
+
everything else is blanked. That covers anything the tokenizer didn't reach as well,
|
|
132
|
+
which is a trailing gap whenever `anonymize` wasn't the one to tokenize `sql`.
|
|
133
|
+
|
|
134
|
+
Args:
|
|
135
|
+
sql: The original SQL string.
|
|
136
|
+
tokens: The anonymized tokens to render.
|
|
137
|
+
dialect: The dialect used to identify comments and quotes in `sql`.
|
|
138
|
+
"""
|
|
139
|
+
tokenizer_class = Dialect.get_or_raise(dialect).tokenizer_class
|
|
140
|
+
comments = sorted(tokenizer_class._COMMENTS.items(), key=lambda c: len(c[0]), reverse=True)
|
|
141
|
+
nested = tokenizer_class.NESTED_COMMENTS
|
|
142
|
+
quotes = sorted(
|
|
143
|
+
{
|
|
144
|
+
**tokenizer_class._QUOTES,
|
|
145
|
+
**{start: end for start, (end, _) in tokenizer_class._FORMAT_STRINGS.items()},
|
|
146
|
+
**tokenizer_class._IDENTIFIERS,
|
|
147
|
+
}.items(),
|
|
148
|
+
key=lambda quote: (len(quote[0]), len(quote[1])),
|
|
149
|
+
reverse=True,
|
|
150
|
+
)
|
|
151
|
+
|
|
152
|
+
result = []
|
|
153
|
+
prev = 0
|
|
154
|
+
|
|
155
|
+
for token in tokens:
|
|
156
|
+
result.append(_redact(sql[prev : token.start], comments, nested))
|
|
157
|
+
prev = token.end + 1
|
|
158
|
+
span = sql[token.start : prev]
|
|
159
|
+
if token.token_type in REWRITTEN_TYPES:
|
|
160
|
+
# Blanked in place by `anonymize`, or synthesized by it, so already span-shaped
|
|
161
|
+
result.append(token.text)
|
|
162
|
+
elif token.token_type in ANONYMIZED_TYPES:
|
|
163
|
+
result.append(_fit(span, token.text, quotes, token.token_type))
|
|
164
|
+
else:
|
|
165
|
+
result.append(span)
|
|
166
|
+
|
|
167
|
+
result.append(_redact(sql[prev:], comments, nested))
|
|
168
|
+
|
|
169
|
+
return "".join(result)
|
|
170
|
+
|
|
171
|
+
|
|
172
|
+
def _alias(counter: int, text: str) -> str:
|
|
173
|
+
digits = []
|
|
174
|
+
while counter:
|
|
175
|
+
counter, digit = divmod(counter, ALPHABET_SIZE)
|
|
176
|
+
digits.append(ALPHABET[digit])
|
|
177
|
+
|
|
178
|
+
letters = "".join(reversed(digits)).rjust(sum(not char.isspace() for char in text), "a")
|
|
179
|
+
|
|
180
|
+
alias = []
|
|
181
|
+
i = 0
|
|
182
|
+
for char in text:
|
|
183
|
+
if char.isspace():
|
|
184
|
+
alias.append(char)
|
|
185
|
+
else:
|
|
186
|
+
alias.append(letters[i])
|
|
187
|
+
i += 1
|
|
188
|
+
|
|
189
|
+
return "".join(alias)
|
|
190
|
+
|
|
191
|
+
|
|
192
|
+
def _number_alias(counter: int, text: str) -> str:
|
|
193
|
+
if len(text) > 4000:
|
|
194
|
+
digits_seen = False
|
|
195
|
+
blanked = []
|
|
196
|
+
for char in text:
|
|
197
|
+
if char.isdigit():
|
|
198
|
+
blanked.append("0" if digits_seen else "1")
|
|
199
|
+
digits_seen = True
|
|
200
|
+
else:
|
|
201
|
+
blanked.append(char)
|
|
202
|
+
return "".join(blanked)
|
|
203
|
+
|
|
204
|
+
sep = "e" if "e" in text else ("E" if "E" in text else "")
|
|
205
|
+
mantissa, _, exponent = text.partition(sep) if sep else (text, "", "")
|
|
206
|
+
sign = ""
|
|
207
|
+
if exponent.startswith(("-", "+")):
|
|
208
|
+
sign, exponent = exponent[0], exponent[1:]
|
|
209
|
+
exponent_length = len(exponent)
|
|
210
|
+
|
|
211
|
+
integer, dot, fraction = mantissa.partition(".")
|
|
212
|
+
integer_length = len(integer)
|
|
213
|
+
digits = integer_length + len(fraction)
|
|
214
|
+
mantissa_value = 10 ** (digits - 1) + counter % (9 * 10 ** (digits - 1))
|
|
215
|
+
result = str(mantissa_value)
|
|
216
|
+
if dot:
|
|
217
|
+
result = result[:integer_length] + "." + result[integer_length:]
|
|
218
|
+
if sep:
|
|
219
|
+
# The exponent marker is kept even when there are no digits after it, e.g. 1e
|
|
220
|
+
result += sep + sign
|
|
221
|
+
if exponent_length:
|
|
222
|
+
exponent_value = 10 ** (exponent_length - 1) + (counter // (9 * 10 ** (digits - 1))) % (
|
|
223
|
+
9 * 10 ** (exponent_length - 1)
|
|
224
|
+
)
|
|
225
|
+
result += str(exponent_value)
|
|
226
|
+
|
|
227
|
+
return result
|
|
228
|
+
|
|
229
|
+
|
|
230
|
+
def _fit(span: str, alias: str, quotes: list[tuple[str, str]], token_type: TokenType) -> str:
|
|
231
|
+
"""Fits `alias` into the quoted region of `span`, so the two are always the same length."""
|
|
232
|
+
start = end = 0
|
|
233
|
+
|
|
234
|
+
if token_type in QUOTED_TYPES:
|
|
235
|
+
for open_quote, close_quote in quotes:
|
|
236
|
+
if (
|
|
237
|
+
len(span) >= len(open_quote) + len(close_quote)
|
|
238
|
+
and span.startswith(open_quote)
|
|
239
|
+
and span.endswith(close_quote)
|
|
240
|
+
):
|
|
241
|
+
start, end = len(open_quote), len(close_quote)
|
|
242
|
+
|
|
243
|
+
if token_type == TokenType.HEREDOC_STRING:
|
|
244
|
+
# A heredoc's tag is part of its delimiter, e.g. $tag$body$tag$
|
|
245
|
+
open_end = span.find(close_quote, start)
|
|
246
|
+
close_start = span.rfind(open_quote, 0, len(span) - end)
|
|
247
|
+
if start <= open_end < close_start:
|
|
248
|
+
start, end = open_end + len(close_quote), len(span) - close_start
|
|
249
|
+
|
|
250
|
+
break
|
|
251
|
+
|
|
252
|
+
width = len(span) - start - end
|
|
253
|
+
pad = "0" if token_type == TokenType.NUMBER else "a"
|
|
254
|
+
|
|
255
|
+
return span[:start] + alias[:width].rjust(width, pad) + span[len(span) - end :]
|
|
256
|
+
|
|
257
|
+
|
|
258
|
+
def _blank(sql: str) -> str:
|
|
259
|
+
return "".join(char if char.isspace() else "." for char in sql)
|
|
260
|
+
|
|
261
|
+
|
|
262
|
+
def _blank_comment(sql: str, i: int, start: str, end: str | None, nested: bool) -> tuple[str, int]:
|
|
263
|
+
"""Blanks the body of the comment at `i`, returning its text and the index past it."""
|
|
264
|
+
body = i + len(start)
|
|
265
|
+
|
|
266
|
+
if not end:
|
|
267
|
+
stop = sql.find("\n", body)
|
|
268
|
+
stop = len(sql) if stop == -1 else stop
|
|
269
|
+
return start + _blank(sql[body:stop]), stop
|
|
270
|
+
|
|
271
|
+
depth = 1
|
|
272
|
+
j = body
|
|
273
|
+
while j < len(sql):
|
|
274
|
+
if nested and sql.startswith(start, j):
|
|
275
|
+
depth += 1
|
|
276
|
+
j += len(start)
|
|
277
|
+
elif sql.startswith(end, j):
|
|
278
|
+
j += len(end)
|
|
279
|
+
depth -= 1
|
|
280
|
+
if not depth:
|
|
281
|
+
return start + _blank(sql[body : j - len(end)]) + end, j
|
|
282
|
+
else:
|
|
283
|
+
j += 1
|
|
284
|
+
|
|
285
|
+
return start + _blank(sql[body:]), len(sql)
|
|
286
|
+
|
|
287
|
+
|
|
288
|
+
def _redact(sql: str, comments: list[tuple[str, str | None]], nested: bool) -> str:
|
|
289
|
+
if not sql or sql.isspace():
|
|
290
|
+
return sql
|
|
291
|
+
|
|
292
|
+
result = []
|
|
293
|
+
i = 0
|
|
294
|
+
length = len(sql)
|
|
295
|
+
|
|
296
|
+
while i < length:
|
|
297
|
+
for start, end in comments:
|
|
298
|
+
if sql.startswith(start, i):
|
|
299
|
+
text, i = _blank_comment(sql, i, start, end, nested)
|
|
300
|
+
result.append(text)
|
|
301
|
+
break
|
|
302
|
+
else:
|
|
303
|
+
char = sql[i]
|
|
304
|
+
result.append(char if char.isspace() else ".")
|
|
305
|
+
i += 1
|
|
306
|
+
|
|
307
|
+
return "".join(result)
|
|
@@ -193,11 +193,8 @@ class BigQuery(Dialect):
|
|
|
193
193
|
"EXCEPTION": TokenType.COMMAND,
|
|
194
194
|
"EXPORT": TokenType.EXPORT,
|
|
195
195
|
"FLOAT64": TokenType.DOUBLE,
|
|
196
|
-
"FOR SYSTEM TIME": TokenType.TIMESTAMP_SNAPSHOT,
|
|
197
|
-
"FOR SYSTEM_TIME": TokenType.TIMESTAMP_SNAPSHOT,
|
|
198
196
|
"LOOP": TokenType.COMMAND,
|
|
199
197
|
"MODEL": TokenType.MODEL,
|
|
200
|
-
"NOT DETERMINISTIC": TokenType.VOLATILE,
|
|
201
198
|
"RECORD": TokenType.STRUCT,
|
|
202
199
|
"REPEAT": TokenType.COMMAND,
|
|
203
200
|
"TIMESTAMP": TokenType.TIMESTAMPTZ,
|
|
@@ -17,7 +17,6 @@ class ClickHouse(Dialect):
|
|
|
17
17
|
NORMALIZE_FUNCTIONS: bool | str = False
|
|
18
18
|
NULL_ORDERING = "nulls_are_last"
|
|
19
19
|
SUPPORTS_USER_DEFINED_TYPES = False
|
|
20
|
-
SAFE_DIVISION = True
|
|
21
20
|
LOG_BASE_FIRST: bool | None = None
|
|
22
21
|
FORCE_EARLY_ALIAS_REF_EXPANSION = True
|
|
23
22
|
PRESERVE_ORIGINAL_NAMES = True
|
|
@@ -24,6 +24,7 @@ from sqlglot.helper import (
|
|
|
24
24
|
ensure_list,
|
|
25
25
|
)
|
|
26
26
|
from sqlglot.jsonpath import ALL_JSON_PATH_PARTS, JSONPathTokenizer, parse as parse_json_path
|
|
27
|
+
from sqlglot.optimizer.scope import find_all_in_scope
|
|
27
28
|
from sqlglot.parser import Parser
|
|
28
29
|
from sqlglot.parsers.base import BaseParser
|
|
29
30
|
from sqlglot.time import TIMEZONES, format_time, subsecond_precision
|
|
@@ -1700,7 +1701,7 @@ def timestamptrunc_sql(
|
|
|
1700
1701
|
func: str = "DATE_TRUNC", zone: bool = False
|
|
1701
1702
|
) -> t.Callable[[Generator, exp.TimestampTrunc], str]:
|
|
1702
1703
|
def _timestamptrunc_sql(self: Generator, expression: exp.TimestampTrunc) -> str:
|
|
1703
|
-
args = [
|
|
1704
|
+
args = [weekstart_unit_to_str(self, expression), expression.this]
|
|
1704
1705
|
if zone:
|
|
1705
1706
|
args.append(expression.args.get("zone"))
|
|
1706
1707
|
return self.func(func, *args)
|
|
@@ -1993,6 +1994,23 @@ def ts_or_ds_add_cast(expression: exp.TsOrDsAdd) -> exp.TsOrDsAdd:
|
|
|
1993
1994
|
return expression
|
|
1994
1995
|
|
|
1995
1996
|
|
|
1997
|
+
def remove_ts_or_ds_to_date(
|
|
1998
|
+
to_sql: t.Callable[[Generator, exp.Expr], str] | None = None,
|
|
1999
|
+
args: tuple[str, ...] = ("this",),
|
|
2000
|
+
) -> t.Callable[[Generator, exp.Func], str]:
|
|
2001
|
+
def func(self: Generator, expression: exp.Func) -> str:
|
|
2002
|
+
for arg_key in args:
|
|
2003
|
+
arg = expression.args.get(arg_key)
|
|
2004
|
+
if isinstance(arg, (exp.TsOrDsToDate, exp.TsOrDsToTimestamp)) and not arg.args.get(
|
|
2005
|
+
"format"
|
|
2006
|
+
):
|
|
2007
|
+
expression.set(arg_key, arg.this)
|
|
2008
|
+
|
|
2009
|
+
return to_sql(self, expression) if to_sql else self.function_fallback_sql(expression)
|
|
2010
|
+
|
|
2011
|
+
return func
|
|
2012
|
+
|
|
2013
|
+
|
|
1996
2014
|
def date_delta_sql(name: str, cast: bool = False) -> t.Callable[[Generator, DATE_ADD_OR_DIFF], str]:
|
|
1997
2015
|
def _delta_sql(self: Generator, expression: DATE_ADD_OR_DIFF) -> str:
|
|
1998
2016
|
if cast and isinstance(expression, exp.TsOrDsAdd):
|
|
@@ -2043,12 +2061,28 @@ def unit_to_str(expression: exp.Expr, default: str = "DAY") -> exp.Expr | None:
|
|
|
2043
2061
|
if not unit:
|
|
2044
2062
|
return exp.Literal.string(default) if default else None
|
|
2045
2063
|
|
|
2064
|
+
if isinstance(unit, exp.WeekStart):
|
|
2065
|
+
# WEEK(<day>) is BigQuery-only syntax, so it degrades to the plain WEEK unit. Unlike
|
|
2066
|
+
# Generator.weekstart_name, this can't warn about a changed week start (no generator
|
|
2067
|
+
# access here) - callers that need the warning should use weekstart_unit_to_str
|
|
2068
|
+
return exp.Literal.string("WEEK")
|
|
2069
|
+
|
|
2046
2070
|
if isinstance(unit, exp.Placeholder) or type(unit) not in (exp.Var, exp.Literal):
|
|
2047
2071
|
return unit
|
|
2048
2072
|
|
|
2049
2073
|
return exp.Literal.string(unit.name)
|
|
2050
2074
|
|
|
2051
2075
|
|
|
2076
|
+
def weekstart_unit_to_str(
|
|
2077
|
+
self: Generator, expression: exp.Expr, default: str = "DAY"
|
|
2078
|
+
) -> exp.Expr | None:
|
|
2079
|
+
unit = expression.args.get("unit")
|
|
2080
|
+
if isinstance(unit, exp.WeekStart):
|
|
2081
|
+
return exp.Literal.string(self.weekstart_name(unit))
|
|
2082
|
+
|
|
2083
|
+
return unit_to_str(expression, default)
|
|
2084
|
+
|
|
2085
|
+
|
|
2052
2086
|
def unit_to_var(expression: exp.Expr, default: str = "DAY") -> exp.Expr | None:
|
|
2053
2087
|
unit = expression.args.get("unit")
|
|
2054
2088
|
|
|
@@ -2072,10 +2106,14 @@ WEEK_START_DAY_TO_DOW = {
|
|
|
2072
2106
|
}
|
|
2073
2107
|
|
|
2074
2108
|
|
|
2109
|
+
def week_offset_to_dow(offset: int) -> int:
|
|
2110
|
+
"""Convert a dialect's WEEK_OFFSET (days relative to Monday) to the ISO day number of its week start."""
|
|
2111
|
+
return offset % 7 + 1
|
|
2112
|
+
|
|
2113
|
+
|
|
2075
2114
|
def week_unit_to_dow(unit: exp.Expr | None) -> int | None:
|
|
2076
2115
|
"""
|
|
2077
|
-
Compute the week start day for a week-ish diff unit, e.g BigQuery's WEEK(<day>)
|
|
2078
|
-
or ISOWEEK unit parts.
|
|
2116
|
+
Compute the week start day for a week-ish diff unit, e.g BigQuery's WEEK(<day>) or ISOWEEK unit parts.
|
|
2079
2117
|
|
|
2080
2118
|
Args:
|
|
2081
2119
|
unit: The unit expression (Var for WEEK/ISOWEEK or WeekStart)
|
|
@@ -2147,7 +2185,7 @@ def merge_without_target_sql(self: Generator, expression: exp.Merge) -> str:
|
|
|
2147
2185
|
then: exp.Insert | exp.Update | None = when.args.get("then")
|
|
2148
2186
|
if then:
|
|
2149
2187
|
if isinstance(then, exp.Update):
|
|
2150
|
-
for equals in then
|
|
2188
|
+
for equals in find_all_in_scope(then, exp.EQ):
|
|
2151
2189
|
equal_lhs = equals.this
|
|
2152
2190
|
if (
|
|
2153
2191
|
isinstance(equal_lhs, exp.Column)
|
|
@@ -2175,7 +2213,11 @@ def build_json_extract_path(
|
|
|
2175
2213
|
for arg in args[1:]:
|
|
2176
2214
|
if not isinstance(arg, exp.Literal):
|
|
2177
2215
|
# We use the fallback parser because we can't really transpile non-literals safely
|
|
2178
|
-
return expr_type
|
|
2216
|
+
return expr_type(
|
|
2217
|
+
this=seq_get(args, 0),
|
|
2218
|
+
expression=seq_get(args, 1),
|
|
2219
|
+
expressions=list(args[2:]) or None,
|
|
2220
|
+
)
|
|
2179
2221
|
|
|
2180
2222
|
text = arg.name
|
|
2181
2223
|
if is_int(text) and (not arrow_req_json_type or not arg.is_string):
|
|
@@ -67,12 +67,6 @@ class Dremio(Dialect):
|
|
|
67
67
|
class Tokenizer(tokens.Tokenizer):
|
|
68
68
|
COMMENTS = ["--", "//", ("/*", "*/")]
|
|
69
69
|
|
|
70
|
-
KEYWORDS = {
|
|
71
|
-
**tokens.Tokenizer.KEYWORDS,
|
|
72
|
-
"AT SNAPSHOT": tokens.TokenType.VERSION_SNAPSHOT,
|
|
73
|
-
"AT TIMESTAMP": tokens.TokenType.TIMESTAMP_SNAPSHOT,
|
|
74
|
-
}
|
|
75
|
-
|
|
76
70
|
Parser = DremioParser
|
|
77
71
|
|
|
78
72
|
Generator = DremioGenerator
|
|
@@ -109,8 +109,6 @@ class Hive(Dialect):
|
|
|
109
109
|
"MINUS": TokenType.EXCEPT,
|
|
110
110
|
"MSCK REPAIR": TokenType.COMMAND,
|
|
111
111
|
"REFRESH": TokenType.REFRESH,
|
|
112
|
-
"TIMESTAMP AS OF": TokenType.TIMESTAMP_SNAPSHOT,
|
|
113
|
-
"VERSION AS OF": TokenType.VERSION_SNAPSHOT,
|
|
114
112
|
"SERDEPROPERTIES": TokenType.SERDE_PROPERTIES,
|
|
115
113
|
}
|
|
116
114
|
|
|
@@ -96,7 +96,6 @@ class MySQL(Dialect):
|
|
|
96
96
|
"SERIAL": TokenType.SERIAL,
|
|
97
97
|
"SIGNED": TokenType.BIGINT,
|
|
98
98
|
"SIGNED INTEGER": TokenType.BIGINT,
|
|
99
|
-
"SOUNDS LIKE": TokenType.SOUNDS_LIKE,
|
|
100
99
|
"START": TokenType.BEGIN,
|
|
101
100
|
"TIMESTAMP": TokenType.TIMESTAMPTZ,
|
|
102
101
|
"TINYBLOB": TokenType.TINYBLOB,
|