polyglot-sql 0.3.1__tar.gz → 0.3.2__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.
- {polyglot_sql-0.3.1 → polyglot_sql-0.3.2}/Cargo.lock +5 -5
- {polyglot_sql-0.3.1 → polyglot_sql-0.3.2}/Cargo.toml +1 -1
- {polyglot_sql-0.3.1 → polyglot_sql-0.3.2}/PKG-INFO +1 -1
- {polyglot_sql-0.3.1 → polyglot_sql-0.3.2}/crates/polyglot-sql/Cargo.toml +1 -1
- {polyglot_sql-0.3.1 → polyglot_sql-0.3.2}/crates/polyglot-sql/src/ast_transforms.rs +12 -0
- {polyglot_sql-0.3.1 → polyglot_sql-0.3.2}/crates/polyglot-sql/src/dialects/bigquery.rs +1 -3
- {polyglot_sql-0.3.1 → polyglot_sql-0.3.2}/crates/polyglot-sql/src/dialects/duckdb.rs +3 -3
- {polyglot_sql-0.3.1 → polyglot_sql-0.3.2}/crates/polyglot-sql/src/dialects/mod.rs +25 -22
- {polyglot_sql-0.3.1 → polyglot_sql-0.3.2}/crates/polyglot-sql/src/dialects/sqlite.rs +1 -3
- {polyglot_sql-0.3.1 → polyglot_sql-0.3.2}/crates/polyglot-sql/src/expressions.rs +3 -0
- {polyglot_sql-0.3.1 → polyglot_sql-0.3.2}/crates/polyglot-sql/src/generator.rs +5 -1
- {polyglot_sql-0.3.1 → polyglot_sql-0.3.2}/crates/polyglot-sql/src/lib.rs +42 -11
- {polyglot_sql-0.3.1 → polyglot_sql-0.3.2}/crates/polyglot-sql/src/lineage.rs +87 -96
- {polyglot_sql-0.3.1 → polyglot_sql-0.3.2}/crates/polyglot-sql/src/parser.rs +386 -118
- {polyglot_sql-0.3.1 → polyglot_sql-0.3.2}/crates/polyglot-sql/src/traversal.rs +8 -0
- {polyglot_sql-0.3.1 → polyglot_sql-0.3.2}/README.md +0 -0
- {polyglot_sql-0.3.1 → polyglot_sql-0.3.2}/crates/polyglot-sql/README.md +0 -0
- {polyglot_sql-0.3.1 → polyglot_sql-0.3.2}/crates/polyglot-sql/benches/in_list.rs +0 -0
- {polyglot_sql-0.3.1 → polyglot_sql-0.3.2}/crates/polyglot-sql/benches/parsing.rs +0 -0
- {polyglot_sql-0.3.1 → polyglot_sql-0.3.2}/crates/polyglot-sql/benches/rust_parsing.rs +0 -0
- {polyglot_sql-0.3.1 → polyglot_sql-0.3.2}/crates/polyglot-sql/benches/transpile.rs +0 -0
- {polyglot_sql-0.3.1 → polyglot_sql-0.3.2}/crates/polyglot-sql/examples/basic_usage.rs +0 -0
- {polyglot_sql-0.3.1 → polyglot_sql-0.3.2}/crates/polyglot-sql/examples/bench_json.rs +0 -0
- {polyglot_sql-0.3.1 → polyglot_sql-0.3.2}/crates/polyglot-sql/src/builder.rs +0 -0
- {polyglot_sql-0.3.1 → polyglot_sql-0.3.2}/crates/polyglot-sql/src/dialects/athena.rs +0 -0
- {polyglot_sql-0.3.1 → polyglot_sql-0.3.2}/crates/polyglot-sql/src/dialects/clickhouse.rs +0 -0
- {polyglot_sql-0.3.1 → polyglot_sql-0.3.2}/crates/polyglot-sql/src/dialects/cockroachdb.rs +0 -0
- {polyglot_sql-0.3.1 → polyglot_sql-0.3.2}/crates/polyglot-sql/src/dialects/databricks.rs +0 -0
- {polyglot_sql-0.3.1 → polyglot_sql-0.3.2}/crates/polyglot-sql/src/dialects/datafusion.rs +0 -0
- {polyglot_sql-0.3.1 → polyglot_sql-0.3.2}/crates/polyglot-sql/src/dialects/doris.rs +0 -0
- {polyglot_sql-0.3.1 → polyglot_sql-0.3.2}/crates/polyglot-sql/src/dialects/dremio.rs +0 -0
- {polyglot_sql-0.3.1 → polyglot_sql-0.3.2}/crates/polyglot-sql/src/dialects/drill.rs +0 -0
- {polyglot_sql-0.3.1 → polyglot_sql-0.3.2}/crates/polyglot-sql/src/dialects/druid.rs +0 -0
- {polyglot_sql-0.3.1 → polyglot_sql-0.3.2}/crates/polyglot-sql/src/dialects/dune.rs +0 -0
- {polyglot_sql-0.3.1 → polyglot_sql-0.3.2}/crates/polyglot-sql/src/dialects/exasol.rs +0 -0
- {polyglot_sql-0.3.1 → polyglot_sql-0.3.2}/crates/polyglot-sql/src/dialects/fabric.rs +0 -0
- {polyglot_sql-0.3.1 → polyglot_sql-0.3.2}/crates/polyglot-sql/src/dialects/generic.rs +0 -0
- {polyglot_sql-0.3.1 → polyglot_sql-0.3.2}/crates/polyglot-sql/src/dialects/hive.rs +0 -0
- {polyglot_sql-0.3.1 → polyglot_sql-0.3.2}/crates/polyglot-sql/src/dialects/materialize.rs +0 -0
- {polyglot_sql-0.3.1 → polyglot_sql-0.3.2}/crates/polyglot-sql/src/dialects/mysql.rs +0 -0
- {polyglot_sql-0.3.1 → polyglot_sql-0.3.2}/crates/polyglot-sql/src/dialects/oracle.rs +0 -0
- {polyglot_sql-0.3.1 → polyglot_sql-0.3.2}/crates/polyglot-sql/src/dialects/postgres.rs +0 -0
- {polyglot_sql-0.3.1 → polyglot_sql-0.3.2}/crates/polyglot-sql/src/dialects/presto.rs +0 -0
- {polyglot_sql-0.3.1 → polyglot_sql-0.3.2}/crates/polyglot-sql/src/dialects/redshift.rs +0 -0
- {polyglot_sql-0.3.1 → polyglot_sql-0.3.2}/crates/polyglot-sql/src/dialects/risingwave.rs +0 -0
- {polyglot_sql-0.3.1 → polyglot_sql-0.3.2}/crates/polyglot-sql/src/dialects/singlestore.rs +0 -0
- {polyglot_sql-0.3.1 → polyglot_sql-0.3.2}/crates/polyglot-sql/src/dialects/snowflake.rs +0 -0
- {polyglot_sql-0.3.1 → polyglot_sql-0.3.2}/crates/polyglot-sql/src/dialects/solr.rs +0 -0
- {polyglot_sql-0.3.1 → polyglot_sql-0.3.2}/crates/polyglot-sql/src/dialects/spark.rs +0 -0
- {polyglot_sql-0.3.1 → polyglot_sql-0.3.2}/crates/polyglot-sql/src/dialects/starrocks.rs +0 -0
- {polyglot_sql-0.3.1 → polyglot_sql-0.3.2}/crates/polyglot-sql/src/dialects/tableau.rs +0 -0
- {polyglot_sql-0.3.1 → polyglot_sql-0.3.2}/crates/polyglot-sql/src/dialects/teradata.rs +0 -0
- {polyglot_sql-0.3.1 → polyglot_sql-0.3.2}/crates/polyglot-sql/src/dialects/tidb.rs +0 -0
- {polyglot_sql-0.3.1 → polyglot_sql-0.3.2}/crates/polyglot-sql/src/dialects/trino.rs +0 -0
- {polyglot_sql-0.3.1 → polyglot_sql-0.3.2}/crates/polyglot-sql/src/dialects/tsql.rs +0 -0
- {polyglot_sql-0.3.1 → polyglot_sql-0.3.2}/crates/polyglot-sql/src/diff.rs +0 -0
- {polyglot_sql-0.3.1 → polyglot_sql-0.3.2}/crates/polyglot-sql/src/error.rs +0 -0
- {polyglot_sql-0.3.1 → polyglot_sql-0.3.2}/crates/polyglot-sql/src/function_catalog.rs +0 -0
- {polyglot_sql-0.3.1 → polyglot_sql-0.3.2}/crates/polyglot-sql/src/function_registry.rs +0 -0
- {polyglot_sql-0.3.1 → polyglot_sql-0.3.2}/crates/polyglot-sql/src/helper.rs +0 -0
- {polyglot_sql-0.3.1 → polyglot_sql-0.3.2}/crates/polyglot-sql/src/optimizer/annotate_types.rs +0 -0
- {polyglot_sql-0.3.1 → polyglot_sql-0.3.2}/crates/polyglot-sql/src/optimizer/canonicalize.rs +0 -0
- {polyglot_sql-0.3.1 → polyglot_sql-0.3.2}/crates/polyglot-sql/src/optimizer/eliminate_ctes.rs +0 -0
- {polyglot_sql-0.3.1 → polyglot_sql-0.3.2}/crates/polyglot-sql/src/optimizer/eliminate_joins.rs +0 -0
- {polyglot_sql-0.3.1 → polyglot_sql-0.3.2}/crates/polyglot-sql/src/optimizer/isolate_table_selects.rs +0 -0
- {polyglot_sql-0.3.1 → polyglot_sql-0.3.2}/crates/polyglot-sql/src/optimizer/mod.rs +0 -0
- {polyglot_sql-0.3.1 → polyglot_sql-0.3.2}/crates/polyglot-sql/src/optimizer/normalize.rs +0 -0
- {polyglot_sql-0.3.1 → polyglot_sql-0.3.2}/crates/polyglot-sql/src/optimizer/normalize_identifiers.rs +0 -0
- {polyglot_sql-0.3.1 → polyglot_sql-0.3.2}/crates/polyglot-sql/src/optimizer/optimize_joins.rs +0 -0
- {polyglot_sql-0.3.1 → polyglot_sql-0.3.2}/crates/polyglot-sql/src/optimizer/optimizer.rs +0 -0
- {polyglot_sql-0.3.1 → polyglot_sql-0.3.2}/crates/polyglot-sql/src/optimizer/pushdown_predicates.rs +0 -0
- {polyglot_sql-0.3.1 → polyglot_sql-0.3.2}/crates/polyglot-sql/src/optimizer/pushdown_projections.rs +0 -0
- {polyglot_sql-0.3.1 → polyglot_sql-0.3.2}/crates/polyglot-sql/src/optimizer/qualify_columns.rs +0 -0
- {polyglot_sql-0.3.1 → polyglot_sql-0.3.2}/crates/polyglot-sql/src/optimizer/qualify_tables.rs +0 -0
- {polyglot_sql-0.3.1 → polyglot_sql-0.3.2}/crates/polyglot-sql/src/optimizer/simplify.rs +0 -0
- {polyglot_sql-0.3.1 → polyglot_sql-0.3.2}/crates/polyglot-sql/src/optimizer/subquery.rs +0 -0
- {polyglot_sql-0.3.1 → polyglot_sql-0.3.2}/crates/polyglot-sql/src/planner.rs +0 -0
- {polyglot_sql-0.3.1 → polyglot_sql-0.3.2}/crates/polyglot-sql/src/resolver.rs +0 -0
- {polyglot_sql-0.3.1 → polyglot_sql-0.3.2}/crates/polyglot-sql/src/schema.rs +0 -0
- {polyglot_sql-0.3.1 → polyglot_sql-0.3.2}/crates/polyglot-sql/src/scope.rs +0 -0
- {polyglot_sql-0.3.1 → polyglot_sql-0.3.2}/crates/polyglot-sql/src/time.rs +0 -0
- {polyglot_sql-0.3.1 → polyglot_sql-0.3.2}/crates/polyglot-sql/src/tokens.rs +0 -0
- {polyglot_sql-0.3.1 → polyglot_sql-0.3.2}/crates/polyglot-sql/src/transforms.rs +0 -0
- {polyglot_sql-0.3.1 → polyglot_sql-0.3.2}/crates/polyglot-sql/src/trie.rs +0 -0
- {polyglot_sql-0.3.1 → polyglot_sql-0.3.2}/crates/polyglot-sql/src/validation/tests.rs +0 -0
- {polyglot_sql-0.3.1 → polyglot_sql-0.3.2}/crates/polyglot-sql/src/validation.rs +0 -0
- {polyglot_sql-0.3.1 → polyglot_sql-0.3.2}/crates/polyglot-sql/tests/analyze_failures.rs +0 -0
- {polyglot_sql-0.3.1 → polyglot_sql-0.3.2}/crates/polyglot-sql/tests/common/known_failures.rs +0 -0
- {polyglot_sql-0.3.1 → polyglot_sql-0.3.2}/crates/polyglot-sql/tests/common/mod.rs +0 -0
- {polyglot_sql-0.3.1 → polyglot_sql-0.3.2}/crates/polyglot-sql/tests/common/test_data.rs +0 -0
- {polyglot_sql-0.3.1 → polyglot_sql-0.3.2}/crates/polyglot-sql/tests/common/test_runner.rs +0 -0
- {polyglot_sql-0.3.1 → polyglot_sql-0.3.2}/crates/polyglot-sql/tests/custom_clickhouse_coverage.rs +0 -0
- {polyglot_sql-0.3.1 → polyglot_sql-0.3.2}/crates/polyglot-sql/tests/custom_clickhouse_parser.rs +0 -0
- {polyglot_sql-0.3.1 → polyglot_sql-0.3.2}/crates/polyglot-sql/tests/custom_dialect.rs +0 -0
- {polyglot_sql-0.3.1 → polyglot_sql-0.3.2}/crates/polyglot-sql/tests/custom_dialect_tests.rs +0 -0
- {polyglot_sql-0.3.1 → polyglot_sql-0.3.2}/crates/polyglot-sql/tests/custom_fixtures/datafusion/ddl.json +0 -0
- {polyglot_sql-0.3.1 → polyglot_sql-0.3.2}/crates/polyglot-sql/tests/custom_fixtures/datafusion/dml.json +0 -0
- {polyglot_sql-0.3.1 → polyglot_sql-0.3.2}/crates/polyglot-sql/tests/custom_fixtures/datafusion/functions.json +0 -0
- {polyglot_sql-0.3.1 → polyglot_sql-0.3.2}/crates/polyglot-sql/tests/custom_fixtures/datafusion/identity.json +0 -0
- {polyglot_sql-0.3.1 → polyglot_sql-0.3.2}/crates/polyglot-sql/tests/custom_fixtures/datafusion/operators.json +0 -0
- {polyglot_sql-0.3.1 → polyglot_sql-0.3.2}/crates/polyglot-sql/tests/custom_fixtures/datafusion/select.json +0 -0
- {polyglot_sql-0.3.1 → polyglot_sql-0.3.2}/crates/polyglot-sql/tests/custom_fixtures/datafusion/transpilation.json +0 -0
- {polyglot_sql-0.3.1 → polyglot_sql-0.3.2}/crates/polyglot-sql/tests/custom_fixtures/datafusion/types.json +0 -0
- {polyglot_sql-0.3.1 → polyglot_sql-0.3.2}/crates/polyglot-sql/tests/dialect_matrix.rs +0 -0
- {polyglot_sql-0.3.1 → polyglot_sql-0.3.2}/crates/polyglot-sql/tests/error_handling.rs +0 -0
- {polyglot_sql-0.3.1 → polyglot_sql-0.3.2}/crates/polyglot-sql/tests/identity_roundtrip.rs +0 -0
- {polyglot_sql-0.3.1 → polyglot_sql-0.3.2}/crates/polyglot-sql/tests/sqlglot_compat.rs +0 -0
- {polyglot_sql-0.3.1 → polyglot_sql-0.3.2}/crates/polyglot-sql/tests/sqlglot_dialect_identity.rs +0 -0
- {polyglot_sql-0.3.1 → polyglot_sql-0.3.2}/crates/polyglot-sql/tests/sqlglot_identity.rs +0 -0
- {polyglot_sql-0.3.1 → polyglot_sql-0.3.2}/crates/polyglot-sql/tests/sqlglot_identity_detailed.rs +0 -0
- {polyglot_sql-0.3.1 → polyglot_sql-0.3.2}/crates/polyglot-sql/tests/sqlglot_parser.rs +0 -0
- {polyglot_sql-0.3.1 → polyglot_sql-0.3.2}/crates/polyglot-sql/tests/sqlglot_pretty.rs +0 -0
- {polyglot_sql-0.3.1 → polyglot_sql-0.3.2}/crates/polyglot-sql/tests/sqlglot_transpilation.rs +0 -0
- {polyglot_sql-0.3.1 → polyglot_sql-0.3.2}/crates/polyglot-sql/tests/sqlglot_transpile.rs +0 -0
- {polyglot_sql-0.3.1 → polyglot_sql-0.3.2}/crates/polyglot-sql-function-catalogs/Cargo.toml +0 -0
- {polyglot_sql-0.3.1 → polyglot_sql-0.3.2}/crates/polyglot-sql-function-catalogs/README.md +0 -0
- {polyglot_sql-0.3.1 → polyglot_sql-0.3.2}/crates/polyglot-sql-function-catalogs/src/clickhouse.rs +0 -0
- {polyglot_sql-0.3.1 → polyglot_sql-0.3.2}/crates/polyglot-sql-function-catalogs/src/duckdb.rs +0 -0
- {polyglot_sql-0.3.1 → polyglot_sql-0.3.2}/crates/polyglot-sql-function-catalogs/src/lib.rs +0 -0
- {polyglot_sql-0.3.1 → polyglot_sql-0.3.2}/crates/polyglot-sql-function-catalogs/tools/clickhouse/extract_functions.py +0 -0
- {polyglot_sql-0.3.1 → polyglot_sql-0.3.2}/crates/polyglot-sql-function-catalogs/tools/duckdb/extract_functions.py +0 -0
- {polyglot_sql-0.3.1 → polyglot_sql-0.3.2}/crates/polyglot-sql-python/Cargo.toml +0 -0
- {polyglot_sql-0.3.1 → polyglot_sql-0.3.2}/crates/polyglot-sql-python/README.md +0 -0
- {polyglot_sql-0.3.1 → polyglot_sql-0.3.2}/crates/polyglot-sql-python/docs/api.md +0 -0
- {polyglot_sql-0.3.1 → polyglot_sql-0.3.2}/crates/polyglot-sql-python/docs/index.md +0 -0
- {polyglot_sql-0.3.1 → polyglot_sql-0.3.2}/crates/polyglot-sql-python/mkdocs.yml +0 -0
- {polyglot_sql-0.3.1 → polyglot_sql-0.3.2}/crates/polyglot-sql-python/src/annotate_types.rs +0 -0
- {polyglot_sql-0.3.1 → polyglot_sql-0.3.2}/crates/polyglot-sql-python/src/dialects.rs +0 -0
- {polyglot_sql-0.3.1 → polyglot_sql-0.3.2}/crates/polyglot-sql-python/src/diff.rs +0 -0
- {polyglot_sql-0.3.1 → polyglot_sql-0.3.2}/crates/polyglot-sql-python/src/errors.rs +0 -0
- {polyglot_sql-0.3.1 → polyglot_sql-0.3.2}/crates/polyglot-sql-python/src/expr.rs +0 -0
- {polyglot_sql-0.3.1 → polyglot_sql-0.3.2}/crates/polyglot-sql-python/src/expr_types.rs +0 -0
- {polyglot_sql-0.3.1 → polyglot_sql-0.3.2}/crates/polyglot-sql-python/src/format.rs +0 -0
- {polyglot_sql-0.3.1 → polyglot_sql-0.3.2}/crates/polyglot-sql-python/src/generate.rs +0 -0
- {polyglot_sql-0.3.1 → polyglot_sql-0.3.2}/crates/polyglot-sql-python/src/helpers.rs +0 -0
- {polyglot_sql-0.3.1 → polyglot_sql-0.3.2}/crates/polyglot-sql-python/src/lib.rs +0 -0
- {polyglot_sql-0.3.1 → polyglot_sql-0.3.2}/crates/polyglot-sql-python/src/lineage.rs +0 -0
- {polyglot_sql-0.3.1 → polyglot_sql-0.3.2}/crates/polyglot-sql-python/src/optimize.rs +0 -0
- {polyglot_sql-0.3.1 → polyglot_sql-0.3.2}/crates/polyglot-sql-python/src/parse.rs +0 -0
- {polyglot_sql-0.3.1 → polyglot_sql-0.3.2}/crates/polyglot-sql-python/src/tokenize.rs +0 -0
- {polyglot_sql-0.3.1 → polyglot_sql-0.3.2}/crates/polyglot-sql-python/src/transpile.rs +0 -0
- {polyglot_sql-0.3.1 → polyglot_sql-0.3.2}/crates/polyglot-sql-python/src/types.rs +0 -0
- {polyglot_sql-0.3.1 → polyglot_sql-0.3.2}/crates/polyglot-sql-python/src/validate.rs +0 -0
- {polyglot_sql-0.3.1 → polyglot_sql-0.3.2}/crates/polyglot-sql-python/tests/conftest.py +0 -0
- {polyglot_sql-0.3.1 → polyglot_sql-0.3.2}/crates/polyglot-sql-python/tests/test_compat.py +0 -0
- {polyglot_sql-0.3.1 → polyglot_sql-0.3.2}/crates/polyglot-sql-python/tests/test_dialects.py +0 -0
- {polyglot_sql-0.3.1 → polyglot_sql-0.3.2}/crates/polyglot-sql-python/tests/test_diff.py +0 -0
- {polyglot_sql-0.3.1 → polyglot_sql-0.3.2}/crates/polyglot-sql-python/tests/test_expression.py +0 -0
- {polyglot_sql-0.3.1 → polyglot_sql-0.3.2}/crates/polyglot-sql-python/tests/test_format.py +0 -0
- {polyglot_sql-0.3.1 → polyglot_sql-0.3.2}/crates/polyglot-sql-python/tests/test_generate.py +0 -0
- {polyglot_sql-0.3.1 → polyglot_sql-0.3.2}/crates/polyglot-sql-python/tests/test_lineage.py +0 -0
- {polyglot_sql-0.3.1 → polyglot_sql-0.3.2}/crates/polyglot-sql-python/tests/test_optimize.py +0 -0
- {polyglot_sql-0.3.1 → polyglot_sql-0.3.2}/crates/polyglot-sql-python/tests/test_parse.py +0 -0
- {polyglot_sql-0.3.1 → polyglot_sql-0.3.2}/crates/polyglot-sql-python/tests/test_transpile.py +0 -0
- {polyglot_sql-0.3.1 → polyglot_sql-0.3.2}/crates/polyglot-sql-python/tests/test_validate.py +0 -0
- {polyglot_sql-0.3.1 → polyglot_sql-0.3.2}/crates/polyglot-sql-python/uv.lock +0 -0
- {polyglot_sql-0.3.1 → polyglot_sql-0.3.2}/pyproject.toml +0 -0
- {polyglot_sql-0.3.1 → polyglot_sql-0.3.2}/python/polyglot_sql/__init__.py +0 -0
- {polyglot_sql-0.3.1 → polyglot_sql-0.3.2}/python/polyglot_sql/__init__.pyi +0 -0
- {polyglot_sql-0.3.1 → polyglot_sql-0.3.2}/python/polyglot_sql/py.typed +0 -0
|
@@ -587,7 +587,7 @@ dependencies = [
|
|
|
587
587
|
|
|
588
588
|
[[package]]
|
|
589
589
|
name = "polyglot-sql"
|
|
590
|
-
version = "0.3.
|
|
590
|
+
version = "0.3.2"
|
|
591
591
|
dependencies = [
|
|
592
592
|
"criterion",
|
|
593
593
|
"once_cell",
|
|
@@ -602,7 +602,7 @@ dependencies = [
|
|
|
602
602
|
|
|
603
603
|
[[package]]
|
|
604
604
|
name = "polyglot-sql-ffi"
|
|
605
|
-
version = "0.3.
|
|
605
|
+
version = "0.3.2"
|
|
606
606
|
dependencies = [
|
|
607
607
|
"cbindgen",
|
|
608
608
|
"polyglot-sql",
|
|
@@ -612,11 +612,11 @@ dependencies = [
|
|
|
612
612
|
|
|
613
613
|
[[package]]
|
|
614
614
|
name = "polyglot-sql-function-catalogs"
|
|
615
|
-
version = "0.3.
|
|
615
|
+
version = "0.3.2"
|
|
616
616
|
|
|
617
617
|
[[package]]
|
|
618
618
|
name = "polyglot-sql-python"
|
|
619
|
-
version = "0.3.
|
|
619
|
+
version = "0.3.2"
|
|
620
620
|
dependencies = [
|
|
621
621
|
"polyglot-sql",
|
|
622
622
|
"pyo3",
|
|
@@ -627,7 +627,7 @@ dependencies = [
|
|
|
627
627
|
|
|
628
628
|
[[package]]
|
|
629
629
|
name = "polyglot-sql-wasm"
|
|
630
|
-
version = "0.3.
|
|
630
|
+
version = "0.3.2"
|
|
631
631
|
dependencies = [
|
|
632
632
|
"console_error_panic_hook",
|
|
633
633
|
"js-sys",
|
|
@@ -78,7 +78,7 @@ serde_json = { workspace = true }
|
|
|
78
78
|
thiserror = { workspace = true }
|
|
79
79
|
unicode-segmentation = { workspace = true }
|
|
80
80
|
ts-rs = { version = "12.0", features = ["serde-compat"], optional = true }
|
|
81
|
-
polyglot-sql-function-catalogs = { path = "../polyglot-sql-function-catalogs", version = "0.3.
|
|
81
|
+
polyglot-sql-function-catalogs = { path = "../polyglot-sql-function-catalogs", version = "0.3.2", optional = true, default-features = false }
|
|
82
82
|
|
|
83
83
|
[dev-dependencies]
|
|
84
84
|
pretty_assertions = "1.4"
|
|
@@ -422,6 +422,18 @@ pub fn get_table_names(expr: &Expression) -> Vec<String> {
|
|
|
422
422
|
}
|
|
423
423
|
}
|
|
424
424
|
}
|
|
425
|
+
Expression::Cache(cache) => {
|
|
426
|
+
let name = cache.table.name.clone();
|
|
427
|
+
if !name.is_empty() && !cte_aliases.contains(&name) {
|
|
428
|
+
names.push(name);
|
|
429
|
+
}
|
|
430
|
+
}
|
|
431
|
+
Expression::Uncache(uncache) => {
|
|
432
|
+
let name = uncache.table.name.clone();
|
|
433
|
+
if !name.is_empty() && !cte_aliases.contains(&name) {
|
|
434
|
+
names.push(name);
|
|
435
|
+
}
|
|
436
|
+
}
|
|
425
437
|
_ => {}
|
|
426
438
|
}
|
|
427
439
|
}
|
|
@@ -1142,9 +1142,7 @@ impl BigQueryDialect {
|
|
|
1142
1142
|
let unit_name = match &unit_expr {
|
|
1143
1143
|
Expression::Identifier(id) => id.name.to_uppercase(),
|
|
1144
1144
|
Expression::Var(v) => v.this.to_uppercase(),
|
|
1145
|
-
Expression::Column(col) if col.table.is_none() =>
|
|
1146
|
-
col.name.name.to_uppercase()
|
|
1147
|
-
}
|
|
1145
|
+
Expression::Column(col) if col.table.is_none() => col.name.name.to_uppercase(),
|
|
1148
1146
|
_ => "DAY".to_string(),
|
|
1149
1147
|
};
|
|
1150
1148
|
let unit = match unit_name.as_str() {
|
|
@@ -13,9 +13,9 @@ use super::{DialectImpl, DialectType};
|
|
|
13
13
|
use crate::error::Result;
|
|
14
14
|
use crate::expressions::{
|
|
15
15
|
AggFunc, Alias, BinaryOp, Case, Cast, CeilFunc, Column, DataType, Expression, Function,
|
|
16
|
-
Identifier, Interval, IntervalUnit, IntervalUnitSpec, IsNull, JSONPath,
|
|
17
|
-
|
|
18
|
-
|
|
16
|
+
Identifier, Interval, IntervalUnit, IntervalUnitSpec, IsNull, JSONPath, JSONPathKey,
|
|
17
|
+
JSONPathRoot, JSONPathSubscript, JsonExtractFunc, Literal, Null, Paren, Struct, Subquery,
|
|
18
|
+
SubstringFunc, UnaryFunc, UnaryOp, VarArgFunc, WindowFunction,
|
|
19
19
|
};
|
|
20
20
|
use crate::generator::GeneratorConfig;
|
|
21
21
|
use crate::tokens::TokenizerConfig;
|
|
@@ -4109,7 +4109,7 @@ impl Dialect {
|
|
|
4109
4109
|
DuckDBTryCastJsonToTryJsonParse, // DuckDB TRY_CAST(x AS JSON) -> TRY(JSON_PARSE(x)) for Trino/Presto/Athena
|
|
4110
4110
|
DuckDBJsonFuncToJsonParse, // DuckDB json(x) -> JSON_PARSE(x) for Trino/Presto/Athena
|
|
4111
4111
|
DuckDBJsonValidToIsJson, // DuckDB json_valid(x) -> x IS JSON for Trino/Presto/Athena
|
|
4112
|
-
ArraySyntaxConvert,
|
|
4112
|
+
ArraySyntaxConvert, // ARRAY[x] -> ARRAY(x) for Spark, [x] for BigQuery/DuckDB
|
|
4113
4113
|
AtTimeZoneConvert, // AT TIME ZONE -> AT_TIMEZONE (Presto) / FROM_UTC_TIMESTAMP (Spark)
|
|
4114
4114
|
DayOfWeekConvert, // DAY_OF_WEEK -> dialect-specific
|
|
4115
4115
|
MaxByMinByConvert, // MAX_BY/MIN_BY -> argMax/argMin for ClickHouse
|
|
@@ -20066,20 +20066,27 @@ impl Dialect {
|
|
|
20066
20066
|
// DuckDB supports TRUNC(x, decimals) — preserve both args
|
|
20067
20067
|
let mut args = f.args;
|
|
20068
20068
|
// Snowflake fractions_supported: wrap non-INT decimals in CAST(... AS INT)
|
|
20069
|
-
if args.len() == 2
|
|
20069
|
+
if args.len() == 2
|
|
20070
|
+
&& matches!(source, DialectType::Snowflake)
|
|
20071
|
+
{
|
|
20070
20072
|
let decimals = args.remove(1);
|
|
20071
20073
|
let is_int = matches!(&decimals, Expression::Literal(lit) if matches!(lit.as_ref(), Literal::Number(_)))
|
|
20072
20074
|
|| matches!(&decimals, Expression::Cast(c) if matches!(c.to, DataType::Int { .. } | DataType::SmallInt { .. } | DataType::BigInt { .. } | DataType::TinyInt { .. }));
|
|
20073
20075
|
let wrapped = if !is_int {
|
|
20074
|
-
Expression::Cast(Box::new(
|
|
20075
|
-
|
|
20076
|
-
|
|
20077
|
-
|
|
20078
|
-
|
|
20079
|
-
|
|
20080
|
-
|
|
20081
|
-
|
|
20082
|
-
|
|
20076
|
+
Expression::Cast(Box::new(
|
|
20077
|
+
crate::expressions::Cast {
|
|
20078
|
+
this: decimals,
|
|
20079
|
+
to: DataType::Int {
|
|
20080
|
+
length: None,
|
|
20081
|
+
integer_spelling: false,
|
|
20082
|
+
},
|
|
20083
|
+
double_colon_syntax: false,
|
|
20084
|
+
trailing_comments: Vec::new(),
|
|
20085
|
+
format: None,
|
|
20086
|
+
default: None,
|
|
20087
|
+
inferred_type: None,
|
|
20088
|
+
},
|
|
20089
|
+
))
|
|
20083
20090
|
} else {
|
|
20084
20091
|
decimals
|
|
20085
20092
|
};
|
|
@@ -22230,14 +22237,12 @@ impl Dialect {
|
|
|
22230
22237
|
// DuckDB json_valid(x) -> x IS JSON (SQL:2016 predicate) for Trino/Presto/Athena
|
|
22231
22238
|
if let Expression::Function(mut f) = e {
|
|
22232
22239
|
let arg = f.args.remove(0);
|
|
22233
|
-
Ok(Expression::IsJson(Box::new(
|
|
22234
|
-
|
|
22235
|
-
|
|
22236
|
-
|
|
22237
|
-
|
|
22238
|
-
|
|
22239
|
-
},
|
|
22240
|
-
)))
|
|
22240
|
+
Ok(Expression::IsJson(Box::new(crate::expressions::IsJson {
|
|
22241
|
+
this: arg,
|
|
22242
|
+
json_type: None,
|
|
22243
|
+
unique_keys: None,
|
|
22244
|
+
negated: false,
|
|
22245
|
+
})))
|
|
22241
22246
|
} else {
|
|
22242
22247
|
Ok(e)
|
|
22243
22248
|
}
|
|
@@ -35998,9 +36003,7 @@ mod tests {
|
|
|
35998
36003
|
#[test]
|
|
35999
36004
|
fn test_pg_hash_bitwise_xor() {
|
|
36000
36005
|
let dialect = Dialect::get(DialectType::PostgreSQL);
|
|
36001
|
-
let result = dialect
|
|
36002
|
-
.transpile("x # y", DialectType::PostgreSQL)
|
|
36003
|
-
.unwrap();
|
|
36006
|
+
let result = dialect.transpile("x # y", DialectType::PostgreSQL).unwrap();
|
|
36004
36007
|
assert_eq!(result[0], "x # y");
|
|
36005
36008
|
}
|
|
36006
36009
|
|
|
@@ -355,9 +355,7 @@ impl SQLiteDialect {
|
|
|
355
355
|
}
|
|
356
356
|
Expression::Identifier(id) => id.name.to_lowercase(),
|
|
357
357
|
Expression::Var(v) => v.this.to_lowercase(),
|
|
358
|
-
Expression::Column(col) if col.table.is_none() =>
|
|
359
|
-
col.name.name.to_lowercase()
|
|
360
|
-
}
|
|
358
|
+
Expression::Column(col) if col.table.is_none() => col.name.name.to_lowercase(),
|
|
361
359
|
_ => "day".to_string(),
|
|
362
360
|
};
|
|
363
361
|
|
|
@@ -10603,6 +10603,9 @@ pub struct MultitableInserts {
|
|
|
10603
10603
|
/// Leading comments before the statement
|
|
10604
10604
|
#[serde(default)]
|
|
10605
10605
|
pub leading_comments: Vec<String>,
|
|
10606
|
+
/// OVERWRITE modifier (Snowflake: INSERT OVERWRITE ALL)
|
|
10607
|
+
#[serde(default, skip_serializing_if = "std::ops::Not::not")]
|
|
10608
|
+
pub overwrite: bool,
|
|
10606
10609
|
}
|
|
10607
10610
|
|
|
10608
10611
|
/// OnConflict
|
|
@@ -31138,8 +31138,12 @@ impl Generator {
|
|
|
31138
31138
|
self.write_space();
|
|
31139
31139
|
}
|
|
31140
31140
|
}
|
|
31141
|
-
// Python: INSERT kind expressions source
|
|
31141
|
+
// Python: INSERT [OVERWRITE] kind expressions source
|
|
31142
31142
|
self.write_keyword("INSERT");
|
|
31143
|
+
if e.overwrite {
|
|
31144
|
+
self.write_space();
|
|
31145
|
+
self.write_keyword("OVERWRITE");
|
|
31146
|
+
}
|
|
31143
31147
|
self.write_space();
|
|
31144
31148
|
self.write(&e.kind);
|
|
31145
31149
|
if self.config.pretty {
|
|
@@ -846,17 +846,48 @@ mod format_tests {
|
|
|
846
846
|
#[test]
|
|
847
847
|
fn transpile_matches_dialect_method() {
|
|
848
848
|
let cases: &[(DialectType, DialectType, &str, &str, &str)] = &[
|
|
849
|
-
(
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
849
|
+
(
|
|
850
|
+
DialectType::DuckDB,
|
|
851
|
+
DialectType::Trino,
|
|
852
|
+
"duckdb",
|
|
853
|
+
"trino",
|
|
854
|
+
"SELECT to_timestamp(col) FROM t",
|
|
855
|
+
),
|
|
856
|
+
(
|
|
857
|
+
DialectType::DuckDB,
|
|
858
|
+
DialectType::Trino,
|
|
859
|
+
"duckdb",
|
|
860
|
+
"trino",
|
|
861
|
+
"SELECT CAST(col AS JSON) FROM t",
|
|
862
|
+
),
|
|
863
|
+
(
|
|
864
|
+
DialectType::DuckDB,
|
|
865
|
+
DialectType::Trino,
|
|
866
|
+
"duckdb",
|
|
867
|
+
"trino",
|
|
868
|
+
"SELECT json_valid(col) FROM t",
|
|
869
|
+
),
|
|
870
|
+
(
|
|
871
|
+
DialectType::Snowflake,
|
|
872
|
+
DialectType::DuckDB,
|
|
873
|
+
"snowflake",
|
|
874
|
+
"duckdb",
|
|
875
|
+
"SELECT DATEDIFF(day, a, b) FROM t",
|
|
876
|
+
),
|
|
877
|
+
(
|
|
878
|
+
DialectType::BigQuery,
|
|
879
|
+
DialectType::DuckDB,
|
|
880
|
+
"bigquery",
|
|
881
|
+
"duckdb",
|
|
882
|
+
"SELECT DATE_DIFF(a, b, DAY) FROM t",
|
|
883
|
+
),
|
|
884
|
+
(
|
|
885
|
+
DialectType::Generic,
|
|
886
|
+
DialectType::Generic,
|
|
887
|
+
"generic",
|
|
888
|
+
"generic",
|
|
889
|
+
"SELECT 1",
|
|
890
|
+
),
|
|
860
891
|
];
|
|
861
892
|
for (read, write, read_name, write_name, sql) in cases {
|
|
862
893
|
let via_lib = transpile(sql, *read, *write).expect("lib::transpile failed");
|
|
@@ -250,12 +250,13 @@ pub fn expand_cte_stars(expr: &mut Expression, schema: Option<&dyn Schema>) {
|
|
|
250
250
|
// a source in its own body, skip it. Non-recursive CTEs in a recursive WITH
|
|
251
251
|
// block are still expanded.
|
|
252
252
|
if with.recursive {
|
|
253
|
-
let is_self_referencing =
|
|
254
|
-
let
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
253
|
+
let is_self_referencing =
|
|
254
|
+
if let Some(body_select) = get_leftmost_select_mut(&mut cte.this) {
|
|
255
|
+
let body_sources = get_select_sources(body_select);
|
|
256
|
+
body_sources.iter().any(|s| s.normalized == cte_name)
|
|
257
|
+
} else {
|
|
258
|
+
false
|
|
259
|
+
};
|
|
259
260
|
if is_self_referencing {
|
|
260
261
|
continue;
|
|
261
262
|
}
|
|
@@ -332,12 +333,9 @@ fn rewrite_stars_in_select(
|
|
|
332
333
|
match expr {
|
|
333
334
|
Expression::Star(star) => {
|
|
334
335
|
let qual = star.table.as_ref();
|
|
335
|
-
if let Some(expanded) =
|
|
336
|
-
qual,
|
|
337
|
-
|
|
338
|
-
resolved_ctes,
|
|
339
|
-
schema,
|
|
340
|
-
) {
|
|
336
|
+
if let Some(expanded) =
|
|
337
|
+
expand_star_from_sources(qual, &sources, resolved_ctes, schema)
|
|
338
|
+
{
|
|
341
339
|
for (src_alias, col_name) in &expanded {
|
|
342
340
|
let table_id = Identifier::new(src_alias);
|
|
343
341
|
new_expressions.push(make_column_expr(col_name, Some(&table_id)));
|
|
@@ -350,12 +348,9 @@ fn rewrite_stars_in_select(
|
|
|
350
348
|
}
|
|
351
349
|
Expression::Column(c) if c.name.name == "*" => {
|
|
352
350
|
let qual = c.table.as_ref();
|
|
353
|
-
if let Some(expanded) =
|
|
354
|
-
qual,
|
|
355
|
-
|
|
356
|
-
resolved_ctes,
|
|
357
|
-
schema,
|
|
358
|
-
) {
|
|
351
|
+
if let Some(expanded) =
|
|
352
|
+
expand_star_from_sources(qual, &sources, resolved_ctes, schema)
|
|
353
|
+
{
|
|
359
354
|
for (_src_alias, col_name) in &expanded {
|
|
360
355
|
// Keep the original table qualifier for qualified stars (table.*)
|
|
361
356
|
new_expressions.push(make_column_expr(col_name, c.table.as_ref()));
|
|
@@ -441,7 +436,10 @@ fn lookup_schema_columns(schema: Option<&dyn Schema>, fq_name: &str) -> Option<V
|
|
|
441
436
|
if fq_name.is_empty() {
|
|
442
437
|
return None;
|
|
443
438
|
}
|
|
444
|
-
schema
|
|
439
|
+
schema
|
|
440
|
+
.column_names(fq_name)
|
|
441
|
+
.ok()
|
|
442
|
+
.filter(|cols| !cols.is_empty() && !cols.contains(&"*".to_string()))
|
|
445
443
|
}
|
|
446
444
|
|
|
447
445
|
/// Create a Column expression with the given name and optional table qualifier.
|
|
@@ -499,13 +497,21 @@ fn get_select_sources(select: &Select) -> Vec<SourceInfo> {
|
|
|
499
497
|
}
|
|
500
498
|
parts.push(t.name.name.clone());
|
|
501
499
|
let fq_name = parts.join(".");
|
|
502
|
-
Some(SourceInfo {
|
|
500
|
+
Some(SourceInfo {
|
|
501
|
+
alias,
|
|
502
|
+
normalized,
|
|
503
|
+
fq_name,
|
|
504
|
+
})
|
|
503
505
|
}
|
|
504
506
|
Expression::Subquery(s) => {
|
|
505
507
|
let alias = s.alias.as_ref()?.name.clone();
|
|
506
508
|
let normalized = alias.to_lowercase();
|
|
507
509
|
let fq_name = alias.clone();
|
|
508
|
-
Some(SourceInfo {
|
|
510
|
+
Some(SourceInfo {
|
|
511
|
+
alias,
|
|
512
|
+
normalized,
|
|
513
|
+
fq_name,
|
|
514
|
+
})
|
|
509
515
|
}
|
|
510
516
|
Expression::Paren(p) => extract_source(&p.this),
|
|
511
517
|
_ => None,
|
|
@@ -816,9 +822,9 @@ fn resolve_qualified_column(
|
|
|
816
822
|
// Check if table is a CTE reference — check both the current scope's cte_sources
|
|
817
823
|
// and ancestor CTE scopes (for sibling CTEs in parent WITH clauses).
|
|
818
824
|
let is_cte = scope.cte_sources.contains_key(effective_table)
|
|
819
|
-
|| all_cte_scopes.iter().any(
|
|
820
|
-
matches!(&s.expression, Expression::Cte(cte) if cte.alias.name == effective_table)
|
|
821
|
-
|
|
825
|
+
|| all_cte_scopes.iter().any(
|
|
826
|
+
|s| matches!(&s.expression, Expression::Cte(cte) if cte.alias.name == effective_table),
|
|
827
|
+
);
|
|
822
828
|
if is_cte {
|
|
823
829
|
if let Some(child_scope) = find_child_scope_in(all_cte_scopes, scope, effective_table) {
|
|
824
830
|
// Build ancestor CTE scopes from all_cte_scopes for the recursive call
|
|
@@ -3261,14 +3267,9 @@ SELECT * FROM orders"#;
|
|
|
3261
3267
|
];
|
|
3262
3268
|
schema.add_table("stg_orders", &cols, None).unwrap();
|
|
3263
3269
|
|
|
3264
|
-
let node =
|
|
3265
|
-
"order_id",
|
|
3266
|
-
|
|
3267
|
-
Some(&schema as &dyn Schema),
|
|
3268
|
-
None,
|
|
3269
|
-
false,
|
|
3270
|
-
)
|
|
3271
|
-
.unwrap();
|
|
3270
|
+
let node =
|
|
3271
|
+
lineage_with_schema("order_id", &expr, Some(&schema as &dyn Schema), None, false)
|
|
3272
|
+
.unwrap();
|
|
3272
3273
|
assert_eq!(node.name, "order_id");
|
|
3273
3274
|
}
|
|
3274
3275
|
|
|
@@ -3284,7 +3285,9 @@ SELECT * FROM orders"#;
|
|
|
3284
3285
|
("order_id".to_string(), DataType::Unknown),
|
|
3285
3286
|
("customer_id".to_string(), DataType::Unknown),
|
|
3286
3287
|
];
|
|
3287
|
-
schema
|
|
3288
|
+
schema
|
|
3289
|
+
.add_table("db.schema.stg_orders", &cols, None)
|
|
3290
|
+
.unwrap();
|
|
3288
3291
|
|
|
3289
3292
|
let node = lineage_with_schema(
|
|
3290
3293
|
"customer_id",
|
|
@@ -3314,14 +3317,8 @@ SELECT * FROM orders"#;
|
|
|
3314
3317
|
];
|
|
3315
3318
|
schema.add_table("external_table", &cols, None).unwrap();
|
|
3316
3319
|
|
|
3317
|
-
let node =
|
|
3318
|
-
"name",
|
|
3319
|
-
&expr,
|
|
3320
|
-
Some(&schema as &dyn Schema),
|
|
3321
|
-
None,
|
|
3322
|
-
false,
|
|
3323
|
-
)
|
|
3324
|
-
.unwrap();
|
|
3320
|
+
let node =
|
|
3321
|
+
lineage_with_schema("name", &expr, Some(&schema as &dyn Schema), None, false).unwrap();
|
|
3325
3322
|
assert_eq!(node.name, "name");
|
|
3326
3323
|
}
|
|
3327
3324
|
|
|
@@ -3345,25 +3342,14 @@ SELECT * FROM orders"#;
|
|
|
3345
3342
|
];
|
|
3346
3343
|
schema.add_table("stg_orders", &cols, None).unwrap();
|
|
3347
3344
|
|
|
3348
|
-
let node =
|
|
3349
|
-
"order_id",
|
|
3350
|
-
|
|
3351
|
-
Some(&schema as &dyn Schema),
|
|
3352
|
-
None,
|
|
3353
|
-
false,
|
|
3354
|
-
)
|
|
3355
|
-
.unwrap();
|
|
3345
|
+
let node =
|
|
3346
|
+
lineage_with_schema("order_id", &expr, Some(&schema as &dyn Schema), None, false)
|
|
3347
|
+
.unwrap();
|
|
3356
3348
|
assert_eq!(node.name, "order_id");
|
|
3357
3349
|
|
|
3358
3350
|
// Also verify the extra column works
|
|
3359
|
-
let extra =
|
|
3360
|
-
"extra",
|
|
3361
|
-
&expr,
|
|
3362
|
-
Some(&schema as &dyn Schema),
|
|
3363
|
-
None,
|
|
3364
|
-
false,
|
|
3365
|
-
)
|
|
3366
|
-
.unwrap();
|
|
3351
|
+
let extra =
|
|
3352
|
+
lineage_with_schema("extra", &expr, Some(&schema as &dyn Schema), None, false).unwrap();
|
|
3367
3353
|
assert_eq!(extra.name, "extra");
|
|
3368
3354
|
}
|
|
3369
3355
|
|
|
@@ -3404,38 +3390,59 @@ SELECT * FROM final_cte"#;
|
|
|
3404
3390
|
|
|
3405
3391
|
let mut schema = MappingSchema::new();
|
|
3406
3392
|
let order_cols = vec![
|
|
3407
|
-
(
|
|
3408
|
-
|
|
3393
|
+
(
|
|
3394
|
+
"order_id".to_string(),
|
|
3395
|
+
crate::expressions::DataType::Unknown,
|
|
3396
|
+
),
|
|
3397
|
+
(
|
|
3398
|
+
"customer_id".to_string(),
|
|
3399
|
+
crate::expressions::DataType::Unknown,
|
|
3400
|
+
),
|
|
3409
3401
|
("status".to_string(), crate::expressions::DataType::Unknown),
|
|
3410
3402
|
];
|
|
3411
3403
|
let pay_cols = vec![
|
|
3412
|
-
(
|
|
3413
|
-
|
|
3404
|
+
(
|
|
3405
|
+
"payment_id".to_string(),
|
|
3406
|
+
crate::expressions::DataType::Unknown,
|
|
3407
|
+
),
|
|
3408
|
+
(
|
|
3409
|
+
"order_id".to_string(),
|
|
3410
|
+
crate::expressions::DataType::Unknown,
|
|
3411
|
+
),
|
|
3414
3412
|
("amount".to_string(), crate::expressions::DataType::Unknown),
|
|
3415
3413
|
];
|
|
3416
3414
|
schema.add_table("stg_orders", &order_cols, None).unwrap();
|
|
3417
3415
|
schema.add_table("stg_payments", &pay_cols, None).unwrap();
|
|
3418
3416
|
|
|
3419
3417
|
// order_id should trace back to stg_orders
|
|
3420
|
-
let node =
|
|
3421
|
-
"order_id", &expr, Some(&schema as &dyn Schema), None, false
|
|
3422
|
-
|
|
3418
|
+
let node =
|
|
3419
|
+
lineage_with_schema("order_id", &expr, Some(&schema as &dyn Schema), None, false)
|
|
3420
|
+
.unwrap();
|
|
3423
3421
|
let all_names: Vec<_> = node.walk().map(|n| n.name.clone()).collect();
|
|
3424
3422
|
|
|
3425
3423
|
// The leaf should be "stg_orders.order_id" (not just "order_id")
|
|
3426
|
-
let has_table_qualified = all_names
|
|
3427
|
-
|
|
3428
|
-
|
|
3424
|
+
let has_table_qualified = all_names
|
|
3425
|
+
.iter()
|
|
3426
|
+
.any(|n| n.contains('.') && n.contains("order_id"));
|
|
3427
|
+
assert!(
|
|
3428
|
+
has_table_qualified,
|
|
3429
|
+
"Expected table-qualified leaf like 'stg_orders.order_id', got: {:?}",
|
|
3430
|
+
all_names
|
|
3431
|
+
);
|
|
3429
3432
|
|
|
3430
3433
|
// amount should trace back to stg_payments
|
|
3431
|
-
let node = lineage_with_schema(
|
|
3432
|
-
|
|
3433
|
-
).unwrap();
|
|
3434
|
+
let node = lineage_with_schema("amount", &expr, Some(&schema as &dyn Schema), None, false)
|
|
3435
|
+
.unwrap();
|
|
3434
3436
|
let all_names: Vec<_> = node.walk().map(|n| n.name.clone()).collect();
|
|
3435
3437
|
|
|
3436
|
-
let has_table_qualified = all_names
|
|
3437
|
-
|
|
3438
|
-
|
|
3438
|
+
let has_table_qualified = all_names
|
|
3439
|
+
.iter()
|
|
3440
|
+
.any(|n| n.contains('.') && n.contains("amount"));
|
|
3441
|
+
assert!(
|
|
3442
|
+
has_table_qualified,
|
|
3443
|
+
"Expected table-qualified leaf like 'stg_payments.amount', got: {:?}",
|
|
3444
|
+
all_names
|
|
3445
|
+
);
|
|
3439
3446
|
}
|
|
3440
3447
|
|
|
3441
3448
|
#[test]
|
|
@@ -3481,14 +3488,8 @@ FROM import_stg AS base"#;
|
|
|
3481
3488
|
)
|
|
3482
3489
|
.unwrap();
|
|
3483
3490
|
|
|
3484
|
-
let node = lineage_with_schema(
|
|
3485
|
-
|
|
3486
|
-
&expr,
|
|
3487
|
-
Some(&schema as &dyn Schema),
|
|
3488
|
-
None,
|
|
3489
|
-
false,
|
|
3490
|
-
)
|
|
3491
|
-
.unwrap();
|
|
3491
|
+
let node = lineage_with_schema("item_id", &expr, Some(&schema as &dyn Schema), None, false)
|
|
3492
|
+
.unwrap();
|
|
3492
3493
|
let all_names: Vec<_> = node.walk().map(|n| n.name.clone()).collect();
|
|
3493
3494
|
assert!(
|
|
3494
3495
|
all_names.iter().any(|n| n == "stg_items.item_id"),
|
|
@@ -3533,9 +3534,7 @@ LEFT JOIN import_orders AS o ON u.id = o.user_id"#;
|
|
|
3533
3534
|
fn test_lineage_unquoted_cte_case_insensitive() {
|
|
3534
3535
|
// Unquoted CTE names are case-insensitive (both normalized to lowercase).
|
|
3535
3536
|
// MyCte and MYCTE should match.
|
|
3536
|
-
let expr = parse(
|
|
3537
|
-
"WITH MyCte AS (SELECT id AS col FROM source) SELECT * FROM MYCTE",
|
|
3538
|
-
);
|
|
3537
|
+
let expr = parse("WITH MyCte AS (SELECT id AS col FROM source) SELECT * FROM MYCTE");
|
|
3539
3538
|
let node = lineage("col", &expr, None, false).unwrap();
|
|
3540
3539
|
assert_eq!(node.name, "col");
|
|
3541
3540
|
assert!(
|
|
@@ -3547,9 +3546,7 @@ LEFT JOIN import_orders AS o ON u.id = o.user_id"#;
|
|
|
3547
3546
|
#[test]
|
|
3548
3547
|
fn test_lineage_quoted_cte_case_preserved() {
|
|
3549
3548
|
// Quoted CTE name preserves case. "MyCte" referenced as "MyCte" should match.
|
|
3550
|
-
let expr = parse(
|
|
3551
|
-
r#"WITH "MyCte" AS (SELECT id AS col FROM source) SELECT * FROM "MyCte""#,
|
|
3552
|
-
);
|
|
3549
|
+
let expr = parse(r#"WITH "MyCte" AS (SELECT id AS col FROM source) SELECT * FROM "MyCte""#);
|
|
3553
3550
|
let node = lineage("col", &expr, None, false).unwrap();
|
|
3554
3551
|
assert_eq!(node.name, "col");
|
|
3555
3552
|
assert!(
|
|
@@ -3563,9 +3560,7 @@ LEFT JOIN import_orders AS o ON u.id = o.user_id"#;
|
|
|
3563
3560
|
// Quoted CTE "MyCte" referenced as "mycte" — case mismatch.
|
|
3564
3561
|
// sqlglot treats this as a table reference, not a CTE match.
|
|
3565
3562
|
// Star expansion should NOT resolve through the CTE.
|
|
3566
|
-
let expr = parse(
|
|
3567
|
-
r#"WITH "MyCte" AS (SELECT id AS col FROM source) SELECT * FROM "mycte""#,
|
|
3568
|
-
);
|
|
3563
|
+
let expr = parse(r#"WITH "MyCte" AS (SELECT id AS col FROM source) SELECT * FROM "mycte""#);
|
|
3569
3564
|
// lineage("col", ...) should fail because "mycte" is treated as an external
|
|
3570
3565
|
// table (not matching CTE "MyCte"), and SELECT * cannot be expanded.
|
|
3571
3566
|
let result = lineage("col", &expr, None, false);
|
|
@@ -3617,9 +3612,7 @@ LEFT JOIN import_orders AS o ON u.id = o.user_id"#;
|
|
|
3617
3612
|
// This test asserts the CURRENT BUGGY behavior. When the bug is fixed,
|
|
3618
3613
|
// this test should fail — update the assertion to match correct behavior:
|
|
3619
3614
|
// child.source_name should be "" (table ref), not "MyCte" (CTE ref).
|
|
3620
|
-
let expr = parse(
|
|
3621
|
-
r#"WITH "MyCte" AS (SELECT 1 AS col) SELECT col FROM "mycte""#,
|
|
3622
|
-
);
|
|
3615
|
+
let expr = parse(r#"WITH "MyCte" AS (SELECT 1 AS col) SELECT col FROM "mycte""#);
|
|
3623
3616
|
let node = lineage("col", &expr, None, false).unwrap();
|
|
3624
3617
|
assert!(!node.downstream.is_empty());
|
|
3625
3618
|
let child = &node.downstream[0];
|
|
@@ -3639,9 +3632,7 @@ LEFT JOIN import_orders AS o ON u.id = o.user_id"#;
|
|
|
3639
3632
|
//
|
|
3640
3633
|
// This test asserts the CURRENT BUGGY behavior. When the bug is fixed,
|
|
3641
3634
|
// this test should fail — update to assert source_name != "MyCte".
|
|
3642
|
-
let expr = parse(
|
|
3643
|
-
r#"WITH "MyCte" AS (SELECT 1 AS col) SELECT "mycte".col FROM "mycte""#,
|
|
3644
|
-
);
|
|
3635
|
+
let expr = parse(r#"WITH "MyCte" AS (SELECT 1 AS col) SELECT "mycte".col FROM "mycte""#);
|
|
3645
3636
|
let node = lineage("col", &expr, None, false).unwrap();
|
|
3646
3637
|
assert!(!node.downstream.is_empty());
|
|
3647
3638
|
let child = &node.downstream[0];
|