sqlglot 26.27.1__tar.gz → 26.29.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-26.27.1 → sqlglot-26.29.0}/CHANGELOG.md +62 -0
- {sqlglot-26.27.1 → sqlglot-26.29.0}/PKG-INFO +1 -1
- {sqlglot-26.27.1 → sqlglot-26.29.0}/sqlglot/_version.py +2 -2
- {sqlglot-26.27.1 → sqlglot-26.29.0}/sqlglot/dialects/athena.py +1 -0
- {sqlglot-26.27.1 → sqlglot-26.29.0}/sqlglot/dialects/dialect.py +4 -1
- {sqlglot-26.27.1 → sqlglot-26.29.0}/sqlglot/dialects/duckdb.py +7 -0
- {sqlglot-26.27.1 → sqlglot-26.29.0}/sqlglot/dialects/snowflake.py +38 -1
- {sqlglot-26.27.1 → sqlglot-26.29.0}/sqlglot/dialects/tsql.py +2 -2
- {sqlglot-26.27.1 → sqlglot-26.29.0}/sqlglot/expressions.py +9 -2
- {sqlglot-26.27.1 → sqlglot-26.29.0}/sqlglot/generator.py +20 -3
- {sqlglot-26.27.1 → sqlglot-26.29.0}/sqlglot/optimizer/annotate_types.py +44 -1
- {sqlglot-26.27.1 → sqlglot-26.29.0}/sqlglot/optimizer/qualify_columns.py +7 -0
- {sqlglot-26.27.1 → sqlglot-26.29.0}/sqlglot/optimizer/scope.py +19 -3
- {sqlglot-26.27.1 → sqlglot-26.29.0}/sqlglot/parser.py +194 -96
- {sqlglot-26.27.1 → sqlglot-26.29.0}/sqlglot.egg-info/PKG-INFO +1 -1
- {sqlglot-26.27.1 → sqlglot-26.29.0}/sqlglot.egg-info/SOURCES.txt +1 -0
- {sqlglot-26.27.1 → sqlglot-26.29.0}/tests/dialects/test_athena.py +4 -0
- {sqlglot-26.27.1 → sqlglot-26.29.0}/tests/dialects/test_dialect.py +0 -219
- {sqlglot-26.27.1 → sqlglot-26.29.0}/tests/dialects/test_duckdb.py +22 -1
- sqlglot-26.29.0/tests/dialects/test_pipe_syntax.py +452 -0
- {sqlglot-26.27.1 → sqlglot-26.29.0}/tests/dialects/test_snowflake.py +38 -1
- {sqlglot-26.27.1 → sqlglot-26.29.0}/tests/dialects/test_tsql.py +4 -0
- {sqlglot-26.27.1 → sqlglot-26.29.0}/tests/fixtures/optimizer/qualify_columns.sql +5 -0
- {sqlglot-26.27.1 → sqlglot-26.29.0}/tests/test_optimizer.py +37 -0
- {sqlglot-26.27.1 → sqlglot-26.29.0}/.gitignore +0 -0
- {sqlglot-26.27.1 → sqlglot-26.29.0}/.gitpod.yml +0 -0
- {sqlglot-26.27.1 → sqlglot-26.29.0}/.pre-commit-config.yaml +0 -0
- {sqlglot-26.27.1 → sqlglot-26.29.0}/CONTRIBUTING.md +0 -0
- {sqlglot-26.27.1 → sqlglot-26.29.0}/LICENSE +0 -0
- {sqlglot-26.27.1 → sqlglot-26.29.0}/MANIFEST.in +0 -0
- {sqlglot-26.27.1 → sqlglot-26.29.0}/Makefile +0 -0
- {sqlglot-26.27.1 → sqlglot-26.29.0}/README.md +0 -0
- {sqlglot-26.27.1 → sqlglot-26.29.0}/pyproject.toml +0 -0
- {sqlglot-26.27.1 → sqlglot-26.29.0}/setup.cfg +0 -0
- {sqlglot-26.27.1 → sqlglot-26.29.0}/setup.py +0 -0
- {sqlglot-26.27.1 → sqlglot-26.29.0}/sqlglot/__init__.py +0 -0
- {sqlglot-26.27.1 → sqlglot-26.29.0}/sqlglot/__main__.py +0 -0
- {sqlglot-26.27.1 → sqlglot-26.29.0}/sqlglot/_typing.py +0 -0
- {sqlglot-26.27.1 → sqlglot-26.29.0}/sqlglot/dialects/__init__.py +0 -0
- {sqlglot-26.27.1 → sqlglot-26.29.0}/sqlglot/dialects/bigquery.py +0 -0
- {sqlglot-26.27.1 → sqlglot-26.29.0}/sqlglot/dialects/clickhouse.py +0 -0
- {sqlglot-26.27.1 → sqlglot-26.29.0}/sqlglot/dialects/databricks.py +0 -0
- {sqlglot-26.27.1 → sqlglot-26.29.0}/sqlglot/dialects/doris.py +0 -0
- {sqlglot-26.27.1 → sqlglot-26.29.0}/sqlglot/dialects/drill.py +0 -0
- {sqlglot-26.27.1 → sqlglot-26.29.0}/sqlglot/dialects/druid.py +0 -0
- {sqlglot-26.27.1 → sqlglot-26.29.0}/sqlglot/dialects/dune.py +0 -0
- {sqlglot-26.27.1 → sqlglot-26.29.0}/sqlglot/dialects/hive.py +0 -0
- {sqlglot-26.27.1 → sqlglot-26.29.0}/sqlglot/dialects/materialize.py +0 -0
- {sqlglot-26.27.1 → sqlglot-26.29.0}/sqlglot/dialects/mysql.py +0 -0
- {sqlglot-26.27.1 → sqlglot-26.29.0}/sqlglot/dialects/oracle.py +0 -0
- {sqlglot-26.27.1 → sqlglot-26.29.0}/sqlglot/dialects/postgres.py +0 -0
- {sqlglot-26.27.1 → sqlglot-26.29.0}/sqlglot/dialects/presto.py +0 -0
- {sqlglot-26.27.1 → sqlglot-26.29.0}/sqlglot/dialects/prql.py +0 -0
- {sqlglot-26.27.1 → sqlglot-26.29.0}/sqlglot/dialects/redshift.py +0 -0
- {sqlglot-26.27.1 → sqlglot-26.29.0}/sqlglot/dialects/risingwave.py +0 -0
- {sqlglot-26.27.1 → sqlglot-26.29.0}/sqlglot/dialects/spark.py +0 -0
- {sqlglot-26.27.1 → sqlglot-26.29.0}/sqlglot/dialects/spark2.py +0 -0
- {sqlglot-26.27.1 → sqlglot-26.29.0}/sqlglot/dialects/sqlite.py +0 -0
- {sqlglot-26.27.1 → sqlglot-26.29.0}/sqlglot/dialects/starrocks.py +0 -0
- {sqlglot-26.27.1 → sqlglot-26.29.0}/sqlglot/dialects/tableau.py +0 -0
- {sqlglot-26.27.1 → sqlglot-26.29.0}/sqlglot/dialects/teradata.py +0 -0
- {sqlglot-26.27.1 → sqlglot-26.29.0}/sqlglot/dialects/trino.py +0 -0
- {sqlglot-26.27.1 → sqlglot-26.29.0}/sqlglot/diff.py +0 -0
- {sqlglot-26.27.1 → sqlglot-26.29.0}/sqlglot/errors.py +0 -0
- {sqlglot-26.27.1 → sqlglot-26.29.0}/sqlglot/executor/__init__.py +0 -0
- {sqlglot-26.27.1 → sqlglot-26.29.0}/sqlglot/executor/context.py +0 -0
- {sqlglot-26.27.1 → sqlglot-26.29.0}/sqlglot/executor/env.py +0 -0
- {sqlglot-26.27.1 → sqlglot-26.29.0}/sqlglot/executor/python.py +0 -0
- {sqlglot-26.27.1 → sqlglot-26.29.0}/sqlglot/executor/table.py +0 -0
- {sqlglot-26.27.1 → sqlglot-26.29.0}/sqlglot/helper.py +0 -0
- {sqlglot-26.27.1 → sqlglot-26.29.0}/sqlglot/jsonpath.py +0 -0
- {sqlglot-26.27.1 → sqlglot-26.29.0}/sqlglot/lineage.py +0 -0
- {sqlglot-26.27.1 → sqlglot-26.29.0}/sqlglot/optimizer/__init__.py +0 -0
- {sqlglot-26.27.1 → sqlglot-26.29.0}/sqlglot/optimizer/canonicalize.py +0 -0
- {sqlglot-26.27.1 → sqlglot-26.29.0}/sqlglot/optimizer/eliminate_ctes.py +0 -0
- {sqlglot-26.27.1 → sqlglot-26.29.0}/sqlglot/optimizer/eliminate_joins.py +0 -0
- {sqlglot-26.27.1 → sqlglot-26.29.0}/sqlglot/optimizer/eliminate_subqueries.py +0 -0
- {sqlglot-26.27.1 → sqlglot-26.29.0}/sqlglot/optimizer/isolate_table_selects.py +0 -0
- {sqlglot-26.27.1 → sqlglot-26.29.0}/sqlglot/optimizer/merge_subqueries.py +0 -0
- {sqlglot-26.27.1 → sqlglot-26.29.0}/sqlglot/optimizer/normalize.py +0 -0
- {sqlglot-26.27.1 → sqlglot-26.29.0}/sqlglot/optimizer/normalize_identifiers.py +0 -0
- {sqlglot-26.27.1 → sqlglot-26.29.0}/sqlglot/optimizer/optimize_joins.py +0 -0
- {sqlglot-26.27.1 → sqlglot-26.29.0}/sqlglot/optimizer/optimizer.py +0 -0
- {sqlglot-26.27.1 → sqlglot-26.29.0}/sqlglot/optimizer/pushdown_predicates.py +0 -0
- {sqlglot-26.27.1 → sqlglot-26.29.0}/sqlglot/optimizer/pushdown_projections.py +0 -0
- {sqlglot-26.27.1 → sqlglot-26.29.0}/sqlglot/optimizer/qualify.py +0 -0
- {sqlglot-26.27.1 → sqlglot-26.29.0}/sqlglot/optimizer/qualify_tables.py +0 -0
- {sqlglot-26.27.1 → sqlglot-26.29.0}/sqlglot/optimizer/simplify.py +0 -0
- {sqlglot-26.27.1 → sqlglot-26.29.0}/sqlglot/optimizer/unnest_subqueries.py +0 -0
- {sqlglot-26.27.1 → sqlglot-26.29.0}/sqlglot/planner.py +0 -0
- {sqlglot-26.27.1 → sqlglot-26.29.0}/sqlglot/py.typed +0 -0
- {sqlglot-26.27.1 → sqlglot-26.29.0}/sqlglot/schema.py +0 -0
- {sqlglot-26.27.1 → sqlglot-26.29.0}/sqlglot/serde.py +0 -0
- {sqlglot-26.27.1 → sqlglot-26.29.0}/sqlglot/time.py +0 -0
- {sqlglot-26.27.1 → sqlglot-26.29.0}/sqlglot/tokens.py +0 -0
- {sqlglot-26.27.1 → sqlglot-26.29.0}/sqlglot/transforms.py +0 -0
- {sqlglot-26.27.1 → sqlglot-26.29.0}/sqlglot/trie.py +0 -0
- {sqlglot-26.27.1 → sqlglot-26.29.0}/sqlglot.egg-info/dependency_links.txt +0 -0
- {sqlglot-26.27.1 → sqlglot-26.29.0}/sqlglot.egg-info/requires.txt +0 -0
- {sqlglot-26.27.1 → sqlglot-26.29.0}/sqlglot.egg-info/top_level.txt +0 -0
- {sqlglot-26.27.1 → sqlglot-26.29.0}/sqlglot.png +0 -0
- {sqlglot-26.27.1 → sqlglot-26.29.0}/sqlglotrs/Cargo.lock +0 -0
- {sqlglot-26.27.1 → sqlglot-26.29.0}/sqlglotrs/Cargo.toml +0 -0
- {sqlglot-26.27.1 → sqlglot-26.29.0}/sqlglotrs/benches/dialect_settings.json +0 -0
- {sqlglot-26.27.1 → sqlglot-26.29.0}/sqlglotrs/benches/long.rs +0 -0
- {sqlglot-26.27.1 → sqlglot-26.29.0}/sqlglotrs/benches/token_type_settings.json +0 -0
- {sqlglot-26.27.1 → sqlglot-26.29.0}/sqlglotrs/benches/tokenizer_dialect_settings.json +0 -0
- {sqlglot-26.27.1 → sqlglot-26.29.0}/sqlglotrs/benches/tokenizer_settings.json +0 -0
- {sqlglot-26.27.1 → sqlglot-26.29.0}/sqlglotrs/pyproject.toml +0 -0
- {sqlglot-26.27.1 → sqlglot-26.29.0}/sqlglotrs/src/lib.rs +0 -0
- {sqlglot-26.27.1 → sqlglot-26.29.0}/sqlglotrs/src/settings.rs +0 -0
- {sqlglot-26.27.1 → sqlglot-26.29.0}/sqlglotrs/src/token.rs +0 -0
- {sqlglot-26.27.1 → sqlglot-26.29.0}/sqlglotrs/src/tokenizer.rs +0 -0
- {sqlglot-26.27.1 → sqlglot-26.29.0}/sqlglotrs/src/trie.rs +0 -0
- {sqlglot-26.27.1 → sqlglot-26.29.0}/tests/__init__.py +0 -0
- {sqlglot-26.27.1 → sqlglot-26.29.0}/tests/dialects/__init__.py +0 -0
- {sqlglot-26.27.1 → sqlglot-26.29.0}/tests/dialects/test_bigquery.py +0 -0
- {sqlglot-26.27.1 → sqlglot-26.29.0}/tests/dialects/test_clickhouse.py +0 -0
- {sqlglot-26.27.1 → sqlglot-26.29.0}/tests/dialects/test_databricks.py +0 -0
- {sqlglot-26.27.1 → sqlglot-26.29.0}/tests/dialects/test_doris.py +0 -0
- {sqlglot-26.27.1 → sqlglot-26.29.0}/tests/dialects/test_drill.py +0 -0
- {sqlglot-26.27.1 → sqlglot-26.29.0}/tests/dialects/test_druid.py +0 -0
- {sqlglot-26.27.1 → sqlglot-26.29.0}/tests/dialects/test_dune.py +0 -0
- {sqlglot-26.27.1 → sqlglot-26.29.0}/tests/dialects/test_hive.py +0 -0
- {sqlglot-26.27.1 → sqlglot-26.29.0}/tests/dialects/test_materialize.py +0 -0
- {sqlglot-26.27.1 → sqlglot-26.29.0}/tests/dialects/test_mysql.py +0 -0
- {sqlglot-26.27.1 → sqlglot-26.29.0}/tests/dialects/test_oracle.py +0 -0
- {sqlglot-26.27.1 → sqlglot-26.29.0}/tests/dialects/test_postgres.py +0 -0
- {sqlglot-26.27.1 → sqlglot-26.29.0}/tests/dialects/test_presto.py +0 -0
- {sqlglot-26.27.1 → sqlglot-26.29.0}/tests/dialects/test_prql.py +0 -0
- {sqlglot-26.27.1 → sqlglot-26.29.0}/tests/dialects/test_redshift.py +0 -0
- {sqlglot-26.27.1 → sqlglot-26.29.0}/tests/dialects/test_risingwave.py +0 -0
- {sqlglot-26.27.1 → sqlglot-26.29.0}/tests/dialects/test_spark.py +0 -0
- {sqlglot-26.27.1 → sqlglot-26.29.0}/tests/dialects/test_sqlite.py +0 -0
- {sqlglot-26.27.1 → sqlglot-26.29.0}/tests/dialects/test_starrocks.py +0 -0
- {sqlglot-26.27.1 → sqlglot-26.29.0}/tests/dialects/test_tableau.py +0 -0
- {sqlglot-26.27.1 → sqlglot-26.29.0}/tests/dialects/test_teradata.py +0 -0
- {sqlglot-26.27.1 → sqlglot-26.29.0}/tests/dialects/test_trino.py +0 -0
- {sqlglot-26.27.1 → sqlglot-26.29.0}/tests/fixtures/identity.sql +0 -0
- {sqlglot-26.27.1 → sqlglot-26.29.0}/tests/fixtures/jsonpath/LICENSE +0 -0
- {sqlglot-26.27.1 → sqlglot-26.29.0}/tests/fixtures/jsonpath/cts.json +0 -0
- {sqlglot-26.27.1 → sqlglot-26.29.0}/tests/fixtures/optimizer/annotate_functions.sql +0 -0
- {sqlglot-26.27.1 → sqlglot-26.29.0}/tests/fixtures/optimizer/annotate_types.sql +0 -0
- {sqlglot-26.27.1 → sqlglot-26.29.0}/tests/fixtures/optimizer/canonicalize.sql +0 -0
- {sqlglot-26.27.1 → sqlglot-26.29.0}/tests/fixtures/optimizer/eliminate_ctes.sql +0 -0
- {sqlglot-26.27.1 → sqlglot-26.29.0}/tests/fixtures/optimizer/eliminate_joins.sql +0 -0
- {sqlglot-26.27.1 → sqlglot-26.29.0}/tests/fixtures/optimizer/eliminate_subqueries.sql +0 -0
- {sqlglot-26.27.1 → sqlglot-26.29.0}/tests/fixtures/optimizer/isolate_table_selects.sql +0 -0
- {sqlglot-26.27.1 → sqlglot-26.29.0}/tests/fixtures/optimizer/merge_subqueries.sql +0 -0
- {sqlglot-26.27.1 → sqlglot-26.29.0}/tests/fixtures/optimizer/normalize.sql +0 -0
- {sqlglot-26.27.1 → sqlglot-26.29.0}/tests/fixtures/optimizer/normalize_identifiers.sql +0 -0
- {sqlglot-26.27.1 → sqlglot-26.29.0}/tests/fixtures/optimizer/optimize_joins.sql +0 -0
- {sqlglot-26.27.1 → sqlglot-26.29.0}/tests/fixtures/optimizer/optimizer.sql +0 -0
- {sqlglot-26.27.1 → sqlglot-26.29.0}/tests/fixtures/optimizer/pushdown_cte_alias_columns.sql +0 -0
- {sqlglot-26.27.1 → sqlglot-26.29.0}/tests/fixtures/optimizer/pushdown_predicates.sql +0 -0
- {sqlglot-26.27.1 → sqlglot-26.29.0}/tests/fixtures/optimizer/pushdown_projections.sql +0 -0
- {sqlglot-26.27.1 → sqlglot-26.29.0}/tests/fixtures/optimizer/qualify_columns__invalid.sql +0 -0
- {sqlglot-26.27.1 → sqlglot-26.29.0}/tests/fixtures/optimizer/qualify_columns__with_invisible.sql +0 -0
- {sqlglot-26.27.1 → sqlglot-26.29.0}/tests/fixtures/optimizer/qualify_columns_ddl.sql +0 -0
- {sqlglot-26.27.1 → sqlglot-26.29.0}/tests/fixtures/optimizer/qualify_tables.sql +0 -0
- {sqlglot-26.27.1 → sqlglot-26.29.0}/tests/fixtures/optimizer/quote_identifiers.sql +0 -0
- {sqlglot-26.27.1 → sqlglot-26.29.0}/tests/fixtures/optimizer/simplify.sql +0 -0
- {sqlglot-26.27.1 → sqlglot-26.29.0}/tests/fixtures/optimizer/tpc-ds/call_center.csv.gz +0 -0
- {sqlglot-26.27.1 → sqlglot-26.29.0}/tests/fixtures/optimizer/tpc-ds/catalog_page.csv.gz +0 -0
- {sqlglot-26.27.1 → sqlglot-26.29.0}/tests/fixtures/optimizer/tpc-ds/catalog_returns.csv.gz +0 -0
- {sqlglot-26.27.1 → sqlglot-26.29.0}/tests/fixtures/optimizer/tpc-ds/catalog_sales.csv.gz +0 -0
- {sqlglot-26.27.1 → sqlglot-26.29.0}/tests/fixtures/optimizer/tpc-ds/customer.csv.gz +0 -0
- {sqlglot-26.27.1 → sqlglot-26.29.0}/tests/fixtures/optimizer/tpc-ds/customer_address.csv.gz +0 -0
- {sqlglot-26.27.1 → sqlglot-26.29.0}/tests/fixtures/optimizer/tpc-ds/customer_demographics.csv.gz +0 -0
- {sqlglot-26.27.1 → sqlglot-26.29.0}/tests/fixtures/optimizer/tpc-ds/date_dim.csv.gz +0 -0
- {sqlglot-26.27.1 → sqlglot-26.29.0}/tests/fixtures/optimizer/tpc-ds/household_demographics.csv.gz +0 -0
- {sqlglot-26.27.1 → sqlglot-26.29.0}/tests/fixtures/optimizer/tpc-ds/income_band.csv.gz +0 -0
- {sqlglot-26.27.1 → sqlglot-26.29.0}/tests/fixtures/optimizer/tpc-ds/inventory.csv.gz +0 -0
- {sqlglot-26.27.1 → sqlglot-26.29.0}/tests/fixtures/optimizer/tpc-ds/item.csv.gz +0 -0
- {sqlglot-26.27.1 → sqlglot-26.29.0}/tests/fixtures/optimizer/tpc-ds/promotion.csv.gz +0 -0
- {sqlglot-26.27.1 → sqlglot-26.29.0}/tests/fixtures/optimizer/tpc-ds/reason.csv.gz +0 -0
- {sqlglot-26.27.1 → sqlglot-26.29.0}/tests/fixtures/optimizer/tpc-ds/ship_mode.csv.gz +0 -0
- {sqlglot-26.27.1 → sqlglot-26.29.0}/tests/fixtures/optimizer/tpc-ds/store.csv.gz +0 -0
- {sqlglot-26.27.1 → sqlglot-26.29.0}/tests/fixtures/optimizer/tpc-ds/store_returns.csv.gz +0 -0
- {sqlglot-26.27.1 → sqlglot-26.29.0}/tests/fixtures/optimizer/tpc-ds/store_sales.csv.gz +0 -0
- {sqlglot-26.27.1 → sqlglot-26.29.0}/tests/fixtures/optimizer/tpc-ds/time_dim.csv.gz +0 -0
- {sqlglot-26.27.1 → sqlglot-26.29.0}/tests/fixtures/optimizer/tpc-ds/tpc-ds.sql +0 -0
- {sqlglot-26.27.1 → sqlglot-26.29.0}/tests/fixtures/optimizer/tpc-ds/warehouse.csv.gz +0 -0
- {sqlglot-26.27.1 → sqlglot-26.29.0}/tests/fixtures/optimizer/tpc-ds/web_page.csv.gz +0 -0
- {sqlglot-26.27.1 → sqlglot-26.29.0}/tests/fixtures/optimizer/tpc-ds/web_returns.csv.gz +0 -0
- {sqlglot-26.27.1 → sqlglot-26.29.0}/tests/fixtures/optimizer/tpc-ds/web_sales.csv.gz +0 -0
- {sqlglot-26.27.1 → sqlglot-26.29.0}/tests/fixtures/optimizer/tpc-ds/web_site.csv.gz +0 -0
- {sqlglot-26.27.1 → sqlglot-26.29.0}/tests/fixtures/optimizer/tpc-h/customer.csv.gz +0 -0
- {sqlglot-26.27.1 → sqlglot-26.29.0}/tests/fixtures/optimizer/tpc-h/lineitem.csv.gz +0 -0
- {sqlglot-26.27.1 → sqlglot-26.29.0}/tests/fixtures/optimizer/tpc-h/nation.csv.gz +0 -0
- {sqlglot-26.27.1 → sqlglot-26.29.0}/tests/fixtures/optimizer/tpc-h/orders.csv.gz +0 -0
- {sqlglot-26.27.1 → sqlglot-26.29.0}/tests/fixtures/optimizer/tpc-h/part.csv.gz +0 -0
- {sqlglot-26.27.1 → sqlglot-26.29.0}/tests/fixtures/optimizer/tpc-h/partsupp.csv.gz +0 -0
- {sqlglot-26.27.1 → sqlglot-26.29.0}/tests/fixtures/optimizer/tpc-h/region.csv.gz +0 -0
- {sqlglot-26.27.1 → sqlglot-26.29.0}/tests/fixtures/optimizer/tpc-h/supplier.csv.gz +0 -0
- {sqlglot-26.27.1 → sqlglot-26.29.0}/tests/fixtures/optimizer/tpc-h/tpc-h.sql +0 -0
- {sqlglot-26.27.1 → sqlglot-26.29.0}/tests/fixtures/optimizer/unnest_subqueries.sql +0 -0
- {sqlglot-26.27.1 → sqlglot-26.29.0}/tests/fixtures/partial.sql +0 -0
- {sqlglot-26.27.1 → sqlglot-26.29.0}/tests/fixtures/pretty.sql +0 -0
- {sqlglot-26.27.1 → sqlglot-26.29.0}/tests/gen_fixtures.py +0 -0
- {sqlglot-26.27.1 → sqlglot-26.29.0}/tests/helpers.py +0 -0
- {sqlglot-26.27.1 → sqlglot-26.29.0}/tests/test_build.py +0 -0
- {sqlglot-26.27.1 → sqlglot-26.29.0}/tests/test_diff.py +0 -0
- {sqlglot-26.27.1 → sqlglot-26.29.0}/tests/test_docs.py +0 -0
- {sqlglot-26.27.1 → sqlglot-26.29.0}/tests/test_executor.py +0 -0
- {sqlglot-26.27.1 → sqlglot-26.29.0}/tests/test_expressions.py +0 -0
- {sqlglot-26.27.1 → sqlglot-26.29.0}/tests/test_generator.py +0 -0
- {sqlglot-26.27.1 → sqlglot-26.29.0}/tests/test_helper.py +0 -0
- {sqlglot-26.27.1 → sqlglot-26.29.0}/tests/test_jsonpath.py +0 -0
- {sqlglot-26.27.1 → sqlglot-26.29.0}/tests/test_lineage.py +0 -0
- {sqlglot-26.27.1 → sqlglot-26.29.0}/tests/test_parser.py +0 -0
- {sqlglot-26.27.1 → sqlglot-26.29.0}/tests/test_schema.py +0 -0
- {sqlglot-26.27.1 → sqlglot-26.29.0}/tests/test_serde.py +0 -0
- {sqlglot-26.27.1 → sqlglot-26.29.0}/tests/test_time.py +0 -0
- {sqlglot-26.27.1 → sqlglot-26.29.0}/tests/test_tokens.py +0 -0
- {sqlglot-26.27.1 → sqlglot-26.29.0}/tests/test_transforms.py +0 -0
- {sqlglot-26.27.1 → sqlglot-26.29.0}/tests/test_transpile.py +0 -0
@@ -1,6 +1,66 @@
|
|
1
1
|
Changelog
|
2
2
|
=========
|
3
3
|
|
4
|
+
## [v26.28.1] - 2025-06-13
|
5
|
+
### :boom: BREAKING CHANGES
|
6
|
+
- due to [`44297f1`](https://github.com/tobymao/sqlglot/commit/44297f1c5c8c2cb16fe77c318312f417b4281708) - JOIN pipe syntax, Set Operators as CTEs *(PR [#5215](https://github.com/tobymao/sqlglot/pull/5215) by [@geooo109](https://github.com/geooo109))*:
|
7
|
+
|
8
|
+
JOIN pipe syntax, Set Operators as CTEs (#5215)
|
9
|
+
|
10
|
+
|
11
|
+
### :sparkles: New Features
|
12
|
+
- [`44297f1`](https://github.com/tobymao/sqlglot/commit/44297f1c5c8c2cb16fe77c318312f417b4281708) - **parser**: JOIN pipe syntax, Set Operators as CTEs *(PR [#5215](https://github.com/tobymao/sqlglot/pull/5215) by [@geooo109](https://github.com/geooo109))*
|
13
|
+
- [`21cd3eb`](https://github.com/tobymao/sqlglot/commit/21cd3ebf5d0b57f5b102c5aadc3b24a598ebe918) - **parser**: PIVOT/UNPIVOT pipe syntax *(PR [#5222](https://github.com/tobymao/sqlglot/pull/5222) by [@geooo109](https://github.com/geooo109))*
|
14
|
+
|
15
|
+
### :bug: Bug Fixes
|
16
|
+
- [`28fed58`](https://github.com/tobymao/sqlglot/commit/28fed586a39df83aade4792217743a1a859fd039) - **optimizer**: UnboundLocalError in scope module *(commit by [@georgesittas](https://github.com/georgesittas))*
|
17
|
+
- [`809e05a`](https://github.com/tobymao/sqlglot/commit/809e05a743d5a2904a1d6f6813f24ca7549ac7ef) - **snowflake**: preserve STRTOK_TO_ARRAY roundtrip *(commit by [@georgesittas](https://github.com/georgesittas))*
|
18
|
+
|
19
|
+
### :recycle: Refactors
|
20
|
+
- [`aac70aa`](https://github.com/tobymao/sqlglot/commit/aac70aaaa8d840c267129e2307ccb65058cef0c9) - **parser**: simpler _parse_pipe_syntax_select *(commit by [@geooo109](https://github.com/geooo109))*
|
21
|
+
|
22
|
+
|
23
|
+
## [v26.27.0] - 2025-06-12
|
24
|
+
### :boom: BREAKING CHANGES
|
25
|
+
- due to [`ac6555b`](https://github.com/tobymao/sqlglot/commit/ac6555b4d6c162ef7b14b63307d01fd560138ea0) - preserve DIV binary operator, fixes [#5198](https://github.com/tobymao/sqlglot/pull/5198) *(PR [#5199](https://github.com/tobymao/sqlglot/pull/5199) by [@georgesittas](https://github.com/georgesittas))*:
|
26
|
+
|
27
|
+
preserve DIV binary operator, fixes #5198 (#5199)
|
28
|
+
|
29
|
+
- due to [`dfdd84b`](https://github.com/tobymao/sqlglot/commit/dfdd84bbc50da70f40a17b39935f8171d961f7d2) - CTEs instead of subqueries for pipe syntax *(PR [#5205](https://github.com/tobymao/sqlglot/pull/5205) by [@geooo109](https://github.com/geooo109))*:
|
30
|
+
|
31
|
+
CTEs instead of subqueries for pipe syntax (#5205)
|
32
|
+
|
33
|
+
- due to [`5f95299`](https://github.com/tobymao/sqlglot/commit/5f9529940d83e89704f7d25eda63cd73fdb503ae) - support multi-part (>3) dotted functions *(PR [#5211](https://github.com/tobymao/sqlglot/pull/5211) by [@georgesittas](https://github.com/georgesittas))*:
|
34
|
+
|
35
|
+
support multi-part (>3) dotted functions (#5211)
|
36
|
+
|
37
|
+
- due to [`02afa2a`](https://github.com/tobymao/sqlglot/commit/02afa2a1941fc67086d50dffac2857262f1c3c4f) - Preserve quoting for UDT *(PR [#5216](https://github.com/tobymao/sqlglot/pull/5216) by [@VaggelisD](https://github.com/VaggelisD))*:
|
38
|
+
|
39
|
+
Preserve quoting for UDT (#5216)
|
40
|
+
|
41
|
+
|
42
|
+
### :sparkles: New Features
|
43
|
+
- [`c20f85e`](https://github.com/tobymao/sqlglot/commit/c20f85e3e171e502fc51f74894d3313f0ad61535) - **spark**: support ALTER ADD PARTITION *(PR [#5208](https://github.com/tobymao/sqlglot/pull/5208) by [@georgesittas](https://github.com/georgesittas))*
|
44
|
+
- :arrow_lower_right: *addresses issue [#5204](https://github.com/tobymao/sqlglot/issues/5204) opened by [@cosinequanon](https://github.com/cosinequanon)*
|
45
|
+
|
46
|
+
### :bug: Bug Fixes
|
47
|
+
- [`99bbae3`](https://github.com/tobymao/sqlglot/commit/99bbae370329c5f5cd132b711c714359cf96ba58) - **sqlite**: allow ALTER RENAME without COLUMN keyword fixes [#5195](https://github.com/tobymao/sqlglot/pull/5195) *(commit by [@georgesittas](https://github.com/georgesittas))*
|
48
|
+
- [`ac6555b`](https://github.com/tobymao/sqlglot/commit/ac6555b4d6c162ef7b14b63307d01fd560138ea0) - **hive**: preserve DIV binary operator, fixes [#5198](https://github.com/tobymao/sqlglot/pull/5198) *(PR [#5199](https://github.com/tobymao/sqlglot/pull/5199) by [@georgesittas](https://github.com/georgesittas))*
|
49
|
+
- [`d0eeb26`](https://github.com/tobymao/sqlglot/commit/d0eeb2639e771e8f8b6feabd41c65f16ed5a9829) - eliminate_join_marks has multiple issues fixes [#5188](https://github.com/tobymao/sqlglot/pull/5188) *(PR [#5189](https://github.com/tobymao/sqlglot/pull/5189) by [@snovik75](https://github.com/snovik75))*
|
50
|
+
- :arrow_lower_right: *fixes issue [#5188](https://github.com/tobymao/sqlglot/issues/5188) opened by [@snovik75](https://github.com/snovik75)*
|
51
|
+
- [`dfdd84b`](https://github.com/tobymao/sqlglot/commit/dfdd84bbc50da70f40a17b39935f8171d961f7d2) - **parser**: CTEs instead of subqueries for pipe syntax *(PR [#5205](https://github.com/tobymao/sqlglot/pull/5205) by [@geooo109](https://github.com/geooo109))*
|
52
|
+
- [`77e9d9a`](https://github.com/tobymao/sqlglot/commit/77e9d9a0269e2013379967cf2f46fbd79c036277) - **mysql**: properly parse STORED/VIRTUAL computed columns *(PR [#5210](https://github.com/tobymao/sqlglot/pull/5210) by [@georgesittas](https://github.com/georgesittas))*
|
53
|
+
- :arrow_lower_right: *fixes issue [#5203](https://github.com/tobymao/sqlglot/issues/5203) opened by [@mdebski](https://github.com/mdebski)*
|
54
|
+
- [`5f95299`](https://github.com/tobymao/sqlglot/commit/5f9529940d83e89704f7d25eda63cd73fdb503ae) - **parser**: support multi-part (>3) dotted functions *(PR [#5211](https://github.com/tobymao/sqlglot/pull/5211) by [@georgesittas](https://github.com/georgesittas))*
|
55
|
+
- :arrow_lower_right: *fixes issue [#5200](https://github.com/tobymao/sqlglot/issues/5200) opened by [@mateuszpoleski](https://github.com/mateuszpoleski)*
|
56
|
+
- [`02afa2a`](https://github.com/tobymao/sqlglot/commit/02afa2a1941fc67086d50dffac2857262f1c3c4f) - **postgres**: Preserve quoting for UDT *(PR [#5216](https://github.com/tobymao/sqlglot/pull/5216) by [@VaggelisD](https://github.com/VaggelisD))*
|
57
|
+
- :arrow_lower_right: *fixes issue [#5212](https://github.com/tobymao/sqlglot/issues/5212) opened by [@NickCrews](https://github.com/NickCrews)*
|
58
|
+
- [`f37c0b1`](https://github.com/tobymao/sqlglot/commit/f37c0b1197321dd610648ce652a171ab063deeeb) - **snowflake**: ensure a standalone GET() expression can be parsed *(PR [#5219](https://github.com/tobymao/sqlglot/pull/5219) by [@georgesittas](https://github.com/georgesittas))*
|
59
|
+
|
60
|
+
### :wrench: Chores
|
61
|
+
- [`ad8a4e7`](https://github.com/tobymao/sqlglot/commit/ad8a4e73e1a9e4234f0b711163fb49630acf736c) - refactor join mark elimination to use is_correlated_subquery *(commit by [@georgesittas](https://github.com/georgesittas))*
|
62
|
+
|
63
|
+
|
4
64
|
## [v26.26.0] - 2025-06-09
|
5
65
|
### :boom: BREAKING CHANGES
|
6
66
|
- due to [`434c45b`](https://github.com/tobymao/sqlglot/commit/434c45b547c3a5ea155dc8d7da2baab326eb6d4f) - improve support for ENDSWITH closes [#5170](https://github.com/tobymao/sqlglot/pull/5170) *(commit by [@georgesittas](https://github.com/georgesittas))*:
|
@@ -4840,3 +4900,5 @@ Changelog
|
|
4840
4900
|
[v26.25.2]: https://github.com/tobymao/sqlglot/compare/v26.25.1...v26.25.2
|
4841
4901
|
[v26.25.3]: https://github.com/tobymao/sqlglot/compare/v26.25.2...v26.25.3
|
4842
4902
|
[v26.26.0]: https://github.com/tobymao/sqlglot/compare/v26.25.3...v26.26.0
|
4903
|
+
[v26.27.0]: https://github.com/tobymao/sqlglot/compare/v26.26.0...v26.27.0
|
4904
|
+
[v26.28.1]: https://github.com/tobymao/sqlglot/compare/v26.27.1...v26.28.1
|
@@ -1621,7 +1621,10 @@ def map_date_part(part, dialect: DialectType = Dialect):
|
|
1621
1621
|
mapped = (
|
1622
1622
|
Dialect.get_or_raise(dialect).DATE_PART_MAPPING.get(part.name.upper()) if part else None
|
1623
1623
|
)
|
1624
|
-
|
1624
|
+
if mapped:
|
1625
|
+
return exp.Literal.string(mapped) if part.is_string else exp.var(mapped)
|
1626
|
+
|
1627
|
+
return part
|
1625
1628
|
|
1626
1629
|
|
1627
1630
|
def no_last_day_sql(self: Generator, expression: exp.LastDay) -> str:
|
@@ -290,6 +290,12 @@ class DuckDB(Dialect):
|
|
290
290
|
# https://duckdb.org/docs/sql/introduction.html#creating-a-new-table
|
291
291
|
NORMALIZATION_STRATEGY = NormalizationStrategy.CASE_INSENSITIVE
|
292
292
|
|
293
|
+
DATE_PART_MAPPING = {
|
294
|
+
**Dialect.DATE_PART_MAPPING,
|
295
|
+
"DAYOFWEEKISO": "ISODOW",
|
296
|
+
}
|
297
|
+
DATE_PART_MAPPING.pop("WEEKDAY")
|
298
|
+
|
293
299
|
def to_json_path(self, path: t.Optional[exp.Expression]) -> t.Optional[exp.Expression]:
|
294
300
|
if isinstance(path, exp.Literal):
|
295
301
|
# DuckDB also supports the JSON pointer syntax, where every path starts with a `/`.
|
@@ -620,6 +626,7 @@ class DuckDB(Dialect):
|
|
620
626
|
PAD_FILL_PATTERN_IS_REQUIRED = True
|
621
627
|
ARRAY_CONCAT_IS_VAR_LEN = False
|
622
628
|
ARRAY_SIZE_DIM_REQUIRED = False
|
629
|
+
NORMALIZE_EXTRACT_DATE_PARTS = True
|
623
630
|
|
624
631
|
TRANSFORMS = {
|
625
632
|
**generator.Generator.TRANSFORMS,
|
@@ -31,6 +31,7 @@ from sqlglot.dialects.dialect import (
|
|
31
31
|
)
|
32
32
|
from sqlglot.generator import unsupported_args
|
33
33
|
from sqlglot.helper import flatten, is_float, is_int, seq_get
|
34
|
+
from sqlglot.optimizer.scope import find_all_in_scope
|
34
35
|
from sqlglot.tokens import TokenType
|
35
36
|
|
36
37
|
if t.TYPE_CHECKING:
|
@@ -333,6 +334,34 @@ def _json_extract_value_array_sql(
|
|
333
334
|
return self.func("TRANSFORM", json_extract, transform_lambda)
|
334
335
|
|
335
336
|
|
337
|
+
def _eliminate_dot_variant_lookup(expression: exp.Expression) -> exp.Expression:
|
338
|
+
if isinstance(expression, exp.Select):
|
339
|
+
# This transformation is used to facilitate transpilation of BigQuery `UNNEST` operations
|
340
|
+
# to Snowflake. It should not affect roundtrip because `Unnest` nodes cannot be produced
|
341
|
+
# by Snowflake's parser.
|
342
|
+
#
|
343
|
+
# Additionally, at the time of writing this, BigQuery is the only dialect that produces a
|
344
|
+
# `TableAlias` node that only fills `columns` and not `this`, due to `UNNEST_COLUMN_ONLY`.
|
345
|
+
unnest_aliases = set()
|
346
|
+
for unnest in find_all_in_scope(expression, exp.Unnest):
|
347
|
+
unnest_alias = unnest.args.get("alias")
|
348
|
+
if (
|
349
|
+
isinstance(unnest_alias, exp.TableAlias)
|
350
|
+
and not unnest_alias.this
|
351
|
+
and len(unnest_alias.columns) == 1
|
352
|
+
):
|
353
|
+
unnest_aliases.add(unnest_alias.columns[0].name)
|
354
|
+
|
355
|
+
if unnest_aliases:
|
356
|
+
for c in find_all_in_scope(expression, exp.Column):
|
357
|
+
if c.table in unnest_aliases:
|
358
|
+
bracket_lhs = c.args["table"]
|
359
|
+
bracket_rhs = exp.Literal.string(c.name)
|
360
|
+
c.replace(exp.Bracket(this=bracket_lhs, expressions=[bracket_rhs]))
|
361
|
+
|
362
|
+
return expression
|
363
|
+
|
364
|
+
|
336
365
|
class Snowflake(Dialect):
|
337
366
|
# https://docs.snowflake.com/en/sql-reference/identifiers-syntax
|
338
367
|
NORMALIZATION_STRATEGY = NormalizationStrategy.UPPERCASE
|
@@ -1096,6 +1125,7 @@ class Snowflake(Dialect):
|
|
1096
1125
|
transforms.explode_projection_to_unnest(),
|
1097
1126
|
transforms.eliminate_semi_and_anti_joins,
|
1098
1127
|
_transform_generate_date_array,
|
1128
|
+
_eliminate_dot_variant_lookup,
|
1099
1129
|
]
|
1100
1130
|
),
|
1101
1131
|
exp.SHA: rename_func("SHA1"),
|
@@ -1314,7 +1344,14 @@ class Snowflake(Dialect):
|
|
1314
1344
|
start = f" START {start}" if start else ""
|
1315
1345
|
increment = expression.args.get("increment")
|
1316
1346
|
increment = f" INCREMENT {increment}" if increment else ""
|
1317
|
-
|
1347
|
+
|
1348
|
+
order = expression.args.get("order")
|
1349
|
+
if order is not None:
|
1350
|
+
order_clause = " ORDER" if order else " NOORDER"
|
1351
|
+
else:
|
1352
|
+
order_clause = ""
|
1353
|
+
|
1354
|
+
return f"AUTOINCREMENT{start}{increment}{order_clause}"
|
1318
1355
|
|
1319
1356
|
def cluster_sql(self, expression: exp.Cluster) -> str:
|
1320
1357
|
return f"CLUSTER BY ({self.expressions(expression, flat=True)})"
|
@@ -1224,8 +1224,6 @@ class TSQL(Dialect):
|
|
1224
1224
|
# to amend the AST by moving the CTEs to the CREATE VIEW statement's query.
|
1225
1225
|
ctas_expression.set("with", with_.pop())
|
1226
1226
|
|
1227
|
-
sql = super().create_sql(expression)
|
1228
|
-
|
1229
1227
|
table = expression.find(exp.Table)
|
1230
1228
|
|
1231
1229
|
# Convert CTAS statement to SELECT .. INTO ..
|
@@ -1243,6 +1241,8 @@ class TSQL(Dialect):
|
|
1243
1241
|
select_into.limit(0, copy=False)
|
1244
1242
|
|
1245
1243
|
sql = self.sql(select_into)
|
1244
|
+
else:
|
1245
|
+
sql = super().create_sql(expression)
|
1246
1246
|
|
1247
1247
|
if exists:
|
1248
1248
|
identifier = self.sql(exp.Literal.string(exp.table_name(table) if table else ""))
|
@@ -51,8 +51,8 @@ class _Expression(type):
|
|
51
51
|
def __new__(cls, clsname, bases, attrs):
|
52
52
|
klass = super().__new__(cls, clsname, bases, attrs)
|
53
53
|
|
54
|
-
# When an Expression class is created, its key is automatically set
|
55
|
-
# the lowercase version of the class' name.
|
54
|
+
# When an Expression class is created, its key is automatically set
|
55
|
+
# to be the lowercase version of the class' name.
|
56
56
|
klass.key = clsname.lower()
|
57
57
|
|
58
58
|
# This is so that docstrings are not inherited in pdoc
|
@@ -1947,6 +1947,7 @@ class GeneratedAsIdentityColumnConstraint(ColumnConstraintKind):
|
|
1947
1947
|
"minvalue": False,
|
1948
1948
|
"maxvalue": False,
|
1949
1949
|
"cycle": False,
|
1950
|
+
"order": False,
|
1950
1951
|
}
|
1951
1952
|
|
1952
1953
|
|
@@ -7044,6 +7045,12 @@ class Semicolon(Expression):
|
|
7044
7045
|
arg_types = {}
|
7045
7046
|
|
7046
7047
|
|
7048
|
+
# BigQuery allows SELECT t FROM t and treats the projection as a struct value. This expression
|
7049
|
+
# type is intended to be constructed by qualify so that we can properly annotate its type later
|
7050
|
+
class TableColumn(Expression):
|
7051
|
+
pass
|
7052
|
+
|
7053
|
+
|
7047
7054
|
def _norm_arg(arg):
|
7048
7055
|
return arg.lower() if type(arg) is str else arg
|
7049
7056
|
|
@@ -201,6 +201,7 @@ class Generator(metaclass=_Generator):
|
|
201
201
|
exp.StreamingTableProperty: lambda *_: "STREAMING",
|
202
202
|
exp.StrictProperty: lambda *_: "STRICT",
|
203
203
|
exp.SwapTable: lambda self, e: f"SWAP WITH {self.sql(e, 'this')}",
|
204
|
+
exp.TableColumn: lambda self, e: self.sql(e.this),
|
204
205
|
exp.Tags: lambda self, e: f"TAG ({self.expressions(e, flat=True)})",
|
205
206
|
exp.TemporaryProperty: lambda *_: "TEMPORARY",
|
206
207
|
exp.TitleColumnConstraint: lambda self, e: f"TITLE {self.sql(e, 'this')}",
|
@@ -463,6 +464,11 @@ class Generator(metaclass=_Generator):
|
|
463
464
|
# Whether to wrap <props> in `AlterSet`, e.g., ALTER ... SET (<props>)
|
464
465
|
ALTER_SET_WRAPPED = False
|
465
466
|
|
467
|
+
# Whether to normalize the date parts in EXTRACT(<date_part> FROM <expr>) into a common representation
|
468
|
+
# For instance, to extract the day of week in ISO semantics, one can use ISODOW, DAYOFWEEKISO etc depending on the dialect.
|
469
|
+
# TODO: The normalization should be done by default once we've tested it across all dialects.
|
470
|
+
NORMALIZE_EXTRACT_DATE_PARTS = False
|
471
|
+
|
466
472
|
# The name to generate for the JSONPath expression. If `None`, only `this` will be generated
|
467
473
|
PARSE_JSON_NAME: t.Optional[str] = "PARSE_JSON"
|
468
474
|
|
@@ -2909,9 +2915,17 @@ class Generator(metaclass=_Generator):
|
|
2909
2915
|
return f"NEXT VALUE FOR {self.sql(expression, 'this')}{order}"
|
2910
2916
|
|
2911
2917
|
def extract_sql(self, expression: exp.Extract) -> str:
|
2912
|
-
|
2918
|
+
from sqlglot.dialects.dialect import map_date_part
|
2919
|
+
|
2920
|
+
this = (
|
2921
|
+
map_date_part(expression.this, self.dialect)
|
2922
|
+
if self.NORMALIZE_EXTRACT_DATE_PARTS
|
2923
|
+
else expression.this
|
2924
|
+
)
|
2925
|
+
this_sql = self.sql(this) if self.EXTRACT_ALLOWS_QUOTES else this.name
|
2913
2926
|
expression_sql = self.sql(expression, "expression")
|
2914
|
-
|
2927
|
+
|
2928
|
+
return f"EXTRACT({this_sql} FROM {expression_sql})"
|
2915
2929
|
|
2916
2930
|
def trim_sql(self, expression: exp.Trim) -> str:
|
2917
2931
|
trim_type = self.sql(expression, "position")
|
@@ -4766,7 +4780,10 @@ class Generator(metaclass=_Generator):
|
|
4766
4780
|
|
4767
4781
|
def detach_sql(self, expression: exp.Detach) -> str:
|
4768
4782
|
this = self.sql(expression, "this")
|
4769
|
-
|
4783
|
+
# the DATABASE keyword is required if IF EXISTS is set
|
4784
|
+
# without it, DuckDB throws an error: Parser Error: syntax error at or near "exists" (Line Number: 1)
|
4785
|
+
# ref: https://duckdb.org/docs/stable/sql/statements/attach.html#detach-syntax
|
4786
|
+
exists_sql = " DATABASE IF EXISTS" if expression.args.get("exists") else ""
|
4770
4787
|
|
4771
4788
|
return f"DETACH{exists_sql} {this}"
|
4772
4789
|
|
@@ -12,7 +12,7 @@ from sqlglot.helper import (
|
|
12
12
|
seq_get,
|
13
13
|
)
|
14
14
|
from sqlglot.optimizer.scope import Scope, traverse_scope
|
15
|
-
from sqlglot.schema import Schema, ensure_schema
|
15
|
+
from sqlglot.schema import MappingSchema, Schema, ensure_schema
|
16
16
|
from sqlglot.dialects.dialect import Dialect
|
17
17
|
|
18
18
|
if t.TYPE_CHECKING:
|
@@ -290,9 +290,52 @@ class TypeAnnotator(metaclass=_TypeAnnotator):
|
|
290
290
|
elif isinstance(source.expression, exp.Unnest):
|
291
291
|
self._set_type(col, source.expression.type)
|
292
292
|
|
293
|
+
if isinstance(self.schema, MappingSchema):
|
294
|
+
for table_column in scope.table_columns:
|
295
|
+
source = scope.sources.get(table_column.name)
|
296
|
+
|
297
|
+
if isinstance(source, exp.Table):
|
298
|
+
schema = self.schema.find(
|
299
|
+
source, raise_on_missing=False, ensure_data_types=True
|
300
|
+
)
|
301
|
+
if not isinstance(schema, dict):
|
302
|
+
continue
|
303
|
+
|
304
|
+
struct_type = exp.DataType(
|
305
|
+
this=exp.DataType.Type.STRUCT,
|
306
|
+
expressions=[
|
307
|
+
exp.ColumnDef(this=exp.to_identifier(c), kind=kind)
|
308
|
+
for c, kind in schema.items()
|
309
|
+
],
|
310
|
+
nested=True,
|
311
|
+
)
|
312
|
+
self._set_type(table_column, struct_type)
|
313
|
+
elif (
|
314
|
+
isinstance(source, Scope)
|
315
|
+
and isinstance(source.expression, exp.Query)
|
316
|
+
and source.expression.is_type(exp.DataType.Type.STRUCT)
|
317
|
+
):
|
318
|
+
self._set_type(table_column, source.expression.type)
|
319
|
+
|
293
320
|
# Then (possibly) annotate the remaining expressions in the scope
|
294
321
|
self._maybe_annotate(scope.expression)
|
295
322
|
|
323
|
+
if self.schema.dialect == "bigquery" and isinstance(scope.expression, exp.Query):
|
324
|
+
struct_type = exp.DataType(
|
325
|
+
this=exp.DataType.Type.STRUCT,
|
326
|
+
expressions=[
|
327
|
+
exp.ColumnDef(this=exp.to_identifier(select.output_name), kind=select.type)
|
328
|
+
for select in scope.expression.selects
|
329
|
+
],
|
330
|
+
nested=True,
|
331
|
+
)
|
332
|
+
if not any(
|
333
|
+
cd.kind.is_type(exp.DataType.Type.UNKNOWN)
|
334
|
+
for cd in struct_type.expressions
|
335
|
+
if cd.kind
|
336
|
+
):
|
337
|
+
self._set_type(scope.expression, struct_type)
|
338
|
+
|
296
339
|
def _maybe_annotate(self, expression: E) -> E:
|
297
340
|
if id(expression) in self._visited:
|
298
341
|
return expression # We've already inferred the expression's type
|
@@ -529,6 +529,13 @@ def _qualify_columns(scope: Scope, resolver: Resolver, allow_partial_qualificati
|
|
529
529
|
column_table = resolver.get_table(column_name)
|
530
530
|
if column_table:
|
531
531
|
column.set("table", column_table)
|
532
|
+
elif (
|
533
|
+
resolver.schema.dialect == "bigquery"
|
534
|
+
and len(column.parts) == 1
|
535
|
+
and column_name in scope.selected_sources
|
536
|
+
):
|
537
|
+
# BigQuery allows tables to be referenced as columns, treating them as structs
|
538
|
+
scope.replace(column, exp.TableColumn(this=column.this))
|
532
539
|
|
533
540
|
for pivot in scope.pivots:
|
534
541
|
for column in pivot.find_all(exp.Column):
|
@@ -88,6 +88,7 @@ class Scope:
|
|
88
88
|
def clear_cache(self):
|
89
89
|
self._collected = False
|
90
90
|
self._raw_columns = None
|
91
|
+
self._table_columns = None
|
91
92
|
self._stars = None
|
92
93
|
self._derived_tables = None
|
93
94
|
self._udtfs = None
|
@@ -125,6 +126,7 @@ class Scope:
|
|
125
126
|
self._derived_tables = []
|
126
127
|
self._udtfs = []
|
127
128
|
self._raw_columns = []
|
129
|
+
self._table_columns = []
|
128
130
|
self._stars = []
|
129
131
|
self._join_hints = []
|
130
132
|
self._semi_anti_join_tables = set()
|
@@ -156,6 +158,8 @@ class Scope:
|
|
156
158
|
self._derived_tables.append(node)
|
157
159
|
elif isinstance(node, exp.UNWRAPPED_QUERIES):
|
158
160
|
self._subqueries.append(node)
|
161
|
+
elif isinstance(node, exp.TableColumn):
|
162
|
+
self._table_columns.append(node)
|
159
163
|
|
160
164
|
self._collected = True
|
161
165
|
|
@@ -309,6 +313,13 @@ class Scope:
|
|
309
313
|
|
310
314
|
return self._columns
|
311
315
|
|
316
|
+
@property
|
317
|
+
def table_columns(self):
|
318
|
+
if self._table_columns is None:
|
319
|
+
self._ensure_collected()
|
320
|
+
|
321
|
+
return self._table_columns
|
322
|
+
|
312
323
|
@property
|
313
324
|
def selected_sources(self):
|
314
325
|
"""
|
@@ -758,6 +769,8 @@ def _traverse_tables(scope):
|
|
758
769
|
expressions.extend(join.this for join in expression.args.get("joins") or [])
|
759
770
|
continue
|
760
771
|
|
772
|
+
child_scope = None
|
773
|
+
|
761
774
|
for child_scope in _traverse_scope(
|
762
775
|
scope.branch(
|
763
776
|
expression,
|
@@ -775,8 +788,9 @@ def _traverse_tables(scope):
|
|
775
788
|
sources[expression.alias] = child_scope
|
776
789
|
|
777
790
|
# append the final child_scope yielded
|
778
|
-
|
779
|
-
|
791
|
+
if child_scope:
|
792
|
+
scopes.append(child_scope)
|
793
|
+
scope.table_scopes.append(child_scope)
|
780
794
|
|
781
795
|
scope.sources.update(sources)
|
782
796
|
|
@@ -846,12 +860,14 @@ def walk_in_scope(expression, bfs=True, prune=None):
|
|
846
860
|
|
847
861
|
if node is expression:
|
848
862
|
continue
|
863
|
+
|
849
864
|
if (
|
850
865
|
isinstance(node, exp.CTE)
|
851
866
|
or (
|
852
867
|
isinstance(node.parent, (exp.From, exp.Join, exp.Subquery))
|
853
|
-
and
|
868
|
+
and _is_derived_table(node)
|
854
869
|
)
|
870
|
+
or (isinstance(node.parent, exp.UDTF) and isinstance(node, exp.Query))
|
855
871
|
or isinstance(node, exp.UNWRAPPED_QUERIES)
|
856
872
|
):
|
857
873
|
crossed_scope_boundary = True
|