polyglot-sql 0.13.2__tar.gz → 0.13.3__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.13.2 → polyglot_sql-0.13.3}/Cargo.lock +6 -6
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/Cargo.toml +1 -1
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/PKG-INFO +1 -1
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/crates/polyglot-sql/Cargo.toml +2 -2
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/crates/polyglot-sql/README.md +4 -4
- polyglot_sql-0.13.3/crates/polyglot-sql/src/dialects/normalization/duckdb.rs +272 -0
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/crates/polyglot-sql/src/dialects/normalization/scalar.rs +2 -1
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/crates/polyglot-sql/src/generator.rs +121 -22
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/crates/polyglot-sql/tests/duckdb_integer_division.rs +211 -6
- polyglot_sql-0.13.3/crates/polyglot-sql/tests/mod_precedence.rs +176 -0
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/crates/polyglot-sql-function-catalogs/README.md +1 -1
- polyglot_sql-0.13.3/crates/polyglot-sql-python/tests/test_duckdb_datafusion_execution.py +102 -0
- polyglot_sql-0.13.2/crates/polyglot-sql/src/dialects/normalization/duckdb.rs +0 -107
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/README.md +0 -0
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/crates/polyglot-sql/benches/allocation_hotspots.rs +0 -0
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/crates/polyglot-sql/benches/ast_traversal.rs +0 -0
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/crates/polyglot-sql/benches/common/mod.rs +0 -0
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/crates/polyglot-sql/benches/in_list.rs +0 -0
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/crates/polyglot-sql/benches/lineage.rs +0 -0
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/crates/polyglot-sql/benches/parsing.rs +0 -0
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/crates/polyglot-sql/benches/performance_hotspots.rs +0 -0
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/crates/polyglot-sql/benches/rust_parsing.rs +0 -0
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/crates/polyglot-sql/benches/transpile.rs +0 -0
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/crates/polyglot-sql/examples/basic_usage.rs +0 -0
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/crates/polyglot-sql/examples/bench_json.rs +0 -0
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/crates/polyglot-sql/src/ast_children.rs +0 -0
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/crates/polyglot-sql/src/ast_json.rs +0 -0
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/crates/polyglot-sql/src/ast_mutation.rs +0 -0
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/crates/polyglot-sql/src/ast_transforms.rs +0 -0
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/crates/polyglot-sql/src/binding.rs +0 -0
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/crates/polyglot-sql/src/builder/mod.rs +0 -0
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/crates/polyglot-sql/src/builder/plan.rs +0 -0
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/crates/polyglot-sql/src/dialects/athena.rs +0 -0
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/crates/polyglot-sql/src/dialects/bigquery.rs +0 -0
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/crates/polyglot-sql/src/dialects/clickhouse.rs +0 -0
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/crates/polyglot-sql/src/dialects/cockroachdb.rs +0 -0
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/crates/polyglot-sql/src/dialects/databricks.rs +0 -0
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/crates/polyglot-sql/src/dialects/datafusion.rs +0 -0
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/crates/polyglot-sql/src/dialects/doris.rs +0 -0
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/crates/polyglot-sql/src/dialects/dremio.rs +0 -0
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/crates/polyglot-sql/src/dialects/drill.rs +0 -0
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/crates/polyglot-sql/src/dialects/druid.rs +0 -0
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/crates/polyglot-sql/src/dialects/duckdb.rs +0 -0
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/crates/polyglot-sql/src/dialects/dune.rs +0 -0
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/crates/polyglot-sql/src/dialects/exasol.rs +0 -0
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/crates/polyglot-sql/src/dialects/fabric.rs +0 -0
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/crates/polyglot-sql/src/dialects/generic.rs +0 -0
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/crates/polyglot-sql/src/dialects/hana.rs +0 -0
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/crates/polyglot-sql/src/dialects/hive.rs +0 -0
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/crates/polyglot-sql/src/dialects/materialize.rs +0 -0
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/crates/polyglot-sql/src/dialects/mod.rs +0 -0
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/crates/polyglot-sql/src/dialects/mysql.rs +0 -0
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/crates/polyglot-sql/src/dialects/normalization/aggregates.rs +0 -0
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/crates/polyglot-sql/src/dialects/normalization/collections.rs +0 -0
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/crates/polyglot-sql/src/dialects/normalization/hana.rs +0 -0
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/crates/polyglot-sql/src/dialects/normalization/json.rs +0 -0
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/crates/polyglot-sql/src/dialects/normalization/mod.rs +0 -0
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/crates/polyglot-sql/src/dialects/normalization/operators.rs +0 -0
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/crates/polyglot-sql/src/dialects/normalization/postgres_interval.rs +0 -0
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/crates/polyglot-sql/src/dialects/normalization/statements.rs +0 -0
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/crates/polyglot-sql/src/dialects/normalization/temporal.rs +0 -0
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/crates/polyglot-sql/src/dialects/normalization/types.rs +0 -0
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/crates/polyglot-sql/src/dialects/normalization/vertica.rs +0 -0
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/crates/polyglot-sql/src/dialects/oracle.rs +0 -0
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/crates/polyglot-sql/src/dialects/postgres.rs +0 -0
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/crates/polyglot-sql/src/dialects/presto.rs +0 -0
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/crates/polyglot-sql/src/dialects/redshift.rs +0 -0
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/crates/polyglot-sql/src/dialects/risingwave.rs +0 -0
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/crates/polyglot-sql/src/dialects/singlestore.rs +0 -0
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/crates/polyglot-sql/src/dialects/snowflake.rs +0 -0
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/crates/polyglot-sql/src/dialects/solr.rs +0 -0
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/crates/polyglot-sql/src/dialects/spark.rs +0 -0
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/crates/polyglot-sql/src/dialects/sqlite.rs +0 -0
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/crates/polyglot-sql/src/dialects/starrocks.rs +0 -0
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/crates/polyglot-sql/src/dialects/tableau.rs +0 -0
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/crates/polyglot-sql/src/dialects/teradata.rs +0 -0
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/crates/polyglot-sql/src/dialects/tidb.rs +0 -0
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/crates/polyglot-sql/src/dialects/trino.rs +0 -0
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/crates/polyglot-sql/src/dialects/tsql.rs +0 -0
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/crates/polyglot-sql/src/dialects/vertica.rs +0 -0
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/crates/polyglot-sql/src/diff.rs +0 -0
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/crates/polyglot-sql/src/error.rs +0 -0
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/crates/polyglot-sql/src/expressions.rs +0 -0
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/crates/polyglot-sql/src/format_tokens.rs +0 -0
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/crates/polyglot-sql/src/function_catalog.rs +0 -0
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/crates/polyglot-sql/src/function_registry.rs +0 -0
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/crates/polyglot-sql/src/guard.rs +0 -0
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/crates/polyglot-sql/src/helper.rs +0 -0
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/crates/polyglot-sql/src/lib.rs +0 -0
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/crates/polyglot-sql/src/lineage.rs +0 -0
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/crates/polyglot-sql/src/openlineage.rs +0 -0
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/crates/polyglot-sql/src/optimizer/annotate_types.rs +0 -0
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/crates/polyglot-sql/src/optimizer/canonicalize.rs +0 -0
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/crates/polyglot-sql/src/optimizer/eliminate_ctes.rs +0 -0
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/crates/polyglot-sql/src/optimizer/eliminate_joins.rs +0 -0
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/crates/polyglot-sql/src/optimizer/isolate_table_selects.rs +0 -0
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/crates/polyglot-sql/src/optimizer/mod.rs +0 -0
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/crates/polyglot-sql/src/optimizer/normalize.rs +0 -0
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/crates/polyglot-sql/src/optimizer/normalize_identifiers.rs +0 -0
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/crates/polyglot-sql/src/optimizer/optimize_joins.rs +0 -0
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/crates/polyglot-sql/src/optimizer/optimizer.rs +0 -0
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/crates/polyglot-sql/src/optimizer/pushdown_predicates.rs +0 -0
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/crates/polyglot-sql/src/optimizer/pushdown_projections.rs +0 -0
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/crates/polyglot-sql/src/optimizer/qualify_columns.rs +0 -0
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/crates/polyglot-sql/src/optimizer/qualify_tables.rs +0 -0
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/crates/polyglot-sql/src/optimizer/set_operation_types.rs +0 -0
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/crates/polyglot-sql/src/optimizer/simplify.rs +0 -0
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/crates/polyglot-sql/src/optimizer/subquery.rs +0 -0
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/crates/polyglot-sql/src/parser.rs +0 -0
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/crates/polyglot-sql/src/planner.rs +0 -0
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/crates/polyglot-sql/src/query_analysis/column_uses.rs +0 -0
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/crates/polyglot-sql/src/query_analysis.rs +0 -0
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/crates/polyglot-sql/src/resolver.rs +0 -0
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/crates/polyglot-sql/src/schema.rs +0 -0
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/crates/polyglot-sql/src/scope.rs +0 -0
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/crates/polyglot-sql/src/set_operation.rs +0 -0
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/crates/polyglot-sql/src/time.rs +0 -0
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/crates/polyglot-sql/src/tokens.rs +0 -0
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/crates/polyglot-sql/src/transforms.rs +0 -0
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/crates/polyglot-sql/src/traversal.rs +0 -0
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/crates/polyglot-sql/src/trie.rs +0 -0
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/crates/polyglot-sql/src/validation/semantics.rs +0 -0
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/crates/polyglot-sql/src/validation/tests.rs +0 -0
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/crates/polyglot-sql/src/validation.rs +0 -0
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/crates/polyglot-sql/tests/analyze_failures.rs +0 -0
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/crates/polyglot-sql/tests/clickhouse_regression.rs +0 -0
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/crates/polyglot-sql/tests/common/known_failures.rs +0 -0
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/crates/polyglot-sql/tests/common/mod.rs +0 -0
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/crates/polyglot-sql/tests/common/test_data.rs +0 -0
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/crates/polyglot-sql/tests/common/test_runner.rs +0 -0
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/crates/polyglot-sql/tests/create_view_security_comment_regression.rs +0 -0
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/crates/polyglot-sql/tests/custom_clickhouse_coverage.rs +0 -0
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/crates/polyglot-sql/tests/custom_clickhouse_parser.rs +0 -0
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/crates/polyglot-sql/tests/custom_dialect.rs +0 -0
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/crates/polyglot-sql/tests/custom_dialect_tests.rs +0 -0
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/crates/polyglot-sql/tests/custom_fixtures/datafusion/ddl.json +0 -0
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/crates/polyglot-sql/tests/custom_fixtures/datafusion/dml.json +0 -0
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/crates/polyglot-sql/tests/custom_fixtures/datafusion/functions.json +0 -0
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/crates/polyglot-sql/tests/custom_fixtures/datafusion/identity.json +0 -0
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/crates/polyglot-sql/tests/custom_fixtures/datafusion/operators.json +0 -0
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/crates/polyglot-sql/tests/custom_fixtures/datafusion/select.json +0 -0
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/crates/polyglot-sql/tests/custom_fixtures/datafusion/transpilation.json +0 -0
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/crates/polyglot-sql/tests/custom_fixtures/datafusion/types.json +0 -0
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/crates/polyglot-sql/tests/custom_fixtures/hana/ddl.json +0 -0
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/crates/polyglot-sql/tests/custom_fixtures/hana/dml.json +0 -0
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/crates/polyglot-sql/tests/custom_fixtures/hana/functions.json +0 -0
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/crates/polyglot-sql/tests/custom_fixtures/hana/identity.json +0 -0
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/crates/polyglot-sql/tests/custom_fixtures/hana/select.json +0 -0
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/crates/polyglot-sql/tests/custom_fixtures/hana/types.json +0 -0
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/crates/polyglot-sql/tests/custom_fixtures/vertica/identity.json +0 -0
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/crates/polyglot-sql/tests/custom_fixtures/vertica/transpilation.json +0 -0
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/crates/polyglot-sql/tests/custom_fixtures/vertica/types.json +0 -0
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/crates/polyglot-sql/tests/data_type_api.rs +0 -0
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/crates/polyglot-sql/tests/deep_nesting_regression.rs +0 -0
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/crates/polyglot-sql/tests/dialect_matrix.rs +0 -0
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/crates/polyglot-sql/tests/duckdb_order_by_all.rs +0 -0
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/crates/polyglot-sql/tests/error_handling.rs +0 -0
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/crates/polyglot-sql/tests/fabric_regression.rs +0 -0
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/crates/polyglot-sql/tests/fabric_tpch_regression.rs +0 -0
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/crates/polyglot-sql/tests/identity_roundtrip.rs +0 -0
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/crates/polyglot-sql/tests/oracle_data_types_regression.rs +0 -0
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/crates/polyglot-sql/tests/postgres_explain_options.rs +0 -0
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/crates/polyglot-sql/tests/postgres_regexp_clickhouse.rs +0 -0
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/crates/polyglot-sql/tests/postgres_sqlite_regression.rs +0 -0
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/crates/polyglot-sql/tests/query_analysis.rs +0 -0
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/crates/polyglot-sql/tests/query_analysis_regression.rs +0 -0
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/crates/polyglot-sql/tests/snowflake_regression_test.rs +0 -0
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/crates/polyglot-sql/tests/sqlglot_compat.rs +0 -0
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/crates/polyglot-sql/tests/sqlglot_dialect_identity.rs +0 -0
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/crates/polyglot-sql/tests/sqlglot_identity.rs +0 -0
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/crates/polyglot-sql/tests/sqlglot_identity_detailed.rs +0 -0
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/crates/polyglot-sql/tests/sqlglot_parser.rs +0 -0
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/crates/polyglot-sql/tests/sqlglot_pretty.rs +0 -0
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/crates/polyglot-sql/tests/sqlglot_transpilation.rs +0 -0
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/crates/polyglot-sql/tests/sqlglot_transpile.rs +0 -0
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/crates/polyglot-sql/tests/tpch_transpile_stack.rs +0 -0
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/crates/polyglot-sql/tests/transform_regression.rs +0 -0
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/crates/polyglot-sql/tests/tsql_regression.rs +0 -0
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/crates/polyglot-sql-ast-derive/Cargo.toml +0 -0
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/crates/polyglot-sql-ast-derive/src/lib.rs +0 -0
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/crates/polyglot-sql-function-catalogs/Cargo.toml +0 -0
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/crates/polyglot-sql-function-catalogs/src/clickhouse.rs +0 -0
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/crates/polyglot-sql-function-catalogs/src/duckdb.rs +0 -0
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/crates/polyglot-sql-function-catalogs/src/lib.rs +0 -0
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/crates/polyglot-sql-function-catalogs/tools/clickhouse/extract_functions.py +0 -0
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/crates/polyglot-sql-function-catalogs/tools/duckdb/extract_functions.py +0 -0
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/crates/polyglot-sql-python/Cargo.toml +0 -0
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/crates/polyglot-sql-python/README.md +0 -0
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/crates/polyglot-sql-python/docs/api.md +0 -0
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/crates/polyglot-sql-python/docs/index.md +0 -0
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/crates/polyglot-sql-python/mkdocs.yml +0 -0
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/crates/polyglot-sql-python/src/annotate_types.rs +0 -0
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/crates/polyglot-sql-python/src/builders.rs +0 -0
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/crates/polyglot-sql-python/src/dialects.rs +0 -0
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/crates/polyglot-sql-python/src/diff.rs +0 -0
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/crates/polyglot-sql-python/src/errors.rs +0 -0
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/crates/polyglot-sql-python/src/expr.rs +0 -0
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/crates/polyglot-sql-python/src/expr_types.rs +0 -0
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/crates/polyglot-sql-python/src/format.rs +0 -0
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/crates/polyglot-sql-python/src/generate.rs +0 -0
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/crates/polyglot-sql-python/src/helpers.rs +0 -0
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/crates/polyglot-sql-python/src/lib.rs +0 -0
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/crates/polyglot-sql-python/src/lineage.rs +0 -0
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/crates/polyglot-sql-python/src/openlineage.rs +0 -0
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/crates/polyglot-sql-python/src/optimize.rs +0 -0
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/crates/polyglot-sql-python/src/parse.rs +0 -0
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/crates/polyglot-sql-python/src/query_analysis.rs +0 -0
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/crates/polyglot-sql-python/src/tokenize.rs +0 -0
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/crates/polyglot-sql-python/src/transforms.rs +0 -0
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/crates/polyglot-sql-python/src/transpile.rs +0 -0
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/crates/polyglot-sql-python/src/types.rs +0 -0
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/crates/polyglot-sql-python/src/validate.rs +0 -0
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/crates/polyglot-sql-python/tests/conftest.py +0 -0
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/crates/polyglot-sql-python/tests/test_builders.py +0 -0
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/crates/polyglot-sql-python/tests/test_compat.py +0 -0
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/crates/polyglot-sql-python/tests/test_dialects.py +0 -0
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/crates/polyglot-sql-python/tests/test_diff.py +0 -0
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/crates/polyglot-sql-python/tests/test_expression.py +0 -0
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/crates/polyglot-sql-python/tests/test_format.py +0 -0
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/crates/polyglot-sql-python/tests/test_generate.py +0 -0
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/crates/polyglot-sql-python/tests/test_lineage.py +0 -0
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/crates/polyglot-sql-python/tests/test_optimize.py +0 -0
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/crates/polyglot-sql-python/tests/test_parse.py +0 -0
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/crates/polyglot-sql-python/tests/test_query_analysis.py +0 -0
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/crates/polyglot-sql-python/tests/test_transforms.py +0 -0
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/crates/polyglot-sql-python/tests/test_transpile.py +0 -0
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/crates/polyglot-sql-python/tests/test_validate.py +0 -0
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/crates/polyglot-sql-python/uv.lock +0 -0
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/pyproject.toml +0 -0
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/python/polyglot_sql/__init__.py +0 -0
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/python/polyglot_sql/__init__.pyi +0 -0
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/python/polyglot_sql/analysis_types.py +0 -0
- {polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/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.13.
|
|
608
|
+
version = "0.13.3"
|
|
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.13.
|
|
626
|
+
version = "0.13.3"
|
|
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.13.
|
|
635
|
+
version = "0.13.3"
|
|
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.13.
|
|
645
|
+
version = "0.13.3"
|
|
646
646
|
|
|
647
647
|
[[package]]
|
|
648
648
|
name = "polyglot-sql-python"
|
|
649
|
-
version = "0.13.
|
|
649
|
+
version = "0.13.3"
|
|
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.13.
|
|
660
|
+
version = "0.13.3"
|
|
661
661
|
dependencies = [
|
|
662
662
|
"console_error_panic_hook",
|
|
663
663
|
"js-sys",
|
|
@@ -103,14 +103,14 @@ function-catalog-all-dialects = [
|
|
|
103
103
|
]
|
|
104
104
|
|
|
105
105
|
[dependencies]
|
|
106
|
-
polyglot-sql-ast-derive = { path = "../polyglot-sql-ast-derive", version = "0.13.
|
|
106
|
+
polyglot-sql-ast-derive = { path = "../polyglot-sql-ast-derive", version = "0.13.3" }
|
|
107
107
|
serde = { workspace = true }
|
|
108
108
|
serde_json = { workspace = true }
|
|
109
109
|
thiserror = { workspace = true }
|
|
110
110
|
unicode-segmentation = { workspace = true }
|
|
111
111
|
stacker = { version = "0.1", optional = true }
|
|
112
112
|
ts-rs = { version = "12.0", features = ["serde-compat"], optional = true }
|
|
113
|
-
polyglot-sql-function-catalogs = { path = "../polyglot-sql-function-catalogs", version = "0.13.
|
|
113
|
+
polyglot-sql-function-catalogs = { path = "../polyglot-sql-function-catalogs", version = "0.13.3", optional = true, default-features = false }
|
|
114
114
|
|
|
115
115
|
[dev-dependencies]
|
|
116
116
|
pretty_assertions = "1.4"
|
|
@@ -25,12 +25,12 @@ 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.13.
|
|
28
|
+
polyglot-sql = { version = "0.13.3", default-features = false }
|
|
29
29
|
```
|
|
30
30
|
|
|
31
31
|
```toml
|
|
32
32
|
polyglot-sql = {
|
|
33
|
-
version = "0.13.
|
|
33
|
+
version = "0.13.3",
|
|
34
34
|
default-features = false,
|
|
35
35
|
features = ["dialect-clickhouse"],
|
|
36
36
|
}
|
|
@@ -44,14 +44,14 @@ Examples:
|
|
|
44
44
|
```toml
|
|
45
45
|
# Parse and generate SQL for one dialect.
|
|
46
46
|
polyglot-sql = {
|
|
47
|
-
version = "0.13.
|
|
47
|
+
version = "0.13.3",
|
|
48
48
|
default-features = false,
|
|
49
49
|
features = ["generate", "dialect-clickhouse"],
|
|
50
50
|
}
|
|
51
51
|
|
|
52
52
|
# Cross-dialect transpilation.
|
|
53
53
|
polyglot-sql = {
|
|
54
|
-
version = "0.13.
|
|
54
|
+
version = "0.13.3",
|
|
55
55
|
default-features = false,
|
|
56
56
|
features = ["transpile", "dialect-clickhouse", "dialect-postgresql"],
|
|
57
57
|
}
|
|
@@ -0,0 +1,272 @@
|
|
|
1
|
+
//! Preserve DuckDB's type-dependent `//` semantics before target rewrites.
|
|
2
|
+
|
|
3
|
+
use super::scalar::{expression_numeric_kind, NumericKind};
|
|
4
|
+
use super::*;
|
|
5
|
+
use crate::expressions::RoundFunc;
|
|
6
|
+
|
|
7
|
+
fn combine(left: NumericKind, right: NumericKind) -> NumericKind {
|
|
8
|
+
use NumericKind::*;
|
|
9
|
+
match (left, right) {
|
|
10
|
+
(Unknown, _) | (_, Unknown) => Unknown,
|
|
11
|
+
(Float, _) | (_, Float) => Float,
|
|
12
|
+
(Decimal, _) | (_, Decimal) => Decimal,
|
|
13
|
+
(Integer, Integer) => Integer,
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
fn numeric_kind(expr: &Expression) -> NumericKind {
|
|
18
|
+
match expr {
|
|
19
|
+
Expression::Paren(p) => numeric_kind(&p.this),
|
|
20
|
+
Expression::Neg(n) => numeric_kind(&n.this),
|
|
21
|
+
Expression::Alias(a) => numeric_kind(&a.this),
|
|
22
|
+
Expression::Add(b) | Expression::Sub(b) | Expression::Mul(b) | Expression::Mod(b) => {
|
|
23
|
+
combine(numeric_kind(&b.left), numeric_kind(&b.right))
|
|
24
|
+
}
|
|
25
|
+
// The complete bottom-up source pass has already lowered fractional
|
|
26
|
+
// children to Div. Remaining IntDiv children have integer operands.
|
|
27
|
+
Expression::IntDiv(_) => NumericKind::Integer,
|
|
28
|
+
Expression::Div(_) => NumericKind::Float,
|
|
29
|
+
Expression::Function(f) if f.name.eq_ignore_ascii_case("NULLIF") && f.args.len() == 2 => {
|
|
30
|
+
numeric_kind(&f.args[0])
|
|
31
|
+
}
|
|
32
|
+
Expression::NullIf(f) => numeric_kind(&f.this),
|
|
33
|
+
_ => expression_numeric_kind(expr),
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/// Classify the rewritten DataFusion expression. Source `/` nodes have already
|
|
38
|
+
/// been made floating, and lowered `//` nodes retain their operands' types.
|
|
39
|
+
/// Never infer provenance from SQL syntax such as a NULLIF divisor.
|
|
40
|
+
fn datafusion_numeric_kind(expr: &Expression) -> NumericKind {
|
|
41
|
+
match expr {
|
|
42
|
+
Expression::Paren(p) => datafusion_numeric_kind(&p.this),
|
|
43
|
+
Expression::Annotated(a) => datafusion_numeric_kind(&a.this),
|
|
44
|
+
Expression::Neg(n) => datafusion_numeric_kind(&n.this),
|
|
45
|
+
Expression::Alias(a) => datafusion_numeric_kind(&a.this),
|
|
46
|
+
Expression::Abs(f) => datafusion_numeric_kind(&f.this),
|
|
47
|
+
Expression::Add(b) | Expression::Sub(b) | Expression::Mul(b) | Expression::Mod(b) => {
|
|
48
|
+
combine(
|
|
49
|
+
datafusion_numeric_kind(&b.left),
|
|
50
|
+
datafusion_numeric_kind(&b.right),
|
|
51
|
+
)
|
|
52
|
+
}
|
|
53
|
+
Expression::Div(b) => {
|
|
54
|
+
let left = datafusion_numeric_kind(&b.left);
|
|
55
|
+
// Div is already target SQL. Its generated NULLIF follows
|
|
56
|
+
// DataFusion's common-type coercion, including a floating divisor.
|
|
57
|
+
let right = match &b.right {
|
|
58
|
+
Expression::Function(f)
|
|
59
|
+
if f.name.eq_ignore_ascii_case("NULLIF") && f.args.len() == 2 =>
|
|
60
|
+
{
|
|
61
|
+
combine(
|
|
62
|
+
datafusion_numeric_kind(&f.args[0]),
|
|
63
|
+
datafusion_numeric_kind(&f.args[1]),
|
|
64
|
+
)
|
|
65
|
+
}
|
|
66
|
+
other => datafusion_numeric_kind(other),
|
|
67
|
+
};
|
|
68
|
+
// A source `/` supplies a floating operand even when columns or
|
|
69
|
+
// function return types on the other side are unresolved.
|
|
70
|
+
if left == NumericKind::Float || right == NumericKind::Float {
|
|
71
|
+
NumericKind::Float
|
|
72
|
+
} else {
|
|
73
|
+
combine(left, right)
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
Expression::Coalesce(f) => datafusion_branch_kind(f.expressions.iter()),
|
|
77
|
+
Expression::Case(c) => datafusion_branch_kind(
|
|
78
|
+
c.whens
|
|
79
|
+
.iter()
|
|
80
|
+
.map(|(_, result)| result)
|
|
81
|
+
.chain(c.else_.iter()),
|
|
82
|
+
),
|
|
83
|
+
Expression::IfFunc(f) => {
|
|
84
|
+
datafusion_branch_kind(std::iter::once(&f.true_value).chain(f.false_value.iter()))
|
|
85
|
+
}
|
|
86
|
+
Expression::Function(f) if f.name.eq_ignore_ascii_case("NULLIF") && f.args.len() == 2 => {
|
|
87
|
+
datafusion_nullif_kind(&f.args[0], &f.args[1])
|
|
88
|
+
}
|
|
89
|
+
Expression::NullIf(f) => datafusion_nullif_kind(&f.this, &f.expression),
|
|
90
|
+
// Do not assume functions such as ROUND preserve numeric types across
|
|
91
|
+
// dialects: DuckDB ROUND(integer) is integer, DataFusion's is floating.
|
|
92
|
+
_ => expression_numeric_kind(expr),
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
fn datafusion_branch_kind<'a>(branches: impl Iterator<Item = &'a Expression>) -> NumericKind {
|
|
97
|
+
branches
|
|
98
|
+
.filter(|expr| !matches!(expr, Expression::Null(_)))
|
|
99
|
+
.map(datafusion_numeric_kind)
|
|
100
|
+
.reduce(combine)
|
|
101
|
+
.unwrap_or(NumericKind::Unknown)
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
fn datafusion_nullif_kind(left: &Expression, right: &Expression) -> NumericKind {
|
|
105
|
+
let left_kind = datafusion_numeric_kind(left);
|
|
106
|
+
// DuckDB preserves the first argument's type, but DataFusion coerces both
|
|
107
|
+
// arguments to a common type. Mixed numeric types need an explicit cast.
|
|
108
|
+
if left_kind == datafusion_numeric_kind(right) || matches!(right, Expression::Null(_)) {
|
|
109
|
+
left_kind
|
|
110
|
+
} else {
|
|
111
|
+
NumericKind::Unknown
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
fn as_double(expr: Expression) -> Expression {
|
|
116
|
+
super::operators::cast_expr(
|
|
117
|
+
expr,
|
|
118
|
+
DataType::Double {
|
|
119
|
+
precision: None,
|
|
120
|
+
scale: None,
|
|
121
|
+
},
|
|
122
|
+
)
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
fn unresolved_division(target: DialectType) -> crate::error::Error {
|
|
126
|
+
crate::error::Error::unsupported(
|
|
127
|
+
"DuckDB // with unresolved operand types; use explicit numeric casts",
|
|
128
|
+
target.to_string(),
|
|
129
|
+
)
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
fn prepare_datafusion_division(expr: Expression) -> Result<Expression> {
|
|
133
|
+
// Stop the outer traversal at each outermost IntDiv. Rewrite that complete
|
|
134
|
+
// subtree once, bottom-up, including casts, functions, CASE and subqueries.
|
|
135
|
+
// Replacement nodes are not revisited, so a generated Div cannot be
|
|
136
|
+
// mistaken for a source `/`, even across nested integer divisions.
|
|
137
|
+
crate::traversal::transform_with_dispatch(
|
|
138
|
+
expr,
|
|
139
|
+
&Ok,
|
|
140
|
+
&|expr| !matches!(expr, Expression::IntDiv(_)),
|
|
141
|
+
&|expr, _| {
|
|
142
|
+
crate::traversal::transform_all(expr, &|mut expr| {
|
|
143
|
+
match &mut expr {
|
|
144
|
+
Expression::Div(b) => {
|
|
145
|
+
// Integer, decimal and unresolved source operands need
|
|
146
|
+
// floating arithmetic. Preserve an existing FLOAT operand
|
|
147
|
+
// rather than widening DuckDB's FLOAT/FLOAT division.
|
|
148
|
+
if datafusion_numeric_kind(&b.left) != NumericKind::Float
|
|
149
|
+
&& datafusion_numeric_kind(&b.right) != NumericKind::Float
|
|
150
|
+
{
|
|
151
|
+
b.left =
|
|
152
|
+
as_double(std::mem::replace(&mut b.left, Expression::number(0)));
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
Expression::Cast(c) | Expression::TryCast(c) | Expression::SafeCast(c)
|
|
156
|
+
if super::scalar::data_type_numeric_kind(&c.to) == NumericKind::Integer
|
|
157
|
+
&& matches!(
|
|
158
|
+
datafusion_numeric_kind(&c.this),
|
|
159
|
+
NumericKind::Float | NumericKind::Decimal
|
|
160
|
+
) =>
|
|
161
|
+
{
|
|
162
|
+
// DuckDB rounds numeric casts to integers; DataFusion
|
|
163
|
+
// truncates. This also matters after a nested source `/`.
|
|
164
|
+
c.this = Expression::Round(Box::new(RoundFunc {
|
|
165
|
+
this: std::mem::replace(&mut c.this, Expression::number(0)),
|
|
166
|
+
decimals: Some(Expression::number(0)),
|
|
167
|
+
}));
|
|
168
|
+
}
|
|
169
|
+
Expression::IntDiv(_) => {
|
|
170
|
+
let Expression::IntDiv(mut division) = expr else {
|
|
171
|
+
unreachable!()
|
|
172
|
+
};
|
|
173
|
+
let kind = combine(
|
|
174
|
+
datafusion_numeric_kind(&division.this),
|
|
175
|
+
datafusion_numeric_kind(&division.expression),
|
|
176
|
+
);
|
|
177
|
+
if kind == NumericKind::Unknown {
|
|
178
|
+
return Err(unresolved_division(DialectType::DataFusion));
|
|
179
|
+
}
|
|
180
|
+
if kind == NumericKind::Decimal {
|
|
181
|
+
division.this = as_double(division.this);
|
|
182
|
+
}
|
|
183
|
+
return Ok(Expression::Div(Box::new(BinaryOp::new(
|
|
184
|
+
division.this,
|
|
185
|
+
Expression::Function(Box::new(Function::new(
|
|
186
|
+
"NULLIF".to_string(),
|
|
187
|
+
vec![division.expression, Expression::number(0)],
|
|
188
|
+
))),
|
|
189
|
+
))));
|
|
190
|
+
}
|
|
191
|
+
_ => {}
|
|
192
|
+
}
|
|
193
|
+
Ok(expr)
|
|
194
|
+
})
|
|
195
|
+
},
|
|
196
|
+
)
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
pub(in crate::dialects) fn prepare_integer_division(
|
|
200
|
+
expr: Expression,
|
|
201
|
+
source: DialectType,
|
|
202
|
+
target: DialectType,
|
|
203
|
+
) -> Result<Expression> {
|
|
204
|
+
if source != DialectType::DuckDB || target == DialectType::DuckDB {
|
|
205
|
+
return Ok(expr);
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
if target == DialectType::DataFusion {
|
|
209
|
+
return prepare_datafusion_division(expr);
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
// Visit every physical child, including typed function arguments and both
|
|
213
|
+
// operands of nested IntDiv nodes, before lowering the enclosing operator.
|
|
214
|
+
crate::traversal::transform_all(expr, &|expr| {
|
|
215
|
+
let Expression::IntDiv(mut division) = expr else {
|
|
216
|
+
return Ok(expr);
|
|
217
|
+
};
|
|
218
|
+
let left_kind = numeric_kind(&division.this);
|
|
219
|
+
let right_kind = numeric_kind(&division.expression);
|
|
220
|
+
let kind = combine(left_kind, right_kind);
|
|
221
|
+
|
|
222
|
+
if kind == NumericKind::Unknown {
|
|
223
|
+
return Err(unresolved_division(target));
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
// NULLIF evaluates the divisor once and preserves NULL on zero for
|
|
227
|
+
// literals, casts, computed expressions, and values only known at runtime.
|
|
228
|
+
division.expression = Expression::Function(Box::new(Function::new(
|
|
229
|
+
"NULLIF".to_string(),
|
|
230
|
+
vec![division.expression, Expression::number(0)],
|
|
231
|
+
)));
|
|
232
|
+
|
|
233
|
+
if kind != NumericKind::Integer {
|
|
234
|
+
// DuckDB decimal division produces DOUBLE, whereas some targets
|
|
235
|
+
// keep decimal arithmetic (and SQLite may treat DECIMAL as INTEGER).
|
|
236
|
+
// An explicitly floating operand already establishes float division.
|
|
237
|
+
if kind == NumericKind::Decimal {
|
|
238
|
+
division.this = super::operators::cast_expr(
|
|
239
|
+
division.this,
|
|
240
|
+
DataType::Double {
|
|
241
|
+
precision: None,
|
|
242
|
+
scale: None,
|
|
243
|
+
},
|
|
244
|
+
);
|
|
245
|
+
}
|
|
246
|
+
return Ok(Expression::Div(Box::new(BinaryOp::new(
|
|
247
|
+
division.this,
|
|
248
|
+
division.expression,
|
|
249
|
+
))));
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
// Only use IntDiv where generation has a native or exact lowering.
|
|
253
|
+
// A generic DIV(...) call is invalid in several other targets.
|
|
254
|
+
if !matches!(
|
|
255
|
+
target,
|
|
256
|
+
DialectType::PostgreSQL
|
|
257
|
+
| DialectType::BigQuery
|
|
258
|
+
| DialectType::ClickHouse
|
|
259
|
+
| DialectType::SQLite
|
|
260
|
+
| DialectType::Vertica
|
|
261
|
+
| DialectType::Hive
|
|
262
|
+
| DialectType::Spark
|
|
263
|
+
| DialectType::Databricks
|
|
264
|
+
) {
|
|
265
|
+
return Err(crate::error::Error::unsupported(
|
|
266
|
+
"DuckDB integer // conversion",
|
|
267
|
+
target.to_string(),
|
|
268
|
+
));
|
|
269
|
+
}
|
|
270
|
+
Ok(Expression::IntDiv(division))
|
|
271
|
+
})
|
|
272
|
+
}
|
{polyglot_sql-0.13.2 → polyglot_sql-0.13.3}/crates/polyglot-sql/src/dialects/normalization/scalar.rs
RENAMED
|
@@ -15738,7 +15738,8 @@ pub(super) fn normalize_bigquery_function(
|
|
|
15738
15738
|
| DialectType::Athena
|
|
15739
15739
|
| DialectType::Snowflake
|
|
15740
15740
|
| DialectType::TSQL
|
|
15741
|
-
| DialectType::Fabric
|
|
15741
|
+
| DialectType::Fabric
|
|
15742
|
+
| DialectType::DataFusion => {
|
|
15742
15743
|
let x = args.remove(0);
|
|
15743
15744
|
let y = args.remove(0);
|
|
15744
15745
|
// Wrap complex expressions in parens to preserve precedence
|
|
@@ -3476,20 +3476,28 @@ impl Generator {
|
|
|
3476
3476
|
Ok(())
|
|
3477
3477
|
} else if is_native_slash_op {
|
|
3478
3478
|
// DuckDB and Vertica use // operator for integer division
|
|
3479
|
-
self.
|
|
3479
|
+
self.generate_infix_operand(InfixOperator::Div, &f.this, OperandSide::Left)?;
|
|
3480
3480
|
self.write(" // ");
|
|
3481
|
-
self.
|
|
3481
|
+
self.generate_infix_operand(
|
|
3482
|
+
InfixOperator::Div,
|
|
3483
|
+
&f.expression,
|
|
3484
|
+
OperandSide::Right,
|
|
3485
|
+
)?;
|
|
3482
3486
|
Ok(())
|
|
3483
3487
|
} else if matches!(
|
|
3484
3488
|
self.config.dialect,
|
|
3485
3489
|
Some(DialectType::Hive | DialectType::Spark | DialectType::Databricks)
|
|
3486
3490
|
) {
|
|
3487
3491
|
// Hive/Spark use DIV as an infix operator
|
|
3488
|
-
self.
|
|
3492
|
+
self.generate_infix_operand(InfixOperator::Div, &f.this, OperandSide::Left)?;
|
|
3489
3493
|
self.write(" ");
|
|
3490
3494
|
self.write_keyword("DIV");
|
|
3491
3495
|
self.write(" ");
|
|
3492
|
-
self.
|
|
3496
|
+
self.generate_infix_operand(
|
|
3497
|
+
InfixOperator::Div,
|
|
3498
|
+
&f.expression,
|
|
3499
|
+
OperandSide::Right,
|
|
3500
|
+
)?;
|
|
3493
3501
|
Ok(())
|
|
3494
3502
|
} else {
|
|
3495
3503
|
// Other dialects use DIV function
|
|
@@ -19030,13 +19038,14 @@ impl Generator {
|
|
|
19030
19038
|
matches!(self.config.dialect, Some(DialectType::ClickHouse))
|
|
19031
19039
|
}
|
|
19032
19040
|
|
|
19033
|
-
///
|
|
19034
|
-
fn
|
|
19035
|
-
|
|
19041
|
+
/// Whether `MOD(x, y)` is rendered as the infix `x % y` for this dialect.
|
|
19042
|
+
fn mod_func_uses_percent_operator(&self) -> bool {
|
|
19043
|
+
Self::mod_func_uses_percent_for(self.config.dialect)
|
|
19044
|
+
}
|
|
19036
19045
|
|
|
19037
|
-
|
|
19038
|
-
|
|
19039
|
-
|
|
19046
|
+
fn mod_func_uses_percent_for(dialect: Option<DialectType>) -> bool {
|
|
19047
|
+
matches!(
|
|
19048
|
+
dialect,
|
|
19040
19049
|
Some(DialectType::Snowflake)
|
|
19041
19050
|
| Some(DialectType::MySQL)
|
|
19042
19051
|
| Some(DialectType::Presto)
|
|
@@ -19049,11 +19058,20 @@ impl Generator {
|
|
|
19049
19058
|
| Some(DialectType::Athena)
|
|
19050
19059
|
| Some(DialectType::TSQL)
|
|
19051
19060
|
| Some(DialectType::Fabric)
|
|
19052
|
-
|
|
19061
|
+
| Some(DialectType::DataFusion)
|
|
19062
|
+
)
|
|
19063
|
+
}
|
|
19064
|
+
|
|
19065
|
+
/// Generate MOD function - uses % operator for dialects that prefer or require it.
|
|
19066
|
+
fn generate_mod_func(&mut self, f: &crate::expressions::BinaryFunc) -> Result<()> {
|
|
19067
|
+
// Several dialects prefer or require x % y instead of MOD(x, y).
|
|
19068
|
+
let use_percent_operator = self.mod_func_uses_percent_operator();
|
|
19053
19069
|
|
|
19054
19070
|
if use_percent_operator {
|
|
19055
19071
|
// MOD(a, b) treats both arguments as grouped expressions. When
|
|
19056
|
-
// lowering to an infix operator, keep binary arguments grouped
|
|
19072
|
+
// lowering to an infix operator, keep binary arguments grouped,
|
|
19073
|
+
// including operators introduced when rendering either argument.
|
|
19074
|
+
let dialect = self.config.dialect;
|
|
19057
19075
|
let needs_paren = |e: &Expression| {
|
|
19058
19076
|
matches!(
|
|
19059
19077
|
e,
|
|
@@ -19063,6 +19081,11 @@ impl Generator {
|
|
|
19063
19081
|
| Expression::Div(_)
|
|
19064
19082
|
| Expression::Mod(_)
|
|
19065
19083
|
| Expression::ModFunc(_)
|
|
19084
|
+
) || Self::infix_operand_needs_parentheses(
|
|
19085
|
+
dialect,
|
|
19086
|
+
InfixOperator::Mod,
|
|
19087
|
+
e,
|
|
19088
|
+
OperandSide::Right,
|
|
19066
19089
|
)
|
|
19067
19090
|
};
|
|
19068
19091
|
if needs_paren(&f.this) {
|
|
@@ -25720,7 +25743,12 @@ impl Generator {
|
|
|
25720
25743
|
infix_operator: Option<InfixOperator>,
|
|
25721
25744
|
) -> Result<()> {
|
|
25722
25745
|
let wrap_left = infix_operator.is_some_and(|parent| {
|
|
25723
|
-
Self::infix_operand_needs_parentheses(
|
|
25746
|
+
Self::infix_operand_needs_parentheses(
|
|
25747
|
+
self.config.dialect,
|
|
25748
|
+
parent,
|
|
25749
|
+
&op.left,
|
|
25750
|
+
OperandSide::Left,
|
|
25751
|
+
)
|
|
25724
25752
|
});
|
|
25725
25753
|
if wrap_left {
|
|
25726
25754
|
self.write("(");
|
|
@@ -25798,7 +25826,12 @@ impl Generator {
|
|
|
25798
25826
|
}
|
|
25799
25827
|
self.write_space();
|
|
25800
25828
|
let wrap_right = infix_operator.is_some_and(|parent| {
|
|
25801
|
-
Self::infix_operand_needs_parentheses(
|
|
25829
|
+
Self::infix_operand_needs_parentheses(
|
|
25830
|
+
self.config.dialect,
|
|
25831
|
+
parent,
|
|
25832
|
+
&op.right,
|
|
25833
|
+
OperandSide::Right,
|
|
25834
|
+
)
|
|
25802
25835
|
});
|
|
25803
25836
|
if wrap_right {
|
|
25804
25837
|
self.write("(");
|
|
@@ -25823,8 +25856,12 @@ impl Generator {
|
|
|
25823
25856
|
|
|
25824
25857
|
let generate_term =
|
|
25825
25858
|
|generator: &mut Self, term: &Expression, side: OperandSide| -> Result<()> {
|
|
25826
|
-
let should_wrap_for_precedence =
|
|
25827
|
-
|
|
25859
|
+
let should_wrap_for_precedence = Self::infix_operand_needs_parentheses(
|
|
25860
|
+
generator.config.dialect,
|
|
25861
|
+
connector.infix_operator(),
|
|
25862
|
+
term,
|
|
25863
|
+
side,
|
|
25864
|
+
);
|
|
25828
25865
|
let should_wrap_for_clickhouse = matches!(connector, ConnectorOperator::Or)
|
|
25829
25866
|
&& matches!(generator.config.dialect, Some(DialectType::ClickHouse))
|
|
25830
25867
|
&& matches!(
|
|
@@ -25903,8 +25940,32 @@ impl Generator {
|
|
|
25903
25940
|
}
|
|
25904
25941
|
}
|
|
25905
25942
|
|
|
25906
|
-
fn infix_operator(
|
|
25943
|
+
fn infix_operator(
|
|
25944
|
+
dialect: Option<DialectType>,
|
|
25945
|
+
expression: &Expression,
|
|
25946
|
+
) -> Option<InfixOperator> {
|
|
25907
25947
|
match expression {
|
|
25948
|
+
// `MOD(x, y)` lowered to `x % y` binds like the infix operator, so as an
|
|
25949
|
+
// operand it needs the same parentheses (`2 * MOD(5, 3)` -> `2 * (5 % 3)`).
|
|
25950
|
+
Expression::ModFunc(_) if Self::mod_func_uses_percent_for(dialect) => {
|
|
25951
|
+
Some(InfixOperator::Mod)
|
|
25952
|
+
}
|
|
25953
|
+
// IntDiv is atomic when rendered as a function or CAST, but // and
|
|
25954
|
+
// DIV have the same precedence and associativity as division.
|
|
25955
|
+
Expression::IntDiv(_)
|
|
25956
|
+
if matches!(
|
|
25957
|
+
dialect,
|
|
25958
|
+
Some(
|
|
25959
|
+
DialectType::DuckDB
|
|
25960
|
+
| DialectType::Vertica
|
|
25961
|
+
| DialectType::Hive
|
|
25962
|
+
| DialectType::Spark
|
|
25963
|
+
| DialectType::Databricks
|
|
25964
|
+
)
|
|
25965
|
+
) =>
|
|
25966
|
+
{
|
|
25967
|
+
Some(InfixOperator::Div)
|
|
25968
|
+
}
|
|
25908
25969
|
Expression::Or(_) => Some(InfixOperator::Or),
|
|
25909
25970
|
Expression::Xor(_) => Some(InfixOperator::Xor),
|
|
25910
25971
|
Expression::And(_) => Some(InfixOperator::And),
|
|
@@ -25940,6 +26001,7 @@ impl Generator {
|
|
|
25940
26001
|
}
|
|
25941
26002
|
|
|
25942
26003
|
fn infix_operand_needs_parentheses(
|
|
26004
|
+
dialect: Option<DialectType>,
|
|
25943
26005
|
parent: InfixOperator,
|
|
25944
26006
|
child: &Expression,
|
|
25945
26007
|
side: OperandSide,
|
|
@@ -25948,7 +26010,22 @@ impl Generator {
|
|
|
25948
26010
|
return false;
|
|
25949
26011
|
}
|
|
25950
26012
|
|
|
25951
|
-
|
|
26013
|
+
// Bitwise precedence differs between dialects. Group these operands
|
|
26014
|
+
// explicitly when emitting arithmetic, including a lowered MOD call.
|
|
26015
|
+
if parent.is_arithmetic()
|
|
26016
|
+
&& matches!(
|
|
26017
|
+
child,
|
|
26018
|
+
Expression::BitwiseAnd(_)
|
|
26019
|
+
| Expression::BitwiseOr(_)
|
|
26020
|
+
| Expression::BitwiseXor(_)
|
|
26021
|
+
| Expression::BitwiseLeftShift(_)
|
|
26022
|
+
| Expression::BitwiseRightShift(_)
|
|
26023
|
+
)
|
|
26024
|
+
{
|
|
26025
|
+
return true;
|
|
26026
|
+
}
|
|
26027
|
+
|
|
26028
|
+
let Some(child_operator) = Self::infix_operator(dialect, child) else {
|
|
25952
26029
|
return false;
|
|
25953
26030
|
};
|
|
25954
26031
|
|
|
@@ -25974,7 +26051,8 @@ impl Generator {
|
|
|
25974
26051
|
expression: &Expression,
|
|
25975
26052
|
side: OperandSide,
|
|
25976
26053
|
) -> Result<()> {
|
|
25977
|
-
let needs_parentheses =
|
|
26054
|
+
let needs_parentheses =
|
|
26055
|
+
Self::infix_operand_needs_parentheses(self.config.dialect, parent, expression, side);
|
|
25978
26056
|
if needs_parentheses {
|
|
25979
26057
|
self.write("(");
|
|
25980
26058
|
}
|
|
@@ -26155,7 +26233,12 @@ impl Generator {
|
|
|
26155
26233
|
infix_operator: Option<InfixOperator>,
|
|
26156
26234
|
) -> Result<()> {
|
|
26157
26235
|
let wrap_left = infix_operator.is_some_and(|parent| {
|
|
26158
|
-
Self::infix_operand_needs_parentheses(
|
|
26236
|
+
Self::infix_operand_needs_parentheses(
|
|
26237
|
+
self.config.dialect,
|
|
26238
|
+
parent,
|
|
26239
|
+
&op.left,
|
|
26240
|
+
OperandSide::Left,
|
|
26241
|
+
)
|
|
26159
26242
|
});
|
|
26160
26243
|
if wrap_left {
|
|
26161
26244
|
self.write("(");
|
|
@@ -26212,7 +26295,12 @@ impl Generator {
|
|
|
26212
26295
|
}
|
|
26213
26296
|
self.write_space();
|
|
26214
26297
|
let wrap_right = infix_operator.is_some_and(|parent| {
|
|
26215
|
-
Self::infix_operand_needs_parentheses(
|
|
26298
|
+
Self::infix_operand_needs_parentheses(
|
|
26299
|
+
self.config.dialect,
|
|
26300
|
+
parent,
|
|
26301
|
+
&op.right,
|
|
26302
|
+
OperandSide::Right,
|
|
26303
|
+
)
|
|
26216
26304
|
});
|
|
26217
26305
|
if wrap_right {
|
|
26218
26306
|
self.write("(");
|
|
@@ -26253,7 +26341,18 @@ impl Generator {
|
|
|
26253
26341
|
self.write_space();
|
|
26254
26342
|
}
|
|
26255
26343
|
}
|
|
26256
|
-
|
|
26344
|
+
// Function-like AST nodes such as MOD and DIV can render as infix
|
|
26345
|
+
// operators. Preserve their grouping under a symbolic unary operator.
|
|
26346
|
+
let needs_parens = matches!(operator, "-" | "~")
|
|
26347
|
+
&& Self::infix_operator(self.config.dialect, &op.this).is_some();
|
|
26348
|
+
if needs_parens {
|
|
26349
|
+
self.write("(");
|
|
26350
|
+
}
|
|
26351
|
+
self.generate_expression(&op.this)?;
|
|
26352
|
+
if needs_parens {
|
|
26353
|
+
self.write(")");
|
|
26354
|
+
}
|
|
26355
|
+
Ok(())
|
|
26257
26356
|
}
|
|
26258
26357
|
|
|
26259
26358
|
fn generate_in(&mut self, in_expr: &In) -> Result<()> {
|