sqlglot 30.0.1__tar.gz → 30.0.2__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 (286) hide show
  1. {sqlglot-30.0.1 → sqlglot-30.0.2}/CHANGELOG.md +138 -0
  2. {sqlglot-30.0.1 → sqlglot-30.0.2}/Makefile +6 -3
  3. {sqlglot-30.0.1 → sqlglot-30.0.2}/PKG-INFO +19 -19
  4. {sqlglot-30.0.1 → sqlglot-30.0.2}/README.md +16 -16
  5. {sqlglot-30.0.1 → sqlglot-30.0.2}/pyproject.toml +3 -0
  6. {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/__init__.py +18 -1
  7. {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/_version.py +3 -3
  8. {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/dialects/databricks.py +1 -0
  9. {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/dialects/duckdb.py +158 -10
  10. {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/dialects/snowflake.py +3 -0
  11. {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/expressions/array.py +7 -1
  12. {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/expressions/core.py +2 -2
  13. {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/expressions/string.py +8 -0
  14. {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/generator.py +6 -3
  15. {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/parser.py +304 -78
  16. {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/parsers/bigquery.py +10 -3
  17. {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/parsers/materialize.py +2 -0
  18. {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/parsers/prql.py +7 -1
  19. {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/parsers/snowflake.py +24 -17
  20. {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/tokenizer_core.py +15 -3
  21. {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/typing/snowflake.py +1 -0
  22. {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot.egg-info/PKG-INFO +19 -19
  23. {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot.egg-info/requires.txt +2 -2
  24. {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglotc/setup.py +8 -6
  25. {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/dialects/test_bigquery.py +1 -1
  26. {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/dialects/test_dialect.py +2 -0
  27. {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/dialects/test_duckdb.py +10 -1
  28. {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/dialects/test_mysql.py +1 -0
  29. {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/dialects/test_oracle.py +1 -1
  30. {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/dialects/test_snowflake.py +55 -13
  31. {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/fixtures/identity.sql +0 -2
  32. {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/test_executor.py +5 -8
  33. {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/test_expressions.py +10 -0
  34. {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/test_transpile.py +26 -1
  35. {sqlglot-30.0.1 → sqlglot-30.0.2}/.gitignore +0 -0
  36. {sqlglot-30.0.1 → sqlglot-30.0.2}/.gitmodules +0 -0
  37. {sqlglot-30.0.1 → sqlglot-30.0.2}/.gitpod.yml +0 -0
  38. {sqlglot-30.0.1 → sqlglot-30.0.2}/.pre-commit-config.yaml +0 -0
  39. {sqlglot-30.0.1 → sqlglot-30.0.2}/CLAUDE.md +0 -0
  40. {sqlglot-30.0.1 → sqlglot-30.0.2}/CONTRIBUTING.md +0 -0
  41. {sqlglot-30.0.1 → sqlglot-30.0.2}/LICENSE +0 -0
  42. {sqlglot-30.0.1 → sqlglot-30.0.2}/MANIFEST.in +0 -0
  43. {sqlglot-30.0.1 → sqlglot-30.0.2}/setup.cfg +0 -0
  44. {sqlglot-30.0.1 → sqlglot-30.0.2}/setup.py +0 -0
  45. {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/__main__.py +0 -0
  46. {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/_typing.py +0 -0
  47. {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/dialects/__init__.py +0 -0
  48. {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/dialects/athena.py +0 -0
  49. {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/dialects/bigquery.py +0 -0
  50. {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/dialects/clickhouse.py +0 -0
  51. {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/dialects/dialect.py +0 -0
  52. {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/dialects/doris.py +0 -0
  53. {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/dialects/dremio.py +0 -0
  54. {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/dialects/drill.py +0 -0
  55. {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/dialects/druid.py +0 -0
  56. {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/dialects/dune.py +0 -0
  57. {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/dialects/exasol.py +0 -0
  58. {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/dialects/fabric.py +0 -0
  59. {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/dialects/hive.py +0 -0
  60. {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/dialects/materialize.py +0 -0
  61. {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/dialects/mysql.py +0 -0
  62. {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/dialects/oracle.py +0 -0
  63. {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/dialects/postgres.py +0 -0
  64. {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/dialects/presto.py +0 -0
  65. {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/dialects/prql.py +0 -0
  66. {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/dialects/redshift.py +0 -0
  67. {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/dialects/risingwave.py +0 -0
  68. {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/dialects/singlestore.py +0 -0
  69. {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/dialects/solr.py +0 -0
  70. {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/dialects/spark.py +0 -0
  71. {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/dialects/spark2.py +0 -0
  72. {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/dialects/sqlite.py +0 -0
  73. {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/dialects/starrocks.py +0 -0
  74. {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/dialects/tableau.py +0 -0
  75. {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/dialects/teradata.py +0 -0
  76. {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/dialects/trino.py +0 -0
  77. {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/dialects/tsql.py +0 -0
  78. {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/diff.py +0 -0
  79. {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/errors.py +0 -0
  80. {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/executor/__init__.py +0 -0
  81. {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/executor/context.py +0 -0
  82. {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/executor/env.py +0 -0
  83. {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/executor/python.py +0 -0
  84. {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/executor/table.py +0 -0
  85. {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/expressions/__init__.py +0 -0
  86. {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/expressions/aggregate.py +0 -0
  87. {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/expressions/builders.py +0 -0
  88. {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/expressions/constraints.py +0 -0
  89. {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/expressions/datatypes.py +0 -0
  90. {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/expressions/ddl.py +0 -0
  91. {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/expressions/dml.py +0 -0
  92. {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/expressions/functions.py +0 -0
  93. {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/expressions/json.py +0 -0
  94. {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/expressions/math.py +0 -0
  95. {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/expressions/properties.py +0 -0
  96. {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/expressions/query.py +0 -0
  97. {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/expressions/temporal.py +0 -0
  98. {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/helper.py +0 -0
  99. {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/jsonpath.py +0 -0
  100. {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/lineage.py +0 -0
  101. {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/optimizer/__init__.py +0 -0
  102. {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/optimizer/annotate_types.py +0 -0
  103. {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/optimizer/canonicalize.py +0 -0
  104. {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/optimizer/eliminate_ctes.py +0 -0
  105. {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/optimizer/eliminate_joins.py +0 -0
  106. {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/optimizer/eliminate_subqueries.py +0 -0
  107. {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/optimizer/isolate_table_selects.py +0 -0
  108. {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/optimizer/merge_subqueries.py +0 -0
  109. {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/optimizer/normalize.py +0 -0
  110. {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/optimizer/normalize_identifiers.py +0 -0
  111. {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/optimizer/optimize_joins.py +0 -0
  112. {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/optimizer/optimizer.py +0 -0
  113. {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/optimizer/pushdown_predicates.py +0 -0
  114. {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/optimizer/pushdown_projections.py +0 -0
  115. {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/optimizer/qualify.py +0 -0
  116. {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/optimizer/qualify_columns.py +0 -0
  117. {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/optimizer/qualify_tables.py +0 -0
  118. {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/optimizer/resolver.py +0 -0
  119. {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/optimizer/scope.py +0 -0
  120. {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/optimizer/simplify.py +0 -0
  121. {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/optimizer/unnest_subqueries.py +0 -0
  122. {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/parsers/__init__.py +0 -0
  123. {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/parsers/athena.py +0 -0
  124. {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/parsers/base.py +0 -0
  125. {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/parsers/clickhouse.py +0 -0
  126. {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/parsers/databricks.py +0 -0
  127. {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/parsers/doris.py +0 -0
  128. {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/parsers/dremio.py +0 -0
  129. {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/parsers/drill.py +0 -0
  130. {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/parsers/druid.py +0 -0
  131. {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/parsers/duckdb.py +0 -0
  132. {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/parsers/dune.py +0 -0
  133. {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/parsers/exasol.py +0 -0
  134. {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/parsers/fabric.py +0 -0
  135. {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/parsers/hive.py +0 -0
  136. {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/parsers/mysql.py +0 -0
  137. {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/parsers/oracle.py +0 -0
  138. {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/parsers/postgres.py +0 -0
  139. {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/parsers/presto.py +0 -0
  140. {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/parsers/redshift.py +0 -0
  141. {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/parsers/risingwave.py +0 -0
  142. {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/parsers/singlestore.py +0 -0
  143. {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/parsers/solr.py +0 -0
  144. {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/parsers/spark.py +0 -0
  145. {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/parsers/spark2.py +0 -0
  146. {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/parsers/sqlite.py +0 -0
  147. {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/parsers/starrocks.py +0 -0
  148. {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/parsers/tableau.py +0 -0
  149. {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/parsers/teradata.py +0 -0
  150. {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/parsers/trino.py +0 -0
  151. {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/parsers/tsql.py +0 -0
  152. {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/planner.py +0 -0
  153. {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/py.typed +0 -0
  154. {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/schema.py +0 -0
  155. {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/serde.py +0 -0
  156. {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/time.py +0 -0
  157. {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/tokens.py +0 -0
  158. {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/transforms.py +0 -0
  159. {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/trie.py +0 -0
  160. {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/typing/__init__.py +0 -0
  161. {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/typing/bigquery.py +0 -0
  162. {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/typing/clickhouse.py +0 -0
  163. {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/typing/duckdb.py +0 -0
  164. {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/typing/hive.py +0 -0
  165. {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/typing/mysql.py +0 -0
  166. {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/typing/presto.py +0 -0
  167. {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/typing/redshift.py +0 -0
  168. {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/typing/spark.py +0 -0
  169. {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/typing/spark2.py +0 -0
  170. {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot/typing/tsql.py +0 -0
  171. {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot.egg-info/SOURCES.txt +0 -0
  172. {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot.egg-info/dependency_links.txt +0 -0
  173. {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot.egg-info/top_level.txt +0 -0
  174. {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglot.png +0 -0
  175. {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglotc/MANIFEST.in +0 -0
  176. {sqlglot-30.0.1 → sqlglot-30.0.2}/sqlglotc/pyproject.toml +0 -0
  177. {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/__init__.py +0 -0
  178. {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/dialects/__init__.py +0 -0
  179. {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/dialects/test_athena.py +0 -0
  180. {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/dialects/test_clickhouse.py +0 -0
  181. {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/dialects/test_databricks.py +0 -0
  182. {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/dialects/test_doris.py +0 -0
  183. {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/dialects/test_dremio.py +0 -0
  184. {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/dialects/test_drill.py +0 -0
  185. {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/dialects/test_druid.py +0 -0
  186. {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/dialects/test_dune.py +0 -0
  187. {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/dialects/test_exasol.py +0 -0
  188. {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/dialects/test_fabric.py +0 -0
  189. {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/dialects/test_hive.py +0 -0
  190. {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/dialects/test_materialize.py +0 -0
  191. {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/dialects/test_pipe_syntax.py +0 -0
  192. {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/dialects/test_postgres.py +0 -0
  193. {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/dialects/test_presto.py +0 -0
  194. {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/dialects/test_prql.py +0 -0
  195. {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/dialects/test_redshift.py +0 -0
  196. {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/dialects/test_risingwave.py +0 -0
  197. {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/dialects/test_singlestore.py +0 -0
  198. {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/dialects/test_solr.py +0 -0
  199. {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/dialects/test_spark.py +0 -0
  200. {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/dialects/test_sqlite.py +0 -0
  201. {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/dialects/test_starrocks.py +0 -0
  202. {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/dialects/test_tableau.py +0 -0
  203. {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/dialects/test_teradata.py +0 -0
  204. {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/dialects/test_trino.py +0 -0
  205. {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/dialects/test_tsql.py +0 -0
  206. {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/fixtures/jsonpath/LICENSE +0 -0
  207. {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/fixtures/jsonpath/cts.json +0 -0
  208. {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/fixtures/optimizer/annotate_functions.sql +0 -0
  209. {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/fixtures/optimizer/annotate_types.sql +0 -0
  210. {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/fixtures/optimizer/canonicalize.sql +0 -0
  211. {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/fixtures/optimizer/eliminate_ctes.sql +0 -0
  212. {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/fixtures/optimizer/eliminate_joins.sql +0 -0
  213. {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/fixtures/optimizer/eliminate_subqueries.sql +0 -0
  214. {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/fixtures/optimizer/isolate_table_selects.sql +0 -0
  215. {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/fixtures/optimizer/merge_subqueries.sql +0 -0
  216. {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/fixtures/optimizer/normalize.sql +0 -0
  217. {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/fixtures/optimizer/normalize_identifiers.sql +0 -0
  218. {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/fixtures/optimizer/optimize_joins.sql +0 -0
  219. {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/fixtures/optimizer/optimizer.sql +0 -0
  220. {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/fixtures/optimizer/pushdown_cte_alias_columns.sql +0 -0
  221. {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/fixtures/optimizer/pushdown_predicates.sql +0 -0
  222. {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/fixtures/optimizer/pushdown_projections.sql +0 -0
  223. {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/fixtures/optimizer/qualify_columns.sql +0 -0
  224. {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/fixtures/optimizer/qualify_columns__invalid.sql +0 -0
  225. {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/fixtures/optimizer/qualify_columns__with_invisible.sql +0 -0
  226. {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/fixtures/optimizer/qualify_columns_ddl.sql +0 -0
  227. {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/fixtures/optimizer/qualify_tables.sql +0 -0
  228. {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/fixtures/optimizer/quote_identifiers.sql +0 -0
  229. {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/fixtures/optimizer/simplify.sql +0 -0
  230. {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/fixtures/optimizer/tpc-ds/call_center.csv.gz +0 -0
  231. {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/fixtures/optimizer/tpc-ds/catalog_page.csv.gz +0 -0
  232. {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/fixtures/optimizer/tpc-ds/catalog_returns.csv.gz +0 -0
  233. {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/fixtures/optimizer/tpc-ds/catalog_sales.csv.gz +0 -0
  234. {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/fixtures/optimizer/tpc-ds/customer.csv.gz +0 -0
  235. {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/fixtures/optimizer/tpc-ds/customer_address.csv.gz +0 -0
  236. {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/fixtures/optimizer/tpc-ds/customer_demographics.csv.gz +0 -0
  237. {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/fixtures/optimizer/tpc-ds/date_dim.csv.gz +0 -0
  238. {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/fixtures/optimizer/tpc-ds/household_demographics.csv.gz +0 -0
  239. {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/fixtures/optimizer/tpc-ds/income_band.csv.gz +0 -0
  240. {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/fixtures/optimizer/tpc-ds/inventory.csv.gz +0 -0
  241. {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/fixtures/optimizer/tpc-ds/item.csv.gz +0 -0
  242. {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/fixtures/optimizer/tpc-ds/promotion.csv.gz +0 -0
  243. {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/fixtures/optimizer/tpc-ds/reason.csv.gz +0 -0
  244. {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/fixtures/optimizer/tpc-ds/ship_mode.csv.gz +0 -0
  245. {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/fixtures/optimizer/tpc-ds/store.csv.gz +0 -0
  246. {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/fixtures/optimizer/tpc-ds/store_returns.csv.gz +0 -0
  247. {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/fixtures/optimizer/tpc-ds/store_sales.csv.gz +0 -0
  248. {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/fixtures/optimizer/tpc-ds/time_dim.csv.gz +0 -0
  249. {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/fixtures/optimizer/tpc-ds/tpc-ds.sql +0 -0
  250. {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/fixtures/optimizer/tpc-ds/warehouse.csv.gz +0 -0
  251. {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/fixtures/optimizer/tpc-ds/web_page.csv.gz +0 -0
  252. {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/fixtures/optimizer/tpc-ds/web_returns.csv.gz +0 -0
  253. {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/fixtures/optimizer/tpc-ds/web_sales.csv.gz +0 -0
  254. {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/fixtures/optimizer/tpc-ds/web_site.csv.gz +0 -0
  255. {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/fixtures/optimizer/tpc-h/customer.csv.gz +0 -0
  256. {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/fixtures/optimizer/tpc-h/lineitem.csv.gz +0 -0
  257. {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/fixtures/optimizer/tpc-h/nation.csv.gz +0 -0
  258. {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/fixtures/optimizer/tpc-h/orders.csv.gz +0 -0
  259. {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/fixtures/optimizer/tpc-h/part.csv.gz +0 -0
  260. {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/fixtures/optimizer/tpc-h/partsupp.csv.gz +0 -0
  261. {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/fixtures/optimizer/tpc-h/region.csv.gz +0 -0
  262. {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/fixtures/optimizer/tpc-h/supplier.csv.gz +0 -0
  263. {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/fixtures/optimizer/tpc-h/tpc-h.sql +0 -0
  264. {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/fixtures/optimizer/unnest_subqueries.sql +0 -0
  265. {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/fixtures/partial.sql +0 -0
  266. {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/fixtures/pretty.sql +0 -0
  267. {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/gen_fixtures.py +0 -0
  268. {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/helpers.py +0 -0
  269. {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/test_build.py +0 -0
  270. {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/test_dialect_entry_points.py +0 -0
  271. {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/test_dialect_imports.py +0 -0
  272. {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/test_diff.py +0 -0
  273. {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/test_docs.py +0 -0
  274. {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/test_errors.py +0 -0
  275. {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/test_generator.py +0 -0
  276. {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/test_helper.py +0 -0
  277. {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/test_integration_loader.py +0 -0
  278. {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/test_jsonpath.py +0 -0
  279. {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/test_lineage.py +0 -0
  280. {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/test_optimizer.py +0 -0
  281. {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/test_parser.py +0 -0
  282. {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/test_schema.py +0 -0
  283. {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/test_serde.py +0 -0
  284. {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/test_time.py +0 -0
  285. {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/test_tokens.py +0 -0
  286. {sqlglot-30.0.1 → sqlglot-30.0.2}/tests/test_transforms.py +0 -0
@@ -1,7 +1,144 @@
1
1
  Changelog
2
2
  =========
3
3
 
4
+ ## [v30.0.1] - 2026-03-16
5
+ ### :bug: Bug Fixes
6
+ - [`7bcad5c`](https://github.com/tobymao/sqlglot/commit/7bcad5c61673a8567e9c22d059ed4326e6698457) - auto pin sqlglotc version to sqlglot so there's no version mismatch closes [#7304](https://github.com/tobymao/sqlglot/pull/7304) *(commit by [@tobymao](https://github.com/tobymao))*
7
+
8
+
4
9
  ## [v30.0.0] - 2026-03-16
10
+
11
+ SQLGlot v30 is a major release focused on performance and compilation. Some of the core components of the library are now fully compilable by [mypyc](https://mypyc.readthedocs.io/), delivering significant speedups when installed with the `[c]` extra. This required restructuring several internal modules, which introduces breaking changes for users who depend on internal APIs, subclass parsers, or import from internal paths.
12
+
13
+ > **If you only use the public API** (`sqlglot.parse`, `sqlglot.parse_one`, `sqlglot.transpile`, `sqlglot.exp.*`, `sqlglot.optimizer.*`), most code will work without changes.
14
+ ---
15
+
16
+ ## Migration Guide
17
+
18
+ ### 1. Rust tokenizer removed — use `[c]` instead of `[rs]`
19
+
20
+ The Rust-based tokenizer (`sqlglotrs`) has been removed (since v29) and replaced with a mypyc-compiled C extension (`sqlglotc`).
21
+
22
+ ```bash
23
+ # Before
24
+ pip install "sqlglot[rs]"
25
+
26
+ # After
27
+ pip install "sqlglot[c]"
28
+ ```
29
+
30
+ The `[rs]` extra still installs but is now a deprecated no-op stub. The following APIs are removed:
31
+ - `use_rs_tokenizer` parameter and attribute on `Tokenizer`
32
+ - `RsTokenizer`, `RsTokenizerSettings`, `RsTokenTypeSettings` imports
33
+ - `USE_RS_TOKENIZER` constant from `tokens.py`
34
+
35
+ ### 2. `expressions.py` split into a package
36
+
37
+ The monolithic `sqlglot/expressions.py` has been split into `sqlglot/expressions/` with submodules:
38
+
39
+ | Module | Contents |
40
+ |---|---|
41
+ | `core.py` | `Expr`, `Expression`, `Condition`, `Func`, `AggFunc`, `Column`, `Literal`, etc. |
42
+ | `datatypes.py` | `DataType`, `DType`, `DataTypeParam`, `Interval` |
43
+ | `query.py` | `Select`, `Query`, `SetOperation`, `UDTF`, `Subquery` |
44
+ | `ddl.py` | `Create`, `Alter`, `Drop`, DDL statements |
45
+ | `dml.py` | `Insert`, `Update`, `Delete`, `Merge` |
46
+ | `properties.py` | All `*Property` classes, `PropertiesLocation` |
47
+ | `constraints.py` | All `*ColumnConstraint` classes |
48
+ | `math.py` | Arithmetic operators (`Add`, `Sub`, `Mul`, `Div`, etc.) |
49
+ | `string.py` | String functions (`Concat`, `Length`, `Upper`, etc.) |
50
+ | `temporal.py` | Date/time functions (`DateAdd`, `DateDiff`, etc.) |
51
+ | `aggregate.py` | Aggregate functions (`Count`, `Sum`, `Avg`, etc.) |
52
+ | `array.py` | Array functions (`ArrayAgg`, `Explode`, etc.) |
53
+ | `json.py` | JSON functions (`JSONExtract`, etc.) |
54
+ | `functions.py` | Other functions (`Coalesce`, `If`, `Case`, `Cast`, etc.) |
55
+ | `builders.py` | Builder helpers (`select()`, `from_()`, `condition()`, etc.) |
56
+
57
+ **Backwards-compatibility:** `from sqlglot.expressions import *` and `from sqlglot import expressions as exp` still work, because everything is re-exported from `expressions/__init__.py`. However, if you were importing from `sqlglot.expressions` by relying on it being a single file (e.g., inspecting `__file__`), that will break.
58
+
59
+ ### 3. `Parser.expression()` no longer accepts `**kwargs`
60
+
61
+ This affects anyone subclassing `Parser` or calling `self.expression()` in custom parse methods.
62
+
63
+ ```python
64
+ # Before
65
+ self.expression(exp.Select, distinct=True, expressions=cols)
66
+
67
+ # After
68
+ self.expression(exp.Select(distinct=True, expressions=cols))
69
+ ```
70
+
71
+ The expression instance is now constructed by the caller and passed directly. This eliminates `**kwargs` dict allocation overhead.
72
+
73
+ ### 4. Scope traversal: `bfs` parameter removed
74
+
75
+ The `bfs` parameter has been removed from all scope traversal functions. Traversal is now always depth-first (DFS).
76
+
77
+ ```python
78
+ # Before
79
+ scope.walk(bfs=True)
80
+ scope.find(exp.Column, bfs=False)
81
+ walk_in_scope(expr, bfs=True)
82
+
83
+ # After
84
+ scope.walk()
85
+ scope.find(exp.Column)
86
+ walk_in_scope(expr)
87
+ ```
88
+
89
+ **Behavioral change:** The old default was `bfs=True`. Now traversal is always DFS. Code that depended on BFS ordering from these functions will get results in a different order.
90
+
91
+ Affected functions: `Scope.walk()`, `Scope.find()`, `Scope.find_all()`, `walk_in_scope()`, `find_in_scope()`, `find_all_in_scope()`.
92
+
93
+ ### 5. Dialect metaclass no longer mutates Parser token sets
94
+
95
+ Previously, the `_Dialect` metaclass dynamically modified parser token sets (`ID_VAR_TOKENS`, `TABLE_ALIAS_TOKENS`, `NO_PAREN_FUNCTIONS`) at class creation time based on dialect flags like `SUPPORTS_SEMI_ANTI_JOIN`. These mutations are removed — each parser now declares its token sets statically.
96
+
97
+ - `Dialect.SUPPORTS_SEMI_ANTI_JOIN` has been removed.
98
+ - `SHOW_TRIE` / `SET_TRIE` are no longer auto-computed from `SHOW_PARSERS` / `SET_PARSERS`.
99
+
100
+ ### 6. Use `Expr` instead of `Expression` for generic `isinstance` checks
101
+
102
+ Base classes like `Func`, `Condition`, `Binary`, and other traits now inherit from `Expr` directly, not from `Expression`. This means `isinstance(node, exp.Expression)` will **not** match these trait classes. If your code uses `isinstance` to check for "any AST node", switch to `exp.Expr`:
103
+
104
+ ```python
105
+ # Before
106
+ isinstance(node, exp.Expression)
107
+
108
+ # After
109
+ isinstance(node, exp.Expr)
110
+ ```
111
+
112
+ ### 7. Compiled classes cannot be subclassed (when using `[c]`)
113
+
114
+ When `sqlglot[c]` is installed, many core classes are compiled via mypyc. **Compiled classes cannot be subclassed at runtime** — class definition succeeds, but instantiation raises `TypeError: interpreted classes cannot inherit from compiled`.
115
+
116
+ **Affected classes (compiled):**
117
+
118
+ | Class | Subclassable? |
119
+ |---|---|
120
+ | All parsers (`BigQueryParser`, `SnowflakeParser`, etc.) | No |
121
+ | `Parser` (base) | No |
122
+ | `Expression`, `Expr`, and all AST nodes (`Select`, `Column`, `Func`, etc.) | No |
123
+ | `MappingSchema`, `AbstractMappingSchema` | No |
124
+ | `Scope` | No |
125
+ | Optimizer rules (`scope.py`, `qualify.py`, `qualify_columns.py`, etc.) | No |
126
+
127
+ **Not compiled (still subclassable):**
128
+
129
+ | Class | Subclassable? |
130
+ |---|---|
131
+ | `Generator` and all dialect generators | Yes |
132
+ | `Tokenizer` and all dialect tokenizers | Yes |
133
+ | `Dialect` and all dialect classes | Yes |
134
+
135
+ If you need to subclass compiled classes (parsers, expressions, schema, etc.), install the pure Python version instead:
136
+
137
+ ```bash
138
+ pip install sqlglot # pure Python — full subclassing support
139
+ pip install "sqlglot[c]" # compiled — faster, but no subclassing
140
+ ```
141
+
5
142
  ### :boom: BREAKING CHANGES
6
143
  - due to [`8ee0646`](https://github.com/tobymao/sqlglot/commit/8ee0646baa6dfae7e96ca86e2c1af5d53fc04290) - Transpile numeric literals with underscores from ClickHouse to other dialects *(PR [#7132](https://github.com/tobymao/sqlglot/pull/7132) by [@fivetran-amrutabhimsenayachit](https://github.com/fivetran-amrutabhimsenayachit))*:
7
144
 
@@ -13663,3 +13800,4 @@ Changelog
13663
13800
  [v29.0.0]: https://github.com/tobymao/sqlglot/compare/v28.10.1...v29.0.0
13664
13801
  [v29.0.1]: https://github.com/tobymao/sqlglot/compare/v29.0.0...v29.0.1
13665
13802
  [v30.0.0]: https://github.com/tobymao/sqlglot/compare/v29.0.1...v30.0.0
13803
+ [v30.0.1]: https://github.com/tobymao/sqlglot/compare/v30.0.0...v30.0.1
@@ -1,4 +1,4 @@
1
- .PHONY: install install-dev install-devc install-devc-release install-pre-commit bench bench-parse bench-optimize test test-fast unit testc unitc style check docs docs-serve hidec showc clean resolve-integration-conflicts
1
+ .PHONY: install install-dev install-devc install-devc-release install-pre-commit bench bench-parse bench-optimize test test-fast unit testc unitc style check docs docs-serve hidec showc clean resolve-integration-conflicts update-fixtures
2
2
 
3
3
  ifdef UV
4
4
  PIP := uv pip
@@ -7,7 +7,7 @@ else
7
7
  endif
8
8
 
9
9
  SO_BACKUP := /tmp/sqlglot_so_backup
10
- FIND_SO := find . -name "*.so" -not -path "*/build/*" -not -path "*/site-packages/*"
10
+ FIND_SO := find sqlglot -name "*.so"
11
11
 
12
12
  hidec:
13
13
  rm -rf $(SO_BACKUP) && $(FIND_SO) | tar cf $(SO_BACKUP) -T - 2>/dev/null && $(FIND_SO) -delete; true
@@ -41,7 +41,7 @@ install-devc:
41
41
  cd sqlglotc && MYPYC_OPT=0 python setup.py build_ext --inplace
42
42
 
43
43
  install-devc-release: clean
44
- cd sqlglotc && $(PIP) install -e .
44
+ cd sqlglotc && python setup.py build_ext --inplace
45
45
 
46
46
  install-pre-commit:
47
47
  pre-commit install
@@ -87,3 +87,6 @@ docs-serve:
87
87
 
88
88
  resolve-integration-conflicts:
89
89
  cd sqlglot-integration-tests && git pull --rebase --autostash
90
+
91
+ update-fixtures:
92
+ python sqlglot-integration-tests/scripts/update_dbt_fixtures.py
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: sqlglot
3
- Version: 30.0.1
3
+ Version: 30.0.2
4
4
  Summary: An easily customizable SQL parser and transpiler
5
5
  Author-email: Toby Mao <toby.mao@gmail.com>
6
6
  License-Expression: MIT
@@ -33,10 +33,10 @@ Requires-Dist: types-pytz; extra == "dev"
33
33
  Requires-Dist: typing_extensions; extra == "dev"
34
34
  Requires-Dist: pyperf; extra == "dev"
35
35
  Provides-Extra: c
36
- Requires-Dist: sqlglotc==30.0.1; extra == "c"
36
+ Requires-Dist: sqlglotc==30.0.2; extra == "c"
37
37
  Provides-Extra: rs
38
38
  Requires-Dist: sqlglotrs==0.13.0; extra == "rs"
39
- Requires-Dist: sqlglotc==30.0.1; extra == "rs"
39
+ Requires-Dist: sqlglotc==30.0.2; extra == "rs"
40
40
  Dynamic: license-file
41
41
  Dynamic: provides-extra
42
42
 
@@ -590,22 +590,22 @@ sqlglot, sqltree, sqlparse, and sqlfluff are python based whereas sqloxide and p
590
590
 
591
591
  | Query | sqlglot | sqlglot[c] | sqltree | sqlparse | sqlfluff | sqloxide | polyglot-sql |
592
592
  | ----------------- | --------------- | --------------- | --------------- | ---------------- | ----------------- | --------------- | --------------- |
593
- | tpch | 0.002986 (1.00) | 0.000946 (0.32) | 0.002173 (0.73) | 0.014071 (4.71) | 0.240238 (80.45) | 0.000566 (0.19) | 0.000613 (0.21) |
594
- | short | 0.000257 (1.00) | 0.000092 (0.36) | 0.000169 (0.66) | 0.000889 (3.45) | 0.034076 (132.35) | 0.000036 (0.14) | 0.000098 (0.38) |
595
- | deep_arithmetic | 0.007875 (1.00) | 0.002343 (0.30) | 0.006065 (0.77) | N/A | 1.361707 (172.90) | 0.003295 (0.42) | 0.002896 (0.37) |
596
- | large_in | 0.441550 (1.00) | 0.126875 (0.29) | 0.482375 (1.09) | N/A | N/A | 0.122851 (0.28) | 0.135547 (0.31) |
597
- | values | 0.520747 (1.00) | 0.140796 (0.27) | 0.566855 (1.09) | N/A | N/A | 0.118219 (0.23) | 0.128448 (0.25) |
598
- | many_joins | 0.015098 (1.00) | 0.004023 (0.27) | 0.010876 (0.72) | 0.060144 (3.98) | 1.250214 (82.81) | 0.002953 (0.20) | 0.002926 (0.19) |
599
- | many_unions | 0.056118 (1.00) | 0.012016 (0.21) | 0.039004 (0.70) | N/A | 1.838802 (32.77) | 0.013354 (0.24) | N/A |
600
- | nested_subqueries | 0.001643 (1.00) | 0.000285 (0.17) | N/A | 0.003768 (2.29) | 0.090923 (55.35) | 0.000215 (0.13) | 0.000246 (0.15) |
601
- | many_columns | 0.013389 (1.00) | 0.003844 (0.29) | 0.012286 (0.92) | 0.238084 (17.78) | 1.057274 (78.96) | 0.002520 (0.19) | 0.004034 (0.30) |
602
- | large_case | 0.037965 (1.00) | 0.010664 (0.28) | 0.035426 (0.93) | N/A | 4.165526 (109.72) | 0.008970 (0.24) | 0.010843 (0.29) |
603
- | complex_where | 0.030109 (1.00) | 0.007886 (0.26) | N/A | 0.133731 (4.44) | 2.497400 (82.95) | 0.005788 (0.19) | 0.008039 (0.27) |
604
- | many_ctes | 0.021528 (1.00) | 0.004891 (0.23) | 0.013173 (0.61) | 0.125813 (5.84) | 0.683930 (31.77) | 0.004004 (0.19) | 0.003397 (0.16) |
605
- | many_windows | 0.024819 (1.00) | 0.006944 (0.28) | N/A | 0.207969 (8.38) | 1.409374 (56.79) | 0.003544 (0.14) | 0.004391 (0.18) |
606
- | nested_functions | 0.001483 (1.00) | 0.000327 (0.22) | 0.000665 (0.45) | 0.005086 (3.43) | 0.092523 (62.37) | 0.000170 (0.11) | 0.000215 (0.14) |
607
- | large_strings | 0.005686 (1.00) | 0.001612 (0.28) | 0.014111 (2.48) | 0.049465 (8.70) | 0.329009 (57.86) | 0.001463 (0.26) | 0.002308 (0.41) |
608
- | many_numbers | 0.107281 (1.00) | 0.030352 (0.28) | 0.120840 (1.13) | N/A | N/A | 0.027484 (0.26) | 0.032682 (0.30) |
593
+ | tpch | 0.002646 (1.00) | 0.000776 (0.29) | 0.002171 (0.82) | 0.014029 (5.30) | 0.247869 (93.68) | 0.000567 (0.21) | 0.000565 (0.21) |
594
+ | short | 0.000221 (1.00) | 0.000077 (0.35) | 0.000169 (0.76) | 0.000891 (4.03) | 0.032397 (146.59) | 0.000036 (0.16) | 0.000100 (0.45) |
595
+ | deep_arithmetic | 0.007739 (1.00) | 0.002249 (0.29) | 0.006108 (0.79) | N/A | 1.404935 (181.54) | 0.002756 (0.36) | 0.002376 (0.31) |
596
+ | large_in | 0.426694 (1.00) | 0.104540 (0.24) | 0.481306 (1.13) | N/A | N/A | 0.118200 (0.28) | 0.109950 (0.26) |
597
+ | values | 0.470626 (1.00) | 0.114497 (0.24) | 0.547718 (1.16) | N/A | N/A | 0.118737 (0.25) | 0.113932 (0.24) |
598
+ | many_joins | 0.012012 (1.00) | 0.002515 (0.21) | 0.010995 (0.92) | 0.057475 (4.78) | 1.354047 (112.72) | 0.002927 (0.24) | 0.002988 (0.25) |
599
+ | many_unions | 0.048105 (1.00) | 0.008505 (0.18) | 0.038477 (0.80) | N/A | 1.894275 (39.38) | 0.012482 (0.26) | 0.014072 (0.29) |
600
+ | nested_subqueries | 0.001377 (1.00) | 0.000238 (0.17) | N/A | 0.003820 (2.77) | 0.092038 (66.84) | 0.000231 (0.17) | 0.000272 (0.20) |
601
+ | many_columns | 0.012463 (1.00) | 0.002794 (0.22) | 0.012433 (1.00) | 0.240845 (19.32) | 1.097327 (88.05) | 0.002403 (0.19) | 0.003731 (0.30) |
602
+ | large_case | 0.043128 (1.00) | 0.008559 (0.20) | 0.034192 (0.79) | N/A | 4.794309 (111.16) | 0.009326 (0.22) | 0.009723 (0.23) |
603
+ | complex_where | 0.032286 (1.00) | 0.006645 (0.21) | N/A | 0.136158 (4.22) | 2.623021 (81.24) | 0.005642 (0.17) | 0.007409 (0.23) |
604
+ | many_ctes | 0.018625 (1.00) | 0.003961 (0.21) | 0.012569 (0.67) | 0.125719 (6.75) | 0.680498 (36.54) | 0.004813 (0.26) | 0.003537 (0.19) |
605
+ | many_windows | 0.021923 (1.00) | 0.005856 (0.27) | N/A | 0.205469 (9.37) | 1.465070 (66.83) | 0.003638 (0.17) | 0.004376 (0.20) |
606
+ | nested_functions | 0.000816 (1.00) | 0.000195 (0.24) | 0.000703 (0.86) | 0.005044 (6.18) | 0.093864 (115.03) | 0.000170 (0.21) | 0.000188 (0.23) |
607
+ | large_strings | 0.005391 (1.00) | 0.001474 (0.27) | 0.014024 (2.60) | 0.050929 (9.45) | 0.335191 (62.18) | 0.001559 (0.29) | 0.002095 (0.39) |
608
+ | many_numbers | 0.107804 (1.00) | 0.025544 (0.24) | 0.122202 (1.13) | N/A | N/A | 0.029262 (0.27) | 0.026409 (0.24) |
609
609
 
610
610
  ```
611
611
  make bench # Run parsing benchmark
@@ -548,22 +548,22 @@ sqlglot, sqltree, sqlparse, and sqlfluff are python based whereas sqloxide and p
548
548
 
549
549
  | Query | sqlglot | sqlglot[c] | sqltree | sqlparse | sqlfluff | sqloxide | polyglot-sql |
550
550
  | ----------------- | --------------- | --------------- | --------------- | ---------------- | ----------------- | --------------- | --------------- |
551
- | tpch | 0.002986 (1.00) | 0.000946 (0.32) | 0.002173 (0.73) | 0.014071 (4.71) | 0.240238 (80.45) | 0.000566 (0.19) | 0.000613 (0.21) |
552
- | short | 0.000257 (1.00) | 0.000092 (0.36) | 0.000169 (0.66) | 0.000889 (3.45) | 0.034076 (132.35) | 0.000036 (0.14) | 0.000098 (0.38) |
553
- | deep_arithmetic | 0.007875 (1.00) | 0.002343 (0.30) | 0.006065 (0.77) | N/A | 1.361707 (172.90) | 0.003295 (0.42) | 0.002896 (0.37) |
554
- | large_in | 0.441550 (1.00) | 0.126875 (0.29) | 0.482375 (1.09) | N/A | N/A | 0.122851 (0.28) | 0.135547 (0.31) |
555
- | values | 0.520747 (1.00) | 0.140796 (0.27) | 0.566855 (1.09) | N/A | N/A | 0.118219 (0.23) | 0.128448 (0.25) |
556
- | many_joins | 0.015098 (1.00) | 0.004023 (0.27) | 0.010876 (0.72) | 0.060144 (3.98) | 1.250214 (82.81) | 0.002953 (0.20) | 0.002926 (0.19) |
557
- | many_unions | 0.056118 (1.00) | 0.012016 (0.21) | 0.039004 (0.70) | N/A | 1.838802 (32.77) | 0.013354 (0.24) | N/A |
558
- | nested_subqueries | 0.001643 (1.00) | 0.000285 (0.17) | N/A | 0.003768 (2.29) | 0.090923 (55.35) | 0.000215 (0.13) | 0.000246 (0.15) |
559
- | many_columns | 0.013389 (1.00) | 0.003844 (0.29) | 0.012286 (0.92) | 0.238084 (17.78) | 1.057274 (78.96) | 0.002520 (0.19) | 0.004034 (0.30) |
560
- | large_case | 0.037965 (1.00) | 0.010664 (0.28) | 0.035426 (0.93) | N/A | 4.165526 (109.72) | 0.008970 (0.24) | 0.010843 (0.29) |
561
- | complex_where | 0.030109 (1.00) | 0.007886 (0.26) | N/A | 0.133731 (4.44) | 2.497400 (82.95) | 0.005788 (0.19) | 0.008039 (0.27) |
562
- | many_ctes | 0.021528 (1.00) | 0.004891 (0.23) | 0.013173 (0.61) | 0.125813 (5.84) | 0.683930 (31.77) | 0.004004 (0.19) | 0.003397 (0.16) |
563
- | many_windows | 0.024819 (1.00) | 0.006944 (0.28) | N/A | 0.207969 (8.38) | 1.409374 (56.79) | 0.003544 (0.14) | 0.004391 (0.18) |
564
- | nested_functions | 0.001483 (1.00) | 0.000327 (0.22) | 0.000665 (0.45) | 0.005086 (3.43) | 0.092523 (62.37) | 0.000170 (0.11) | 0.000215 (0.14) |
565
- | large_strings | 0.005686 (1.00) | 0.001612 (0.28) | 0.014111 (2.48) | 0.049465 (8.70) | 0.329009 (57.86) | 0.001463 (0.26) | 0.002308 (0.41) |
566
- | many_numbers | 0.107281 (1.00) | 0.030352 (0.28) | 0.120840 (1.13) | N/A | N/A | 0.027484 (0.26) | 0.032682 (0.30) |
551
+ | tpch | 0.002646 (1.00) | 0.000776 (0.29) | 0.002171 (0.82) | 0.014029 (5.30) | 0.247869 (93.68) | 0.000567 (0.21) | 0.000565 (0.21) |
552
+ | short | 0.000221 (1.00) | 0.000077 (0.35) | 0.000169 (0.76) | 0.000891 (4.03) | 0.032397 (146.59) | 0.000036 (0.16) | 0.000100 (0.45) |
553
+ | deep_arithmetic | 0.007739 (1.00) | 0.002249 (0.29) | 0.006108 (0.79) | N/A | 1.404935 (181.54) | 0.002756 (0.36) | 0.002376 (0.31) |
554
+ | large_in | 0.426694 (1.00) | 0.104540 (0.24) | 0.481306 (1.13) | N/A | N/A | 0.118200 (0.28) | 0.109950 (0.26) |
555
+ | values | 0.470626 (1.00) | 0.114497 (0.24) | 0.547718 (1.16) | N/A | N/A | 0.118737 (0.25) | 0.113932 (0.24) |
556
+ | many_joins | 0.012012 (1.00) | 0.002515 (0.21) | 0.010995 (0.92) | 0.057475 (4.78) | 1.354047 (112.72) | 0.002927 (0.24) | 0.002988 (0.25) |
557
+ | many_unions | 0.048105 (1.00) | 0.008505 (0.18) | 0.038477 (0.80) | N/A | 1.894275 (39.38) | 0.012482 (0.26) | 0.014072 (0.29) |
558
+ | nested_subqueries | 0.001377 (1.00) | 0.000238 (0.17) | N/A | 0.003820 (2.77) | 0.092038 (66.84) | 0.000231 (0.17) | 0.000272 (0.20) |
559
+ | many_columns | 0.012463 (1.00) | 0.002794 (0.22) | 0.012433 (1.00) | 0.240845 (19.32) | 1.097327 (88.05) | 0.002403 (0.19) | 0.003731 (0.30) |
560
+ | large_case | 0.043128 (1.00) | 0.008559 (0.20) | 0.034192 (0.79) | N/A | 4.794309 (111.16) | 0.009326 (0.22) | 0.009723 (0.23) |
561
+ | complex_where | 0.032286 (1.00) | 0.006645 (0.21) | N/A | 0.136158 (4.22) | 2.623021 (81.24) | 0.005642 (0.17) | 0.007409 (0.23) |
562
+ | many_ctes | 0.018625 (1.00) | 0.003961 (0.21) | 0.012569 (0.67) | 0.125719 (6.75) | 0.680498 (36.54) | 0.004813 (0.26) | 0.003537 (0.19) |
563
+ | many_windows | 0.021923 (1.00) | 0.005856 (0.27) | N/A | 0.205469 (9.37) | 1.465070 (66.83) | 0.003638 (0.17) | 0.004376 (0.20) |
564
+ | nested_functions | 0.000816 (1.00) | 0.000195 (0.24) | 0.000703 (0.86) | 0.005044 (6.18) | 0.093864 (115.03) | 0.000170 (0.21) | 0.000188 (0.23) |
565
+ | large_strings | 0.005391 (1.00) | 0.001474 (0.27) | 0.014024 (2.60) | 0.050929 (9.45) | 0.335191 (62.18) | 0.001559 (0.29) | 0.002095 (0.39) |
566
+ | many_numbers | 0.107804 (1.00) | 0.025544 (0.24) | 0.122202 (1.13) | N/A | N/A | 0.029262 (0.27) | 0.026409 (0.24) |
567
567
 
568
568
  ```
569
569
  make bench # Run parsing benchmark
@@ -40,6 +40,9 @@ include = ["sqlglot", "sqlglot.*"]
40
40
  [tool.setuptools.package-data]
41
41
  "*" = ["py.typed"]
42
42
 
43
+ [tool.uv.sources]
44
+ sqlglotc = { path = "./sqlglotc" }
45
+
43
46
  [tool.ruff]
44
47
  line-length = 100
45
48
 
@@ -1,4 +1,4 @@
1
- # ruff: noqa: F401
1
+ # ruff: noqa: F401, E402
2
2
  """
3
3
  .. include:: ../README.md
4
4
 
@@ -7,6 +7,23 @@
7
7
 
8
8
  from __future__ import annotations
9
9
 
10
+ # bootstrap mypyc runtime: compiled .so modules do a top-level `import HASH__mypyc`,
11
+ # but the runtime .so lives inside sqlglot/. Pre-load it into sys.modules.
12
+ # this is only needed for editable builds
13
+ import sys
14
+ from pathlib import Path
15
+
16
+ for path in Path(__file__).parent.glob("*__mypyc*.so"):
17
+ name = path.stem.split(".")[0]
18
+ if name not in sys.modules:
19
+ import importlib.util
20
+
21
+ spec = importlib.util.spec_from_file_location(name, path)
22
+ if spec and spec.loader:
23
+ mod = importlib.util.module_from_spec(spec)
24
+ sys.modules[name] = mod
25
+ spec.loader.exec_module(mod)
26
+
10
27
  import logging
11
28
  import typing as t
12
29
 
@@ -28,7 +28,7 @@ version_tuple: VERSION_TUPLE
28
28
  commit_id: COMMIT_ID
29
29
  __commit_id__: COMMIT_ID
30
30
 
31
- __version__ = version = '30.0.1'
32
- __version_tuple__ = version_tuple = (30, 0, 1)
31
+ __version__ = version = '30.0.2'
32
+ __version_tuple__ = version_tuple = (30, 0, 2)
33
33
 
34
- __commit_id__ = commit_id = 'g7bcad5c61'
34
+ __commit_id__ = commit_id = 'g64509a2a3'
@@ -43,6 +43,7 @@ class Databricks(Spark):
43
43
  class Tokenizer(Spark.Tokenizer):
44
44
  KEYWORDS = {
45
45
  **Spark.Tokenizer.KEYWORDS,
46
+ "STREAM": TokenType.STREAM,
46
47
  "VOID": TokenType.VOID,
47
48
  }
48
49
 
@@ -2202,6 +2202,58 @@ class DuckDB(Dialect):
2202
2202
  """
2203
2203
  )
2204
2204
 
2205
+ # Template for STRTOK function transpilation
2206
+ #
2207
+ # DuckDB itself doesn't have a strtok function. This handles the transpilation from Snowflake to DuckDB.
2208
+ # We may need to adjust this if we want to support transpilation from other dialects
2209
+ #
2210
+ # CASE
2211
+ # -- Snowflake: empty delimiter + empty input string → NULL
2212
+ # WHEN delimiter = '' AND input_str = '' THEN NULL
2213
+ #
2214
+ # -- Snowflake: empty delimiter + non-empty input string → treats whole input as 1 token → return input string if index is 1
2215
+ # WHEN delimiter = '' AND index = 1 THEN input_str
2216
+ #
2217
+ # -- Snowflake: empty delimiter + non-empty input string → treats whole input as 1 token → return NULL if index is not 1
2218
+ # WHEN delimiter = '' THEN NULL
2219
+ #
2220
+ # -- Snowflake: negative indices return NULL
2221
+ # WHEN index < 0 THEN NULL
2222
+ #
2223
+ # -- Snowflake: return NULL if any argument is NULL
2224
+ # WHEN input_str IS NULL OR delimiter IS NULL OR index IS NULL THEN NULL
2225
+ #
2226
+ #
2227
+ # ELSE LIST_FILTER(
2228
+ # REGEXP_SPLIT_TO_ARRAY(
2229
+ # input_str,
2230
+ # CASE
2231
+ # -- if delimiter is '', we don't want to surround it with '[' and ']' as '[]' is invalid for DuckDB
2232
+ # WHEN delimiter = '' THEN ''
2233
+ #
2234
+ # -- handle problematic regex characters in delimiter with REGEXP_REPLACE
2235
+ # -- turn delimiter into a regex char set, otherwise DuckDB will match in order, which we don't want
2236
+ # ELSE '[' || REGEXP_REPLACE(delimiter, problematic_char_set, '\\\1', 'g') || ']'
2237
+ # END
2238
+ # ),
2239
+ #
2240
+ # -- Snowflake: don't return empty strings
2241
+ # x -> NOT x = ''
2242
+ # )[index]
2243
+ # END
2244
+ STRTOK_TEMPLATE: exp.Expr = exp.maybe_parse(
2245
+ """
2246
+ CASE
2247
+ WHEN :delimiter = '' AND :string = '' THEN NULL
2248
+ WHEN :delimiter = '' AND :part_index = 1 THEN :string
2249
+ WHEN :delimiter = '' THEN NULL
2250
+ WHEN :part_index < 0 THEN NULL
2251
+ WHEN :string IS NULL OR :delimiter IS NULL OR :part_index IS NULL THEN NULL
2252
+ ELSE :base_func
2253
+ END
2254
+ """
2255
+ )
2256
+
2205
2257
  def _array_bag_sql(self, condition: exp.Expr, arr1: exp.Expr, arr2: exp.Expr) -> str:
2206
2258
  cond = exp.Paren(this=exp.replace_placeholders(condition, arr1=arr1, arr2=arr2))
2207
2259
  return self.sql(
@@ -3642,14 +3694,14 @@ class DuckDB(Dialect):
3642
3694
  """
3643
3695
  Output looks something like this:
3644
3696
 
3645
- CASE
3646
- WHEN delimiter is '' THEN
3697
+ CASE
3698
+ WHEN delimiter is '' THEN
3647
3699
  (
3648
- CASE
3700
+ CASE
3649
3701
  WHEN adjusted_part_index = 1 OR adjusted_part_index = -1 THEN input
3650
3702
  ELSE '' END
3651
- )
3652
- ELSE SPLIT_PART(input, delimiter, adjusted_part_index)
3703
+ )
3704
+ ELSE SPLIT_PART(input, delimiter, adjusted_part_index)
3653
3705
  END
3654
3706
 
3655
3707
  """
@@ -3667,13 +3719,46 @@ class DuckDB(Dialect):
3667
3719
  return self.sql(expression, "this")
3668
3720
 
3669
3721
  def arraytostring_sql(self, expression: exp.ArrayToString) -> str:
3670
- this = self.sql(expression, "this")
3671
- null_text = self.sql(expression, "null")
3722
+ null = expression.args.get("null")
3723
+
3724
+ if expression.args.get("null_is_empty"):
3725
+ x = exp.to_identifier("x")
3726
+ list_transform = exp.Transform(
3727
+ this=expression.this.copy(),
3728
+ expression=exp.Lambda(
3729
+ this=exp.Coalesce(
3730
+ this=exp.cast(x, "TEXT"), expressions=[exp.Literal.string("")]
3731
+ ),
3732
+ expressions=[x],
3733
+ ),
3734
+ )
3735
+ array_to_string = exp.ArrayToString(
3736
+ this=list_transform, expression=expression.expression
3737
+ )
3738
+ if expression.args.get("null_delim_is_null"):
3739
+ return self.sql(
3740
+ exp.case()
3741
+ .when(expression.expression.copy().is_(exp.null()), exp.null())
3742
+ .else_(array_to_string)
3743
+ )
3744
+ return self.sql(array_to_string)
3672
3745
 
3673
- if null_text:
3674
- this = f"LIST_TRANSFORM({this}, x -> COALESCE(x, {null_text}))"
3746
+ if null:
3747
+ x = exp.to_identifier("x")
3748
+ return self.sql(
3749
+ exp.ArrayToString(
3750
+ this=exp.Transform(
3751
+ this=expression.this,
3752
+ expression=exp.Lambda(
3753
+ this=exp.Coalesce(this=x, expressions=[null]),
3754
+ expressions=[x],
3755
+ ),
3756
+ ),
3757
+ expression=expression.expression,
3758
+ )
3759
+ )
3675
3760
 
3676
- return self.func("ARRAY_TO_STRING", this, expression.expression)
3761
+ return self.func("ARRAY_TO_STRING", expression.this, expression.expression)
3677
3762
 
3678
3763
  def _regexp_extract_sql(self, expression: exp.RegexpExtract | exp.RegexpExtractAll) -> str:
3679
3764
  this = expression.this
@@ -4033,6 +4118,69 @@ class DuckDB(Dialect):
4033
4118
 
4034
4119
  return self.func(func, this, decimals, truncate)
4035
4120
 
4121
+ def strtok_sql(self, expression: exp.Strtok) -> str:
4122
+ string_arg = expression.this
4123
+ delimiter_arg = expression.args.get("delimiter")
4124
+ part_index_arg = expression.args.get("part_index")
4125
+
4126
+ if delimiter_arg and part_index_arg:
4127
+ # Escape regex chars and build character class at runtime using REGEXP_REPLACE
4128
+ escaped_delimiter = exp.Anonymous(
4129
+ this="REGEXP_REPLACE",
4130
+ expressions=[
4131
+ delimiter_arg,
4132
+ exp.Literal.string(
4133
+ r"([\[\]^.\-*+?(){}|$\\])"
4134
+ ), # Escape problematic regex chars
4135
+ exp.Literal.string(
4136
+ r"\\\1"
4137
+ ), # Replace with escaped version using $1 backreference
4138
+ exp.Literal.string("g"), # Global flag
4139
+ ],
4140
+ )
4141
+ # CASE WHEN delimiter = '' THEN '' ELSE CONCAT('[', escaped_delimiter, ']') END
4142
+ regex_pattern = (
4143
+ exp.case()
4144
+ .when(delimiter_arg.eq(exp.Literal.string("")), exp.Literal.string(""))
4145
+ .else_(
4146
+ exp.func(
4147
+ "CONCAT",
4148
+ exp.Literal.string("["),
4149
+ escaped_delimiter,
4150
+ exp.Literal.string("]"),
4151
+ )
4152
+ )
4153
+ )
4154
+
4155
+ # STRTOK skips empty strings, so we need to filter them out
4156
+ # LIST_FILTER(REGEXP_SPLIT_TO_ARRAY(string, pattern), x -> x != '')[index]
4157
+ split_array = exp.func("REGEXP_SPLIT_TO_ARRAY", string_arg, regex_pattern)
4158
+ x = exp.to_identifier("x")
4159
+ is_empty = x.eq(exp.Literal.string(""))
4160
+ filtered_array = exp.func(
4161
+ "LIST_FILTER",
4162
+ split_array,
4163
+ exp.Lambda(this=exp.not_(is_empty.copy()), expressions=[x.copy()]),
4164
+ )
4165
+ base_func = exp.Bracket(
4166
+ this=filtered_array,
4167
+ expressions=[part_index_arg],
4168
+ offset=1,
4169
+ )
4170
+
4171
+ # Use template with the built regex pattern
4172
+ result = exp.replace_placeholders(
4173
+ self.STRTOK_TEMPLATE.copy(),
4174
+ string=string_arg,
4175
+ delimiter=delimiter_arg,
4176
+ part_index=part_index_arg,
4177
+ base_func=base_func,
4178
+ )
4179
+
4180
+ return self.sql(result)
4181
+
4182
+ return self.function_fallback_sql(expression)
4183
+
4036
4184
  def approxquantile_sql(self, expression: exp.ApproxQuantile) -> str:
4037
4185
  result = self.func("APPROX_QUANTILE", expression.this, expression.args.get("quantile"))
4038
4186
 
@@ -1201,6 +1201,9 @@ class Snowflake(Dialect):
1201
1201
 
1202
1202
  return expr_sql
1203
1203
 
1204
+ def arraytostring_sql(self, expression: exp.ArrayToString) -> str:
1205
+ return self.func("ARRAY_TO_STRING", expression.this, expression.expression)
1206
+
1204
1207
  def array_sql(self, expression: exp.Array) -> str:
1205
1208
  expressions = expression.expressions
1206
1209
 
@@ -174,7 +174,13 @@ class ArraysZip(Expression, Func):
174
174
 
175
175
 
176
176
  class ArrayToString(Expression, Func):
177
- arg_types = {"this": True, "expression": True, "null": False}
177
+ arg_types = {
178
+ "this": True,
179
+ "expression": True,
180
+ "null": False,
181
+ "null_is_empty": False,
182
+ "null_delim_is_null": False,
183
+ }
178
184
  _sql_names = ["ARRAY_TO_STRING", "ARRAY_JOIN"]
179
185
 
180
186
 
@@ -617,8 +617,8 @@ class Expression(Expr):
617
617
  Returns the alias of the expression, or an empty string if it's not aliased.
618
618
  """
619
619
  alias = self.args.get("alias")
620
- if type(alias).__name__ == "TableAlias":
621
- return alias.name # type: ignore[union-attr]
620
+ if isinstance(alias, Expression):
621
+ return alias.name
622
622
  return self.text("alias")
623
623
 
624
624
  @property
@@ -177,6 +177,14 @@ class SplitPart(Expression, Func):
177
177
  }
178
178
 
179
179
 
180
+ class Strtok(Expression, Func):
181
+ arg_types = {
182
+ "this": True,
183
+ "delimiter": False,
184
+ "part_index": False,
185
+ }
186
+
187
+
180
188
  class StartsWith(Expression, Func):
181
189
  _sql_names = ["STARTS_WITH", "STARTSWITH"]
182
190
  arg_types = {"this": True, "expression": True}
@@ -933,9 +933,10 @@ class Generator(metaclass=_Generator):
933
933
  comment = " " + comment if comment[0].strip() else comment
934
934
  comment = comment + " " if comment[-1].strip() else comment
935
935
 
936
- if not self.dialect.tokenizer_class.NESTED_COMMENTS:
937
- # Necessary workaround to avoid syntax errors due to nesting: /* ... */ ... */
938
- comment = comment.replace("*/", "* /")
936
+ # Escape block comment markers to prevent premature closure or unintended nesting.
937
+ # This is necessary because single-line comments (--) are converted to block comments
938
+ # (/* */) on output, and any */ in the original text would close the comment early.
939
+ comment = comment.replace("*/", "* /").replace("/*", "/ *")
939
940
 
940
941
  return comment
941
942
 
@@ -4086,6 +4087,8 @@ class Generator(metaclass=_Generator):
4086
4087
 
4087
4088
  if isinstance(exprs, exp.Tuple):
4088
4089
  exprs = exprs.expressions
4090
+ else:
4091
+ exprs = [exprs]
4089
4092
 
4090
4093
  connective = exp.or_ if isinstance(rhs, exp.Any) else exp.and_
4091
4094