polyglot-sql 0.3.3__tar.gz → 0.3.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 (168) hide show
  1. {polyglot_sql-0.3.3 → polyglot_sql-0.3.5}/Cargo.lock +5 -5
  2. {polyglot_sql-0.3.3 → polyglot_sql-0.3.5}/Cargo.toml +1 -1
  3. {polyglot_sql-0.3.3 → polyglot_sql-0.3.5}/PKG-INFO +1 -1
  4. {polyglot_sql-0.3.3 → polyglot_sql-0.3.5}/crates/polyglot-sql/Cargo.toml +1 -1
  5. {polyglot_sql-0.3.3 → polyglot_sql-0.3.5}/crates/polyglot-sql/src/builder.rs +1 -0
  6. {polyglot_sql-0.3.3 → polyglot_sql-0.3.5}/crates/polyglot-sql/src/dialects/databricks.rs +106 -0
  7. {polyglot_sql-0.3.3 → polyglot_sql-0.3.5}/crates/polyglot-sql/src/dialects/fabric.rs +11 -22
  8. {polyglot_sql-0.3.3 → polyglot_sql-0.3.5}/crates/polyglot-sql/src/dialects/hive.rs +6 -0
  9. {polyglot_sql-0.3.3 → polyglot_sql-0.3.5}/crates/polyglot-sql/src/dialects/mod.rs +182 -4
  10. {polyglot_sql-0.3.3 → polyglot_sql-0.3.5}/crates/polyglot-sql/src/dialects/mysql.rs +23 -0
  11. {polyglot_sql-0.3.3 → polyglot_sql-0.3.5}/crates/polyglot-sql/src/dialects/snowflake.rs +31 -0
  12. {polyglot_sql-0.3.3 → polyglot_sql-0.3.5}/crates/polyglot-sql/src/dialects/spark.rs +6 -0
  13. {polyglot_sql-0.3.3 → polyglot_sql-0.3.5}/crates/polyglot-sql/src/dialects/sqlite.rs +201 -5
  14. {polyglot_sql-0.3.3 → polyglot_sql-0.3.5}/crates/polyglot-sql/src/dialects/tsql.rs +86 -4
  15. {polyglot_sql-0.3.3 → polyglot_sql-0.3.5}/crates/polyglot-sql/src/expressions.rs +4 -0
  16. {polyglot_sql-0.3.3 → polyglot_sql-0.3.5}/crates/polyglot-sql/src/generator.rs +69 -54
  17. {polyglot_sql-0.3.3 → polyglot_sql-0.3.5}/crates/polyglot-sql/src/parser.rs +225 -28
  18. {polyglot_sql-0.3.3 → polyglot_sql-0.3.5}/crates/polyglot-sql/tests/dialect_matrix.rs +84 -0
  19. polyglot_sql-0.3.5/crates/polyglot-sql/tests/fabric_regression.rs +85 -0
  20. polyglot_sql-0.3.5/crates/polyglot-sql/tests/postgres_sqlite_regression.rs +155 -0
  21. {polyglot_sql-0.3.3 → polyglot_sql-0.3.5}/crates/polyglot-sql/tests/snowflake_regression_test.rs +102 -0
  22. {polyglot_sql-0.3.3 → polyglot_sql-0.3.5}/crates/polyglot-sql/tests/tpch_transpile_stack.rs +5 -2
  23. polyglot_sql-0.3.5/crates/polyglot-sql/tests/tsql_regression.rs +85 -0
  24. {polyglot_sql-0.3.3 → polyglot_sql-0.3.5}/crates/polyglot-sql-python/tests/test_compat.py +2 -2
  25. {polyglot_sql-0.3.3 → polyglot_sql-0.3.5}/README.md +0 -0
  26. {polyglot_sql-0.3.3 → polyglot_sql-0.3.5}/crates/polyglot-sql/README.md +0 -0
  27. {polyglot_sql-0.3.3 → polyglot_sql-0.3.5}/crates/polyglot-sql/benches/in_list.rs +0 -0
  28. {polyglot_sql-0.3.3 → polyglot_sql-0.3.5}/crates/polyglot-sql/benches/parsing.rs +0 -0
  29. {polyglot_sql-0.3.3 → polyglot_sql-0.3.5}/crates/polyglot-sql/benches/rust_parsing.rs +0 -0
  30. {polyglot_sql-0.3.3 → polyglot_sql-0.3.5}/crates/polyglot-sql/benches/transpile.rs +0 -0
  31. {polyglot_sql-0.3.3 → polyglot_sql-0.3.5}/crates/polyglot-sql/examples/basic_usage.rs +0 -0
  32. {polyglot_sql-0.3.3 → polyglot_sql-0.3.5}/crates/polyglot-sql/examples/bench_json.rs +0 -0
  33. {polyglot_sql-0.3.3 → polyglot_sql-0.3.5}/crates/polyglot-sql/src/ast_transforms.rs +0 -0
  34. {polyglot_sql-0.3.3 → polyglot_sql-0.3.5}/crates/polyglot-sql/src/dialects/athena.rs +0 -0
  35. {polyglot_sql-0.3.3 → polyglot_sql-0.3.5}/crates/polyglot-sql/src/dialects/bigquery.rs +0 -0
  36. {polyglot_sql-0.3.3 → polyglot_sql-0.3.5}/crates/polyglot-sql/src/dialects/clickhouse.rs +0 -0
  37. {polyglot_sql-0.3.3 → polyglot_sql-0.3.5}/crates/polyglot-sql/src/dialects/cockroachdb.rs +0 -0
  38. {polyglot_sql-0.3.3 → polyglot_sql-0.3.5}/crates/polyglot-sql/src/dialects/datafusion.rs +0 -0
  39. {polyglot_sql-0.3.3 → polyglot_sql-0.3.5}/crates/polyglot-sql/src/dialects/doris.rs +0 -0
  40. {polyglot_sql-0.3.3 → polyglot_sql-0.3.5}/crates/polyglot-sql/src/dialects/dremio.rs +0 -0
  41. {polyglot_sql-0.3.3 → polyglot_sql-0.3.5}/crates/polyglot-sql/src/dialects/drill.rs +0 -0
  42. {polyglot_sql-0.3.3 → polyglot_sql-0.3.5}/crates/polyglot-sql/src/dialects/druid.rs +0 -0
  43. {polyglot_sql-0.3.3 → polyglot_sql-0.3.5}/crates/polyglot-sql/src/dialects/duckdb.rs +0 -0
  44. {polyglot_sql-0.3.3 → polyglot_sql-0.3.5}/crates/polyglot-sql/src/dialects/dune.rs +0 -0
  45. {polyglot_sql-0.3.3 → polyglot_sql-0.3.5}/crates/polyglot-sql/src/dialects/exasol.rs +0 -0
  46. {polyglot_sql-0.3.3 → polyglot_sql-0.3.5}/crates/polyglot-sql/src/dialects/generic.rs +0 -0
  47. {polyglot_sql-0.3.3 → polyglot_sql-0.3.5}/crates/polyglot-sql/src/dialects/materialize.rs +0 -0
  48. {polyglot_sql-0.3.3 → polyglot_sql-0.3.5}/crates/polyglot-sql/src/dialects/oracle.rs +0 -0
  49. {polyglot_sql-0.3.3 → polyglot_sql-0.3.5}/crates/polyglot-sql/src/dialects/postgres.rs +0 -0
  50. {polyglot_sql-0.3.3 → polyglot_sql-0.3.5}/crates/polyglot-sql/src/dialects/presto.rs +0 -0
  51. {polyglot_sql-0.3.3 → polyglot_sql-0.3.5}/crates/polyglot-sql/src/dialects/redshift.rs +0 -0
  52. {polyglot_sql-0.3.3 → polyglot_sql-0.3.5}/crates/polyglot-sql/src/dialects/risingwave.rs +0 -0
  53. {polyglot_sql-0.3.3 → polyglot_sql-0.3.5}/crates/polyglot-sql/src/dialects/singlestore.rs +0 -0
  54. {polyglot_sql-0.3.3 → polyglot_sql-0.3.5}/crates/polyglot-sql/src/dialects/solr.rs +0 -0
  55. {polyglot_sql-0.3.3 → polyglot_sql-0.3.5}/crates/polyglot-sql/src/dialects/starrocks.rs +0 -0
  56. {polyglot_sql-0.3.3 → polyglot_sql-0.3.5}/crates/polyglot-sql/src/dialects/tableau.rs +0 -0
  57. {polyglot_sql-0.3.3 → polyglot_sql-0.3.5}/crates/polyglot-sql/src/dialects/teradata.rs +0 -0
  58. {polyglot_sql-0.3.3 → polyglot_sql-0.3.5}/crates/polyglot-sql/src/dialects/tidb.rs +0 -0
  59. {polyglot_sql-0.3.3 → polyglot_sql-0.3.5}/crates/polyglot-sql/src/dialects/trino.rs +0 -0
  60. {polyglot_sql-0.3.3 → polyglot_sql-0.3.5}/crates/polyglot-sql/src/diff.rs +0 -0
  61. {polyglot_sql-0.3.3 → polyglot_sql-0.3.5}/crates/polyglot-sql/src/error.rs +0 -0
  62. {polyglot_sql-0.3.3 → polyglot_sql-0.3.5}/crates/polyglot-sql/src/function_catalog.rs +0 -0
  63. {polyglot_sql-0.3.3 → polyglot_sql-0.3.5}/crates/polyglot-sql/src/function_registry.rs +0 -0
  64. {polyglot_sql-0.3.3 → polyglot_sql-0.3.5}/crates/polyglot-sql/src/helper.rs +0 -0
  65. {polyglot_sql-0.3.3 → polyglot_sql-0.3.5}/crates/polyglot-sql/src/lib.rs +0 -0
  66. {polyglot_sql-0.3.3 → polyglot_sql-0.3.5}/crates/polyglot-sql/src/lineage.rs +0 -0
  67. {polyglot_sql-0.3.3 → polyglot_sql-0.3.5}/crates/polyglot-sql/src/optimizer/annotate_types.rs +0 -0
  68. {polyglot_sql-0.3.3 → polyglot_sql-0.3.5}/crates/polyglot-sql/src/optimizer/canonicalize.rs +0 -0
  69. {polyglot_sql-0.3.3 → polyglot_sql-0.3.5}/crates/polyglot-sql/src/optimizer/eliminate_ctes.rs +0 -0
  70. {polyglot_sql-0.3.3 → polyglot_sql-0.3.5}/crates/polyglot-sql/src/optimizer/eliminate_joins.rs +0 -0
  71. {polyglot_sql-0.3.3 → polyglot_sql-0.3.5}/crates/polyglot-sql/src/optimizer/isolate_table_selects.rs +0 -0
  72. {polyglot_sql-0.3.3 → polyglot_sql-0.3.5}/crates/polyglot-sql/src/optimizer/mod.rs +0 -0
  73. {polyglot_sql-0.3.3 → polyglot_sql-0.3.5}/crates/polyglot-sql/src/optimizer/normalize.rs +0 -0
  74. {polyglot_sql-0.3.3 → polyglot_sql-0.3.5}/crates/polyglot-sql/src/optimizer/normalize_identifiers.rs +0 -0
  75. {polyglot_sql-0.3.3 → polyglot_sql-0.3.5}/crates/polyglot-sql/src/optimizer/optimize_joins.rs +0 -0
  76. {polyglot_sql-0.3.3 → polyglot_sql-0.3.5}/crates/polyglot-sql/src/optimizer/optimizer.rs +0 -0
  77. {polyglot_sql-0.3.3 → polyglot_sql-0.3.5}/crates/polyglot-sql/src/optimizer/pushdown_predicates.rs +0 -0
  78. {polyglot_sql-0.3.3 → polyglot_sql-0.3.5}/crates/polyglot-sql/src/optimizer/pushdown_projections.rs +0 -0
  79. {polyglot_sql-0.3.3 → polyglot_sql-0.3.5}/crates/polyglot-sql/src/optimizer/qualify_columns.rs +0 -0
  80. {polyglot_sql-0.3.3 → polyglot_sql-0.3.5}/crates/polyglot-sql/src/optimizer/qualify_tables.rs +0 -0
  81. {polyglot_sql-0.3.3 → polyglot_sql-0.3.5}/crates/polyglot-sql/src/optimizer/simplify.rs +0 -0
  82. {polyglot_sql-0.3.3 → polyglot_sql-0.3.5}/crates/polyglot-sql/src/optimizer/subquery.rs +0 -0
  83. {polyglot_sql-0.3.3 → polyglot_sql-0.3.5}/crates/polyglot-sql/src/planner.rs +0 -0
  84. {polyglot_sql-0.3.3 → polyglot_sql-0.3.5}/crates/polyglot-sql/src/resolver.rs +0 -0
  85. {polyglot_sql-0.3.3 → polyglot_sql-0.3.5}/crates/polyglot-sql/src/schema.rs +0 -0
  86. {polyglot_sql-0.3.3 → polyglot_sql-0.3.5}/crates/polyglot-sql/src/scope.rs +0 -0
  87. {polyglot_sql-0.3.3 → polyglot_sql-0.3.5}/crates/polyglot-sql/src/time.rs +0 -0
  88. {polyglot_sql-0.3.3 → polyglot_sql-0.3.5}/crates/polyglot-sql/src/tokens.rs +0 -0
  89. {polyglot_sql-0.3.3 → polyglot_sql-0.3.5}/crates/polyglot-sql/src/transforms.rs +0 -0
  90. {polyglot_sql-0.3.3 → polyglot_sql-0.3.5}/crates/polyglot-sql/src/traversal.rs +0 -0
  91. {polyglot_sql-0.3.3 → polyglot_sql-0.3.5}/crates/polyglot-sql/src/trie.rs +0 -0
  92. {polyglot_sql-0.3.3 → polyglot_sql-0.3.5}/crates/polyglot-sql/src/validation/tests.rs +0 -0
  93. {polyglot_sql-0.3.3 → polyglot_sql-0.3.5}/crates/polyglot-sql/src/validation.rs +0 -0
  94. {polyglot_sql-0.3.3 → polyglot_sql-0.3.5}/crates/polyglot-sql/tests/analyze_failures.rs +0 -0
  95. {polyglot_sql-0.3.3 → polyglot_sql-0.3.5}/crates/polyglot-sql/tests/clickhouse_regression.rs +0 -0
  96. {polyglot_sql-0.3.3 → polyglot_sql-0.3.5}/crates/polyglot-sql/tests/common/known_failures.rs +0 -0
  97. {polyglot_sql-0.3.3 → polyglot_sql-0.3.5}/crates/polyglot-sql/tests/common/mod.rs +0 -0
  98. {polyglot_sql-0.3.3 → polyglot_sql-0.3.5}/crates/polyglot-sql/tests/common/test_data.rs +0 -0
  99. {polyglot_sql-0.3.3 → polyglot_sql-0.3.5}/crates/polyglot-sql/tests/common/test_runner.rs +0 -0
  100. {polyglot_sql-0.3.3 → polyglot_sql-0.3.5}/crates/polyglot-sql/tests/custom_clickhouse_coverage.rs +0 -0
  101. {polyglot_sql-0.3.3 → polyglot_sql-0.3.5}/crates/polyglot-sql/tests/custom_clickhouse_parser.rs +0 -0
  102. {polyglot_sql-0.3.3 → polyglot_sql-0.3.5}/crates/polyglot-sql/tests/custom_dialect.rs +0 -0
  103. {polyglot_sql-0.3.3 → polyglot_sql-0.3.5}/crates/polyglot-sql/tests/custom_dialect_tests.rs +0 -0
  104. {polyglot_sql-0.3.3 → polyglot_sql-0.3.5}/crates/polyglot-sql/tests/custom_fixtures/datafusion/ddl.json +0 -0
  105. {polyglot_sql-0.3.3 → polyglot_sql-0.3.5}/crates/polyglot-sql/tests/custom_fixtures/datafusion/dml.json +0 -0
  106. {polyglot_sql-0.3.3 → polyglot_sql-0.3.5}/crates/polyglot-sql/tests/custom_fixtures/datafusion/functions.json +0 -0
  107. {polyglot_sql-0.3.3 → polyglot_sql-0.3.5}/crates/polyglot-sql/tests/custom_fixtures/datafusion/identity.json +0 -0
  108. {polyglot_sql-0.3.3 → polyglot_sql-0.3.5}/crates/polyglot-sql/tests/custom_fixtures/datafusion/operators.json +0 -0
  109. {polyglot_sql-0.3.3 → polyglot_sql-0.3.5}/crates/polyglot-sql/tests/custom_fixtures/datafusion/select.json +0 -0
  110. {polyglot_sql-0.3.3 → polyglot_sql-0.3.5}/crates/polyglot-sql/tests/custom_fixtures/datafusion/transpilation.json +0 -0
  111. {polyglot_sql-0.3.3 → polyglot_sql-0.3.5}/crates/polyglot-sql/tests/custom_fixtures/datafusion/types.json +0 -0
  112. {polyglot_sql-0.3.3 → polyglot_sql-0.3.5}/crates/polyglot-sql/tests/deep_nesting_regression.rs +0 -0
  113. {polyglot_sql-0.3.3 → polyglot_sql-0.3.5}/crates/polyglot-sql/tests/error_handling.rs +0 -0
  114. {polyglot_sql-0.3.3 → polyglot_sql-0.3.5}/crates/polyglot-sql/tests/identity_roundtrip.rs +0 -0
  115. {polyglot_sql-0.3.3 → polyglot_sql-0.3.5}/crates/polyglot-sql/tests/sqlglot_compat.rs +0 -0
  116. {polyglot_sql-0.3.3 → polyglot_sql-0.3.5}/crates/polyglot-sql/tests/sqlglot_dialect_identity.rs +0 -0
  117. {polyglot_sql-0.3.3 → polyglot_sql-0.3.5}/crates/polyglot-sql/tests/sqlglot_identity.rs +0 -0
  118. {polyglot_sql-0.3.3 → polyglot_sql-0.3.5}/crates/polyglot-sql/tests/sqlglot_identity_detailed.rs +0 -0
  119. {polyglot_sql-0.3.3 → polyglot_sql-0.3.5}/crates/polyglot-sql/tests/sqlglot_parser.rs +0 -0
  120. {polyglot_sql-0.3.3 → polyglot_sql-0.3.5}/crates/polyglot-sql/tests/sqlglot_pretty.rs +0 -0
  121. {polyglot_sql-0.3.3 → polyglot_sql-0.3.5}/crates/polyglot-sql/tests/sqlglot_transpilation.rs +0 -0
  122. {polyglot_sql-0.3.3 → polyglot_sql-0.3.5}/crates/polyglot-sql/tests/sqlglot_transpile.rs +0 -0
  123. {polyglot_sql-0.3.3 → polyglot_sql-0.3.5}/crates/polyglot-sql/tests/transform_regression.rs +0 -0
  124. {polyglot_sql-0.3.3 → polyglot_sql-0.3.5}/crates/polyglot-sql-function-catalogs/Cargo.toml +0 -0
  125. {polyglot_sql-0.3.3 → polyglot_sql-0.3.5}/crates/polyglot-sql-function-catalogs/README.md +0 -0
  126. {polyglot_sql-0.3.3 → polyglot_sql-0.3.5}/crates/polyglot-sql-function-catalogs/src/clickhouse.rs +0 -0
  127. {polyglot_sql-0.3.3 → polyglot_sql-0.3.5}/crates/polyglot-sql-function-catalogs/src/duckdb.rs +0 -0
  128. {polyglot_sql-0.3.3 → polyglot_sql-0.3.5}/crates/polyglot-sql-function-catalogs/src/lib.rs +0 -0
  129. {polyglot_sql-0.3.3 → polyglot_sql-0.3.5}/crates/polyglot-sql-function-catalogs/tools/clickhouse/extract_functions.py +0 -0
  130. {polyglot_sql-0.3.3 → polyglot_sql-0.3.5}/crates/polyglot-sql-function-catalogs/tools/duckdb/extract_functions.py +0 -0
  131. {polyglot_sql-0.3.3 → polyglot_sql-0.3.5}/crates/polyglot-sql-python/Cargo.toml +0 -0
  132. {polyglot_sql-0.3.3 → polyglot_sql-0.3.5}/crates/polyglot-sql-python/README.md +0 -0
  133. {polyglot_sql-0.3.3 → polyglot_sql-0.3.5}/crates/polyglot-sql-python/docs/api.md +0 -0
  134. {polyglot_sql-0.3.3 → polyglot_sql-0.3.5}/crates/polyglot-sql-python/docs/index.md +0 -0
  135. {polyglot_sql-0.3.3 → polyglot_sql-0.3.5}/crates/polyglot-sql-python/mkdocs.yml +0 -0
  136. {polyglot_sql-0.3.3 → polyglot_sql-0.3.5}/crates/polyglot-sql-python/src/annotate_types.rs +0 -0
  137. {polyglot_sql-0.3.3 → polyglot_sql-0.3.5}/crates/polyglot-sql-python/src/dialects.rs +0 -0
  138. {polyglot_sql-0.3.3 → polyglot_sql-0.3.5}/crates/polyglot-sql-python/src/diff.rs +0 -0
  139. {polyglot_sql-0.3.3 → polyglot_sql-0.3.5}/crates/polyglot-sql-python/src/errors.rs +0 -0
  140. {polyglot_sql-0.3.3 → polyglot_sql-0.3.5}/crates/polyglot-sql-python/src/expr.rs +0 -0
  141. {polyglot_sql-0.3.3 → polyglot_sql-0.3.5}/crates/polyglot-sql-python/src/expr_types.rs +0 -0
  142. {polyglot_sql-0.3.3 → polyglot_sql-0.3.5}/crates/polyglot-sql-python/src/format.rs +0 -0
  143. {polyglot_sql-0.3.3 → polyglot_sql-0.3.5}/crates/polyglot-sql-python/src/generate.rs +0 -0
  144. {polyglot_sql-0.3.3 → polyglot_sql-0.3.5}/crates/polyglot-sql-python/src/helpers.rs +0 -0
  145. {polyglot_sql-0.3.3 → polyglot_sql-0.3.5}/crates/polyglot-sql-python/src/lib.rs +0 -0
  146. {polyglot_sql-0.3.3 → polyglot_sql-0.3.5}/crates/polyglot-sql-python/src/lineage.rs +0 -0
  147. {polyglot_sql-0.3.3 → polyglot_sql-0.3.5}/crates/polyglot-sql-python/src/optimize.rs +0 -0
  148. {polyglot_sql-0.3.3 → polyglot_sql-0.3.5}/crates/polyglot-sql-python/src/parse.rs +0 -0
  149. {polyglot_sql-0.3.3 → polyglot_sql-0.3.5}/crates/polyglot-sql-python/src/tokenize.rs +0 -0
  150. {polyglot_sql-0.3.3 → polyglot_sql-0.3.5}/crates/polyglot-sql-python/src/transpile.rs +0 -0
  151. {polyglot_sql-0.3.3 → polyglot_sql-0.3.5}/crates/polyglot-sql-python/src/types.rs +0 -0
  152. {polyglot_sql-0.3.3 → polyglot_sql-0.3.5}/crates/polyglot-sql-python/src/validate.rs +0 -0
  153. {polyglot_sql-0.3.3 → polyglot_sql-0.3.5}/crates/polyglot-sql-python/tests/conftest.py +0 -0
  154. {polyglot_sql-0.3.3 → polyglot_sql-0.3.5}/crates/polyglot-sql-python/tests/test_dialects.py +0 -0
  155. {polyglot_sql-0.3.3 → polyglot_sql-0.3.5}/crates/polyglot-sql-python/tests/test_diff.py +0 -0
  156. {polyglot_sql-0.3.3 → polyglot_sql-0.3.5}/crates/polyglot-sql-python/tests/test_expression.py +0 -0
  157. {polyglot_sql-0.3.3 → polyglot_sql-0.3.5}/crates/polyglot-sql-python/tests/test_format.py +0 -0
  158. {polyglot_sql-0.3.3 → polyglot_sql-0.3.5}/crates/polyglot-sql-python/tests/test_generate.py +0 -0
  159. {polyglot_sql-0.3.3 → polyglot_sql-0.3.5}/crates/polyglot-sql-python/tests/test_lineage.py +0 -0
  160. {polyglot_sql-0.3.3 → polyglot_sql-0.3.5}/crates/polyglot-sql-python/tests/test_optimize.py +0 -0
  161. {polyglot_sql-0.3.3 → polyglot_sql-0.3.5}/crates/polyglot-sql-python/tests/test_parse.py +0 -0
  162. {polyglot_sql-0.3.3 → polyglot_sql-0.3.5}/crates/polyglot-sql-python/tests/test_transpile.py +0 -0
  163. {polyglot_sql-0.3.3 → polyglot_sql-0.3.5}/crates/polyglot-sql-python/tests/test_validate.py +0 -0
  164. {polyglot_sql-0.3.3 → polyglot_sql-0.3.5}/crates/polyglot-sql-python/uv.lock +0 -0
  165. {polyglot_sql-0.3.3 → polyglot_sql-0.3.5}/pyproject.toml +0 -0
  166. {polyglot_sql-0.3.3 → polyglot_sql-0.3.5}/python/polyglot_sql/__init__.py +0 -0
  167. {polyglot_sql-0.3.3 → polyglot_sql-0.3.5}/python/polyglot_sql/__init__.pyi +0 -0
  168. {polyglot_sql-0.3.3 → polyglot_sql-0.3.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.3.3"
608
+ version = "0.3.5"
609
609
  dependencies = [
610
610
  "criterion",
611
611
  "once_cell",
@@ -621,7 +621,7 @@ dependencies = [
621
621
 
622
622
  [[package]]
623
623
  name = "polyglot-sql-ffi"
624
- version = "0.3.3"
624
+ version = "0.3.5"
625
625
  dependencies = [
626
626
  "cbindgen",
627
627
  "polyglot-sql",
@@ -631,11 +631,11 @@ dependencies = [
631
631
 
632
632
  [[package]]
633
633
  name = "polyglot-sql-function-catalogs"
634
- version = "0.3.3"
634
+ version = "0.3.5"
635
635
 
636
636
  [[package]]
637
637
  name = "polyglot-sql-python"
638
- version = "0.3.3"
638
+ version = "0.3.5"
639
639
  dependencies = [
640
640
  "polyglot-sql",
641
641
  "pyo3",
@@ -646,7 +646,7 @@ dependencies = [
646
646
 
647
647
  [[package]]
648
648
  name = "polyglot-sql-wasm"
649
- version = "0.3.3"
649
+ version = "0.3.5"
650
650
  dependencies = [
651
651
  "console_error_panic_hook",
652
652
  "js-sys",
@@ -6,7 +6,7 @@ exclude = [
6
6
  ]
7
7
 
8
8
  [workspace.package]
9
- version = "0.3.3"
9
+ version = "0.3.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.3.3
3
+ Version: 0.3.5
4
4
  Classifier: Development Status :: 4 - Beta
5
5
  Classifier: Intended Audience :: Developers
6
6
  Classifier: License :: OSI Approved :: MIT License
@@ -83,7 +83,7 @@ thiserror = { workspace = true }
83
83
  unicode-segmentation = { workspace = true }
84
84
  stacker = { version = "0.1", optional = true }
85
85
  ts-rs = { version = "12.0", features = ["serde-compat"], optional = true }
86
- polyglot-sql-function-catalogs = { path = "../polyglot-sql-function-catalogs", version = "0.3.3", optional = true, default-features = false }
86
+ polyglot-sql-function-catalogs = { path = "../polyglot-sql-function-catalogs", version = "0.3.5", optional = true, default-features = false }
87
87
 
88
88
  [dev-dependencies]
89
89
  pretty_assertions = "1.4"
@@ -1603,6 +1603,7 @@ impl SelectBuilder {
1603
1603
  clone_at_clause: None,
1604
1604
  is_copy: false,
1605
1605
  shallow_clone: false,
1606
+ deep_clone: false,
1606
1607
  leading_comments: vec![],
1607
1608
  with_properties: vec![],
1608
1609
  teradata_post_name_options: vec![],
@@ -37,6 +37,12 @@ impl DialectImpl for DatabricksDialect {
37
37
  config
38
38
  .keywords
39
39
  .insert("DIV".to_string(), crate::tokens::TokenType::Div);
40
+ config
41
+ .keywords
42
+ .insert("REPAIR".to_string(), crate::tokens::TokenType::Command);
43
+ config
44
+ .keywords
45
+ .insert("MSCK".to_string(), crate::tokens::TokenType::Command);
40
46
  // Databricks numeric literal suffixes (same as Hive/Spark)
41
47
  config
42
48
  .numeric_literals
@@ -1009,4 +1015,104 @@ mod tests {
1009
1015
  "FROM_UTC_TIMESTAMP with existing CAST failed"
1010
1016
  );
1011
1017
  }
1018
+
1019
+ #[test]
1020
+ fn test_deep_clone_version_as_of() {
1021
+ let sql = "CREATE TABLE events_clone DEEP CLONE events VERSION AS OF 5";
1022
+ let d = Dialect::get(DialectType::Databricks);
1023
+ let ast = d.parse(sql).expect("Parse failed");
1024
+ let output = d.generate(&ast[0]).expect("Generate failed");
1025
+
1026
+ assert_eq!(output, sql);
1027
+ }
1028
+
1029
+ #[test]
1030
+ fn test_deep_clone_timestamp_as_of() {
1031
+ let sql = "CREATE TABLE events_clone DEEP CLONE events TIMESTAMP AS OF '2024-01-01'";
1032
+ let d = Dialect::get(DialectType::Databricks);
1033
+ let ast = d.parse(sql).expect("Parse failed");
1034
+ let output = d.generate(&ast[0]).expect("Generate failed");
1035
+
1036
+ assert_eq!(output, sql);
1037
+ }
1038
+
1039
+ #[test]
1040
+ fn test_shallow_clone_still_roundtrips() {
1041
+ let sql = "CREATE TABLE events_clone SHALLOW CLONE events";
1042
+ let d = Dialect::get(DialectType::Databricks);
1043
+ let ast = d.parse(sql).expect("Parse failed");
1044
+ let output = d.generate(&ast[0]).expect("Generate failed");
1045
+
1046
+ assert_eq!(output, sql);
1047
+ }
1048
+
1049
+ #[test]
1050
+ fn test_repair_table_commands_roundtrip() {
1051
+ let d = Dialect::get(DialectType::Databricks);
1052
+ let cases = [
1053
+ "REPAIR TABLE events",
1054
+ "MSCK REPAIR TABLE events",
1055
+ "REPAIR TABLE events ADD PARTITIONS",
1056
+ "REPAIR TABLE events DROP PARTITIONS",
1057
+ "REPAIR TABLE events SYNC PARTITIONS",
1058
+ "REPAIR TABLE events SYNC METADATA",
1059
+ ];
1060
+
1061
+ for sql in cases {
1062
+ let ast = d.parse(sql).expect("Parse failed");
1063
+ let output = d.generate(&ast[0]).expect("Generate failed");
1064
+ assert_eq!(output, sql);
1065
+ }
1066
+ }
1067
+
1068
+ #[test]
1069
+ fn test_apply_changes_commands_roundtrip() {
1070
+ let d = Dialect::get(DialectType::Databricks);
1071
+ let cases = [
1072
+ "APPLY CHANGES INTO silver.orders FROM STREAM(bronze.orders) KEYS (id) SEQUENCE BY ts",
1073
+ "APPLY CHANGES INTO LIVE.silver_orders FROM STREAM(LIVE.bronze_orders) KEYS (id) IGNORE NULL UPDATES SEQUENCE BY ts",
1074
+ "APPLY CHANGES INTO LIVE.silver_orders FROM STREAM(LIVE.bronze_orders) KEYS (id) APPLY AS DELETE WHEN operation = 'DELETE' SEQUENCE BY ts COLUMNS * EXCEPT (operation) STORED AS SCD TYPE 1",
1075
+ "APPLY CHANGES INTO LIVE.silver_orders FROM STREAM(LIVE.bronze_orders) KEYS (id) SEQUENCE BY ts STORED AS SCD TYPE 2 TRACK HISTORY ON * EXCEPT (updated_at)",
1076
+ "AUTO CDC INTO silver.orders FROM STREAM(bronze.orders) KEYS (id) SEQUENCE BY ts",
1077
+ "CREATE FLOW apply_cdc AS AUTO CDC INTO silver.orders FROM STREAM(bronze.orders) KEYS (id) SEQUENCE BY ts",
1078
+ ];
1079
+
1080
+ for sql in cases {
1081
+ let ast = d.parse(sql).expect("Parse failed");
1082
+ let output = d.generate(&ast[0]).expect("Generate failed");
1083
+ assert_eq!(output, sql);
1084
+ }
1085
+ }
1086
+
1087
+ #[test]
1088
+ fn test_generate_symlink_format_manifest_roundtrip() {
1089
+ let d = Dialect::get(DialectType::Databricks);
1090
+ let cases = [
1091
+ "GENERATE symlink_format_manifest FOR TABLE events",
1092
+ "GENERATE symlink_format_manifest FOR TABLE catalog.schema.events",
1093
+ ];
1094
+
1095
+ for sql in cases {
1096
+ let ast = d.parse(sql).expect("Parse failed");
1097
+ let output = d.generate(&ast[0]).expect("Generate failed");
1098
+ assert_eq!(output, sql);
1099
+ }
1100
+ }
1101
+
1102
+ #[test]
1103
+ fn test_convert_to_delta_roundtrip() {
1104
+ let d = Dialect::get(DialectType::Databricks);
1105
+ let cases = [
1106
+ "CONVERT TO DELTA parquet.`/mnt/data/events`",
1107
+ "CONVERT TO DELTA database_name.table_name",
1108
+ "CONVERT TO DELTA parquet.`s3://my-bucket/path/to/table` PARTITIONED BY (date DATE)",
1109
+ "CONVERT TO DELTA database_name.table_name NO STATISTICS",
1110
+ ];
1111
+
1112
+ for sql in cases {
1113
+ let ast = d.parse(sql).expect("Parse failed");
1114
+ let output = d.generate(&ast[0]).expect("Generate failed");
1115
+ assert_eq!(output, sql);
1116
+ }
1117
+ }
1012
1118
  }
@@ -42,6 +42,7 @@ impl DialectImpl for FabricDialect {
42
42
  identifier_quote: '[',
43
43
  identifier_quote_style: IdentifierQuoteStyle::BRACKET,
44
44
  dialect: Some(DialectType::Fabric),
45
+ null_ordering_supported: false,
45
46
  ..Default::default()
46
47
  }
47
48
  }
@@ -63,7 +64,14 @@ impl DialectImpl for FabricDialect {
63
64
  }
64
65
  _ => {}
65
66
  }
66
- // Also transform column data types through Fabric's type mappings
67
+ // Also transform column data types through Fabric's type mappings.
68
+ // Apply TSQL normalisation first (e.g. BPCHAR → Char), then Fabric-specific.
69
+ let tsql = TSQLDialect;
70
+ if let Ok(Expression::DataType(tsql_dt)) =
71
+ tsql.transform_data_type(col.data_type.clone())
72
+ {
73
+ col.data_type = tsql_dt;
74
+ }
67
75
  if let Expression::DataType(new_dt) =
68
76
  self.transform_fabric_data_type(col.data_type.clone())?
69
77
  {
@@ -361,7 +369,8 @@ impl FabricDialect {
361
369
  let upper = name.to_uppercase();
362
370
 
363
371
  // Parse out precision and scale if present: "TYPENAME(n)" or "TYPENAME(n, m)"
364
- let (base_name, precision, scale) = Self::parse_type_precision_and_scale(&upper);
372
+ let (base_name, precision, scale) =
373
+ TSQLDialect::parse_type_precision_and_scale(&upper);
365
374
 
366
375
  match base_name.as_str() {
367
376
  // DATETIME -> DATETIME2(6)
@@ -518,24 +527,4 @@ impl FabricDialect {
518
527
  None => max, // Default to max if not specified
519
528
  }
520
529
  }
521
-
522
- /// Parse type name and optional precision/scale from strings like "DATETIME2(7)" or "NUMERIC(10, 2)"
523
- fn parse_type_precision_and_scale(name: &str) -> (String, Option<u32>, Option<u32>) {
524
- if let Some(paren_pos) = name.find('(') {
525
- let base = name[..paren_pos].to_string();
526
- let rest = &name[paren_pos + 1..];
527
- if let Some(close_pos) = rest.find(')') {
528
- let args = &rest[..close_pos];
529
- let parts: Vec<&str> = args.split(',').map(|s| s.trim()).collect();
530
-
531
- let precision = parts.first().and_then(|s| s.parse::<u32>().ok());
532
- let scale = parts.get(1).and_then(|s| s.parse::<u32>().ok());
533
-
534
- return (base, precision, scale);
535
- }
536
- (base, None, None)
537
- } else {
538
- (name.to_string(), None, None)
539
- }
540
- }
541
530
  }
@@ -42,6 +42,12 @@ impl DialectImpl for HiveDialect {
42
42
  config
43
43
  .keywords
44
44
  .insert("DIV".to_string(), crate::tokens::TokenType::Div);
45
+ config
46
+ .keywords
47
+ .insert("REPAIR".to_string(), crate::tokens::TokenType::Command);
48
+ config
49
+ .keywords
50
+ .insert("MSCK".to_string(), crate::tokens::TokenType::Command);
45
51
  // Hive numeric literal suffixes: 1L -> BIGINT, 1S -> SMALLINT, etc.
46
52
  config
47
53
  .numeric_literals
@@ -158,10 +158,10 @@ pub use trino::TrinoDialect;
158
158
  pub use tsql::TSQLDialect;
159
159
 
160
160
  use crate::error::Result;
161
- use crate::expressions::{Expression, FunctionBody, Null};
161
+ use crate::expressions::{Expression, Function, FunctionBody, Identifier, Null};
162
162
  use crate::generator::{Generator, GeneratorConfig};
163
163
  use crate::parser::Parser;
164
- use crate::tokens::{Token, Tokenizer, TokenizerConfig};
164
+ use crate::tokens::{Token, TokenType, Tokenizer, TokenizerConfig};
165
165
  use serde::{Deserialize, Serialize};
166
166
  use std::collections::HashMap;
167
167
  use std::sync::{Arc, LazyLock, RwLock};
@@ -3750,6 +3750,11 @@ impl Dialect {
3750
3750
  pretty: bool,
3751
3751
  ) -> Result<Vec<String>> {
3752
3752
  let target = target_dialect.dialect_type;
3753
+ if matches!(self.dialect_type, DialectType::PostgreSQL)
3754
+ && matches!(target, DialectType::SQLite)
3755
+ {
3756
+ self.reject_pgvector_distance_operators_for_sqlite(sql)?;
3757
+ }
3753
3758
  let expressions = self.parse(sql)?;
3754
3759
  let generic_identity =
3755
3760
  self.dialect_type == DialectType::Generic && target == DialectType::Generic;
@@ -4063,6 +4068,14 @@ impl Dialect {
4063
4068
  let normalized =
4064
4069
  Self::cross_dialect_normalize(normalized, self.dialect_type, target)?;
4065
4070
 
4071
+ let normalized = if matches!(self.dialect_type, DialectType::PostgreSQL)
4072
+ && matches!(target, DialectType::SQLite)
4073
+ {
4074
+ Self::normalize_postgres_to_sqlite_types(normalized)?
4075
+ } else {
4076
+ normalized
4077
+ };
4078
+
4066
4079
  // For DuckDB target from BigQuery source: wrap UNNEST of struct arrays in
4067
4080
  // (SELECT UNNEST(..., max_depth => 2)) subquery
4068
4081
  // Must run BEFORE unnest_alias_to_column_alias since it changes alias structure
@@ -4222,6 +4235,77 @@ impl Dialect {
4222
4235
  // Transpile-only methods: cross-dialect normalization and helpers
4223
4236
  #[cfg(feature = "transpile")]
4224
4237
  impl Dialect {
4238
+ fn reject_pgvector_distance_operators_for_sqlite(&self, sql: &str) -> Result<()> {
4239
+ let tokens = self.tokenize(sql)?;
4240
+ for (i, token) in tokens.iter().enumerate() {
4241
+ if token.token_type == TokenType::NullsafeEq {
4242
+ return Err(crate::error::Error::unsupported(
4243
+ "PostgreSQL pgvector cosine distance operator <=>",
4244
+ "SQLite",
4245
+ ));
4246
+ }
4247
+ if token.token_type == TokenType::Lt
4248
+ && tokens
4249
+ .get(i + 1)
4250
+ .is_some_and(|token| token.token_type == TokenType::Tilde)
4251
+ && tokens
4252
+ .get(i + 2)
4253
+ .is_some_and(|token| token.token_type == TokenType::Gt)
4254
+ {
4255
+ return Err(crate::error::Error::unsupported(
4256
+ "PostgreSQL pgvector Hamming distance operator <~>",
4257
+ "SQLite",
4258
+ ));
4259
+ }
4260
+ }
4261
+ Ok(())
4262
+ }
4263
+
4264
+ fn normalize_postgres_to_sqlite_types(expr: Expression) -> Result<Expression> {
4265
+ fn sqlite_type(dt: crate::expressions::DataType) -> crate::expressions::DataType {
4266
+ use crate::expressions::DataType;
4267
+
4268
+ match dt {
4269
+ DataType::Bit { .. } => DataType::Int {
4270
+ length: None,
4271
+ integer_spelling: true,
4272
+ },
4273
+ DataType::TextWithLength { .. } => DataType::Text,
4274
+ DataType::VarChar { .. } => DataType::Text,
4275
+ DataType::Char { .. } => DataType::Text,
4276
+ DataType::Timestamp { timezone: true, .. } => DataType::Text,
4277
+ DataType::Custom { name } => {
4278
+ let base = name
4279
+ .split_once('(')
4280
+ .map_or(name.as_str(), |(base, _)| base)
4281
+ .trim();
4282
+ if base.eq_ignore_ascii_case("TSVECTOR")
4283
+ || base.eq_ignore_ascii_case("TIMESTAMPTZ")
4284
+ || base.eq_ignore_ascii_case("TIMESTAMP WITH TIME ZONE")
4285
+ || base.eq_ignore_ascii_case("NVARCHAR")
4286
+ || base.eq_ignore_ascii_case("NCHAR")
4287
+ {
4288
+ DataType::Text
4289
+ } else {
4290
+ DataType::Custom { name }
4291
+ }
4292
+ }
4293
+ _ => dt,
4294
+ }
4295
+ }
4296
+
4297
+ transform_recursive(expr, &|e| match e {
4298
+ Expression::DataType(dt) => Ok(Expression::DataType(sqlite_type(dt))),
4299
+ Expression::CreateTable(mut ct) => {
4300
+ for column in &mut ct.columns {
4301
+ column.data_type = sqlite_type(column.data_type.clone());
4302
+ }
4303
+ Ok(Expression::CreateTable(ct))
4304
+ }
4305
+ _ => Ok(e),
4306
+ })
4307
+ }
4308
+
4225
4309
  /// For DuckDB target: when FROM clause contains RANGE(n), replace
4226
4310
  /// `(ROW_NUMBER() OVER (ORDER BY 1 NULLS FIRST) - 1)` with `range` in select expressions.
4227
4311
  /// This handles SEQ1/2/4/8 → RANGE transpilation from Snowflake.
@@ -9067,6 +9151,11 @@ impl Dialect {
9067
9151
  match action {
9068
9152
  Action::None => {
9069
9153
  // Handle inline transforms that don't need a dedicated action
9154
+ if matches!(target, DialectType::TSQL | DialectType::Fabric) {
9155
+ if let Some(rewritten) = Self::rewrite_tsql_interval_arithmetic(&e) {
9156
+ return Ok(rewritten);
9157
+ }
9158
+ }
9070
9159
 
9071
9160
  // BETWEEN SYMMETRIC/ASYMMETRIC expansion for non-PostgreSQL/Dremio targets
9072
9161
  if let Expression::Between(ref b) = e {
@@ -31321,6 +31410,7 @@ impl Dialect {
31321
31410
  clone_source: None,
31322
31411
  clone_at_clause: None,
31323
31412
  shallow_clone: false,
31413
+ deep_clone: false,
31324
31414
  is_copy: false,
31325
31415
  leading_comments: Vec::new(),
31326
31416
  with_properties: Vec::new(),
@@ -31897,7 +31987,9 @@ impl Dialect {
31897
31987
  // Return just the numeric part as value and parsed unit
31898
31988
  return (
31899
31989
  Expression::Literal(Box::new(
31900
- crate::expressions::Literal::String(parts[0].to_string()),
31990
+ crate::expressions::Literal::String(
31991
+ parts[0].trim().to_string(),
31992
+ ),
31901
31993
  )),
31902
31994
  parsed_unit,
31903
31995
  );
@@ -31919,6 +32011,88 @@ impl Dialect {
31919
32011
  }
31920
32012
  }
31921
32013
 
32014
+ fn rewrite_tsql_interval_arithmetic(expr: &Expression) -> Option<Expression> {
32015
+ match expr {
32016
+ Expression::Add(op) => {
32017
+ let Expression::Interval(_) = &op.right else {
32018
+ return None;
32019
+ };
32020
+ Some(Self::build_tsql_dateadd_from_interval(
32021
+ op.left.clone(),
32022
+ &op.right,
32023
+ false,
32024
+ ))
32025
+ }
32026
+ Expression::Sub(op) => {
32027
+ let Expression::Interval(_) = &op.right else {
32028
+ return None;
32029
+ };
32030
+ Some(Self::build_tsql_dateadd_from_interval(
32031
+ op.left.clone(),
32032
+ &op.right,
32033
+ true,
32034
+ ))
32035
+ }
32036
+ _ => None,
32037
+ }
32038
+ }
32039
+
32040
+ fn build_tsql_dateadd_from_interval(
32041
+ date: Expression,
32042
+ interval: &Expression,
32043
+ subtract: bool,
32044
+ ) -> Expression {
32045
+ let (value, unit) = Self::extract_interval_parts(interval);
32046
+ let unit = Self::interval_unit_to_string(&unit);
32047
+ let amount = Self::tsql_dateadd_amount(value, subtract);
32048
+
32049
+ Expression::Function(Box::new(Function::new(
32050
+ "DATEADD".to_string(),
32051
+ vec![Expression::Identifier(Identifier::new(unit)), amount, date],
32052
+ )))
32053
+ }
32054
+
32055
+ fn tsql_dateadd_amount(value: Expression, negate: bool) -> Expression {
32056
+ use crate::expressions::UnaryOp;
32057
+
32058
+ fn numeric_literal_value(value: &Expression) -> Option<&str> {
32059
+ match value {
32060
+ Expression::Literal(lit) => match lit.as_ref() {
32061
+ crate::expressions::Literal::Number(n)
32062
+ | crate::expressions::Literal::String(n) => Some(n.as_str()),
32063
+ _ => None,
32064
+ },
32065
+ _ => None,
32066
+ }
32067
+ }
32068
+
32069
+ if let Some(n) = numeric_literal_value(&value) {
32070
+ if let Ok(parsed) = n.parse::<f64>() {
32071
+ let normalized = if negate { -parsed } else { parsed };
32072
+ let rendered = if normalized.fract() == 0.0 {
32073
+ format!("{}", normalized as i64)
32074
+ } else {
32075
+ normalized.to_string()
32076
+ };
32077
+ return Expression::Literal(Box::new(crate::expressions::Literal::Number(
32078
+ rendered,
32079
+ )));
32080
+ }
32081
+ }
32082
+
32083
+ if !negate {
32084
+ return value;
32085
+ }
32086
+
32087
+ match value {
32088
+ Expression::Neg(op) => op.this,
32089
+ other => Expression::Neg(Box::new(UnaryOp {
32090
+ this: other,
32091
+ inferred_type: None,
32092
+ })),
32093
+ }
32094
+ }
32095
+
31922
32096
  /// Normalize BigQuery-specific functions to standard forms that target dialects can handle
31923
32097
  fn normalize_bigquery_function(
31924
32098
  e: Expression,
@@ -37962,7 +38136,11 @@ mod tests {
37962
38136
  "Expected IS NOT DISTINCT FROM: {}",
37963
38137
  result[0]
37964
38138
  );
37965
- assert!(result[0].contains("= 0"), "Expected = 0 filter: {}", result[0]);
38139
+ assert!(
38140
+ result[0].contains("= 0"),
38141
+ "Expected = 0 filter: {}",
38142
+ result[0]
38143
+ );
37966
38144
  }
37967
38145
 
37968
38146
  #[test]
@@ -1217,6 +1217,29 @@ mod tests {
1217
1217
  assert_eq!(config.identifier_quote, '`');
1218
1218
  }
1219
1219
 
1220
+ #[test]
1221
+ fn test_create_procedure_signal_sqlstate_regression() {
1222
+ let sql = "CREATE PROCEDURE CheckSalary(IN p_salary DECIMAL(10,2))
1223
+ BEGIN
1224
+ IF p_salary <= 0 THEN
1225
+ SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'Salary must be positive';
1226
+ END IF;
1227
+ INSERT INTO employees (salary) VALUES (p_salary);
1228
+ END;";
1229
+
1230
+ let dialect = Dialect::get(DialectType::MySQL);
1231
+ let ast = dialect.parse(sql).expect("Parse failed");
1232
+ let output = dialect.generate(&ast[0]).expect("Generate failed");
1233
+
1234
+ assert!(output.contains("CREATE PROCEDURE CheckSalary"));
1235
+ assert!(output.contains("IF p_salary <= 0 THEN"));
1236
+ assert!(
1237
+ output.contains("SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'Salary must be positive'")
1238
+ );
1239
+ assert!(output.contains("END IF"));
1240
+ assert!(output.contains("INSERT INTO employees (salary) VALUES (p_salary)"));
1241
+ }
1242
+
1220
1243
  fn mysql_identity(sql: &str, expected: &str) {
1221
1244
  let dialect = Dialect::get(DialectType::MySQL);
1222
1245
  let ast = dialect.parse(sql).expect("Parse failed");
@@ -3921,6 +3921,37 @@ mod tests {
3921
3921
  assert!(result.contains("FROM users"));
3922
3922
  }
3923
3923
 
3924
+ #[test]
3925
+ fn test_snowflake_scripting_cursor_declare_block_roundtrip() {
3926
+ let sql = "DECLARE
3927
+ emp CURSOR FOR SELECT salary FROM employees;
3928
+ BEGIN
3929
+ RETURN 1;
3930
+ END";
3931
+
3932
+ let dialect = Dialect::get(DialectType::Snowflake);
3933
+ let ast = dialect.parse(sql).expect("Parse failed");
3934
+ let output = dialect.generate(&ast[0]).expect("Generate failed");
3935
+
3936
+ assert_eq!(output, sql);
3937
+ }
3938
+
3939
+ #[test]
3940
+ fn test_snowflake_scripting_cursor_return_table_roundtrip() {
3941
+ let sql = "DECLARE
3942
+ c1 CURSOR FOR SELECT * FROM invoices;
3943
+ BEGIN
3944
+ OPEN c1;
3945
+ RETURN TABLE(RESULTSET_FROM_CURSOR(c1));
3946
+ END";
3947
+
3948
+ let dialect = Dialect::get(DialectType::Snowflake);
3949
+ let ast = dialect.parse(sql).expect("Parse failed");
3950
+ let output = dialect.generate(&ast[0]).expect("Generate failed");
3951
+
3952
+ assert_eq!(output, sql);
3953
+ }
3954
+
3924
3955
  #[test]
3925
3956
  fn test_group_concat_to_listagg() {
3926
3957
  let result = transpile_to_snowflake("SELECT GROUP_CONCAT(name)");
@@ -41,6 +41,12 @@ impl DialectImpl for SparkDialect {
41
41
  config
42
42
  .keywords
43
43
  .insert("DIV".to_string(), crate::tokens::TokenType::Div);
44
+ config
45
+ .keywords
46
+ .insert("REPAIR".to_string(), crate::tokens::TokenType::Command);
47
+ config
48
+ .keywords
49
+ .insert("MSCK".to_string(), crate::tokens::TokenType::Command);
44
50
  // Spark numeric literal suffixes (same as Hive): 1L -> BIGINT, 1S -> SMALLINT, etc.
45
51
  config
46
52
  .numeric_literals