sqlglot 27.5.1__tar.gz → 27.6.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-27.5.1 → sqlglot-27.6.0}/CHANGELOG.md +6 -0
- {sqlglot-27.5.1 → sqlglot-27.6.0}/PKG-INFO +1 -1
- {sqlglot-27.5.1 → sqlglot-27.6.0}/sqlglot/_version.py +2 -2
- {sqlglot-27.5.1 → sqlglot-27.6.0}/sqlglot/dialects/bigquery.py +3 -1
- {sqlglot-27.5.1 → sqlglot-27.6.0}/sqlglot/dialects/exasol.py +60 -2
- {sqlglot-27.5.1 → sqlglot-27.6.0}/sqlglot/dialects/singlestore.py +22 -0
- {sqlglot-27.5.1 → sqlglot-27.6.0}/sqlglot/dialects/snowflake.py +2 -0
- {sqlglot-27.5.1 → sqlglot-27.6.0}/sqlglot/expressions.py +5 -0
- {sqlglot-27.5.1 → sqlglot-27.6.0}/sqlglot/generator.py +14 -0
- {sqlglot-27.5.1 → sqlglot-27.6.0}/sqlglot/optimizer/qualify_columns.py +40 -25
- {sqlglot-27.5.1 → sqlglot-27.6.0}/sqlglot/parser.py +6 -1
- {sqlglot-27.5.1 → sqlglot-27.6.0}/sqlglot.egg-info/PKG-INFO +1 -1
- {sqlglot-27.5.1 → sqlglot-27.6.0}/tests/dialects/test_exasol.py +57 -1
- {sqlglot-27.5.1 → sqlglot-27.6.0}/tests/dialects/test_singlestore.py +26 -2
- {sqlglot-27.5.1 → sqlglot-27.6.0}/tests/dialects/test_snowflake.py +28 -1
- {sqlglot-27.5.1 → sqlglot-27.6.0}/tests/fixtures/optimizer/qualify_columns.sql +19 -0
- {sqlglot-27.5.1 → sqlglot-27.6.0}/.gitignore +0 -0
- {sqlglot-27.5.1 → sqlglot-27.6.0}/.gitpod.yml +0 -0
- {sqlglot-27.5.1 → sqlglot-27.6.0}/.pre-commit-config.yaml +0 -0
- {sqlglot-27.5.1 → sqlglot-27.6.0}/CONTRIBUTING.md +0 -0
- {sqlglot-27.5.1 → sqlglot-27.6.0}/LICENSE +0 -0
- {sqlglot-27.5.1 → sqlglot-27.6.0}/MANIFEST.in +0 -0
- {sqlglot-27.5.1 → sqlglot-27.6.0}/Makefile +0 -0
- {sqlglot-27.5.1 → sqlglot-27.6.0}/README.md +0 -0
- {sqlglot-27.5.1 → sqlglot-27.6.0}/pyproject.toml +0 -0
- {sqlglot-27.5.1 → sqlglot-27.6.0}/setup.cfg +0 -0
- {sqlglot-27.5.1 → sqlglot-27.6.0}/setup.py +0 -0
- {sqlglot-27.5.1 → sqlglot-27.6.0}/sqlglot/__init__.py +0 -0
- {sqlglot-27.5.1 → sqlglot-27.6.0}/sqlglot/__main__.py +0 -0
- {sqlglot-27.5.1 → sqlglot-27.6.0}/sqlglot/_typing.py +0 -0
- {sqlglot-27.5.1 → sqlglot-27.6.0}/sqlglot/dialects/__init__.py +0 -0
- {sqlglot-27.5.1 → sqlglot-27.6.0}/sqlglot/dialects/athena.py +0 -0
- {sqlglot-27.5.1 → sqlglot-27.6.0}/sqlglot/dialects/clickhouse.py +0 -0
- {sqlglot-27.5.1 → sqlglot-27.6.0}/sqlglot/dialects/databricks.py +0 -0
- {sqlglot-27.5.1 → sqlglot-27.6.0}/sqlglot/dialects/dialect.py +0 -0
- {sqlglot-27.5.1 → sqlglot-27.6.0}/sqlglot/dialects/doris.py +0 -0
- {sqlglot-27.5.1 → sqlglot-27.6.0}/sqlglot/dialects/dremio.py +0 -0
- {sqlglot-27.5.1 → sqlglot-27.6.0}/sqlglot/dialects/drill.py +0 -0
- {sqlglot-27.5.1 → sqlglot-27.6.0}/sqlglot/dialects/druid.py +0 -0
- {sqlglot-27.5.1 → sqlglot-27.6.0}/sqlglot/dialects/duckdb.py +0 -0
- {sqlglot-27.5.1 → sqlglot-27.6.0}/sqlglot/dialects/dune.py +0 -0
- {sqlglot-27.5.1 → sqlglot-27.6.0}/sqlglot/dialects/fabric.py +0 -0
- {sqlglot-27.5.1 → sqlglot-27.6.0}/sqlglot/dialects/hive.py +0 -0
- {sqlglot-27.5.1 → sqlglot-27.6.0}/sqlglot/dialects/materialize.py +0 -0
- {sqlglot-27.5.1 → sqlglot-27.6.0}/sqlglot/dialects/mysql.py +0 -0
- {sqlglot-27.5.1 → sqlglot-27.6.0}/sqlglot/dialects/oracle.py +0 -0
- {sqlglot-27.5.1 → sqlglot-27.6.0}/sqlglot/dialects/postgres.py +0 -0
- {sqlglot-27.5.1 → sqlglot-27.6.0}/sqlglot/dialects/presto.py +0 -0
- {sqlglot-27.5.1 → sqlglot-27.6.0}/sqlglot/dialects/prql.py +0 -0
- {sqlglot-27.5.1 → sqlglot-27.6.0}/sqlglot/dialects/redshift.py +0 -0
- {sqlglot-27.5.1 → sqlglot-27.6.0}/sqlglot/dialects/risingwave.py +0 -0
- {sqlglot-27.5.1 → sqlglot-27.6.0}/sqlglot/dialects/spark.py +0 -0
- {sqlglot-27.5.1 → sqlglot-27.6.0}/sqlglot/dialects/spark2.py +0 -0
- {sqlglot-27.5.1 → sqlglot-27.6.0}/sqlglot/dialects/sqlite.py +0 -0
- {sqlglot-27.5.1 → sqlglot-27.6.0}/sqlglot/dialects/starrocks.py +0 -0
- {sqlglot-27.5.1 → sqlglot-27.6.0}/sqlglot/dialects/tableau.py +0 -0
- {sqlglot-27.5.1 → sqlglot-27.6.0}/sqlglot/dialects/teradata.py +0 -0
- {sqlglot-27.5.1 → sqlglot-27.6.0}/sqlglot/dialects/trino.py +0 -0
- {sqlglot-27.5.1 → sqlglot-27.6.0}/sqlglot/dialects/tsql.py +0 -0
- {sqlglot-27.5.1 → sqlglot-27.6.0}/sqlglot/diff.py +0 -0
- {sqlglot-27.5.1 → sqlglot-27.6.0}/sqlglot/errors.py +0 -0
- {sqlglot-27.5.1 → sqlglot-27.6.0}/sqlglot/executor/__init__.py +0 -0
- {sqlglot-27.5.1 → sqlglot-27.6.0}/sqlglot/executor/context.py +0 -0
- {sqlglot-27.5.1 → sqlglot-27.6.0}/sqlglot/executor/env.py +0 -0
- {sqlglot-27.5.1 → sqlglot-27.6.0}/sqlglot/executor/python.py +0 -0
- {sqlglot-27.5.1 → sqlglot-27.6.0}/sqlglot/executor/table.py +0 -0
- {sqlglot-27.5.1 → sqlglot-27.6.0}/sqlglot/helper.py +0 -0
- {sqlglot-27.5.1 → sqlglot-27.6.0}/sqlglot/jsonpath.py +0 -0
- {sqlglot-27.5.1 → sqlglot-27.6.0}/sqlglot/lineage.py +0 -0
- {sqlglot-27.5.1 → sqlglot-27.6.0}/sqlglot/optimizer/__init__.py +0 -0
- {sqlglot-27.5.1 → sqlglot-27.6.0}/sqlglot/optimizer/annotate_types.py +0 -0
- {sqlglot-27.5.1 → sqlglot-27.6.0}/sqlglot/optimizer/canonicalize.py +0 -0
- {sqlglot-27.5.1 → sqlglot-27.6.0}/sqlglot/optimizer/eliminate_ctes.py +0 -0
- {sqlglot-27.5.1 → sqlglot-27.6.0}/sqlglot/optimizer/eliminate_joins.py +0 -0
- {sqlglot-27.5.1 → sqlglot-27.6.0}/sqlglot/optimizer/eliminate_subqueries.py +0 -0
- {sqlglot-27.5.1 → sqlglot-27.6.0}/sqlglot/optimizer/isolate_table_selects.py +0 -0
- {sqlglot-27.5.1 → sqlglot-27.6.0}/sqlglot/optimizer/merge_subqueries.py +0 -0
- {sqlglot-27.5.1 → sqlglot-27.6.0}/sqlglot/optimizer/normalize.py +0 -0
- {sqlglot-27.5.1 → sqlglot-27.6.0}/sqlglot/optimizer/normalize_identifiers.py +0 -0
- {sqlglot-27.5.1 → sqlglot-27.6.0}/sqlglot/optimizer/optimize_joins.py +0 -0
- {sqlglot-27.5.1 → sqlglot-27.6.0}/sqlglot/optimizer/optimizer.py +0 -0
- {sqlglot-27.5.1 → sqlglot-27.6.0}/sqlglot/optimizer/pushdown_predicates.py +0 -0
- {sqlglot-27.5.1 → sqlglot-27.6.0}/sqlglot/optimizer/pushdown_projections.py +0 -0
- {sqlglot-27.5.1 → sqlglot-27.6.0}/sqlglot/optimizer/qualify.py +0 -0
- {sqlglot-27.5.1 → sqlglot-27.6.0}/sqlglot/optimizer/qualify_tables.py +0 -0
- {sqlglot-27.5.1 → sqlglot-27.6.0}/sqlglot/optimizer/scope.py +0 -0
- {sqlglot-27.5.1 → sqlglot-27.6.0}/sqlglot/optimizer/simplify.py +0 -0
- {sqlglot-27.5.1 → sqlglot-27.6.0}/sqlglot/optimizer/unnest_subqueries.py +0 -0
- {sqlglot-27.5.1 → sqlglot-27.6.0}/sqlglot/planner.py +0 -0
- {sqlglot-27.5.1 → sqlglot-27.6.0}/sqlglot/py.typed +0 -0
- {sqlglot-27.5.1 → sqlglot-27.6.0}/sqlglot/schema.py +0 -0
- {sqlglot-27.5.1 → sqlglot-27.6.0}/sqlglot/serde.py +0 -0
- {sqlglot-27.5.1 → sqlglot-27.6.0}/sqlglot/time.py +0 -0
- {sqlglot-27.5.1 → sqlglot-27.6.0}/sqlglot/tokens.py +0 -0
- {sqlglot-27.5.1 → sqlglot-27.6.0}/sqlglot/transforms.py +0 -0
- {sqlglot-27.5.1 → sqlglot-27.6.0}/sqlglot/trie.py +0 -0
- {sqlglot-27.5.1 → sqlglot-27.6.0}/sqlglot.egg-info/SOURCES.txt +0 -0
- {sqlglot-27.5.1 → sqlglot-27.6.0}/sqlglot.egg-info/dependency_links.txt +0 -0
- {sqlglot-27.5.1 → sqlglot-27.6.0}/sqlglot.egg-info/requires.txt +0 -0
- {sqlglot-27.5.1 → sqlglot-27.6.0}/sqlglot.egg-info/top_level.txt +0 -0
- {sqlglot-27.5.1 → sqlglot-27.6.0}/sqlglot.png +0 -0
- {sqlglot-27.5.1 → sqlglot-27.6.0}/sqlglotrs/Cargo.lock +0 -0
- {sqlglot-27.5.1 → sqlglot-27.6.0}/sqlglotrs/Cargo.toml +0 -0
- {sqlglot-27.5.1 → sqlglot-27.6.0}/sqlglotrs/benches/dialect_settings.json +0 -0
- {sqlglot-27.5.1 → sqlglot-27.6.0}/sqlglotrs/benches/long.rs +0 -0
- {sqlglot-27.5.1 → sqlglot-27.6.0}/sqlglotrs/benches/token_type_settings.json +0 -0
- {sqlglot-27.5.1 → sqlglot-27.6.0}/sqlglotrs/benches/tokenizer_dialect_settings.json +0 -0
- {sqlglot-27.5.1 → sqlglot-27.6.0}/sqlglotrs/benches/tokenizer_settings.json +0 -0
- {sqlglot-27.5.1 → sqlglot-27.6.0}/sqlglotrs/pyproject.toml +0 -0
- {sqlglot-27.5.1 → sqlglot-27.6.0}/sqlglotrs/src/lib.rs +0 -0
- {sqlglot-27.5.1 → sqlglot-27.6.0}/sqlglotrs/src/settings.rs +0 -0
- {sqlglot-27.5.1 → sqlglot-27.6.0}/sqlglotrs/src/token.rs +0 -0
- {sqlglot-27.5.1 → sqlglot-27.6.0}/sqlglotrs/src/tokenizer.rs +0 -0
- {sqlglot-27.5.1 → sqlglot-27.6.0}/sqlglotrs/src/trie.rs +0 -0
- {sqlglot-27.5.1 → sqlglot-27.6.0}/tests/__init__.py +0 -0
- {sqlglot-27.5.1 → sqlglot-27.6.0}/tests/dialects/__init__.py +0 -0
- {sqlglot-27.5.1 → sqlglot-27.6.0}/tests/dialects/test_athena.py +0 -0
- {sqlglot-27.5.1 → sqlglot-27.6.0}/tests/dialects/test_bigquery.py +0 -0
- {sqlglot-27.5.1 → sqlglot-27.6.0}/tests/dialects/test_clickhouse.py +0 -0
- {sqlglot-27.5.1 → sqlglot-27.6.0}/tests/dialects/test_databricks.py +0 -0
- {sqlglot-27.5.1 → sqlglot-27.6.0}/tests/dialects/test_dialect.py +0 -0
- {sqlglot-27.5.1 → sqlglot-27.6.0}/tests/dialects/test_doris.py +0 -0
- {sqlglot-27.5.1 → sqlglot-27.6.0}/tests/dialects/test_dremio.py +0 -0
- {sqlglot-27.5.1 → sqlglot-27.6.0}/tests/dialects/test_drill.py +0 -0
- {sqlglot-27.5.1 → sqlglot-27.6.0}/tests/dialects/test_druid.py +0 -0
- {sqlglot-27.5.1 → sqlglot-27.6.0}/tests/dialects/test_duckdb.py +0 -0
- {sqlglot-27.5.1 → sqlglot-27.6.0}/tests/dialects/test_dune.py +0 -0
- {sqlglot-27.5.1 → sqlglot-27.6.0}/tests/dialects/test_fabric.py +0 -0
- {sqlglot-27.5.1 → sqlglot-27.6.0}/tests/dialects/test_hive.py +0 -0
- {sqlglot-27.5.1 → sqlglot-27.6.0}/tests/dialects/test_materialize.py +0 -0
- {sqlglot-27.5.1 → sqlglot-27.6.0}/tests/dialects/test_mysql.py +0 -0
- {sqlglot-27.5.1 → sqlglot-27.6.0}/tests/dialects/test_oracle.py +0 -0
- {sqlglot-27.5.1 → sqlglot-27.6.0}/tests/dialects/test_pipe_syntax.py +0 -0
- {sqlglot-27.5.1 → sqlglot-27.6.0}/tests/dialects/test_postgres.py +0 -0
- {sqlglot-27.5.1 → sqlglot-27.6.0}/tests/dialects/test_presto.py +0 -0
- {sqlglot-27.5.1 → sqlglot-27.6.0}/tests/dialects/test_prql.py +0 -0
- {sqlglot-27.5.1 → sqlglot-27.6.0}/tests/dialects/test_redshift.py +0 -0
- {sqlglot-27.5.1 → sqlglot-27.6.0}/tests/dialects/test_risingwave.py +0 -0
- {sqlglot-27.5.1 → sqlglot-27.6.0}/tests/dialects/test_spark.py +0 -0
- {sqlglot-27.5.1 → sqlglot-27.6.0}/tests/dialects/test_sqlite.py +0 -0
- {sqlglot-27.5.1 → sqlglot-27.6.0}/tests/dialects/test_starrocks.py +0 -0
- {sqlglot-27.5.1 → sqlglot-27.6.0}/tests/dialects/test_tableau.py +0 -0
- {sqlglot-27.5.1 → sqlglot-27.6.0}/tests/dialects/test_teradata.py +0 -0
- {sqlglot-27.5.1 → sqlglot-27.6.0}/tests/dialects/test_trino.py +0 -0
- {sqlglot-27.5.1 → sqlglot-27.6.0}/tests/dialects/test_tsql.py +0 -0
- {sqlglot-27.5.1 → sqlglot-27.6.0}/tests/fixtures/identity.sql +0 -0
- {sqlglot-27.5.1 → sqlglot-27.6.0}/tests/fixtures/jsonpath/LICENSE +0 -0
- {sqlglot-27.5.1 → sqlglot-27.6.0}/tests/fixtures/jsonpath/cts.json +0 -0
- {sqlglot-27.5.1 → sqlglot-27.6.0}/tests/fixtures/optimizer/annotate_functions.sql +0 -0
- {sqlglot-27.5.1 → sqlglot-27.6.0}/tests/fixtures/optimizer/annotate_types.sql +0 -0
- {sqlglot-27.5.1 → sqlglot-27.6.0}/tests/fixtures/optimizer/canonicalize.sql +0 -0
- {sqlglot-27.5.1 → sqlglot-27.6.0}/tests/fixtures/optimizer/eliminate_ctes.sql +0 -0
- {sqlglot-27.5.1 → sqlglot-27.6.0}/tests/fixtures/optimizer/eliminate_joins.sql +0 -0
- {sqlglot-27.5.1 → sqlglot-27.6.0}/tests/fixtures/optimizer/eliminate_subqueries.sql +0 -0
- {sqlglot-27.5.1 → sqlglot-27.6.0}/tests/fixtures/optimizer/isolate_table_selects.sql +0 -0
- {sqlglot-27.5.1 → sqlglot-27.6.0}/tests/fixtures/optimizer/merge_subqueries.sql +0 -0
- {sqlglot-27.5.1 → sqlglot-27.6.0}/tests/fixtures/optimizer/normalize.sql +0 -0
- {sqlglot-27.5.1 → sqlglot-27.6.0}/tests/fixtures/optimizer/normalize_identifiers.sql +0 -0
- {sqlglot-27.5.1 → sqlglot-27.6.0}/tests/fixtures/optimizer/optimize_joins.sql +0 -0
- {sqlglot-27.5.1 → sqlglot-27.6.0}/tests/fixtures/optimizer/optimizer.sql +0 -0
- {sqlglot-27.5.1 → sqlglot-27.6.0}/tests/fixtures/optimizer/pushdown_cte_alias_columns.sql +0 -0
- {sqlglot-27.5.1 → sqlglot-27.6.0}/tests/fixtures/optimizer/pushdown_predicates.sql +0 -0
- {sqlglot-27.5.1 → sqlglot-27.6.0}/tests/fixtures/optimizer/pushdown_projections.sql +0 -0
- {sqlglot-27.5.1 → sqlglot-27.6.0}/tests/fixtures/optimizer/qualify_columns__invalid.sql +0 -0
- {sqlglot-27.5.1 → sqlglot-27.6.0}/tests/fixtures/optimizer/qualify_columns__with_invisible.sql +0 -0
- {sqlglot-27.5.1 → sqlglot-27.6.0}/tests/fixtures/optimizer/qualify_columns_ddl.sql +0 -0
- {sqlglot-27.5.1 → sqlglot-27.6.0}/tests/fixtures/optimizer/qualify_tables.sql +0 -0
- {sqlglot-27.5.1 → sqlglot-27.6.0}/tests/fixtures/optimizer/quote_identifiers.sql +0 -0
- {sqlglot-27.5.1 → sqlglot-27.6.0}/tests/fixtures/optimizer/simplify.sql +0 -0
- {sqlglot-27.5.1 → sqlglot-27.6.0}/tests/fixtures/optimizer/tpc-ds/call_center.csv.gz +0 -0
- {sqlglot-27.5.1 → sqlglot-27.6.0}/tests/fixtures/optimizer/tpc-ds/catalog_page.csv.gz +0 -0
- {sqlglot-27.5.1 → sqlglot-27.6.0}/tests/fixtures/optimizer/tpc-ds/catalog_returns.csv.gz +0 -0
- {sqlglot-27.5.1 → sqlglot-27.6.0}/tests/fixtures/optimizer/tpc-ds/catalog_sales.csv.gz +0 -0
- {sqlglot-27.5.1 → sqlglot-27.6.0}/tests/fixtures/optimizer/tpc-ds/customer.csv.gz +0 -0
- {sqlglot-27.5.1 → sqlglot-27.6.0}/tests/fixtures/optimizer/tpc-ds/customer_address.csv.gz +0 -0
- {sqlglot-27.5.1 → sqlglot-27.6.0}/tests/fixtures/optimizer/tpc-ds/customer_demographics.csv.gz +0 -0
- {sqlglot-27.5.1 → sqlglot-27.6.0}/tests/fixtures/optimizer/tpc-ds/date_dim.csv.gz +0 -0
- {sqlglot-27.5.1 → sqlglot-27.6.0}/tests/fixtures/optimizer/tpc-ds/household_demographics.csv.gz +0 -0
- {sqlglot-27.5.1 → sqlglot-27.6.0}/tests/fixtures/optimizer/tpc-ds/income_band.csv.gz +0 -0
- {sqlglot-27.5.1 → sqlglot-27.6.0}/tests/fixtures/optimizer/tpc-ds/inventory.csv.gz +0 -0
- {sqlglot-27.5.1 → sqlglot-27.6.0}/tests/fixtures/optimizer/tpc-ds/item.csv.gz +0 -0
- {sqlglot-27.5.1 → sqlglot-27.6.0}/tests/fixtures/optimizer/tpc-ds/promotion.csv.gz +0 -0
- {sqlglot-27.5.1 → sqlglot-27.6.0}/tests/fixtures/optimizer/tpc-ds/reason.csv.gz +0 -0
- {sqlglot-27.5.1 → sqlglot-27.6.0}/tests/fixtures/optimizer/tpc-ds/ship_mode.csv.gz +0 -0
- {sqlglot-27.5.1 → sqlglot-27.6.0}/tests/fixtures/optimizer/tpc-ds/store.csv.gz +0 -0
- {sqlglot-27.5.1 → sqlglot-27.6.0}/tests/fixtures/optimizer/tpc-ds/store_returns.csv.gz +0 -0
- {sqlglot-27.5.1 → sqlglot-27.6.0}/tests/fixtures/optimizer/tpc-ds/store_sales.csv.gz +0 -0
- {sqlglot-27.5.1 → sqlglot-27.6.0}/tests/fixtures/optimizer/tpc-ds/time_dim.csv.gz +0 -0
- {sqlglot-27.5.1 → sqlglot-27.6.0}/tests/fixtures/optimizer/tpc-ds/tpc-ds.sql +0 -0
- {sqlglot-27.5.1 → sqlglot-27.6.0}/tests/fixtures/optimizer/tpc-ds/warehouse.csv.gz +0 -0
- {sqlglot-27.5.1 → sqlglot-27.6.0}/tests/fixtures/optimizer/tpc-ds/web_page.csv.gz +0 -0
- {sqlglot-27.5.1 → sqlglot-27.6.0}/tests/fixtures/optimizer/tpc-ds/web_returns.csv.gz +0 -0
- {sqlglot-27.5.1 → sqlglot-27.6.0}/tests/fixtures/optimizer/tpc-ds/web_sales.csv.gz +0 -0
- {sqlglot-27.5.1 → sqlglot-27.6.0}/tests/fixtures/optimizer/tpc-ds/web_site.csv.gz +0 -0
- {sqlglot-27.5.1 → sqlglot-27.6.0}/tests/fixtures/optimizer/tpc-h/customer.csv.gz +0 -0
- {sqlglot-27.5.1 → sqlglot-27.6.0}/tests/fixtures/optimizer/tpc-h/lineitem.csv.gz +0 -0
- {sqlglot-27.5.1 → sqlglot-27.6.0}/tests/fixtures/optimizer/tpc-h/nation.csv.gz +0 -0
- {sqlglot-27.5.1 → sqlglot-27.6.0}/tests/fixtures/optimizer/tpc-h/orders.csv.gz +0 -0
- {sqlglot-27.5.1 → sqlglot-27.6.0}/tests/fixtures/optimizer/tpc-h/part.csv.gz +0 -0
- {sqlglot-27.5.1 → sqlglot-27.6.0}/tests/fixtures/optimizer/tpc-h/partsupp.csv.gz +0 -0
- {sqlglot-27.5.1 → sqlglot-27.6.0}/tests/fixtures/optimizer/tpc-h/region.csv.gz +0 -0
- {sqlglot-27.5.1 → sqlglot-27.6.0}/tests/fixtures/optimizer/tpc-h/supplier.csv.gz +0 -0
- {sqlglot-27.5.1 → sqlglot-27.6.0}/tests/fixtures/optimizer/tpc-h/tpc-h.sql +0 -0
- {sqlglot-27.5.1 → sqlglot-27.6.0}/tests/fixtures/optimizer/unnest_subqueries.sql +0 -0
- {sqlglot-27.5.1 → sqlglot-27.6.0}/tests/fixtures/partial.sql +0 -0
- {sqlglot-27.5.1 → sqlglot-27.6.0}/tests/fixtures/pretty.sql +0 -0
- {sqlglot-27.5.1 → sqlglot-27.6.0}/tests/gen_fixtures.py +0 -0
- {sqlglot-27.5.1 → sqlglot-27.6.0}/tests/helpers.py +0 -0
- {sqlglot-27.5.1 → sqlglot-27.6.0}/tests/test_build.py +0 -0
- {sqlglot-27.5.1 → sqlglot-27.6.0}/tests/test_dialect_imports.py +0 -0
- {sqlglot-27.5.1 → sqlglot-27.6.0}/tests/test_diff.py +0 -0
- {sqlglot-27.5.1 → sqlglot-27.6.0}/tests/test_docs.py +0 -0
- {sqlglot-27.5.1 → sqlglot-27.6.0}/tests/test_executor.py +0 -0
- {sqlglot-27.5.1 → sqlglot-27.6.0}/tests/test_expressions.py +0 -0
- {sqlglot-27.5.1 → sqlglot-27.6.0}/tests/test_generator.py +0 -0
- {sqlglot-27.5.1 → sqlglot-27.6.0}/tests/test_helper.py +0 -0
- {sqlglot-27.5.1 → sqlglot-27.6.0}/tests/test_jsonpath.py +0 -0
- {sqlglot-27.5.1 → sqlglot-27.6.0}/tests/test_lineage.py +0 -0
- {sqlglot-27.5.1 → sqlglot-27.6.0}/tests/test_optimizer.py +0 -0
- {sqlglot-27.5.1 → sqlglot-27.6.0}/tests/test_parser.py +0 -0
- {sqlglot-27.5.1 → sqlglot-27.6.0}/tests/test_schema.py +0 -0
- {sqlglot-27.5.1 → sqlglot-27.6.0}/tests/test_serde.py +0 -0
- {sqlglot-27.5.1 → sqlglot-27.6.0}/tests/test_time.py +0 -0
- {sqlglot-27.5.1 → sqlglot-27.6.0}/tests/test_tokens.py +0 -0
- {sqlglot-27.5.1 → sqlglot-27.6.0}/tests/test_transforms.py +0 -0
- {sqlglot-27.5.1 → sqlglot-27.6.0}/tests/test_transpile.py +0 -0
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
Changelog
|
|
2
2
|
=========
|
|
3
3
|
|
|
4
|
+
## [v27.5.1] - 2025-07-30
|
|
5
|
+
### :bug: Bug Fixes
|
|
6
|
+
- [`caf71d6`](https://github.com/tobymao/sqlglot/commit/caf71d687c0048d2346fddaee58b519e4f2e7945) - `between` builder should not set `symmetric` by default *(commit by [@georgesittas](https://github.com/georgesittas))*
|
|
7
|
+
|
|
8
|
+
|
|
4
9
|
## [v27.5.0] - 2025-07-30
|
|
5
10
|
### :boom: BREAKING CHANGES
|
|
6
11
|
- due to [`002286e`](https://github.com/tobymao/sqlglot/commit/002286ee05a608e303a2238a9a74ab963709b5da) - remove AM/PM entries from postgres, oracle `TIME_MAPPING` *(PR [#5491](https://github.com/tobymao/sqlglot/pull/5491) by [@georgesittas](https://github.com/georgesittas))*:
|
|
@@ -6373,3 +6378,4 @@ Changelog
|
|
|
6373
6378
|
[v27.4.0]: https://github.com/tobymao/sqlglot/compare/v27.3.1...v27.4.0
|
|
6374
6379
|
[v27.4.1]: https://github.com/tobymao/sqlglot/compare/v27.4.0...v27.4.1
|
|
6375
6380
|
[v27.5.0]: https://github.com/tobymao/sqlglot/compare/v27.4.1...v27.5.0
|
|
6381
|
+
[v27.5.1]: https://github.com/tobymao/sqlglot/compare/v27.5.0...v27.5.1
|
|
@@ -434,7 +434,9 @@ class BigQuery(Dialect):
|
|
|
434
434
|
|
|
435
435
|
# The _PARTITIONTIME and _PARTITIONDATE pseudo-columns are not returned by a SELECT * statement
|
|
436
436
|
# https://cloud.google.com/bigquery/docs/querying-partitioned-tables#query_an_ingestion-time_partitioned_table
|
|
437
|
-
|
|
437
|
+
# https://cloud.google.com/bigquery/docs/querying-wildcard-tables#scanning_a_range_of_tables_using_table_suffix
|
|
438
|
+
# https://cloud.google.com/bigquery/docs/query-cloud-storage-data#query_the_file_name_pseudo-column
|
|
439
|
+
PSEUDOCOLUMNS = {"_PARTITIONTIME", "_PARTITIONDATE", "_TABLE_SUFFIX", "_FILE_NAME"}
|
|
438
440
|
|
|
439
441
|
# All set operations require either a DISTINCT or ALL specifier
|
|
440
442
|
SET_OP_DISTINCT_BY_DEFAULT = dict.fromkeys((exp.Except, exp.Intersect, exp.Union), None)
|
|
@@ -3,7 +3,6 @@ from __future__ import annotations
|
|
|
3
3
|
import typing as t
|
|
4
4
|
|
|
5
5
|
from sqlglot import exp, generator, parser, tokens
|
|
6
|
-
from sqlglot.dialects.clickhouse import timestamptrunc_sql
|
|
7
6
|
from sqlglot.dialects.dialect import (
|
|
8
7
|
Dialect,
|
|
9
8
|
binary_from_function,
|
|
@@ -12,6 +11,8 @@ from sqlglot.dialects.dialect import (
|
|
|
12
11
|
strposition_sql,
|
|
13
12
|
timestrtotime_sql,
|
|
14
13
|
unit_to_str,
|
|
14
|
+
timestamptrunc_sql,
|
|
15
|
+
build_date_delta,
|
|
15
16
|
)
|
|
16
17
|
from sqlglot.generator import unsupported_args
|
|
17
18
|
from sqlglot.helper import seq_get
|
|
@@ -46,6 +47,18 @@ def _build_trunc(args: t.List[exp.Expression], dialect: DialectType) -> exp.Expr
|
|
|
46
47
|
return exp.Anonymous(this="TRUNC", expressions=args)
|
|
47
48
|
|
|
48
49
|
|
|
50
|
+
# https://docs.exasol.com/db/latest/sql_references/functions/alphabeticallistfunctions/zeroifnull.htm
|
|
51
|
+
def _build_zeroifnull(args: t.List) -> exp.If:
|
|
52
|
+
cond = exp.Is(this=seq_get(args, 0), expression=exp.Null())
|
|
53
|
+
return exp.If(this=cond, true=exp.Literal.number(0), false=seq_get(args, 0))
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
# https://docs.exasol.com/db/latest/sql_references/functions/alphabeticallistfunctions/nullifzero.htm
|
|
57
|
+
def _build_nullifzero(args: t.List) -> exp.If:
|
|
58
|
+
cond = exp.EQ(this=seq_get(args, 0), expression=exp.Literal.number(0))
|
|
59
|
+
return exp.If(this=cond, true=exp.Null(), false=seq_get(args, 0))
|
|
60
|
+
|
|
61
|
+
|
|
49
62
|
class Exasol(Dialect):
|
|
50
63
|
TIME_MAPPING = {
|
|
51
64
|
"yyyy": "%Y",
|
|
@@ -79,11 +92,28 @@ class Exasol(Dialect):
|
|
|
79
92
|
KEYWORDS = {
|
|
80
93
|
**tokens.Tokenizer.KEYWORDS,
|
|
81
94
|
"USER": TokenType.CURRENT_USER,
|
|
95
|
+
# https://docs.exasol.com/db/latest/sql_references/functions/alphabeticallistfunctions/if.htm
|
|
96
|
+
"ENDIF": TokenType.END,
|
|
97
|
+
"LONG VARCHAR": TokenType.TEXT,
|
|
82
98
|
}
|
|
83
99
|
|
|
84
100
|
class Parser(parser.Parser):
|
|
85
101
|
FUNCTIONS = {
|
|
86
102
|
**parser.Parser.FUNCTIONS,
|
|
103
|
+
# https://docs.exasol.com/db/latest/sql_references/functions/alphabeticallistfunctions/add_days.htm
|
|
104
|
+
"ADD_DAYS": build_date_delta(exp.DateAdd, default_unit="DAY"),
|
|
105
|
+
# https://docs.exasol.com/db/latest/sql_references/functions/alphabeticallistfunctions/add_years.htm
|
|
106
|
+
"ADD_YEARS": build_date_delta(exp.DateAdd, default_unit="YEAR"),
|
|
107
|
+
# https://docs.exasol.com/db/latest/sql_references/functions/alphabeticallistfunctions/add_months.htm
|
|
108
|
+
"ADD_MONTHS": build_date_delta(exp.DateAdd, default_unit="MONTH"),
|
|
109
|
+
# https://docs.exasol.com/db/latest/sql_references/functions/alphabeticallistfunctions/add_weeks.htm
|
|
110
|
+
"ADD_WEEKS": build_date_delta(exp.DateAdd, default_unit="WEEK"),
|
|
111
|
+
# https://docs.exasol.com/db/latest/sql_references/functions/alphabeticallistfunctions/add_hour.htm
|
|
112
|
+
"ADD_HOURS": build_date_delta(exp.DateAdd, default_unit="HOUR"),
|
|
113
|
+
# https://docs.exasol.com/db/latest/sql_references/functions/alphabeticallistfunctions/add_minutes.htm
|
|
114
|
+
"ADD_MINUTES": build_date_delta(exp.DateAdd, default_unit="MINUTE"),
|
|
115
|
+
# https://docs.exasol.com/db/latest/sql_references/functions/alphabeticallistfunctions/add_seconds.htm
|
|
116
|
+
"ADD_SECONDS": build_date_delta(exp.DateAdd, default_unit="SECOND"),
|
|
87
117
|
"BIT_AND": binary_from_function(exp.BitwiseAnd),
|
|
88
118
|
"BIT_OR": binary_from_function(exp.BitwiseOr),
|
|
89
119
|
"BIT_XOR": binary_from_function(exp.BitwiseXor),
|
|
@@ -127,6 +157,8 @@ class Exasol(Dialect):
|
|
|
127
157
|
timestamp=seq_get(args, 0),
|
|
128
158
|
options=seq_get(args, 3),
|
|
129
159
|
),
|
|
160
|
+
"NULLIFZERO": _build_nullifzero,
|
|
161
|
+
"ZEROIFNULL": _build_zeroifnull,
|
|
130
162
|
}
|
|
131
163
|
CONSTRAINT_PARSERS = {
|
|
132
164
|
**parser.Parser.CONSTRAINT_PARSERS,
|
|
@@ -146,7 +178,8 @@ class Exasol(Dialect):
|
|
|
146
178
|
exp.DataType.Type.MEDIUMTEXT: "VARCHAR",
|
|
147
179
|
exp.DataType.Type.TINYBLOB: "VARCHAR",
|
|
148
180
|
exp.DataType.Type.TINYTEXT: "VARCHAR",
|
|
149
|
-
|
|
181
|
+
# https://docs.exasol.com/db/latest/sql_references/data_types/datatypealiases.htm
|
|
182
|
+
exp.DataType.Type.TEXT: "LONG VARCHAR",
|
|
150
183
|
exp.DataType.Type.VARBINARY: "VARCHAR",
|
|
151
184
|
}
|
|
152
185
|
|
|
@@ -163,6 +196,16 @@ class Exasol(Dialect):
|
|
|
163
196
|
exp.DataType.Type.DATETIME: "TIMESTAMP",
|
|
164
197
|
}
|
|
165
198
|
|
|
199
|
+
DATE_ADD_FUNCTION_BY_UNIT = {
|
|
200
|
+
"DAY": "ADD_DAYS",
|
|
201
|
+
"WEEK": "ADD_WEEKS",
|
|
202
|
+
"MONTH": "ADD_MONTHS",
|
|
203
|
+
"YEAR": "ADD_YEARS",
|
|
204
|
+
"HOUR": "ADD_HOURS",
|
|
205
|
+
"MINUTE": "ADD_MINUTES",
|
|
206
|
+
"SECOND": "ADD_SECONDS",
|
|
207
|
+
}
|
|
208
|
+
|
|
166
209
|
def datatype_sql(self, expression: exp.DataType) -> str:
|
|
167
210
|
# Exasol supports a fixed default precision of 3 for TIMESTAMP WITH LOCAL TIME ZONE
|
|
168
211
|
# and does not allow specifying a different custom precision
|
|
@@ -249,3 +292,18 @@ class Exasol(Dialect):
|
|
|
249
292
|
options = expression.args.get("options")
|
|
250
293
|
|
|
251
294
|
return self.func("CONVERT_TZ", datetime, from_tz, to_tz, options)
|
|
295
|
+
|
|
296
|
+
def if_sql(self, expression: exp.If) -> str:
|
|
297
|
+
this = self.sql(expression, "this")
|
|
298
|
+
true = self.sql(expression, "true")
|
|
299
|
+
false = self.sql(expression, "false")
|
|
300
|
+
return f"IF {this} THEN {true} ELSE {false} ENDIF"
|
|
301
|
+
|
|
302
|
+
def dateadd_sql(self, expression: exp.DateAdd) -> str:
|
|
303
|
+
unit = expression.text("unit").upper() or "DAY"
|
|
304
|
+
func_name = self.DATE_ADD_FUNCTION_BY_UNIT.get(unit)
|
|
305
|
+
if not func_name:
|
|
306
|
+
self.unsupported(f"'{unit}' is not supported in Exasol.")
|
|
307
|
+
return self.function_fallback_sql(expression)
|
|
308
|
+
|
|
309
|
+
return self.func(func_name, expression.this, expression.expression)
|
|
@@ -4,6 +4,7 @@ import typing as t
|
|
|
4
4
|
from sqlglot import exp
|
|
5
5
|
from sqlglot.dialects.dialect import build_formatted_time
|
|
6
6
|
from sqlglot.dialects.mysql import MySQL
|
|
7
|
+
from sqlglot.generator import unsupported_args
|
|
7
8
|
from sqlglot.helper import seq_get
|
|
8
9
|
|
|
9
10
|
|
|
@@ -65,6 +66,21 @@ class SingleStore(MySQL):
|
|
|
65
66
|
),
|
|
66
67
|
}
|
|
67
68
|
|
|
69
|
+
CAST_COLUMN_OPERATORS = {TokenType.COLON_GT, TokenType.NCOLON_GT}
|
|
70
|
+
|
|
71
|
+
COLUMN_OPERATORS = {
|
|
72
|
+
TokenType.COLON_GT: lambda self, this, to: self.expression(
|
|
73
|
+
exp.Cast,
|
|
74
|
+
this=this,
|
|
75
|
+
to=to,
|
|
76
|
+
),
|
|
77
|
+
TokenType.NCOLON_GT: lambda self, this, to: self.expression(
|
|
78
|
+
exp.TryCast,
|
|
79
|
+
this=this,
|
|
80
|
+
to=to,
|
|
81
|
+
),
|
|
82
|
+
}
|
|
83
|
+
|
|
68
84
|
class Generator(MySQL.Generator):
|
|
69
85
|
TRANSFORMS = {
|
|
70
86
|
**MySQL.Generator.TRANSFORMS,
|
|
@@ -89,6 +105,12 @@ class SingleStore(MySQL):
|
|
|
89
105
|
inverse_time_trie=MySQL.INVERSE_TIME_TRIE,
|
|
90
106
|
),
|
|
91
107
|
),
|
|
108
|
+
exp.Cast: unsupported_args("format", "action", "default")(
|
|
109
|
+
lambda self, e: f"{self.sql(e, 'this')} :> {self.sql(e, 'to')}"
|
|
110
|
+
),
|
|
111
|
+
exp.TryCast: unsupported_args("format", "action", "default")(
|
|
112
|
+
lambda self, e: f"{self.sql(e, 'this')} !:> {self.sql(e, 'to')}"
|
|
113
|
+
),
|
|
92
114
|
}
|
|
93
115
|
|
|
94
116
|
# https://docs.singlestore.com/cloud/reference/sql-reference/restricted-keywords/list-of-restricted-keywords/
|
|
@@ -591,6 +591,7 @@ class Snowflake(Dialect):
|
|
|
591
591
|
this=seq_get(args, 0), expression=seq_get(args, 1), max_dist=seq_get(args, 2)
|
|
592
592
|
),
|
|
593
593
|
"FLATTEN": exp.Explode.from_arg_list,
|
|
594
|
+
"GET": exp.GetExtract.from_arg_list,
|
|
594
595
|
"GET_PATH": lambda args, dialect: exp.JSONExtract(
|
|
595
596
|
this=seq_get(args, 0),
|
|
596
597
|
expression=dialect.to_json_path(seq_get(args, 1)),
|
|
@@ -1220,6 +1221,7 @@ class Snowflake(Dialect):
|
|
|
1220
1221
|
exp.GenerateSeries: lambda self, e: self.func(
|
|
1221
1222
|
"ARRAY_GENERATE_RANGE", e.args["start"], e.args["end"] + 1, e.args.get("step")
|
|
1222
1223
|
),
|
|
1224
|
+
exp.GetExtract: rename_func("GET"),
|
|
1223
1225
|
exp.GroupConcat: lambda self, e: groupconcat_sql(self, e, sep=""),
|
|
1224
1226
|
exp.If: if_sql(name="IFF", false_value="NULL"),
|
|
1225
1227
|
exp.JSONExtractArray: _json_extract_value_array_sql,
|
|
@@ -6185,6 +6185,11 @@ class GenerateTimestampArray(Func):
|
|
|
6185
6185
|
arg_types = {"start": True, "end": True, "step": True}
|
|
6186
6186
|
|
|
6187
6187
|
|
|
6188
|
+
# https://docs.snowflake.com/en/sql-reference/functions/get
|
|
6189
|
+
class GetExtract(Func):
|
|
6190
|
+
arg_types = {"this": True, "expression": True}
|
|
6191
|
+
|
|
6192
|
+
|
|
6188
6193
|
class Greatest(Func):
|
|
6189
6194
|
arg_types = {"this": True, "expressions": False}
|
|
6190
6195
|
is_var_len_args = True
|
|
@@ -5113,3 +5113,17 @@ class Generator(metaclass=_Generator):
|
|
|
5113
5113
|
where = self.sql(expression, "where")
|
|
5114
5114
|
where = self.seg(f"WHERE {where}") if where else ""
|
|
5115
5115
|
return f"SEMANTIC_VIEW({self.indent(this + metrics + dimensions + where)}{self.seg(')', sep='')}"
|
|
5116
|
+
|
|
5117
|
+
def getextract_sql(self, expression: exp.GetExtract) -> str:
|
|
5118
|
+
this = expression.this
|
|
5119
|
+
expr = expression.expression
|
|
5120
|
+
|
|
5121
|
+
if not this.type or not expression.type:
|
|
5122
|
+
from sqlglot.optimizer.annotate_types import annotate_types
|
|
5123
|
+
|
|
5124
|
+
this = annotate_types(this, dialect=self.dialect)
|
|
5125
|
+
|
|
5126
|
+
if this.is_type(*(exp.DataType.Type.ARRAY, exp.DataType.Type.MAP)):
|
|
5127
|
+
return self.sql(exp.Bracket(this=this, expressions=[expr]))
|
|
5128
|
+
|
|
5129
|
+
return self.sql(exp.JSONExtract(this=this, expression=self.dialect.to_json_path(expr)))
|
|
@@ -972,6 +972,44 @@ class Resolver:
|
|
|
972
972
|
}
|
|
973
973
|
return self._all_columns
|
|
974
974
|
|
|
975
|
+
def get_source_columns_from_set_op(self, expression: exp.Expression) -> t.List[str]:
|
|
976
|
+
if isinstance(expression, exp.Select):
|
|
977
|
+
return expression.named_selects
|
|
978
|
+
if isinstance(expression, exp.Subquery) and isinstance(expression.this, exp.SetOperation):
|
|
979
|
+
# Different types of SET modifiers can be chained together if they're explicitly grouped by nesting
|
|
980
|
+
return self.get_source_columns_from_set_op(expression.this)
|
|
981
|
+
if not isinstance(expression, exp.SetOperation):
|
|
982
|
+
raise OptimizeError(f"Unknown set operation: {expression}")
|
|
983
|
+
|
|
984
|
+
set_op = expression
|
|
985
|
+
|
|
986
|
+
# BigQuery specific set operations modifiers, e.g INNER UNION ALL BY NAME
|
|
987
|
+
on_column_list = set_op.args.get("on")
|
|
988
|
+
|
|
989
|
+
if on_column_list:
|
|
990
|
+
# The resulting columns are the columns in the ON clause:
|
|
991
|
+
# {INNER | LEFT | FULL} UNION ALL BY NAME ON (col1, col2, ...)
|
|
992
|
+
columns = [col.name for col in on_column_list]
|
|
993
|
+
elif set_op.side or set_op.kind:
|
|
994
|
+
side = set_op.side
|
|
995
|
+
kind = set_op.kind
|
|
996
|
+
|
|
997
|
+
# Visit the children UNIONs (if any) in a post-order traversal
|
|
998
|
+
left = self.get_source_columns_from_set_op(set_op.left)
|
|
999
|
+
right = self.get_source_columns_from_set_op(set_op.right)
|
|
1000
|
+
|
|
1001
|
+
# We use dict.fromkeys to deduplicate keys and maintain insertion order
|
|
1002
|
+
if side == "LEFT":
|
|
1003
|
+
columns = left
|
|
1004
|
+
elif side == "FULL":
|
|
1005
|
+
columns = list(dict.fromkeys(left + right))
|
|
1006
|
+
elif kind == "INNER":
|
|
1007
|
+
columns = list(dict.fromkeys(left).keys() & dict.fromkeys(right).keys())
|
|
1008
|
+
else:
|
|
1009
|
+
columns = set_op.named_selects
|
|
1010
|
+
|
|
1011
|
+
return columns
|
|
1012
|
+
|
|
975
1013
|
def get_source_columns(self, name: str, only_visible: bool = False) -> t.Sequence[str]:
|
|
976
1014
|
"""Resolve the source columns for a given source `name`."""
|
|
977
1015
|
cache_key = (name, only_visible)
|
|
@@ -996,31 +1034,8 @@ class Resolver:
|
|
|
996
1034
|
for k in source.expression.type.expressions: # type: ignore
|
|
997
1035
|
columns.append(k.name)
|
|
998
1036
|
elif isinstance(source, Scope) and isinstance(source.expression, exp.SetOperation):
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
# BigQuery specific set operations modifiers, e.g INNER UNION ALL BY NAME
|
|
1002
|
-
on_column_list = set_op.args.get("on")
|
|
1003
|
-
|
|
1004
|
-
if on_column_list:
|
|
1005
|
-
# The resulting columns are the columns in the ON clause:
|
|
1006
|
-
# {INNER | LEFT | FULL} UNION ALL BY NAME ON (col1, col2, ...)
|
|
1007
|
-
columns = [col.name for col in on_column_list]
|
|
1008
|
-
elif set_op.side or set_op.kind:
|
|
1009
|
-
side = set_op.side
|
|
1010
|
-
kind = set_op.kind
|
|
1011
|
-
|
|
1012
|
-
left = set_op.left.named_selects
|
|
1013
|
-
right = set_op.right.named_selects
|
|
1014
|
-
|
|
1015
|
-
# We use dict.fromkeys to deduplicate keys and maintain insertion order
|
|
1016
|
-
if side == "LEFT":
|
|
1017
|
-
columns = left
|
|
1018
|
-
elif side == "FULL":
|
|
1019
|
-
columns = list(dict.fromkeys(left + right))
|
|
1020
|
-
elif kind == "INNER":
|
|
1021
|
-
columns = list(dict.fromkeys(left).keys() & dict.fromkeys(right).keys())
|
|
1022
|
-
else:
|
|
1023
|
-
columns = set_op.named_selects
|
|
1037
|
+
columns = self.get_source_columns_from_set_op(source.expression)
|
|
1038
|
+
|
|
1024
1039
|
else:
|
|
1025
1040
|
select = seq_get(source.expression.selects, 0)
|
|
1026
1041
|
|
|
@@ -792,6 +792,11 @@ class Parser(metaclass=_Parser):
|
|
|
792
792
|
),
|
|
793
793
|
}
|
|
794
794
|
|
|
795
|
+
CAST_COLUMN_OPERATORS = {
|
|
796
|
+
TokenType.DOTCOLON,
|
|
797
|
+
TokenType.DCOLON,
|
|
798
|
+
}
|
|
799
|
+
|
|
795
800
|
EXPRESSION_PARSERS = {
|
|
796
801
|
exp.Cluster: lambda self: self._parse_sort(exp.Cluster, TokenType.CLUSTER_BY),
|
|
797
802
|
exp.Column: lambda self: self._parse_column(),
|
|
@@ -5621,7 +5626,7 @@ class Parser(metaclass=_Parser):
|
|
|
5621
5626
|
op_token = self._prev.token_type
|
|
5622
5627
|
op = self.COLUMN_OPERATORS.get(op_token)
|
|
5623
5628
|
|
|
5624
|
-
if op_token in
|
|
5629
|
+
if op_token in self.CAST_COLUMN_OPERATORS:
|
|
5625
5630
|
field = self._parse_dcolon()
|
|
5626
5631
|
if not field:
|
|
5627
5632
|
self.raise_error("Expected type")
|
|
@@ -13,7 +13,10 @@ class TestExasol(Validator):
|
|
|
13
13
|
self.validate_identity("CAST(x AS MEDIUMTEXT)", "CAST(x AS VARCHAR)")
|
|
14
14
|
self.validate_identity("CAST(x AS TINYBLOB)", "CAST(x AS VARCHAR)")
|
|
15
15
|
self.validate_identity("CAST(x AS TINYTEXT)", "CAST(x AS VARCHAR)")
|
|
16
|
-
self.validate_identity("CAST(x AS TEXT)", "CAST(x AS VARCHAR)")
|
|
16
|
+
self.validate_identity("CAST(x AS TEXT)", "CAST(x AS LONG VARCHAR)")
|
|
17
|
+
self.validate_identity(
|
|
18
|
+
"SELECT CAST((CAST(202305 AS INT) - 100) AS LONG VARCHAR) AS CAL_YEAR_WEEK_ADJUSTED"
|
|
19
|
+
)
|
|
17
20
|
self.validate_identity("CAST(x AS VARBINARY)", "CAST(x AS VARCHAR)")
|
|
18
21
|
self.validate_identity("CAST(x AS VARCHAR)", "CAST(x AS VARCHAR)")
|
|
19
22
|
self.validate_identity("CAST(x AS CHAR)", "CAST(x AS CHAR)")
|
|
@@ -400,6 +403,32 @@ class TestExasol(Validator):
|
|
|
400
403
|
"databricks": "SELECT DATE_TRUNC('MINUTE', CAST('2006-12-31 23:59:59' AS TIMESTAMP)) AS DATE_TRUNC",
|
|
401
404
|
},
|
|
402
405
|
)
|
|
406
|
+
test_cases = {
|
|
407
|
+
"ADD_DAYS": ("DAY", "add_days"),
|
|
408
|
+
"ADD_WEEKS": ("WEEK", "add_weeks"),
|
|
409
|
+
"ADD_MONTHS": ("MONTH", "add_months"),
|
|
410
|
+
"ADD_YEARS": ("YEAR", "add_years"),
|
|
411
|
+
"ADD_HOURS": ("HOUR", "add_hours"),
|
|
412
|
+
"ADD_MINUTES": ("MINUTE", "add_minutes"),
|
|
413
|
+
"ADD_SECONDS": ("SECOND", "add_seconds"),
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
for func_name, (unit, alias) in test_cases.items():
|
|
417
|
+
with self.subTest(f"Testing {func_name}"):
|
|
418
|
+
write = {
|
|
419
|
+
"exasol": f"SELECT {func_name}(CAST('2000-02-28' AS DATE), 1) AS {alias}",
|
|
420
|
+
"bigquery": f"SELECT DATE_ADD(CAST('2000-02-28' AS DATE), INTERVAL 1 {unit}) AS {alias}",
|
|
421
|
+
"duckdb": f"SELECT CAST('2000-02-28' AS DATE) + INTERVAL 1 {unit} AS {alias}",
|
|
422
|
+
"presto": f"SELECT DATE_ADD('{unit}', 1, CAST('2000-02-28' AS DATE)) AS {alias}",
|
|
423
|
+
"redshift": f"SELECT DATEADD({unit}, 1, CAST('2000-02-28' AS DATE)) AS {alias}",
|
|
424
|
+
"snowflake": f"SELECT DATEADD({unit}, 1, CAST('2000-02-28' AS DATE)) AS {alias}",
|
|
425
|
+
"tsql": f"SELECT DATEADD({unit}, 1, CAST('2000-02-28' AS DATE)) AS {alias}",
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
self.validate_all(
|
|
429
|
+
f"SELECT {func_name}(DATE '2000-02-28', 1) AS {alias}",
|
|
430
|
+
write=write,
|
|
431
|
+
)
|
|
403
432
|
|
|
404
433
|
def test_number_functions(self):
|
|
405
434
|
self.validate_identity("SELECT TRUNC(123.456, 2) AS TRUNC")
|
|
@@ -509,3 +538,30 @@ class TestExasol(Validator):
|
|
|
509
538
|
"trino": "SHA512(x)",
|
|
510
539
|
},
|
|
511
540
|
)
|
|
541
|
+
self.validate_all(
|
|
542
|
+
"SELECT NULLIFZERO(1) NIZ1",
|
|
543
|
+
write={
|
|
544
|
+
"exasol": "SELECT IF 1 = 0 THEN NULL ELSE 1 ENDIF AS NIZ1",
|
|
545
|
+
"snowflake": "SELECT IFF(1 = 0, NULL, 1) AS NIZ1",
|
|
546
|
+
"sqlite": "SELECT IIF(1 = 0, NULL, 1) AS NIZ1",
|
|
547
|
+
"presto": "SELECT IF(1 = 0, NULL, 1) AS NIZ1",
|
|
548
|
+
"spark": "SELECT IF(1 = 0, NULL, 1) AS NIZ1",
|
|
549
|
+
"hive": "SELECT IF(1 = 0, NULL, 1) AS NIZ1",
|
|
550
|
+
"duckdb": "SELECT CASE WHEN 1 = 0 THEN NULL ELSE 1 END AS NIZ1",
|
|
551
|
+
},
|
|
552
|
+
)
|
|
553
|
+
self.validate_all(
|
|
554
|
+
"SELECT ZEROIFNULL(NULL) NIZ1",
|
|
555
|
+
write={
|
|
556
|
+
"exasol": "SELECT IF NULL IS NULL THEN 0 ELSE NULL ENDIF AS NIZ1",
|
|
557
|
+
"snowflake": "SELECT IFF(NULL IS NULL, 0, NULL) AS NIZ1",
|
|
558
|
+
"sqlite": "SELECT IIF(NULL IS NULL, 0, NULL) AS NIZ1",
|
|
559
|
+
"presto": "SELECT IF(NULL IS NULL, 0, NULL) AS NIZ1",
|
|
560
|
+
"spark": "SELECT IF(NULL IS NULL, 0, NULL) AS NIZ1",
|
|
561
|
+
"hive": "SELECT IF(NULL IS NULL, 0, NULL) AS NIZ1",
|
|
562
|
+
"duckdb": "SELECT CASE WHEN NULL IS NULL THEN 0 ELSE NULL END AS NIZ1",
|
|
563
|
+
},
|
|
564
|
+
)
|
|
565
|
+
self.validate_identity(
|
|
566
|
+
"SELECT name, age, IF age < 18 THEN 'underaged' ELSE 'adult' ENDIF AS LEGALITY FROM persons"
|
|
567
|
+
)
|
|
@@ -19,7 +19,6 @@ class TestSingleStore(Validator):
|
|
|
19
19
|
|
|
20
20
|
self.validate_identity("SELECT 1")
|
|
21
21
|
self.validate_identity("SELECT * FROM `users` ORDER BY ALL")
|
|
22
|
-
self.validate_identity("SELECT CAST(x AS GEOGRAPHYPOINT)")
|
|
23
22
|
|
|
24
23
|
def test_byte_strings(self):
|
|
25
24
|
self.validate_identity("SELECT e'text'")
|
|
@@ -47,5 +46,30 @@ class TestSingleStore(Validator):
|
|
|
47
46
|
)
|
|
48
47
|
self.validate_identity(
|
|
49
48
|
"SELECT TIME_FORMAT('12:05:47', '%s, %i, %h')",
|
|
50
|
-
"SELECT DATE_FORMAT(
|
|
49
|
+
"SELECT DATE_FORMAT('12:05:47' :> TIME(6), '%s, %i, %h')",
|
|
51
50
|
)
|
|
51
|
+
|
|
52
|
+
def test_cast(self):
|
|
53
|
+
self.validate_all(
|
|
54
|
+
"SELECT 1 :> INT",
|
|
55
|
+
read={
|
|
56
|
+
"": "SELECT CAST(1 AS INT)",
|
|
57
|
+
},
|
|
58
|
+
write={
|
|
59
|
+
"singlestore": "SELECT 1 :> INT",
|
|
60
|
+
"": "SELECT CAST(1 AS INT)",
|
|
61
|
+
},
|
|
62
|
+
)
|
|
63
|
+
self.validate_all(
|
|
64
|
+
"SELECT 1 !:> INT",
|
|
65
|
+
read={
|
|
66
|
+
"": "SELECT TRY_CAST(1 AS INT)",
|
|
67
|
+
},
|
|
68
|
+
write={
|
|
69
|
+
"singlestore": "SELECT 1 !:> INT",
|
|
70
|
+
"": "SELECT TRY_CAST(1 AS INT)",
|
|
71
|
+
},
|
|
72
|
+
)
|
|
73
|
+
self.validate_identity("SELECT '{\"a\" : 1}' :> JSON")
|
|
74
|
+
self.validate_identity("SELECT NOW() !:> TIMESTAMP(6)")
|
|
75
|
+
self.validate_identity("SELECT x :> GEOGRAPHYPOINT")
|
|
@@ -2746,7 +2746,7 @@ SINGLE = TRUE""",
|
|
|
2746
2746
|
|
|
2747
2747
|
def test_get_from_stage(self):
|
|
2748
2748
|
self.validate_identity('GET @"my_DB"."schEMA1"."MYstage" \'file:///dir/tmp.csv\'')
|
|
2749
|
-
self.validate_identity("GET @s1/test 'file:///dir/tmp.csv'")
|
|
2749
|
+
self.validate_identity("GET @s1/test 'file:///dir/tmp.csv'").assert_is(exp.Get)
|
|
2750
2750
|
|
|
2751
2751
|
# GET with file path and stage ref containing spaces (wrapped in single quotes)
|
|
2752
2752
|
ast = parse_one("GET '@s1/my folder' 'file://my file.txt'", read="snowflake")
|
|
@@ -2950,3 +2950,30 @@ FROM SEMANTIC_VIEW(
|
|
|
2950
2950
|
)""",
|
|
2951
2951
|
pretty=True,
|
|
2952
2952
|
)
|
|
2953
|
+
|
|
2954
|
+
def test_get_extract(self):
|
|
2955
|
+
self.validate_all(
|
|
2956
|
+
"SELECT GET([4, 5, 6], 1)",
|
|
2957
|
+
write={
|
|
2958
|
+
"snowflake": "SELECT GET([4, 5, 6], 1)",
|
|
2959
|
+
"duckdb": "SELECT [4, 5, 6][2]",
|
|
2960
|
+
},
|
|
2961
|
+
)
|
|
2962
|
+
|
|
2963
|
+
self.validate_all(
|
|
2964
|
+
"SELECT GET(col::MAP(INTEGER, VARCHAR), 1)",
|
|
2965
|
+
write={
|
|
2966
|
+
"snowflake": "SELECT GET(CAST(col AS MAP(INT, VARCHAR)), 1)",
|
|
2967
|
+
"duckdb": "SELECT CAST(col AS MAP(INT, TEXT))[1]",
|
|
2968
|
+
},
|
|
2969
|
+
)
|
|
2970
|
+
|
|
2971
|
+
self.validate_all(
|
|
2972
|
+
"SELECT GET(v, 'field')",
|
|
2973
|
+
write={
|
|
2974
|
+
"snowflake": "SELECT GET(v, 'field')",
|
|
2975
|
+
"duckdb": "SELECT v -> '$.field'",
|
|
2976
|
+
},
|
|
2977
|
+
)
|
|
2978
|
+
|
|
2979
|
+
self.validate_identity("GET(foo, bar)").assert_is(exp.GetExtract)
|
|
@@ -389,6 +389,25 @@ SELECT _q_0.foo AS foo, _q_0.qux AS qux FROM ((SELECT 1 AS foo, 2 AS bar LEFT UN
|
|
|
389
389
|
SELECT * FROM (((SELECT 1 AS foo, 2 AS bar LEFT UNION ALL BY NAME SELECT 3 AS bar, 4 AS baz) FULL UNION ALL BY NAME ON (foo, qux) SELECT 3 AS qux, 4 AS bar) INNER UNION ALL BY NAME ON (foo) SELECT 6 AS foo);
|
|
390
390
|
SELECT _q_0.foo AS foo FROM (((SELECT 1 AS foo, 2 AS bar LEFT UNION ALL BY NAME SELECT 3 AS bar, 4 AS baz) FULL UNION ALL BY NAME ON (foo, qux) SELECT 3 AS qux, 4 AS bar) INNER UNION ALL BY NAME ON (foo) SELECT 6 AS foo) AS _q_0;
|
|
391
391
|
|
|
392
|
+
# Title: Nested set operations with modifiers
|
|
393
|
+
# dialect: bigquery
|
|
394
|
+
# execute: false
|
|
395
|
+
WITH t1 AS (SELECT 1 AS a, 2 AS b), t2 AS (SELECT 2 AS b, 3 AS c), t3 AS (SELECT 2 AS c, 3 AS d), t4 AS (SELECT 2 AS e, 3 AS f) SELECT * FROM ((SELECT * FROM t1 FULL OUTER UNION ALL BY NAME (SELECT * FROM t2 FULL OUTER UNION ALL BY NAME (SELECT * FROM t3 FULL OUTER UNION ALL BY NAME SELECT * FROM t4))));
|
|
396
|
+
WITH t1 AS (SELECT 1 AS a, 2 AS b), t2 AS (SELECT 2 AS b, 3 AS c), t3 AS (SELECT 2 AS c, 3 AS d), t4 AS (SELECT 2 AS e, 3 AS f) SELECT _q_0.a AS a, _q_0.b AS b, _q_0.c AS c, _q_0.d AS d, _q_0.e AS e, _q_0.f AS f FROM ((SELECT t1.a AS a, t1.b AS b FROM t1 AS t1 FULL OUTER UNION ALL BY NAME (SELECT t2.b AS b, t2.c AS c FROM t2 AS t2 FULL OUTER UNION ALL BY NAME (SELECT t3.c AS c, t3.d AS d FROM t3 AS t3 FULL OUTER UNION ALL BY NAME SELECT t4.e AS e, t4.f AS f FROM t4 AS t4))) AS _q_0);
|
|
397
|
+
|
|
398
|
+
|
|
399
|
+
# Title: Nested set operations with different modifiers (FULL + INNER)
|
|
400
|
+
# dialect: bigquery
|
|
401
|
+
# execute: false
|
|
402
|
+
WITH t1 AS (SELECT 1 AS a, 2 AS b), t2 AS (SELECT 2 AS b, 3 AS c), t3 AS (SELECT 2 AS c, 3 AS d), t4 AS (SELECT 2 AS e, 3 AS f) SELECT * FROM ((SELECT * FROM t1 FULL OUTER UNION ALL BY NAME (SELECT * FROM t2 INNER UNION ALL BY NAME (SELECT * FROM t3 FULL OUTER UNION ALL BY NAME SELECT * FROM t4))));
|
|
403
|
+
WITH t1 AS (SELECT 1 AS a, 2 AS b), t2 AS (SELECT 2 AS b, 3 AS c), t3 AS (SELECT 2 AS c, 3 AS d), t4 AS (SELECT 2 AS e, 3 AS f) SELECT _q_0.a AS a, _q_0.b AS b, _q_0.c AS c FROM ((SELECT t1.a AS a, t1.b AS b FROM t1 AS t1 FULL OUTER UNION ALL BY NAME (SELECT t2.b AS b, t2.c AS c FROM t2 AS t2 INNER UNION ALL BY NAME (SELECT t3.c AS c, t3.d AS d FROM t3 AS t3 FULL OUTER UNION ALL BY NAME SELECT t4.e AS e, t4.f AS f FROM t4 AS t4))) AS _q_0);
|
|
404
|
+
|
|
405
|
+
# Title: Nested set operations with different modifiers (FULL + LEFT)
|
|
406
|
+
# dialect: bigquery
|
|
407
|
+
# execute: false
|
|
408
|
+
WITH t1 AS (SELECT 1 AS a, 2 AS b, 3 AS c, 4 AS d), t2 AS (SELECT 2 AS b, 3 AS c), t3 AS (SELECT 2 AS c, 3 AS d), t4 AS (SELECT 2 AS d, 3 AS e) SELECT * FROM ((SELECT * FROM t1 FULL OUTER UNION ALL BY NAME (SELECT * FROM t2 FULL UNION ALL BY NAME (SELECT * FROM t3 LEFT UNION ALL BY NAME SELECT * FROM t4))));
|
|
409
|
+
WITH t1 AS (SELECT 1 AS a, 2 AS b, 3 AS c, 4 AS d), t2 AS (SELECT 2 AS b, 3 AS c), t3 AS (SELECT 2 AS c, 3 AS d), t4 AS (SELECT 2 AS d, 3 AS e) SELECT _q_0.a AS a, _q_0.b AS b, _q_0.c AS c, _q_0.d AS d FROM ((SELECT t1.a AS a, t1.b AS b, t1.c AS c, t1.d AS d FROM t1 AS t1 FULL OUTER UNION ALL BY NAME (SELECT t2.b AS b, t2.c AS c FROM t2 AS t2 FULL UNION ALL BY NAME (SELECT t3.c AS c, t3.d AS d FROM t3 AS t3 LEFT UNION ALL BY NAME SELECT t4.d AS d, t4.e AS e FROM t4 AS t4))) AS _q_0);
|
|
410
|
+
|
|
392
411
|
--------------------------------------
|
|
393
412
|
-- Subqueries
|
|
394
413
|
--------------------------------------
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|