polyglot-sql 0.6.0__tar.gz → 0.6.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.6.0 → polyglot_sql-0.6.1}/Cargo.lock +6 -6
- {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/Cargo.toml +1 -1
- {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/PKG-INFO +1 -1
- {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/Cargo.toml +2 -2
- {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/README.md +1 -1
- {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/src/dialects/mod.rs +185 -8
- {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/src/dialects/normalization/mod.rs +42 -2
- {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/src/dialects/normalization/statements.rs +19 -0
- {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/src/dialects/normalization/temporal.rs +169 -0
- {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/src/dialects/normalization/types.rs +81 -0
- {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/src/transforms.rs +9 -2
- {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/tests/dialect_matrix.rs +311 -0
- {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/tests/fabric_regression.rs +8 -0
- {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/tests/tsql_regression.rs +8 -0
- {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql-ast-derive/Cargo.toml +3 -1
- {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/README.md +0 -0
- {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/benches/allocation_hotspots.rs +0 -0
- {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/benches/ast_traversal.rs +0 -0
- {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/benches/in_list.rs +0 -0
- {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/benches/parsing.rs +0 -0
- {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/benches/performance_hotspots.rs +0 -0
- {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/benches/rust_parsing.rs +0 -0
- {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/benches/transpile.rs +0 -0
- {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/examples/basic_usage.rs +0 -0
- {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/examples/bench_json.rs +0 -0
- {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/src/ast_children.rs +0 -0
- {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/src/ast_json.rs +0 -0
- {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/src/ast_transforms.rs +0 -0
- {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/src/builder.rs +0 -0
- {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/src/dialects/athena.rs +0 -0
- {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/src/dialects/bigquery.rs +0 -0
- {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/src/dialects/clickhouse.rs +0 -0
- {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/src/dialects/cockroachdb.rs +0 -0
- {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/src/dialects/databricks.rs +0 -0
- {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/src/dialects/datafusion.rs +0 -0
- {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/src/dialects/doris.rs +0 -0
- {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/src/dialects/dremio.rs +0 -0
- {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/src/dialects/drill.rs +0 -0
- {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/src/dialects/druid.rs +0 -0
- {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/src/dialects/duckdb.rs +0 -0
- {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/src/dialects/dune.rs +0 -0
- {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/src/dialects/exasol.rs +0 -0
- {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/src/dialects/fabric.rs +0 -0
- {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/src/dialects/generic.rs +0 -0
- {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/src/dialects/hive.rs +0 -0
- {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/src/dialects/materialize.rs +0 -0
- {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/src/dialects/mysql.rs +0 -0
- {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/src/dialects/normalization/aggregates.rs +0 -0
- {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/src/dialects/normalization/collections.rs +0 -0
- {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/src/dialects/normalization/json.rs +0 -0
- {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/src/dialects/normalization/operators.rs +0 -0
- {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/src/dialects/normalization/scalar.rs +0 -0
- {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/src/dialects/oracle.rs +0 -0
- {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/src/dialects/postgres.rs +0 -0
- {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/src/dialects/presto.rs +0 -0
- {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/src/dialects/redshift.rs +0 -0
- {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/src/dialects/risingwave.rs +0 -0
- {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/src/dialects/singlestore.rs +0 -0
- {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/src/dialects/snowflake.rs +0 -0
- {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/src/dialects/solr.rs +0 -0
- {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/src/dialects/spark.rs +0 -0
- {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/src/dialects/sqlite.rs +0 -0
- {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/src/dialects/starrocks.rs +0 -0
- {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/src/dialects/tableau.rs +0 -0
- {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/src/dialects/teradata.rs +0 -0
- {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/src/dialects/tidb.rs +0 -0
- {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/src/dialects/trino.rs +0 -0
- {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/src/dialects/tsql.rs +0 -0
- {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/src/diff.rs +0 -0
- {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/src/error.rs +0 -0
- {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/src/expressions.rs +0 -0
- {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/src/format_tokens.rs +0 -0
- {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/src/function_catalog.rs +0 -0
- {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/src/function_registry.rs +0 -0
- {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/src/generator.rs +0 -0
- {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/src/guard.rs +0 -0
- {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/src/helper.rs +0 -0
- {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/src/lib.rs +0 -0
- {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/src/lineage.rs +0 -0
- {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/src/openlineage.rs +0 -0
- {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/src/optimizer/annotate_types.rs +0 -0
- {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/src/optimizer/canonicalize.rs +0 -0
- {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/src/optimizer/eliminate_ctes.rs +0 -0
- {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/src/optimizer/eliminate_joins.rs +0 -0
- {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/src/optimizer/isolate_table_selects.rs +0 -0
- {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/src/optimizer/mod.rs +0 -0
- {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/src/optimizer/normalize.rs +0 -0
- {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/src/optimizer/normalize_identifiers.rs +0 -0
- {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/src/optimizer/optimize_joins.rs +0 -0
- {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/src/optimizer/optimizer.rs +0 -0
- {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/src/optimizer/pushdown_predicates.rs +0 -0
- {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/src/optimizer/pushdown_projections.rs +0 -0
- {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/src/optimizer/qualify_columns.rs +0 -0
- {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/src/optimizer/qualify_tables.rs +0 -0
- {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/src/optimizer/simplify.rs +0 -0
- {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/src/optimizer/subquery.rs +0 -0
- {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/src/parser.rs +0 -0
- {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/src/planner.rs +0 -0
- {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/src/query_analysis.rs +0 -0
- {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/src/resolver.rs +0 -0
- {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/src/schema.rs +0 -0
- {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/src/scope.rs +0 -0
- {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/src/time.rs +0 -0
- {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/src/tokens.rs +0 -0
- {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/src/traversal.rs +0 -0
- {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/src/trie.rs +0 -0
- {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/src/validation/tests.rs +0 -0
- {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/src/validation.rs +0 -0
- {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/tests/analyze_failures.rs +0 -0
- {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/tests/clickhouse_regression.rs +0 -0
- {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/tests/common/known_failures.rs +0 -0
- {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/tests/common/mod.rs +0 -0
- {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/tests/common/test_data.rs +0 -0
- {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/tests/common/test_runner.rs +0 -0
- {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/tests/create_view_security_comment_regression.rs +0 -0
- {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/tests/custom_clickhouse_coverage.rs +0 -0
- {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/tests/custom_clickhouse_parser.rs +0 -0
- {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/tests/custom_dialect.rs +0 -0
- {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/tests/custom_dialect_tests.rs +0 -0
- {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/tests/custom_fixtures/datafusion/ddl.json +0 -0
- {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/tests/custom_fixtures/datafusion/dml.json +0 -0
- {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/tests/custom_fixtures/datafusion/functions.json +0 -0
- {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/tests/custom_fixtures/datafusion/identity.json +0 -0
- {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/tests/custom_fixtures/datafusion/operators.json +0 -0
- {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/tests/custom_fixtures/datafusion/select.json +0 -0
- {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/tests/custom_fixtures/datafusion/transpilation.json +0 -0
- {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/tests/custom_fixtures/datafusion/types.json +0 -0
- {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/tests/data_type_api.rs +0 -0
- {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/tests/deep_nesting_regression.rs +0 -0
- {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/tests/error_handling.rs +0 -0
- {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/tests/fabric_tpch_regression.rs +0 -0
- {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/tests/identity_roundtrip.rs +0 -0
- {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/tests/postgres_regexp_clickhouse.rs +0 -0
- {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/tests/postgres_sqlite_regression.rs +0 -0
- {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/tests/query_analysis.rs +0 -0
- {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/tests/query_analysis_regression.rs +0 -0
- {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/tests/snowflake_regression_test.rs +0 -0
- {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/tests/sqlglot_compat.rs +0 -0
- {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/tests/sqlglot_dialect_identity.rs +0 -0
- {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/tests/sqlglot_identity.rs +0 -0
- {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/tests/sqlglot_identity_detailed.rs +0 -0
- {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/tests/sqlglot_parser.rs +0 -0
- {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/tests/sqlglot_pretty.rs +0 -0
- {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/tests/sqlglot_transpilation.rs +0 -0
- {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/tests/sqlglot_transpile.rs +0 -0
- {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/tests/tpch_transpile_stack.rs +0 -0
- {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/tests/transform_regression.rs +0 -0
- {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql-ast-derive/src/lib.rs +0 -0
- {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql-function-catalogs/Cargo.toml +0 -0
- {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql-function-catalogs/README.md +0 -0
- {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql-function-catalogs/src/clickhouse.rs +0 -0
- {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql-function-catalogs/src/duckdb.rs +0 -0
- {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql-function-catalogs/src/lib.rs +0 -0
- {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql-function-catalogs/tools/clickhouse/extract_functions.py +0 -0
- {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql-function-catalogs/tools/duckdb/extract_functions.py +0 -0
- {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql-python/Cargo.toml +0 -0
- {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql-python/README.md +0 -0
- {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql-python/docs/api.md +0 -0
- {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql-python/docs/index.md +0 -0
- {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql-python/mkdocs.yml +0 -0
- {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql-python/src/annotate_types.rs +0 -0
- {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql-python/src/dialects.rs +0 -0
- {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql-python/src/diff.rs +0 -0
- {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql-python/src/errors.rs +0 -0
- {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql-python/src/expr.rs +0 -0
- {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql-python/src/expr_types.rs +0 -0
- {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql-python/src/format.rs +0 -0
- {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql-python/src/generate.rs +0 -0
- {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql-python/src/helpers.rs +0 -0
- {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql-python/src/lib.rs +0 -0
- {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql-python/src/lineage.rs +0 -0
- {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql-python/src/openlineage.rs +0 -0
- {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql-python/src/optimize.rs +0 -0
- {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql-python/src/parse.rs +0 -0
- {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql-python/src/query_analysis.rs +0 -0
- {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql-python/src/tokenize.rs +0 -0
- {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql-python/src/transforms.rs +0 -0
- {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql-python/src/transpile.rs +0 -0
- {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql-python/src/types.rs +0 -0
- {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql-python/src/validate.rs +0 -0
- {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql-python/tests/conftest.py +0 -0
- {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql-python/tests/test_compat.py +0 -0
- {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql-python/tests/test_dialects.py +0 -0
- {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql-python/tests/test_diff.py +0 -0
- {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql-python/tests/test_expression.py +0 -0
- {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql-python/tests/test_format.py +0 -0
- {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql-python/tests/test_generate.py +0 -0
- {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql-python/tests/test_lineage.py +0 -0
- {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql-python/tests/test_optimize.py +0 -0
- {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql-python/tests/test_parse.py +0 -0
- {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql-python/tests/test_query_analysis.py +0 -0
- {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql-python/tests/test_transforms.py +0 -0
- {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql-python/tests/test_transpile.py +0 -0
- {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql-python/tests/test_validate.py +0 -0
- {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql-python/uv.lock +0 -0
- {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/pyproject.toml +0 -0
- {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/python/polyglot_sql/__init__.py +0 -0
- {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/python/polyglot_sql/__init__.pyi +0 -0
- {polyglot_sql-0.6.0 → polyglot_sql-0.6.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.6.
|
|
608
|
+
version = "0.6.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.6.
|
|
626
|
+
version = "0.6.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.6.
|
|
635
|
+
version = "0.6.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.6.
|
|
645
|
+
version = "0.6.1"
|
|
646
646
|
|
|
647
647
|
[[package]]
|
|
648
648
|
name = "polyglot-sql-python"
|
|
649
|
-
version = "0.6.
|
|
649
|
+
version = "0.6.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.6.
|
|
660
|
+
version = "0.6.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" }
|
|
103
|
+
polyglot-sql-ast-derive = { path = "../polyglot-sql-ast-derive", version = "0.6.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.6.
|
|
110
|
+
polyglot-sql-function-catalogs = { path = "../polyglot-sql-function-catalogs", version = "0.6.1", optional = true, default-features = false }
|
|
111
111
|
|
|
112
112
|
[dev-dependencies]
|
|
113
113
|
pretty_assertions = "1.4"
|
|
@@ -25,7 +25,7 @@ By default, `polyglot-sql` enables the full public API. Parser-only consumers ca
|
|
|
25
25
|
disable default features and opt into only the dialect parsers they need:
|
|
26
26
|
|
|
27
27
|
```toml
|
|
28
|
-
polyglot-sql = { version = "0.6.
|
|
28
|
+
polyglot-sql = { version = "0.6.1", default-features = false }
|
|
29
29
|
```
|
|
30
30
|
|
|
31
31
|
```toml
|
|
@@ -3415,6 +3415,12 @@ impl Dialect {
|
|
|
3415
3415
|
target,
|
|
3416
3416
|
opts,
|
|
3417
3417
|
)?;
|
|
3418
|
+
Self::reject_postgres_tsql_strict_unknown_text_casts(
|
|
3419
|
+
&expr,
|
|
3420
|
+
self.dialect_type,
|
|
3421
|
+
target,
|
|
3422
|
+
opts,
|
|
3423
|
+
)?;
|
|
3418
3424
|
|
|
3419
3425
|
// When source and target differ, first normalize the source dialect's
|
|
3420
3426
|
// AST constructs to standard SQL, so that the target dialect can handle them.
|
|
@@ -3704,7 +3710,7 @@ impl Dialect {
|
|
|
3704
3710
|
DialectType::PostgreSQL | DialectType::CockroachDB
|
|
3705
3711
|
) && !matches!(target, DialectType::PostgreSQL | DialectType::CockroachDB)
|
|
3706
3712
|
{
|
|
3707
|
-
Self::normalize_postgres_type_function_casts(normalized)?
|
|
3713
|
+
Self::normalize_postgres_type_function_casts(normalized, target)?
|
|
3708
3714
|
} else {
|
|
3709
3715
|
normalized
|
|
3710
3716
|
};
|
|
@@ -3820,6 +3826,16 @@ impl Dialect {
|
|
|
3820
3826
|
normalized
|
|
3821
3827
|
};
|
|
3822
3828
|
|
|
3829
|
+
let normalized = if matches!(
|
|
3830
|
+
self.dialect_type,
|
|
3831
|
+
DialectType::PostgreSQL | DialectType::CockroachDB
|
|
3832
|
+
) && matches!(target, DialectType::TSQL | DialectType::Fabric)
|
|
3833
|
+
{
|
|
3834
|
+
Self::normalize_postgres_boolean_semantics_for_tsql(normalized)?
|
|
3835
|
+
} else {
|
|
3836
|
+
normalized
|
|
3837
|
+
};
|
|
3838
|
+
|
|
3823
3839
|
// TSQL: Convert COUNT(*) -> COUNT_BIG(*) when source is not TSQL/Fabric
|
|
3824
3840
|
// Python sqlglot does this in the TSQL generator, but we can't do it there
|
|
3825
3841
|
// because it would break TSQL -> TSQL identity
|
|
@@ -4265,6 +4281,20 @@ impl Dialect {
|
|
|
4265
4281
|
Self::push_unsupported_diagnostic(&mut diagnostics, "PostgreSQL TO_TSVECTOR");
|
|
4266
4282
|
}
|
|
4267
4283
|
if matches!(target, DialectType::TSQL | DialectType::Fabric) {
|
|
4284
|
+
if let Some(composite_semantics) =
|
|
4285
|
+
Self::postgres_tsql_unsupported_composite_semantics(node)
|
|
4286
|
+
{
|
|
4287
|
+
Self::push_unsupported_diagnostic(
|
|
4288
|
+
&mut diagnostics,
|
|
4289
|
+
&format!("PostgreSQL {composite_semantics}"),
|
|
4290
|
+
);
|
|
4291
|
+
}
|
|
4292
|
+
if Self::node_is_postgres_unknown_cast(node) {
|
|
4293
|
+
Self::push_unsupported_diagnostic(
|
|
4294
|
+
&mut diagnostics,
|
|
4295
|
+
"PostgreSQL unresolved UNKNOWN casts",
|
|
4296
|
+
);
|
|
4297
|
+
}
|
|
4268
4298
|
if let Some(collation_name) =
|
|
4269
4299
|
Self::postgres_tsql_unsupported_collation_name(node)
|
|
4270
4300
|
{
|
|
@@ -4354,6 +4384,38 @@ impl Dialect {
|
|
|
4354
4384
|
Ok(())
|
|
4355
4385
|
}
|
|
4356
4386
|
|
|
4387
|
+
fn reject_postgres_tsql_strict_unknown_text_casts(
|
|
4388
|
+
expr: &Expression,
|
|
4389
|
+
source: DialectType,
|
|
4390
|
+
target: DialectType,
|
|
4391
|
+
opts: &TranspileOptions,
|
|
4392
|
+
) -> Result<()> {
|
|
4393
|
+
if !matches!(
|
|
4394
|
+
opts.unsupported_level,
|
|
4395
|
+
UnsupportedLevel::Raise | UnsupportedLevel::Immediate
|
|
4396
|
+
) || !matches!(source, DialectType::PostgreSQL | DialectType::CockroachDB)
|
|
4397
|
+
|| !matches!(target, DialectType::TSQL | DialectType::Fabric)
|
|
4398
|
+
{
|
|
4399
|
+
return Ok(());
|
|
4400
|
+
}
|
|
4401
|
+
|
|
4402
|
+
if expr.dfs().any(|node| {
|
|
4403
|
+
matches!(
|
|
4404
|
+
node,
|
|
4405
|
+
Expression::Cast(cast)
|
|
4406
|
+
if matches!(cast.to, DataType::Text)
|
|
4407
|
+
&& Self::is_column_expr(&cast.this)
|
|
4408
|
+
)
|
|
4409
|
+
}) {
|
|
4410
|
+
return Err(crate::error::Error::unsupported(
|
|
4411
|
+
"PostgreSQL cast of a column with an unknown source type to text",
|
|
4412
|
+
target.to_string(),
|
|
4413
|
+
));
|
|
4414
|
+
}
|
|
4415
|
+
|
|
4416
|
+
Ok(())
|
|
4417
|
+
}
|
|
4418
|
+
|
|
4357
4419
|
fn push_unsupported_diagnostic(diagnostics: &mut Vec<String>, message: &str) {
|
|
4358
4420
|
if !diagnostics.iter().any(|existing| existing == message) {
|
|
4359
4421
|
diagnostics.push(message.to_string());
|
|
@@ -4880,6 +4942,33 @@ impl Dialect {
|
|
|
4880
4942
|
}
|
|
4881
4943
|
}
|
|
4882
4944
|
|
|
4945
|
+
fn postgres_tsql_unsupported_composite_semantics(expr: &Expression) -> Option<&'static str> {
|
|
4946
|
+
match expr {
|
|
4947
|
+
Expression::Tuple(_) | Expression::Struct(_) | Expression::StructFunc(_) => {
|
|
4948
|
+
Some("row/composite values")
|
|
4949
|
+
}
|
|
4950
|
+
Expression::Function(function)
|
|
4951
|
+
if !function.quoted && function.name.eq_ignore_ascii_case("ROW") =>
|
|
4952
|
+
{
|
|
4953
|
+
Some("row/composite values")
|
|
4954
|
+
}
|
|
4955
|
+
Expression::StructExtract(_) => Some("row/composite field access"),
|
|
4956
|
+
Expression::Cast(cast) | Expression::TryCast(cast) | Expression::SafeCast(cast) if matches!(&cast.this, Expression::Star(star) if star.table.is_some()) => {
|
|
4957
|
+
Some("qualified whole-row casts")
|
|
4958
|
+
}
|
|
4959
|
+
_ => None,
|
|
4960
|
+
}
|
|
4961
|
+
}
|
|
4962
|
+
|
|
4963
|
+
fn node_is_postgres_unknown_cast(expr: &Expression) -> bool {
|
|
4964
|
+
match expr {
|
|
4965
|
+
Expression::Cast(cast) | Expression::TryCast(cast) | Expression::SafeCast(cast) => {
|
|
4966
|
+
normalization::is_postgres_unknown_type(&cast.to)
|
|
4967
|
+
}
|
|
4968
|
+
_ => false,
|
|
4969
|
+
}
|
|
4970
|
+
}
|
|
4971
|
+
|
|
4883
4972
|
fn postgres_tsql_unsupported_array_semantics(expr: &Expression) -> Option<&'static str> {
|
|
4884
4973
|
match expr {
|
|
4885
4974
|
Expression::Array(_) | Expression::ArrayFunc(_) => Some("array literals"),
|
|
@@ -5655,7 +5744,10 @@ impl Dialect {
|
|
|
5655
5744
|
}
|
|
5656
5745
|
}
|
|
5657
5746
|
|
|
5658
|
-
fn normalize_postgres_type_function_casts(
|
|
5747
|
+
fn normalize_postgres_type_function_casts(
|
|
5748
|
+
expr: Expression,
|
|
5749
|
+
target: DialectType,
|
|
5750
|
+
) -> Result<Expression> {
|
|
5659
5751
|
transform_recursive(expr, &|e| match e {
|
|
5660
5752
|
Expression::Function(function) => {
|
|
5661
5753
|
let mut function = *function;
|
|
@@ -5667,7 +5759,7 @@ impl Dialect {
|
|
|
5667
5759
|
{
|
|
5668
5760
|
if let Some(to) = Self::postgres_type_function_data_type(&function.name) {
|
|
5669
5761
|
let this = function.args.remove(0);
|
|
5670
|
-
|
|
5762
|
+
let cast = Cast {
|
|
5671
5763
|
this,
|
|
5672
5764
|
to,
|
|
5673
5765
|
trailing_comments: function.trailing_comments,
|
|
@@ -5675,7 +5767,14 @@ impl Dialect {
|
|
|
5675
5767
|
format: None,
|
|
5676
5768
|
default: None,
|
|
5677
5769
|
inferred_type: function.inferred_type,
|
|
5678
|
-
}
|
|
5770
|
+
};
|
|
5771
|
+
return Ok(
|
|
5772
|
+
if matches!(target, DialectType::TSQL | DialectType::Fabric) {
|
|
5773
|
+
normalization::rewrite_postgres_float_to_integer_cast(cast)
|
|
5774
|
+
} else {
|
|
5775
|
+
Expression::Cast(Box::new(cast))
|
|
5776
|
+
},
|
|
5777
|
+
);
|
|
5679
5778
|
}
|
|
5680
5779
|
}
|
|
5681
5780
|
Ok(Expression::Function(Box::new(function)))
|
|
@@ -6069,7 +6168,82 @@ impl Dialect {
|
|
|
6069
6168
|
Ok(Expression::Select(select))
|
|
6070
6169
|
}
|
|
6071
6170
|
|
|
6171
|
+
fn normalize_postgres_boolean_semantics_for_tsql(expr: Expression) -> Result<Expression> {
|
|
6172
|
+
transform_recursive(expr, &|e| match e {
|
|
6173
|
+
Expression::Function(function)
|
|
6174
|
+
if function.args.len() == 2
|
|
6175
|
+
&& (function.name.eq_ignore_ascii_case("BOOLEQ")
|
|
6176
|
+
|| function.name.eq_ignore_ascii_case("BOOLNE")) =>
|
|
6177
|
+
{
|
|
6178
|
+
let is_equal = function.name.eq_ignore_ascii_case("BOOLEQ");
|
|
6179
|
+
let mut args = function.args.into_iter();
|
|
6180
|
+
let op = BinaryOp {
|
|
6181
|
+
left: args.next().expect("checked boolean operator arity"),
|
|
6182
|
+
right: args.next().expect("checked boolean operator arity"),
|
|
6183
|
+
left_comments: Vec::new(),
|
|
6184
|
+
operator_comments: Vec::new(),
|
|
6185
|
+
trailing_comments: function.trailing_comments,
|
|
6186
|
+
inferred_type: None,
|
|
6187
|
+
};
|
|
6188
|
+
if is_equal {
|
|
6189
|
+
Ok(Expression::Eq(Box::new(op)))
|
|
6190
|
+
} else {
|
|
6191
|
+
Ok(Expression::Neq(Box::new(op)))
|
|
6192
|
+
}
|
|
6193
|
+
}
|
|
6194
|
+
Expression::Cast(cast)
|
|
6195
|
+
if matches!(cast.to, DataType::Text)
|
|
6196
|
+
&& Self::is_known_postgres_boolean_expression(&cast.this) =>
|
|
6197
|
+
{
|
|
6198
|
+
Ok(Self::postgres_boolean_text_value(cast.this))
|
|
6199
|
+
}
|
|
6200
|
+
other => Ok(other),
|
|
6201
|
+
})
|
|
6202
|
+
}
|
|
6203
|
+
|
|
6204
|
+
fn is_known_postgres_boolean_expression(expr: &Expression) -> bool {
|
|
6205
|
+
match expr {
|
|
6206
|
+
Expression::Boolean(_) => true,
|
|
6207
|
+
Expression::Cast(cast) => matches!(cast.to, DataType::Boolean),
|
|
6208
|
+
Expression::Paren(paren) => Self::is_known_postgres_boolean_expression(&paren.this),
|
|
6209
|
+
other => Self::is_tsql_boolean_value_expression(other),
|
|
6210
|
+
}
|
|
6211
|
+
}
|
|
6212
|
+
|
|
6213
|
+
fn postgres_boolean_text_value(predicate: Expression) -> Expression {
|
|
6214
|
+
if let Expression::Boolean(boolean) = predicate {
|
|
6215
|
+
return Expression::string(if boolean.value { "true" } else { "false" });
|
|
6216
|
+
}
|
|
6217
|
+
|
|
6218
|
+
let false_predicate = Expression::Not(Box::new(crate::expressions::UnaryOp {
|
|
6219
|
+
this: predicate.clone(),
|
|
6220
|
+
inferred_type: None,
|
|
6221
|
+
}));
|
|
6222
|
+
Expression::Case(Box::new(crate::expressions::Case {
|
|
6223
|
+
operand: None,
|
|
6224
|
+
whens: vec![
|
|
6225
|
+
(predicate, Expression::string("true")),
|
|
6226
|
+
(false_predicate, Expression::string("false")),
|
|
6227
|
+
],
|
|
6228
|
+
else_: Some(Expression::null()),
|
|
6229
|
+
comments: Vec::new(),
|
|
6230
|
+
inferred_type: None,
|
|
6231
|
+
}))
|
|
6232
|
+
}
|
|
6233
|
+
|
|
6072
6234
|
fn rewrite_tsql_boolean_scalar_value(expr: Expression) -> Result<Expression> {
|
|
6235
|
+
if let Expression::Boolean(boolean) = expr {
|
|
6236
|
+
return Ok(Expression::Cast(Box::new(Cast {
|
|
6237
|
+
this: Expression::Boolean(boolean),
|
|
6238
|
+
to: DataType::Boolean,
|
|
6239
|
+
trailing_comments: Vec::new(),
|
|
6240
|
+
double_colon_syntax: false,
|
|
6241
|
+
format: None,
|
|
6242
|
+
default: None,
|
|
6243
|
+
inferred_type: None,
|
|
6244
|
+
})));
|
|
6245
|
+
}
|
|
6246
|
+
|
|
6073
6247
|
if Self::is_tsql_boolean_value_expression(&expr) {
|
|
6074
6248
|
let predicate = Self::rewrite_tsql_boolean_predicate_context(expr)?;
|
|
6075
6249
|
return Ok(Self::tsql_boolean_value_case(predicate));
|
|
@@ -6124,6 +6298,7 @@ impl Dialect {
|
|
|
6124
6298
|
Ok(Expression::SafeCast(cast))
|
|
6125
6299
|
}
|
|
6126
6300
|
Expression::Case(mut case) => {
|
|
6301
|
+
let is_simple_case = case.operand.is_some();
|
|
6127
6302
|
if let Some(operand) = case.operand.take() {
|
|
6128
6303
|
case.operand = Some(Self::rewrite_tsql_boolean_scalar_value(operand)?);
|
|
6129
6304
|
}
|
|
@@ -6131,10 +6306,12 @@ impl Dialect {
|
|
|
6131
6306
|
.whens
|
|
6132
6307
|
.into_iter()
|
|
6133
6308
|
.map(|(condition, result)| {
|
|
6134
|
-
|
|
6135
|
-
Self::
|
|
6136
|
-
|
|
6137
|
-
|
|
6309
|
+
let condition = if is_simple_case {
|
|
6310
|
+
Self::rewrite_tsql_boolean_scalar_value(condition)?
|
|
6311
|
+
} else {
|
|
6312
|
+
Self::rewrite_tsql_boolean_predicate_context(condition)?
|
|
6313
|
+
};
|
|
6314
|
+
Ok((condition, Self::rewrite_tsql_boolean_scalar_value(result)?))
|
|
6138
6315
|
})
|
|
6139
6316
|
.collect::<Result<Vec<_>>>()?;
|
|
6140
6317
|
if let Some(else_) = case.else_.take() {
|
{polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/src/dialects/normalization/mod.rs
RENAMED
|
@@ -21,6 +21,14 @@ struct NormalizationContext {
|
|
|
21
21
|
target: DialectType,
|
|
22
22
|
}
|
|
23
23
|
|
|
24
|
+
pub(super) fn rewrite_postgres_float_to_integer_cast(cast: Cast) -> Expression {
|
|
25
|
+
types::rewrite_postgres_float_to_integer_cast(cast)
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
pub(super) fn is_postgres_unknown_type(data_type: &DataType) -> bool {
|
|
29
|
+
types::is_postgres_unknown_type(data_type)
|
|
30
|
+
}
|
|
31
|
+
|
|
24
32
|
enum RewriteOutcome {
|
|
25
33
|
// No domain action was selected. The ordered fallback may still have
|
|
26
34
|
// normalized the expression before returning it.
|
|
@@ -1399,11 +1407,33 @@ pub(super) fn normalize(
|
|
|
1399
1407
|
matches!(target, DialectType::DuckDB | DialectType::PostgreSQL);
|
|
1400
1408
|
|
|
1401
1409
|
match &e {
|
|
1410
|
+
Expression::Subquery(subquery)
|
|
1411
|
+
if matches!(target, DialectType::TSQL | DialectType::Fabric)
|
|
1412
|
+
&& subquery.alias.is_some()
|
|
1413
|
+
&& subquery.column_aliases.is_empty()
|
|
1414
|
+
&& matches!(&subquery.this, Expression::Values(values) if !values.expressions.is_empty()) =>
|
|
1415
|
+
{
|
|
1416
|
+
Action::Statements(
|
|
1417
|
+
statements::Action::EnsureValuesDerivedTableColumnAliases,
|
|
1418
|
+
)
|
|
1419
|
+
}
|
|
1420
|
+
Expression::Extract(_)
|
|
1421
|
+
if matches!(source, DialectType::PostgreSQL)
|
|
1422
|
+
&& matches!(target, DialectType::TSQL | DialectType::Fabric)
|
|
1423
|
+
&& temporal::is_postgres_time_date_part(&e) =>
|
|
1424
|
+
{
|
|
1425
|
+
Action::Temporal(temporal::Action::PostgresTimeDatePartForTsql)
|
|
1426
|
+
}
|
|
1402
1427
|
Expression::Function(f) => {
|
|
1403
1428
|
let name = f.name.to_ascii_uppercase();
|
|
1404
1429
|
// DuckDB json(x) is a synonym for CAST(x AS JSON) — parses a string.
|
|
1405
1430
|
// Map to JSON_PARSE(x) for Trino/Presto/Athena to preserve semantics.
|
|
1406
|
-
if
|
|
1431
|
+
if matches!(source, DialectType::PostgreSQL)
|
|
1432
|
+
&& matches!(target, DialectType::TSQL | DialectType::Fabric)
|
|
1433
|
+
&& temporal::is_postgres_time_date_part(&e)
|
|
1434
|
+
{
|
|
1435
|
+
Action::Temporal(temporal::Action::PostgresTimeDatePartForTsql)
|
|
1436
|
+
} else if name == "JSON"
|
|
1407
1437
|
&& f.args.len() == 1
|
|
1408
1438
|
&& matches!(source, DialectType::DuckDB)
|
|
1409
1439
|
&& matches!(
|
|
@@ -2136,11 +2166,21 @@ pub(super) fn normalize(
|
|
|
2136
2166
|
// because BigQuery's TIMESTAMP is really TIMESTAMPTZ, and
|
|
2137
2167
|
// DATETIME is the timezone-unaware type
|
|
2138
2168
|
Expression::Cast(ref c) => {
|
|
2139
|
-
if
|
|
2169
|
+
if matches!(source, DialectType::PostgreSQL)
|
|
2170
|
+
&& matches!(target, DialectType::TSQL | DialectType::Fabric)
|
|
2171
|
+
&& types::is_postgres_unknown_null_cast(c)
|
|
2172
|
+
{
|
|
2173
|
+
Action::Types(types::Action::PostgresUnknownNullCast)
|
|
2174
|
+
} else if c.format.is_some()
|
|
2140
2175
|
&& (matches!(source, DialectType::BigQuery)
|
|
2141
2176
|
|| matches!(source, DialectType::Teradata))
|
|
2142
2177
|
{
|
|
2143
2178
|
Action::Types(types::Action::BigQueryCastFormat)
|
|
2179
|
+
} else if matches!(source, DialectType::PostgreSQL)
|
|
2180
|
+
&& matches!(target, DialectType::TSQL | DialectType::Fabric)
|
|
2181
|
+
&& types::is_postgres_float_to_integer_cast(c)
|
|
2182
|
+
{
|
|
2183
|
+
Action::Types(types::Action::PostgresFloatToIntegerCast)
|
|
2144
2184
|
} else if matches!(target, DialectType::BigQuery)
|
|
2145
2185
|
&& !matches!(source, DialectType::BigQuery)
|
|
2146
2186
|
&& matches!(
|
|
@@ -6,6 +6,7 @@ use crate::expressions::*;
|
|
|
6
6
|
#[derive(Debug)]
|
|
7
7
|
pub(super) enum Action {
|
|
8
8
|
SetToVariable,
|
|
9
|
+
EnsureValuesDerivedTableColumnAliases,
|
|
9
10
|
AlterTableRenameStripSchema,
|
|
10
11
|
TempTableHash,
|
|
11
12
|
TablesampleReservoir,
|
|
@@ -400,6 +401,24 @@ pub(super) fn rewrite(
|
|
|
400
401
|
let e = expression;
|
|
401
402
|
let expression = (|| -> Result<Expression> {
|
|
402
403
|
match action {
|
|
404
|
+
Action::EnsureValuesDerivedTableColumnAliases => {
|
|
405
|
+
if let Expression::Subquery(mut subquery) = e {
|
|
406
|
+
let column_count = match &subquery.this {
|
|
407
|
+
Expression::Values(values) => values
|
|
408
|
+
.expressions
|
|
409
|
+
.first()
|
|
410
|
+
.map(|row| row.expressions.len())
|
|
411
|
+
.unwrap_or(0),
|
|
412
|
+
_ => 0,
|
|
413
|
+
};
|
|
414
|
+
subquery.column_aliases = (1..=column_count)
|
|
415
|
+
.map(|index| Identifier::new(format!("column{index}")))
|
|
416
|
+
.collect();
|
|
417
|
+
Ok(Expression::Subquery(subquery))
|
|
418
|
+
} else {
|
|
419
|
+
Ok(e)
|
|
420
|
+
}
|
|
421
|
+
}
|
|
403
422
|
Action::SetToVariable => {
|
|
404
423
|
// For DuckDB: SET a = 1 -> SET VARIABLE a = 1
|
|
405
424
|
if let Expression::SetStatement(mut s) = e {
|
{polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/src/dialects/normalization/temporal.rs
RENAMED
|
@@ -5,6 +5,7 @@ use crate::expressions::*;
|
|
|
5
5
|
|
|
6
6
|
#[derive(Debug)]
|
|
7
7
|
pub(super) enum Action {
|
|
8
|
+
PostgresTimeDatePartForTsql,
|
|
8
9
|
ConvertTimezoneToExpr,
|
|
9
10
|
EpochConvert,
|
|
10
11
|
EpochMsConvert,
|
|
@@ -50,6 +51,7 @@ pub(super) fn rewrite(
|
|
|
50
51
|
let e = expression;
|
|
51
52
|
let expression = (|| -> Result<Expression> {
|
|
52
53
|
match action {
|
|
54
|
+
Action::PostgresTimeDatePartForTsql => rewrite_postgres_time_date_part_for_tsql(e),
|
|
53
55
|
Action::ConvertTimezoneToExpr => {
|
|
54
56
|
// Convert Function("CONVERT_TIMEZONE", args) to Expression::ConvertTimezone
|
|
55
57
|
// This prevents Redshift's transform_expr from expanding 2-arg to 3-arg with 'UTC'
|
|
@@ -2695,6 +2697,173 @@ pub(super) fn rewrite(
|
|
|
2695
2697
|
Ok(RewriteOutcome::Rewritten(expression))
|
|
2696
2698
|
}
|
|
2697
2699
|
|
|
2700
|
+
#[derive(Debug, Clone, Copy)]
|
|
2701
|
+
enum PostgresTimeDatePart {
|
|
2702
|
+
Second,
|
|
2703
|
+
Millisecond,
|
|
2704
|
+
Microsecond,
|
|
2705
|
+
Epoch,
|
|
2706
|
+
}
|
|
2707
|
+
|
|
2708
|
+
pub(super) fn is_postgres_time_date_part(expression: &Expression) -> bool {
|
|
2709
|
+
postgres_time_date_part(expression).is_some()
|
|
2710
|
+
}
|
|
2711
|
+
|
|
2712
|
+
fn postgres_time_date_part(expression: &Expression) -> Option<(PostgresTimeDatePart, Expression)> {
|
|
2713
|
+
match expression {
|
|
2714
|
+
Expression::Extract(extract) if is_time_value(&extract.this) => {
|
|
2715
|
+
let field = match &extract.field {
|
|
2716
|
+
DateTimeField::Second => PostgresTimeDatePart::Second,
|
|
2717
|
+
DateTimeField::Millisecond => PostgresTimeDatePart::Millisecond,
|
|
2718
|
+
DateTimeField::Microsecond => PostgresTimeDatePart::Microsecond,
|
|
2719
|
+
DateTimeField::Epoch => PostgresTimeDatePart::Epoch,
|
|
2720
|
+
_ => return None,
|
|
2721
|
+
};
|
|
2722
|
+
Some((field, extract.this.clone()))
|
|
2723
|
+
}
|
|
2724
|
+
Expression::Function(function)
|
|
2725
|
+
if function.args.len() == 2
|
|
2726
|
+
&& matches!(
|
|
2727
|
+
function.name.to_ascii_uppercase().as_str(),
|
|
2728
|
+
"DATE_PART" | "DATEPART"
|
|
2729
|
+
)
|
|
2730
|
+
&& is_time_value(&function.args[1]) =>
|
|
2731
|
+
{
|
|
2732
|
+
let field = postgres_time_date_part_name(&function.args[0])?;
|
|
2733
|
+
Some((field, function.args[1].clone()))
|
|
2734
|
+
}
|
|
2735
|
+
_ => None,
|
|
2736
|
+
}
|
|
2737
|
+
}
|
|
2738
|
+
|
|
2739
|
+
fn postgres_time_date_part_name(expression: &Expression) -> Option<PostgresTimeDatePart> {
|
|
2740
|
+
let name = match expression {
|
|
2741
|
+
Expression::Literal(literal) => match literal.as_ref() {
|
|
2742
|
+
Literal::String(name) => name.as_str(),
|
|
2743
|
+
_ => return None,
|
|
2744
|
+
},
|
|
2745
|
+
Expression::Identifier(identifier) => identifier.name.as_str(),
|
|
2746
|
+
Expression::Column(column) if column.table.is_none() => column.name.name.as_str(),
|
|
2747
|
+
Expression::Cast(cast)
|
|
2748
|
+
if matches!(
|
|
2749
|
+
cast.to,
|
|
2750
|
+
DataType::Text | DataType::TextWithLength { .. } | DataType::VarChar { .. }
|
|
2751
|
+
) =>
|
|
2752
|
+
{
|
|
2753
|
+
return postgres_time_date_part_name(&cast.this);
|
|
2754
|
+
}
|
|
2755
|
+
_ => return None,
|
|
2756
|
+
};
|
|
2757
|
+
|
|
2758
|
+
match name.trim().to_ascii_uppercase().as_str() {
|
|
2759
|
+
"SECOND" | "SECONDS" | "SEC" | "SECS" | "S" | "SS" => Some(PostgresTimeDatePart::Second),
|
|
2760
|
+
"MILLISECOND" | "MILLISECONDS" | "MILLISEC" | "MILLISECS" | "MS" | "MSEC" | "MSECS" => {
|
|
2761
|
+
Some(PostgresTimeDatePart::Millisecond)
|
|
2762
|
+
}
|
|
2763
|
+
"MICROSECOND" | "MICROSECONDS" | "MICROSEC" | "MICROSECS" | "US" | "USEC" | "USECS"
|
|
2764
|
+
| "MCS" => Some(PostgresTimeDatePart::Microsecond),
|
|
2765
|
+
"EPOCH" | "EPOCH_SECOND" | "EPOCH_SECONDS" => Some(PostgresTimeDatePart::Epoch),
|
|
2766
|
+
_ => None,
|
|
2767
|
+
}
|
|
2768
|
+
}
|
|
2769
|
+
|
|
2770
|
+
fn is_time_value(expression: &Expression) -> bool {
|
|
2771
|
+
let is_time_type = |data_type: &DataType| {
|
|
2772
|
+
matches!(data_type, DataType::Time { .. })
|
|
2773
|
+
|| matches!(
|
|
2774
|
+
data_type,
|
|
2775
|
+
DataType::Custom { name }
|
|
2776
|
+
if name.eq_ignore_ascii_case("TIME") || name.to_ascii_uppercase().starts_with("TIME(")
|
|
2777
|
+
)
|
|
2778
|
+
};
|
|
2779
|
+
|
|
2780
|
+
match expression {
|
|
2781
|
+
Expression::Cast(cast) | Expression::TryCast(cast) | Expression::SafeCast(cast) => {
|
|
2782
|
+
is_time_type(&cast.to)
|
|
2783
|
+
}
|
|
2784
|
+
Expression::Literal(literal) => matches!(literal.as_ref(), Literal::Time(_)),
|
|
2785
|
+
Expression::Paren(paren) => is_time_value(&paren.this),
|
|
2786
|
+
Expression::Alias(alias) => is_time_value(&alias.this),
|
|
2787
|
+
Expression::CurrentTime(_) | Expression::Localtime(_) => true,
|
|
2788
|
+
other => other.inferred_type().is_some_and(is_time_type),
|
|
2789
|
+
}
|
|
2790
|
+
}
|
|
2791
|
+
|
|
2792
|
+
fn rewrite_postgres_time_date_part_for_tsql(expression: Expression) -> Result<Expression> {
|
|
2793
|
+
let Some((field, value)) = postgres_time_date_part(&expression) else {
|
|
2794
|
+
return Ok(expression);
|
|
2795
|
+
};
|
|
2796
|
+
|
|
2797
|
+
let date_part = |name: &str, value: Expression| {
|
|
2798
|
+
Expression::Function(Box::new(Function::new(
|
|
2799
|
+
"DATEPART",
|
|
2800
|
+
vec![Expression::Identifier(Identifier::new(name)), value],
|
|
2801
|
+
)))
|
|
2802
|
+
};
|
|
2803
|
+
let decimal = |value: &str| Expression::Literal(Box::new(Literal::Number(value.to_string())));
|
|
2804
|
+
let fractional_microseconds = date_part("MICROSECOND", value.clone());
|
|
2805
|
+
let fractional_seconds = Expression::Div(Box::new(BinaryOp::new(
|
|
2806
|
+
fractional_microseconds.clone(),
|
|
2807
|
+
decimal("1000000.0"),
|
|
2808
|
+
)));
|
|
2809
|
+
let whole_seconds = date_part("SECOND", value.clone());
|
|
2810
|
+
|
|
2811
|
+
let rewritten = match field {
|
|
2812
|
+
PostgresTimeDatePart::Second => {
|
|
2813
|
+
Expression::Add(Box::new(BinaryOp::new(whole_seconds, fractional_seconds)))
|
|
2814
|
+
}
|
|
2815
|
+
PostgresTimeDatePart::Millisecond => {
|
|
2816
|
+
let whole_milliseconds = Expression::Mul(Box::new(BinaryOp::new(
|
|
2817
|
+
whole_seconds,
|
|
2818
|
+
Expression::number(1000),
|
|
2819
|
+
)));
|
|
2820
|
+
let fractional_milliseconds = Expression::Div(Box::new(BinaryOp::new(
|
|
2821
|
+
fractional_microseconds,
|
|
2822
|
+
decimal("1000.0"),
|
|
2823
|
+
)));
|
|
2824
|
+
Expression::Add(Box::new(BinaryOp::new(
|
|
2825
|
+
whole_milliseconds,
|
|
2826
|
+
fractional_milliseconds,
|
|
2827
|
+
)))
|
|
2828
|
+
}
|
|
2829
|
+
PostgresTimeDatePart::Microsecond => {
|
|
2830
|
+
let whole_microseconds = Expression::Mul(Box::new(BinaryOp::new(
|
|
2831
|
+
whole_seconds,
|
|
2832
|
+
Expression::number(1_000_000),
|
|
2833
|
+
)));
|
|
2834
|
+
Expression::Add(Box::new(BinaryOp::new(
|
|
2835
|
+
whole_microseconds,
|
|
2836
|
+
fractional_microseconds,
|
|
2837
|
+
)))
|
|
2838
|
+
}
|
|
2839
|
+
PostgresTimeDatePart::Epoch => {
|
|
2840
|
+
let midnight = Expression::Cast(Box::new(Cast {
|
|
2841
|
+
this: Expression::string("00:00:00"),
|
|
2842
|
+
to: DataType::Time {
|
|
2843
|
+
precision: Some(6),
|
|
2844
|
+
timezone: false,
|
|
2845
|
+
},
|
|
2846
|
+
trailing_comments: Vec::new(),
|
|
2847
|
+
double_colon_syntax: false,
|
|
2848
|
+
format: None,
|
|
2849
|
+
default: None,
|
|
2850
|
+
inferred_type: None,
|
|
2851
|
+
}));
|
|
2852
|
+
let elapsed_seconds = Expression::Function(Box::new(Function::new(
|
|
2853
|
+
"DATEDIFF",
|
|
2854
|
+
vec![
|
|
2855
|
+
Expression::Identifier(Identifier::new("SECOND")),
|
|
2856
|
+
midnight,
|
|
2857
|
+
value,
|
|
2858
|
+
],
|
|
2859
|
+
)));
|
|
2860
|
+
Expression::Add(Box::new(BinaryOp::new(elapsed_seconds, fractional_seconds)))
|
|
2861
|
+
}
|
|
2862
|
+
};
|
|
2863
|
+
|
|
2864
|
+
Ok(rewritten)
|
|
2865
|
+
}
|
|
2866
|
+
|
|
2698
2867
|
pub(super) fn date_trunc_to_mysql(unit: &str, expr: &Expression) -> Result<Expression> {
|
|
2699
2868
|
use crate::expressions::Function;
|
|
2700
2869
|
match unit {
|