polyglot-sql 0.12.0__tar.gz → 0.12.1__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.12.0 → polyglot_sql-0.12.1}/Cargo.lock +6 -6
- {polyglot_sql-0.12.0 → polyglot_sql-0.12.1}/Cargo.toml +1 -1
- {polyglot_sql-0.12.0 → polyglot_sql-0.12.1}/PKG-INFO +1 -1
- {polyglot_sql-0.12.0 → polyglot_sql-0.12.1}/crates/polyglot-sql/Cargo.toml +2 -2
- {polyglot_sql-0.12.0 → polyglot_sql-0.12.1}/crates/polyglot-sql/README.md +4 -4
- {polyglot_sql-0.12.0 → polyglot_sql-0.12.1}/crates/polyglot-sql/src/dialects/duckdb.rs +173 -0
- {polyglot_sql-0.12.0 → polyglot_sql-0.12.1}/crates/polyglot-sql/src/dialects/normalization/aggregates.rs +25 -5
- {polyglot_sql-0.12.0 → polyglot_sql-0.12.1}/crates/polyglot-sql/src/dialects/normalization/mod.rs +24 -0
- {polyglot_sql-0.12.0 → polyglot_sql-0.12.1}/crates/polyglot-sql/src/dialects/normalization/operators.rs +76 -0
- {polyglot_sql-0.12.0 → polyglot_sql-0.12.1}/crates/polyglot-sql/src/generator.rs +14 -1
- {polyglot_sql-0.12.0 → polyglot_sql-0.12.1}/crates/polyglot-sql/src/optimizer/annotate_types.rs +402 -30
- {polyglot_sql-0.12.0 → polyglot_sql-0.12.1}/crates/polyglot-sql/src/optimizer/mod.rs +2 -0
- polyglot_sql-0.12.1/crates/polyglot-sql/src/optimizer/set_operation_types.rs +1182 -0
- {polyglot_sql-0.12.0 → polyglot_sql-0.12.1}/crates/polyglot-sql/src/query_analysis.rs +46 -0
- {polyglot_sql-0.12.0 → polyglot_sql-0.12.1}/crates/polyglot-sql/tests/common/known_failures.rs +12 -0
- {polyglot_sql-0.12.0 → polyglot_sql-0.12.1}/crates/polyglot-sql/tests/query_analysis.rs +161 -1
- {polyglot_sql-0.12.0 → polyglot_sql-0.12.1}/crates/polyglot-sql-function-catalogs/README.md +1 -1
- {polyglot_sql-0.12.0 → polyglot_sql-0.12.1}/crates/polyglot-sql-python/tests/test_query_analysis.py +21 -0
- {polyglot_sql-0.12.0 → polyglot_sql-0.12.1}/README.md +0 -0
- {polyglot_sql-0.12.0 → polyglot_sql-0.12.1}/crates/polyglot-sql/benches/allocation_hotspots.rs +0 -0
- {polyglot_sql-0.12.0 → polyglot_sql-0.12.1}/crates/polyglot-sql/benches/ast_traversal.rs +0 -0
- {polyglot_sql-0.12.0 → polyglot_sql-0.12.1}/crates/polyglot-sql/benches/in_list.rs +0 -0
- {polyglot_sql-0.12.0 → polyglot_sql-0.12.1}/crates/polyglot-sql/benches/lineage.rs +0 -0
- {polyglot_sql-0.12.0 → polyglot_sql-0.12.1}/crates/polyglot-sql/benches/parsing.rs +0 -0
- {polyglot_sql-0.12.0 → polyglot_sql-0.12.1}/crates/polyglot-sql/benches/performance_hotspots.rs +0 -0
- {polyglot_sql-0.12.0 → polyglot_sql-0.12.1}/crates/polyglot-sql/benches/rust_parsing.rs +0 -0
- {polyglot_sql-0.12.0 → polyglot_sql-0.12.1}/crates/polyglot-sql/benches/transpile.rs +0 -0
- {polyglot_sql-0.12.0 → polyglot_sql-0.12.1}/crates/polyglot-sql/examples/basic_usage.rs +0 -0
- {polyglot_sql-0.12.0 → polyglot_sql-0.12.1}/crates/polyglot-sql/examples/bench_json.rs +0 -0
- {polyglot_sql-0.12.0 → polyglot_sql-0.12.1}/crates/polyglot-sql/src/ast_children.rs +0 -0
- {polyglot_sql-0.12.0 → polyglot_sql-0.12.1}/crates/polyglot-sql/src/ast_json.rs +0 -0
- {polyglot_sql-0.12.0 → polyglot_sql-0.12.1}/crates/polyglot-sql/src/ast_mutation.rs +0 -0
- {polyglot_sql-0.12.0 → polyglot_sql-0.12.1}/crates/polyglot-sql/src/ast_transforms.rs +0 -0
- {polyglot_sql-0.12.0 → polyglot_sql-0.12.1}/crates/polyglot-sql/src/binding.rs +0 -0
- {polyglot_sql-0.12.0 → polyglot_sql-0.12.1}/crates/polyglot-sql/src/builder/mod.rs +0 -0
- {polyglot_sql-0.12.0 → polyglot_sql-0.12.1}/crates/polyglot-sql/src/builder/plan.rs +0 -0
- {polyglot_sql-0.12.0 → polyglot_sql-0.12.1}/crates/polyglot-sql/src/dialects/athena.rs +0 -0
- {polyglot_sql-0.12.0 → polyglot_sql-0.12.1}/crates/polyglot-sql/src/dialects/bigquery.rs +0 -0
- {polyglot_sql-0.12.0 → polyglot_sql-0.12.1}/crates/polyglot-sql/src/dialects/clickhouse.rs +0 -0
- {polyglot_sql-0.12.0 → polyglot_sql-0.12.1}/crates/polyglot-sql/src/dialects/cockroachdb.rs +0 -0
- {polyglot_sql-0.12.0 → polyglot_sql-0.12.1}/crates/polyglot-sql/src/dialects/databricks.rs +0 -0
- {polyglot_sql-0.12.0 → polyglot_sql-0.12.1}/crates/polyglot-sql/src/dialects/datafusion.rs +0 -0
- {polyglot_sql-0.12.0 → polyglot_sql-0.12.1}/crates/polyglot-sql/src/dialects/doris.rs +0 -0
- {polyglot_sql-0.12.0 → polyglot_sql-0.12.1}/crates/polyglot-sql/src/dialects/dremio.rs +0 -0
- {polyglot_sql-0.12.0 → polyglot_sql-0.12.1}/crates/polyglot-sql/src/dialects/drill.rs +0 -0
- {polyglot_sql-0.12.0 → polyglot_sql-0.12.1}/crates/polyglot-sql/src/dialects/druid.rs +0 -0
- {polyglot_sql-0.12.0 → polyglot_sql-0.12.1}/crates/polyglot-sql/src/dialects/dune.rs +0 -0
- {polyglot_sql-0.12.0 → polyglot_sql-0.12.1}/crates/polyglot-sql/src/dialects/exasol.rs +0 -0
- {polyglot_sql-0.12.0 → polyglot_sql-0.12.1}/crates/polyglot-sql/src/dialects/fabric.rs +0 -0
- {polyglot_sql-0.12.0 → polyglot_sql-0.12.1}/crates/polyglot-sql/src/dialects/generic.rs +0 -0
- {polyglot_sql-0.12.0 → polyglot_sql-0.12.1}/crates/polyglot-sql/src/dialects/hive.rs +0 -0
- {polyglot_sql-0.12.0 → polyglot_sql-0.12.1}/crates/polyglot-sql/src/dialects/materialize.rs +0 -0
- {polyglot_sql-0.12.0 → polyglot_sql-0.12.1}/crates/polyglot-sql/src/dialects/mod.rs +0 -0
- {polyglot_sql-0.12.0 → polyglot_sql-0.12.1}/crates/polyglot-sql/src/dialects/mysql.rs +0 -0
- {polyglot_sql-0.12.0 → polyglot_sql-0.12.1}/crates/polyglot-sql/src/dialects/normalization/collections.rs +0 -0
- {polyglot_sql-0.12.0 → polyglot_sql-0.12.1}/crates/polyglot-sql/src/dialects/normalization/json.rs +0 -0
- {polyglot_sql-0.12.0 → polyglot_sql-0.12.1}/crates/polyglot-sql/src/dialects/normalization/postgres_interval.rs +0 -0
- {polyglot_sql-0.12.0 → polyglot_sql-0.12.1}/crates/polyglot-sql/src/dialects/normalization/scalar.rs +0 -0
- {polyglot_sql-0.12.0 → polyglot_sql-0.12.1}/crates/polyglot-sql/src/dialects/normalization/statements.rs +0 -0
- {polyglot_sql-0.12.0 → polyglot_sql-0.12.1}/crates/polyglot-sql/src/dialects/normalization/temporal.rs +0 -0
- {polyglot_sql-0.12.0 → polyglot_sql-0.12.1}/crates/polyglot-sql/src/dialects/normalization/types.rs +0 -0
- {polyglot_sql-0.12.0 → polyglot_sql-0.12.1}/crates/polyglot-sql/src/dialects/oracle.rs +0 -0
- {polyglot_sql-0.12.0 → polyglot_sql-0.12.1}/crates/polyglot-sql/src/dialects/postgres.rs +0 -0
- {polyglot_sql-0.12.0 → polyglot_sql-0.12.1}/crates/polyglot-sql/src/dialects/presto.rs +0 -0
- {polyglot_sql-0.12.0 → polyglot_sql-0.12.1}/crates/polyglot-sql/src/dialects/redshift.rs +0 -0
- {polyglot_sql-0.12.0 → polyglot_sql-0.12.1}/crates/polyglot-sql/src/dialects/risingwave.rs +0 -0
- {polyglot_sql-0.12.0 → polyglot_sql-0.12.1}/crates/polyglot-sql/src/dialects/singlestore.rs +0 -0
- {polyglot_sql-0.12.0 → polyglot_sql-0.12.1}/crates/polyglot-sql/src/dialects/snowflake.rs +0 -0
- {polyglot_sql-0.12.0 → polyglot_sql-0.12.1}/crates/polyglot-sql/src/dialects/solr.rs +0 -0
- {polyglot_sql-0.12.0 → polyglot_sql-0.12.1}/crates/polyglot-sql/src/dialects/spark.rs +0 -0
- {polyglot_sql-0.12.0 → polyglot_sql-0.12.1}/crates/polyglot-sql/src/dialects/sqlite.rs +0 -0
- {polyglot_sql-0.12.0 → polyglot_sql-0.12.1}/crates/polyglot-sql/src/dialects/starrocks.rs +0 -0
- {polyglot_sql-0.12.0 → polyglot_sql-0.12.1}/crates/polyglot-sql/src/dialects/tableau.rs +0 -0
- {polyglot_sql-0.12.0 → polyglot_sql-0.12.1}/crates/polyglot-sql/src/dialects/teradata.rs +0 -0
- {polyglot_sql-0.12.0 → polyglot_sql-0.12.1}/crates/polyglot-sql/src/dialects/tidb.rs +0 -0
- {polyglot_sql-0.12.0 → polyglot_sql-0.12.1}/crates/polyglot-sql/src/dialects/trino.rs +0 -0
- {polyglot_sql-0.12.0 → polyglot_sql-0.12.1}/crates/polyglot-sql/src/dialects/tsql.rs +0 -0
- {polyglot_sql-0.12.0 → polyglot_sql-0.12.1}/crates/polyglot-sql/src/diff.rs +0 -0
- {polyglot_sql-0.12.0 → polyglot_sql-0.12.1}/crates/polyglot-sql/src/error.rs +0 -0
- {polyglot_sql-0.12.0 → polyglot_sql-0.12.1}/crates/polyglot-sql/src/expressions.rs +0 -0
- {polyglot_sql-0.12.0 → polyglot_sql-0.12.1}/crates/polyglot-sql/src/format_tokens.rs +0 -0
- {polyglot_sql-0.12.0 → polyglot_sql-0.12.1}/crates/polyglot-sql/src/function_catalog.rs +0 -0
- {polyglot_sql-0.12.0 → polyglot_sql-0.12.1}/crates/polyglot-sql/src/function_registry.rs +0 -0
- {polyglot_sql-0.12.0 → polyglot_sql-0.12.1}/crates/polyglot-sql/src/guard.rs +0 -0
- {polyglot_sql-0.12.0 → polyglot_sql-0.12.1}/crates/polyglot-sql/src/helper.rs +0 -0
- {polyglot_sql-0.12.0 → polyglot_sql-0.12.1}/crates/polyglot-sql/src/lib.rs +0 -0
- {polyglot_sql-0.12.0 → polyglot_sql-0.12.1}/crates/polyglot-sql/src/lineage.rs +0 -0
- {polyglot_sql-0.12.0 → polyglot_sql-0.12.1}/crates/polyglot-sql/src/openlineage.rs +0 -0
- {polyglot_sql-0.12.0 → polyglot_sql-0.12.1}/crates/polyglot-sql/src/optimizer/canonicalize.rs +0 -0
- {polyglot_sql-0.12.0 → polyglot_sql-0.12.1}/crates/polyglot-sql/src/optimizer/eliminate_ctes.rs +0 -0
- {polyglot_sql-0.12.0 → polyglot_sql-0.12.1}/crates/polyglot-sql/src/optimizer/eliminate_joins.rs +0 -0
- {polyglot_sql-0.12.0 → polyglot_sql-0.12.1}/crates/polyglot-sql/src/optimizer/isolate_table_selects.rs +0 -0
- {polyglot_sql-0.12.0 → polyglot_sql-0.12.1}/crates/polyglot-sql/src/optimizer/normalize.rs +0 -0
- {polyglot_sql-0.12.0 → polyglot_sql-0.12.1}/crates/polyglot-sql/src/optimizer/normalize_identifiers.rs +0 -0
- {polyglot_sql-0.12.0 → polyglot_sql-0.12.1}/crates/polyglot-sql/src/optimizer/optimize_joins.rs +0 -0
- {polyglot_sql-0.12.0 → polyglot_sql-0.12.1}/crates/polyglot-sql/src/optimizer/optimizer.rs +0 -0
- {polyglot_sql-0.12.0 → polyglot_sql-0.12.1}/crates/polyglot-sql/src/optimizer/pushdown_predicates.rs +0 -0
- {polyglot_sql-0.12.0 → polyglot_sql-0.12.1}/crates/polyglot-sql/src/optimizer/pushdown_projections.rs +0 -0
- {polyglot_sql-0.12.0 → polyglot_sql-0.12.1}/crates/polyglot-sql/src/optimizer/qualify_columns.rs +0 -0
- {polyglot_sql-0.12.0 → polyglot_sql-0.12.1}/crates/polyglot-sql/src/optimizer/qualify_tables.rs +0 -0
- {polyglot_sql-0.12.0 → polyglot_sql-0.12.1}/crates/polyglot-sql/src/optimizer/simplify.rs +0 -0
- {polyglot_sql-0.12.0 → polyglot_sql-0.12.1}/crates/polyglot-sql/src/optimizer/subquery.rs +0 -0
- {polyglot_sql-0.12.0 → polyglot_sql-0.12.1}/crates/polyglot-sql/src/parser.rs +0 -0
- {polyglot_sql-0.12.0 → polyglot_sql-0.12.1}/crates/polyglot-sql/src/planner.rs +0 -0
- {polyglot_sql-0.12.0 → polyglot_sql-0.12.1}/crates/polyglot-sql/src/query_analysis/column_uses.rs +0 -0
- {polyglot_sql-0.12.0 → polyglot_sql-0.12.1}/crates/polyglot-sql/src/resolver.rs +0 -0
- {polyglot_sql-0.12.0 → polyglot_sql-0.12.1}/crates/polyglot-sql/src/schema.rs +0 -0
- {polyglot_sql-0.12.0 → polyglot_sql-0.12.1}/crates/polyglot-sql/src/scope.rs +0 -0
- {polyglot_sql-0.12.0 → polyglot_sql-0.12.1}/crates/polyglot-sql/src/set_operation.rs +0 -0
- {polyglot_sql-0.12.0 → polyglot_sql-0.12.1}/crates/polyglot-sql/src/time.rs +0 -0
- {polyglot_sql-0.12.0 → polyglot_sql-0.12.1}/crates/polyglot-sql/src/tokens.rs +0 -0
- {polyglot_sql-0.12.0 → polyglot_sql-0.12.1}/crates/polyglot-sql/src/transforms.rs +0 -0
- {polyglot_sql-0.12.0 → polyglot_sql-0.12.1}/crates/polyglot-sql/src/traversal.rs +0 -0
- {polyglot_sql-0.12.0 → polyglot_sql-0.12.1}/crates/polyglot-sql/src/trie.rs +0 -0
- {polyglot_sql-0.12.0 → polyglot_sql-0.12.1}/crates/polyglot-sql/src/validation/semantics.rs +0 -0
- {polyglot_sql-0.12.0 → polyglot_sql-0.12.1}/crates/polyglot-sql/src/validation/tests.rs +0 -0
- {polyglot_sql-0.12.0 → polyglot_sql-0.12.1}/crates/polyglot-sql/src/validation.rs +0 -0
- {polyglot_sql-0.12.0 → polyglot_sql-0.12.1}/crates/polyglot-sql/tests/analyze_failures.rs +0 -0
- {polyglot_sql-0.12.0 → polyglot_sql-0.12.1}/crates/polyglot-sql/tests/clickhouse_regression.rs +0 -0
- {polyglot_sql-0.12.0 → polyglot_sql-0.12.1}/crates/polyglot-sql/tests/common/mod.rs +0 -0
- {polyglot_sql-0.12.0 → polyglot_sql-0.12.1}/crates/polyglot-sql/tests/common/test_data.rs +0 -0
- {polyglot_sql-0.12.0 → polyglot_sql-0.12.1}/crates/polyglot-sql/tests/common/test_runner.rs +0 -0
- {polyglot_sql-0.12.0 → polyglot_sql-0.12.1}/crates/polyglot-sql/tests/create_view_security_comment_regression.rs +0 -0
- {polyglot_sql-0.12.0 → polyglot_sql-0.12.1}/crates/polyglot-sql/tests/custom_clickhouse_coverage.rs +0 -0
- {polyglot_sql-0.12.0 → polyglot_sql-0.12.1}/crates/polyglot-sql/tests/custom_clickhouse_parser.rs +0 -0
- {polyglot_sql-0.12.0 → polyglot_sql-0.12.1}/crates/polyglot-sql/tests/custom_dialect.rs +0 -0
- {polyglot_sql-0.12.0 → polyglot_sql-0.12.1}/crates/polyglot-sql/tests/custom_dialect_tests.rs +0 -0
- {polyglot_sql-0.12.0 → polyglot_sql-0.12.1}/crates/polyglot-sql/tests/custom_fixtures/datafusion/ddl.json +0 -0
- {polyglot_sql-0.12.0 → polyglot_sql-0.12.1}/crates/polyglot-sql/tests/custom_fixtures/datafusion/dml.json +0 -0
- {polyglot_sql-0.12.0 → polyglot_sql-0.12.1}/crates/polyglot-sql/tests/custom_fixtures/datafusion/functions.json +0 -0
- {polyglot_sql-0.12.0 → polyglot_sql-0.12.1}/crates/polyglot-sql/tests/custom_fixtures/datafusion/identity.json +0 -0
- {polyglot_sql-0.12.0 → polyglot_sql-0.12.1}/crates/polyglot-sql/tests/custom_fixtures/datafusion/operators.json +0 -0
- {polyglot_sql-0.12.0 → polyglot_sql-0.12.1}/crates/polyglot-sql/tests/custom_fixtures/datafusion/select.json +0 -0
- {polyglot_sql-0.12.0 → polyglot_sql-0.12.1}/crates/polyglot-sql/tests/custom_fixtures/datafusion/transpilation.json +0 -0
- {polyglot_sql-0.12.0 → polyglot_sql-0.12.1}/crates/polyglot-sql/tests/custom_fixtures/datafusion/types.json +0 -0
- {polyglot_sql-0.12.0 → polyglot_sql-0.12.1}/crates/polyglot-sql/tests/data_type_api.rs +0 -0
- {polyglot_sql-0.12.0 → polyglot_sql-0.12.1}/crates/polyglot-sql/tests/deep_nesting_regression.rs +0 -0
- {polyglot_sql-0.12.0 → polyglot_sql-0.12.1}/crates/polyglot-sql/tests/dialect_matrix.rs +0 -0
- {polyglot_sql-0.12.0 → polyglot_sql-0.12.1}/crates/polyglot-sql/tests/error_handling.rs +0 -0
- {polyglot_sql-0.12.0 → polyglot_sql-0.12.1}/crates/polyglot-sql/tests/fabric_regression.rs +0 -0
- {polyglot_sql-0.12.0 → polyglot_sql-0.12.1}/crates/polyglot-sql/tests/fabric_tpch_regression.rs +0 -0
- {polyglot_sql-0.12.0 → polyglot_sql-0.12.1}/crates/polyglot-sql/tests/identity_roundtrip.rs +0 -0
- {polyglot_sql-0.12.0 → polyglot_sql-0.12.1}/crates/polyglot-sql/tests/oracle_data_types_regression.rs +0 -0
- {polyglot_sql-0.12.0 → polyglot_sql-0.12.1}/crates/polyglot-sql/tests/postgres_explain_options.rs +0 -0
- {polyglot_sql-0.12.0 → polyglot_sql-0.12.1}/crates/polyglot-sql/tests/postgres_regexp_clickhouse.rs +0 -0
- {polyglot_sql-0.12.0 → polyglot_sql-0.12.1}/crates/polyglot-sql/tests/postgres_sqlite_regression.rs +0 -0
- {polyglot_sql-0.12.0 → polyglot_sql-0.12.1}/crates/polyglot-sql/tests/query_analysis_regression.rs +0 -0
- {polyglot_sql-0.12.0 → polyglot_sql-0.12.1}/crates/polyglot-sql/tests/snowflake_regression_test.rs +0 -0
- {polyglot_sql-0.12.0 → polyglot_sql-0.12.1}/crates/polyglot-sql/tests/sqlglot_compat.rs +0 -0
- {polyglot_sql-0.12.0 → polyglot_sql-0.12.1}/crates/polyglot-sql/tests/sqlglot_dialect_identity.rs +0 -0
- {polyglot_sql-0.12.0 → polyglot_sql-0.12.1}/crates/polyglot-sql/tests/sqlglot_identity.rs +0 -0
- {polyglot_sql-0.12.0 → polyglot_sql-0.12.1}/crates/polyglot-sql/tests/sqlglot_identity_detailed.rs +0 -0
- {polyglot_sql-0.12.0 → polyglot_sql-0.12.1}/crates/polyglot-sql/tests/sqlglot_parser.rs +0 -0
- {polyglot_sql-0.12.0 → polyglot_sql-0.12.1}/crates/polyglot-sql/tests/sqlglot_pretty.rs +0 -0
- {polyglot_sql-0.12.0 → polyglot_sql-0.12.1}/crates/polyglot-sql/tests/sqlglot_transpilation.rs +0 -0
- {polyglot_sql-0.12.0 → polyglot_sql-0.12.1}/crates/polyglot-sql/tests/sqlglot_transpile.rs +0 -0
- {polyglot_sql-0.12.0 → polyglot_sql-0.12.1}/crates/polyglot-sql/tests/tpch_transpile_stack.rs +0 -0
- {polyglot_sql-0.12.0 → polyglot_sql-0.12.1}/crates/polyglot-sql/tests/transform_regression.rs +0 -0
- {polyglot_sql-0.12.0 → polyglot_sql-0.12.1}/crates/polyglot-sql/tests/tsql_regression.rs +0 -0
- {polyglot_sql-0.12.0 → polyglot_sql-0.12.1}/crates/polyglot-sql-ast-derive/Cargo.toml +0 -0
- {polyglot_sql-0.12.0 → polyglot_sql-0.12.1}/crates/polyglot-sql-ast-derive/src/lib.rs +0 -0
- {polyglot_sql-0.12.0 → polyglot_sql-0.12.1}/crates/polyglot-sql-function-catalogs/Cargo.toml +0 -0
- {polyglot_sql-0.12.0 → polyglot_sql-0.12.1}/crates/polyglot-sql-function-catalogs/src/clickhouse.rs +0 -0
- {polyglot_sql-0.12.0 → polyglot_sql-0.12.1}/crates/polyglot-sql-function-catalogs/src/duckdb.rs +0 -0
- {polyglot_sql-0.12.0 → polyglot_sql-0.12.1}/crates/polyglot-sql-function-catalogs/src/lib.rs +0 -0
- {polyglot_sql-0.12.0 → polyglot_sql-0.12.1}/crates/polyglot-sql-function-catalogs/tools/clickhouse/extract_functions.py +0 -0
- {polyglot_sql-0.12.0 → polyglot_sql-0.12.1}/crates/polyglot-sql-function-catalogs/tools/duckdb/extract_functions.py +0 -0
- {polyglot_sql-0.12.0 → polyglot_sql-0.12.1}/crates/polyglot-sql-python/Cargo.toml +0 -0
- {polyglot_sql-0.12.0 → polyglot_sql-0.12.1}/crates/polyglot-sql-python/README.md +0 -0
- {polyglot_sql-0.12.0 → polyglot_sql-0.12.1}/crates/polyglot-sql-python/docs/api.md +0 -0
- {polyglot_sql-0.12.0 → polyglot_sql-0.12.1}/crates/polyglot-sql-python/docs/index.md +0 -0
- {polyglot_sql-0.12.0 → polyglot_sql-0.12.1}/crates/polyglot-sql-python/mkdocs.yml +0 -0
- {polyglot_sql-0.12.0 → polyglot_sql-0.12.1}/crates/polyglot-sql-python/src/annotate_types.rs +0 -0
- {polyglot_sql-0.12.0 → polyglot_sql-0.12.1}/crates/polyglot-sql-python/src/builders.rs +0 -0
- {polyglot_sql-0.12.0 → polyglot_sql-0.12.1}/crates/polyglot-sql-python/src/dialects.rs +0 -0
- {polyglot_sql-0.12.0 → polyglot_sql-0.12.1}/crates/polyglot-sql-python/src/diff.rs +0 -0
- {polyglot_sql-0.12.0 → polyglot_sql-0.12.1}/crates/polyglot-sql-python/src/errors.rs +0 -0
- {polyglot_sql-0.12.0 → polyglot_sql-0.12.1}/crates/polyglot-sql-python/src/expr.rs +0 -0
- {polyglot_sql-0.12.0 → polyglot_sql-0.12.1}/crates/polyglot-sql-python/src/expr_types.rs +0 -0
- {polyglot_sql-0.12.0 → polyglot_sql-0.12.1}/crates/polyglot-sql-python/src/format.rs +0 -0
- {polyglot_sql-0.12.0 → polyglot_sql-0.12.1}/crates/polyglot-sql-python/src/generate.rs +0 -0
- {polyglot_sql-0.12.0 → polyglot_sql-0.12.1}/crates/polyglot-sql-python/src/helpers.rs +0 -0
- {polyglot_sql-0.12.0 → polyglot_sql-0.12.1}/crates/polyglot-sql-python/src/lib.rs +0 -0
- {polyglot_sql-0.12.0 → polyglot_sql-0.12.1}/crates/polyglot-sql-python/src/lineage.rs +0 -0
- {polyglot_sql-0.12.0 → polyglot_sql-0.12.1}/crates/polyglot-sql-python/src/openlineage.rs +0 -0
- {polyglot_sql-0.12.0 → polyglot_sql-0.12.1}/crates/polyglot-sql-python/src/optimize.rs +0 -0
- {polyglot_sql-0.12.0 → polyglot_sql-0.12.1}/crates/polyglot-sql-python/src/parse.rs +0 -0
- {polyglot_sql-0.12.0 → polyglot_sql-0.12.1}/crates/polyglot-sql-python/src/query_analysis.rs +0 -0
- {polyglot_sql-0.12.0 → polyglot_sql-0.12.1}/crates/polyglot-sql-python/src/tokenize.rs +0 -0
- {polyglot_sql-0.12.0 → polyglot_sql-0.12.1}/crates/polyglot-sql-python/src/transforms.rs +0 -0
- {polyglot_sql-0.12.0 → polyglot_sql-0.12.1}/crates/polyglot-sql-python/src/transpile.rs +0 -0
- {polyglot_sql-0.12.0 → polyglot_sql-0.12.1}/crates/polyglot-sql-python/src/types.rs +0 -0
- {polyglot_sql-0.12.0 → polyglot_sql-0.12.1}/crates/polyglot-sql-python/src/validate.rs +0 -0
- {polyglot_sql-0.12.0 → polyglot_sql-0.12.1}/crates/polyglot-sql-python/tests/conftest.py +0 -0
- {polyglot_sql-0.12.0 → polyglot_sql-0.12.1}/crates/polyglot-sql-python/tests/test_builders.py +0 -0
- {polyglot_sql-0.12.0 → polyglot_sql-0.12.1}/crates/polyglot-sql-python/tests/test_compat.py +0 -0
- {polyglot_sql-0.12.0 → polyglot_sql-0.12.1}/crates/polyglot-sql-python/tests/test_dialects.py +0 -0
- {polyglot_sql-0.12.0 → polyglot_sql-0.12.1}/crates/polyglot-sql-python/tests/test_diff.py +0 -0
- {polyglot_sql-0.12.0 → polyglot_sql-0.12.1}/crates/polyglot-sql-python/tests/test_expression.py +0 -0
- {polyglot_sql-0.12.0 → polyglot_sql-0.12.1}/crates/polyglot-sql-python/tests/test_format.py +0 -0
- {polyglot_sql-0.12.0 → polyglot_sql-0.12.1}/crates/polyglot-sql-python/tests/test_generate.py +0 -0
- {polyglot_sql-0.12.0 → polyglot_sql-0.12.1}/crates/polyglot-sql-python/tests/test_lineage.py +0 -0
- {polyglot_sql-0.12.0 → polyglot_sql-0.12.1}/crates/polyglot-sql-python/tests/test_optimize.py +0 -0
- {polyglot_sql-0.12.0 → polyglot_sql-0.12.1}/crates/polyglot-sql-python/tests/test_parse.py +0 -0
- {polyglot_sql-0.12.0 → polyglot_sql-0.12.1}/crates/polyglot-sql-python/tests/test_transforms.py +0 -0
- {polyglot_sql-0.12.0 → polyglot_sql-0.12.1}/crates/polyglot-sql-python/tests/test_transpile.py +0 -0
- {polyglot_sql-0.12.0 → polyglot_sql-0.12.1}/crates/polyglot-sql-python/tests/test_validate.py +0 -0
- {polyglot_sql-0.12.0 → polyglot_sql-0.12.1}/crates/polyglot-sql-python/uv.lock +0 -0
- {polyglot_sql-0.12.0 → polyglot_sql-0.12.1}/pyproject.toml +0 -0
- {polyglot_sql-0.12.0 → polyglot_sql-0.12.1}/python/polyglot_sql/__init__.py +0 -0
- {polyglot_sql-0.12.0 → polyglot_sql-0.12.1}/python/polyglot_sql/__init__.pyi +0 -0
- {polyglot_sql-0.12.0 → polyglot_sql-0.12.1}/python/polyglot_sql/analysis_types.py +0 -0
- {polyglot_sql-0.12.0 → polyglot_sql-0.12.1}/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.12.
|
|
608
|
+
version = "0.12.1"
|
|
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.12.
|
|
626
|
+
version = "0.12.1"
|
|
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.12.
|
|
635
|
+
version = "0.12.1"
|
|
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.12.
|
|
645
|
+
version = "0.12.1"
|
|
646
646
|
|
|
647
647
|
[[package]]
|
|
648
648
|
name = "polyglot-sql-python"
|
|
649
|
-
version = "0.12.
|
|
649
|
+
version = "0.12.1"
|
|
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.12.
|
|
660
|
+
version = "0.12.1"
|
|
661
661
|
dependencies = [
|
|
662
662
|
"console_error_panic_hook",
|
|
663
663
|
"js-sys",
|
|
@@ -100,14 +100,14 @@ function-catalog-all-dialects = [
|
|
|
100
100
|
]
|
|
101
101
|
|
|
102
102
|
[dependencies]
|
|
103
|
-
polyglot-sql-ast-derive = { path = "../polyglot-sql-ast-derive", version = "0.12.
|
|
103
|
+
polyglot-sql-ast-derive = { path = "../polyglot-sql-ast-derive", version = "0.12.1" }
|
|
104
104
|
serde = { workspace = true }
|
|
105
105
|
serde_json = { workspace = true }
|
|
106
106
|
thiserror = { workspace = true }
|
|
107
107
|
unicode-segmentation = { workspace = true }
|
|
108
108
|
stacker = { version = "0.1", optional = true }
|
|
109
109
|
ts-rs = { version = "12.0", features = ["serde-compat"], optional = true }
|
|
110
|
-
polyglot-sql-function-catalogs = { path = "../polyglot-sql-function-catalogs", version = "0.12.
|
|
110
|
+
polyglot-sql-function-catalogs = { path = "../polyglot-sql-function-catalogs", version = "0.12.1", optional = true, default-features = false }
|
|
111
111
|
|
|
112
112
|
[dev-dependencies]
|
|
113
113
|
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.12.
|
|
28
|
+
polyglot-sql = { version = "0.12.1", default-features = false }
|
|
29
29
|
```
|
|
30
30
|
|
|
31
31
|
```toml
|
|
32
32
|
polyglot-sql = {
|
|
33
|
-
version = "0.12.
|
|
33
|
+
version = "0.12.1",
|
|
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.12.
|
|
47
|
+
version = "0.12.1",
|
|
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.12.
|
|
54
|
+
version = "0.12.1",
|
|
55
55
|
default-features = false,
|
|
56
56
|
features = ["transpile", "dialect-clickhouse", "dialect-postgresql"],
|
|
57
57
|
}
|
|
@@ -7513,6 +7513,179 @@ mod tests {
|
|
|
7513
7513
|
result[0].clone()
|
|
7514
7514
|
}
|
|
7515
7515
|
|
|
7516
|
+
#[test]
|
|
7517
|
+
fn test_athena_max_by_preserves_filter() {
|
|
7518
|
+
let sql = "SELECT max_by(value,seq) FILTER (WHERE keep) AS answer FROM (VALUES ('kept',1,true),('ignored',2,false)) t(value,seq,keep)";
|
|
7519
|
+
assert_eq!(
|
|
7520
|
+
transpile_to_duckdb_from(sql, DialectType::Athena),
|
|
7521
|
+
"SELECT ARG_MAX_NULL(value, seq) FILTER(WHERE keep) AS answer FROM (VALUES ('kept', 1, TRUE), ('ignored', 2, FALSE)) AS t(value, seq, keep)"
|
|
7522
|
+
);
|
|
7523
|
+
|
|
7524
|
+
for read in [DialectType::Athena, DialectType::Presto, DialectType::Trino] {
|
|
7525
|
+
for (source, target) in [("MAX_BY", "ARG_MAX"), ("MIN_BY", "ARG_MIN")] {
|
|
7526
|
+
for args in ["value, seq", "value, seq, 2"] {
|
|
7527
|
+
let target = if args == "value, seq" {
|
|
7528
|
+
format!("{target}_NULL")
|
|
7529
|
+
} else {
|
|
7530
|
+
target.to_string()
|
|
7531
|
+
};
|
|
7532
|
+
for suffix in ["", " OVER (PARTITION BY category)"] {
|
|
7533
|
+
let sql =
|
|
7534
|
+
format!("SELECT {source}({args}) FILTER (WHERE keep){suffix} FROM t");
|
|
7535
|
+
assert_eq!(
|
|
7536
|
+
transpile_to_duckdb_from(&sql, read),
|
|
7537
|
+
format!("SELECT {target}({args}) FILTER(WHERE keep){suffix} FROM t"),
|
|
7538
|
+
"{read:?}: {sql}"
|
|
7539
|
+
);
|
|
7540
|
+
}
|
|
7541
|
+
}
|
|
7542
|
+
}
|
|
7543
|
+
}
|
|
7544
|
+
}
|
|
7545
|
+
|
|
7546
|
+
#[test]
|
|
7547
|
+
fn test_athena_max_by_preserves_null_winner() {
|
|
7548
|
+
for read in [DialectType::Athena, DialectType::Presto, DialectType::Trino] {
|
|
7549
|
+
for (source, target) in [("MAX_BY", "ARG_MAX_NULL"), ("MIN_BY", "ARG_MIN_NULL")] {
|
|
7550
|
+
let sql = format!(
|
|
7551
|
+
"SELECT {source}(value, seq) AS answer FROM (VALUES ('older', 1), (CAST(NULL AS VARCHAR), 2)) t(value, seq)"
|
|
7552
|
+
);
|
|
7553
|
+
assert_eq!(
|
|
7554
|
+
transpile_to_duckdb_from(&sql, read),
|
|
7555
|
+
format!("SELECT {target}(value, seq) AS answer FROM (VALUES ('older', 1), (CAST(NULL AS TEXT), 2)) AS t(value, seq)"),
|
|
7556
|
+
"{read:?}: {sql}"
|
|
7557
|
+
);
|
|
7558
|
+
assert_eq!(
|
|
7559
|
+
transpile_to_duckdb_from(
|
|
7560
|
+
&format!("SELECT {source}(DISTINCT value, seq) FILTER (WHERE keep) FROM t"),
|
|
7561
|
+
read,
|
|
7562
|
+
),
|
|
7563
|
+
format!("SELECT {target}(DISTINCT value, seq) FILTER(WHERE keep) FROM t")
|
|
7564
|
+
);
|
|
7565
|
+
}
|
|
7566
|
+
}
|
|
7567
|
+
|
|
7568
|
+
// DuckDB's native aliases intentionally skip NULL values.
|
|
7569
|
+
for (source, target) in [("MAX_BY", "ARG_MAX"), ("MIN_BY", "ARG_MIN")] {
|
|
7570
|
+
assert_eq!(
|
|
7571
|
+
transpile_to_duckdb_from(
|
|
7572
|
+
&format!("SELECT {source}(value, seq) FROM t"),
|
|
7573
|
+
DialectType::DuckDB,
|
|
7574
|
+
),
|
|
7575
|
+
format!("SELECT {target}(value, seq) FROM t")
|
|
7576
|
+
);
|
|
7577
|
+
}
|
|
7578
|
+
}
|
|
7579
|
+
|
|
7580
|
+
#[test]
|
|
7581
|
+
fn test_athena_regexp_extract_preserves_null_and_empty_matches() {
|
|
7582
|
+
for read in [DialectType::Athena, DialectType::Presto, DialectType::Trino] {
|
|
7583
|
+
for args in [
|
|
7584
|
+
"'no-match', '([0-9]+)', 1",
|
|
7585
|
+
"'abc', '(z*)a', 1",
|
|
7586
|
+
"'abc', '(z)?a', 1",
|
|
7587
|
+
"'abc', '(a)(b)(c)'",
|
|
7588
|
+
"'abc', '(a)(b)(c)', 2",
|
|
7589
|
+
"'12 34', '[0-9]+'",
|
|
7590
|
+
"'', '()'",
|
|
7591
|
+
"NULL, '([0-9]+)', 1",
|
|
7592
|
+
"'abc', NULL, 1",
|
|
7593
|
+
"value, pattern, group_index",
|
|
7594
|
+
] {
|
|
7595
|
+
assert_eq!(
|
|
7596
|
+
transpile_to_duckdb_from(
|
|
7597
|
+
&format!("SELECT REGEXP_EXTRACT({args}) AS answer"),
|
|
7598
|
+
read,
|
|
7599
|
+
),
|
|
7600
|
+
format!("SELECT ARRAY_EXTRACT(REGEXP_EXTRACT_ALL({args}), 1) AS answer"),
|
|
7601
|
+
"{read:?}: {args}"
|
|
7602
|
+
);
|
|
7603
|
+
}
|
|
7604
|
+
}
|
|
7605
|
+
|
|
7606
|
+
assert_eq!(
|
|
7607
|
+
transpile_to_duckdb_from(
|
|
7608
|
+
"SELECT REGEXP_EXTRACT('no-match', '([0-9]+)', 1)",
|
|
7609
|
+
DialectType::DuckDB,
|
|
7610
|
+
),
|
|
7611
|
+
"SELECT REGEXP_EXTRACT('no-match', '([0-9]+)', 1)"
|
|
7612
|
+
);
|
|
7613
|
+
}
|
|
7614
|
+
|
|
7615
|
+
#[test]
|
|
7616
|
+
fn test_athena_regexp_replace_capture_references() {
|
|
7617
|
+
for read in [DialectType::Athena, DialectType::Presto, DialectType::Trino] {
|
|
7618
|
+
for (sql, expected) in [
|
|
7619
|
+
(
|
|
7620
|
+
"SELECT regexp_replace('2026.09 2027.10', '([0-9]+)[.]([0-9]+)', '$1-$2') AS answer",
|
|
7621
|
+
r"SELECT REGEXP_REPLACE('2026.09 2027.10', '([0-9]+)[.]([0-9]+)', '\1-\2', 'g') AS answer",
|
|
7622
|
+
),
|
|
7623
|
+
(
|
|
7624
|
+
"SELECT regexp_replace(value, pattern, '$0/$1/$2') FROM t",
|
|
7625
|
+
r"SELECT REGEXP_REPLACE(value, pattern, '\0/\1/\2', 'g') FROM t",
|
|
7626
|
+
),
|
|
7627
|
+
(
|
|
7628
|
+
r"SELECT regexp_replace('aa', '(a)', '\$1')",
|
|
7629
|
+
"SELECT REGEXP_REPLACE('aa', '(a)', '$1', 'g')",
|
|
7630
|
+
),
|
|
7631
|
+
(
|
|
7632
|
+
"SELECT regexp_replace('a1b2', '[0-9]')",
|
|
7633
|
+
"SELECT REGEXP_REPLACE('a1b2', '[0-9]', '', 'g')",
|
|
7634
|
+
),
|
|
7635
|
+
(
|
|
7636
|
+
"SELECT regexp_replace('aa', 'a', 'x')",
|
|
7637
|
+
"SELECT REGEXP_REPLACE('aa', 'a', 'x', 'g')",
|
|
7638
|
+
),
|
|
7639
|
+
] {
|
|
7640
|
+
assert_eq!(transpile_to_duckdb_from(sql, read), expected, "{read:?}: {sql}");
|
|
7641
|
+
}
|
|
7642
|
+
}
|
|
7643
|
+
|
|
7644
|
+
assert_eq!(
|
|
7645
|
+
transpile_to_duckdb_from(
|
|
7646
|
+
"SELECT REGEXP_REPLACE('aa', '(a)', '$1')",
|
|
7647
|
+
DialectType::DuckDB,
|
|
7648
|
+
),
|
|
7649
|
+
"SELECT REGEXP_REPLACE('aa', '(a)', '$1')"
|
|
7650
|
+
);
|
|
7651
|
+
}
|
|
7652
|
+
|
|
7653
|
+
#[test]
|
|
7654
|
+
fn test_athena_to_iso8601_reports_unsupported_translation() {
|
|
7655
|
+
for read in [DialectType::Athena, DialectType::Presto, DialectType::Trino] {
|
|
7656
|
+
let dialect = Dialect::get(read);
|
|
7657
|
+
for argument in [
|
|
7658
|
+
"TIMESTAMP '2026-05-26 02:08:02.930'",
|
|
7659
|
+
"TIMESTAMP '2026-05-26 02:08:02.123456789'",
|
|
7660
|
+
"TIMESTAMP '2026-05-26 02:08:02.930 +02:00'",
|
|
7661
|
+
"DATE '2026-05-26'",
|
|
7662
|
+
"CAST(value AS TIMESTAMP(3))",
|
|
7663
|
+
"CAST(value AS TIMESTAMP WITH TIME ZONE)",
|
|
7664
|
+
"value",
|
|
7665
|
+
] {
|
|
7666
|
+
let sql = format!("SELECT TO_ISO8601({argument}) AS answer FROM t");
|
|
7667
|
+
for options in [
|
|
7668
|
+
crate::dialects::TranspileOptions::default(),
|
|
7669
|
+
crate::dialects::TranspileOptions::strict(),
|
|
7670
|
+
] {
|
|
7671
|
+
let error = dialect
|
|
7672
|
+
.transpile_with(&sql, DialectType::DuckDB, options)
|
|
7673
|
+
.expect_err("unsupported TO_ISO8601 must not emit invalid DuckDB SQL");
|
|
7674
|
+
assert!(matches!(error, crate::error::Error::Unsupported { .. }));
|
|
7675
|
+
assert!(error.to_string().contains("TO_ISO8601"));
|
|
7676
|
+
assert!(error.to_string().contains("precision and time zone"));
|
|
7677
|
+
}
|
|
7678
|
+
}
|
|
7679
|
+
|
|
7680
|
+
assert_eq!(
|
|
7681
|
+
dialect
|
|
7682
|
+
.transpile("SELECT TO_ISO8601(value) FROM t", read)
|
|
7683
|
+
.unwrap()[0],
|
|
7684
|
+
"SELECT TO_ISO8601(value) FROM t"
|
|
7685
|
+
);
|
|
7686
|
+
}
|
|
7687
|
+
}
|
|
7688
|
+
|
|
7516
7689
|
#[test]
|
|
7517
7690
|
fn test_ifnull_to_coalesce() {
|
|
7518
7691
|
let result = transpile_to_duckdb("SELECT IFNULL(a, b)");
|
|
@@ -681,11 +681,31 @@ pub(super) fn rewrite(
|
|
|
681
681
|
))))
|
|
682
682
|
}
|
|
683
683
|
DialectType::DuckDB => {
|
|
684
|
-
let
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
684
|
+
let preserve_null_value = args.len() == 2
|
|
685
|
+
&& matches!(
|
|
686
|
+
context.source,
|
|
687
|
+
DialectType::Athena | DialectType::Presto | DialectType::Trino
|
|
688
|
+
);
|
|
689
|
+
// Trino/Presto retain a NULL value when its key wins.
|
|
690
|
+
// DuckDB's ordinary ARG_MAX/ARG_MIN skip such rows.
|
|
691
|
+
let name = match (is_max, preserve_null_value) {
|
|
692
|
+
(true, true) => "ARG_MAX_NULL",
|
|
693
|
+
(false, true) => "ARG_MIN_NULL",
|
|
694
|
+
(true, false) => "ARG_MAX",
|
|
695
|
+
(false, false) => "ARG_MIN",
|
|
696
|
+
};
|
|
697
|
+
// Renaming must retain FILTER and other aggregate modifiers.
|
|
698
|
+
match e {
|
|
699
|
+
Expression::AggregateFunction(mut af) => {
|
|
700
|
+
af.name = name.to_string();
|
|
701
|
+
Ok(Expression::AggregateFunction(af))
|
|
702
|
+
}
|
|
703
|
+
Expression::Function(mut f) => {
|
|
704
|
+
f.name = name.to_string();
|
|
705
|
+
Ok(Expression::Function(f))
|
|
706
|
+
}
|
|
707
|
+
_ => Ok(e),
|
|
708
|
+
}
|
|
689
709
|
}
|
|
690
710
|
DialectType::Spark | DialectType::Databricks => {
|
|
691
711
|
let mut args = args;
|
{polyglot_sql-0.12.0 → polyglot_sql-0.12.1}/crates/polyglot-sql/src/dialects/normalization/mod.rs
RENAMED
|
@@ -1667,6 +1667,17 @@ pub(super) fn normalize(
|
|
|
1667
1667
|
}
|
|
1668
1668
|
Expression::Function(f) => {
|
|
1669
1669
|
let name = f.name.to_ascii_uppercase();
|
|
1670
|
+
if name == "TO_ISO8601"
|
|
1671
|
+
&& matches!(source, DialectType::Athena | DialectType::Presto | DialectType::Trino)
|
|
1672
|
+
&& matches!(target, DialectType::DuckDB)
|
|
1673
|
+
{
|
|
1674
|
+
// DuckDB has no native equivalent. A generic STRFTIME
|
|
1675
|
+
// rewrite loses source precision and per-value time zones.
|
|
1676
|
+
return Err(crate::error::Error::unsupported(
|
|
1677
|
+
"TO_ISO8601 translation preserving source precision and time zone",
|
|
1678
|
+
target.to_string(),
|
|
1679
|
+
));
|
|
1680
|
+
}
|
|
1670
1681
|
// DuckDB json(x) is a synonym for CAST(x AS JSON) — parses a string.
|
|
1671
1682
|
// Map to JSON_PARSE(x) for Trino/Presto/Athena to preserve semantics.
|
|
1672
1683
|
if matches!(source, DialectType::PostgreSQL)
|
|
@@ -1795,6 +1806,19 @@ pub(super) fn normalize(
|
|
|
1795
1806
|
// The Redshift parser adds 'UTC' as default source_tz, but when
|
|
1796
1807
|
// transpiling from other dialects, we should preserve the original form.
|
|
1797
1808
|
Action::Temporal(temporal::Action::ConvertTimezoneToExpr)
|
|
1809
|
+
} else if matches!(source, DialectType::Athena | DialectType::Presto | DialectType::Trino)
|
|
1810
|
+
&& matches!(target, DialectType::DuckDB)
|
|
1811
|
+
&& name == "REGEXP_EXTRACT"
|
|
1812
|
+
&& matches!(f.args.len(), 2 | 3)
|
|
1813
|
+
{
|
|
1814
|
+
Action::Operators(operators::Action::RegexpExtractPrestoToDuckDB)
|
|
1815
|
+
} else if matches!(source, DialectType::Athena | DialectType::Presto | DialectType::Trino)
|
|
1816
|
+
&& matches!(target, DialectType::DuckDB)
|
|
1817
|
+
&& name == "REGEXP_REPLACE"
|
|
1818
|
+
&& matches!(f.args.len(), 2 | 3)
|
|
1819
|
+
&& !matches!(f.args.get(2), Some(Expression::Lambda(_)))
|
|
1820
|
+
{
|
|
1821
|
+
Action::Operators(operators::Action::RegexpReplacePrestoToDuckDB)
|
|
1798
1822
|
} else if matches!(source, DialectType::Snowflake)
|
|
1799
1823
|
&& matches!(target, DialectType::DuckDB)
|
|
1800
1824
|
&& name == "REGEXP_REPLACE"
|
|
@@ -8,6 +8,8 @@ pub(super) enum Action {
|
|
|
8
8
|
Div0TypedDivision,
|
|
9
9
|
SourceDivisionToClickHouse,
|
|
10
10
|
RegexpReplaceSnowflakeToDuckDB,
|
|
11
|
+
RegexpExtractPrestoToDuckDB,
|
|
12
|
+
RegexpReplacePrestoToDuckDB,
|
|
11
13
|
BigQuerySafeDivide,
|
|
12
14
|
RegexpLikeToDuckDB,
|
|
13
15
|
RegexpLikeToTsqlPatindex,
|
|
@@ -47,6 +49,36 @@ pub(super) fn rewrite(
|
|
|
47
49
|
let e = expression;
|
|
48
50
|
let expression = (|| -> Result<Expression> {
|
|
49
51
|
match action {
|
|
52
|
+
Action::RegexpReplacePrestoToDuckDB => {
|
|
53
|
+
if let Expression::Function(mut f) = e {
|
|
54
|
+
if f.args.len() == 2 {
|
|
55
|
+
f.args.push(Expression::string(""));
|
|
56
|
+
} else if let Expression::Literal(lit) = &f.args[2] {
|
|
57
|
+
if let Literal::String(replacement) = lit.as_ref() {
|
|
58
|
+
f.args[2] = Expression::string(presto_regexp_replacement_to_duckdb(
|
|
59
|
+
replacement,
|
|
60
|
+
)?);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
f.args.push(Expression::string("g"));
|
|
64
|
+
Ok(Expression::Function(f))
|
|
65
|
+
} else {
|
|
66
|
+
unreachable!("action only triggered for REGEXP_REPLACE functions")
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
Action::RegexpExtractPrestoToDuckDB => {
|
|
70
|
+
if let Expression::Function(mut f) = e {
|
|
71
|
+
// A missing first match (or capture group) is NULL, while
|
|
72
|
+
// a successful empty capture must remain an empty string.
|
|
73
|
+
f.name = "REGEXP_EXTRACT_ALL".to_string();
|
|
74
|
+
Ok(Expression::Function(Box::new(Function::new(
|
|
75
|
+
"ARRAY_EXTRACT",
|
|
76
|
+
vec![Expression::Function(f), Expression::number(1)],
|
|
77
|
+
))))
|
|
78
|
+
} else {
|
|
79
|
+
unreachable!("action only triggered for REGEXP_EXTRACT functions")
|
|
80
|
+
}
|
|
81
|
+
}
|
|
50
82
|
Action::SourceDivisionToClickHouse => {
|
|
51
83
|
if let Expression::Div(div) = e {
|
|
52
84
|
normalize_source_division_to_clickhouse(*div, context)
|
|
@@ -2223,3 +2255,47 @@ pub(super) fn build_tsql_cbrt_power(this: Expression) -> Expression {
|
|
|
2223
2255
|
inferred_type: None,
|
|
2224
2256
|
}))
|
|
2225
2257
|
}
|
|
2258
|
+
|
|
2259
|
+
fn presto_regexp_replacement_to_duckdb(replacement: &str) -> Result<String> {
|
|
2260
|
+
let mut chars = replacement.chars().peekable();
|
|
2261
|
+
let mut converted = String::with_capacity(replacement.len());
|
|
2262
|
+
while let Some(ch) = chars.next() {
|
|
2263
|
+
match ch {
|
|
2264
|
+
'\\' => {
|
|
2265
|
+
if let Some(literal) = chars.next() {
|
|
2266
|
+
// Trino quotes the following character; RE2 only needs
|
|
2267
|
+
// quoting for a literal backslash in replacement text.
|
|
2268
|
+
if literal == '\\' {
|
|
2269
|
+
converted.push('\\');
|
|
2270
|
+
}
|
|
2271
|
+
converted.push(literal);
|
|
2272
|
+
} else {
|
|
2273
|
+
return Err(crate::error::Error::unsupported(
|
|
2274
|
+
"REGEXP_REPLACE replacement ends in an escape",
|
|
2275
|
+
"duckdb",
|
|
2276
|
+
));
|
|
2277
|
+
}
|
|
2278
|
+
}
|
|
2279
|
+
'$' => match chars.next() {
|
|
2280
|
+
Some(group) if group.is_ascii_digit() => {
|
|
2281
|
+
if chars.peek().is_some_and(|ch| ch.is_ascii_digit()) {
|
|
2282
|
+
return Err(crate::error::Error::unsupported(
|
|
2283
|
+
"DuckDB REGEXP_REPLACE does not support multi-digit capture references",
|
|
2284
|
+
"duckdb",
|
|
2285
|
+
));
|
|
2286
|
+
}
|
|
2287
|
+
converted.push('\\');
|
|
2288
|
+
converted.push(group);
|
|
2289
|
+
}
|
|
2290
|
+
_ => {
|
|
2291
|
+
return Err(crate::error::Error::unsupported(
|
|
2292
|
+
"DuckDB REGEXP_REPLACE requires numbered capture references",
|
|
2293
|
+
"duckdb",
|
|
2294
|
+
))
|
|
2295
|
+
}
|
|
2296
|
+
},
|
|
2297
|
+
_ => converted.push(ch),
|
|
2298
|
+
}
|
|
2299
|
+
}
|
|
2300
|
+
Ok(converted)
|
|
2301
|
+
}
|
|
@@ -2447,6 +2447,18 @@ impl Generator {
|
|
|
2447
2447
|
Ok(std::mem::take(&mut self.output))
|
|
2448
2448
|
}
|
|
2449
2449
|
|
|
2450
|
+
/// Render an analysis type without implicit ClickHouse Nullable wrapping.
|
|
2451
|
+
#[cfg(feature = "semantic")]
|
|
2452
|
+
pub(crate) fn generate_type_hint(&mut self, data_type: &DataType) -> Result<String> {
|
|
2453
|
+
// Analysis already models nullability separately. Native ClickHouse
|
|
2454
|
+
// types must acquire Nullable only from an explicit type wrapper.
|
|
2455
|
+
let saved_depth = self.clickhouse_nullable_depth;
|
|
2456
|
+
self.clickhouse_nullable_depth = -1;
|
|
2457
|
+
let result = self.generate(&Expression::DataType(data_type.clone()));
|
|
2458
|
+
self.clickhouse_nullable_depth = saved_depth;
|
|
2459
|
+
result
|
|
2460
|
+
}
|
|
2461
|
+
|
|
2450
2462
|
/// Returns the unsupported diagnostics collected during the most recent generate call.
|
|
2451
2463
|
pub fn unsupported_messages(&self) -> &[String] {
|
|
2452
2464
|
&self.unsupported_messages
|
|
@@ -26850,9 +26862,10 @@ impl Generator {
|
|
|
26850
26862
|
// ClickHouse: Map(key_type, value_type) with parenthesized syntax
|
|
26851
26863
|
// Key types must NOT be wrapped in Nullable
|
|
26852
26864
|
self.write("Map(");
|
|
26865
|
+
let saved_depth = self.clickhouse_nullable_depth;
|
|
26853
26866
|
self.clickhouse_nullable_depth = -1; // suppress Nullable for key
|
|
26854
26867
|
self.generate_data_type(key_type)?;
|
|
26855
|
-
self.clickhouse_nullable_depth =
|
|
26868
|
+
self.clickhouse_nullable_depth = saved_depth;
|
|
26856
26869
|
self.write(", ");
|
|
26857
26870
|
self.generate_data_type(value_type)?;
|
|
26858
26871
|
self.write(")");
|