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.
Files changed (199) hide show
  1. {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/Cargo.lock +6 -6
  2. {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/Cargo.toml +1 -1
  3. {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/PKG-INFO +1 -1
  4. {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/Cargo.toml +2 -2
  5. {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/README.md +1 -1
  6. {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/src/dialects/mod.rs +185 -8
  7. {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/src/dialects/normalization/mod.rs +42 -2
  8. {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/src/dialects/normalization/statements.rs +19 -0
  9. {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/src/dialects/normalization/temporal.rs +169 -0
  10. {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/src/dialects/normalization/types.rs +81 -0
  11. {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/src/transforms.rs +9 -2
  12. {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/tests/dialect_matrix.rs +311 -0
  13. {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/tests/fabric_regression.rs +8 -0
  14. {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/tests/tsql_regression.rs +8 -0
  15. {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql-ast-derive/Cargo.toml +3 -1
  16. {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/README.md +0 -0
  17. {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/benches/allocation_hotspots.rs +0 -0
  18. {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/benches/ast_traversal.rs +0 -0
  19. {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/benches/in_list.rs +0 -0
  20. {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/benches/parsing.rs +0 -0
  21. {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/benches/performance_hotspots.rs +0 -0
  22. {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/benches/rust_parsing.rs +0 -0
  23. {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/benches/transpile.rs +0 -0
  24. {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/examples/basic_usage.rs +0 -0
  25. {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/examples/bench_json.rs +0 -0
  26. {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/src/ast_children.rs +0 -0
  27. {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/src/ast_json.rs +0 -0
  28. {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/src/ast_transforms.rs +0 -0
  29. {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/src/builder.rs +0 -0
  30. {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/src/dialects/athena.rs +0 -0
  31. {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/src/dialects/bigquery.rs +0 -0
  32. {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/src/dialects/clickhouse.rs +0 -0
  33. {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/src/dialects/cockroachdb.rs +0 -0
  34. {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/src/dialects/databricks.rs +0 -0
  35. {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/src/dialects/datafusion.rs +0 -0
  36. {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/src/dialects/doris.rs +0 -0
  37. {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/src/dialects/dremio.rs +0 -0
  38. {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/src/dialects/drill.rs +0 -0
  39. {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/src/dialects/druid.rs +0 -0
  40. {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/src/dialects/duckdb.rs +0 -0
  41. {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/src/dialects/dune.rs +0 -0
  42. {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/src/dialects/exasol.rs +0 -0
  43. {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/src/dialects/fabric.rs +0 -0
  44. {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/src/dialects/generic.rs +0 -0
  45. {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/src/dialects/hive.rs +0 -0
  46. {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/src/dialects/materialize.rs +0 -0
  47. {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/src/dialects/mysql.rs +0 -0
  48. {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/src/dialects/normalization/aggregates.rs +0 -0
  49. {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/src/dialects/normalization/collections.rs +0 -0
  50. {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/src/dialects/normalization/json.rs +0 -0
  51. {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/src/dialects/normalization/operators.rs +0 -0
  52. {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/src/dialects/normalization/scalar.rs +0 -0
  53. {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/src/dialects/oracle.rs +0 -0
  54. {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/src/dialects/postgres.rs +0 -0
  55. {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/src/dialects/presto.rs +0 -0
  56. {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/src/dialects/redshift.rs +0 -0
  57. {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/src/dialects/risingwave.rs +0 -0
  58. {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/src/dialects/singlestore.rs +0 -0
  59. {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/src/dialects/snowflake.rs +0 -0
  60. {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/src/dialects/solr.rs +0 -0
  61. {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/src/dialects/spark.rs +0 -0
  62. {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/src/dialects/sqlite.rs +0 -0
  63. {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/src/dialects/starrocks.rs +0 -0
  64. {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/src/dialects/tableau.rs +0 -0
  65. {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/src/dialects/teradata.rs +0 -0
  66. {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/src/dialects/tidb.rs +0 -0
  67. {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/src/dialects/trino.rs +0 -0
  68. {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/src/dialects/tsql.rs +0 -0
  69. {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/src/diff.rs +0 -0
  70. {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/src/error.rs +0 -0
  71. {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/src/expressions.rs +0 -0
  72. {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/src/format_tokens.rs +0 -0
  73. {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/src/function_catalog.rs +0 -0
  74. {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/src/function_registry.rs +0 -0
  75. {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/src/generator.rs +0 -0
  76. {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/src/guard.rs +0 -0
  77. {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/src/helper.rs +0 -0
  78. {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/src/lib.rs +0 -0
  79. {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/src/lineage.rs +0 -0
  80. {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/src/openlineage.rs +0 -0
  81. {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/src/optimizer/annotate_types.rs +0 -0
  82. {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/src/optimizer/canonicalize.rs +0 -0
  83. {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/src/optimizer/eliminate_ctes.rs +0 -0
  84. {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/src/optimizer/eliminate_joins.rs +0 -0
  85. {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/src/optimizer/isolate_table_selects.rs +0 -0
  86. {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/src/optimizer/mod.rs +0 -0
  87. {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/src/optimizer/normalize.rs +0 -0
  88. {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/src/optimizer/normalize_identifiers.rs +0 -0
  89. {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/src/optimizer/optimize_joins.rs +0 -0
  90. {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/src/optimizer/optimizer.rs +0 -0
  91. {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/src/optimizer/pushdown_predicates.rs +0 -0
  92. {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/src/optimizer/pushdown_projections.rs +0 -0
  93. {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/src/optimizer/qualify_columns.rs +0 -0
  94. {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/src/optimizer/qualify_tables.rs +0 -0
  95. {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/src/optimizer/simplify.rs +0 -0
  96. {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/src/optimizer/subquery.rs +0 -0
  97. {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/src/parser.rs +0 -0
  98. {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/src/planner.rs +0 -0
  99. {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/src/query_analysis.rs +0 -0
  100. {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/src/resolver.rs +0 -0
  101. {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/src/schema.rs +0 -0
  102. {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/src/scope.rs +0 -0
  103. {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/src/time.rs +0 -0
  104. {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/src/tokens.rs +0 -0
  105. {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/src/traversal.rs +0 -0
  106. {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/src/trie.rs +0 -0
  107. {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/src/validation/tests.rs +0 -0
  108. {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/src/validation.rs +0 -0
  109. {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/tests/analyze_failures.rs +0 -0
  110. {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/tests/clickhouse_regression.rs +0 -0
  111. {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/tests/common/known_failures.rs +0 -0
  112. {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/tests/common/mod.rs +0 -0
  113. {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/tests/common/test_data.rs +0 -0
  114. {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/tests/common/test_runner.rs +0 -0
  115. {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/tests/create_view_security_comment_regression.rs +0 -0
  116. {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/tests/custom_clickhouse_coverage.rs +0 -0
  117. {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/tests/custom_clickhouse_parser.rs +0 -0
  118. {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/tests/custom_dialect.rs +0 -0
  119. {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/tests/custom_dialect_tests.rs +0 -0
  120. {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/tests/custom_fixtures/datafusion/ddl.json +0 -0
  121. {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/tests/custom_fixtures/datafusion/dml.json +0 -0
  122. {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/tests/custom_fixtures/datafusion/functions.json +0 -0
  123. {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/tests/custom_fixtures/datafusion/identity.json +0 -0
  124. {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/tests/custom_fixtures/datafusion/operators.json +0 -0
  125. {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/tests/custom_fixtures/datafusion/select.json +0 -0
  126. {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/tests/custom_fixtures/datafusion/transpilation.json +0 -0
  127. {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/tests/custom_fixtures/datafusion/types.json +0 -0
  128. {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/tests/data_type_api.rs +0 -0
  129. {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/tests/deep_nesting_regression.rs +0 -0
  130. {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/tests/error_handling.rs +0 -0
  131. {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/tests/fabric_tpch_regression.rs +0 -0
  132. {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/tests/identity_roundtrip.rs +0 -0
  133. {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/tests/postgres_regexp_clickhouse.rs +0 -0
  134. {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/tests/postgres_sqlite_regression.rs +0 -0
  135. {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/tests/query_analysis.rs +0 -0
  136. {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/tests/query_analysis_regression.rs +0 -0
  137. {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/tests/snowflake_regression_test.rs +0 -0
  138. {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/tests/sqlglot_compat.rs +0 -0
  139. {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/tests/sqlglot_dialect_identity.rs +0 -0
  140. {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/tests/sqlglot_identity.rs +0 -0
  141. {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/tests/sqlglot_identity_detailed.rs +0 -0
  142. {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/tests/sqlglot_parser.rs +0 -0
  143. {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/tests/sqlglot_pretty.rs +0 -0
  144. {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/tests/sqlglot_transpilation.rs +0 -0
  145. {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/tests/sqlglot_transpile.rs +0 -0
  146. {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/tests/tpch_transpile_stack.rs +0 -0
  147. {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql/tests/transform_regression.rs +0 -0
  148. {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql-ast-derive/src/lib.rs +0 -0
  149. {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql-function-catalogs/Cargo.toml +0 -0
  150. {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql-function-catalogs/README.md +0 -0
  151. {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql-function-catalogs/src/clickhouse.rs +0 -0
  152. {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql-function-catalogs/src/duckdb.rs +0 -0
  153. {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql-function-catalogs/src/lib.rs +0 -0
  154. {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql-function-catalogs/tools/clickhouse/extract_functions.py +0 -0
  155. {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql-function-catalogs/tools/duckdb/extract_functions.py +0 -0
  156. {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql-python/Cargo.toml +0 -0
  157. {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql-python/README.md +0 -0
  158. {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql-python/docs/api.md +0 -0
  159. {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql-python/docs/index.md +0 -0
  160. {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql-python/mkdocs.yml +0 -0
  161. {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql-python/src/annotate_types.rs +0 -0
  162. {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql-python/src/dialects.rs +0 -0
  163. {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql-python/src/diff.rs +0 -0
  164. {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql-python/src/errors.rs +0 -0
  165. {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql-python/src/expr.rs +0 -0
  166. {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql-python/src/expr_types.rs +0 -0
  167. {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql-python/src/format.rs +0 -0
  168. {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql-python/src/generate.rs +0 -0
  169. {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql-python/src/helpers.rs +0 -0
  170. {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql-python/src/lib.rs +0 -0
  171. {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql-python/src/lineage.rs +0 -0
  172. {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql-python/src/openlineage.rs +0 -0
  173. {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql-python/src/optimize.rs +0 -0
  174. {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql-python/src/parse.rs +0 -0
  175. {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql-python/src/query_analysis.rs +0 -0
  176. {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql-python/src/tokenize.rs +0 -0
  177. {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql-python/src/transforms.rs +0 -0
  178. {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql-python/src/transpile.rs +0 -0
  179. {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql-python/src/types.rs +0 -0
  180. {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql-python/src/validate.rs +0 -0
  181. {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql-python/tests/conftest.py +0 -0
  182. {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql-python/tests/test_compat.py +0 -0
  183. {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql-python/tests/test_dialects.py +0 -0
  184. {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql-python/tests/test_diff.py +0 -0
  185. {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql-python/tests/test_expression.py +0 -0
  186. {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql-python/tests/test_format.py +0 -0
  187. {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql-python/tests/test_generate.py +0 -0
  188. {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql-python/tests/test_lineage.py +0 -0
  189. {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql-python/tests/test_optimize.py +0 -0
  190. {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql-python/tests/test_parse.py +0 -0
  191. {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql-python/tests/test_query_analysis.py +0 -0
  192. {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql-python/tests/test_transforms.py +0 -0
  193. {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql-python/tests/test_transpile.py +0 -0
  194. {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql-python/tests/test_validate.py +0 -0
  195. {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/crates/polyglot-sql-python/uv.lock +0 -0
  196. {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/pyproject.toml +0 -0
  197. {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/python/polyglot_sql/__init__.py +0 -0
  198. {polyglot_sql-0.6.0 → polyglot_sql-0.6.1}/python/polyglot_sql/__init__.pyi +0 -0
  199. {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.0"
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.0"
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.0"
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.0"
645
+ version = "0.6.1"
646
646
 
647
647
  [[package]]
648
648
  name = "polyglot-sql-python"
649
- version = "0.6.0"
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.0"
660
+ version = "0.6.1"
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.6.0"
9
+ version = "0.6.1"
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.6.0
3
+ Version: 0.6.1
4
4
  Classifier: Development Status :: 4 - Beta
5
5
  Classifier: Intended Audience :: Developers
6
6
  Classifier: License :: OSI Approved :: MIT License
@@ -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.0", optional = true, default-features = false }
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.0", default-features = false }
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(expr: Expression) -> Result<Expression> {
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
- return Ok(Expression::Cast(Box::new(Cast {
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
- Ok((
6135
- Self::rewrite_tsql_boolean_predicate_context(condition)?,
6136
- Self::rewrite_tsql_boolean_scalar_value(result)?,
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() {
@@ -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 name == "JSON"
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 c.format.is_some()
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 {
@@ -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 {