polyglot-sql 0.13.1__tar.gz → 0.13.2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/Cargo.lock +6 -6
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/Cargo.toml +1 -1
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/PKG-INFO +1 -1
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/crates/polyglot-sql/Cargo.toml +2 -2
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/crates/polyglot-sql/README.md +4 -4
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/crates/polyglot-sql/src/dialects/duckdb.rs +2 -0
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/crates/polyglot-sql/src/dialects/mod.rs +246 -4
- polyglot_sql-0.13.2/crates/polyglot-sql/src/dialects/normalization/duckdb.rs +107 -0
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/crates/polyglot-sql/src/dialects/normalization/mod.rs +1 -0
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/crates/polyglot-sql/src/generator.rs +37 -6
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/crates/polyglot-sql/src/parser.rs +22 -0
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/crates/polyglot-sql/src/transforms.rs +48 -2
- polyglot_sql-0.13.2/crates/polyglot-sql/tests/duckdb_integer_division.rs +367 -0
- polyglot_sql-0.13.2/crates/polyglot-sql/tests/duckdb_order_by_all.rs +517 -0
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/crates/polyglot-sql-function-catalogs/README.md +1 -1
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/README.md +0 -0
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/crates/polyglot-sql/benches/allocation_hotspots.rs +0 -0
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/crates/polyglot-sql/benches/ast_traversal.rs +0 -0
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/crates/polyglot-sql/benches/common/mod.rs +0 -0
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/crates/polyglot-sql/benches/in_list.rs +0 -0
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/crates/polyglot-sql/benches/lineage.rs +0 -0
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/crates/polyglot-sql/benches/parsing.rs +0 -0
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/crates/polyglot-sql/benches/performance_hotspots.rs +0 -0
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/crates/polyglot-sql/benches/rust_parsing.rs +0 -0
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/crates/polyglot-sql/benches/transpile.rs +0 -0
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/crates/polyglot-sql/examples/basic_usage.rs +0 -0
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/crates/polyglot-sql/examples/bench_json.rs +0 -0
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/crates/polyglot-sql/src/ast_children.rs +0 -0
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/crates/polyglot-sql/src/ast_json.rs +0 -0
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/crates/polyglot-sql/src/ast_mutation.rs +0 -0
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/crates/polyglot-sql/src/ast_transforms.rs +0 -0
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/crates/polyglot-sql/src/binding.rs +0 -0
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/crates/polyglot-sql/src/builder/mod.rs +0 -0
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/crates/polyglot-sql/src/builder/plan.rs +0 -0
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/crates/polyglot-sql/src/dialects/athena.rs +0 -0
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/crates/polyglot-sql/src/dialects/bigquery.rs +0 -0
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/crates/polyglot-sql/src/dialects/clickhouse.rs +0 -0
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/crates/polyglot-sql/src/dialects/cockroachdb.rs +0 -0
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/crates/polyglot-sql/src/dialects/databricks.rs +0 -0
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/crates/polyglot-sql/src/dialects/datafusion.rs +0 -0
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/crates/polyglot-sql/src/dialects/doris.rs +0 -0
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/crates/polyglot-sql/src/dialects/dremio.rs +0 -0
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/crates/polyglot-sql/src/dialects/drill.rs +0 -0
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/crates/polyglot-sql/src/dialects/druid.rs +0 -0
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/crates/polyglot-sql/src/dialects/dune.rs +0 -0
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/crates/polyglot-sql/src/dialects/exasol.rs +0 -0
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/crates/polyglot-sql/src/dialects/fabric.rs +0 -0
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/crates/polyglot-sql/src/dialects/generic.rs +0 -0
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/crates/polyglot-sql/src/dialects/hana.rs +0 -0
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/crates/polyglot-sql/src/dialects/hive.rs +0 -0
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/crates/polyglot-sql/src/dialects/materialize.rs +0 -0
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/crates/polyglot-sql/src/dialects/mysql.rs +0 -0
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/crates/polyglot-sql/src/dialects/normalization/aggregates.rs +0 -0
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/crates/polyglot-sql/src/dialects/normalization/collections.rs +0 -0
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/crates/polyglot-sql/src/dialects/normalization/hana.rs +0 -0
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/crates/polyglot-sql/src/dialects/normalization/json.rs +0 -0
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/crates/polyglot-sql/src/dialects/normalization/operators.rs +0 -0
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/crates/polyglot-sql/src/dialects/normalization/postgres_interval.rs +0 -0
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/crates/polyglot-sql/src/dialects/normalization/scalar.rs +0 -0
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/crates/polyglot-sql/src/dialects/normalization/statements.rs +0 -0
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/crates/polyglot-sql/src/dialects/normalization/temporal.rs +0 -0
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/crates/polyglot-sql/src/dialects/normalization/types.rs +0 -0
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/crates/polyglot-sql/src/dialects/normalization/vertica.rs +0 -0
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/crates/polyglot-sql/src/dialects/oracle.rs +0 -0
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/crates/polyglot-sql/src/dialects/postgres.rs +0 -0
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/crates/polyglot-sql/src/dialects/presto.rs +0 -0
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/crates/polyglot-sql/src/dialects/redshift.rs +0 -0
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/crates/polyglot-sql/src/dialects/risingwave.rs +0 -0
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/crates/polyglot-sql/src/dialects/singlestore.rs +0 -0
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/crates/polyglot-sql/src/dialects/snowflake.rs +0 -0
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/crates/polyglot-sql/src/dialects/solr.rs +0 -0
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/crates/polyglot-sql/src/dialects/spark.rs +0 -0
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/crates/polyglot-sql/src/dialects/sqlite.rs +0 -0
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/crates/polyglot-sql/src/dialects/starrocks.rs +0 -0
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/crates/polyglot-sql/src/dialects/tableau.rs +0 -0
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/crates/polyglot-sql/src/dialects/teradata.rs +0 -0
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/crates/polyglot-sql/src/dialects/tidb.rs +0 -0
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/crates/polyglot-sql/src/dialects/trino.rs +0 -0
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/crates/polyglot-sql/src/dialects/tsql.rs +0 -0
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/crates/polyglot-sql/src/dialects/vertica.rs +0 -0
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/crates/polyglot-sql/src/diff.rs +0 -0
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/crates/polyglot-sql/src/error.rs +0 -0
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/crates/polyglot-sql/src/expressions.rs +0 -0
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/crates/polyglot-sql/src/format_tokens.rs +0 -0
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/crates/polyglot-sql/src/function_catalog.rs +0 -0
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/crates/polyglot-sql/src/function_registry.rs +0 -0
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/crates/polyglot-sql/src/guard.rs +0 -0
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/crates/polyglot-sql/src/helper.rs +0 -0
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/crates/polyglot-sql/src/lib.rs +0 -0
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/crates/polyglot-sql/src/lineage.rs +0 -0
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/crates/polyglot-sql/src/openlineage.rs +0 -0
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/crates/polyglot-sql/src/optimizer/annotate_types.rs +0 -0
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/crates/polyglot-sql/src/optimizer/canonicalize.rs +0 -0
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/crates/polyglot-sql/src/optimizer/eliminate_ctes.rs +0 -0
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/crates/polyglot-sql/src/optimizer/eliminate_joins.rs +0 -0
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/crates/polyglot-sql/src/optimizer/isolate_table_selects.rs +0 -0
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/crates/polyglot-sql/src/optimizer/mod.rs +0 -0
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/crates/polyglot-sql/src/optimizer/normalize.rs +0 -0
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/crates/polyglot-sql/src/optimizer/normalize_identifiers.rs +0 -0
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/crates/polyglot-sql/src/optimizer/optimize_joins.rs +0 -0
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/crates/polyglot-sql/src/optimizer/optimizer.rs +0 -0
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/crates/polyglot-sql/src/optimizer/pushdown_predicates.rs +0 -0
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/crates/polyglot-sql/src/optimizer/pushdown_projections.rs +0 -0
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/crates/polyglot-sql/src/optimizer/qualify_columns.rs +0 -0
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/crates/polyglot-sql/src/optimizer/qualify_tables.rs +0 -0
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/crates/polyglot-sql/src/optimizer/set_operation_types.rs +0 -0
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/crates/polyglot-sql/src/optimizer/simplify.rs +0 -0
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/crates/polyglot-sql/src/optimizer/subquery.rs +0 -0
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/crates/polyglot-sql/src/planner.rs +0 -0
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/crates/polyglot-sql/src/query_analysis/column_uses.rs +0 -0
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/crates/polyglot-sql/src/query_analysis.rs +0 -0
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/crates/polyglot-sql/src/resolver.rs +0 -0
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/crates/polyglot-sql/src/schema.rs +0 -0
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/crates/polyglot-sql/src/scope.rs +0 -0
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/crates/polyglot-sql/src/set_operation.rs +0 -0
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/crates/polyglot-sql/src/time.rs +0 -0
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/crates/polyglot-sql/src/tokens.rs +0 -0
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/crates/polyglot-sql/src/traversal.rs +0 -0
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/crates/polyglot-sql/src/trie.rs +0 -0
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/crates/polyglot-sql/src/validation/semantics.rs +0 -0
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/crates/polyglot-sql/src/validation/tests.rs +0 -0
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/crates/polyglot-sql/src/validation.rs +0 -0
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/crates/polyglot-sql/tests/analyze_failures.rs +0 -0
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/crates/polyglot-sql/tests/clickhouse_regression.rs +0 -0
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/crates/polyglot-sql/tests/common/known_failures.rs +0 -0
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/crates/polyglot-sql/tests/common/mod.rs +0 -0
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/crates/polyglot-sql/tests/common/test_data.rs +0 -0
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/crates/polyglot-sql/tests/common/test_runner.rs +0 -0
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/crates/polyglot-sql/tests/create_view_security_comment_regression.rs +0 -0
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/crates/polyglot-sql/tests/custom_clickhouse_coverage.rs +0 -0
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/crates/polyglot-sql/tests/custom_clickhouse_parser.rs +0 -0
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/crates/polyglot-sql/tests/custom_dialect.rs +0 -0
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/crates/polyglot-sql/tests/custom_dialect_tests.rs +0 -0
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/crates/polyglot-sql/tests/custom_fixtures/datafusion/ddl.json +0 -0
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/crates/polyglot-sql/tests/custom_fixtures/datafusion/dml.json +0 -0
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/crates/polyglot-sql/tests/custom_fixtures/datafusion/functions.json +0 -0
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/crates/polyglot-sql/tests/custom_fixtures/datafusion/identity.json +0 -0
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/crates/polyglot-sql/tests/custom_fixtures/datafusion/operators.json +0 -0
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/crates/polyglot-sql/tests/custom_fixtures/datafusion/select.json +0 -0
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/crates/polyglot-sql/tests/custom_fixtures/datafusion/transpilation.json +0 -0
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/crates/polyglot-sql/tests/custom_fixtures/datafusion/types.json +0 -0
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/crates/polyglot-sql/tests/custom_fixtures/hana/ddl.json +0 -0
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/crates/polyglot-sql/tests/custom_fixtures/hana/dml.json +0 -0
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/crates/polyglot-sql/tests/custom_fixtures/hana/functions.json +0 -0
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/crates/polyglot-sql/tests/custom_fixtures/hana/identity.json +0 -0
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/crates/polyglot-sql/tests/custom_fixtures/hana/select.json +0 -0
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/crates/polyglot-sql/tests/custom_fixtures/hana/types.json +0 -0
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/crates/polyglot-sql/tests/custom_fixtures/vertica/identity.json +0 -0
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/crates/polyglot-sql/tests/custom_fixtures/vertica/transpilation.json +0 -0
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/crates/polyglot-sql/tests/custom_fixtures/vertica/types.json +0 -0
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/crates/polyglot-sql/tests/data_type_api.rs +0 -0
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/crates/polyglot-sql/tests/deep_nesting_regression.rs +0 -0
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/crates/polyglot-sql/tests/dialect_matrix.rs +0 -0
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/crates/polyglot-sql/tests/error_handling.rs +0 -0
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/crates/polyglot-sql/tests/fabric_regression.rs +0 -0
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/crates/polyglot-sql/tests/fabric_tpch_regression.rs +0 -0
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/crates/polyglot-sql/tests/identity_roundtrip.rs +0 -0
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/crates/polyglot-sql/tests/oracle_data_types_regression.rs +0 -0
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/crates/polyglot-sql/tests/postgres_explain_options.rs +0 -0
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/crates/polyglot-sql/tests/postgres_regexp_clickhouse.rs +0 -0
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/crates/polyglot-sql/tests/postgres_sqlite_regression.rs +0 -0
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/crates/polyglot-sql/tests/query_analysis.rs +0 -0
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/crates/polyglot-sql/tests/query_analysis_regression.rs +0 -0
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/crates/polyglot-sql/tests/snowflake_regression_test.rs +0 -0
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/crates/polyglot-sql/tests/sqlglot_compat.rs +0 -0
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/crates/polyglot-sql/tests/sqlglot_dialect_identity.rs +0 -0
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/crates/polyglot-sql/tests/sqlglot_identity.rs +0 -0
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/crates/polyglot-sql/tests/sqlglot_identity_detailed.rs +0 -0
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/crates/polyglot-sql/tests/sqlglot_parser.rs +0 -0
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/crates/polyglot-sql/tests/sqlglot_pretty.rs +0 -0
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/crates/polyglot-sql/tests/sqlglot_transpilation.rs +0 -0
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/crates/polyglot-sql/tests/sqlglot_transpile.rs +0 -0
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/crates/polyglot-sql/tests/tpch_transpile_stack.rs +0 -0
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/crates/polyglot-sql/tests/transform_regression.rs +0 -0
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/crates/polyglot-sql/tests/tsql_regression.rs +0 -0
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/crates/polyglot-sql-ast-derive/Cargo.toml +0 -0
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/crates/polyglot-sql-ast-derive/src/lib.rs +0 -0
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/crates/polyglot-sql-function-catalogs/Cargo.toml +0 -0
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/crates/polyglot-sql-function-catalogs/src/clickhouse.rs +0 -0
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/crates/polyglot-sql-function-catalogs/src/duckdb.rs +0 -0
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/crates/polyglot-sql-function-catalogs/src/lib.rs +0 -0
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/crates/polyglot-sql-function-catalogs/tools/clickhouse/extract_functions.py +0 -0
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/crates/polyglot-sql-function-catalogs/tools/duckdb/extract_functions.py +0 -0
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/crates/polyglot-sql-python/Cargo.toml +0 -0
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/crates/polyglot-sql-python/README.md +0 -0
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/crates/polyglot-sql-python/docs/api.md +0 -0
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/crates/polyglot-sql-python/docs/index.md +0 -0
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/crates/polyglot-sql-python/mkdocs.yml +0 -0
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/crates/polyglot-sql-python/src/annotate_types.rs +0 -0
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/crates/polyglot-sql-python/src/builders.rs +0 -0
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/crates/polyglot-sql-python/src/dialects.rs +0 -0
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/crates/polyglot-sql-python/src/diff.rs +0 -0
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/crates/polyglot-sql-python/src/errors.rs +0 -0
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/crates/polyglot-sql-python/src/expr.rs +0 -0
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/crates/polyglot-sql-python/src/expr_types.rs +0 -0
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/crates/polyglot-sql-python/src/format.rs +0 -0
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/crates/polyglot-sql-python/src/generate.rs +0 -0
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/crates/polyglot-sql-python/src/helpers.rs +0 -0
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/crates/polyglot-sql-python/src/lib.rs +0 -0
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/crates/polyglot-sql-python/src/lineage.rs +0 -0
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/crates/polyglot-sql-python/src/openlineage.rs +0 -0
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/crates/polyglot-sql-python/src/optimize.rs +0 -0
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/crates/polyglot-sql-python/src/parse.rs +0 -0
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/crates/polyglot-sql-python/src/query_analysis.rs +0 -0
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/crates/polyglot-sql-python/src/tokenize.rs +0 -0
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/crates/polyglot-sql-python/src/transforms.rs +0 -0
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/crates/polyglot-sql-python/src/transpile.rs +0 -0
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/crates/polyglot-sql-python/src/types.rs +0 -0
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/crates/polyglot-sql-python/src/validate.rs +0 -0
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/crates/polyglot-sql-python/tests/conftest.py +0 -0
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/crates/polyglot-sql-python/tests/test_builders.py +0 -0
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/crates/polyglot-sql-python/tests/test_compat.py +0 -0
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/crates/polyglot-sql-python/tests/test_dialects.py +0 -0
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/crates/polyglot-sql-python/tests/test_diff.py +0 -0
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/crates/polyglot-sql-python/tests/test_expression.py +0 -0
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/crates/polyglot-sql-python/tests/test_format.py +0 -0
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/crates/polyglot-sql-python/tests/test_generate.py +0 -0
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/crates/polyglot-sql-python/tests/test_lineage.py +0 -0
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/crates/polyglot-sql-python/tests/test_optimize.py +0 -0
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/crates/polyglot-sql-python/tests/test_parse.py +0 -0
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/crates/polyglot-sql-python/tests/test_query_analysis.py +0 -0
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/crates/polyglot-sql-python/tests/test_transforms.py +0 -0
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/crates/polyglot-sql-python/tests/test_transpile.py +0 -0
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/crates/polyglot-sql-python/tests/test_validate.py +0 -0
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/crates/polyglot-sql-python/uv.lock +0 -0
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/pyproject.toml +0 -0
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/python/polyglot_sql/__init__.py +0 -0
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/python/polyglot_sql/__init__.pyi +0 -0
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/python/polyglot_sql/analysis_types.py +0 -0
- {polyglot_sql-0.13.1 → polyglot_sql-0.13.2}/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.2"
|
|
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.2"
|
|
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.2"
|
|
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.2"
|
|
646
646
|
|
|
647
647
|
[[package]]
|
|
648
648
|
name = "polyglot-sql-python"
|
|
649
|
-
version = "0.13.
|
|
649
|
+
version = "0.13.2"
|
|
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.2"
|
|
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.2" }
|
|
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.2", 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.2", default-features = false }
|
|
29
29
|
```
|
|
30
30
|
|
|
31
31
|
```toml
|
|
32
32
|
polyglot-sql = {
|
|
33
|
-
version = "0.13.
|
|
33
|
+
version = "0.13.2",
|
|
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.2",
|
|
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.2",
|
|
55
55
|
default-features = false,
|
|
56
56
|
features = ["transpile", "dialect-clickhouse", "dialect-postgresql"],
|
|
57
57
|
}
|
|
@@ -103,6 +103,8 @@ impl DialectImpl for DuckDBDialect {
|
|
|
103
103
|
config.nested_comments = true;
|
|
104
104
|
// DuckDB allows underscores as digit separators in numeric literals
|
|
105
105
|
config.numbers_can_be_underscore_separated = true;
|
|
106
|
+
// `//` is integer division (same tokenizer-level recognition as Vertica)
|
|
107
|
+
config.double_slash_int_div = true;
|
|
106
108
|
config
|
|
107
109
|
}
|
|
108
110
|
|
|
@@ -298,6 +298,20 @@ impl DialectType {
|
|
|
298
298
|
DialectType::TSQL | DialectType::Fabric | DialectType::MySQL | DialectType::SQLite
|
|
299
299
|
) || (matches!(self, DialectType::DuckDB) && explicit_as)
|
|
300
300
|
}
|
|
301
|
+
|
|
302
|
+
/// Whether this dialect natively accepts DuckDB-style `ORDER BY ALL`
|
|
303
|
+
/// (a bare `ALL` keyword meaning "every projected column, in order").
|
|
304
|
+
/// Other targets need it rewritten to positional `ORDER BY 1, 2, ...`.
|
|
305
|
+
pub(crate) const fn supports_order_by_all(self) -> bool {
|
|
306
|
+
matches!(
|
|
307
|
+
self,
|
|
308
|
+
DialectType::DuckDB
|
|
309
|
+
| DialectType::Snowflake
|
|
310
|
+
| DialectType::ClickHouse
|
|
311
|
+
| DialectType::Databricks
|
|
312
|
+
| DialectType::Spark
|
|
313
|
+
)
|
|
314
|
+
}
|
|
301
315
|
}
|
|
302
316
|
|
|
303
317
|
impl Default for DialectType {
|
|
@@ -648,6 +662,189 @@ fn is_default_presto_date_format(fmt: &str) -> bool {
|
|
|
648
662
|
fmt == "%Y-%m-%d" || fmt == "%F"
|
|
649
663
|
}
|
|
650
664
|
|
|
665
|
+
/// The parser marks the ORDER BY ALL keyword as a Var, never an identifier.
|
|
666
|
+
#[cfg(feature = "generate")]
|
|
667
|
+
pub(crate) fn is_order_by_all_marker(e: &Expression) -> bool {
|
|
668
|
+
matches!(e, Expression::Var(v) if v.this.eq_ignore_ascii_case("all"))
|
|
669
|
+
}
|
|
670
|
+
|
|
671
|
+
#[cfg(feature = "transpile")]
|
|
672
|
+
fn is_order_by_all(order_by: &Option<crate::expressions::OrderBy>) -> bool {
|
|
673
|
+
order_by.as_ref().is_some_and(|ob| {
|
|
674
|
+
ob.expressions.len() == 1 && is_order_by_all_marker(&ob.expressions[0].this)
|
|
675
|
+
})
|
|
676
|
+
}
|
|
677
|
+
|
|
678
|
+
/// Whether `e` is a projection item that can produce more or fewer than one
|
|
679
|
+
/// output column (`*`, or DuckDB's `COLUMNS(...)` macro), making the output
|
|
680
|
+
/// column count unknowable from the AST alone.
|
|
681
|
+
#[cfg(feature = "transpile")]
|
|
682
|
+
fn has_unknown_column_count(e: &Expression) -> bool {
|
|
683
|
+
use crate::expressions::Expression as E;
|
|
684
|
+
let mut inner = e;
|
|
685
|
+
loop {
|
|
686
|
+
inner = match inner {
|
|
687
|
+
E::Alias(a) => &a.this,
|
|
688
|
+
E::Paren(p) => &p.this,
|
|
689
|
+
_ => break,
|
|
690
|
+
};
|
|
691
|
+
}
|
|
692
|
+
if matches!(inner, E::Star(_)) {
|
|
693
|
+
return true;
|
|
694
|
+
}
|
|
695
|
+
// COLUMNS still expands inside arithmetic, casts and aggregate/function
|
|
696
|
+
// arguments. COUNT(*) and scalar subqueries, however, produce one column.
|
|
697
|
+
contains_in_projection(inner, |node| match node {
|
|
698
|
+
E::Columns(_) => true,
|
|
699
|
+
E::Function(f) => {
|
|
700
|
+
!f.quoted && f.qualified_name.is_empty() && f.name.eq_ignore_ascii_case("COLUMNS")
|
|
701
|
+
}
|
|
702
|
+
E::MethodCall(m) => m.method.name.eq_ignore_ascii_case("COLUMNS"),
|
|
703
|
+
_ => false,
|
|
704
|
+
})
|
|
705
|
+
}
|
|
706
|
+
|
|
707
|
+
#[cfg(feature = "transpile")]
|
|
708
|
+
pub(crate) fn contains_in_projection(
|
|
709
|
+
e: &Expression,
|
|
710
|
+
predicate: impl Fn(&Expression) -> bool,
|
|
711
|
+
) -> bool {
|
|
712
|
+
let mut pending = vec![e];
|
|
713
|
+
while let Some(node) = pending.pop() {
|
|
714
|
+
if matches!(
|
|
715
|
+
node,
|
|
716
|
+
Expression::Subquery(_) | Expression::Select(_) | Expression::Exists(_)
|
|
717
|
+
) {
|
|
718
|
+
continue;
|
|
719
|
+
}
|
|
720
|
+
if predicate(node) {
|
|
721
|
+
return true;
|
|
722
|
+
}
|
|
723
|
+
crate::ast_children::for_each_child_untracked(node, |child| pending.push(child));
|
|
724
|
+
}
|
|
725
|
+
false
|
|
726
|
+
}
|
|
727
|
+
|
|
728
|
+
/// The number of columns a query block projects, when that count is known
|
|
729
|
+
/// statically from the AST. Compound queries (UNION/INTERSECT/EXCEPT) take
|
|
730
|
+
/// their width from the left-hand operand, per standard SQL set-operation
|
|
731
|
+
/// rules (both sides must already agree on column count).
|
|
732
|
+
#[cfg(feature = "transpile")]
|
|
733
|
+
fn query_output_width(e: &Expression) -> Option<usize> {
|
|
734
|
+
use crate::expressions::Expression as E;
|
|
735
|
+
match e {
|
|
736
|
+
E::Select(sel) => {
|
|
737
|
+
if sel.expressions.is_empty() || sel.expressions.iter().any(has_unknown_column_count) {
|
|
738
|
+
None
|
|
739
|
+
} else {
|
|
740
|
+
Some(sel.expressions.len())
|
|
741
|
+
}
|
|
742
|
+
}
|
|
743
|
+
E::Paren(p) => query_output_width(&p.this),
|
|
744
|
+
E::Subquery(s) => query_output_width(&s.this),
|
|
745
|
+
E::Union(u) if !u.by_name => query_output_width(&u.left),
|
|
746
|
+
E::Intersect(i) => query_output_width(&i.left),
|
|
747
|
+
E::Except(ex) => query_output_width(&ex.left),
|
|
748
|
+
_ => None,
|
|
749
|
+
}
|
|
750
|
+
}
|
|
751
|
+
|
|
752
|
+
/// Rewrite an `ORDER BY ALL` clause into positional `ORDER BY 1..n` over
|
|
753
|
+
/// `width` columns, in place. No-op if `order_by` isn't the ALL marker.
|
|
754
|
+
/// Errors if the marker is present but `width` is unknown (e.g. a `*` or
|
|
755
|
+
/// `COLUMNS(...)` projection, where positional ordinals can't be derived).
|
|
756
|
+
///
|
|
757
|
+
/// The source's explicit direction and NULL order (if any) carry over to each
|
|
758
|
+
/// positional entry unchanged; the later cross-dialect NULL-ordering pass
|
|
759
|
+
/// fills in the source dialect's implied default where the target's differs.
|
|
760
|
+
/// MySQL is the exception: it has no NULLS FIRST/LAST syntax and is skipped by
|
|
761
|
+
/// that pass, so compare every supported source's default against MySQL here.
|
|
762
|
+
#[cfg(feature = "transpile")]
|
|
763
|
+
fn expand_order_by_all(
|
|
764
|
+
order_by: &mut Option<crate::expressions::OrderBy>,
|
|
765
|
+
width: Option<usize>,
|
|
766
|
+
source: DialectType,
|
|
767
|
+
target: DialectType,
|
|
768
|
+
) -> Result<()> {
|
|
769
|
+
use crate::expressions::Expression as E;
|
|
770
|
+
if !is_order_by_all(order_by) {
|
|
771
|
+
return Ok(());
|
|
772
|
+
}
|
|
773
|
+
let Some(n) = width else {
|
|
774
|
+
return Err(crate::error::Error::unsupported(
|
|
775
|
+
"ORDER BY ALL over a projection with an unknown column count (*, COLUMNS(...), or UNION BY NAME) cannot be expanded to positional ORDER BY",
|
|
776
|
+
target.to_string(),
|
|
777
|
+
));
|
|
778
|
+
};
|
|
779
|
+
let ob = order_by.as_mut().unwrap();
|
|
780
|
+
let (desc, nulls_first) = (ob.expressions[0].desc, ob.expressions[0].nulls_first);
|
|
781
|
+
|
|
782
|
+
// An ordinal cannot be used inside a CASE expression to emulate NULL
|
|
783
|
+
// placement: it would become a constant instead of a column reference.
|
|
784
|
+
if matches!(target, DialectType::MySQL) {
|
|
785
|
+
let required_nulls_first = nulls_first.unwrap_or(match source {
|
|
786
|
+
DialectType::DuckDB | DialectType::ClickHouse => false,
|
|
787
|
+
DialectType::Snowflake => desc,
|
|
788
|
+
DialectType::Spark | DialectType::Databricks => !desc,
|
|
789
|
+
_ => unreachable!("ORDER BY ALL source capability must be checked"),
|
|
790
|
+
});
|
|
791
|
+
if required_nulls_first != !desc {
|
|
792
|
+
return Err(crate::error::Error::unsupported(
|
|
793
|
+
"ORDER BY ALL's NULL ordering (MySQL's default NULL placement does not match and cannot be emulated with positional ordering)",
|
|
794
|
+
target.to_string(),
|
|
795
|
+
));
|
|
796
|
+
}
|
|
797
|
+
}
|
|
798
|
+
|
|
799
|
+
ob.expressions = (1..=n as i64)
|
|
800
|
+
.map(|i| {
|
|
801
|
+
let mut o = ob.expressions[0].clone();
|
|
802
|
+
o.this = E::number(i);
|
|
803
|
+
if target == DialectType::MySQL {
|
|
804
|
+
// Matching explicit NULL placement is redundant and MySQL
|
|
805
|
+
// cannot print the NULLS FIRST/LAST syntax.
|
|
806
|
+
o.nulls_first = None;
|
|
807
|
+
}
|
|
808
|
+
o
|
|
809
|
+
})
|
|
810
|
+
.collect();
|
|
811
|
+
Ok(())
|
|
812
|
+
}
|
|
813
|
+
|
|
814
|
+
/// Expand when the target lacks ALL, or when a native target cannot use it
|
|
815
|
+
/// for this query (aggregate projections in Snowflake, DISTINCT ON emulation).
|
|
816
|
+
#[cfg(feature = "transpile")]
|
|
817
|
+
fn expand_select_order_by_all(
|
|
818
|
+
mut sel: Box<crate::expressions::Select>,
|
|
819
|
+
source: DialectType,
|
|
820
|
+
target: DialectType,
|
|
821
|
+
) -> Result<Box<crate::expressions::Select>> {
|
|
822
|
+
if !is_order_by_all(&sel.order_by) {
|
|
823
|
+
return Ok(sel);
|
|
824
|
+
}
|
|
825
|
+
let emulate_distinct = sel
|
|
826
|
+
.distinct_on
|
|
827
|
+
.as_ref()
|
|
828
|
+
.is_some_and(|cols| !cols.is_empty())
|
|
829
|
+
&& !Dialect::target_supports_distinct_on(target);
|
|
830
|
+
let snowflake_aggregate = target == DialectType::Snowflake
|
|
831
|
+
&& sel
|
|
832
|
+
.expressions
|
|
833
|
+
.iter()
|
|
834
|
+
.any(|e| contains_in_projection(e, crate::traversal::is_aggregate));
|
|
835
|
+
if target.supports_order_by_all() && !emulate_distinct && !snowflake_aggregate {
|
|
836
|
+
return Ok(sel);
|
|
837
|
+
}
|
|
838
|
+
let width =
|
|
839
|
+
if sel.expressions.is_empty() || sel.expressions.iter().any(has_unknown_column_count) {
|
|
840
|
+
None
|
|
841
|
+
} else {
|
|
842
|
+
Some(sel.expressions.len())
|
|
843
|
+
};
|
|
844
|
+
expand_order_by_all(&mut sel.order_by, width, source, target)?;
|
|
845
|
+
Ok(sel)
|
|
846
|
+
}
|
|
847
|
+
|
|
651
848
|
/// Applies a dialect transform bottom-up through selected syntax children.
|
|
652
849
|
///
|
|
653
850
|
/// The public entrypoint uses an explicit task stack for the recursion-heavy shapes
|
|
@@ -708,6 +905,7 @@ where
|
|
|
708
905
|
Expression::Union(set_op) => set_op.with.is_none() && set_op.order_by.is_none(),
|
|
709
906
|
Expression::Intersect(set_op) => set_op.with.is_none() && set_op.order_by.is_none(),
|
|
710
907
|
Expression::Except(set_op) => set_op.with.is_none() && set_op.order_by.is_none(),
|
|
908
|
+
Expression::Subquery(subquery) => subquery.order_by.is_none(),
|
|
711
909
|
Expression::Vertica(_)
|
|
712
910
|
| Expression::Literal(_)
|
|
713
911
|
| Expression::Boolean(_)
|
|
@@ -725,7 +923,6 @@ where
|
|
|
725
923
|
| Expression::IsNull(_)
|
|
726
924
|
| Expression::IsTrue(_)
|
|
727
925
|
| Expression::IsFalse(_)
|
|
728
|
-
| Expression::Subquery(_)
|
|
729
926
|
| Expression::Exists(_)
|
|
730
927
|
| Expression::Any(_)
|
|
731
928
|
| Expression::All(_)
|
|
@@ -736,6 +933,7 @@ where
|
|
|
736
933
|
| Expression::Sub(_)
|
|
737
934
|
| Expression::Mul(_)
|
|
738
935
|
| Expression::Div(_)
|
|
936
|
+
| Expression::IntDiv(_)
|
|
739
937
|
| Expression::Eq(_)
|
|
740
938
|
| Expression::NullSafeEq(_)
|
|
741
939
|
| Expression::NullSafeNeq(_)
|
|
@@ -1596,6 +1794,9 @@ where
|
|
|
1596
1794
|
// ===== Subquery expressions =====
|
|
1597
1795
|
Expression::Subquery(mut s) => {
|
|
1598
1796
|
s.this = transform_recursive(s.this, transform_fn)?;
|
|
1797
|
+
if let Some(order_by) = s.order_by.take() {
|
|
1798
|
+
s.order_by = Some(transform_order_by_recursive(order_by, transform_fn)?);
|
|
1799
|
+
}
|
|
1599
1800
|
Expression::Subquery(s)
|
|
1600
1801
|
}
|
|
1601
1802
|
Expression::Exists(mut e) => {
|
|
@@ -3515,16 +3716,57 @@ impl Dialect {
|
|
|
3515
3716
|
let expr =
|
|
3516
3717
|
normalization::vertica::prepare_conversion(expr, self.dialect_type, target)?;
|
|
3517
3718
|
normalization::vertica::validate_conversion(&expr, self.dialect_type, target)?;
|
|
3719
|
+
let expr = normalization::duckdb::prepare_integer_division(
|
|
3720
|
+
expr,
|
|
3721
|
+
self.dialect_type,
|
|
3722
|
+
target,
|
|
3723
|
+
)?;
|
|
3518
3724
|
// DuckDB source: normalize VARCHAR/CHAR to TEXT (DuckDB doesn't support
|
|
3519
3725
|
// VARCHAR length constraints). This emulates Python sqlglot's DuckDB parser
|
|
3520
3726
|
// where VARCHAR_LENGTH = None and VARCHAR maps to TEXT.
|
|
3521
|
-
|
|
3727
|
+
//
|
|
3728
|
+
// Any source with native `ORDER BY ALL`: expand it to positional
|
|
3729
|
+
// `ORDER BY 1..n` for targets without it, on both plain SELECTs and
|
|
3730
|
+
// compound queries (whose ORDER BY lives on the set-op node).
|
|
3731
|
+
let source = self.dialect_type;
|
|
3732
|
+
let is_duckdb = matches!(source, DialectType::DuckDB);
|
|
3733
|
+
let expand_all = source.supports_order_by_all() && !target.supports_order_by_all();
|
|
3734
|
+
let expr = if source.supports_order_by_all() {
|
|
3522
3735
|
use crate::expressions::DataType as DT;
|
|
3523
3736
|
transform_recursive(expr, &|e| match e {
|
|
3524
|
-
Expression::DataType(DT::VarChar { .. }) => {
|
|
3737
|
+
Expression::DataType(DT::VarChar { .. }) if is_duckdb => {
|
|
3738
|
+
Ok(Expression::DataType(DT::Text))
|
|
3739
|
+
}
|
|
3740
|
+
Expression::DataType(DT::Char { .. }) if is_duckdb => {
|
|
3525
3741
|
Ok(Expression::DataType(DT::Text))
|
|
3526
3742
|
}
|
|
3527
|
-
Expression::
|
|
3743
|
+
Expression::Select(sel) => {
|
|
3744
|
+
expand_select_order_by_all(sel, source, target).map(Expression::Select)
|
|
3745
|
+
}
|
|
3746
|
+
Expression::Subquery(mut subquery) if expand_all => {
|
|
3747
|
+
let width = query_output_width(&subquery.this);
|
|
3748
|
+
expand_order_by_all(&mut subquery.order_by, width, source, target)?;
|
|
3749
|
+
Ok(Expression::Subquery(subquery))
|
|
3750
|
+
}
|
|
3751
|
+
Expression::Union(mut u) if expand_all => {
|
|
3752
|
+
let width = if u.by_name {
|
|
3753
|
+
None
|
|
3754
|
+
} else {
|
|
3755
|
+
query_output_width(&u.left)
|
|
3756
|
+
};
|
|
3757
|
+
expand_order_by_all(&mut u.order_by, width, source, target)?;
|
|
3758
|
+
Ok(Expression::Union(u))
|
|
3759
|
+
}
|
|
3760
|
+
Expression::Intersect(mut i) if expand_all => {
|
|
3761
|
+
let width = query_output_width(&i.left);
|
|
3762
|
+
expand_order_by_all(&mut i.order_by, width, source, target)?;
|
|
3763
|
+
Ok(Expression::Intersect(i))
|
|
3764
|
+
}
|
|
3765
|
+
Expression::Except(mut ex) if expand_all => {
|
|
3766
|
+
let width = query_output_width(&ex.left);
|
|
3767
|
+
expand_order_by_all(&mut ex.order_by, width, source, target)?;
|
|
3768
|
+
Ok(Expression::Except(ex))
|
|
3769
|
+
}
|
|
3528
3770
|
_ => Ok(e),
|
|
3529
3771
|
})?
|
|
3530
3772
|
} else {
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
//! Preserve DuckDB's type-dependent `//` semantics before target rewrites.
|
|
2
|
+
|
|
3
|
+
use super::scalar::{expression_numeric_kind, NumericKind};
|
|
4
|
+
use super::*;
|
|
5
|
+
|
|
6
|
+
fn combine(left: NumericKind, right: NumericKind) -> NumericKind {
|
|
7
|
+
use NumericKind::*;
|
|
8
|
+
match (left, right) {
|
|
9
|
+
(Unknown, _) | (_, Unknown) => Unknown,
|
|
10
|
+
(Float, _) | (_, Float) => Float,
|
|
11
|
+
(Decimal, _) | (_, Decimal) => Decimal,
|
|
12
|
+
(Integer, Integer) => Integer,
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
fn numeric_kind(expr: &Expression) -> NumericKind {
|
|
17
|
+
match expr {
|
|
18
|
+
Expression::Paren(p) => numeric_kind(&p.this),
|
|
19
|
+
Expression::Neg(n) => numeric_kind(&n.this),
|
|
20
|
+
Expression::Alias(a) => numeric_kind(&a.this),
|
|
21
|
+
Expression::Add(b) | Expression::Sub(b) | Expression::Mul(b) | Expression::Mod(b) => {
|
|
22
|
+
combine(numeric_kind(&b.left), numeric_kind(&b.right))
|
|
23
|
+
}
|
|
24
|
+
// The complete bottom-up source pass has already lowered fractional
|
|
25
|
+
// children to Div. Remaining IntDiv children have integer operands.
|
|
26
|
+
Expression::IntDiv(_) => NumericKind::Integer,
|
|
27
|
+
Expression::Div(_) => NumericKind::Float,
|
|
28
|
+
Expression::Function(f) if f.name.eq_ignore_ascii_case("NULLIF") && f.args.len() == 2 => {
|
|
29
|
+
numeric_kind(&f.args[0])
|
|
30
|
+
}
|
|
31
|
+
Expression::NullIf(f) => numeric_kind(&f.this),
|
|
32
|
+
_ => expression_numeric_kind(expr),
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
pub(in crate::dialects) fn prepare_integer_division(
|
|
37
|
+
expr: Expression,
|
|
38
|
+
source: DialectType,
|
|
39
|
+
target: DialectType,
|
|
40
|
+
) -> Result<Expression> {
|
|
41
|
+
if source != DialectType::DuckDB || target == DialectType::DuckDB {
|
|
42
|
+
return Ok(expr);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// Visit every physical child, including typed function arguments and both
|
|
46
|
+
// operands of nested IntDiv nodes, before lowering the enclosing operator.
|
|
47
|
+
crate::traversal::transform_all(expr, &|expr| {
|
|
48
|
+
let Expression::IntDiv(mut division) = expr else {
|
|
49
|
+
return Ok(expr);
|
|
50
|
+
};
|
|
51
|
+
let left_kind = numeric_kind(&division.this);
|
|
52
|
+
let right_kind = numeric_kind(&division.expression);
|
|
53
|
+
let kind = combine(left_kind, right_kind);
|
|
54
|
+
if kind == NumericKind::Unknown {
|
|
55
|
+
return Err(crate::error::Error::unsupported(
|
|
56
|
+
"DuckDB // with unresolved operand types; use explicit numeric casts",
|
|
57
|
+
target.to_string(),
|
|
58
|
+
));
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// NULLIF evaluates the divisor once and preserves NULL on zero for
|
|
62
|
+
// literals, casts, computed expressions, and values only known at runtime.
|
|
63
|
+
division.expression = Expression::Function(Box::new(Function::new(
|
|
64
|
+
"NULLIF".to_string(),
|
|
65
|
+
vec![division.expression, Expression::number(0)],
|
|
66
|
+
)));
|
|
67
|
+
|
|
68
|
+
if kind != NumericKind::Integer {
|
|
69
|
+
// DuckDB decimal division produces DOUBLE, whereas some targets
|
|
70
|
+
// keep decimal arithmetic (and SQLite may treat DECIMAL as INTEGER).
|
|
71
|
+
// An explicitly floating operand already establishes float division.
|
|
72
|
+
if kind == NumericKind::Decimal {
|
|
73
|
+
division.this = super::operators::cast_expr(
|
|
74
|
+
division.this,
|
|
75
|
+
DataType::Double {
|
|
76
|
+
precision: None,
|
|
77
|
+
scale: None,
|
|
78
|
+
},
|
|
79
|
+
);
|
|
80
|
+
}
|
|
81
|
+
return Ok(Expression::Div(Box::new(BinaryOp::new(
|
|
82
|
+
division.this,
|
|
83
|
+
division.expression,
|
|
84
|
+
))));
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// Only use IntDiv where generation has a native or exact lowering.
|
|
88
|
+
// A generic DIV(...) call is invalid in several other targets.
|
|
89
|
+
if !matches!(
|
|
90
|
+
target,
|
|
91
|
+
DialectType::PostgreSQL
|
|
92
|
+
| DialectType::BigQuery
|
|
93
|
+
| DialectType::ClickHouse
|
|
94
|
+
| DialectType::SQLite
|
|
95
|
+
| DialectType::Vertica
|
|
96
|
+
| DialectType::Hive
|
|
97
|
+
| DialectType::Spark
|
|
98
|
+
| DialectType::Databricks
|
|
99
|
+
) {
|
|
100
|
+
return Err(crate::error::Error::unsupported(
|
|
101
|
+
"DuckDB integer // conversion",
|
|
102
|
+
target.to_string(),
|
|
103
|
+
));
|
|
104
|
+
}
|
|
105
|
+
Ok(Expression::IntDiv(division))
|
|
106
|
+
})
|
|
107
|
+
}
|
|
@@ -3448,17 +3448,33 @@ impl Generator {
|
|
|
3448
3448
|
Expression::Div(op) => self.generate_precedence_binary_op(op, "/", InfixOperator::Div),
|
|
3449
3449
|
Expression::IntDiv(f) => {
|
|
3450
3450
|
use crate::dialects::DialectType;
|
|
3451
|
-
|
|
3451
|
+
let is_native_slash_op = matches!(
|
|
3452
|
+
self.config.dialect,
|
|
3453
|
+
Some(DialectType::DuckDB) | Some(DialectType::Vertica)
|
|
3454
|
+
);
|
|
3455
|
+
if matches!(self.config.dialect, Some(DialectType::SQLite)) {
|
|
3456
|
+
// Keep native integer arithmetic exact above 2^53. The
|
|
3457
|
+
// outer cast truncates floating operands for other sources
|
|
3458
|
+
// whose IntDiv always truncates (e.g. MySQL and Vertica).
|
|
3459
|
+
self.write_keyword("CAST");
|
|
3460
|
+
self.write("(");
|
|
3461
|
+
self.generate_infix_operand(InfixOperator::Div, &f.this, OperandSide::Left)?;
|
|
3462
|
+
self.write(" / ");
|
|
3463
|
+
self.generate_infix_operand(
|
|
3464
|
+
InfixOperator::Div,
|
|
3465
|
+
&f.expression,
|
|
3466
|
+
OperandSide::Right,
|
|
3467
|
+
)?;
|
|
3468
|
+
self.write(" AS INTEGER)");
|
|
3469
|
+
Ok(())
|
|
3470
|
+
} else if matches!(self.config.dialect, Some(DialectType::ClickHouse)) {
|
|
3452
3471
|
self.write("intDiv(");
|
|
3453
3472
|
self.generate_expression(&f.this)?;
|
|
3454
3473
|
self.write(", ");
|
|
3455
3474
|
self.generate_expression(&f.expression)?;
|
|
3456
3475
|
self.write(")");
|
|
3457
3476
|
Ok(())
|
|
3458
|
-
} else if
|
|
3459
|
-
self.config.dialect,
|
|
3460
|
-
Some(DialectType::DuckDB) | Some(DialectType::Vertica)
|
|
3461
|
-
) {
|
|
3477
|
+
} else if is_native_slash_op {
|
|
3462
3478
|
// DuckDB and Vertica use // operator for integer division
|
|
3463
3479
|
self.generate_expression(&f.this)?;
|
|
3464
3480
|
self.write(" // ");
|
|
@@ -27118,7 +27134,22 @@ impl Generator {
|
|
|
27118
27134
|
}
|
|
27119
27135
|
}
|
|
27120
27136
|
|
|
27121
|
-
|
|
27137
|
+
// Only a parser-marked keyword bypasses ordinary identifier quoting.
|
|
27138
|
+
if crate::dialects::is_order_by_all_marker(&ordered.this) {
|
|
27139
|
+
if !self
|
|
27140
|
+
.config
|
|
27141
|
+
.dialect
|
|
27142
|
+
.is_some_and(|d| d.supports_order_by_all())
|
|
27143
|
+
{
|
|
27144
|
+
return Err(crate::error::Error::unsupported(
|
|
27145
|
+
"ORDER BY ALL must be expanded before generation",
|
|
27146
|
+
format!("{:?}", self.config.dialect),
|
|
27147
|
+
));
|
|
27148
|
+
}
|
|
27149
|
+
self.write_keyword("ALL");
|
|
27150
|
+
} else {
|
|
27151
|
+
self.generate_expression(&ordered.this)?;
|
|
27152
|
+
}
|
|
27122
27153
|
if ordered.desc {
|
|
27123
27154
|
self.write_space();
|
|
27124
27155
|
self.write_keyword("DESC");
|
|
@@ -8962,6 +8962,7 @@ impl Parser {
|
|
|
8962
8962
|
}
|
|
8963
8963
|
}
|
|
8964
8964
|
|
|
8965
|
+
self.mark_order_by_all(&mut expressions);
|
|
8965
8966
|
Ok(OrderBy {
|
|
8966
8967
|
expressions,
|
|
8967
8968
|
siblings,
|
|
@@ -8969,6 +8970,26 @@ impl Parser {
|
|
|
8969
8970
|
})
|
|
8970
8971
|
}
|
|
8971
8972
|
|
|
8973
|
+
/// Keep the query-level ALL keyword separate from identifiers, including
|
|
8974
|
+
/// columns subsequently created by builders or rename_columns. Var is the
|
|
8975
|
+
/// AST's unquoted keyword representation (also used for LIMIT ALL).
|
|
8976
|
+
fn mark_order_by_all(&self, expressions: &mut [Ordered]) {
|
|
8977
|
+
if !self
|
|
8978
|
+
.config
|
|
8979
|
+
.dialect
|
|
8980
|
+
.is_some_and(|d| d.supports_order_by_all())
|
|
8981
|
+
{
|
|
8982
|
+
return;
|
|
8983
|
+
}
|
|
8984
|
+
if let [ordered] = expressions {
|
|
8985
|
+
if matches!(&ordered.this, Expression::Column(c)
|
|
8986
|
+
if c.table.is_none() && !c.name.quoted && c.name.name.eq_ignore_ascii_case("all"))
|
|
8987
|
+
{
|
|
8988
|
+
ordered.this = Expression::Var(Box::new(Var { this: "ALL".into() }));
|
|
8989
|
+
}
|
|
8990
|
+
}
|
|
8991
|
+
}
|
|
8992
|
+
|
|
8972
8993
|
/// Parse a LIMIT count without mistaking a trailing percent sign for modulo.
|
|
8973
8994
|
fn parse_limit_value(&mut self) -> Result<(Expression, bool)> {
|
|
8974
8995
|
let saved_pos = self.current;
|
|
@@ -58458,6 +58479,7 @@ impl Parser {
|
|
|
58458
58479
|
}
|
|
58459
58480
|
}
|
|
58460
58481
|
|
|
58482
|
+
self.mark_order_by_all(&mut expressions);
|
|
58461
58483
|
Ok(Some(Expression::OrderBy(Box::new(OrderBy {
|
|
58462
58484
|
expressions,
|
|
58463
58485
|
siblings: false,
|