polyglot-sql 0.13.4__tar.gz → 0.13.5__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.
Files changed (238) hide show
  1. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/Cargo.lock +6 -6
  2. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/Cargo.toml +1 -1
  3. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/PKG-INFO +1 -1
  4. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql/Cargo.toml +2 -2
  5. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql/README.md +4 -4
  6. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql/src/dialects/mod.rs +18 -10
  7. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql/src/dialects/normalization/mod.rs +6 -46
  8. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql/src/dialects/normalization/operators.rs +0 -52
  9. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql/src/dialects/normalization/scalar.rs +0 -52
  10. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql/src/dialects/starrocks.rs +1 -1
  11. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql/src/expressions.rs +180 -0
  12. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql/src/generator.rs +179 -16
  13. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql/src/lineage.rs +280 -19
  14. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql/src/openlineage.rs +406 -45
  15. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql/src/optimizer/qualify_columns.rs +99 -27
  16. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql/src/parser.rs +84 -43
  17. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql/src/query_analysis/column_uses.rs +16 -2
  18. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql/src/query_analysis.rs +283 -28
  19. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql/src/resolver.rs +8 -2
  20. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql/src/scope.rs +155 -8
  21. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql/src/transforms.rs +477 -306
  22. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql/tests/clickhouse_regression.rs +134 -0
  23. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql/tests/common/known_failures.rs +8 -0
  24. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql/tests/custom_dialect_tests.rs +23 -0
  25. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql/tests/custom_fixtures/datafusion/transpilation.json +22 -22
  26. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql/tests/custom_fixtures/vertica/identity.json +3 -3
  27. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql/tests/dialect_matrix.rs +216 -7
  28. polyglot_sql-0.13.5/crates/polyglot-sql/tests/duckdb_decimal_precision.rs +80 -0
  29. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql/tests/query_analysis.rs +847 -2
  30. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql/tests/transform_regression.rs +130 -0
  31. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql-function-catalogs/README.md +1 -1
  32. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/python/polyglot_sql/analysis_types.py +6 -1
  33. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/README.md +0 -0
  34. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql/benches/allocation_hotspots.rs +0 -0
  35. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql/benches/ast_traversal.rs +0 -0
  36. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql/benches/common/mod.rs +0 -0
  37. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql/benches/in_list.rs +0 -0
  38. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql/benches/lineage.rs +0 -0
  39. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql/benches/parsing.rs +0 -0
  40. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql/benches/performance_hotspots.rs +0 -0
  41. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql/benches/rust_parsing.rs +0 -0
  42. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql/benches/transpile.rs +0 -0
  43. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql/examples/basic_usage.rs +0 -0
  44. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql/examples/bench_json.rs +0 -0
  45. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql/src/ast_children.rs +0 -0
  46. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql/src/ast_json.rs +0 -0
  47. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql/src/ast_mutation.rs +0 -0
  48. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql/src/ast_transforms.rs +0 -0
  49. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql/src/binding.rs +0 -0
  50. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql/src/builder/mod.rs +0 -0
  51. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql/src/builder/plan.rs +0 -0
  52. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql/src/dialects/athena.rs +0 -0
  53. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql/src/dialects/bigquery.rs +0 -0
  54. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql/src/dialects/clickhouse.rs +0 -0
  55. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql/src/dialects/cockroachdb.rs +0 -0
  56. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql/src/dialects/databricks.rs +0 -0
  57. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql/src/dialects/datafusion.rs +0 -0
  58. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql/src/dialects/doris.rs +0 -0
  59. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql/src/dialects/dremio.rs +0 -0
  60. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql/src/dialects/drill.rs +0 -0
  61. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql/src/dialects/druid.rs +0 -0
  62. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql/src/dialects/duckdb.rs +0 -0
  63. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql/src/dialects/dune.rs +0 -0
  64. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql/src/dialects/exasol.rs +0 -0
  65. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql/src/dialects/fabric.rs +0 -0
  66. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql/src/dialects/generic.rs +0 -0
  67. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql/src/dialects/hana.rs +0 -0
  68. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql/src/dialects/hive.rs +0 -0
  69. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql/src/dialects/materialize.rs +0 -0
  70. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql/src/dialects/mysql.rs +0 -0
  71. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql/src/dialects/normalization/aggregates.rs +0 -0
  72. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql/src/dialects/normalization/collections.rs +0 -0
  73. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql/src/dialects/normalization/duckdb.rs +0 -0
  74. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql/src/dialects/normalization/hana.rs +0 -0
  75. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql/src/dialects/normalization/json.rs +0 -0
  76. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql/src/dialects/normalization/postgres_interval.rs +0 -0
  77. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql/src/dialects/normalization/statements.rs +0 -0
  78. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql/src/dialects/normalization/temporal.rs +0 -0
  79. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql/src/dialects/normalization/types.rs +0 -0
  80. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql/src/dialects/normalization/vertica.rs +0 -0
  81. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql/src/dialects/oracle.rs +0 -0
  82. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql/src/dialects/postgres.rs +0 -0
  83. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql/src/dialects/presto.rs +0 -0
  84. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql/src/dialects/redshift.rs +0 -0
  85. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql/src/dialects/risingwave.rs +0 -0
  86. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql/src/dialects/singlestore.rs +0 -0
  87. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql/src/dialects/snowflake.rs +0 -0
  88. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql/src/dialects/solr.rs +0 -0
  89. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql/src/dialects/spark.rs +0 -0
  90. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql/src/dialects/sqlite.rs +0 -0
  91. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql/src/dialects/tableau.rs +0 -0
  92. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql/src/dialects/teradata.rs +0 -0
  93. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql/src/dialects/tidb.rs +0 -0
  94. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql/src/dialects/trino.rs +0 -0
  95. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql/src/dialects/tsql.rs +0 -0
  96. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql/src/dialects/vertica.rs +0 -0
  97. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql/src/diff.rs +0 -0
  98. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql/src/error.rs +0 -0
  99. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql/src/format_tokens.rs +0 -0
  100. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql/src/function_catalog.rs +0 -0
  101. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql/src/function_registry.rs +0 -0
  102. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql/src/guard.rs +0 -0
  103. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql/src/helper.rs +0 -0
  104. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql/src/lib.rs +0 -0
  105. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql/src/optimizer/annotate_types.rs +0 -0
  106. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql/src/optimizer/canonicalize.rs +0 -0
  107. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql/src/optimizer/eliminate_ctes.rs +0 -0
  108. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql/src/optimizer/eliminate_joins.rs +0 -0
  109. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql/src/optimizer/isolate_table_selects.rs +0 -0
  110. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql/src/optimizer/mod.rs +0 -0
  111. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql/src/optimizer/normalize.rs +0 -0
  112. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql/src/optimizer/normalize_identifiers.rs +0 -0
  113. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql/src/optimizer/optimize_joins.rs +0 -0
  114. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql/src/optimizer/optimizer.rs +0 -0
  115. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql/src/optimizer/pushdown_predicates.rs +0 -0
  116. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql/src/optimizer/pushdown_projections.rs +0 -0
  117. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql/src/optimizer/qualify_tables.rs +0 -0
  118. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql/src/optimizer/set_operation_types.rs +0 -0
  119. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql/src/optimizer/simplify.rs +0 -0
  120. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql/src/optimizer/subquery.rs +0 -0
  121. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql/src/planner.rs +0 -0
  122. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql/src/schema.rs +0 -0
  123. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql/src/set_operation.rs +0 -0
  124. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql/src/time.rs +0 -0
  125. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql/src/tokens.rs +0 -0
  126. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql/src/traversal.rs +0 -0
  127. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql/src/trie.rs +0 -0
  128. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql/src/validation/semantics.rs +0 -0
  129. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql/src/validation/tests.rs +0 -0
  130. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql/src/validation.rs +0 -0
  131. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql/tests/analyze_failures.rs +0 -0
  132. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql/tests/common/mod.rs +0 -0
  133. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql/tests/common/test_data.rs +0 -0
  134. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql/tests/common/test_runner.rs +0 -0
  135. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql/tests/create_view_security_comment_regression.rs +0 -0
  136. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql/tests/custom_clickhouse_coverage.rs +0 -0
  137. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql/tests/custom_clickhouse_parser.rs +0 -0
  138. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql/tests/custom_dialect.rs +0 -0
  139. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql/tests/custom_fixtures/datafusion/ddl.json +0 -0
  140. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql/tests/custom_fixtures/datafusion/dml.json +0 -0
  141. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql/tests/custom_fixtures/datafusion/functions.json +0 -0
  142. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql/tests/custom_fixtures/datafusion/identity.json +0 -0
  143. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql/tests/custom_fixtures/datafusion/operators.json +0 -0
  144. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql/tests/custom_fixtures/datafusion/select.json +0 -0
  145. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql/tests/custom_fixtures/datafusion/types.json +0 -0
  146. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql/tests/custom_fixtures/hana/ddl.json +0 -0
  147. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql/tests/custom_fixtures/hana/dml.json +0 -0
  148. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql/tests/custom_fixtures/hana/functions.json +0 -0
  149. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql/tests/custom_fixtures/hana/identity.json +0 -0
  150. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql/tests/custom_fixtures/hana/select.json +0 -0
  151. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql/tests/custom_fixtures/hana/types.json +0 -0
  152. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql/tests/custom_fixtures/vertica/transpilation.json +0 -0
  153. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql/tests/custom_fixtures/vertica/types.json +0 -0
  154. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql/tests/data_type_api.rs +0 -0
  155. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql/tests/deep_nesting_regression.rs +0 -0
  156. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql/tests/duckdb_integer_division.rs +0 -0
  157. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql/tests/duckdb_json_arrow_context.rs +0 -0
  158. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql/tests/duckdb_order_by_all.rs +0 -0
  159. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql/tests/duckdb_unreserved_relation_aliases.rs +0 -0
  160. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql/tests/error_handling.rs +0 -0
  161. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql/tests/fabric_regression.rs +0 -0
  162. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql/tests/fabric_tpch_regression.rs +0 -0
  163. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql/tests/identity_roundtrip.rs +0 -0
  164. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql/tests/is_predicate_precedence.rs +0 -0
  165. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql/tests/mod_precedence.rs +0 -0
  166. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql/tests/numeric_exponent_boundaries.rs +0 -0
  167. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql/tests/oracle_data_types_regression.rs +0 -0
  168. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql/tests/postgres_explain_options.rs +0 -0
  169. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql/tests/postgres_regexp_clickhouse.rs +0 -0
  170. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql/tests/postgres_sqlite_regression.rs +0 -0
  171. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql/tests/query_analysis_regression.rs +0 -0
  172. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql/tests/quoted_relation_columns.rs +0 -0
  173. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql/tests/snowflake_regression_test.rs +0 -0
  174. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql/tests/sqlglot_compat.rs +0 -0
  175. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql/tests/sqlglot_dialect_identity.rs +0 -0
  176. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql/tests/sqlglot_identity.rs +0 -0
  177. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql/tests/sqlglot_identity_detailed.rs +0 -0
  178. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql/tests/sqlglot_parser.rs +0 -0
  179. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql/tests/sqlglot_pretty.rs +0 -0
  180. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql/tests/sqlglot_transpilation.rs +0 -0
  181. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql/tests/sqlglot_transpile.rs +0 -0
  182. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql/tests/tpch_transpile_stack.rs +0 -0
  183. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql/tests/tsql_regression.rs +0 -0
  184. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql-ast-derive/Cargo.toml +0 -0
  185. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql-ast-derive/src/lib.rs +0 -0
  186. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql-function-catalogs/Cargo.toml +0 -0
  187. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql-function-catalogs/src/clickhouse.rs +0 -0
  188. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql-function-catalogs/src/duckdb.rs +0 -0
  189. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql-function-catalogs/src/lib.rs +0 -0
  190. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql-function-catalogs/tools/clickhouse/extract_functions.py +0 -0
  191. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql-function-catalogs/tools/duckdb/extract_functions.py +0 -0
  192. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql-python/Cargo.toml +0 -0
  193. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql-python/README.md +0 -0
  194. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql-python/docs/api.md +0 -0
  195. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql-python/docs/index.md +0 -0
  196. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql-python/mkdocs.yml +0 -0
  197. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql-python/src/annotate_types.rs +0 -0
  198. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql-python/src/builders.rs +0 -0
  199. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql-python/src/dialects.rs +0 -0
  200. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql-python/src/diff.rs +0 -0
  201. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql-python/src/errors.rs +0 -0
  202. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql-python/src/expr.rs +0 -0
  203. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql-python/src/expr_types.rs +0 -0
  204. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql-python/src/format.rs +0 -0
  205. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql-python/src/generate.rs +0 -0
  206. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql-python/src/helpers.rs +0 -0
  207. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql-python/src/lib.rs +0 -0
  208. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql-python/src/lineage.rs +0 -0
  209. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql-python/src/openlineage.rs +0 -0
  210. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql-python/src/optimize.rs +0 -0
  211. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql-python/src/parse.rs +0 -0
  212. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql-python/src/query_analysis.rs +0 -0
  213. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql-python/src/tokenize.rs +0 -0
  214. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql-python/src/transforms.rs +0 -0
  215. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql-python/src/transpile.rs +0 -0
  216. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql-python/src/types.rs +0 -0
  217. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql-python/src/validate.rs +0 -0
  218. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql-python/tests/conftest.py +0 -0
  219. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql-python/tests/test_builders.py +0 -0
  220. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql-python/tests/test_compat.py +0 -0
  221. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql-python/tests/test_dialects.py +0 -0
  222. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql-python/tests/test_diff.py +0 -0
  223. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql-python/tests/test_duckdb_datafusion_execution.py +0 -0
  224. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql-python/tests/test_expression.py +0 -0
  225. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql-python/tests/test_format.py +0 -0
  226. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql-python/tests/test_generate.py +0 -0
  227. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql-python/tests/test_lineage.py +0 -0
  228. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql-python/tests/test_optimize.py +0 -0
  229. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql-python/tests/test_parse.py +0 -0
  230. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql-python/tests/test_query_analysis.py +0 -0
  231. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql-python/tests/test_transforms.py +0 -0
  232. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql-python/tests/test_transpile.py +0 -0
  233. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql-python/tests/test_validate.py +0 -0
  234. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/crates/polyglot-sql-python/uv.lock +0 -0
  235. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/pyproject.toml +0 -0
  236. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/python/polyglot_sql/__init__.py +0 -0
  237. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/python/polyglot_sql/__init__.pyi +0 -0
  238. {polyglot_sql-0.13.4 → polyglot_sql-0.13.5}/python/polyglot_sql/py.typed +0 -0
@@ -605,7 +605,7 @@ dependencies = [
605
605
 
606
606
  [[package]]
607
607
  name = "polyglot-sql"
608
- version = "0.13.4"
608
+ version = "0.13.5"
609
609
  dependencies = [
610
610
  "criterion",
611
611
  "once_cell",
@@ -623,7 +623,7 @@ dependencies = [
623
623
 
624
624
  [[package]]
625
625
  name = "polyglot-sql-ast-derive"
626
- version = "0.13.4"
626
+ version = "0.13.5"
627
627
  dependencies = [
628
628
  "proc-macro2",
629
629
  "quote",
@@ -632,7 +632,7 @@ dependencies = [
632
632
 
633
633
  [[package]]
634
634
  name = "polyglot-sql-ffi"
635
- version = "0.13.4"
635
+ version = "0.13.5"
636
636
  dependencies = [
637
637
  "cbindgen",
638
638
  "polyglot-sql",
@@ -642,11 +642,11 @@ dependencies = [
642
642
 
643
643
  [[package]]
644
644
  name = "polyglot-sql-function-catalogs"
645
- version = "0.13.4"
645
+ version = "0.13.5"
646
646
 
647
647
  [[package]]
648
648
  name = "polyglot-sql-python"
649
- version = "0.13.4"
649
+ version = "0.13.5"
650
650
  dependencies = [
651
651
  "polyglot-sql",
652
652
  "pyo3",
@@ -657,7 +657,7 @@ dependencies = [
657
657
 
658
658
  [[package]]
659
659
  name = "polyglot-sql-wasm"
660
- version = "0.13.4"
660
+ version = "0.13.5"
661
661
  dependencies = [
662
662
  "console_error_panic_hook",
663
663
  "js-sys",
@@ -6,7 +6,7 @@ exclude = [
6
6
  ]
7
7
 
8
8
  [workspace.package]
9
- version = "0.13.4"
9
+ version = "0.13.5"
10
10
  edition = "2021"
11
11
  license = "MIT"
12
12
  authors = ["polyglot contributors"]
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: polyglot-sql
3
- Version: 0.13.4
3
+ Version: 0.13.5
4
4
  Classifier: Development Status :: 4 - Beta
5
5
  Classifier: Intended Audience :: Developers
6
6
  Classifier: License :: OSI Approved :: MIT License
@@ -103,14 +103,14 @@ function-catalog-all-dialects = [
103
103
  ]
104
104
 
105
105
  [dependencies]
106
- polyglot-sql-ast-derive = { path = "../polyglot-sql-ast-derive", version = "0.13.4" }
106
+ polyglot-sql-ast-derive = { path = "../polyglot-sql-ast-derive", version = "0.13.5" }
107
107
  serde = { workspace = true }
108
108
  serde_json = { workspace = true }
109
109
  thiserror = { workspace = true }
110
110
  unicode-segmentation = { workspace = true }
111
111
  stacker = { version = "0.1", optional = true }
112
112
  ts-rs = { version = "12.0", features = ["serde-compat"], optional = true }
113
- polyglot-sql-function-catalogs = { path = "../polyglot-sql-function-catalogs", version = "0.13.4", optional = true, default-features = false }
113
+ polyglot-sql-function-catalogs = { path = "../polyglot-sql-function-catalogs", version = "0.13.5", optional = true, default-features = false }
114
114
 
115
115
  [dev-dependencies]
116
116
  pretty_assertions = "1.4"
@@ -25,12 +25,12 @@ By default, `polyglot-sql` enables the full public API. Parser-only consumers ca
25
25
  disable default features and opt into only the dialect parsers they need:
26
26
 
27
27
  ```toml
28
- polyglot-sql = { version = "0.13.4", default-features = false }
28
+ polyglot-sql = { version = "0.13.5", default-features = false }
29
29
  ```
30
30
 
31
31
  ```toml
32
32
  polyglot-sql = {
33
- version = "0.13.4",
33
+ version = "0.13.5",
34
34
  default-features = false,
35
35
  features = ["dialect-clickhouse"],
36
36
  }
@@ -44,14 +44,14 @@ Examples:
44
44
  ```toml
45
45
  # Parse and generate SQL for one dialect.
46
46
  polyglot-sql = {
47
- version = "0.13.4",
47
+ version = "0.13.5",
48
48
  default-features = false,
49
49
  features = ["generate", "dialect-clickhouse"],
50
50
  }
51
51
 
52
52
  # Cross-dialect transpilation.
53
53
  polyglot-sql = {
54
- version = "0.13.4",
54
+ version = "0.13.5",
55
55
  default-features = false,
56
56
  features = ["transpile", "dialect-clickhouse", "dialect-postgresql"],
57
57
  }
@@ -757,8 +757,8 @@ fn query_output_width(e: &Expression) -> Option<usize> {
757
757
  /// The source's explicit direction and NULL order (if any) carry over to each
758
758
  /// positional entry unchanged; the later cross-dialect NULL-ordering pass
759
759
  /// fills in the source dialect's implied default where the target's differs.
760
- /// MySQL is the exception: it has no NULLS FIRST/LAST syntax and is skipped by
761
- /// that pass, so compare every supported source's default against MySQL here.
760
+ /// MySQL additionally checks placement here because a known width alone does
761
+ /// not establish that every generated ordinal can be resolved to an expression.
762
762
  #[cfg(feature = "transpile")]
763
763
  fn expand_order_by_all(
764
764
  order_by: &mut Option<crate::expressions::OrderBy>,
@@ -800,11 +800,8 @@ fn expand_order_by_all(
800
800
  .map(|i| {
801
801
  let mut o = ob.expressions[0].clone();
802
802
  o.this = E::number(i);
803
- if target == DialectType::MySQL {
804
- // Matching explicit NULL placement is redundant and MySQL
805
- // cannot print the NULLS FIRST/LAST syntax.
806
- o.nulls_first = None;
807
- }
803
+ // Keep explicit placement until generation. Clearing it here would
804
+ // make normalization substitute the source dialect's implicit default.
808
805
  o
809
806
  })
810
807
  .collect();
@@ -3440,6 +3437,7 @@ impl Dialect {
3440
3437
  feature = "dialect-sqlite",
3441
3438
  feature = "dialect-trino",
3442
3439
  feature = "dialect-presto",
3440
+ feature = "dialect-athena",
3443
3441
  feature = "dialect-duckdb",
3444
3442
  feature = "dialect-redshift",
3445
3443
  feature = "dialect-starrocks",
@@ -3583,6 +3581,12 @@ impl Dialect {
3583
3581
  let expr = transforms::explode_projection_to_unnest(expr, DialectType::Presto)?;
3584
3582
  Ok(expr)
3585
3583
  }
3584
+ #[cfg(feature = "dialect-athena")]
3585
+ DialectType::Athena => {
3586
+ let expr = transforms::eliminate_qualify(expr)?;
3587
+ let expr = transforms::eliminate_window_clause(expr)?;
3588
+ transforms::explode_projection_to_unnest(expr, DialectType::Athena)
3589
+ }
3586
3590
  // DuckDB supports QUALIFY - no elimination needed
3587
3591
  // Expand POSEXPLODE to GENERATE_SUBSCRIPTS + UNNEST
3588
3592
  // Expand LIKE ANY / ILIKE ANY to OR chains (DuckDB doesn't support quantifiers)
@@ -3592,15 +3596,14 @@ impl Dialect {
3592
3596
  let expr = transforms::expand_like_any(expr)?;
3593
3597
  Ok(expr)
3594
3598
  }
3595
- // Redshift doesn't support QUALIFY, WINDOW clause, or GENERATE_DATE_ARRAY
3599
+ // Redshift supports QUALIFY, but not WINDOW or GENERATE_DATE_ARRAY.
3596
3600
  #[cfg(feature = "dialect-redshift")]
3597
3601
  DialectType::Redshift => {
3598
- let expr = transforms::eliminate_qualify(expr)?;
3599
3602
  let expr = transforms::eliminate_window_clause(expr)?;
3600
3603
  let expr = transforms::unnest_generate_date_array_using_recursive_cte(expr)?;
3601
3604
  Ok(expr)
3602
3605
  }
3603
- // StarRocks doesn't support BETWEEN in DELETE statements or QUALIFY
3606
+ // StarRocks supports only restricted QUALIFY forms; lower the general form.
3604
3607
  #[cfg(feature = "dialect-starrocks")]
3605
3608
  DialectType::StarRocks => {
3606
3609
  let expr = transforms::eliminate_qualify(expr)?;
@@ -4333,6 +4336,11 @@ impl Dialect {
4333
4336
  normalized
4334
4337
  };
4335
4338
 
4339
+ let normalized = crate::transforms::lower_set_operations_by_name(
4340
+ normalized,
4341
+ self.dialect_type,
4342
+ target,
4343
+ )?;
4336
4344
  let transformed =
4337
4345
  target_dialect.transform_with_guard(normalized, opts.complexity_guard)?;
4338
4346
 
@@ -2746,33 +2746,13 @@ pub(super) fn normalize(
2746
2746
  // When nulls_first is not specified, fill in the source dialect's implied
2747
2747
  // default so the target generator can correctly add/strip NULLS FIRST/LAST.
2748
2748
  Expression::Ordered(o) => {
2749
- // MySQL doesn't support NULLS FIRST/LAST - strip or rewrite
2750
- if matches!(target, DialectType::MySQL) && o.nulls_first.is_some() {
2751
- Action::Operators(operators::Action::MysqlNullsOrdering)
2749
+ if o.nulls_first.is_none()
2750
+ && source != target
2751
+ && source != DialectType::Vertica
2752
+ {
2753
+ Action::Operators(operators::Action::NullsOrdering)
2752
2754
  } else {
2753
- // Skip targets that don't support NULLS FIRST/LAST syntax unless
2754
- // the generator can preserve semantics with a CASE sort key.
2755
- let target_rewrites_nulls =
2756
- matches!(target, DialectType::TSQL | DialectType::Fabric);
2757
- let target_supports_nulls = !matches!(
2758
- target,
2759
- DialectType::MySQL
2760
- | DialectType::TSQL
2761
- | DialectType::Fabric
2762
- | DialectType::StarRocks
2763
- | DialectType::Doris
2764
- );
2765
- // Vertica's implicit NULL placement depends on the sort key's data
2766
- // type (NULLS AUTO), so there is no source default to make explicit.
2767
- if o.nulls_first.is_none()
2768
- && source != target
2769
- && source != DialectType::Vertica
2770
- && (target_supports_nulls || target_rewrites_nulls)
2771
- {
2772
- Action::Operators(operators::Action::NullsOrdering)
2773
- } else {
2774
- Action::None
2775
- }
2755
+ Action::None
2776
2756
  }
2777
2757
  }
2778
2758
  // BigQuery data types: convert INT64, BYTES, NUMERIC etc. to standard types
@@ -3556,7 +3536,6 @@ pub(super) fn normalize(
3556
3536
  Action::Collections(collections::Action::ArrayIndexConvert)
3557
3537
  }
3558
3538
  // ANY_VALUE IGNORE NULLS detection moved to the AnyValue arm above
3559
- // MysqlNullsOrdering for Ordered is now handled in the Ordered arm above
3560
3539
  // RESPECT NULLS handling for SQLite (strip it, add NULLS LAST to ORDER BY)
3561
3540
  // and for MySQL (rewrite ORDER BY with CASE WHEN for null ordering)
3562
3541
  Expression::WindowFunction(ref wf) => {
@@ -3569,25 +3548,7 @@ pub(super) fn normalize(
3569
3548
  && wf.over.order_by.iter().any(|o| o.nulls_first.is_some())
3570
3549
  {
3571
3550
  Action::Operators(operators::Action::BigQueryNullsOrdering)
3572
- // DuckDB -> MySQL: Add CASE WHEN for NULLS LAST simulation in window ORDER BY
3573
- // But NOT when frame is RANGE/GROUPS, since adding CASE WHEN would break value-based frames
3574
3551
  } else {
3575
- let source_nulls_last = matches!(source, DialectType::DuckDB);
3576
- let has_range_frame = wf.over.frame.as_ref().map_or(false, |f| {
3577
- matches!(
3578
- f.kind,
3579
- crate::expressions::WindowFrameKind::Range
3580
- | crate::expressions::WindowFrameKind::Groups
3581
- )
3582
- });
3583
- if source_nulls_last
3584
- && matches!(target, DialectType::MySQL)
3585
- && !wf.over.order_by.is_empty()
3586
- && wf.over.order_by.iter().any(|o| !o.desc)
3587
- && !has_range_frame
3588
- {
3589
- Action::Scalar(scalar::Action::MysqlNullsLastRewrite)
3590
- } else {
3591
3552
  // Check for Snowflake window frame handling for FIRST_VALUE/LAST_VALUE/NTH_VALUE
3592
3553
  let is_ranking_window_func = matches!(
3593
3554
  &wf.this,
@@ -3639,7 +3600,6 @@ pub(super) fn normalize(
3639
3600
  _ => Action::None,
3640
3601
  }
3641
3602
  }
3642
- }
3643
3603
  }
3644
3604
  }
3645
3605
  // CREATE TABLE a LIKE b -> dialect-specific transformations
@@ -20,7 +20,6 @@ pub(super) enum Action {
20
20
  DollarParamConvert,
21
21
  AnyToExists,
22
22
  RespectNullsConvert,
23
- MysqlNullsOrdering,
24
23
  BigQueryNullsOrdering,
25
24
  PipeConcatToConcat,
26
25
  PostgresPipeConcatToTsql,
@@ -691,57 +690,6 @@ pub(super) fn rewrite(
691
690
  }
692
691
  }
693
692
 
694
- Action::MysqlNullsOrdering => {
695
- // MySQL doesn't support NULLS FIRST/LAST - strip or rewrite
696
- if let Expression::Ordered(mut o) = e {
697
- let nulls_last = o.nulls_first == Some(false);
698
- let desc = o.desc;
699
- // MySQL default: ASC -> NULLS LAST, DESC -> NULLS FIRST
700
- // If requested ordering matches default, just strip NULLS clause
701
- let matches_default = if desc {
702
- // DESC default is NULLS FIRST, so nulls_first=true matches
703
- o.nulls_first == Some(true)
704
- } else {
705
- // ASC default is NULLS LAST, so nulls_first=false matches
706
- nulls_last
707
- };
708
- if matches_default {
709
- o.nulls_first = None;
710
- Ok(Expression::Ordered(o))
711
- } else {
712
- // Need CASE WHEN x IS NULL THEN 0/1 ELSE 0/1 END, x
713
- // For ASC NULLS FIRST: ORDER BY CASE WHEN x IS NULL THEN 0 ELSE 1 END, x ASC
714
- // For DESC NULLS LAST: ORDER BY CASE WHEN x IS NULL THEN 1 ELSE 0 END, x DESC
715
- let null_val = if desc { 1 } else { 0 };
716
- let non_null_val = if desc { 0 } else { 1 };
717
- let _case_expr = Expression::Case(Box::new(Case {
718
- operand: None,
719
- whens: vec![(
720
- Expression::IsNull(Box::new(crate::expressions::IsNull {
721
- this: o.this.clone(),
722
- not: false,
723
- postfix_form: false,
724
- })),
725
- Expression::number(null_val),
726
- )],
727
- else_: Some(Expression::number(non_null_val)),
728
- comments: Vec::new(),
729
- inferred_type: None,
730
- }));
731
- o.nulls_first = None;
732
- // Return a tuple of [case_expr, ordered_expr]
733
- // We need to return both as part of the ORDER BY
734
- // But since transform_recursive processes individual expressions,
735
- // we can't easily add extra ORDER BY items here.
736
- // Instead, strip the nulls_first
737
- o.nulls_first = None;
738
- Ok(Expression::Ordered(o))
739
- }
740
- } else {
741
- Ok(e)
742
- }
743
- }
744
-
745
693
  Action::BigQueryNullsOrdering => {
746
694
  // BigQuery doesn't support NULLS FIRST/LAST in window function ORDER BY
747
695
  if let Expression::WindowFunction(mut wf) = e {
@@ -73,7 +73,6 @@ pub(super) enum Action {
73
73
  CurrentUserParens,
74
74
  EscapeStringNormalize,
75
75
  SnowflakeIntervalFormat,
76
- MysqlNullsLastRewrite,
77
76
  FilterToIff,
78
77
  StrPositionExpand,
79
78
  CurrentUserSparkParens,
@@ -11247,57 +11246,6 @@ pub(super) fn rewrite(
11247
11246
  }
11248
11247
  }
11249
11248
 
11250
- Action::MysqlNullsLastRewrite => {
11251
- // DuckDB -> MySQL: Add CASE WHEN IS NULL THEN 1 ELSE 0 END to ORDER BY
11252
- // to simulate NULLS LAST for ASC ordering
11253
- if let Expression::WindowFunction(mut wf) = e {
11254
- let mut new_order_by = Vec::new();
11255
- for o in wf.over.order_by {
11256
- if !o.desc {
11257
- // ASC: DuckDB has NULLS LAST, MySQL has NULLS FIRST
11258
- // Add CASE WHEN expr IS NULL THEN 1 ELSE 0 END before expr
11259
- let case_expr = Expression::Case(Box::new(Case {
11260
- operand: None,
11261
- whens: vec![(
11262
- Expression::IsNull(Box::new(crate::expressions::IsNull {
11263
- this: o.this.clone(),
11264
- not: false,
11265
- postfix_form: false,
11266
- })),
11267
- Expression::Literal(Box::new(Literal::Number("1".to_string()))),
11268
- )],
11269
- else_: Some(Expression::Literal(Box::new(Literal::Number(
11270
- "0".to_string(),
11271
- )))),
11272
- comments: Vec::new(),
11273
- inferred_type: None,
11274
- }));
11275
- new_order_by.push(crate::expressions::Ordered {
11276
- nulls_auto: false,
11277
- this: case_expr,
11278
- desc: false,
11279
- nulls_first: None,
11280
- explicit_asc: false,
11281
- with_fill: None,
11282
- });
11283
- let mut ordered = o;
11284
- ordered.nulls_first = None;
11285
- new_order_by.push(ordered);
11286
- } else {
11287
- // DESC: DuckDB has NULLS LAST, MySQL also has NULLS LAST (NULLs smallest in DESC)
11288
- // No change needed
11289
- let mut ordered = o;
11290
- ordered.nulls_first = None;
11291
- new_order_by.push(ordered);
11292
- }
11293
- }
11294
- wf.over.order_by = new_order_by;
11295
- Ok(Expression::WindowFunction(wf))
11296
- } else {
11297
- Ok(e)
11298
- }
11299
- }
11300
-
11301
11249
  Action::FilterToIff => {
11302
11250
  // FILTER(WHERE cond) -> rewrite aggregate: AGG(IFF(cond, val, NULL))
11303
11251
  if let Expression::Filter(f) = e {
@@ -50,7 +50,7 @@ impl DialectImpl for StarRocksDialect {
50
50
  // StarRocks: PROPERTIES prefix for WITH properties
51
51
  with_properties_prefix: "PROPERTIES",
52
52
  // StarRocks uses MySQL-style settings
53
- null_ordering_supported: false,
53
+ null_ordering_supported: true,
54
54
  limit_only_literals: true,
55
55
  semi_anti_join_with_side: false,
56
56
  supports_table_alias_columns: false,
@@ -3681,6 +3681,186 @@ pub struct Star {
3681
3681
  pub span: Option<Span>,
3682
3682
  }
3683
3683
 
3684
+ impl Star {
3685
+ /// Apply EXCEPT, REPLACE, and RENAME to the expanded `column` named `name`.
3686
+ /// Returns `None` when EXCEPT removes the column.
3687
+ #[cfg(feature = "semantic")]
3688
+ pub(crate) fn expand_column(
3689
+ &self,
3690
+ name: &str,
3691
+ column: Expression,
3692
+ dialect: Option<crate::dialects::DialectType>,
3693
+ ) -> Option<Expression> {
3694
+ if self.excludes(name, dialect) {
3695
+ return None;
3696
+ }
3697
+ let renamed = self.renamed(name, dialect);
3698
+ if let Some(replacement) = self.replacement(name, dialect) {
3699
+ let mut replacement = replacement.clone();
3700
+ if let Some(alias) = renamed {
3701
+ replacement.alias = alias;
3702
+ }
3703
+ return Some(Expression::Alias(Box::new(replacement)));
3704
+ }
3705
+ Some(match renamed {
3706
+ Some(alias) => Expression::Alias(Box::new(Alias::new(column, alias))),
3707
+ None => column,
3708
+ })
3709
+ }
3710
+
3711
+ /// Whether EXCEPT holds a ClickHouse pattern string (`EXCEPT ('re')`).
3712
+ /// The columns it removes are not known, so the star stays unexpanded.
3713
+ #[cfg(any(feature = "semantic", test))]
3714
+ pub(crate) fn has_except_pattern(&self) -> bool {
3715
+ self.except.iter().flatten().any(is_except_pattern)
3716
+ }
3717
+
3718
+ /// Whether EXCEPT / EXCLUDE removes the column `name`.
3719
+ #[cfg(feature = "semantic")]
3720
+ pub(crate) fn excludes(
3721
+ &self,
3722
+ name: &str,
3723
+ dialect: Option<crate::dialects::DialectType>,
3724
+ ) -> bool {
3725
+ self.except
3726
+ .iter()
3727
+ .flatten()
3728
+ .any(|column| star_modifier_matches(column, name, dialect))
3729
+ }
3730
+
3731
+ /// The new name RENAME gives to the column `name`. With a known dialect,
3732
+ /// the name gets the identifier normalization that schema columns get.
3733
+ #[cfg(feature = "semantic")]
3734
+ pub(crate) fn renamed(
3735
+ &self,
3736
+ name: &str,
3737
+ dialect: Option<crate::dialects::DialectType>,
3738
+ ) -> Option<Identifier> {
3739
+ let (_, new) = self
3740
+ .rename
3741
+ .iter()
3742
+ .flatten()
3743
+ .find(|(old, _)| star_modifier_matches(old, name, dialect))?;
3744
+ Some(match dialect {
3745
+ Some(_) => crate::optimizer::normalize_identifiers::normalize_identifier(
3746
+ new.clone(),
3747
+ crate::optimizer::normalize_identifiers::get_normalization_strategy(dialect),
3748
+ ),
3749
+ None => new.clone(),
3750
+ })
3751
+ }
3752
+
3753
+ /// The REPLACE expression for the column `name`.
3754
+ #[cfg(feature = "semantic")]
3755
+ pub(crate) fn replacement(
3756
+ &self,
3757
+ name: &str,
3758
+ dialect: Option<crate::dialects::DialectType>,
3759
+ ) -> Option<&Alias> {
3760
+ self.replace
3761
+ .iter()
3762
+ .flatten()
3763
+ .find(|replacement| star_modifier_matches(&replacement.alias, name, dialect))
3764
+ }
3765
+
3766
+ /// The source column that the star outputs as `output`, after RENAME and
3767
+ /// EXCEPT. Returns `None` when the star does not output `output`.
3768
+ #[cfg(feature = "semantic")]
3769
+ pub(crate) fn source_column(
3770
+ &self,
3771
+ output: &str,
3772
+ dialect: Option<crate::dialects::DialectType>,
3773
+ ) -> Option<String> {
3774
+ let renames = self.rename.iter().flatten();
3775
+ let column = match renames
3776
+ .clone()
3777
+ .find(|(_, new)| star_modifier_matches(new, output, dialect))
3778
+ {
3779
+ Some((old, _)) => old.name.clone(),
3780
+ None if renames
3781
+ .clone()
3782
+ .any(|(old, _)| star_modifier_matches(old, output, dialect)) =>
3783
+ {
3784
+ return None
3785
+ }
3786
+ None => output.to_string(),
3787
+ };
3788
+ (!self.excludes(&column, dialect)).then_some(column)
3789
+ }
3790
+ }
3791
+
3792
+ /// A pattern string keeps its quotes in the name (see `parse_star_except_name`).
3793
+ #[cfg(any(feature = "semantic", test))]
3794
+ fn is_except_pattern(identifier: &Identifier) -> bool {
3795
+ !identifier.quoted && identifier.name.starts_with('\'')
3796
+ }
3797
+
3798
+ /// Match a modifier name to the column `name`. A quoted name matches with
3799
+ /// its case, unless the dialect ignores case. An unquoted name ignores case,
3800
+ /// unless the dialect is case sensitive. A qualified name such as `t.col`
3801
+ /// matches on its column part, as in sqlglot. A pattern string never matches.
3802
+ #[cfg(feature = "semantic")]
3803
+ fn star_modifier_matches(
3804
+ identifier: &Identifier,
3805
+ name: &str,
3806
+ dialect: Option<crate::dialects::DialectType>,
3807
+ ) -> bool {
3808
+ use crate::optimizer::normalize_identifiers::{
3809
+ get_normalization_strategy, NormalizationStrategy,
3810
+ };
3811
+ use std::borrow::Cow;
3812
+ if is_except_pattern(identifier) {
3813
+ return false;
3814
+ }
3815
+ let text = identifier.name.as_str();
3816
+ let (column, quoted) = if identifier.quoted {
3817
+ (Cow::Borrowed(text), true)
3818
+ } else if let Some(quote) = text.chars().last().filter(|c| matches!(c, '"' | '`')) {
3819
+ // A qualified name keeps the quotes of its parts: `t."col"`.
3820
+ let body = &text[..text.len() - 1];
3821
+ let mut chars = body.char_indices().rev().peekable();
3822
+ let mut opening = None;
3823
+ while let Some((index, ch)) = chars.next() {
3824
+ if ch == quote {
3825
+ if chars.peek().is_some_and(|(_, next)| *next == quote) {
3826
+ chars.next(); // Skip an escaped quote inside the identifier.
3827
+ } else {
3828
+ opening = Some(index);
3829
+ break;
3830
+ }
3831
+ }
3832
+ }
3833
+ match opening {
3834
+ Some(open) => (
3835
+ Cow::Owned(
3836
+ body[open + 1..].replace(&format!("{quote}{quote}"), &quote.to_string()),
3837
+ ),
3838
+ true,
3839
+ ),
3840
+ None => (Cow::Borrowed(text), false),
3841
+ }
3842
+ } else {
3843
+ (
3844
+ Cow::Borrowed(text.rsplit_once('.').map_or(text, |(_, column)| column)),
3845
+ false,
3846
+ )
3847
+ };
3848
+ let strategy = dialect.map(|dialect| get_normalization_strategy(Some(dialect)));
3849
+ let exact = match strategy {
3850
+ Some(NormalizationStrategy::CaseSensitive) => true,
3851
+ Some(
3852
+ NormalizationStrategy::CaseInsensitive
3853
+ | NormalizationStrategy::CaseInsensitiveUppercase,
3854
+ ) => false,
3855
+ _ => quoted,
3856
+ };
3857
+ if exact {
3858
+ column == name
3859
+ } else {
3860
+ column.eq_ignore_ascii_case(name)
3861
+ }
3862
+ }
3863
+
3684
3864
  /// Represent a complete SELECT statement.
3685
3865
  ///
3686
3866
  /// This is the most feature-rich AST node, covering the full surface area of