polyglot-sql 0.6.2__tar.gz → 0.6.3__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {polyglot_sql-0.6.2 → polyglot_sql-0.6.3}/Cargo.lock +6 -6
- {polyglot_sql-0.6.2 → polyglot_sql-0.6.3}/Cargo.toml +1 -1
- {polyglot_sql-0.6.2 → polyglot_sql-0.6.3}/PKG-INFO +1 -1
- {polyglot_sql-0.6.2 → polyglot_sql-0.6.3}/crates/polyglot-sql/Cargo.toml +2 -2
- {polyglot_sql-0.6.2 → polyglot_sql-0.6.3}/crates/polyglot-sql/README.md +1 -1
- {polyglot_sql-0.6.2 → polyglot_sql-0.6.3}/crates/polyglot-sql/src/dialects/athena.rs +2 -0
- {polyglot_sql-0.6.2 → polyglot_sql-0.6.3}/crates/polyglot-sql/src/dialects/bigquery.rs +3 -0
- {polyglot_sql-0.6.2 → polyglot_sql-0.6.3}/crates/polyglot-sql/src/dialects/duckdb.rs +1 -0
- {polyglot_sql-0.6.2 → polyglot_sql-0.6.3}/crates/polyglot-sql/src/dialects/mod.rs +382 -2
- {polyglot_sql-0.6.2 → polyglot_sql-0.6.3}/crates/polyglot-sql/src/dialects/mysql.rs +50 -0
- {polyglot_sql-0.6.2 → polyglot_sql-0.6.3}/crates/polyglot-sql/src/dialects/normalization/collections.rs +7 -0
- {polyglot_sql-0.6.2 → polyglot_sql-0.6.3}/crates/polyglot-sql/src/dialects/normalization/mod.rs +5 -3
- {polyglot_sql-0.6.2 → polyglot_sql-0.6.3}/crates/polyglot-sql/src/dialects/normalization/scalar.rs +1 -0
- {polyglot_sql-0.6.2 → polyglot_sql-0.6.3}/crates/polyglot-sql/src/dialects/normalization/temporal.rs +37 -27
- {polyglot_sql-0.6.2 → polyglot_sql-0.6.3}/crates/polyglot-sql/src/dialects/postgres.rs +2 -0
- {polyglot_sql-0.6.2 → polyglot_sql-0.6.3}/crates/polyglot-sql/src/dialects/presto.rs +2 -0
- {polyglot_sql-0.6.2 → polyglot_sql-0.6.3}/crates/polyglot-sql/src/dialects/trino.rs +2 -0
- {polyglot_sql-0.6.2 → polyglot_sql-0.6.3}/crates/polyglot-sql/src/dialects/tsql.rs +97 -23
- {polyglot_sql-0.6.2 → polyglot_sql-0.6.3}/crates/polyglot-sql/src/expressions.rs +119 -0
- {polyglot_sql-0.6.2 → polyglot_sql-0.6.3}/crates/polyglot-sql/src/generator.rs +642 -31
- {polyglot_sql-0.6.2 → polyglot_sql-0.6.3}/crates/polyglot-sql/src/lib.rs +4 -4
- {polyglot_sql-0.6.2 → polyglot_sql-0.6.3}/crates/polyglot-sql/src/lineage.rs +421 -57
- {polyglot_sql-0.6.2 → polyglot_sql-0.6.3}/crates/polyglot-sql/src/openlineage.rs +2 -2
- {polyglot_sql-0.6.2 → polyglot_sql-0.6.3}/crates/polyglot-sql/src/optimizer/annotate_types.rs +445 -4
- {polyglot_sql-0.6.2 → polyglot_sql-0.6.3}/crates/polyglot-sql/src/parser.rs +802 -108
- {polyglot_sql-0.6.2 → polyglot_sql-0.6.3}/crates/polyglot-sql/src/query_analysis.rs +5 -92
- {polyglot_sql-0.6.2 → polyglot_sql-0.6.3}/crates/polyglot-sql/src/tokens.rs +0 -2
- {polyglot_sql-0.6.2 → polyglot_sql-0.6.3}/crates/polyglot-sql/src/transforms.rs +10 -0
- {polyglot_sql-0.6.2 → polyglot_sql-0.6.3}/crates/polyglot-sql/src/validation.rs +64 -1
- {polyglot_sql-0.6.2 → polyglot_sql-0.6.3}/crates/polyglot-sql/tests/dialect_matrix.rs +41 -3
- {polyglot_sql-0.6.2 → polyglot_sql-0.6.3}/crates/polyglot-sql/tests/fabric_regression.rs +261 -26
- polyglot_sql-0.6.3/crates/polyglot-sql/tests/oracle_data_types_regression.rs +285 -0
- {polyglot_sql-0.6.2 → polyglot_sql-0.6.3}/crates/polyglot-sql/tests/query_analysis.rs +77 -0
- {polyglot_sql-0.6.2 → polyglot_sql-0.6.3}/crates/polyglot-sql/tests/sqlglot_compat.rs +63 -0
- {polyglot_sql-0.6.2 → polyglot_sql-0.6.3}/crates/polyglot-sql/tests/tsql_regression.rs +308 -25
- {polyglot_sql-0.6.2 → polyglot_sql-0.6.3}/crates/polyglot-sql-python/src/annotate_types.rs +9 -3
- {polyglot_sql-0.6.2 → polyglot_sql-0.6.3}/crates/polyglot-sql-python/src/lineage.rs +7 -1
- {polyglot_sql-0.6.2 → polyglot_sql-0.6.3}/README.md +0 -0
- {polyglot_sql-0.6.2 → polyglot_sql-0.6.3}/crates/polyglot-sql/benches/allocation_hotspots.rs +0 -0
- {polyglot_sql-0.6.2 → polyglot_sql-0.6.3}/crates/polyglot-sql/benches/ast_traversal.rs +0 -0
- {polyglot_sql-0.6.2 → polyglot_sql-0.6.3}/crates/polyglot-sql/benches/in_list.rs +0 -0
- {polyglot_sql-0.6.2 → polyglot_sql-0.6.3}/crates/polyglot-sql/benches/lineage.rs +0 -0
- {polyglot_sql-0.6.2 → polyglot_sql-0.6.3}/crates/polyglot-sql/benches/parsing.rs +0 -0
- {polyglot_sql-0.6.2 → polyglot_sql-0.6.3}/crates/polyglot-sql/benches/performance_hotspots.rs +0 -0
- {polyglot_sql-0.6.2 → polyglot_sql-0.6.3}/crates/polyglot-sql/benches/rust_parsing.rs +0 -0
- {polyglot_sql-0.6.2 → polyglot_sql-0.6.3}/crates/polyglot-sql/benches/transpile.rs +0 -0
- {polyglot_sql-0.6.2 → polyglot_sql-0.6.3}/crates/polyglot-sql/examples/basic_usage.rs +0 -0
- {polyglot_sql-0.6.2 → polyglot_sql-0.6.3}/crates/polyglot-sql/examples/bench_json.rs +0 -0
- {polyglot_sql-0.6.2 → polyglot_sql-0.6.3}/crates/polyglot-sql/src/ast_children.rs +0 -0
- {polyglot_sql-0.6.2 → polyglot_sql-0.6.3}/crates/polyglot-sql/src/ast_json.rs +0 -0
- {polyglot_sql-0.6.2 → polyglot_sql-0.6.3}/crates/polyglot-sql/src/ast_transforms.rs +0 -0
- {polyglot_sql-0.6.2 → polyglot_sql-0.6.3}/crates/polyglot-sql/src/builder.rs +0 -0
- {polyglot_sql-0.6.2 → polyglot_sql-0.6.3}/crates/polyglot-sql/src/dialects/clickhouse.rs +0 -0
- {polyglot_sql-0.6.2 → polyglot_sql-0.6.3}/crates/polyglot-sql/src/dialects/cockroachdb.rs +0 -0
- {polyglot_sql-0.6.2 → polyglot_sql-0.6.3}/crates/polyglot-sql/src/dialects/databricks.rs +0 -0
- {polyglot_sql-0.6.2 → polyglot_sql-0.6.3}/crates/polyglot-sql/src/dialects/datafusion.rs +0 -0
- {polyglot_sql-0.6.2 → polyglot_sql-0.6.3}/crates/polyglot-sql/src/dialects/doris.rs +0 -0
- {polyglot_sql-0.6.2 → polyglot_sql-0.6.3}/crates/polyglot-sql/src/dialects/dremio.rs +0 -0
- {polyglot_sql-0.6.2 → polyglot_sql-0.6.3}/crates/polyglot-sql/src/dialects/drill.rs +0 -0
- {polyglot_sql-0.6.2 → polyglot_sql-0.6.3}/crates/polyglot-sql/src/dialects/druid.rs +0 -0
- {polyglot_sql-0.6.2 → polyglot_sql-0.6.3}/crates/polyglot-sql/src/dialects/dune.rs +0 -0
- {polyglot_sql-0.6.2 → polyglot_sql-0.6.3}/crates/polyglot-sql/src/dialects/exasol.rs +0 -0
- {polyglot_sql-0.6.2 → polyglot_sql-0.6.3}/crates/polyglot-sql/src/dialects/fabric.rs +0 -0
- {polyglot_sql-0.6.2 → polyglot_sql-0.6.3}/crates/polyglot-sql/src/dialects/generic.rs +0 -0
- {polyglot_sql-0.6.2 → polyglot_sql-0.6.3}/crates/polyglot-sql/src/dialects/hive.rs +0 -0
- {polyglot_sql-0.6.2 → polyglot_sql-0.6.3}/crates/polyglot-sql/src/dialects/materialize.rs +0 -0
- {polyglot_sql-0.6.2 → polyglot_sql-0.6.3}/crates/polyglot-sql/src/dialects/normalization/aggregates.rs +0 -0
- {polyglot_sql-0.6.2 → polyglot_sql-0.6.3}/crates/polyglot-sql/src/dialects/normalization/json.rs +0 -0
- {polyglot_sql-0.6.2 → polyglot_sql-0.6.3}/crates/polyglot-sql/src/dialects/normalization/operators.rs +0 -0
- {polyglot_sql-0.6.2 → polyglot_sql-0.6.3}/crates/polyglot-sql/src/dialects/normalization/postgres_interval.rs +0 -0
- {polyglot_sql-0.6.2 → polyglot_sql-0.6.3}/crates/polyglot-sql/src/dialects/normalization/statements.rs +0 -0
- {polyglot_sql-0.6.2 → polyglot_sql-0.6.3}/crates/polyglot-sql/src/dialects/normalization/types.rs +0 -0
- {polyglot_sql-0.6.2 → polyglot_sql-0.6.3}/crates/polyglot-sql/src/dialects/oracle.rs +0 -0
- {polyglot_sql-0.6.2 → polyglot_sql-0.6.3}/crates/polyglot-sql/src/dialects/redshift.rs +0 -0
- {polyglot_sql-0.6.2 → polyglot_sql-0.6.3}/crates/polyglot-sql/src/dialects/risingwave.rs +0 -0
- {polyglot_sql-0.6.2 → polyglot_sql-0.6.3}/crates/polyglot-sql/src/dialects/singlestore.rs +0 -0
- {polyglot_sql-0.6.2 → polyglot_sql-0.6.3}/crates/polyglot-sql/src/dialects/snowflake.rs +0 -0
- {polyglot_sql-0.6.2 → polyglot_sql-0.6.3}/crates/polyglot-sql/src/dialects/solr.rs +0 -0
- {polyglot_sql-0.6.2 → polyglot_sql-0.6.3}/crates/polyglot-sql/src/dialects/spark.rs +0 -0
- {polyglot_sql-0.6.2 → polyglot_sql-0.6.3}/crates/polyglot-sql/src/dialects/sqlite.rs +0 -0
- {polyglot_sql-0.6.2 → polyglot_sql-0.6.3}/crates/polyglot-sql/src/dialects/starrocks.rs +0 -0
- {polyglot_sql-0.6.2 → polyglot_sql-0.6.3}/crates/polyglot-sql/src/dialects/tableau.rs +0 -0
- {polyglot_sql-0.6.2 → polyglot_sql-0.6.3}/crates/polyglot-sql/src/dialects/teradata.rs +0 -0
- {polyglot_sql-0.6.2 → polyglot_sql-0.6.3}/crates/polyglot-sql/src/dialects/tidb.rs +0 -0
- {polyglot_sql-0.6.2 → polyglot_sql-0.6.3}/crates/polyglot-sql/src/diff.rs +0 -0
- {polyglot_sql-0.6.2 → polyglot_sql-0.6.3}/crates/polyglot-sql/src/error.rs +0 -0
- {polyglot_sql-0.6.2 → polyglot_sql-0.6.3}/crates/polyglot-sql/src/format_tokens.rs +0 -0
- {polyglot_sql-0.6.2 → polyglot_sql-0.6.3}/crates/polyglot-sql/src/function_catalog.rs +0 -0
- {polyglot_sql-0.6.2 → polyglot_sql-0.6.3}/crates/polyglot-sql/src/function_registry.rs +0 -0
- {polyglot_sql-0.6.2 → polyglot_sql-0.6.3}/crates/polyglot-sql/src/guard.rs +0 -0
- {polyglot_sql-0.6.2 → polyglot_sql-0.6.3}/crates/polyglot-sql/src/helper.rs +0 -0
- {polyglot_sql-0.6.2 → polyglot_sql-0.6.3}/crates/polyglot-sql/src/optimizer/canonicalize.rs +0 -0
- {polyglot_sql-0.6.2 → polyglot_sql-0.6.3}/crates/polyglot-sql/src/optimizer/eliminate_ctes.rs +0 -0
- {polyglot_sql-0.6.2 → polyglot_sql-0.6.3}/crates/polyglot-sql/src/optimizer/eliminate_joins.rs +0 -0
- {polyglot_sql-0.6.2 → polyglot_sql-0.6.3}/crates/polyglot-sql/src/optimizer/isolate_table_selects.rs +0 -0
- {polyglot_sql-0.6.2 → polyglot_sql-0.6.3}/crates/polyglot-sql/src/optimizer/mod.rs +0 -0
- {polyglot_sql-0.6.2 → polyglot_sql-0.6.3}/crates/polyglot-sql/src/optimizer/normalize.rs +0 -0
- {polyglot_sql-0.6.2 → polyglot_sql-0.6.3}/crates/polyglot-sql/src/optimizer/normalize_identifiers.rs +0 -0
- {polyglot_sql-0.6.2 → polyglot_sql-0.6.3}/crates/polyglot-sql/src/optimizer/optimize_joins.rs +0 -0
- {polyglot_sql-0.6.2 → polyglot_sql-0.6.3}/crates/polyglot-sql/src/optimizer/optimizer.rs +0 -0
- {polyglot_sql-0.6.2 → polyglot_sql-0.6.3}/crates/polyglot-sql/src/optimizer/pushdown_predicates.rs +0 -0
- {polyglot_sql-0.6.2 → polyglot_sql-0.6.3}/crates/polyglot-sql/src/optimizer/pushdown_projections.rs +0 -0
- {polyglot_sql-0.6.2 → polyglot_sql-0.6.3}/crates/polyglot-sql/src/optimizer/qualify_columns.rs +0 -0
- {polyglot_sql-0.6.2 → polyglot_sql-0.6.3}/crates/polyglot-sql/src/optimizer/qualify_tables.rs +0 -0
- {polyglot_sql-0.6.2 → polyglot_sql-0.6.3}/crates/polyglot-sql/src/optimizer/simplify.rs +0 -0
- {polyglot_sql-0.6.2 → polyglot_sql-0.6.3}/crates/polyglot-sql/src/optimizer/subquery.rs +0 -0
- {polyglot_sql-0.6.2 → polyglot_sql-0.6.3}/crates/polyglot-sql/src/planner.rs +0 -0
- {polyglot_sql-0.6.2 → polyglot_sql-0.6.3}/crates/polyglot-sql/src/resolver.rs +0 -0
- {polyglot_sql-0.6.2 → polyglot_sql-0.6.3}/crates/polyglot-sql/src/schema.rs +0 -0
- {polyglot_sql-0.6.2 → polyglot_sql-0.6.3}/crates/polyglot-sql/src/scope.rs +0 -0
- {polyglot_sql-0.6.2 → polyglot_sql-0.6.3}/crates/polyglot-sql/src/time.rs +0 -0
- {polyglot_sql-0.6.2 → polyglot_sql-0.6.3}/crates/polyglot-sql/src/traversal.rs +0 -0
- {polyglot_sql-0.6.2 → polyglot_sql-0.6.3}/crates/polyglot-sql/src/trie.rs +0 -0
- {polyglot_sql-0.6.2 → polyglot_sql-0.6.3}/crates/polyglot-sql/src/validation/tests.rs +0 -0
- {polyglot_sql-0.6.2 → polyglot_sql-0.6.3}/crates/polyglot-sql/tests/analyze_failures.rs +0 -0
- {polyglot_sql-0.6.2 → polyglot_sql-0.6.3}/crates/polyglot-sql/tests/clickhouse_regression.rs +0 -0
- {polyglot_sql-0.6.2 → polyglot_sql-0.6.3}/crates/polyglot-sql/tests/common/known_failures.rs +0 -0
- {polyglot_sql-0.6.2 → polyglot_sql-0.6.3}/crates/polyglot-sql/tests/common/mod.rs +0 -0
- {polyglot_sql-0.6.2 → polyglot_sql-0.6.3}/crates/polyglot-sql/tests/common/test_data.rs +0 -0
- {polyglot_sql-0.6.2 → polyglot_sql-0.6.3}/crates/polyglot-sql/tests/common/test_runner.rs +0 -0
- {polyglot_sql-0.6.2 → polyglot_sql-0.6.3}/crates/polyglot-sql/tests/create_view_security_comment_regression.rs +0 -0
- {polyglot_sql-0.6.2 → polyglot_sql-0.6.3}/crates/polyglot-sql/tests/custom_clickhouse_coverage.rs +0 -0
- {polyglot_sql-0.6.2 → polyglot_sql-0.6.3}/crates/polyglot-sql/tests/custom_clickhouse_parser.rs +0 -0
- {polyglot_sql-0.6.2 → polyglot_sql-0.6.3}/crates/polyglot-sql/tests/custom_dialect.rs +0 -0
- {polyglot_sql-0.6.2 → polyglot_sql-0.6.3}/crates/polyglot-sql/tests/custom_dialect_tests.rs +0 -0
- {polyglot_sql-0.6.2 → polyglot_sql-0.6.3}/crates/polyglot-sql/tests/custom_fixtures/datafusion/ddl.json +0 -0
- {polyglot_sql-0.6.2 → polyglot_sql-0.6.3}/crates/polyglot-sql/tests/custom_fixtures/datafusion/dml.json +0 -0
- {polyglot_sql-0.6.2 → polyglot_sql-0.6.3}/crates/polyglot-sql/tests/custom_fixtures/datafusion/functions.json +0 -0
- {polyglot_sql-0.6.2 → polyglot_sql-0.6.3}/crates/polyglot-sql/tests/custom_fixtures/datafusion/identity.json +0 -0
- {polyglot_sql-0.6.2 → polyglot_sql-0.6.3}/crates/polyglot-sql/tests/custom_fixtures/datafusion/operators.json +0 -0
- {polyglot_sql-0.6.2 → polyglot_sql-0.6.3}/crates/polyglot-sql/tests/custom_fixtures/datafusion/select.json +0 -0
- {polyglot_sql-0.6.2 → polyglot_sql-0.6.3}/crates/polyglot-sql/tests/custom_fixtures/datafusion/transpilation.json +0 -0
- {polyglot_sql-0.6.2 → polyglot_sql-0.6.3}/crates/polyglot-sql/tests/custom_fixtures/datafusion/types.json +0 -0
- {polyglot_sql-0.6.2 → polyglot_sql-0.6.3}/crates/polyglot-sql/tests/data_type_api.rs +0 -0
- {polyglot_sql-0.6.2 → polyglot_sql-0.6.3}/crates/polyglot-sql/tests/deep_nesting_regression.rs +0 -0
- {polyglot_sql-0.6.2 → polyglot_sql-0.6.3}/crates/polyglot-sql/tests/error_handling.rs +0 -0
- {polyglot_sql-0.6.2 → polyglot_sql-0.6.3}/crates/polyglot-sql/tests/fabric_tpch_regression.rs +0 -0
- {polyglot_sql-0.6.2 → polyglot_sql-0.6.3}/crates/polyglot-sql/tests/identity_roundtrip.rs +0 -0
- {polyglot_sql-0.6.2 → polyglot_sql-0.6.3}/crates/polyglot-sql/tests/postgres_explain_options.rs +0 -0
- {polyglot_sql-0.6.2 → polyglot_sql-0.6.3}/crates/polyglot-sql/tests/postgres_regexp_clickhouse.rs +0 -0
- {polyglot_sql-0.6.2 → polyglot_sql-0.6.3}/crates/polyglot-sql/tests/postgres_sqlite_regression.rs +0 -0
- {polyglot_sql-0.6.2 → polyglot_sql-0.6.3}/crates/polyglot-sql/tests/query_analysis_regression.rs +0 -0
- {polyglot_sql-0.6.2 → polyglot_sql-0.6.3}/crates/polyglot-sql/tests/snowflake_regression_test.rs +0 -0
- {polyglot_sql-0.6.2 → polyglot_sql-0.6.3}/crates/polyglot-sql/tests/sqlglot_dialect_identity.rs +0 -0
- {polyglot_sql-0.6.2 → polyglot_sql-0.6.3}/crates/polyglot-sql/tests/sqlglot_identity.rs +0 -0
- {polyglot_sql-0.6.2 → polyglot_sql-0.6.3}/crates/polyglot-sql/tests/sqlglot_identity_detailed.rs +0 -0
- {polyglot_sql-0.6.2 → polyglot_sql-0.6.3}/crates/polyglot-sql/tests/sqlglot_parser.rs +0 -0
- {polyglot_sql-0.6.2 → polyglot_sql-0.6.3}/crates/polyglot-sql/tests/sqlglot_pretty.rs +0 -0
- {polyglot_sql-0.6.2 → polyglot_sql-0.6.3}/crates/polyglot-sql/tests/sqlglot_transpilation.rs +0 -0
- {polyglot_sql-0.6.2 → polyglot_sql-0.6.3}/crates/polyglot-sql/tests/sqlglot_transpile.rs +0 -0
- {polyglot_sql-0.6.2 → polyglot_sql-0.6.3}/crates/polyglot-sql/tests/tpch_transpile_stack.rs +0 -0
- {polyglot_sql-0.6.2 → polyglot_sql-0.6.3}/crates/polyglot-sql/tests/transform_regression.rs +0 -0
- {polyglot_sql-0.6.2 → polyglot_sql-0.6.3}/crates/polyglot-sql-ast-derive/Cargo.toml +0 -0
- {polyglot_sql-0.6.2 → polyglot_sql-0.6.3}/crates/polyglot-sql-ast-derive/src/lib.rs +0 -0
- {polyglot_sql-0.6.2 → polyglot_sql-0.6.3}/crates/polyglot-sql-function-catalogs/Cargo.toml +0 -0
- {polyglot_sql-0.6.2 → polyglot_sql-0.6.3}/crates/polyglot-sql-function-catalogs/README.md +0 -0
- {polyglot_sql-0.6.2 → polyglot_sql-0.6.3}/crates/polyglot-sql-function-catalogs/src/clickhouse.rs +0 -0
- {polyglot_sql-0.6.2 → polyglot_sql-0.6.3}/crates/polyglot-sql-function-catalogs/src/duckdb.rs +0 -0
- {polyglot_sql-0.6.2 → polyglot_sql-0.6.3}/crates/polyglot-sql-function-catalogs/src/lib.rs +0 -0
- {polyglot_sql-0.6.2 → polyglot_sql-0.6.3}/crates/polyglot-sql-function-catalogs/tools/clickhouse/extract_functions.py +0 -0
- {polyglot_sql-0.6.2 → polyglot_sql-0.6.3}/crates/polyglot-sql-function-catalogs/tools/duckdb/extract_functions.py +0 -0
- {polyglot_sql-0.6.2 → polyglot_sql-0.6.3}/crates/polyglot-sql-python/Cargo.toml +0 -0
- {polyglot_sql-0.6.2 → polyglot_sql-0.6.3}/crates/polyglot-sql-python/README.md +0 -0
- {polyglot_sql-0.6.2 → polyglot_sql-0.6.3}/crates/polyglot-sql-python/docs/api.md +0 -0
- {polyglot_sql-0.6.2 → polyglot_sql-0.6.3}/crates/polyglot-sql-python/docs/index.md +0 -0
- {polyglot_sql-0.6.2 → polyglot_sql-0.6.3}/crates/polyglot-sql-python/mkdocs.yml +0 -0
- {polyglot_sql-0.6.2 → polyglot_sql-0.6.3}/crates/polyglot-sql-python/src/dialects.rs +0 -0
- {polyglot_sql-0.6.2 → polyglot_sql-0.6.3}/crates/polyglot-sql-python/src/diff.rs +0 -0
- {polyglot_sql-0.6.2 → polyglot_sql-0.6.3}/crates/polyglot-sql-python/src/errors.rs +0 -0
- {polyglot_sql-0.6.2 → polyglot_sql-0.6.3}/crates/polyglot-sql-python/src/expr.rs +0 -0
- {polyglot_sql-0.6.2 → polyglot_sql-0.6.3}/crates/polyglot-sql-python/src/expr_types.rs +0 -0
- {polyglot_sql-0.6.2 → polyglot_sql-0.6.3}/crates/polyglot-sql-python/src/format.rs +0 -0
- {polyglot_sql-0.6.2 → polyglot_sql-0.6.3}/crates/polyglot-sql-python/src/generate.rs +0 -0
- {polyglot_sql-0.6.2 → polyglot_sql-0.6.3}/crates/polyglot-sql-python/src/helpers.rs +0 -0
- {polyglot_sql-0.6.2 → polyglot_sql-0.6.3}/crates/polyglot-sql-python/src/lib.rs +0 -0
- {polyglot_sql-0.6.2 → polyglot_sql-0.6.3}/crates/polyglot-sql-python/src/openlineage.rs +0 -0
- {polyglot_sql-0.6.2 → polyglot_sql-0.6.3}/crates/polyglot-sql-python/src/optimize.rs +0 -0
- {polyglot_sql-0.6.2 → polyglot_sql-0.6.3}/crates/polyglot-sql-python/src/parse.rs +0 -0
- {polyglot_sql-0.6.2 → polyglot_sql-0.6.3}/crates/polyglot-sql-python/src/query_analysis.rs +0 -0
- {polyglot_sql-0.6.2 → polyglot_sql-0.6.3}/crates/polyglot-sql-python/src/tokenize.rs +0 -0
- {polyglot_sql-0.6.2 → polyglot_sql-0.6.3}/crates/polyglot-sql-python/src/transforms.rs +0 -0
- {polyglot_sql-0.6.2 → polyglot_sql-0.6.3}/crates/polyglot-sql-python/src/transpile.rs +0 -0
- {polyglot_sql-0.6.2 → polyglot_sql-0.6.3}/crates/polyglot-sql-python/src/types.rs +0 -0
- {polyglot_sql-0.6.2 → polyglot_sql-0.6.3}/crates/polyglot-sql-python/src/validate.rs +0 -0
- {polyglot_sql-0.6.2 → polyglot_sql-0.6.3}/crates/polyglot-sql-python/tests/conftest.py +0 -0
- {polyglot_sql-0.6.2 → polyglot_sql-0.6.3}/crates/polyglot-sql-python/tests/test_compat.py +0 -0
- {polyglot_sql-0.6.2 → polyglot_sql-0.6.3}/crates/polyglot-sql-python/tests/test_dialects.py +0 -0
- {polyglot_sql-0.6.2 → polyglot_sql-0.6.3}/crates/polyglot-sql-python/tests/test_diff.py +0 -0
- {polyglot_sql-0.6.2 → polyglot_sql-0.6.3}/crates/polyglot-sql-python/tests/test_expression.py +0 -0
- {polyglot_sql-0.6.2 → polyglot_sql-0.6.3}/crates/polyglot-sql-python/tests/test_format.py +0 -0
- {polyglot_sql-0.6.2 → polyglot_sql-0.6.3}/crates/polyglot-sql-python/tests/test_generate.py +0 -0
- {polyglot_sql-0.6.2 → polyglot_sql-0.6.3}/crates/polyglot-sql-python/tests/test_lineage.py +0 -0
- {polyglot_sql-0.6.2 → polyglot_sql-0.6.3}/crates/polyglot-sql-python/tests/test_optimize.py +0 -0
- {polyglot_sql-0.6.2 → polyglot_sql-0.6.3}/crates/polyglot-sql-python/tests/test_parse.py +0 -0
- {polyglot_sql-0.6.2 → polyglot_sql-0.6.3}/crates/polyglot-sql-python/tests/test_query_analysis.py +0 -0
- {polyglot_sql-0.6.2 → polyglot_sql-0.6.3}/crates/polyglot-sql-python/tests/test_transforms.py +0 -0
- {polyglot_sql-0.6.2 → polyglot_sql-0.6.3}/crates/polyglot-sql-python/tests/test_transpile.py +0 -0
- {polyglot_sql-0.6.2 → polyglot_sql-0.6.3}/crates/polyglot-sql-python/tests/test_validate.py +0 -0
- {polyglot_sql-0.6.2 → polyglot_sql-0.6.3}/crates/polyglot-sql-python/uv.lock +0 -0
- {polyglot_sql-0.6.2 → polyglot_sql-0.6.3}/pyproject.toml +0 -0
- {polyglot_sql-0.6.2 → polyglot_sql-0.6.3}/python/polyglot_sql/__init__.py +0 -0
- {polyglot_sql-0.6.2 → polyglot_sql-0.6.3}/python/polyglot_sql/__init__.pyi +0 -0
- {polyglot_sql-0.6.2 → polyglot_sql-0.6.3}/python/polyglot_sql/py.typed +0 -0
|
@@ -605,7 +605,7 @@ dependencies = [
|
|
|
605
605
|
|
|
606
606
|
[[package]]
|
|
607
607
|
name = "polyglot-sql"
|
|
608
|
-
version = "0.6.
|
|
608
|
+
version = "0.6.3"
|
|
609
609
|
dependencies = [
|
|
610
610
|
"criterion",
|
|
611
611
|
"once_cell",
|
|
@@ -623,7 +623,7 @@ dependencies = [
|
|
|
623
623
|
|
|
624
624
|
[[package]]
|
|
625
625
|
name = "polyglot-sql-ast-derive"
|
|
626
|
-
version = "0.6.
|
|
626
|
+
version = "0.6.3"
|
|
627
627
|
dependencies = [
|
|
628
628
|
"proc-macro2",
|
|
629
629
|
"quote",
|
|
@@ -632,7 +632,7 @@ dependencies = [
|
|
|
632
632
|
|
|
633
633
|
[[package]]
|
|
634
634
|
name = "polyglot-sql-ffi"
|
|
635
|
-
version = "0.6.
|
|
635
|
+
version = "0.6.3"
|
|
636
636
|
dependencies = [
|
|
637
637
|
"cbindgen",
|
|
638
638
|
"polyglot-sql",
|
|
@@ -642,11 +642,11 @@ dependencies = [
|
|
|
642
642
|
|
|
643
643
|
[[package]]
|
|
644
644
|
name = "polyglot-sql-function-catalogs"
|
|
645
|
-
version = "0.6.
|
|
645
|
+
version = "0.6.3"
|
|
646
646
|
|
|
647
647
|
[[package]]
|
|
648
648
|
name = "polyglot-sql-python"
|
|
649
|
-
version = "0.6.
|
|
649
|
+
version = "0.6.3"
|
|
650
650
|
dependencies = [
|
|
651
651
|
"polyglot-sql",
|
|
652
652
|
"pyo3",
|
|
@@ -657,7 +657,7 @@ dependencies = [
|
|
|
657
657
|
|
|
658
658
|
[[package]]
|
|
659
659
|
name = "polyglot-sql-wasm"
|
|
660
|
-
version = "0.6.
|
|
660
|
+
version = "0.6.3"
|
|
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.6.
|
|
103
|
+
polyglot-sql-ast-derive = { path = "../polyglot-sql-ast-derive", version = "0.6.3" }
|
|
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.3", 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.3", default-features = false }
|
|
29
29
|
```
|
|
30
30
|
|
|
31
31
|
```toml
|
|
@@ -147,6 +147,7 @@ impl DialectImpl for AthenaDialect {
|
|
|
147
147
|
with_ordinality: false,
|
|
148
148
|
alias: None,
|
|
149
149
|
offset_alias: None,
|
|
150
|
+
inferred_type: None,
|
|
150
151
|
},
|
|
151
152
|
))),
|
|
152
153
|
|
|
@@ -158,6 +159,7 @@ impl DialectImpl for AthenaDialect {
|
|
|
158
159
|
with_ordinality: false,
|
|
159
160
|
alias: None,
|
|
160
161
|
offset_alias: None,
|
|
162
|
+
inferred_type: None,
|
|
161
163
|
},
|
|
162
164
|
))),
|
|
163
165
|
|
|
@@ -196,6 +196,7 @@ impl DialectImpl for BigQueryDialect {
|
|
|
196
196
|
with_ordinality: false,
|
|
197
197
|
alias: None,
|
|
198
198
|
offset_alias: None,
|
|
199
|
+
inferred_type: None,
|
|
199
200
|
},
|
|
200
201
|
))),
|
|
201
202
|
|
|
@@ -207,6 +208,7 @@ impl DialectImpl for BigQueryDialect {
|
|
|
207
208
|
with_ordinality: false,
|
|
208
209
|
alias: None,
|
|
209
210
|
offset_alias: None,
|
|
211
|
+
inferred_type: None,
|
|
210
212
|
},
|
|
211
213
|
))),
|
|
212
214
|
|
|
@@ -703,6 +705,7 @@ impl DialectImpl for BigQueryDialect {
|
|
|
703
705
|
with_ordinality: false,
|
|
704
706
|
alias: None,
|
|
705
707
|
offset_alias: None,
|
|
708
|
+
inferred_type: None,
|
|
706
709
|
}));
|
|
707
710
|
let aliased_unnest = Expression::Alias(Box::new(Alias {
|
|
708
711
|
this: unnest,
|
|
@@ -163,8 +163,8 @@ use crate::error::Result;
|
|
|
163
163
|
#[cfg(feature = "transpile")]
|
|
164
164
|
use crate::expressions::{
|
|
165
165
|
BinaryOp, Case, Cast, ColumnConstraint, DateBin, Fetch, Function, Identifier, Interval,
|
|
166
|
-
IntervalUnit, IntervalUnitSpec, Literal, Offset, Over, Top, Var, WindowFrame,
|
|
167
|
-
WindowFrameKind,
|
|
166
|
+
IntervalUnit, IntervalUnitSpec, Literal, Offset, Over, Select, Subquery, Top, Var, WindowFrame,
|
|
167
|
+
WindowFrameBound, WindowFrameKind,
|
|
168
168
|
};
|
|
169
169
|
use crate::expressions::{DataType, Expression};
|
|
170
170
|
#[cfg(any(
|
|
@@ -181,6 +181,8 @@ use crate::generator::{Generator, GeneratorConfig};
|
|
|
181
181
|
#[cfg(feature = "transpile")]
|
|
182
182
|
use crate::guard::enforce_generate_ast;
|
|
183
183
|
use crate::guard::{enforce_input, ComplexityGuardOptions};
|
|
184
|
+
#[cfg(feature = "transpile")]
|
|
185
|
+
use crate::helper::find_new_name;
|
|
184
186
|
use crate::parser::Parser;
|
|
185
187
|
#[cfg(feature = "transpile")]
|
|
186
188
|
use crate::tokens::TokenType;
|
|
@@ -274,6 +276,16 @@ pub enum DialectType {
|
|
|
274
276
|
DataFusion,
|
|
275
277
|
}
|
|
276
278
|
|
|
279
|
+
impl DialectType {
|
|
280
|
+
/// Whether SELECT projections may use string literals as column aliases.
|
|
281
|
+
pub(crate) const fn supports_string_aliases(self) -> bool {
|
|
282
|
+
matches!(
|
|
283
|
+
self,
|
|
284
|
+
DialectType::TSQL | DialectType::Fabric | DialectType::MySQL | DialectType::SQLite
|
|
285
|
+
)
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
|
|
277
289
|
impl Default for DialectType {
|
|
278
290
|
fn default() -> Self {
|
|
279
291
|
DialectType::Generic
|
|
@@ -3858,6 +3870,14 @@ impl Dialect {
|
|
|
3858
3870
|
normalized
|
|
3859
3871
|
};
|
|
3860
3872
|
|
|
3873
|
+
let normalized = if self.dialect_type == DialectType::PostgreSQL
|
|
3874
|
+
&& matches!(target, DialectType::TSQL | DialectType::Fabric)
|
|
3875
|
+
{
|
|
3876
|
+
Self::normalize_postgres_bytea_literals_for_tsql(normalized)?
|
|
3877
|
+
} else {
|
|
3878
|
+
normalized
|
|
3879
|
+
};
|
|
3880
|
+
|
|
3861
3881
|
let normalized = if matches!(
|
|
3862
3882
|
self.dialect_type,
|
|
3863
3883
|
DialectType::PostgreSQL | DialectType::CockroachDB
|
|
@@ -3917,6 +3937,11 @@ impl Dialect {
|
|
|
3917
3937
|
let normalized = if matches!(target, DialectType::TSQL | DialectType::Fabric)
|
|
3918
3938
|
&& !matches!(self.dialect_type, DialectType::TSQL | DialectType::Fabric)
|
|
3919
3939
|
{
|
|
3940
|
+
let normalized = if self.dialect_type == DialectType::PostgreSQL {
|
|
3941
|
+
Self::rewrite_postgres_row_value_equality_for_tsql(normalized)?
|
|
3942
|
+
} else {
|
|
3943
|
+
normalized
|
|
3944
|
+
};
|
|
3920
3945
|
Self::rewrite_boolean_values_for_tsql(normalized)?
|
|
3921
3946
|
} else {
|
|
3922
3947
|
normalized
|
|
@@ -4422,6 +4447,16 @@ impl Dialect {
|
|
|
4422
4447
|
&format!("PostgreSQL {string_semantics}"),
|
|
4423
4448
|
);
|
|
4424
4449
|
}
|
|
4450
|
+
if source == DialectType::PostgreSQL {
|
|
4451
|
+
if let Some(binary_semantics) =
|
|
4452
|
+
Self::postgres_tsql_unsupported_binary_semantics(node)
|
|
4453
|
+
{
|
|
4454
|
+
Self::push_unsupported_diagnostic(
|
|
4455
|
+
&mut diagnostics,
|
|
4456
|
+
&format!("PostgreSQL {binary_semantics}"),
|
|
4457
|
+
);
|
|
4458
|
+
}
|
|
4459
|
+
}
|
|
4425
4460
|
if let Some(function_name) =
|
|
4426
4461
|
Self::postgres_tsql_unsupported_function_name(node, target)
|
|
4427
4462
|
{
|
|
@@ -6093,6 +6128,110 @@ impl Dialect {
|
|
|
6093
6128
|
})
|
|
6094
6129
|
}
|
|
6095
6130
|
|
|
6131
|
+
fn normalize_postgres_bytea_literals_for_tsql(expr: Expression) -> Result<Expression> {
|
|
6132
|
+
transform_recursive(expr, &|e| match e {
|
|
6133
|
+
Expression::Cast(cast) if Self::is_postgres_bytea_data_type(&cast.to) => {
|
|
6134
|
+
let Some(value) = Self::postgres_plain_string_literal_value(&cast.this) else {
|
|
6135
|
+
return Ok(Expression::Cast(cast));
|
|
6136
|
+
};
|
|
6137
|
+
let Some(hex) = Self::postgres_bytea_hex_payload(value) else {
|
|
6138
|
+
return Ok(Expression::Cast(cast));
|
|
6139
|
+
};
|
|
6140
|
+
|
|
6141
|
+
// Replace the complete BYTEA cast. Keeping a bare T-SQL
|
|
6142
|
+
// CAST(... AS VARBINARY) would apply SQL Server's default length
|
|
6143
|
+
// and could truncate payloads longer than 30 bytes.
|
|
6144
|
+
Ok(Expression::Literal(Box::new(Literal::HexString(hex))))
|
|
6145
|
+
}
|
|
6146
|
+
other => Ok(other),
|
|
6147
|
+
})
|
|
6148
|
+
}
|
|
6149
|
+
|
|
6150
|
+
fn postgres_plain_string_literal_value(expr: &Expression) -> Option<&str> {
|
|
6151
|
+
match expr {
|
|
6152
|
+
Expression::Literal(literal) => match literal.as_ref() {
|
|
6153
|
+
Literal::String(value) => Some(value),
|
|
6154
|
+
_ => None,
|
|
6155
|
+
},
|
|
6156
|
+
Expression::Paren(paren) => Self::postgres_plain_string_literal_value(&paren.this),
|
|
6157
|
+
_ => None,
|
|
6158
|
+
}
|
|
6159
|
+
}
|
|
6160
|
+
|
|
6161
|
+
fn postgres_bytea_hex_payload(value: &str) -> Option<String> {
|
|
6162
|
+
let payload = value.strip_prefix("\\x")?;
|
|
6163
|
+
if payload.is_empty() {
|
|
6164
|
+
return Some(String::new());
|
|
6165
|
+
}
|
|
6166
|
+
|
|
6167
|
+
let mut chars = payload.chars().peekable();
|
|
6168
|
+
let mut hex = String::with_capacity(payload.len());
|
|
6169
|
+
loop {
|
|
6170
|
+
let high = chars.next()?;
|
|
6171
|
+
let low = chars.next()?;
|
|
6172
|
+
if !high.is_ascii_hexdigit() || !low.is_ascii_hexdigit() {
|
|
6173
|
+
return None;
|
|
6174
|
+
}
|
|
6175
|
+
hex.push(high);
|
|
6176
|
+
hex.push(low);
|
|
6177
|
+
|
|
6178
|
+
let Some(next) = chars.peek().copied() else {
|
|
6179
|
+
return Some(hex);
|
|
6180
|
+
};
|
|
6181
|
+
if next.is_ascii_whitespace() {
|
|
6182
|
+
while chars
|
|
6183
|
+
.peek()
|
|
6184
|
+
.is_some_and(|character| character.is_ascii_whitespace())
|
|
6185
|
+
{
|
|
6186
|
+
chars.next();
|
|
6187
|
+
}
|
|
6188
|
+
// PostgreSQL permits whitespace between byte pairs, not after
|
|
6189
|
+
// the prefix or after the final pair.
|
|
6190
|
+
chars.peek()?;
|
|
6191
|
+
}
|
|
6192
|
+
}
|
|
6193
|
+
}
|
|
6194
|
+
|
|
6195
|
+
fn is_postgres_bytea_data_type(data_type: &DataType) -> bool {
|
|
6196
|
+
match data_type {
|
|
6197
|
+
DataType::VarBinary { length: None } => true,
|
|
6198
|
+
DataType::Custom { name } => name.trim().eq_ignore_ascii_case("BYTEA"),
|
|
6199
|
+
_ => false,
|
|
6200
|
+
}
|
|
6201
|
+
}
|
|
6202
|
+
|
|
6203
|
+
fn postgres_tsql_unsupported_binary_semantics(expr: &Expression) -> Option<&'static str> {
|
|
6204
|
+
let cast = match expr {
|
|
6205
|
+
Expression::Cast(cast) | Expression::TryCast(cast) | Expression::SafeCast(cast)
|
|
6206
|
+
if Self::is_postgres_bytea_data_type(&cast.to) =>
|
|
6207
|
+
{
|
|
6208
|
+
cast
|
|
6209
|
+
}
|
|
6210
|
+
_ => return None,
|
|
6211
|
+
};
|
|
6212
|
+
|
|
6213
|
+
let literal = match &cast.this {
|
|
6214
|
+
Expression::Literal(literal) => literal.as_ref(),
|
|
6215
|
+
Expression::Paren(paren) => match &paren.this {
|
|
6216
|
+
Expression::Literal(literal) => literal.as_ref(),
|
|
6217
|
+
_ => return None,
|
|
6218
|
+
},
|
|
6219
|
+
_ => return None,
|
|
6220
|
+
};
|
|
6221
|
+
let value = match literal {
|
|
6222
|
+
Literal::String(value) | Literal::EscapeString(value) => value,
|
|
6223
|
+
_ => return None,
|
|
6224
|
+
};
|
|
6225
|
+
|
|
6226
|
+
if value.starts_with("\\x") {
|
|
6227
|
+
Some("bytea hex literals with invalid or unsupported formatting")
|
|
6228
|
+
} else if value.contains('\\') {
|
|
6229
|
+
Some("bytea escape-format literals")
|
|
6230
|
+
} else {
|
|
6231
|
+
None
|
|
6232
|
+
}
|
|
6233
|
+
}
|
|
6234
|
+
|
|
6096
6235
|
fn recover_postgres_like_escape(op: &mut crate::expressions::LikeOp) {
|
|
6097
6236
|
if op.escape.is_some() {
|
|
6098
6237
|
return;
|
|
@@ -6616,6 +6755,247 @@ impl Dialect {
|
|
|
6616
6755
|
}
|
|
6617
6756
|
}
|
|
6618
6757
|
|
|
6758
|
+
fn rewrite_postgres_row_value_equality_for_tsql(expr: Expression) -> Result<Expression> {
|
|
6759
|
+
transform_recursive(expr, &|e| match e {
|
|
6760
|
+
Expression::Eq(op) => {
|
|
6761
|
+
let op = *op;
|
|
6762
|
+
Ok(Self::postgres_row_value_equality_to_tsql_scalar(&op)
|
|
6763
|
+
.unwrap_or_else(|| Expression::Eq(Box::new(op))))
|
|
6764
|
+
}
|
|
6765
|
+
other => Ok(other),
|
|
6766
|
+
})
|
|
6767
|
+
}
|
|
6768
|
+
|
|
6769
|
+
fn postgres_row_value_equality_to_tsql_scalar(op: &BinaryOp) -> Option<Expression> {
|
|
6770
|
+
let (row, query) =
|
|
6771
|
+
if Self::expr_is_row_value(&op.left) && Self::expr_is_subquery_like(&op.right) {
|
|
6772
|
+
(&op.left, &op.right)
|
|
6773
|
+
} else if Self::expr_is_row_value(&op.right) && Self::expr_is_subquery_like(&op.left) {
|
|
6774
|
+
(&op.right, &op.left)
|
|
6775
|
+
} else {
|
|
6776
|
+
return None;
|
|
6777
|
+
};
|
|
6778
|
+
|
|
6779
|
+
let row_values = Self::row_value_expressions(row)?;
|
|
6780
|
+
let projection_count = Self::subquery_projection_count(query)?;
|
|
6781
|
+
if row_values.is_empty() || row_values.len() != projection_count {
|
|
6782
|
+
return None;
|
|
6783
|
+
}
|
|
6784
|
+
|
|
6785
|
+
// Keep the complete original query behind a derived table. The outer scalar
|
|
6786
|
+
// SELECT therefore returns the same number of rows as the PostgreSQL
|
|
6787
|
+
// single-row subquery: zero rows stay NULL and multiple rows still raise a
|
|
6788
|
+
// scalar-subquery cardinality error in T-SQL/Fabric.
|
|
6789
|
+
let mut taken_names = HashSet::new();
|
|
6790
|
+
Self::collect_generated_alias_conflicts(row, &mut taken_names);
|
|
6791
|
+
Self::collect_generated_alias_conflicts(query, &mut taken_names);
|
|
6792
|
+
|
|
6793
|
+
let source_alias = find_new_name(&taken_names, "_polyglot_row");
|
|
6794
|
+
taken_names.insert(source_alias.to_ascii_lowercase());
|
|
6795
|
+
let column_aliases = (1..=row_values.len())
|
|
6796
|
+
.map(|index| {
|
|
6797
|
+
let name = find_new_name(&taken_names, &format!("_polyglot_row_value_{index}"));
|
|
6798
|
+
taken_names.insert(name.to_ascii_lowercase());
|
|
6799
|
+
Identifier::new(name)
|
|
6800
|
+
})
|
|
6801
|
+
.collect::<Vec<_>>();
|
|
6802
|
+
let source = Self::subquery_as_derived_table(
|
|
6803
|
+
query,
|
|
6804
|
+
Identifier::new(&source_alias),
|
|
6805
|
+
column_aliases.clone(),
|
|
6806
|
+
)?;
|
|
6807
|
+
|
|
6808
|
+
let mut equal_components = Vec::with_capacity(row_values.len());
|
|
6809
|
+
let mut unequal_components = Vec::with_capacity(row_values.len());
|
|
6810
|
+
for (column, row_value) in column_aliases.into_iter().zip(row_values) {
|
|
6811
|
+
let projected = Expression::qualified_column(source_alias.clone(), column.name);
|
|
6812
|
+
equal_components.push(Expression::Eq(Box::new(BinaryOp::new(
|
|
6813
|
+
projected.clone(),
|
|
6814
|
+
row_value.clone(),
|
|
6815
|
+
))));
|
|
6816
|
+
unequal_components.push(Expression::Neq(Box::new(BinaryOp::new(
|
|
6817
|
+
projected, row_value,
|
|
6818
|
+
))));
|
|
6819
|
+
}
|
|
6820
|
+
|
|
6821
|
+
let all_equal = equal_components
|
|
6822
|
+
.into_iter()
|
|
6823
|
+
.reduce(|left, right| Expression::And(Box::new(BinaryOp::new(left, right))))?;
|
|
6824
|
+
let any_unequal = unequal_components
|
|
6825
|
+
.into_iter()
|
|
6826
|
+
.reduce(|left, right| Expression::Or(Box::new(BinaryOp::new(left, right))))?;
|
|
6827
|
+
let comparison = Expression::Case(Box::new(Case {
|
|
6828
|
+
operand: None,
|
|
6829
|
+
whens: vec![
|
|
6830
|
+
(all_equal, Expression::number(1)),
|
|
6831
|
+
(any_unequal, Expression::number(0)),
|
|
6832
|
+
],
|
|
6833
|
+
else_: Some(Expression::null()),
|
|
6834
|
+
comments: Vec::new(),
|
|
6835
|
+
inferred_type: None,
|
|
6836
|
+
}));
|
|
6837
|
+
|
|
6838
|
+
let scalar_select = Select::new().column(comparison).from(source);
|
|
6839
|
+
let scalar_subquery = Expression::Subquery(Box::new(Subquery {
|
|
6840
|
+
this: Expression::Select(Box::new(scalar_select)),
|
|
6841
|
+
alias: None,
|
|
6842
|
+
column_aliases: Vec::new(),
|
|
6843
|
+
alias_explicit_as: false,
|
|
6844
|
+
alias_keyword: None,
|
|
6845
|
+
order_by: None,
|
|
6846
|
+
limit: None,
|
|
6847
|
+
offset: None,
|
|
6848
|
+
distribute_by: None,
|
|
6849
|
+
sort_by: None,
|
|
6850
|
+
cluster_by: None,
|
|
6851
|
+
lateral: false,
|
|
6852
|
+
modifiers_inside: false,
|
|
6853
|
+
trailing_comments: Vec::new(),
|
|
6854
|
+
inferred_type: Some(DataType::Boolean),
|
|
6855
|
+
}));
|
|
6856
|
+
|
|
6857
|
+
Some(Expression::Cast(Box::new(Cast {
|
|
6858
|
+
this: scalar_subquery,
|
|
6859
|
+
to: DataType::Boolean,
|
|
6860
|
+
trailing_comments: Vec::new(),
|
|
6861
|
+
double_colon_syntax: false,
|
|
6862
|
+
format: None,
|
|
6863
|
+
default: None,
|
|
6864
|
+
inferred_type: Some(DataType::Boolean),
|
|
6865
|
+
})))
|
|
6866
|
+
}
|
|
6867
|
+
|
|
6868
|
+
fn row_value_expressions(expr: &Expression) -> Option<Vec<Expression>> {
|
|
6869
|
+
match expr {
|
|
6870
|
+
Expression::Tuple(tuple) => Some(tuple.expressions.clone()),
|
|
6871
|
+
Expression::Function(function) if function.name.eq_ignore_ascii_case("ROW") => {
|
|
6872
|
+
Some(function.args.clone())
|
|
6873
|
+
}
|
|
6874
|
+
Expression::Paren(paren) => Self::row_value_expressions(&paren.this),
|
|
6875
|
+
_ => None,
|
|
6876
|
+
}
|
|
6877
|
+
}
|
|
6878
|
+
|
|
6879
|
+
fn subquery_projection_count(expr: &Expression) -> Option<usize> {
|
|
6880
|
+
match expr {
|
|
6881
|
+
Expression::Select(select) => Some(select.expressions.len()),
|
|
6882
|
+
Expression::Subquery(subquery) => Self::subquery_projection_count(&subquery.this),
|
|
6883
|
+
Expression::Paren(paren) => Self::subquery_projection_count(&paren.this),
|
|
6884
|
+
_ => None,
|
|
6885
|
+
}
|
|
6886
|
+
}
|
|
6887
|
+
|
|
6888
|
+
fn subquery_as_derived_table(
|
|
6889
|
+
expr: &Expression,
|
|
6890
|
+
alias: Identifier,
|
|
6891
|
+
column_aliases: Vec<Identifier>,
|
|
6892
|
+
) -> Option<Expression> {
|
|
6893
|
+
match expr.clone() {
|
|
6894
|
+
Expression::Subquery(mut subquery) => {
|
|
6895
|
+
subquery.alias = Some(alias);
|
|
6896
|
+
subquery.column_aliases = column_aliases;
|
|
6897
|
+
subquery.alias_explicit_as = true;
|
|
6898
|
+
subquery.alias_keyword = None;
|
|
6899
|
+
Some(Expression::Subquery(subquery))
|
|
6900
|
+
}
|
|
6901
|
+
Expression::Select(_) | Expression::Paren(_) => {
|
|
6902
|
+
Some(Expression::Subquery(Box::new(Subquery {
|
|
6903
|
+
this: expr.clone(),
|
|
6904
|
+
alias: Some(alias),
|
|
6905
|
+
column_aliases,
|
|
6906
|
+
alias_explicit_as: true,
|
|
6907
|
+
alias_keyword: None,
|
|
6908
|
+
order_by: None,
|
|
6909
|
+
limit: None,
|
|
6910
|
+
offset: None,
|
|
6911
|
+
distribute_by: None,
|
|
6912
|
+
sort_by: None,
|
|
6913
|
+
cluster_by: None,
|
|
6914
|
+
lateral: false,
|
|
6915
|
+
modifiers_inside: false,
|
|
6916
|
+
trailing_comments: Vec::new(),
|
|
6917
|
+
inferred_type: None,
|
|
6918
|
+
})))
|
|
6919
|
+
}
|
|
6920
|
+
_ => None,
|
|
6921
|
+
}
|
|
6922
|
+
}
|
|
6923
|
+
|
|
6924
|
+
fn collect_generated_alias_conflicts(expr: &Expression, names: &mut HashSet<String>) {
|
|
6925
|
+
fn insert(names: &mut HashSet<String>, identifier: &Identifier) {
|
|
6926
|
+
if !identifier.name.is_empty() {
|
|
6927
|
+
names.insert(identifier.name.to_ascii_lowercase());
|
|
6928
|
+
}
|
|
6929
|
+
}
|
|
6930
|
+
|
|
6931
|
+
for node in expr.dfs() {
|
|
6932
|
+
match node {
|
|
6933
|
+
Expression::Identifier(identifier) => insert(names, identifier),
|
|
6934
|
+
Expression::Column(column) => {
|
|
6935
|
+
insert(names, &column.name);
|
|
6936
|
+
if let Some(table) = &column.table {
|
|
6937
|
+
insert(names, table);
|
|
6938
|
+
}
|
|
6939
|
+
}
|
|
6940
|
+
Expression::Table(table) => {
|
|
6941
|
+
insert(names, &table.name);
|
|
6942
|
+
if let Some(schema) = &table.schema {
|
|
6943
|
+
insert(names, schema);
|
|
6944
|
+
}
|
|
6945
|
+
if let Some(catalog) = &table.catalog {
|
|
6946
|
+
insert(names, catalog);
|
|
6947
|
+
}
|
|
6948
|
+
if let Some(alias) = &table.alias {
|
|
6949
|
+
insert(names, alias);
|
|
6950
|
+
}
|
|
6951
|
+
for alias in &table.column_aliases {
|
|
6952
|
+
insert(names, alias);
|
|
6953
|
+
}
|
|
6954
|
+
}
|
|
6955
|
+
Expression::Alias(alias) => {
|
|
6956
|
+
insert(names, &alias.alias);
|
|
6957
|
+
for column_alias in &alias.column_aliases {
|
|
6958
|
+
insert(names, column_alias);
|
|
6959
|
+
}
|
|
6960
|
+
}
|
|
6961
|
+
Expression::Subquery(subquery) => {
|
|
6962
|
+
if let Some(alias) = &subquery.alias {
|
|
6963
|
+
insert(names, alias);
|
|
6964
|
+
}
|
|
6965
|
+
for column_alias in &subquery.column_aliases {
|
|
6966
|
+
insert(names, column_alias);
|
|
6967
|
+
}
|
|
6968
|
+
}
|
|
6969
|
+
Expression::Cte(cte) => {
|
|
6970
|
+
insert(names, &cte.alias);
|
|
6971
|
+
for column in &cte.columns {
|
|
6972
|
+
insert(names, column);
|
|
6973
|
+
}
|
|
6974
|
+
for key in &cte.key_expressions {
|
|
6975
|
+
insert(names, key);
|
|
6976
|
+
}
|
|
6977
|
+
}
|
|
6978
|
+
Expression::Values(values) => {
|
|
6979
|
+
if let Some(alias) = &values.alias {
|
|
6980
|
+
insert(names, alias);
|
|
6981
|
+
}
|
|
6982
|
+
for column_alias in &values.column_aliases {
|
|
6983
|
+
insert(names, column_alias);
|
|
6984
|
+
}
|
|
6985
|
+
}
|
|
6986
|
+
Expression::Unnest(unnest) => {
|
|
6987
|
+
if let Some(alias) = &unnest.alias {
|
|
6988
|
+
insert(names, alias);
|
|
6989
|
+
}
|
|
6990
|
+
if let Some(offset_alias) = &unnest.offset_alias {
|
|
6991
|
+
insert(names, offset_alias);
|
|
6992
|
+
}
|
|
6993
|
+
}
|
|
6994
|
+
_ => {}
|
|
6995
|
+
}
|
|
6996
|
+
}
|
|
6997
|
+
}
|
|
6998
|
+
|
|
6619
6999
|
fn rewrite_postgres_format_for_tsql(
|
|
6620
7000
|
expr: Expression,
|
|
6621
7001
|
target: DialectType,
|
|
@@ -1404,6 +1404,56 @@ END;";
|
|
|
1404
1404
|
assert!(output.contains("INSERT INTO employees (salary) VALUES (p_salary)"));
|
|
1405
1405
|
}
|
|
1406
1406
|
|
|
1407
|
+
#[test]
|
|
1408
|
+
fn test_mysql_functional_index_key_parts() {
|
|
1409
|
+
let dialect = Dialect::get(DialectType::MySQL);
|
|
1410
|
+
let issue_sql = "CREATE TABLE `test_report` (
|
|
1411
|
+
`id` bigint NOT NULL AUTO_INCREMENT,
|
|
1412
|
+
`batch_no` varchar(64) NOT NULL,
|
|
1413
|
+
PRIMARY KEY (`id`),
|
|
1414
|
+
KEY `idx_clean_batch` ((trim(leading _utf8mb4'0' from `batch_no`)))
|
|
1415
|
+
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;";
|
|
1416
|
+
let ast = dialect.parse(issue_sql).expect("Issue #371 should parse");
|
|
1417
|
+
let output = dialect.generate(&ast[0]).expect("Generate failed");
|
|
1418
|
+
assert!(
|
|
1419
|
+
output.contains("INDEX idx_clean_batch ((TRIM(LEADING _utf8mb4 '0' FROM `batch_no`)))"),
|
|
1420
|
+
"Unexpected output: {output}"
|
|
1421
|
+
);
|
|
1422
|
+
|
|
1423
|
+
for (sql, expected) in [
|
|
1424
|
+
(
|
|
1425
|
+
"CREATE TABLE t (c VARCHAR(20), d INT, KEY idx (d, (LOWER(c)) DESC))",
|
|
1426
|
+
"INDEX idx (d, (LOWER(c)) DESC)",
|
|
1427
|
+
),
|
|
1428
|
+
(
|
|
1429
|
+
"CREATE TABLE t (c VARCHAR(20), UNIQUE INDEX idx ((LOWER(c))))",
|
|
1430
|
+
"UNIQUE idx ((LOWER(c)))",
|
|
1431
|
+
),
|
|
1432
|
+
(
|
|
1433
|
+
"ALTER TABLE t ADD INDEX idx ((LOWER(c)))",
|
|
1434
|
+
"ADD INDEX idx ((LOWER(c)))",
|
|
1435
|
+
),
|
|
1436
|
+
(
|
|
1437
|
+
"CREATE INDEX idx ON t ((LOWER(c)))",
|
|
1438
|
+
"CREATE INDEX idx ON t((LOWER(c)))",
|
|
1439
|
+
),
|
|
1440
|
+
(
|
|
1441
|
+
"CREATE INDEX idx ON t (c(10), d DESC)",
|
|
1442
|
+
"CREATE INDEX idx ON t(c(10), d DESC)",
|
|
1443
|
+
),
|
|
1444
|
+
] {
|
|
1445
|
+
let ast = dialect
|
|
1446
|
+
.parse(sql)
|
|
1447
|
+
.unwrap_or_else(|error| panic!("{sql}: {error}"));
|
|
1448
|
+
let output = dialect.generate(&ast[0]).expect("Generate failed");
|
|
1449
|
+
assert!(
|
|
1450
|
+
output.contains(expected),
|
|
1451
|
+
"SQL: {sql}\nExpected: {expected}\nActual: {output}"
|
|
1452
|
+
);
|
|
1453
|
+
assert!(!output.contains('?'), "Expression was lost: {output}");
|
|
1454
|
+
}
|
|
1455
|
+
}
|
|
1456
|
+
|
|
1407
1457
|
fn mysql_identity(sql: &str, expected: &str) {
|
|
1408
1458
|
let dialect = Dialect::get(DialectType::MySQL);
|
|
1409
1459
|
let ast = dialect.parse(sql).expect("Parse failed");
|