polyglot-sql 0.6.3__tar.gz → 0.7.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.
- {polyglot_sql-0.6.3 → polyglot_sql-0.7.0}/Cargo.lock +6 -6
- {polyglot_sql-0.6.3 → polyglot_sql-0.7.0}/Cargo.toml +1 -1
- {polyglot_sql-0.6.3 → polyglot_sql-0.7.0}/PKG-INFO +7 -1
- {polyglot_sql-0.6.3/crates/polyglot-sql-python → polyglot_sql-0.7.0}/README.md +6 -0
- {polyglot_sql-0.6.3 → polyglot_sql-0.7.0}/crates/polyglot-sql/Cargo.toml +2 -2
- {polyglot_sql-0.6.3 → polyglot_sql-0.7.0}/crates/polyglot-sql/README.md +1 -1
- {polyglot_sql-0.6.3 → polyglot_sql-0.7.0}/crates/polyglot-sql/src/dialects/duckdb.rs +9 -9
- {polyglot_sql-0.6.3 → polyglot_sql-0.7.0}/crates/polyglot-sql/src/dialects/mod.rs +15 -0
- {polyglot_sql-0.6.3 → polyglot_sql-0.7.0}/crates/polyglot-sql/src/dialects/normalization/aggregates.rs +67 -15
- {polyglot_sql-0.6.3 → polyglot_sql-0.7.0}/crates/polyglot-sql/src/dialects/normalization/collections.rs +5 -1
- {polyglot_sql-0.6.3 → polyglot_sql-0.7.0}/crates/polyglot-sql/src/dialects/normalization/mod.rs +234 -4
- {polyglot_sql-0.6.3 → polyglot_sql-0.7.0}/crates/polyglot-sql/src/dialects/normalization/scalar.rs +351 -57
- {polyglot_sql-0.6.3 → polyglot_sql-0.7.0}/crates/polyglot-sql/src/dialects/normalization/statements.rs +140 -0
- {polyglot_sql-0.6.3 → polyglot_sql-0.7.0}/crates/polyglot-sql/src/dialects/normalization/temporal.rs +18 -6
- {polyglot_sql-0.6.3 → polyglot_sql-0.7.0}/crates/polyglot-sql/src/dialects/oracle.rs +2 -0
- {polyglot_sql-0.6.3 → polyglot_sql-0.7.0}/crates/polyglot-sql/src/dialects/presto.rs +8 -8
- {polyglot_sql-0.6.3 → polyglot_sql-0.7.0}/crates/polyglot-sql/src/error.rs +69 -0
- {polyglot_sql-0.6.3 → polyglot_sql-0.7.0}/crates/polyglot-sql/src/expressions.rs +6 -0
- {polyglot_sql-0.6.3 → polyglot_sql-0.7.0}/crates/polyglot-sql/src/generator.rs +187 -44
- {polyglot_sql-0.6.3 → polyglot_sql-0.7.0}/crates/polyglot-sql/src/lib.rs +10 -1
- {polyglot_sql-0.6.3 → polyglot_sql-0.7.0}/crates/polyglot-sql/src/lineage.rs +639 -114
- {polyglot_sql-0.6.3 → polyglot_sql-0.7.0}/crates/polyglot-sql/src/parser.rs +355 -56
- {polyglot_sql-0.6.3 → polyglot_sql-0.7.0}/crates/polyglot-sql/src/schema.rs +32 -6
- {polyglot_sql-0.6.3 → polyglot_sql-0.7.0}/crates/polyglot-sql/src/tokens.rs +24 -12
- {polyglot_sql-0.6.3 → polyglot_sql-0.7.0/crates/polyglot-sql-python}/README.md +6 -0
- {polyglot_sql-0.6.3 → polyglot_sql-0.7.0}/crates/polyglot-sql-python/src/errors.rs +31 -1
- {polyglot_sql-0.6.3 → polyglot_sql-0.7.0}/crates/polyglot-sql-python/src/lib.rs +4 -0
- polyglot_sql-0.7.0/crates/polyglot-sql-python/src/lineage.rs +222 -0
- {polyglot_sql-0.6.3 → polyglot_sql-0.7.0}/crates/polyglot-sql-python/tests/test_lineage.py +36 -0
- {polyglot_sql-0.6.3 → polyglot_sql-0.7.0}/python/polyglot_sql/__init__.py +10 -0
- {polyglot_sql-0.6.3 → polyglot_sql-0.7.0}/python/polyglot_sql/__init__.pyi +39 -0
- polyglot_sql-0.6.3/crates/polyglot-sql-python/src/lineage.rs +0 -100
- {polyglot_sql-0.6.3 → polyglot_sql-0.7.0}/crates/polyglot-sql/benches/allocation_hotspots.rs +0 -0
- {polyglot_sql-0.6.3 → polyglot_sql-0.7.0}/crates/polyglot-sql/benches/ast_traversal.rs +0 -0
- {polyglot_sql-0.6.3 → polyglot_sql-0.7.0}/crates/polyglot-sql/benches/in_list.rs +0 -0
- {polyglot_sql-0.6.3 → polyglot_sql-0.7.0}/crates/polyglot-sql/benches/lineage.rs +0 -0
- {polyglot_sql-0.6.3 → polyglot_sql-0.7.0}/crates/polyglot-sql/benches/parsing.rs +0 -0
- {polyglot_sql-0.6.3 → polyglot_sql-0.7.0}/crates/polyglot-sql/benches/performance_hotspots.rs +0 -0
- {polyglot_sql-0.6.3 → polyglot_sql-0.7.0}/crates/polyglot-sql/benches/rust_parsing.rs +0 -0
- {polyglot_sql-0.6.3 → polyglot_sql-0.7.0}/crates/polyglot-sql/benches/transpile.rs +0 -0
- {polyglot_sql-0.6.3 → polyglot_sql-0.7.0}/crates/polyglot-sql/examples/basic_usage.rs +0 -0
- {polyglot_sql-0.6.3 → polyglot_sql-0.7.0}/crates/polyglot-sql/examples/bench_json.rs +0 -0
- {polyglot_sql-0.6.3 → polyglot_sql-0.7.0}/crates/polyglot-sql/src/ast_children.rs +0 -0
- {polyglot_sql-0.6.3 → polyglot_sql-0.7.0}/crates/polyglot-sql/src/ast_json.rs +0 -0
- {polyglot_sql-0.6.3 → polyglot_sql-0.7.0}/crates/polyglot-sql/src/ast_transforms.rs +0 -0
- {polyglot_sql-0.6.3 → polyglot_sql-0.7.0}/crates/polyglot-sql/src/builder.rs +0 -0
- {polyglot_sql-0.6.3 → polyglot_sql-0.7.0}/crates/polyglot-sql/src/dialects/athena.rs +0 -0
- {polyglot_sql-0.6.3 → polyglot_sql-0.7.0}/crates/polyglot-sql/src/dialects/bigquery.rs +0 -0
- {polyglot_sql-0.6.3 → polyglot_sql-0.7.0}/crates/polyglot-sql/src/dialects/clickhouse.rs +0 -0
- {polyglot_sql-0.6.3 → polyglot_sql-0.7.0}/crates/polyglot-sql/src/dialects/cockroachdb.rs +0 -0
- {polyglot_sql-0.6.3 → polyglot_sql-0.7.0}/crates/polyglot-sql/src/dialects/databricks.rs +0 -0
- {polyglot_sql-0.6.3 → polyglot_sql-0.7.0}/crates/polyglot-sql/src/dialects/datafusion.rs +0 -0
- {polyglot_sql-0.6.3 → polyglot_sql-0.7.0}/crates/polyglot-sql/src/dialects/doris.rs +0 -0
- {polyglot_sql-0.6.3 → polyglot_sql-0.7.0}/crates/polyglot-sql/src/dialects/dremio.rs +0 -0
- {polyglot_sql-0.6.3 → polyglot_sql-0.7.0}/crates/polyglot-sql/src/dialects/drill.rs +0 -0
- {polyglot_sql-0.6.3 → polyglot_sql-0.7.0}/crates/polyglot-sql/src/dialects/druid.rs +0 -0
- {polyglot_sql-0.6.3 → polyglot_sql-0.7.0}/crates/polyglot-sql/src/dialects/dune.rs +0 -0
- {polyglot_sql-0.6.3 → polyglot_sql-0.7.0}/crates/polyglot-sql/src/dialects/exasol.rs +0 -0
- {polyglot_sql-0.6.3 → polyglot_sql-0.7.0}/crates/polyglot-sql/src/dialects/fabric.rs +0 -0
- {polyglot_sql-0.6.3 → polyglot_sql-0.7.0}/crates/polyglot-sql/src/dialects/generic.rs +0 -0
- {polyglot_sql-0.6.3 → polyglot_sql-0.7.0}/crates/polyglot-sql/src/dialects/hive.rs +0 -0
- {polyglot_sql-0.6.3 → polyglot_sql-0.7.0}/crates/polyglot-sql/src/dialects/materialize.rs +0 -0
- {polyglot_sql-0.6.3 → polyglot_sql-0.7.0}/crates/polyglot-sql/src/dialects/mysql.rs +0 -0
- {polyglot_sql-0.6.3 → polyglot_sql-0.7.0}/crates/polyglot-sql/src/dialects/normalization/json.rs +0 -0
- {polyglot_sql-0.6.3 → polyglot_sql-0.7.0}/crates/polyglot-sql/src/dialects/normalization/operators.rs +0 -0
- {polyglot_sql-0.6.3 → polyglot_sql-0.7.0}/crates/polyglot-sql/src/dialects/normalization/postgres_interval.rs +0 -0
- {polyglot_sql-0.6.3 → polyglot_sql-0.7.0}/crates/polyglot-sql/src/dialects/normalization/types.rs +0 -0
- {polyglot_sql-0.6.3 → polyglot_sql-0.7.0}/crates/polyglot-sql/src/dialects/postgres.rs +0 -0
- {polyglot_sql-0.6.3 → polyglot_sql-0.7.0}/crates/polyglot-sql/src/dialects/redshift.rs +0 -0
- {polyglot_sql-0.6.3 → polyglot_sql-0.7.0}/crates/polyglot-sql/src/dialects/risingwave.rs +0 -0
- {polyglot_sql-0.6.3 → polyglot_sql-0.7.0}/crates/polyglot-sql/src/dialects/singlestore.rs +0 -0
- {polyglot_sql-0.6.3 → polyglot_sql-0.7.0}/crates/polyglot-sql/src/dialects/snowflake.rs +0 -0
- {polyglot_sql-0.6.3 → polyglot_sql-0.7.0}/crates/polyglot-sql/src/dialects/solr.rs +0 -0
- {polyglot_sql-0.6.3 → polyglot_sql-0.7.0}/crates/polyglot-sql/src/dialects/spark.rs +0 -0
- {polyglot_sql-0.6.3 → polyglot_sql-0.7.0}/crates/polyglot-sql/src/dialects/sqlite.rs +0 -0
- {polyglot_sql-0.6.3 → polyglot_sql-0.7.0}/crates/polyglot-sql/src/dialects/starrocks.rs +0 -0
- {polyglot_sql-0.6.3 → polyglot_sql-0.7.0}/crates/polyglot-sql/src/dialects/tableau.rs +0 -0
- {polyglot_sql-0.6.3 → polyglot_sql-0.7.0}/crates/polyglot-sql/src/dialects/teradata.rs +0 -0
- {polyglot_sql-0.6.3 → polyglot_sql-0.7.0}/crates/polyglot-sql/src/dialects/tidb.rs +0 -0
- {polyglot_sql-0.6.3 → polyglot_sql-0.7.0}/crates/polyglot-sql/src/dialects/trino.rs +0 -0
- {polyglot_sql-0.6.3 → polyglot_sql-0.7.0}/crates/polyglot-sql/src/dialects/tsql.rs +0 -0
- {polyglot_sql-0.6.3 → polyglot_sql-0.7.0}/crates/polyglot-sql/src/diff.rs +0 -0
- {polyglot_sql-0.6.3 → polyglot_sql-0.7.0}/crates/polyglot-sql/src/format_tokens.rs +0 -0
- {polyglot_sql-0.6.3 → polyglot_sql-0.7.0}/crates/polyglot-sql/src/function_catalog.rs +0 -0
- {polyglot_sql-0.6.3 → polyglot_sql-0.7.0}/crates/polyglot-sql/src/function_registry.rs +0 -0
- {polyglot_sql-0.6.3 → polyglot_sql-0.7.0}/crates/polyglot-sql/src/guard.rs +0 -0
- {polyglot_sql-0.6.3 → polyglot_sql-0.7.0}/crates/polyglot-sql/src/helper.rs +0 -0
- {polyglot_sql-0.6.3 → polyglot_sql-0.7.0}/crates/polyglot-sql/src/openlineage.rs +0 -0
- {polyglot_sql-0.6.3 → polyglot_sql-0.7.0}/crates/polyglot-sql/src/optimizer/annotate_types.rs +0 -0
- {polyglot_sql-0.6.3 → polyglot_sql-0.7.0}/crates/polyglot-sql/src/optimizer/canonicalize.rs +0 -0
- {polyglot_sql-0.6.3 → polyglot_sql-0.7.0}/crates/polyglot-sql/src/optimizer/eliminate_ctes.rs +0 -0
- {polyglot_sql-0.6.3 → polyglot_sql-0.7.0}/crates/polyglot-sql/src/optimizer/eliminate_joins.rs +0 -0
- {polyglot_sql-0.6.3 → polyglot_sql-0.7.0}/crates/polyglot-sql/src/optimizer/isolate_table_selects.rs +0 -0
- {polyglot_sql-0.6.3 → polyglot_sql-0.7.0}/crates/polyglot-sql/src/optimizer/mod.rs +0 -0
- {polyglot_sql-0.6.3 → polyglot_sql-0.7.0}/crates/polyglot-sql/src/optimizer/normalize.rs +0 -0
- {polyglot_sql-0.6.3 → polyglot_sql-0.7.0}/crates/polyglot-sql/src/optimizer/normalize_identifiers.rs +0 -0
- {polyglot_sql-0.6.3 → polyglot_sql-0.7.0}/crates/polyglot-sql/src/optimizer/optimize_joins.rs +0 -0
- {polyglot_sql-0.6.3 → polyglot_sql-0.7.0}/crates/polyglot-sql/src/optimizer/optimizer.rs +0 -0
- {polyglot_sql-0.6.3 → polyglot_sql-0.7.0}/crates/polyglot-sql/src/optimizer/pushdown_predicates.rs +0 -0
- {polyglot_sql-0.6.3 → polyglot_sql-0.7.0}/crates/polyglot-sql/src/optimizer/pushdown_projections.rs +0 -0
- {polyglot_sql-0.6.3 → polyglot_sql-0.7.0}/crates/polyglot-sql/src/optimizer/qualify_columns.rs +0 -0
- {polyglot_sql-0.6.3 → polyglot_sql-0.7.0}/crates/polyglot-sql/src/optimizer/qualify_tables.rs +0 -0
- {polyglot_sql-0.6.3 → polyglot_sql-0.7.0}/crates/polyglot-sql/src/optimizer/simplify.rs +0 -0
- {polyglot_sql-0.6.3 → polyglot_sql-0.7.0}/crates/polyglot-sql/src/optimizer/subquery.rs +0 -0
- {polyglot_sql-0.6.3 → polyglot_sql-0.7.0}/crates/polyglot-sql/src/planner.rs +0 -0
- {polyglot_sql-0.6.3 → polyglot_sql-0.7.0}/crates/polyglot-sql/src/query_analysis.rs +0 -0
- {polyglot_sql-0.6.3 → polyglot_sql-0.7.0}/crates/polyglot-sql/src/resolver.rs +0 -0
- {polyglot_sql-0.6.3 → polyglot_sql-0.7.0}/crates/polyglot-sql/src/scope.rs +0 -0
- {polyglot_sql-0.6.3 → polyglot_sql-0.7.0}/crates/polyglot-sql/src/time.rs +0 -0
- {polyglot_sql-0.6.3 → polyglot_sql-0.7.0}/crates/polyglot-sql/src/transforms.rs +0 -0
- {polyglot_sql-0.6.3 → polyglot_sql-0.7.0}/crates/polyglot-sql/src/traversal.rs +0 -0
- {polyglot_sql-0.6.3 → polyglot_sql-0.7.0}/crates/polyglot-sql/src/trie.rs +0 -0
- {polyglot_sql-0.6.3 → polyglot_sql-0.7.0}/crates/polyglot-sql/src/validation/tests.rs +0 -0
- {polyglot_sql-0.6.3 → polyglot_sql-0.7.0}/crates/polyglot-sql/src/validation.rs +0 -0
- {polyglot_sql-0.6.3 → polyglot_sql-0.7.0}/crates/polyglot-sql/tests/analyze_failures.rs +0 -0
- {polyglot_sql-0.6.3 → polyglot_sql-0.7.0}/crates/polyglot-sql/tests/clickhouse_regression.rs +0 -0
- {polyglot_sql-0.6.3 → polyglot_sql-0.7.0}/crates/polyglot-sql/tests/common/known_failures.rs +0 -0
- {polyglot_sql-0.6.3 → polyglot_sql-0.7.0}/crates/polyglot-sql/tests/common/mod.rs +0 -0
- {polyglot_sql-0.6.3 → polyglot_sql-0.7.0}/crates/polyglot-sql/tests/common/test_data.rs +0 -0
- {polyglot_sql-0.6.3 → polyglot_sql-0.7.0}/crates/polyglot-sql/tests/common/test_runner.rs +0 -0
- {polyglot_sql-0.6.3 → polyglot_sql-0.7.0}/crates/polyglot-sql/tests/create_view_security_comment_regression.rs +0 -0
- {polyglot_sql-0.6.3 → polyglot_sql-0.7.0}/crates/polyglot-sql/tests/custom_clickhouse_coverage.rs +0 -0
- {polyglot_sql-0.6.3 → polyglot_sql-0.7.0}/crates/polyglot-sql/tests/custom_clickhouse_parser.rs +0 -0
- {polyglot_sql-0.6.3 → polyglot_sql-0.7.0}/crates/polyglot-sql/tests/custom_dialect.rs +0 -0
- {polyglot_sql-0.6.3 → polyglot_sql-0.7.0}/crates/polyglot-sql/tests/custom_dialect_tests.rs +0 -0
- {polyglot_sql-0.6.3 → polyglot_sql-0.7.0}/crates/polyglot-sql/tests/custom_fixtures/datafusion/ddl.json +0 -0
- {polyglot_sql-0.6.3 → polyglot_sql-0.7.0}/crates/polyglot-sql/tests/custom_fixtures/datafusion/dml.json +0 -0
- {polyglot_sql-0.6.3 → polyglot_sql-0.7.0}/crates/polyglot-sql/tests/custom_fixtures/datafusion/functions.json +0 -0
- {polyglot_sql-0.6.3 → polyglot_sql-0.7.0}/crates/polyglot-sql/tests/custom_fixtures/datafusion/identity.json +0 -0
- {polyglot_sql-0.6.3 → polyglot_sql-0.7.0}/crates/polyglot-sql/tests/custom_fixtures/datafusion/operators.json +0 -0
- {polyglot_sql-0.6.3 → polyglot_sql-0.7.0}/crates/polyglot-sql/tests/custom_fixtures/datafusion/select.json +0 -0
- {polyglot_sql-0.6.3 → polyglot_sql-0.7.0}/crates/polyglot-sql/tests/custom_fixtures/datafusion/transpilation.json +0 -0
- {polyglot_sql-0.6.3 → polyglot_sql-0.7.0}/crates/polyglot-sql/tests/custom_fixtures/datafusion/types.json +0 -0
- {polyglot_sql-0.6.3 → polyglot_sql-0.7.0}/crates/polyglot-sql/tests/data_type_api.rs +0 -0
- {polyglot_sql-0.6.3 → polyglot_sql-0.7.0}/crates/polyglot-sql/tests/deep_nesting_regression.rs +0 -0
- {polyglot_sql-0.6.3 → polyglot_sql-0.7.0}/crates/polyglot-sql/tests/dialect_matrix.rs +0 -0
- {polyglot_sql-0.6.3 → polyglot_sql-0.7.0}/crates/polyglot-sql/tests/error_handling.rs +0 -0
- {polyglot_sql-0.6.3 → polyglot_sql-0.7.0}/crates/polyglot-sql/tests/fabric_regression.rs +0 -0
- {polyglot_sql-0.6.3 → polyglot_sql-0.7.0}/crates/polyglot-sql/tests/fabric_tpch_regression.rs +0 -0
- {polyglot_sql-0.6.3 → polyglot_sql-0.7.0}/crates/polyglot-sql/tests/identity_roundtrip.rs +0 -0
- {polyglot_sql-0.6.3 → polyglot_sql-0.7.0}/crates/polyglot-sql/tests/oracle_data_types_regression.rs +0 -0
- {polyglot_sql-0.6.3 → polyglot_sql-0.7.0}/crates/polyglot-sql/tests/postgres_explain_options.rs +0 -0
- {polyglot_sql-0.6.3 → polyglot_sql-0.7.0}/crates/polyglot-sql/tests/postgres_regexp_clickhouse.rs +0 -0
- {polyglot_sql-0.6.3 → polyglot_sql-0.7.0}/crates/polyglot-sql/tests/postgres_sqlite_regression.rs +0 -0
- {polyglot_sql-0.6.3 → polyglot_sql-0.7.0}/crates/polyglot-sql/tests/query_analysis.rs +0 -0
- {polyglot_sql-0.6.3 → polyglot_sql-0.7.0}/crates/polyglot-sql/tests/query_analysis_regression.rs +0 -0
- {polyglot_sql-0.6.3 → polyglot_sql-0.7.0}/crates/polyglot-sql/tests/snowflake_regression_test.rs +0 -0
- {polyglot_sql-0.6.3 → polyglot_sql-0.7.0}/crates/polyglot-sql/tests/sqlglot_compat.rs +0 -0
- {polyglot_sql-0.6.3 → polyglot_sql-0.7.0}/crates/polyglot-sql/tests/sqlglot_dialect_identity.rs +0 -0
- {polyglot_sql-0.6.3 → polyglot_sql-0.7.0}/crates/polyglot-sql/tests/sqlglot_identity.rs +0 -0
- {polyglot_sql-0.6.3 → polyglot_sql-0.7.0}/crates/polyglot-sql/tests/sqlglot_identity_detailed.rs +0 -0
- {polyglot_sql-0.6.3 → polyglot_sql-0.7.0}/crates/polyglot-sql/tests/sqlglot_parser.rs +0 -0
- {polyglot_sql-0.6.3 → polyglot_sql-0.7.0}/crates/polyglot-sql/tests/sqlglot_pretty.rs +0 -0
- {polyglot_sql-0.6.3 → polyglot_sql-0.7.0}/crates/polyglot-sql/tests/sqlglot_transpilation.rs +0 -0
- {polyglot_sql-0.6.3 → polyglot_sql-0.7.0}/crates/polyglot-sql/tests/sqlglot_transpile.rs +0 -0
- {polyglot_sql-0.6.3 → polyglot_sql-0.7.0}/crates/polyglot-sql/tests/tpch_transpile_stack.rs +0 -0
- {polyglot_sql-0.6.3 → polyglot_sql-0.7.0}/crates/polyglot-sql/tests/transform_regression.rs +0 -0
- {polyglot_sql-0.6.3 → polyglot_sql-0.7.0}/crates/polyglot-sql/tests/tsql_regression.rs +0 -0
- {polyglot_sql-0.6.3 → polyglot_sql-0.7.0}/crates/polyglot-sql-ast-derive/Cargo.toml +0 -0
- {polyglot_sql-0.6.3 → polyglot_sql-0.7.0}/crates/polyglot-sql-ast-derive/src/lib.rs +0 -0
- {polyglot_sql-0.6.3 → polyglot_sql-0.7.0}/crates/polyglot-sql-function-catalogs/Cargo.toml +0 -0
- {polyglot_sql-0.6.3 → polyglot_sql-0.7.0}/crates/polyglot-sql-function-catalogs/README.md +0 -0
- {polyglot_sql-0.6.3 → polyglot_sql-0.7.0}/crates/polyglot-sql-function-catalogs/src/clickhouse.rs +0 -0
- {polyglot_sql-0.6.3 → polyglot_sql-0.7.0}/crates/polyglot-sql-function-catalogs/src/duckdb.rs +0 -0
- {polyglot_sql-0.6.3 → polyglot_sql-0.7.0}/crates/polyglot-sql-function-catalogs/src/lib.rs +0 -0
- {polyglot_sql-0.6.3 → polyglot_sql-0.7.0}/crates/polyglot-sql-function-catalogs/tools/clickhouse/extract_functions.py +0 -0
- {polyglot_sql-0.6.3 → polyglot_sql-0.7.0}/crates/polyglot-sql-function-catalogs/tools/duckdb/extract_functions.py +0 -0
- {polyglot_sql-0.6.3 → polyglot_sql-0.7.0}/crates/polyglot-sql-python/Cargo.toml +0 -0
- {polyglot_sql-0.6.3 → polyglot_sql-0.7.0}/crates/polyglot-sql-python/docs/api.md +0 -0
- {polyglot_sql-0.6.3 → polyglot_sql-0.7.0}/crates/polyglot-sql-python/docs/index.md +0 -0
- {polyglot_sql-0.6.3 → polyglot_sql-0.7.0}/crates/polyglot-sql-python/mkdocs.yml +0 -0
- {polyglot_sql-0.6.3 → polyglot_sql-0.7.0}/crates/polyglot-sql-python/src/annotate_types.rs +0 -0
- {polyglot_sql-0.6.3 → polyglot_sql-0.7.0}/crates/polyglot-sql-python/src/dialects.rs +0 -0
- {polyglot_sql-0.6.3 → polyglot_sql-0.7.0}/crates/polyglot-sql-python/src/diff.rs +0 -0
- {polyglot_sql-0.6.3 → polyglot_sql-0.7.0}/crates/polyglot-sql-python/src/expr.rs +0 -0
- {polyglot_sql-0.6.3 → polyglot_sql-0.7.0}/crates/polyglot-sql-python/src/expr_types.rs +0 -0
- {polyglot_sql-0.6.3 → polyglot_sql-0.7.0}/crates/polyglot-sql-python/src/format.rs +0 -0
- {polyglot_sql-0.6.3 → polyglot_sql-0.7.0}/crates/polyglot-sql-python/src/generate.rs +0 -0
- {polyglot_sql-0.6.3 → polyglot_sql-0.7.0}/crates/polyglot-sql-python/src/helpers.rs +0 -0
- {polyglot_sql-0.6.3 → polyglot_sql-0.7.0}/crates/polyglot-sql-python/src/openlineage.rs +0 -0
- {polyglot_sql-0.6.3 → polyglot_sql-0.7.0}/crates/polyglot-sql-python/src/optimize.rs +0 -0
- {polyglot_sql-0.6.3 → polyglot_sql-0.7.0}/crates/polyglot-sql-python/src/parse.rs +0 -0
- {polyglot_sql-0.6.3 → polyglot_sql-0.7.0}/crates/polyglot-sql-python/src/query_analysis.rs +0 -0
- {polyglot_sql-0.6.3 → polyglot_sql-0.7.0}/crates/polyglot-sql-python/src/tokenize.rs +0 -0
- {polyglot_sql-0.6.3 → polyglot_sql-0.7.0}/crates/polyglot-sql-python/src/transforms.rs +0 -0
- {polyglot_sql-0.6.3 → polyglot_sql-0.7.0}/crates/polyglot-sql-python/src/transpile.rs +0 -0
- {polyglot_sql-0.6.3 → polyglot_sql-0.7.0}/crates/polyglot-sql-python/src/types.rs +0 -0
- {polyglot_sql-0.6.3 → polyglot_sql-0.7.0}/crates/polyglot-sql-python/src/validate.rs +0 -0
- {polyglot_sql-0.6.3 → polyglot_sql-0.7.0}/crates/polyglot-sql-python/tests/conftest.py +0 -0
- {polyglot_sql-0.6.3 → polyglot_sql-0.7.0}/crates/polyglot-sql-python/tests/test_compat.py +0 -0
- {polyglot_sql-0.6.3 → polyglot_sql-0.7.0}/crates/polyglot-sql-python/tests/test_dialects.py +0 -0
- {polyglot_sql-0.6.3 → polyglot_sql-0.7.0}/crates/polyglot-sql-python/tests/test_diff.py +0 -0
- {polyglot_sql-0.6.3 → polyglot_sql-0.7.0}/crates/polyglot-sql-python/tests/test_expression.py +0 -0
- {polyglot_sql-0.6.3 → polyglot_sql-0.7.0}/crates/polyglot-sql-python/tests/test_format.py +0 -0
- {polyglot_sql-0.6.3 → polyglot_sql-0.7.0}/crates/polyglot-sql-python/tests/test_generate.py +0 -0
- {polyglot_sql-0.6.3 → polyglot_sql-0.7.0}/crates/polyglot-sql-python/tests/test_optimize.py +0 -0
- {polyglot_sql-0.6.3 → polyglot_sql-0.7.0}/crates/polyglot-sql-python/tests/test_parse.py +0 -0
- {polyglot_sql-0.6.3 → polyglot_sql-0.7.0}/crates/polyglot-sql-python/tests/test_query_analysis.py +0 -0
- {polyglot_sql-0.6.3 → polyglot_sql-0.7.0}/crates/polyglot-sql-python/tests/test_transforms.py +0 -0
- {polyglot_sql-0.6.3 → polyglot_sql-0.7.0}/crates/polyglot-sql-python/tests/test_transpile.py +0 -0
- {polyglot_sql-0.6.3 → polyglot_sql-0.7.0}/crates/polyglot-sql-python/tests/test_validate.py +0 -0
- {polyglot_sql-0.6.3 → polyglot_sql-0.7.0}/crates/polyglot-sql-python/uv.lock +0 -0
- {polyglot_sql-0.6.3 → polyglot_sql-0.7.0}/pyproject.toml +0 -0
- {polyglot_sql-0.6.3 → polyglot_sql-0.7.0}/python/polyglot_sql/py.typed +0 -0
|
@@ -605,7 +605,7 @@ dependencies = [
|
|
|
605
605
|
|
|
606
606
|
[[package]]
|
|
607
607
|
name = "polyglot-sql"
|
|
608
|
-
version = "0.
|
|
608
|
+
version = "0.7.0"
|
|
609
609
|
dependencies = [
|
|
610
610
|
"criterion",
|
|
611
611
|
"once_cell",
|
|
@@ -623,7 +623,7 @@ dependencies = [
|
|
|
623
623
|
|
|
624
624
|
[[package]]
|
|
625
625
|
name = "polyglot-sql-ast-derive"
|
|
626
|
-
version = "0.
|
|
626
|
+
version = "0.7.0"
|
|
627
627
|
dependencies = [
|
|
628
628
|
"proc-macro2",
|
|
629
629
|
"quote",
|
|
@@ -632,7 +632,7 @@ dependencies = [
|
|
|
632
632
|
|
|
633
633
|
[[package]]
|
|
634
634
|
name = "polyglot-sql-ffi"
|
|
635
|
-
version = "0.
|
|
635
|
+
version = "0.7.0"
|
|
636
636
|
dependencies = [
|
|
637
637
|
"cbindgen",
|
|
638
638
|
"polyglot-sql",
|
|
@@ -642,11 +642,11 @@ dependencies = [
|
|
|
642
642
|
|
|
643
643
|
[[package]]
|
|
644
644
|
name = "polyglot-sql-function-catalogs"
|
|
645
|
-
version = "0.
|
|
645
|
+
version = "0.7.0"
|
|
646
646
|
|
|
647
647
|
[[package]]
|
|
648
648
|
name = "polyglot-sql-python"
|
|
649
|
-
version = "0.
|
|
649
|
+
version = "0.7.0"
|
|
650
650
|
dependencies = [
|
|
651
651
|
"polyglot-sql",
|
|
652
652
|
"pyo3",
|
|
@@ -657,7 +657,7 @@ dependencies = [
|
|
|
657
657
|
|
|
658
658
|
[[package]]
|
|
659
659
|
name = "polyglot-sql-wasm"
|
|
660
|
-
version = "0.
|
|
660
|
+
version = "0.7.0"
|
|
661
661
|
dependencies = [
|
|
662
662
|
"console_error_panic_hook",
|
|
663
663
|
"js-sys",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: polyglot-sql
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.7.0
|
|
4
4
|
Classifier: Development Status :: 4 - Beta
|
|
5
5
|
Classifier: Intended Audience :: Developers
|
|
6
6
|
Classifier: License :: OSI Approved :: MIT License
|
|
@@ -222,6 +222,11 @@ All functions are exported from `polyglot_sql`.
|
|
|
222
222
|
- `validate(sql: str, dialect: str = "generic", *, strict_syntax: bool = False, semantic: bool = False) -> ValidationResult`
|
|
223
223
|
- `optimize(sql: str, dialect: str = "generic") -> str`
|
|
224
224
|
- `lineage(column: str, sql: str, dialect: str = "generic") -> dict`
|
|
225
|
+
- `lineage_at(ordinal: int, sql: str, dialect: str = "generic") -> dict`
|
|
226
|
+
- `lineage_at_with_schema(ordinal: int, sql: str, schema: dict, dialect: str = "generic") -> dict`
|
|
227
|
+
- `lineage_with_schema(column: str, sql: str, schema: dict, dialect: str = "generic") -> dict`
|
|
228
|
+
- `output_columns(sql: str, dialect: str = "generic") -> dict`
|
|
229
|
+
- `output_columns_with_schema(sql: str, schema: dict, dialect: str = "generic") -> dict`
|
|
225
230
|
- `source_tables(column: str, sql: str, dialect: str = "generic") -> list[str]`
|
|
226
231
|
- `analyze_query(sql: str, options: dict | None = None, dialect: str = "generic") -> dict`
|
|
227
232
|
- `openlineage_column_lineage(sql: str, options: dict) -> dict`
|
|
@@ -246,6 +251,7 @@ Exception hierarchy:
|
|
|
246
251
|
- `GenerateError`
|
|
247
252
|
- `TranspileError`
|
|
248
253
|
- `ValidationError`
|
|
254
|
+
- `ColumnResolutionError` (`reason`, `column`, and `ordinal` attributes)
|
|
249
255
|
|
|
250
256
|
Unknown dialect names raise built-in `ValueError`.
|
|
251
257
|
|
|
@@ -195,6 +195,11 @@ All functions are exported from `polyglot_sql`.
|
|
|
195
195
|
- `validate(sql: str, dialect: str = "generic", *, strict_syntax: bool = False, semantic: bool = False) -> ValidationResult`
|
|
196
196
|
- `optimize(sql: str, dialect: str = "generic") -> str`
|
|
197
197
|
- `lineage(column: str, sql: str, dialect: str = "generic") -> dict`
|
|
198
|
+
- `lineage_at(ordinal: int, sql: str, dialect: str = "generic") -> dict`
|
|
199
|
+
- `lineage_at_with_schema(ordinal: int, sql: str, schema: dict, dialect: str = "generic") -> dict`
|
|
200
|
+
- `lineage_with_schema(column: str, sql: str, schema: dict, dialect: str = "generic") -> dict`
|
|
201
|
+
- `output_columns(sql: str, dialect: str = "generic") -> dict`
|
|
202
|
+
- `output_columns_with_schema(sql: str, schema: dict, dialect: str = "generic") -> dict`
|
|
198
203
|
- `source_tables(column: str, sql: str, dialect: str = "generic") -> list[str]`
|
|
199
204
|
- `analyze_query(sql: str, options: dict | None = None, dialect: str = "generic") -> dict`
|
|
200
205
|
- `openlineage_column_lineage(sql: str, options: dict) -> dict`
|
|
@@ -219,6 +224,7 @@ Exception hierarchy:
|
|
|
219
224
|
- `GenerateError`
|
|
220
225
|
- `TranspileError`
|
|
221
226
|
- `ValidationError`
|
|
227
|
+
- `ColumnResolutionError` (`reason`, `column`, and `ordinal` attributes)
|
|
222
228
|
|
|
223
229
|
Unknown dialect names raise built-in `ValueError`.
|
|
224
230
|
|
|
@@ -100,14 +100,14 @@ function-catalog-all-dialects = [
|
|
|
100
100
|
]
|
|
101
101
|
|
|
102
102
|
[dependencies]
|
|
103
|
-
polyglot-sql-ast-derive = { path = "../polyglot-sql-ast-derive", version = "0.
|
|
103
|
+
polyglot-sql-ast-derive = { path = "../polyglot-sql-ast-derive", version = "0.7.0" }
|
|
104
104
|
serde = { workspace = true }
|
|
105
105
|
serde_json = { workspace = true }
|
|
106
106
|
thiserror = { workspace = true }
|
|
107
107
|
unicode-segmentation = { workspace = true }
|
|
108
108
|
stacker = { version = "0.1", optional = true }
|
|
109
109
|
ts-rs = { version = "12.0", features = ["serde-compat"], optional = true }
|
|
110
|
-
polyglot-sql-function-catalogs = { path = "../polyglot-sql-function-catalogs", version = "0.
|
|
110
|
+
polyglot-sql-function-catalogs = { path = "../polyglot-sql-function-catalogs", version = "0.7.0", optional = true, default-features = false }
|
|
111
111
|
|
|
112
112
|
[dev-dependencies]
|
|
113
113
|
pretty_assertions = "1.4"
|
|
@@ -25,7 +25,7 @@ By default, `polyglot-sql` enables the full public API. Parser-only consumers ca
|
|
|
25
25
|
disable default features and opt into only the dialect parsers they need:
|
|
26
26
|
|
|
27
27
|
```toml
|
|
28
|
-
polyglot-sql = { version = "0.
|
|
28
|
+
polyglot-sql = { version = "0.7.0", default-features = false }
|
|
29
29
|
```
|
|
30
30
|
|
|
31
31
|
```toml
|
|
@@ -15,7 +15,7 @@ use crate::expressions::{
|
|
|
15
15
|
AggFunc, Alias, BinaryOp, Case, Cast, CeilFunc, Column, DataType, Expression, Function,
|
|
16
16
|
Identifier, Interval, IntervalUnit, IntervalUnitSpec, IsNull, JSONPath, JSONPathKey,
|
|
17
17
|
JSONPathRoot, JSONPathSubscript, JsonExtractFunc, Literal, Null, Paren, Struct, Subquery,
|
|
18
|
-
SubstringFunc, UnaryFunc, UnaryOp, VarArgFunc, WindowFunction,
|
|
18
|
+
SubstringFunc, UnaryFunc, UnaryOp, Unhex, VarArgFunc, WindowFunction,
|
|
19
19
|
};
|
|
20
20
|
#[cfg(feature = "generate")]
|
|
21
21
|
use crate::generator::GeneratorConfig;
|
|
@@ -1687,6 +1687,14 @@ impl DuckDBDialect {
|
|
|
1687
1687
|
fn transform_function(&self, f: Function) -> Result<Expression> {
|
|
1688
1688
|
let name_upper = f.name.to_uppercase();
|
|
1689
1689
|
match name_upper.as_str() {
|
|
1690
|
+
"FROM_HEX" if f.args.len() == 1 => {
|
|
1691
|
+
let mut args = f.args;
|
|
1692
|
+
Ok(Expression::Unhex(Box::new(Unhex {
|
|
1693
|
+
this: Box::new(args.remove(0)),
|
|
1694
|
+
expression: None,
|
|
1695
|
+
})))
|
|
1696
|
+
}
|
|
1697
|
+
|
|
1690
1698
|
// IFNULL -> COALESCE
|
|
1691
1699
|
"IFNULL" if f.args.len() == 2 => Ok(Expression::Coalesce(Box::new(VarArgFunc {
|
|
1692
1700
|
original_name: None,
|
|
@@ -1968,14 +1976,6 @@ impl DuckDBDialect {
|
|
|
1968
1976
|
f.args,
|
|
1969
1977
|
)))),
|
|
1970
1978
|
|
|
1971
|
-
// NOW -> CURRENT_TIMESTAMP
|
|
1972
|
-
"NOW" => Ok(Expression::CurrentTimestamp(
|
|
1973
|
-
crate::expressions::CurrentTimestamp {
|
|
1974
|
-
precision: None,
|
|
1975
|
-
sysdate: false,
|
|
1976
|
-
},
|
|
1977
|
-
)),
|
|
1978
|
-
|
|
1979
1979
|
// GETDATE -> CURRENT_TIMESTAMP
|
|
1980
1980
|
"GETDATE" => Ok(Expression::CurrentTimestamp(
|
|
1981
1981
|
crate::expressions::CurrentTimestamp {
|
|
@@ -580,6 +580,21 @@ fn presto_to_java_format(fmt: &str) -> String {
|
|
|
580
580
|
.replace("%M", "MMMM")
|
|
581
581
|
}
|
|
582
582
|
|
|
583
|
+
#[cfg(feature = "transpile")]
|
|
584
|
+
fn presto_to_java_parse_format(fmt: &str) -> String {
|
|
585
|
+
fmt.replace("%Y", "yyyy")
|
|
586
|
+
.replace("%m", "M")
|
|
587
|
+
.replace("%d", "d")
|
|
588
|
+
.replace("%H", "H")
|
|
589
|
+
.replace("%i", "m")
|
|
590
|
+
.replace("%S", "s")
|
|
591
|
+
.replace("%s", "s")
|
|
592
|
+
.replace("%y", "yy")
|
|
593
|
+
.replace("%T", "H:m:s")
|
|
594
|
+
.replace("%F", "yyyy-M-d")
|
|
595
|
+
.replace("%M", "MMMM")
|
|
596
|
+
}
|
|
597
|
+
|
|
583
598
|
#[cfg(feature = "transpile")]
|
|
584
599
|
fn normalize_presto_format(fmt: &str) -> String {
|
|
585
600
|
fmt.replace("%H:%i:%S", "%T").replace("%H:%i:%s", "%T")
|
|
@@ -632,12 +632,9 @@ pub(super) fn rewrite(
|
|
|
632
632
|
|
|
633
633
|
Action::ArrayAggToCollectList => {
|
|
634
634
|
// ARRAY_AGG(x ORDER BY ...) -> COLLECT_LIST(x) for Hive/Spark
|
|
635
|
-
// Python sqlglot Hive.arrayagg_sql strips ORDER BY for simple cases
|
|
636
|
-
// but preserves it when DISTINCT/IGNORE NULLS/LIMIT are present
|
|
637
635
|
match e {
|
|
638
636
|
Expression::AggregateFunction(mut af) => {
|
|
639
|
-
let
|
|
640
|
-
!af.distinct && af.ignore_nulls.is_none() && af.limit.is_none();
|
|
637
|
+
let preserves_order = af.limit.is_some();
|
|
641
638
|
let args = if af.args.is_empty() {
|
|
642
639
|
vec![]
|
|
643
640
|
} else {
|
|
@@ -645,24 +642,23 @@ pub(super) fn rewrite(
|
|
|
645
642
|
};
|
|
646
643
|
af.name = "COLLECT_LIST".to_string();
|
|
647
644
|
af.args = args;
|
|
648
|
-
if
|
|
645
|
+
if !preserves_order {
|
|
649
646
|
af.order_by = Vec::new();
|
|
650
647
|
}
|
|
651
648
|
Ok(Expression::AggregateFunction(af))
|
|
652
649
|
}
|
|
653
650
|
Expression::ArrayAgg(agg) => {
|
|
654
|
-
let
|
|
655
|
-
!agg.distinct && agg.ignore_nulls.is_none() && agg.limit.is_none();
|
|
651
|
+
let preserves_order = agg.limit.is_some();
|
|
656
652
|
Ok(Expression::AggregateFunction(Box::new(
|
|
657
653
|
crate::expressions::AggregateFunction {
|
|
658
654
|
name: "COLLECT_LIST".to_string(),
|
|
659
655
|
args: vec![agg.this.clone()],
|
|
660
656
|
distinct: agg.distinct,
|
|
661
657
|
filter: agg.filter.clone(),
|
|
662
|
-
order_by: if
|
|
663
|
-
Vec::new()
|
|
664
|
-
} else {
|
|
658
|
+
order_by: if preserves_order {
|
|
665
659
|
agg.order_by.clone()
|
|
660
|
+
} else {
|
|
661
|
+
Vec::new()
|
|
666
662
|
},
|
|
667
663
|
limit: agg.limit.clone(),
|
|
668
664
|
ignore_nulls: agg.ignore_nulls,
|
|
@@ -716,14 +712,19 @@ pub(super) fn rewrite(
|
|
|
716
712
|
}
|
|
717
713
|
|
|
718
714
|
Action::ArrayAggIgnoreNullsDuckDB => {
|
|
719
|
-
// ARRAY_AGG(x IGNORE NULLS
|
|
720
|
-
//
|
|
715
|
+
// ARRAY_AGG(x IGNORE NULLS ...) -> ARRAY_AGG(x ...) FILTER(WHERE x IS NOT NULL)
|
|
716
|
+
// DuckDB also needs NULLS FIRST on the first inline ordering expression.
|
|
721
717
|
let mut agg = if let Expression::ArrayAgg(a) = e {
|
|
722
718
|
*a
|
|
723
719
|
} else {
|
|
724
720
|
unreachable!("action only triggered for ArrayAgg expressions")
|
|
725
721
|
};
|
|
726
|
-
agg.ignore_nulls = None;
|
|
722
|
+
agg.ignore_nulls = None;
|
|
723
|
+
agg.filter = Some(Expression::IsNull(Box::new(IsNull {
|
|
724
|
+
this: agg.this.clone(),
|
|
725
|
+
not: true,
|
|
726
|
+
postfix_form: false,
|
|
727
|
+
})));
|
|
727
728
|
if !agg.order_by.is_empty() {
|
|
728
729
|
agg.order_by[0].nulls_first = Some(true);
|
|
729
730
|
}
|
|
@@ -858,11 +859,19 @@ pub(super) fn rewrite(
|
|
|
858
859
|
|
|
859
860
|
Action::AggFilterToIff => {
|
|
860
861
|
// AggFunc.filter -> IFF wrapping: AVG(x) FILTER(WHERE cond) -> AVG(IFF(cond, x, NULL))
|
|
862
|
+
let prefix_not_null = |condition: Expression| match condition {
|
|
863
|
+
Expression::IsNull(mut is_null) if is_null.not => {
|
|
864
|
+
is_null.postfix_form = true;
|
|
865
|
+
Expression::IsNull(is_null)
|
|
866
|
+
}
|
|
867
|
+
other => other,
|
|
868
|
+
};
|
|
861
869
|
// Helper macro to handle the common AggFunc case
|
|
862
870
|
macro_rules! handle_agg_filter_to_iff {
|
|
863
871
|
($variant:ident, $agg:expr) => {{
|
|
864
872
|
let mut agg = $agg;
|
|
865
873
|
if let Some(filter_cond) = agg.filter.take() {
|
|
874
|
+
let filter_cond = prefix_not_null(filter_cond);
|
|
866
875
|
let iff_call = Expression::Function(Box::new(Function::new(
|
|
867
876
|
"IFF".to_string(),
|
|
868
877
|
vec![filter_cond, agg.this.clone(), Expression::Null(Null)],
|
|
@@ -878,7 +887,24 @@ pub(super) fn rewrite(
|
|
|
878
887
|
Expression::Sum(agg) => handle_agg_filter_to_iff!(Sum, agg),
|
|
879
888
|
Expression::Min(agg) => handle_agg_filter_to_iff!(Min, agg),
|
|
880
889
|
Expression::Max(agg) => handle_agg_filter_to_iff!(Max, agg),
|
|
881
|
-
Expression::ArrayAgg(agg) =>
|
|
890
|
+
Expression::ArrayAgg(mut agg) => {
|
|
891
|
+
if let Some(filter_cond) = agg.filter.take() {
|
|
892
|
+
let filter_cond = prefix_not_null(filter_cond);
|
|
893
|
+
agg.this = Expression::Function(Box::new(Function::new(
|
|
894
|
+
"IFF".to_string(),
|
|
895
|
+
vec![filter_cond, agg.this, Expression::Null(Null)],
|
|
896
|
+
)));
|
|
897
|
+
}
|
|
898
|
+
if agg.order_by.is_empty() {
|
|
899
|
+
Ok(Expression::ArrayAgg(agg))
|
|
900
|
+
} else {
|
|
901
|
+
let order_by = std::mem::take(&mut agg.order_by);
|
|
902
|
+
Ok(Expression::WithinGroup(Box::new(WithinGroup {
|
|
903
|
+
this: Expression::ArrayAgg(agg),
|
|
904
|
+
order_by,
|
|
905
|
+
})))
|
|
906
|
+
}
|
|
907
|
+
}
|
|
882
908
|
Expression::CountIf(agg) => handle_agg_filter_to_iff!(CountIf, agg),
|
|
883
909
|
Expression::Stddev(agg) => handle_agg_filter_to_iff!(Stddev, agg),
|
|
884
910
|
Expression::StddevPop(agg) => handle_agg_filter_to_iff!(StddevPop, agg),
|
|
@@ -896,7 +922,21 @@ pub(super) fn rewrite(
|
|
|
896
922
|
}
|
|
897
923
|
Expression::Count(mut c) => {
|
|
898
924
|
if let Some(filter_cond) = c.filter.take() {
|
|
899
|
-
|
|
925
|
+
let filter_cond = prefix_not_null(filter_cond);
|
|
926
|
+
let is_star = c.star || matches!(c.this, Some(Expression::Star(_)));
|
|
927
|
+
if is_star {
|
|
928
|
+
return Ok(Expression::CountIf(Box::new(AggFunc {
|
|
929
|
+
this: filter_cond,
|
|
930
|
+
distinct: false,
|
|
931
|
+
filter: None,
|
|
932
|
+
order_by: Vec::new(),
|
|
933
|
+
name: None,
|
|
934
|
+
ignore_nulls: None,
|
|
935
|
+
having_max: None,
|
|
936
|
+
limit: None,
|
|
937
|
+
inferred_type: None,
|
|
938
|
+
})));
|
|
939
|
+
} else if let Some(ref this_expr) = c.this {
|
|
900
940
|
let iff_call = Expression::Function(Box::new(Function::new(
|
|
901
941
|
"IFF".to_string(),
|
|
902
942
|
vec![filter_cond, this_expr.clone(), Expression::Null(Null)],
|
|
@@ -906,6 +946,18 @@ pub(super) fn rewrite(
|
|
|
906
946
|
}
|
|
907
947
|
Ok(Expression::Count(c))
|
|
908
948
|
}
|
|
949
|
+
Expression::AggregateFunction(mut af) => {
|
|
950
|
+
if let Some(filter_cond) = af.filter.take() {
|
|
951
|
+
let filter_cond = prefix_not_null(filter_cond);
|
|
952
|
+
if let Some(first_arg) = af.args.first_mut() {
|
|
953
|
+
*first_arg = Expression::Function(Box::new(Function::new(
|
|
954
|
+
"IFF".to_string(),
|
|
955
|
+
vec![filter_cond, first_arg.clone(), Expression::Null(Null)],
|
|
956
|
+
)));
|
|
957
|
+
}
|
|
958
|
+
}
|
|
959
|
+
Ok(Expression::AggregateFunction(af))
|
|
960
|
+
}
|
|
909
961
|
other => Ok(other),
|
|
910
962
|
}
|
|
911
963
|
}
|
|
@@ -862,7 +862,11 @@ pub(super) fn rewrite(
|
|
|
862
862
|
}
|
|
863
863
|
|
|
864
864
|
let seq = Expression::Function(Box::new(Function::new(
|
|
865
|
-
|
|
865
|
+
if matches!(target, DialectType::BigQuery) {
|
|
866
|
+
"GENERATE_ARRAY".to_string()
|
|
867
|
+
} else {
|
|
868
|
+
"SEQUENCE".to_string()
|
|
869
|
+
},
|
|
866
870
|
seq_args,
|
|
867
871
|
)));
|
|
868
872
|
|
{polyglot_sql-0.6.3 → polyglot_sql-0.7.0}/crates/polyglot-sql/src/dialects/normalization/mod.rs
RENAMED
|
@@ -86,6 +86,118 @@ pub(super) fn normalize(
|
|
|
86
86
|
let expr = statements::normalize_root(expr, &context);
|
|
87
87
|
|
|
88
88
|
transform_recursive(expr, &|e| {
|
|
89
|
+
if matches!(source, DialectType::DataFusion) && matches!(target, DialectType::DuckDB) {
|
|
90
|
+
if let Expression::Function(ref function) = e {
|
|
91
|
+
if function.name.eq_ignore_ascii_case("NOW") && function.args.is_empty() {
|
|
92
|
+
return Ok(Expression::CurrentTimestamp(
|
|
93
|
+
crate::expressions::CurrentTimestamp {
|
|
94
|
+
precision: None,
|
|
95
|
+
sysdate: false,
|
|
96
|
+
},
|
|
97
|
+
));
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
if matches!(source, DialectType::Teradata)
|
|
103
|
+
&& matches!(target, DialectType::Spark | DialectType::Databricks)
|
|
104
|
+
{
|
|
105
|
+
if let Expression::StrToDate(ref str_to_date) = e {
|
|
106
|
+
let mut normalized = str_to_date.as_ref().clone();
|
|
107
|
+
normalized.format = normalized.format.map(|format| format.replace("%d", "%-d"));
|
|
108
|
+
return Ok(Expression::StrToDate(Box::new(normalized)));
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
if matches!(source, DialectType::DuckDB) && matches!(target, DialectType::DuckDB) {
|
|
113
|
+
if let Expression::ArrayAgg(ref array_agg) = e {
|
|
114
|
+
if let Some(Expression::IsNull(is_null)) = &array_agg.filter {
|
|
115
|
+
if is_null.not && !is_null.postfix_form {
|
|
116
|
+
let mut normalized = array_agg.as_ref().clone();
|
|
117
|
+
let mut condition = is_null.as_ref().clone();
|
|
118
|
+
condition.postfix_form = true;
|
|
119
|
+
normalized.filter = Some(Expression::IsNull(Box::new(condition)));
|
|
120
|
+
return Ok(Expression::ArrayAgg(Box::new(normalized)));
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
if matches!(source, DialectType::Generic) && matches!(target, DialectType::BigQuery) {
|
|
127
|
+
if let Expression::TimeToStr(ref time_to_str) = e {
|
|
128
|
+
let mut normalized = time_to_str.as_ref().clone();
|
|
129
|
+
normalized.format = normalized
|
|
130
|
+
.format
|
|
131
|
+
.replace("%Y-%m-%d", "%F")
|
|
132
|
+
.replace("%H:%M:%S", "%T");
|
|
133
|
+
return Ok(Expression::TimeToStr(Box::new(normalized)));
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
if matches!(source, DialectType::Hive) && matches!(target, DialectType::Hive) {
|
|
138
|
+
if let Expression::Function(ref function) = e {
|
|
139
|
+
if function.name.eq_ignore_ascii_case("STR_TO_DATE") && function.args.len() == 1 {
|
|
140
|
+
return Ok(Expression::Cast(Box::new(Cast {
|
|
141
|
+
this: function.args[0].clone(),
|
|
142
|
+
to: DataType::Date,
|
|
143
|
+
trailing_comments: Vec::new(),
|
|
144
|
+
double_colon_syntax: false,
|
|
145
|
+
format: None,
|
|
146
|
+
default: None,
|
|
147
|
+
inferred_type: None,
|
|
148
|
+
})));
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
if matches!(source, DialectType::Generic) && matches!(target, DialectType::Drill) {
|
|
154
|
+
if let Expression::ILike(ref like) = e {
|
|
155
|
+
return Ok(Expression::Function(Box::new(Function::new(
|
|
156
|
+
"ILIKE".to_string(),
|
|
157
|
+
vec![like.left.clone(), like.right.clone()],
|
|
158
|
+
))));
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
// DuckDB canonicalizes `x IS NOT NULL` as prefix `NOT x IS NULL`.
|
|
163
|
+
if matches!(source, DialectType::DuckDB) {
|
|
164
|
+
if let Expression::IsNull(ref is_null) = e {
|
|
165
|
+
if is_null.not && !is_null.postfix_form {
|
|
166
|
+
let mut normalized = is_null.as_ref().clone();
|
|
167
|
+
normalized.postfix_form = true;
|
|
168
|
+
return Ok(Expression::IsNull(Box::new(normalized)));
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
// Snowflake COUNT_IF requires an explicitly boolean predicate in DuckDB.
|
|
174
|
+
if matches!(source, DialectType::Snowflake) && matches!(target, DialectType::DuckDB) {
|
|
175
|
+
if let Expression::CountIf(ref count_if) = e {
|
|
176
|
+
let mut count_if = count_if.as_ref().clone();
|
|
177
|
+
count_if.this = Expression::Is(Box::new(crate::expressions::BinaryOp::new(
|
|
178
|
+
Expression::Paren(Box::new(crate::expressions::Paren {
|
|
179
|
+
this: count_if.this,
|
|
180
|
+
trailing_comments: Vec::new(),
|
|
181
|
+
})),
|
|
182
|
+
Expression::Boolean(crate::expressions::BooleanLiteral { value: true }),
|
|
183
|
+
)));
|
|
184
|
+
return Ok(Expression::CountIf(Box::new(count_if)));
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
if matches!(source, DialectType::Presto | DialectType::Trino)
|
|
189
|
+
&& matches!(target, DialectType::DuckDB)
|
|
190
|
+
{
|
|
191
|
+
if let Expression::Function(ref function) = e {
|
|
192
|
+
if function.name.eq_ignore_ascii_case("SHA256") && function.args.len() == 1 {
|
|
193
|
+
return Ok(Expression::Unhex(Box::new(crate::expressions::Unhex {
|
|
194
|
+
this: Box::new(Expression::Function(function.clone())),
|
|
195
|
+
expression: None,
|
|
196
|
+
})));
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
|
|
89
201
|
if matches!(source, DialectType::PostgreSQL | DialectType::Redshift)
|
|
90
202
|
&& matches!(target, DialectType::TSQL | DialectType::Fabric)
|
|
91
203
|
{
|
|
@@ -616,7 +728,100 @@ pub(super) fn normalize(
|
|
|
616
728
|
}
|
|
617
729
|
}
|
|
618
730
|
|
|
619
|
-
// BigQuery IN UNNEST
|
|
731
|
+
// BigQuery renders NOT IN UNNEST as prefix NOT around the membership predicate.
|
|
732
|
+
if matches!(source, DialectType::BigQuery) && matches!(target, DialectType::BigQuery) {
|
|
733
|
+
if let Expression::In(ref in_expr) = e {
|
|
734
|
+
if in_expr.not && in_expr.unnest.is_some() {
|
|
735
|
+
let mut positive = in_expr.as_ref().clone();
|
|
736
|
+
positive.not = false;
|
|
737
|
+
return Ok(Expression::Not(Box::new(crate::expressions::UnaryOp::new(
|
|
738
|
+
Expression::In(Box::new(positive)),
|
|
739
|
+
))));
|
|
740
|
+
}
|
|
741
|
+
}
|
|
742
|
+
}
|
|
743
|
+
|
|
744
|
+
// BigQuery IN UNNEST(expr) -> a NULL-aware DuckDB CASE expression.
|
|
745
|
+
if matches!(source, DialectType::BigQuery) && matches!(target, DialectType::DuckDB) {
|
|
746
|
+
if let Expression::In(ref in_expr) = e {
|
|
747
|
+
if let Some(ref unnest_inner) = in_expr.unnest {
|
|
748
|
+
let array = unnest_inner.as_ref().clone();
|
|
749
|
+
let value = in_expr.this.clone();
|
|
750
|
+
let array_length = || {
|
|
751
|
+
Expression::Function(Box::new(Function::new(
|
|
752
|
+
"ARRAY_LENGTH".to_string(),
|
|
753
|
+
vec![array.clone()],
|
|
754
|
+
)))
|
|
755
|
+
};
|
|
756
|
+
let empty_or_null =
|
|
757
|
+
Expression::Or(Box::new(crate::expressions::BinaryOp::new(
|
|
758
|
+
Expression::IsNull(Box::new(crate::expressions::IsNull {
|
|
759
|
+
this: array.clone(),
|
|
760
|
+
not: false,
|
|
761
|
+
postfix_form: false,
|
|
762
|
+
})),
|
|
763
|
+
Expression::Eq(Box::new(crate::expressions::BinaryOp::new(
|
|
764
|
+
array_length(),
|
|
765
|
+
Expression::number(0),
|
|
766
|
+
))),
|
|
767
|
+
)));
|
|
768
|
+
let contains = Expression::Function(Box::new(Function::new(
|
|
769
|
+
"ARRAY_CONTAINS".to_string(),
|
|
770
|
+
vec![array.clone(), value.clone()],
|
|
771
|
+
)));
|
|
772
|
+
let value_null_or_array_has_null =
|
|
773
|
+
Expression::Or(Box::new(crate::expressions::BinaryOp::new(
|
|
774
|
+
Expression::IsNull(Box::new(crate::expressions::IsNull {
|
|
775
|
+
this: value,
|
|
776
|
+
not: false,
|
|
777
|
+
postfix_form: false,
|
|
778
|
+
})),
|
|
779
|
+
Expression::Neq(Box::new(crate::expressions::BinaryOp::new(
|
|
780
|
+
array_length(),
|
|
781
|
+
Expression::Function(Box::new(Function::new(
|
|
782
|
+
"LIST_COUNT".to_string(),
|
|
783
|
+
vec![array],
|
|
784
|
+
))),
|
|
785
|
+
))),
|
|
786
|
+
)));
|
|
787
|
+
let case = Expression::Case(Box::new(Case {
|
|
788
|
+
operand: None,
|
|
789
|
+
whens: vec![
|
|
790
|
+
(
|
|
791
|
+
empty_or_null,
|
|
792
|
+
Expression::Boolean(crate::expressions::BooleanLiteral {
|
|
793
|
+
value: false,
|
|
794
|
+
}),
|
|
795
|
+
),
|
|
796
|
+
(
|
|
797
|
+
contains,
|
|
798
|
+
Expression::Boolean(crate::expressions::BooleanLiteral {
|
|
799
|
+
value: true,
|
|
800
|
+
}),
|
|
801
|
+
),
|
|
802
|
+
(
|
|
803
|
+
value_null_or_array_has_null,
|
|
804
|
+
Expression::Null(crate::expressions::Null),
|
|
805
|
+
),
|
|
806
|
+
],
|
|
807
|
+
else_: Some(Expression::Boolean(crate::expressions::BooleanLiteral {
|
|
808
|
+
value: false,
|
|
809
|
+
})),
|
|
810
|
+
comments: Vec::new(),
|
|
811
|
+
inferred_type: None,
|
|
812
|
+
}));
|
|
813
|
+
return if in_expr.not {
|
|
814
|
+
Ok(Expression::Not(Box::new(crate::expressions::UnaryOp::new(
|
|
815
|
+
case,
|
|
816
|
+
))))
|
|
817
|
+
} else {
|
|
818
|
+
Ok(case)
|
|
819
|
+
};
|
|
820
|
+
}
|
|
821
|
+
}
|
|
822
|
+
}
|
|
823
|
+
|
|
824
|
+
// BigQuery IN UNNEST(expr) -> IN (SELECT UNNEST/EXPLODE(expr)) for other targets
|
|
620
825
|
if matches!(source, DialectType::BigQuery) && !matches!(target, DialectType::BigQuery) {
|
|
621
826
|
if let Expression::In(ref in_expr) = e {
|
|
622
827
|
if let Some(ref unnest_inner) = in_expr.unnest {
|
|
@@ -1403,6 +1608,25 @@ pub(super) fn normalize(
|
|
|
1403
1608
|
}
|
|
1404
1609
|
}
|
|
1405
1610
|
|
|
1611
|
+
// ARRAY_CONCAT_AGG -> DuckDB: flatten an ARRAY_AGG while excluding NULL arrays.
|
|
1612
|
+
if matches!(target, DialectType::DuckDB) {
|
|
1613
|
+
if let Expression::ArrayConcatAgg(ref agg) = e {
|
|
1614
|
+
let mut agg = agg.as_ref().clone();
|
|
1615
|
+
agg.name = None;
|
|
1616
|
+
agg.filter = Some(Expression::IsNull(Box::new(crate::expressions::IsNull {
|
|
1617
|
+
this: agg.this.clone(),
|
|
1618
|
+
not: true,
|
|
1619
|
+
postfix_form: true,
|
|
1620
|
+
})));
|
|
1621
|
+
if let Some(first) = agg.order_by.first_mut() {
|
|
1622
|
+
first.nulls_first = Some(true);
|
|
1623
|
+
}
|
|
1624
|
+
return Ok(Expression::ArrayFlatten(Box::new(
|
|
1625
|
+
crate::expressions::UnaryFunc::new(Expression::ArrayAgg(Box::new(agg))),
|
|
1626
|
+
)));
|
|
1627
|
+
}
|
|
1628
|
+
}
|
|
1629
|
+
|
|
1406
1630
|
// ARRAY_CONCAT_AGG -> others: keep as function for cross-dialect
|
|
1407
1631
|
if !matches!(target, DialectType::BigQuery | DialectType::Snowflake) {
|
|
1408
1632
|
if let Expression::ArrayConcatAgg(agg) = e {
|
|
@@ -1779,7 +2003,7 @@ pub(super) fn normalize(
|
|
|
1779
2003
|
| "STRFTIME" | "STRPTIME"
|
|
1780
2004
|
| "DATE_FORMAT" | "FORMAT_DATE"
|
|
1781
2005
|
| "PARSE_TIMESTAMP" | "PARSE_DATETIME" | "PARSE_DATE"
|
|
1782
|
-
| "FROM_ISO8601_TIMESTAMP" | "FROM_ISO8601_DATE"
|
|
2006
|
+
| "FROM_ISO8601_TIMESTAMP" | "FROM_ISO8601_TIMESTAMP_NANOS" | "FROM_ISO8601_DATE"
|
|
1783
2007
|
| "FROM_BASE64" | "TO_BASE64"
|
|
1784
2008
|
| "GETDATE"
|
|
1785
2009
|
| "TO_HEX" | "FROM_HEX" | "UNHEX" | "HEX"
|
|
@@ -1957,6 +2181,11 @@ pub(super) fn normalize(
|
|
|
1957
2181
|
}
|
|
1958
2182
|
}
|
|
1959
2183
|
}
|
|
2184
|
+
Expression::AggregateFunction(af)
|
|
2185
|
+
if matches!(target, DialectType::Snowflake) && af.filter.is_some() =>
|
|
2186
|
+
{
|
|
2187
|
+
Action::Aggregates(aggregates::Action::AggFilterToIff)
|
|
2188
|
+
}
|
|
1960
2189
|
Expression::AggregateFunction(af) => {
|
|
1961
2190
|
let name = af.name.to_ascii_uppercase();
|
|
1962
2191
|
match name.as_str() {
|
|
@@ -2124,7 +2353,9 @@ pub(super) fn normalize(
|
|
|
2124
2353
|
_ => Action::None,
|
|
2125
2354
|
},
|
|
2126
2355
|
Expression::ArrayAgg(ref agg) => {
|
|
2127
|
-
if matches!(target, DialectType::
|
|
2356
|
+
if matches!(target, DialectType::Snowflake) && agg.filter.is_some() {
|
|
2357
|
+
Action::Aggregates(aggregates::Action::AggFilterToIff)
|
|
2358
|
+
} else if matches!(target, DialectType::MySQL | DialectType::SingleStore) {
|
|
2128
2359
|
Action::Aggregates(aggregates::Action::ArrayAggToGroupConcat)
|
|
2129
2360
|
} else if matches!(
|
|
2130
2361
|
target,
|
|
@@ -2143,7 +2374,6 @@ pub(super) fn normalize(
|
|
|
2143
2374
|
Action::Aggregates(aggregates::Action::ArrayAggNullFilter)
|
|
2144
2375
|
} else if matches!(target, DialectType::DuckDB)
|
|
2145
2376
|
&& agg.ignore_nulls == Some(true)
|
|
2146
|
-
&& !agg.order_by.is_empty()
|
|
2147
2377
|
{
|
|
2148
2378
|
// BigQuery ARRAY_AGG(x IGNORE NULLS ORDER BY ...) -> DuckDB ARRAY_AGG(x ORDER BY a NULLS FIRST, ...)
|
|
2149
2379
|
Action::Aggregates(aggregates::Action::ArrayAggIgnoreNullsDuckDB)
|