sqlglot 27.19.0__tar.gz → 27.20.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.19.0 → sqlglot-27.20.0}/CHANGELOG.md +41 -0
- {sqlglot-27.19.0 → sqlglot-27.20.0}/Makefile +8 -2
- {sqlglot-27.19.0 → sqlglot-27.20.0}/PKG-INFO +3 -1
- {sqlglot-27.19.0 → sqlglot-27.20.0}/README.md +2 -0
- {sqlglot-27.19.0 → sqlglot-27.20.0}/sqlglot/_version.py +3 -3
- {sqlglot-27.19.0 → sqlglot-27.20.0}/sqlglot/dialects/snowflake.py +21 -0
- {sqlglot-27.19.0 → sqlglot-27.20.0}/sqlglot/dialects/sqlite.py +9 -0
- {sqlglot-27.19.0 → sqlglot-27.20.0}/sqlglot/dialects/starrocks.py +3 -0
- {sqlglot-27.19.0 → sqlglot-27.20.0}/sqlglot/expressions.py +78 -25
- {sqlglot-27.19.0 → sqlglot-27.20.0}/sqlglot/generator.py +3 -0
- {sqlglot-27.19.0 → sqlglot-27.20.0}/sqlglot/helper.py +0 -18
- {sqlglot-27.19.0 → sqlglot-27.20.0}/sqlglot/parser.py +1 -1
- {sqlglot-27.19.0 → sqlglot-27.20.0}/sqlglot.egg-info/PKG-INFO +3 -1
- {sqlglot-27.19.0 → sqlglot-27.20.0}/tests/dialects/test_snowflake.py +23 -0
- {sqlglot-27.19.0 → sqlglot-27.20.0}/tests/dialects/test_sqlite.py +1 -0
- {sqlglot-27.19.0 → sqlglot-27.20.0}/tests/dialects/test_starrocks.py +3 -0
- {sqlglot-27.19.0 → sqlglot-27.20.0}/tests/fixtures/optimizer/annotate_functions.sql +44 -0
- {sqlglot-27.19.0 → sqlglot-27.20.0}/tests/test_expressions.py +8 -0
- {sqlglot-27.19.0 → sqlglot-27.20.0}/.gitignore +0 -0
- {sqlglot-27.19.0 → sqlglot-27.20.0}/.gitpod.yml +0 -0
- {sqlglot-27.19.0 → sqlglot-27.20.0}/.pre-commit-config.yaml +0 -0
- {sqlglot-27.19.0 → sqlglot-27.20.0}/CONTRIBUTING.md +0 -0
- {sqlglot-27.19.0 → sqlglot-27.20.0}/LICENSE +0 -0
- {sqlglot-27.19.0 → sqlglot-27.20.0}/MANIFEST.in +0 -0
- {sqlglot-27.19.0 → sqlglot-27.20.0}/pyproject.toml +0 -0
- {sqlglot-27.19.0 → sqlglot-27.20.0}/setup.cfg +0 -0
- {sqlglot-27.19.0 → sqlglot-27.20.0}/setup.py +0 -0
- {sqlglot-27.19.0 → sqlglot-27.20.0}/sqlglot/__init__.py +0 -0
- {sqlglot-27.19.0 → sqlglot-27.20.0}/sqlglot/__main__.py +0 -0
- {sqlglot-27.19.0 → sqlglot-27.20.0}/sqlglot/_typing.py +0 -0
- {sqlglot-27.19.0 → sqlglot-27.20.0}/sqlglot/dialects/__init__.py +0 -0
- {sqlglot-27.19.0 → sqlglot-27.20.0}/sqlglot/dialects/athena.py +0 -0
- {sqlglot-27.19.0 → sqlglot-27.20.0}/sqlglot/dialects/bigquery.py +0 -0
- {sqlglot-27.19.0 → sqlglot-27.20.0}/sqlglot/dialects/clickhouse.py +0 -0
- {sqlglot-27.19.0 → sqlglot-27.20.0}/sqlglot/dialects/databricks.py +0 -0
- {sqlglot-27.19.0 → sqlglot-27.20.0}/sqlglot/dialects/dialect.py +0 -0
- {sqlglot-27.19.0 → sqlglot-27.20.0}/sqlglot/dialects/doris.py +0 -0
- {sqlglot-27.19.0 → sqlglot-27.20.0}/sqlglot/dialects/dremio.py +0 -0
- {sqlglot-27.19.0 → sqlglot-27.20.0}/sqlglot/dialects/drill.py +0 -0
- {sqlglot-27.19.0 → sqlglot-27.20.0}/sqlglot/dialects/druid.py +0 -0
- {sqlglot-27.19.0 → sqlglot-27.20.0}/sqlglot/dialects/duckdb.py +0 -0
- {sqlglot-27.19.0 → sqlglot-27.20.0}/sqlglot/dialects/dune.py +0 -0
- {sqlglot-27.19.0 → sqlglot-27.20.0}/sqlglot/dialects/exasol.py +0 -0
- {sqlglot-27.19.0 → sqlglot-27.20.0}/sqlglot/dialects/fabric.py +0 -0
- {sqlglot-27.19.0 → sqlglot-27.20.0}/sqlglot/dialects/hive.py +0 -0
- {sqlglot-27.19.0 → sqlglot-27.20.0}/sqlglot/dialects/materialize.py +0 -0
- {sqlglot-27.19.0 → sqlglot-27.20.0}/sqlglot/dialects/mysql.py +0 -0
- {sqlglot-27.19.0 → sqlglot-27.20.0}/sqlglot/dialects/oracle.py +0 -0
- {sqlglot-27.19.0 → sqlglot-27.20.0}/sqlglot/dialects/postgres.py +0 -0
- {sqlglot-27.19.0 → sqlglot-27.20.0}/sqlglot/dialects/presto.py +0 -0
- {sqlglot-27.19.0 → sqlglot-27.20.0}/sqlglot/dialects/prql.py +0 -0
- {sqlglot-27.19.0 → sqlglot-27.20.0}/sqlglot/dialects/redshift.py +0 -0
- {sqlglot-27.19.0 → sqlglot-27.20.0}/sqlglot/dialects/risingwave.py +0 -0
- {sqlglot-27.19.0 → sqlglot-27.20.0}/sqlglot/dialects/singlestore.py +0 -0
- {sqlglot-27.19.0 → sqlglot-27.20.0}/sqlglot/dialects/solr.py +0 -0
- {sqlglot-27.19.0 → sqlglot-27.20.0}/sqlglot/dialects/spark.py +0 -0
- {sqlglot-27.19.0 → sqlglot-27.20.0}/sqlglot/dialects/spark2.py +0 -0
- {sqlglot-27.19.0 → sqlglot-27.20.0}/sqlglot/dialects/tableau.py +0 -0
- {sqlglot-27.19.0 → sqlglot-27.20.0}/sqlglot/dialects/teradata.py +0 -0
- {sqlglot-27.19.0 → sqlglot-27.20.0}/sqlglot/dialects/trino.py +0 -0
- {sqlglot-27.19.0 → sqlglot-27.20.0}/sqlglot/dialects/tsql.py +0 -0
- {sqlglot-27.19.0 → sqlglot-27.20.0}/sqlglot/diff.py +0 -0
- {sqlglot-27.19.0 → sqlglot-27.20.0}/sqlglot/errors.py +0 -0
- {sqlglot-27.19.0 → sqlglot-27.20.0}/sqlglot/executor/__init__.py +0 -0
- {sqlglot-27.19.0 → sqlglot-27.20.0}/sqlglot/executor/context.py +0 -0
- {sqlglot-27.19.0 → sqlglot-27.20.0}/sqlglot/executor/env.py +0 -0
- {sqlglot-27.19.0 → sqlglot-27.20.0}/sqlglot/executor/python.py +0 -0
- {sqlglot-27.19.0 → sqlglot-27.20.0}/sqlglot/executor/table.py +0 -0
- {sqlglot-27.19.0 → sqlglot-27.20.0}/sqlglot/jsonpath.py +0 -0
- {sqlglot-27.19.0 → sqlglot-27.20.0}/sqlglot/lineage.py +0 -0
- {sqlglot-27.19.0 → sqlglot-27.20.0}/sqlglot/optimizer/__init__.py +0 -0
- {sqlglot-27.19.0 → sqlglot-27.20.0}/sqlglot/optimizer/annotate_types.py +0 -0
- {sqlglot-27.19.0 → sqlglot-27.20.0}/sqlglot/optimizer/canonicalize.py +0 -0
- {sqlglot-27.19.0 → sqlglot-27.20.0}/sqlglot/optimizer/eliminate_ctes.py +0 -0
- {sqlglot-27.19.0 → sqlglot-27.20.0}/sqlglot/optimizer/eliminate_joins.py +0 -0
- {sqlglot-27.19.0 → sqlglot-27.20.0}/sqlglot/optimizer/eliminate_subqueries.py +0 -0
- {sqlglot-27.19.0 → sqlglot-27.20.0}/sqlglot/optimizer/isolate_table_selects.py +0 -0
- {sqlglot-27.19.0 → sqlglot-27.20.0}/sqlglot/optimizer/merge_subqueries.py +0 -0
- {sqlglot-27.19.0 → sqlglot-27.20.0}/sqlglot/optimizer/normalize.py +0 -0
- {sqlglot-27.19.0 → sqlglot-27.20.0}/sqlglot/optimizer/normalize_identifiers.py +0 -0
- {sqlglot-27.19.0 → sqlglot-27.20.0}/sqlglot/optimizer/optimize_joins.py +0 -0
- {sqlglot-27.19.0 → sqlglot-27.20.0}/sqlglot/optimizer/optimizer.py +0 -0
- {sqlglot-27.19.0 → sqlglot-27.20.0}/sqlglot/optimizer/pushdown_predicates.py +0 -0
- {sqlglot-27.19.0 → sqlglot-27.20.0}/sqlglot/optimizer/pushdown_projections.py +0 -0
- {sqlglot-27.19.0 → sqlglot-27.20.0}/sqlglot/optimizer/qualify.py +0 -0
- {sqlglot-27.19.0 → sqlglot-27.20.0}/sqlglot/optimizer/qualify_columns.py +0 -0
- {sqlglot-27.19.0 → sqlglot-27.20.0}/sqlglot/optimizer/qualify_tables.py +0 -0
- {sqlglot-27.19.0 → sqlglot-27.20.0}/sqlglot/optimizer/scope.py +0 -0
- {sqlglot-27.19.0 → sqlglot-27.20.0}/sqlglot/optimizer/simplify.py +0 -0
- {sqlglot-27.19.0 → sqlglot-27.20.0}/sqlglot/optimizer/unnest_subqueries.py +0 -0
- {sqlglot-27.19.0 → sqlglot-27.20.0}/sqlglot/planner.py +0 -0
- {sqlglot-27.19.0 → sqlglot-27.20.0}/sqlglot/py.typed +0 -0
- {sqlglot-27.19.0 → sqlglot-27.20.0}/sqlglot/schema.py +0 -0
- {sqlglot-27.19.0 → sqlglot-27.20.0}/sqlglot/serde.py +0 -0
- {sqlglot-27.19.0 → sqlglot-27.20.0}/sqlglot/time.py +0 -0
- {sqlglot-27.19.0 → sqlglot-27.20.0}/sqlglot/tokens.py +0 -0
- {sqlglot-27.19.0 → sqlglot-27.20.0}/sqlglot/transforms.py +0 -0
- {sqlglot-27.19.0 → sqlglot-27.20.0}/sqlglot/trie.py +0 -0
- {sqlglot-27.19.0 → sqlglot-27.20.0}/sqlglot.egg-info/SOURCES.txt +0 -0
- {sqlglot-27.19.0 → sqlglot-27.20.0}/sqlglot.egg-info/dependency_links.txt +0 -0
- {sqlglot-27.19.0 → sqlglot-27.20.0}/sqlglot.egg-info/requires.txt +0 -0
- {sqlglot-27.19.0 → sqlglot-27.20.0}/sqlglot.egg-info/top_level.txt +0 -0
- {sqlglot-27.19.0 → sqlglot-27.20.0}/sqlglot.png +0 -0
- {sqlglot-27.19.0 → sqlglot-27.20.0}/sqlglotrs/Cargo.lock +0 -0
- {sqlglot-27.19.0 → sqlglot-27.20.0}/sqlglotrs/Cargo.toml +0 -0
- {sqlglot-27.19.0 → sqlglot-27.20.0}/sqlglotrs/benches/dialect_settings.json +0 -0
- {sqlglot-27.19.0 → sqlglot-27.20.0}/sqlglotrs/benches/long.rs +0 -0
- {sqlglot-27.19.0 → sqlglot-27.20.0}/sqlglotrs/benches/token_type_settings.json +0 -0
- {sqlglot-27.19.0 → sqlglot-27.20.0}/sqlglotrs/benches/tokenizer_dialect_settings.json +0 -0
- {sqlglot-27.19.0 → sqlglot-27.20.0}/sqlglotrs/benches/tokenizer_settings.json +0 -0
- {sqlglot-27.19.0 → sqlglot-27.20.0}/sqlglotrs/pyproject.toml +0 -0
- {sqlglot-27.19.0 → sqlglot-27.20.0}/sqlglotrs/src/lib.rs +0 -0
- {sqlglot-27.19.0 → sqlglot-27.20.0}/sqlglotrs/src/settings.rs +0 -0
- {sqlglot-27.19.0 → sqlglot-27.20.0}/sqlglotrs/src/token.rs +0 -0
- {sqlglot-27.19.0 → sqlglot-27.20.0}/sqlglotrs/src/tokenizer.rs +0 -0
- {sqlglot-27.19.0 → sqlglot-27.20.0}/sqlglotrs/src/trie.rs +0 -0
- {sqlglot-27.19.0 → sqlglot-27.20.0}/tests/__init__.py +0 -0
- {sqlglot-27.19.0 → sqlglot-27.20.0}/tests/dialects/__init__.py +0 -0
- {sqlglot-27.19.0 → sqlglot-27.20.0}/tests/dialects/test_athena.py +0 -0
- {sqlglot-27.19.0 → sqlglot-27.20.0}/tests/dialects/test_bigquery.py +0 -0
- {sqlglot-27.19.0 → sqlglot-27.20.0}/tests/dialects/test_clickhouse.py +0 -0
- {sqlglot-27.19.0 → sqlglot-27.20.0}/tests/dialects/test_databricks.py +0 -0
- {sqlglot-27.19.0 → sqlglot-27.20.0}/tests/dialects/test_dialect.py +0 -0
- {sqlglot-27.19.0 → sqlglot-27.20.0}/tests/dialects/test_doris.py +0 -0
- {sqlglot-27.19.0 → sqlglot-27.20.0}/tests/dialects/test_dremio.py +0 -0
- {sqlglot-27.19.0 → sqlglot-27.20.0}/tests/dialects/test_drill.py +0 -0
- {sqlglot-27.19.0 → sqlglot-27.20.0}/tests/dialects/test_druid.py +0 -0
- {sqlglot-27.19.0 → sqlglot-27.20.0}/tests/dialects/test_duckdb.py +0 -0
- {sqlglot-27.19.0 → sqlglot-27.20.0}/tests/dialects/test_dune.py +0 -0
- {sqlglot-27.19.0 → sqlglot-27.20.0}/tests/dialects/test_exasol.py +0 -0
- {sqlglot-27.19.0 → sqlglot-27.20.0}/tests/dialects/test_fabric.py +0 -0
- {sqlglot-27.19.0 → sqlglot-27.20.0}/tests/dialects/test_hive.py +0 -0
- {sqlglot-27.19.0 → sqlglot-27.20.0}/tests/dialects/test_materialize.py +0 -0
- {sqlglot-27.19.0 → sqlglot-27.20.0}/tests/dialects/test_mysql.py +0 -0
- {sqlglot-27.19.0 → sqlglot-27.20.0}/tests/dialects/test_oracle.py +0 -0
- {sqlglot-27.19.0 → sqlglot-27.20.0}/tests/dialects/test_pipe_syntax.py +0 -0
- {sqlglot-27.19.0 → sqlglot-27.20.0}/tests/dialects/test_postgres.py +0 -0
- {sqlglot-27.19.0 → sqlglot-27.20.0}/tests/dialects/test_presto.py +0 -0
- {sqlglot-27.19.0 → sqlglot-27.20.0}/tests/dialects/test_prql.py +0 -0
- {sqlglot-27.19.0 → sqlglot-27.20.0}/tests/dialects/test_redshift.py +0 -0
- {sqlglot-27.19.0 → sqlglot-27.20.0}/tests/dialects/test_risingwave.py +0 -0
- {sqlglot-27.19.0 → sqlglot-27.20.0}/tests/dialects/test_singlestore.py +0 -0
- {sqlglot-27.19.0 → sqlglot-27.20.0}/tests/dialects/test_solr.py +0 -0
- {sqlglot-27.19.0 → sqlglot-27.20.0}/tests/dialects/test_spark.py +0 -0
- {sqlglot-27.19.0 → sqlglot-27.20.0}/tests/dialects/test_tableau.py +0 -0
- {sqlglot-27.19.0 → sqlglot-27.20.0}/tests/dialects/test_teradata.py +0 -0
- {sqlglot-27.19.0 → sqlglot-27.20.0}/tests/dialects/test_trino.py +0 -0
- {sqlglot-27.19.0 → sqlglot-27.20.0}/tests/dialects/test_tsql.py +0 -0
- {sqlglot-27.19.0 → sqlglot-27.20.0}/tests/fixtures/identity.sql +0 -0
- {sqlglot-27.19.0 → sqlglot-27.20.0}/tests/fixtures/jsonpath/LICENSE +0 -0
- {sqlglot-27.19.0 → sqlglot-27.20.0}/tests/fixtures/jsonpath/cts.json +0 -0
- {sqlglot-27.19.0 → sqlglot-27.20.0}/tests/fixtures/optimizer/annotate_types.sql +0 -0
- {sqlglot-27.19.0 → sqlglot-27.20.0}/tests/fixtures/optimizer/canonicalize.sql +0 -0
- {sqlglot-27.19.0 → sqlglot-27.20.0}/tests/fixtures/optimizer/eliminate_ctes.sql +0 -0
- {sqlglot-27.19.0 → sqlglot-27.20.0}/tests/fixtures/optimizer/eliminate_joins.sql +0 -0
- {sqlglot-27.19.0 → sqlglot-27.20.0}/tests/fixtures/optimizer/eliminate_subqueries.sql +0 -0
- {sqlglot-27.19.0 → sqlglot-27.20.0}/tests/fixtures/optimizer/isolate_table_selects.sql +0 -0
- {sqlglot-27.19.0 → sqlglot-27.20.0}/tests/fixtures/optimizer/merge_subqueries.sql +0 -0
- {sqlglot-27.19.0 → sqlglot-27.20.0}/tests/fixtures/optimizer/normalize.sql +0 -0
- {sqlglot-27.19.0 → sqlglot-27.20.0}/tests/fixtures/optimizer/normalize_identifiers.sql +0 -0
- {sqlglot-27.19.0 → sqlglot-27.20.0}/tests/fixtures/optimizer/optimize_joins.sql +0 -0
- {sqlglot-27.19.0 → sqlglot-27.20.0}/tests/fixtures/optimizer/optimizer.sql +0 -0
- {sqlglot-27.19.0 → sqlglot-27.20.0}/tests/fixtures/optimizer/pushdown_cte_alias_columns.sql +0 -0
- {sqlglot-27.19.0 → sqlglot-27.20.0}/tests/fixtures/optimizer/pushdown_predicates.sql +0 -0
- {sqlglot-27.19.0 → sqlglot-27.20.0}/tests/fixtures/optimizer/pushdown_projections.sql +0 -0
- {sqlglot-27.19.0 → sqlglot-27.20.0}/tests/fixtures/optimizer/qualify_columns.sql +0 -0
- {sqlglot-27.19.0 → sqlglot-27.20.0}/tests/fixtures/optimizer/qualify_columns__invalid.sql +0 -0
- {sqlglot-27.19.0 → sqlglot-27.20.0}/tests/fixtures/optimizer/qualify_columns__with_invisible.sql +0 -0
- {sqlglot-27.19.0 → sqlglot-27.20.0}/tests/fixtures/optimizer/qualify_columns_ddl.sql +0 -0
- {sqlglot-27.19.0 → sqlglot-27.20.0}/tests/fixtures/optimizer/qualify_tables.sql +0 -0
- {sqlglot-27.19.0 → sqlglot-27.20.0}/tests/fixtures/optimizer/quote_identifiers.sql +0 -0
- {sqlglot-27.19.0 → sqlglot-27.20.0}/tests/fixtures/optimizer/simplify.sql +0 -0
- {sqlglot-27.19.0 → sqlglot-27.20.0}/tests/fixtures/optimizer/tpc-ds/call_center.csv.gz +0 -0
- {sqlglot-27.19.0 → sqlglot-27.20.0}/tests/fixtures/optimizer/tpc-ds/catalog_page.csv.gz +0 -0
- {sqlglot-27.19.0 → sqlglot-27.20.0}/tests/fixtures/optimizer/tpc-ds/catalog_returns.csv.gz +0 -0
- {sqlglot-27.19.0 → sqlglot-27.20.0}/tests/fixtures/optimizer/tpc-ds/catalog_sales.csv.gz +0 -0
- {sqlglot-27.19.0 → sqlglot-27.20.0}/tests/fixtures/optimizer/tpc-ds/customer.csv.gz +0 -0
- {sqlglot-27.19.0 → sqlglot-27.20.0}/tests/fixtures/optimizer/tpc-ds/customer_address.csv.gz +0 -0
- {sqlglot-27.19.0 → sqlglot-27.20.0}/tests/fixtures/optimizer/tpc-ds/customer_demographics.csv.gz +0 -0
- {sqlglot-27.19.0 → sqlglot-27.20.0}/tests/fixtures/optimizer/tpc-ds/date_dim.csv.gz +0 -0
- {sqlglot-27.19.0 → sqlglot-27.20.0}/tests/fixtures/optimizer/tpc-ds/household_demographics.csv.gz +0 -0
- {sqlglot-27.19.0 → sqlglot-27.20.0}/tests/fixtures/optimizer/tpc-ds/income_band.csv.gz +0 -0
- {sqlglot-27.19.0 → sqlglot-27.20.0}/tests/fixtures/optimizer/tpc-ds/inventory.csv.gz +0 -0
- {sqlglot-27.19.0 → sqlglot-27.20.0}/tests/fixtures/optimizer/tpc-ds/item.csv.gz +0 -0
- {sqlglot-27.19.0 → sqlglot-27.20.0}/tests/fixtures/optimizer/tpc-ds/promotion.csv.gz +0 -0
- {sqlglot-27.19.0 → sqlglot-27.20.0}/tests/fixtures/optimizer/tpc-ds/reason.csv.gz +0 -0
- {sqlglot-27.19.0 → sqlglot-27.20.0}/tests/fixtures/optimizer/tpc-ds/ship_mode.csv.gz +0 -0
- {sqlglot-27.19.0 → sqlglot-27.20.0}/tests/fixtures/optimizer/tpc-ds/store.csv.gz +0 -0
- {sqlglot-27.19.0 → sqlglot-27.20.0}/tests/fixtures/optimizer/tpc-ds/store_returns.csv.gz +0 -0
- {sqlglot-27.19.0 → sqlglot-27.20.0}/tests/fixtures/optimizer/tpc-ds/store_sales.csv.gz +0 -0
- {sqlglot-27.19.0 → sqlglot-27.20.0}/tests/fixtures/optimizer/tpc-ds/time_dim.csv.gz +0 -0
- {sqlglot-27.19.0 → sqlglot-27.20.0}/tests/fixtures/optimizer/tpc-ds/tpc-ds.sql +0 -0
- {sqlglot-27.19.0 → sqlglot-27.20.0}/tests/fixtures/optimizer/tpc-ds/warehouse.csv.gz +0 -0
- {sqlglot-27.19.0 → sqlglot-27.20.0}/tests/fixtures/optimizer/tpc-ds/web_page.csv.gz +0 -0
- {sqlglot-27.19.0 → sqlglot-27.20.0}/tests/fixtures/optimizer/tpc-ds/web_returns.csv.gz +0 -0
- {sqlglot-27.19.0 → sqlglot-27.20.0}/tests/fixtures/optimizer/tpc-ds/web_sales.csv.gz +0 -0
- {sqlglot-27.19.0 → sqlglot-27.20.0}/tests/fixtures/optimizer/tpc-ds/web_site.csv.gz +0 -0
- {sqlglot-27.19.0 → sqlglot-27.20.0}/tests/fixtures/optimizer/tpc-h/customer.csv.gz +0 -0
- {sqlglot-27.19.0 → sqlglot-27.20.0}/tests/fixtures/optimizer/tpc-h/lineitem.csv.gz +0 -0
- {sqlglot-27.19.0 → sqlglot-27.20.0}/tests/fixtures/optimizer/tpc-h/nation.csv.gz +0 -0
- {sqlglot-27.19.0 → sqlglot-27.20.0}/tests/fixtures/optimizer/tpc-h/orders.csv.gz +0 -0
- {sqlglot-27.19.0 → sqlglot-27.20.0}/tests/fixtures/optimizer/tpc-h/part.csv.gz +0 -0
- {sqlglot-27.19.0 → sqlglot-27.20.0}/tests/fixtures/optimizer/tpc-h/partsupp.csv.gz +0 -0
- {sqlglot-27.19.0 → sqlglot-27.20.0}/tests/fixtures/optimizer/tpc-h/region.csv.gz +0 -0
- {sqlglot-27.19.0 → sqlglot-27.20.0}/tests/fixtures/optimizer/tpc-h/supplier.csv.gz +0 -0
- {sqlglot-27.19.0 → sqlglot-27.20.0}/tests/fixtures/optimizer/tpc-h/tpc-h.sql +0 -0
- {sqlglot-27.19.0 → sqlglot-27.20.0}/tests/fixtures/optimizer/unnest_subqueries.sql +0 -0
- {sqlglot-27.19.0 → sqlglot-27.20.0}/tests/fixtures/partial.sql +0 -0
- {sqlglot-27.19.0 → sqlglot-27.20.0}/tests/fixtures/pretty.sql +0 -0
- {sqlglot-27.19.0 → sqlglot-27.20.0}/tests/gen_fixtures.py +0 -0
- {sqlglot-27.19.0 → sqlglot-27.20.0}/tests/helpers.py +0 -0
- {sqlglot-27.19.0 → sqlglot-27.20.0}/tests/test_build.py +0 -0
- {sqlglot-27.19.0 → sqlglot-27.20.0}/tests/test_dialect_imports.py +0 -0
- {sqlglot-27.19.0 → sqlglot-27.20.0}/tests/test_diff.py +0 -0
- {sqlglot-27.19.0 → sqlglot-27.20.0}/tests/test_docs.py +0 -0
- {sqlglot-27.19.0 → sqlglot-27.20.0}/tests/test_executor.py +0 -0
- {sqlglot-27.19.0 → sqlglot-27.20.0}/tests/test_generator.py +0 -0
- {sqlglot-27.19.0 → sqlglot-27.20.0}/tests/test_helper.py +0 -0
- {sqlglot-27.19.0 → sqlglot-27.20.0}/tests/test_jsonpath.py +0 -0
- {sqlglot-27.19.0 → sqlglot-27.20.0}/tests/test_lineage.py +0 -0
- {sqlglot-27.19.0 → sqlglot-27.20.0}/tests/test_optimizer.py +0 -0
- {sqlglot-27.19.0 → sqlglot-27.20.0}/tests/test_parser.py +0 -0
- {sqlglot-27.19.0 → sqlglot-27.20.0}/tests/test_schema.py +0 -0
- {sqlglot-27.19.0 → sqlglot-27.20.0}/tests/test_serde.py +0 -0
- {sqlglot-27.19.0 → sqlglot-27.20.0}/tests/test_time.py +0 -0
- {sqlglot-27.19.0 → sqlglot-27.20.0}/tests/test_tokens.py +0 -0
- {sqlglot-27.19.0 → sqlglot-27.20.0}/tests/test_transforms.py +0 -0
- {sqlglot-27.19.0 → sqlglot-27.20.0}/tests/test_transpile.py +0 -0
|
@@ -1,6 +1,46 @@
|
|
|
1
1
|
Changelog
|
|
2
2
|
=========
|
|
3
3
|
|
|
4
|
+
## [v27.19.0] - 2025-09-26
|
|
5
|
+
### :boom: BREAKING CHANGES
|
|
6
|
+
- due to [`68473ac`](https://github.com/tobymao/sqlglot/commit/68473ac3ec8dc76512dc76819892a1b0324c7ddc) - Annotate type for snowflake PARSE_URL function *(PR [#5962](https://github.com/tobymao/sqlglot/pull/5962) by [@fivetran-amrutabhimsenayachit](https://github.com/fivetran-amrutabhimsenayachit))*:
|
|
7
|
+
|
|
8
|
+
Annotate type for snowflake PARSE_URL function (#5962)
|
|
9
|
+
|
|
10
|
+
- due to [`b015a9d`](https://github.com/tobymao/sqlglot/commit/b015a9d944d0a87069a7750ad74953c399d7da34) - annotate type for Snowflake REGEXP_INSTR function *(commit by [@fivetran-BradfordPaskewitz](https://github.com/fivetran-BradfordPaskewitz))*:
|
|
11
|
+
|
|
12
|
+
annotate type for Snowflake REGEXP_INSTR function
|
|
13
|
+
|
|
14
|
+
- due to [`1f29ba7`](https://github.com/tobymao/sqlglot/commit/1f29ba710f4213beb1a2f993244d7d824f3536ce) - annotate type for Snowflake PARSE_IP function *(PR [#5961](https://github.com/tobymao/sqlglot/pull/5961) by [@fivetran-BradfordPaskewitz](https://github.com/fivetran-BradfordPaskewitz))*:
|
|
15
|
+
|
|
16
|
+
annotate type for Snowflake PARSE_IP function (#5961)
|
|
17
|
+
|
|
18
|
+
- due to [`bf45d5d`](https://github.com/tobymao/sqlglot/commit/bf45d5d3cb0c0f380824019eb32ec29049268a61) - annotate types for Snowflake RTRIMMED_LENGTH function *(PR [#5968](https://github.com/tobymao/sqlglot/pull/5968) by [@fivetran-BradfordPaskewitz](https://github.com/fivetran-BradfordPaskewitz))*:
|
|
19
|
+
|
|
20
|
+
annotate types for Snowflake RTRIMMED_LENGTH function (#5968)
|
|
21
|
+
|
|
22
|
+
- due to [`13caa69`](https://github.com/tobymao/sqlglot/commit/13caa6991f003ad7abb590073451e591b6fd888c) - Annotate type for snowflake POSITION function *(PR [#5964](https://github.com/tobymao/sqlglot/pull/5964) by [@fivetran-amrutabhimsenayachit](https://github.com/fivetran-amrutabhimsenayachit))*:
|
|
23
|
+
|
|
24
|
+
Annotate type for snowflake POSITION function (#5964)
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
### :sparkles: New Features
|
|
28
|
+
- [`88e4e4c`](https://github.com/tobymao/sqlglot/commit/88e4e4c55f3a113127eb3c82c0be46c29bcf15ab) - **optimizer**: Annotate type for OCTET_LENGTH function *(PR [#5960](https://github.com/tobymao/sqlglot/pull/5960) by [@fivetran-amrutabhimsenayachit](https://github.com/fivetran-amrutabhimsenayachit))*
|
|
29
|
+
- [`68473ac`](https://github.com/tobymao/sqlglot/commit/68473ac3ec8dc76512dc76819892a1b0324c7ddc) - **optimizer**: Annotate type for snowflake PARSE_URL function *(PR [#5962](https://github.com/tobymao/sqlglot/pull/5962) by [@fivetran-amrutabhimsenayachit](https://github.com/fivetran-amrutabhimsenayachit))*
|
|
30
|
+
- [`b015a9d`](https://github.com/tobymao/sqlglot/commit/b015a9d944d0a87069a7750ad74953c399d7da34) - **optimizer**: annotate type for Snowflake REGEXP_INSTR function *(commit by [@fivetran-BradfordPaskewitz](https://github.com/fivetran-BradfordPaskewitz))*
|
|
31
|
+
- [`1f29ba7`](https://github.com/tobymao/sqlglot/commit/1f29ba710f4213beb1a2f993244d7d824f3536ce) - **optimizer**: annotate type for Snowflake PARSE_IP function *(PR [#5961](https://github.com/tobymao/sqlglot/pull/5961) by [@fivetran-BradfordPaskewitz](https://github.com/fivetran-BradfordPaskewitz))*
|
|
32
|
+
- [`bf45d5d`](https://github.com/tobymao/sqlglot/commit/bf45d5d3cb0c0f380824019eb32ec29049268a61) - **optimizer**: annotate types for Snowflake RTRIMMED_LENGTH function *(PR [#5968](https://github.com/tobymao/sqlglot/pull/5968) by [@fivetran-BradfordPaskewitz](https://github.com/fivetran-BradfordPaskewitz))*
|
|
33
|
+
- [`13caa69`](https://github.com/tobymao/sqlglot/commit/13caa6991f003ad7abb590073451e591b6fd888c) - **optimizer**: Annotate type for snowflake POSITION function *(PR [#5964](https://github.com/tobymao/sqlglot/pull/5964) by [@fivetran-amrutabhimsenayachit](https://github.com/fivetran-amrutabhimsenayachit))*
|
|
34
|
+
- [`1471306`](https://github.com/tobymao/sqlglot/commit/1471306ed317830c294e3654075f55424d14bf5a) - support parse into grant principal and privilege *(PR [#5971](https://github.com/tobymao/sqlglot/pull/5971) by [@eakmanrq](https://github.com/eakmanrq))*
|
|
35
|
+
|
|
36
|
+
### :bug: Bug Fixes
|
|
37
|
+
- [`5432976`](https://github.com/tobymao/sqlglot/commit/543297680755344185e0f306843bc4909f4f75ed) - **bigquery**: allow GRANT as an id var *(PR [#5965](https://github.com/tobymao/sqlglot/pull/5965) by [@treysp](https://github.com/treysp))*
|
|
38
|
+
|
|
39
|
+
### :wrench: Chores
|
|
40
|
+
- [`1514bc6`](https://github.com/tobymao/sqlglot/commit/1514bc640ec129a96aedd9e89bfd5d61e832d6b1) - **optimizer**: add type inference tests for Snowflake RPAD function *(PR [#5967](https://github.com/tobymao/sqlglot/pull/5967) by [@fivetran-BradfordPaskewitz](https://github.com/fivetran-BradfordPaskewitz))*
|
|
41
|
+
- [`050b89d`](https://github.com/tobymao/sqlglot/commit/050b89deb9be842f2ddd07c78ea201ec4eae4779) - **optimizer**: Annotate type for snowflake regexp function *(PR [#5970](https://github.com/tobymao/sqlglot/pull/5970) by [@fivetran-amrutabhimsenayachit](https://github.com/fivetran-amrutabhimsenayachit))*
|
|
42
|
+
|
|
43
|
+
|
|
4
44
|
## [v27.18.0] - 2025-09-25
|
|
5
45
|
### :boom: BREAKING CHANGES
|
|
6
46
|
- due to [`7f13eaf`](https://github.com/tobymao/sqlglot/commit/7f13eaf7769a3381a56c9209af590835be2f95cd) - Annotate type for snowflake DECOMPRESS_BINARY function *(PR [#5945](https://github.com/tobymao/sqlglot/pull/5945) by [@fivetran-amrutabhimsenayachit](https://github.com/fivetran-amrutabhimsenayachit))*:
|
|
@@ -7520,3 +7560,4 @@ Changelog
|
|
|
7520
7560
|
[v27.16.3]: https://github.com/tobymao/sqlglot/compare/v27.16.2...v27.16.3
|
|
7521
7561
|
[v27.17.0]: https://github.com/tobymao/sqlglot/compare/v27.16.3...v27.17.0
|
|
7522
7562
|
[v27.18.0]: https://github.com/tobymao/sqlglot/compare/v27.17.0...v27.18.0
|
|
7563
|
+
[v27.19.0]: https://github.com/tobymao/sqlglot/compare/v27.18.0...v27.19.0
|
|
@@ -1,7 +1,13 @@
|
|
|
1
1
|
.PHONY: install install-dev install-pre-commit test unit style check docs docs-serve
|
|
2
2
|
|
|
3
|
+
ifdef UV
|
|
4
|
+
PIP := uv pip
|
|
5
|
+
else
|
|
6
|
+
PIP := pip
|
|
7
|
+
endif
|
|
8
|
+
|
|
3
9
|
install:
|
|
4
|
-
|
|
10
|
+
$(PIP) install -e .
|
|
5
11
|
|
|
6
12
|
bench: install-dev-rs-release
|
|
7
13
|
python -m benchmarks.bench
|
|
@@ -17,7 +23,7 @@ install-dev-rs:
|
|
|
17
23
|
cd sqlglotrs/ && python -m maturin develop
|
|
18
24
|
|
|
19
25
|
install-dev-core:
|
|
20
|
-
|
|
26
|
+
$(PIP) install -e ".[dev]"
|
|
21
27
|
|
|
22
28
|
install-dev: install-dev-core install-dev-rs
|
|
23
29
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: sqlglot
|
|
3
|
-
Version: 27.
|
|
3
|
+
Version: 27.20.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
|
|
@@ -89,12 +89,14 @@ pip3 install "sqlglot[rs]"
|
|
|
89
89
|
Or with a local checkout:
|
|
90
90
|
|
|
91
91
|
```
|
|
92
|
+
# Optionally prefix with UV=1 to use uv for the installation
|
|
92
93
|
make install
|
|
93
94
|
```
|
|
94
95
|
|
|
95
96
|
Requirements for development (optional):
|
|
96
97
|
|
|
97
98
|
```
|
|
99
|
+
# Optionally prefix with UV=1 to use uv for the installation
|
|
98
100
|
make install-dev
|
|
99
101
|
```
|
|
100
102
|
|
|
@@ -50,12 +50,14 @@ pip3 install "sqlglot[rs]"
|
|
|
50
50
|
Or with a local checkout:
|
|
51
51
|
|
|
52
52
|
```
|
|
53
|
+
# Optionally prefix with UV=1 to use uv for the installation
|
|
53
54
|
make install
|
|
54
55
|
```
|
|
55
56
|
|
|
56
57
|
Requirements for development (optional):
|
|
57
58
|
|
|
58
59
|
```
|
|
60
|
+
# Optionally prefix with UV=1 to use uv for the installation
|
|
59
61
|
make install-dev
|
|
60
62
|
```
|
|
61
63
|
|
|
@@ -28,7 +28,7 @@ version_tuple: VERSION_TUPLE
|
|
|
28
28
|
commit_id: COMMIT_ID
|
|
29
29
|
__commit_id__: COMMIT_ID
|
|
30
30
|
|
|
31
|
-
__version__ = version = '27.
|
|
32
|
-
__version_tuple__ = version_tuple = (27,
|
|
31
|
+
__version__ = version = '27.20.0'
|
|
32
|
+
__version_tuple__ = version_tuple = (27, 20, 0)
|
|
33
33
|
|
|
34
|
-
__commit_id__ = commit_id = '
|
|
34
|
+
__commit_id__ = commit_id = 'g0d772e0b9'
|
|
@@ -543,6 +543,7 @@ class Snowflake(Dialect):
|
|
|
543
543
|
exp.DataType.Type.VARCHAR: {
|
|
544
544
|
*Dialect.TYPE_TO_EXPRESSIONS[exp.DataType.Type.VARCHAR],
|
|
545
545
|
exp.Base64DecodeString,
|
|
546
|
+
exp.TryBase64DecodeString,
|
|
546
547
|
exp.Base64Encode,
|
|
547
548
|
exp.DecompressString,
|
|
548
549
|
exp.MD5,
|
|
@@ -553,6 +554,7 @@ class Snowflake(Dialect):
|
|
|
553
554
|
exp.Collate,
|
|
554
555
|
exp.Collation,
|
|
555
556
|
exp.HexDecodeString,
|
|
557
|
+
exp.TryHexDecodeString,
|
|
556
558
|
exp.HexEncode,
|
|
557
559
|
exp.Initcap,
|
|
558
560
|
exp.RegexpExtract,
|
|
@@ -561,12 +563,16 @@ class Snowflake(Dialect):
|
|
|
561
563
|
exp.Replace,
|
|
562
564
|
exp.SHA,
|
|
563
565
|
exp.SHA2,
|
|
566
|
+
exp.Soundex,
|
|
564
567
|
exp.Space,
|
|
568
|
+
exp.SplitPart,
|
|
565
569
|
exp.Uuid,
|
|
566
570
|
},
|
|
567
571
|
exp.DataType.Type.BINARY: {
|
|
568
572
|
*Dialect.TYPE_TO_EXPRESSIONS[exp.DataType.Type.BINARY],
|
|
569
573
|
exp.Base64DecodeBinary,
|
|
574
|
+
exp.TryBase64DecodeBinary,
|
|
575
|
+
exp.TryHexDecodeBinary,
|
|
570
576
|
exp.Compress,
|
|
571
577
|
exp.DecompressBinary,
|
|
572
578
|
exp.MD5Digest,
|
|
@@ -586,6 +592,9 @@ class Snowflake(Dialect):
|
|
|
586
592
|
exp.ParseUrl,
|
|
587
593
|
exp.ParseIp,
|
|
588
594
|
},
|
|
595
|
+
exp.DataType.Type.DECIMAL: {
|
|
596
|
+
exp.RegexpCount,
|
|
597
|
+
},
|
|
589
598
|
}
|
|
590
599
|
|
|
591
600
|
ANNOTATORS = {
|
|
@@ -607,6 +616,9 @@ class Snowflake(Dialect):
|
|
|
607
616
|
},
|
|
608
617
|
exp.ConcatWs: lambda self, e: self._annotate_by_args(e, "expressions"),
|
|
609
618
|
exp.Reverse: _annotate_reverse,
|
|
619
|
+
exp.RegexpCount: lambda self, e: self._annotate_with_type(
|
|
620
|
+
e, exp.DataType.build("NUMBER", dialect="snowflake")
|
|
621
|
+
),
|
|
610
622
|
}
|
|
611
623
|
|
|
612
624
|
TIME_MAPPING = {
|
|
@@ -793,6 +805,7 @@ class Snowflake(Dialect):
|
|
|
793
805
|
FUNCTION_PARSERS = {
|
|
794
806
|
**parser.Parser.FUNCTION_PARSERS,
|
|
795
807
|
"DATE_PART": lambda self: self._parse_date_part(),
|
|
808
|
+
"DIRECTORY": lambda self: self._parse_directory(),
|
|
796
809
|
"OBJECT_CONSTRUCT_KEEP_NULL": lambda self: self._parse_json_object(),
|
|
797
810
|
"LISTAGG": lambda self: self._parse_string_agg(),
|
|
798
811
|
"SEMANTIC_VIEW": lambda self: self._parse_semantic_view(),
|
|
@@ -902,6 +915,14 @@ class Snowflake(Dialect):
|
|
|
902
915
|
),
|
|
903
916
|
}
|
|
904
917
|
|
|
918
|
+
def _parse_directory(self) -> exp.DirectoryStage:
|
|
919
|
+
table = self._parse_table_parts()
|
|
920
|
+
|
|
921
|
+
if isinstance(table, exp.Table):
|
|
922
|
+
table = table.this
|
|
923
|
+
|
|
924
|
+
return self.expression(exp.DirectoryStage, this=table)
|
|
925
|
+
|
|
905
926
|
def _parse_use(self) -> exp.Use:
|
|
906
927
|
if self._match_text_seq("SECONDARY", "ROLES"):
|
|
907
928
|
this = self._match_texts(("ALL", "NONE")) and exp.var(self._prev.text.upper())
|
|
@@ -342,3 +342,12 @@ class SQLite(Dialect):
|
|
|
342
342
|
|
|
343
343
|
def respectnulls_sql(self, expression: exp.RespectNulls) -> str:
|
|
344
344
|
return self.sql(expression.this)
|
|
345
|
+
|
|
346
|
+
def windowspec_sql(self, expression: exp.WindowSpec) -> str:
|
|
347
|
+
if (
|
|
348
|
+
expression.text("kind").upper() == "RANGE"
|
|
349
|
+
and expression.text("start").upper() == "CURRENT ROW"
|
|
350
|
+
):
|
|
351
|
+
return "RANGE CURRENT ROW"
|
|
352
|
+
|
|
353
|
+
return super().windowspec_sql(expression)
|
|
@@ -32,6 +32,7 @@ def st_distance_sphere(self, expression: exp.StDistance) -> str:
|
|
|
32
32
|
|
|
33
33
|
class StarRocks(MySQL):
|
|
34
34
|
STRICT_JSON_PATH_SYNTAX = False
|
|
35
|
+
INDEX_OFFSET = 1
|
|
35
36
|
|
|
36
37
|
class Tokenizer(MySQL.Tokenizer):
|
|
37
38
|
KEYWORDS = {
|
|
@@ -49,6 +50,7 @@ class StarRocks(MySQL):
|
|
|
49
50
|
"DATE_DIFF": lambda args: exp.DateDiff(
|
|
50
51
|
this=seq_get(args, 1), expression=seq_get(args, 2), unit=seq_get(args, 0)
|
|
51
52
|
),
|
|
53
|
+
"ARRAY_FLATTEN": exp.Flatten.from_arg_list,
|
|
52
54
|
"REGEXP": exp.RegexpLike.from_arg_list,
|
|
53
55
|
}
|
|
54
56
|
|
|
@@ -152,6 +154,7 @@ class StarRocks(MySQL):
|
|
|
152
154
|
exp.DateDiff: lambda self, e: self.func(
|
|
153
155
|
"DATE_DIFF", unit_to_str(e), e.this, e.expression
|
|
154
156
|
),
|
|
157
|
+
exp.Flatten: rename_func("ARRAY_FLATTEN"),
|
|
155
158
|
exp.JSONExtractScalar: arrow_json_extract_sql,
|
|
156
159
|
exp.JSONExtract: arrow_json_extract_sql,
|
|
157
160
|
exp.Property: property_sql,
|
|
@@ -120,19 +120,43 @@ class Expression(metaclass=_Expression):
|
|
|
120
120
|
def __eq__(self, other) -> bool:
|
|
121
121
|
return type(self) is type(other) and hash(self) == hash(other)
|
|
122
122
|
|
|
123
|
-
@property
|
|
124
|
-
def hashable_args(self) -> t.Any:
|
|
125
|
-
return frozenset(
|
|
126
|
-
(k, tuple(_norm_arg(a) for a in v) if type(v) is list else _norm_arg(v))
|
|
127
|
-
for k, v in self.args.items()
|
|
128
|
-
if not (v is None or v is False or (type(v) is list and not v))
|
|
129
|
-
)
|
|
130
|
-
|
|
131
123
|
def __hash__(self) -> int:
|
|
132
|
-
if self._hash is
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
124
|
+
if self._hash is None:
|
|
125
|
+
nodes = []
|
|
126
|
+
queue = deque([self])
|
|
127
|
+
|
|
128
|
+
while queue:
|
|
129
|
+
node = queue.popleft()
|
|
130
|
+
nodes.append(node)
|
|
131
|
+
|
|
132
|
+
for v in node.iter_expressions():
|
|
133
|
+
if v._hash is None:
|
|
134
|
+
queue.append(v)
|
|
135
|
+
|
|
136
|
+
for node in reversed(nodes):
|
|
137
|
+
hash_ = hash(node.key)
|
|
138
|
+
t = type(node)
|
|
139
|
+
|
|
140
|
+
if t is Literal or t is Identifier:
|
|
141
|
+
for k, v in sorted(node.args.items()):
|
|
142
|
+
if v:
|
|
143
|
+
hash_ = hash((hash_, k, v))
|
|
144
|
+
else:
|
|
145
|
+
for k, v in sorted(node.args.items()):
|
|
146
|
+
t = type(v)
|
|
147
|
+
|
|
148
|
+
if t is list:
|
|
149
|
+
for x in v:
|
|
150
|
+
if x is not None and x is not False:
|
|
151
|
+
hash_ = hash((hash_, k, x.lower() if type(x) is str else x))
|
|
152
|
+
else:
|
|
153
|
+
hash_ = hash((hash_, k))
|
|
154
|
+
elif v is not None and v is not False:
|
|
155
|
+
hash_ = hash((hash_, k, v.lower() if t is str else v))
|
|
156
|
+
|
|
157
|
+
node._hash = hash_
|
|
158
|
+
assert self._hash
|
|
159
|
+
return self._hash
|
|
136
160
|
|
|
137
161
|
def __reduce__(self) -> t.Tuple[t.Callable, t.Tuple[t.List[t.Dict[str, t.Any]]]]:
|
|
138
162
|
from sqlglot.serde import dump, load
|
|
@@ -369,6 +393,12 @@ class Expression(metaclass=_Expression):
|
|
|
369
393
|
overwrite: assuming an index is given, this determines whether to overwrite the
|
|
370
394
|
list entry instead of only inserting a new value (i.e., like list.insert).
|
|
371
395
|
"""
|
|
396
|
+
expression: t.Optional[Expression] = self
|
|
397
|
+
|
|
398
|
+
while expression and expression._hash is not None:
|
|
399
|
+
expression._hash = None
|
|
400
|
+
expression = expression.parent
|
|
401
|
+
|
|
372
402
|
if index is not None:
|
|
373
403
|
expressions = self.args.get(arg_key) or []
|
|
374
404
|
|
|
@@ -2235,10 +2265,14 @@ class Prior(Expression):
|
|
|
2235
2265
|
|
|
2236
2266
|
|
|
2237
2267
|
class Directory(Expression):
|
|
2238
|
-
# https://spark.apache.org/docs/3.0.0-preview/sql-ref-syntax-dml-insert-overwrite-directory-hive.html
|
|
2239
2268
|
arg_types = {"this": True, "local": False, "row_format": False}
|
|
2240
2269
|
|
|
2241
2270
|
|
|
2271
|
+
# https://docs.snowflake.com/en/user-guide/data-load-dirtables-query
|
|
2272
|
+
class DirectoryStage(Expression):
|
|
2273
|
+
pass
|
|
2274
|
+
|
|
2275
|
+
|
|
2242
2276
|
class ForeignKey(Expression):
|
|
2243
2277
|
arg_types = {
|
|
2244
2278
|
"expressions": False,
|
|
@@ -2298,10 +2332,6 @@ class Identifier(Expression):
|
|
|
2298
2332
|
def quoted(self) -> bool:
|
|
2299
2333
|
return bool(self.args.get("quoted"))
|
|
2300
2334
|
|
|
2301
|
-
@property
|
|
2302
|
-
def hashable_args(self) -> t.Any:
|
|
2303
|
-
return (self.this, self.quoted)
|
|
2304
|
-
|
|
2305
2335
|
@property
|
|
2306
2336
|
def output_name(self) -> str:
|
|
2307
2337
|
return self.name
|
|
@@ -2536,10 +2566,6 @@ class LimitOptions(Expression):
|
|
|
2536
2566
|
class Literal(Condition):
|
|
2537
2567
|
arg_types = {"this": True, "is_string": True}
|
|
2538
2568
|
|
|
2539
|
-
@property
|
|
2540
|
-
def hashable_args(self) -> t.Any:
|
|
2541
|
-
return (self.this, self.args.get("is_string"))
|
|
2542
|
-
|
|
2543
2569
|
@classmethod
|
|
2544
2570
|
def number(cls, number) -> Literal:
|
|
2545
2571
|
return cls(this=str(number), is_string=False)
|
|
@@ -6427,14 +6453,36 @@ class Base64DecodeBinary(Func):
|
|
|
6427
6453
|
arg_types = {"this": True, "alphabet": False}
|
|
6428
6454
|
|
|
6429
6455
|
|
|
6456
|
+
# https://docs.snowflake.com/en/sql-reference/functions/base64_decode_string
|
|
6430
6457
|
class Base64DecodeString(Func):
|
|
6431
6458
|
arg_types = {"this": True, "alphabet": False}
|
|
6432
6459
|
|
|
6433
6460
|
|
|
6461
|
+
# https://docs.snowflake.com/en/sql-reference/functions/base64_encode
|
|
6434
6462
|
class Base64Encode(Func):
|
|
6435
6463
|
arg_types = {"this": True, "max_line_length": False, "alphabet": False}
|
|
6436
6464
|
|
|
6437
6465
|
|
|
6466
|
+
# https://docs.snowflake.com/en/sql-reference/functions/try_base64_decode_binary
|
|
6467
|
+
class TryBase64DecodeBinary(Func):
|
|
6468
|
+
arg_types = {"this": True, "alphabet": False}
|
|
6469
|
+
|
|
6470
|
+
|
|
6471
|
+
# https://docs.snowflake.com/en/sql-reference/functions/try_base64_decode_string
|
|
6472
|
+
class TryBase64DecodeString(Func):
|
|
6473
|
+
arg_types = {"this": True, "alphabet": False}
|
|
6474
|
+
|
|
6475
|
+
|
|
6476
|
+
# https://docs.snowflake.com/en/sql-reference/functions/try_hex_decode_binary
|
|
6477
|
+
class TryHexDecodeBinary(Func):
|
|
6478
|
+
pass
|
|
6479
|
+
|
|
6480
|
+
|
|
6481
|
+
# https://docs.snowflake.com/en/sql-reference/functions/try_hex_decode_string
|
|
6482
|
+
class TryHexDecodeString(Func):
|
|
6483
|
+
pass
|
|
6484
|
+
|
|
6485
|
+
|
|
6438
6486
|
# https://trino.io/docs/current/functions/datetime.html#from_iso8601_timestamp
|
|
6439
6487
|
class FromISO8601Timestamp(Func):
|
|
6440
6488
|
_sql_names = ["FROM_ISO8601_TIMESTAMP"]
|
|
@@ -7249,6 +7297,15 @@ class RegexpSplit(Func):
|
|
|
7249
7297
|
arg_types = {"this": True, "expression": True, "limit": False}
|
|
7250
7298
|
|
|
7251
7299
|
|
|
7300
|
+
class RegexpCount(Func):
|
|
7301
|
+
arg_types = {
|
|
7302
|
+
"this": True,
|
|
7303
|
+
"expression": True,
|
|
7304
|
+
"position": False,
|
|
7305
|
+
"parameters": False,
|
|
7306
|
+
}
|
|
7307
|
+
|
|
7308
|
+
|
|
7252
7309
|
class Repeat(Func):
|
|
7253
7310
|
arg_types = {"this": True, "times": True}
|
|
7254
7311
|
|
|
@@ -7712,10 +7769,6 @@ class TableColumn(Expression):
|
|
|
7712
7769
|
pass
|
|
7713
7770
|
|
|
7714
7771
|
|
|
7715
|
-
def _norm_arg(arg):
|
|
7716
|
-
return arg.lower() if type(arg) is str else arg
|
|
7717
|
-
|
|
7718
|
-
|
|
7719
7772
|
ALL_FUNCTIONS = subclasses(__name__, Func, (AggFunc, Anonymous, Func))
|
|
7720
7773
|
FUNCTION_BY_NAME = {name: func for func in ALL_FUNCTIONS for name in func.sql_names()}
|
|
7721
7774
|
|
|
@@ -5334,3 +5334,6 @@ class Generator(metaclass=_Generator):
|
|
|
5334
5334
|
def modelattribute_sql(self, expression: exp.ModelAttribute) -> str:
|
|
5335
5335
|
self.unsupported("The model!attribute syntax is not supported")
|
|
5336
5336
|
return ""
|
|
5337
|
+
|
|
5338
|
+
def directorystage_sql(self, expression: exp.DirectoryStage) -> str:
|
|
5339
|
+
return self.func("DIRECTORY", expression.this)
|
|
@@ -226,31 +226,13 @@ def while_changing(expression: Expression, func: t.Callable[[Expression], E]) ->
|
|
|
226
226
|
Returns:
|
|
227
227
|
The transformed expression.
|
|
228
228
|
"""
|
|
229
|
-
end_hash: t.Optional[int] = None
|
|
230
229
|
|
|
231
230
|
while True:
|
|
232
|
-
# No need to walk the AST– we've already cached the hashes in the previous iteration
|
|
233
|
-
if end_hash is None:
|
|
234
|
-
for n in reversed(tuple(expression.walk())):
|
|
235
|
-
n._hash = hash(n)
|
|
236
|
-
|
|
237
231
|
start_hash = hash(expression)
|
|
238
232
|
expression = func(expression)
|
|
239
|
-
|
|
240
|
-
expression_nodes = tuple(expression.walk())
|
|
241
|
-
|
|
242
|
-
# Uncache previous caches so we can recompute them
|
|
243
|
-
for n in reversed(expression_nodes):
|
|
244
|
-
n._hash = None
|
|
245
|
-
n._hash = hash(n)
|
|
246
|
-
|
|
247
233
|
end_hash = hash(expression)
|
|
248
234
|
|
|
249
235
|
if start_hash == end_hash:
|
|
250
|
-
# ... and reset the hash so we don't risk it becoming out of date if a mutation happens
|
|
251
|
-
for n in expression_nodes:
|
|
252
|
-
n._hash = None
|
|
253
|
-
|
|
254
236
|
break
|
|
255
237
|
|
|
256
238
|
return expression
|
|
@@ -1411,7 +1411,7 @@ class Parser(metaclass=_Parser):
|
|
|
1411
1411
|
|
|
1412
1412
|
VIEW_ATTRIBUTES = {"ENCRYPTION", "SCHEMABINDING", "VIEW_METADATA"}
|
|
1413
1413
|
|
|
1414
|
-
WINDOW_ALIAS_TOKENS = ID_VAR_TOKENS - {TokenType.ROWS}
|
|
1414
|
+
WINDOW_ALIAS_TOKENS = ID_VAR_TOKENS - {TokenType.RANGE, TokenType.ROWS}
|
|
1415
1415
|
WINDOW_BEFORE_PAREN_TOKENS = {TokenType.OVER}
|
|
1416
1416
|
WINDOW_SIDES = {"FOLLOWING", "PRECEDING"}
|
|
1417
1417
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: sqlglot
|
|
3
|
-
Version: 27.
|
|
3
|
+
Version: 27.20.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
|
|
@@ -89,12 +89,14 @@ pip3 install "sqlglot[rs]"
|
|
|
89
89
|
Or with a local checkout:
|
|
90
90
|
|
|
91
91
|
```
|
|
92
|
+
# Optionally prefix with UV=1 to use uv for the installation
|
|
92
93
|
make install
|
|
93
94
|
```
|
|
94
95
|
|
|
95
96
|
Requirements for development (optional):
|
|
96
97
|
|
|
97
98
|
```
|
|
99
|
+
# Optionally prefix with UV=1 to use uv for the installation
|
|
98
100
|
make install-dev
|
|
99
101
|
```
|
|
100
102
|
|
|
@@ -44,7 +44,9 @@ class TestSnowflake(Validator):
|
|
|
44
44
|
self.validate_identity("SELECT LPAD(tbl.bin_col, 10)")
|
|
45
45
|
self.validate_identity("SELECT RPAD('Hello', 10, '*')")
|
|
46
46
|
self.validate_identity("SELECT RPAD(tbl.bin_col, 10)")
|
|
47
|
+
self.validate_identity("SELECT SOUNDEX(column_name)")
|
|
47
48
|
self.validate_identity("SELECT JAROWINKLER_SIMILARITY('hello', 'world')")
|
|
49
|
+
self.validate_identity("SELECT SPLIT_PART('11.22.33', '.', 1)")
|
|
48
50
|
self.validate_identity("PARSE_URL('https://example.com/path')")
|
|
49
51
|
self.validate_identity("PARSE_URL('https://example.com/path', 1)")
|
|
50
52
|
self.validate_identity("SELECT {*} FROM my_table")
|
|
@@ -121,6 +123,9 @@ class TestSnowflake(Validator):
|
|
|
121
123
|
self.validate_identity("SELECT GET_PATH(foo, 'bar')")
|
|
122
124
|
self.validate_identity("SELECT a, exclude, b FROM xxx")
|
|
123
125
|
self.validate_identity("SELECT ARRAY_SORT(x, TRUE, FALSE)")
|
|
126
|
+
self.validate_identity("SELECT FILE_URL FROM DIRECTORY(@mystage) WHERE SIZE > 100000").args[
|
|
127
|
+
"from"
|
|
128
|
+
].this.this.assert_is(exp.DirectoryStage).this.assert_is(exp.Var)
|
|
124
129
|
self.validate_identity(
|
|
125
130
|
"SELECT AI_CLASSIFY('text', ['travel', 'cooking'], OBJECT_CONSTRUCT('output_mode', 'multi'))"
|
|
126
131
|
)
|
|
@@ -1392,6 +1397,20 @@ class TestSnowflake(Validator):
|
|
|
1392
1397
|
"SELECT BASE64_ENCODE('Hello World', 76, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/')"
|
|
1393
1398
|
)
|
|
1394
1399
|
|
|
1400
|
+
self.validate_identity("SELECT TRY_BASE64_DECODE_BINARY('SGVsbG8=')")
|
|
1401
|
+
self.validate_identity(
|
|
1402
|
+
"SELECT TRY_BASE64_DECODE_BINARY('SGVsbG8=', 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/')"
|
|
1403
|
+
)
|
|
1404
|
+
|
|
1405
|
+
self.validate_identity("SELECT TRY_BASE64_DECODE_STRING('SGVsbG8gV29ybGQ=')")
|
|
1406
|
+
self.validate_identity(
|
|
1407
|
+
"SELECT TRY_BASE64_DECODE_STRING('SGVsbG8gV29ybGQ=', 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/')"
|
|
1408
|
+
)
|
|
1409
|
+
|
|
1410
|
+
self.validate_identity("SELECT TRY_HEX_DECODE_BINARY('48656C6C6F')")
|
|
1411
|
+
|
|
1412
|
+
self.validate_identity("SELECT TRY_HEX_DECODE_STRING('48656C6C6F')")
|
|
1413
|
+
|
|
1395
1414
|
def test_null_treatment(self):
|
|
1396
1415
|
self.validate_all(
|
|
1397
1416
|
r"SELECT FIRST_VALUE(TABLE1.COLUMN1) OVER (PARTITION BY RANDOM_COLUMN1, RANDOM_COLUMN2 ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) AS MY_ALIAS FROM TABLE1",
|
|
@@ -2407,6 +2426,10 @@ FROM persons AS p, LATERAL FLATTEN(input => p.c, path => 'contact') AS _flattene
|
|
|
2407
2426
|
"REGEXP_EXTRACT_ALL(subject, pattern)",
|
|
2408
2427
|
)
|
|
2409
2428
|
|
|
2429
|
+
self.validate_identity("SELECT REGEXP_COUNT('hello world', 'l')")
|
|
2430
|
+
self.validate_identity("SELECT REGEXP_COUNT('hello world', 'l', 1)")
|
|
2431
|
+
self.validate_identity("SELECT REGEXP_COUNT('hello world', 'l', 1, 'i')")
|
|
2432
|
+
|
|
2410
2433
|
@mock.patch("sqlglot.generator.logger")
|
|
2411
2434
|
def test_regexp_replace(self, logger):
|
|
2412
2435
|
self.validate_all(
|
|
@@ -7,6 +7,7 @@ class TestSQLite(Validator):
|
|
|
7
7
|
dialect = "sqlite"
|
|
8
8
|
|
|
9
9
|
def test_sqlite(self):
|
|
10
|
+
self.validate_identity("SELECT RANK() OVER (RANGE CURRENT ROW) FROM tbl")
|
|
10
11
|
self.validate_identity("UNHEX(a, b)")
|
|
11
12
|
self.validate_identity("SELECT DATE()")
|
|
12
13
|
self.validate_identity("SELECT DATE('now', 'start of month', '+1 month', '-1 day')")
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
from sqlglot import exp
|
|
1
2
|
from sqlglot.errors import UnsupportedError
|
|
2
3
|
from tests.dialects.test_dialect import Validator
|
|
3
4
|
|
|
@@ -12,6 +13,8 @@ class TestStarrocks(Validator):
|
|
|
12
13
|
self.validate_identity("SELECT ARRAY_AGG(a) FROM x")
|
|
13
14
|
self.validate_identity("SELECT ST_POINT(10, 20)")
|
|
14
15
|
self.validate_identity("SELECT ST_DISTANCE_SPHERE(10.1, 20.2, 30.3, 40.4)")
|
|
16
|
+
self.validate_identity("ARRAY_FLATTEN(arr)").assert_is(exp.Flatten)
|
|
17
|
+
self.assertEqual(self.validate_identity("arr[1]").expressions[0], exp.Literal.number(0))
|
|
15
18
|
|
|
16
19
|
def test_ddl(self):
|
|
17
20
|
self.validate_identity("CREATE TABLE t (c INT) COMMENT 'c'")
|
|
@@ -1883,6 +1883,18 @@ BOOLEAN;
|
|
|
1883
1883
|
REGEXP_LIKE('foo', NULL, 'baz');
|
|
1884
1884
|
BOOLEAN;
|
|
1885
1885
|
|
|
1886
|
+
# dialect: snowflake
|
|
1887
|
+
REGEXP_COUNT('hello world', 'l');
|
|
1888
|
+
DECIMAL(38, 0);
|
|
1889
|
+
|
|
1890
|
+
# dialect: snowflake
|
|
1891
|
+
REGEXP_COUNT('hello world', 'l', 1);
|
|
1892
|
+
DECIMAL(38, 0);
|
|
1893
|
+
|
|
1894
|
+
# dialect: snowflake
|
|
1895
|
+
REGEXP_COUNT('hello world', 'l', 1, 'i');
|
|
1896
|
+
DECIMAL(38, 0);
|
|
1897
|
+
|
|
1886
1898
|
# dialect: snowflake
|
|
1887
1899
|
REGEXP_REPLACE('hello world', 'world', 'universe');
|
|
1888
1900
|
VARCHAR;
|
|
@@ -2067,6 +2079,10 @@ VARCHAR;
|
|
|
2067
2079
|
SHA2_HEX('foo', null);
|
|
2068
2080
|
VARCHAR;
|
|
2069
2081
|
|
|
2082
|
+
# dialect: snowflake
|
|
2083
|
+
SOUNDEX(tbl.str_col);
|
|
2084
|
+
VARCHAR;
|
|
2085
|
+
|
|
2070
2086
|
# dialect: snowflake
|
|
2071
2087
|
SPACE(5);
|
|
2072
2088
|
VARCHAR;
|
|
@@ -2091,6 +2107,10 @@ ARRAY;
|
|
|
2091
2107
|
SPLIT(NULL, ',');
|
|
2092
2108
|
ARRAY;
|
|
2093
2109
|
|
|
2110
|
+
# dialect: snowflake
|
|
2111
|
+
SPLIT_PART('11.22.33', '.', 1);
|
|
2112
|
+
VARCHAR;
|
|
2113
|
+
|
|
2094
2114
|
# dialect: snowflake
|
|
2095
2115
|
STARTSWITH('hello world', 'hello');
|
|
2096
2116
|
BOOLEAN;
|
|
@@ -2143,6 +2163,30 @@ VARCHAR;
|
|
|
2143
2163
|
TRIM(NULL);
|
|
2144
2164
|
VARCHAR;
|
|
2145
2165
|
|
|
2166
|
+
# dialect: snowflake
|
|
2167
|
+
TRY_BASE64_DECODE_BINARY('SGVsbG8=');
|
|
2168
|
+
BINARY;
|
|
2169
|
+
|
|
2170
|
+
# dialect: snowflake
|
|
2171
|
+
TRY_BASE64_DECODE_BINARY('SGVsbG8=', 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/');
|
|
2172
|
+
BINARY;
|
|
2173
|
+
|
|
2174
|
+
# dialect: snowflake
|
|
2175
|
+
TRY_BASE64_DECODE_STRING('SGVsbG8gV29ybGQ=');
|
|
2176
|
+
VARCHAR;
|
|
2177
|
+
|
|
2178
|
+
# dialect: snowflake
|
|
2179
|
+
TRY_BASE64_DECODE_STRING('SGVsbG8gV29ybGQ=', 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/');
|
|
2180
|
+
VARCHAR;
|
|
2181
|
+
|
|
2182
|
+
# dialect: snowflake
|
|
2183
|
+
TRY_HEX_DECODE_BINARY('48656C6C6F');
|
|
2184
|
+
BINARY;
|
|
2185
|
+
|
|
2186
|
+
# dialect: snowflake
|
|
2187
|
+
TRY_HEX_DECODE_STRING('48656C6C6F');
|
|
2188
|
+
VARCHAR;
|
|
2189
|
+
|
|
2146
2190
|
# dialect: snowflake
|
|
2147
2191
|
UPPER('Hello, world!');
|
|
2148
2192
|
VARCHAR;
|
|
@@ -73,6 +73,10 @@ class TestExpressions(unittest.TestCase):
|
|
|
73
73
|
self.assertEqual(
|
|
74
74
|
exp.DataType.build("int"), exp.DataType(this=exp.DataType.Type.INT, nested=False)
|
|
75
75
|
)
|
|
76
|
+
self.assertNotEqual(
|
|
77
|
+
exp.Identifier(this="a", temporary=True),
|
|
78
|
+
exp.Identifier(this="a"),
|
|
79
|
+
)
|
|
76
80
|
|
|
77
81
|
def test_find(self):
|
|
78
82
|
expression = parse_one("CREATE TABLE x STORED AS PARQUET AS SELECT * FROM y")
|
|
@@ -1262,3 +1266,7 @@ FROM foo""",
|
|
|
1262
1266
|
|
|
1263
1267
|
self.assertIsInstance(result, exp.TsOrDsToTime)
|
|
1264
1268
|
self.assertEqual(result.sql(), "CAST('12:00:00' AS TIME)")
|
|
1269
|
+
|
|
1270
|
+
def test_hash_large_ast(self):
|
|
1271
|
+
expr = parse_one("SELECT 1 UNION ALL " * 3000 + "SELECT 1")
|
|
1272
|
+
assert expr == expr
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|