sqlglot 30.14.0__tar.gz → 30.16.0__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 (341) hide show
  1. {sqlglot-30.14.0 → sqlglot-30.16.0}/.gitignore +6 -0
  2. {sqlglot-30.14.0 → sqlglot-30.16.0}/CHANGELOG.md +108 -0
  3. {sqlglot-30.14.0/sqlglot.egg-info → sqlglot-30.16.0}/PKG-INFO +3 -3
  4. {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/_version.py +3 -3
  5. sqlglot-30.16.0/sqlglot/anonymize.py +307 -0
  6. {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/dialects/bigquery.py +0 -3
  7. {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/dialects/clickhouse.py +0 -1
  8. {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/dialects/dialect.py +47 -5
  9. {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/dialects/dremio.py +0 -6
  10. {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/dialects/duckdb.py +0 -1
  11. {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/dialects/hive.py +0 -2
  12. {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/dialects/mysql.py +0 -1
  13. {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/dialects/starrocks.py +1 -0
  14. {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/dialects/trino.py +4 -0
  15. {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/dialects/tsql.py +3 -1
  16. {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/errors.py +15 -1
  17. {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/executor/env.py +52 -0
  18. {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/executor/python.py +109 -31
  19. {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/expressions/array.py +6 -4
  20. {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/expressions/core.py +20 -14
  21. {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/expressions/datatypes.py +12 -0
  22. {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/expressions/ddl.py +2 -0
  23. {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/expressions/dml.py +1 -0
  24. {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/expressions/json.py +4 -3
  25. {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/expressions/math.py +4 -0
  26. {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/expressions/properties.py +9 -1
  27. {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/expressions/query.py +24 -3
  28. {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/expressions/string.py +7 -3
  29. {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/expressions/temporal.py +1 -1
  30. {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/generator.py +134 -40
  31. {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/generators/bigquery.py +8 -1
  32. {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/generators/clickhouse.py +32 -5
  33. {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/generators/doris.py +12 -5
  34. {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/generators/duckdb.py +88 -48
  35. {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/generators/exasol.py +9 -4
  36. {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/generators/fabric.py +2 -1
  37. {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/generators/hive.py +11 -5
  38. {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/generators/mysql.py +32 -36
  39. {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/generators/oracle.py +2 -0
  40. {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/generators/postgres.py +23 -1
  41. {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/generators/python.py +4 -4
  42. {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/generators/singlestore.py +5 -3
  43. {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/generators/snowflake.py +1 -1
  44. {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/generators/spark2.py +12 -24
  45. {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/generators/sqlite.py +9 -2
  46. {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/generators/starrocks.py +10 -5
  47. {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/generators/trino.py +50 -0
  48. {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/generators/tsql.py +7 -1
  49. {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/lineage.py +78 -33
  50. {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/optimizer/annotate_types.py +101 -82
  51. {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/optimizer/canonicalize_internal_names.py +19 -6
  52. {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/optimizer/eliminate_ctes.py +6 -1
  53. sqlglot-30.16.0/sqlglot/optimizer/journal.py +32 -0
  54. {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/optimizer/pushdown_predicates.py +20 -6
  55. {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/optimizer/pushdown_projections.py +52 -6
  56. {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/optimizer/qualify_columns.py +95 -17
  57. {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/optimizer/qualify_tables.py +11 -3
  58. {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/optimizer/scope.py +7 -1
  59. {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/optimizer/simplify.py +66 -24
  60. {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/optimizer/unnest_subqueries.py +20 -10
  61. {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/parser.py +223 -56
  62. {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/parsers/bigquery.py +33 -19
  63. {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/parsers/clickhouse.py +80 -17
  64. {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/parsers/dremio.py +6 -0
  65. {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/parsers/duckdb.py +11 -0
  66. {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/parsers/mysql.py +17 -7
  67. {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/parsers/postgres.py +16 -1
  68. {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/parsers/prql.py +1 -1
  69. {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/parsers/snowflake.py +11 -4
  70. {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/parsers/spark.py +0 -1
  71. {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/parsers/sqlite.py +79 -0
  72. {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/parsers/teradata.py +1 -1
  73. sqlglot-30.16.0/sqlglot/parsers/trino.py +222 -0
  74. {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/parsers/tsql.py +24 -3
  75. {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/planner.py +3 -2
  76. {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/schema.py +2 -0
  77. {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/tokenizer_core.py +1 -3
  78. {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/tokens.py +0 -4
  79. {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/transforms.py +17 -0
  80. {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/typing/__init__.py +2 -2
  81. {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/typing/bigquery.py +0 -2
  82. {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/typing/databricks.py +7 -2
  83. {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/typing/hive.py +6 -5
  84. sqlglot-30.16.0/sqlglot/typing/mysql.py +205 -0
  85. {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/typing/snowflake.py +0 -3
  86. {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/typing/spark.py +18 -10
  87. {sqlglot-30.14.0 → sqlglot-30.16.0/sqlglot.egg-info}/PKG-INFO +3 -3
  88. {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot.egg-info/SOURCES.txt +4 -0
  89. {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot.egg-info/requires.txt +2 -2
  90. {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot.egg-info/scm_file_list.json +322 -318
  91. sqlglot-30.16.0/sqlglot.egg-info/scm_version.json +8 -0
  92. {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglotc/setup.py +1 -0
  93. {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/dialects/test_bigquery.py +174 -0
  94. {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/dialects/test_clickhouse.py +72 -0
  95. {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/dialects/test_databricks.py +15 -1
  96. {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/dialects/test_doris.py +3 -0
  97. {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/dialects/test_duckdb.py +13 -0
  98. {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/dialects/test_mysql.py +12 -6
  99. {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/dialects/test_oracle.py +31 -0
  100. {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/dialects/test_postgres.py +90 -3
  101. {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/dialects/test_snowflake.py +28 -0
  102. {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/dialects/test_spark.py +2 -0
  103. {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/dialects/test_sqlite.py +69 -0
  104. {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/dialects/test_starrocks.py +11 -0
  105. sqlglot-30.16.0/tests/dialects/test_trino.py +425 -0
  106. {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/dialects/test_tsql.py +58 -0
  107. {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/fixtures/optimizer/annotate_functions.sql +475 -0
  108. {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/fixtures/optimizer/canonicalize_internal_names.sql +20 -0
  109. {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/fixtures/optimizer/pushdown_predicates.sql +20 -0
  110. {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/fixtures/optimizer/pushdown_projections.sql +12 -0
  111. {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/fixtures/optimizer/qualify_columns.sql +98 -0
  112. {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/fixtures/optimizer/qualify_columns__invalid.sql +3 -0
  113. {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/fixtures/optimizer/qualify_tables.sql +14 -0
  114. {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/fixtures/optimizer/simplify.sql +207 -19
  115. {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/fixtures/optimizer/unnest_subqueries.sql +12 -0
  116. sqlglot-30.16.0/tests/test_anonymize.py +514 -0
  117. {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/test_executor.py +147 -1
  118. {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/test_expressions.py +24 -0
  119. {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/test_lineage.py +126 -0
  120. {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/test_optimizer.py +241 -2
  121. {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/test_parser.py +14 -0
  122. {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/test_tokens.py +6 -2
  123. sqlglot-30.16.0/tests/test_typing.py +83 -0
  124. sqlglot-30.14.0/sqlglot/parsers/trino.py +0 -63
  125. sqlglot-30.14.0/sqlglot/typing/mysql.py +0 -96
  126. sqlglot-30.14.0/sqlglot.egg-info/scm_version.json +0 -8
  127. sqlglot-30.14.0/tests/dialects/test_trino.py +0 -178
  128. {sqlglot-30.14.0 → sqlglot-30.16.0}/.gitmodules +0 -0
  129. {sqlglot-30.14.0 → sqlglot-30.16.0}/.gitpod.yml +0 -0
  130. {sqlglot-30.14.0 → sqlglot-30.16.0}/.pre-commit-config.yaml +0 -0
  131. {sqlglot-30.14.0 → sqlglot-30.16.0}/AGENTS.md +0 -0
  132. {sqlglot-30.14.0 → sqlglot-30.16.0}/CLAUDE.md +0 -0
  133. {sqlglot-30.14.0 → sqlglot-30.16.0}/CONTRIBUTING.md +0 -0
  134. {sqlglot-30.14.0 → sqlglot-30.16.0}/LICENSE +0 -0
  135. {sqlglot-30.14.0 → sqlglot-30.16.0}/MANIFEST.in +0 -0
  136. {sqlglot-30.14.0 → sqlglot-30.16.0}/Makefile +0 -0
  137. {sqlglot-30.14.0 → sqlglot-30.16.0}/README.md +0 -0
  138. {sqlglot-30.14.0 → sqlglot-30.16.0}/pyproject.toml +0 -0
  139. {sqlglot-30.14.0 → sqlglot-30.16.0}/setup.cfg +0 -0
  140. {sqlglot-30.14.0 → sqlglot-30.16.0}/setup.py +0 -0
  141. {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/__init__.py +0 -0
  142. {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/__main__.py +0 -0
  143. {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/_typing.py +0 -0
  144. {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/dialects/__init__.py +0 -0
  145. {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/dialects/athena.py +0 -0
  146. {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/dialects/databricks.py +0 -0
  147. {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/dialects/dax.py +0 -0
  148. {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/dialects/doris.py +0 -0
  149. {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/dialects/drill.py +0 -0
  150. {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/dialects/druid.py +0 -0
  151. {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/dialects/dune.py +0 -0
  152. {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/dialects/exasol.py +0 -0
  153. {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/dialects/fabric.py +0 -0
  154. {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/dialects/materialize.py +0 -0
  155. {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/dialects/oracle.py +0 -0
  156. {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/dialects/postgres.py +0 -0
  157. {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/dialects/presto.py +0 -0
  158. {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/dialects/prql.py +0 -0
  159. {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/dialects/redshift.py +0 -0
  160. {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/dialects/risingwave.py +0 -0
  161. {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/dialects/singlestore.py +0 -0
  162. {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/dialects/snowflake.py +0 -0
  163. {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/dialects/solr.py +0 -0
  164. {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/dialects/spark.py +0 -0
  165. {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/dialects/spark2.py +0 -0
  166. {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/dialects/sqlite.py +0 -0
  167. {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/dialects/tableau.py +0 -0
  168. {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/dialects/teradata.py +0 -0
  169. {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/diff.py +0 -0
  170. {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/executor/__init__.py +0 -0
  171. {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/executor/context.py +0 -0
  172. {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/executor/table.py +0 -0
  173. {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/expressions/__init__.py +0 -0
  174. {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/expressions/aggregate.py +0 -0
  175. {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/expressions/builders.py +0 -0
  176. {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/expressions/constraints.py +0 -0
  177. {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/expressions/functions.py +0 -0
  178. {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/generators/__init__.py +0 -0
  179. {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/generators/athena.py +0 -0
  180. {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/generators/databricks.py +0 -0
  181. {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/generators/dax.py +0 -0
  182. {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/generators/dremio.py +0 -0
  183. {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/generators/drill.py +0 -0
  184. {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/generators/druid.py +0 -0
  185. {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/generators/dune.py +0 -0
  186. {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/generators/materialize.py +0 -0
  187. {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/generators/presto.py +0 -0
  188. {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/generators/prql.py +0 -0
  189. {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/generators/redshift.py +0 -0
  190. {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/generators/risingwave.py +0 -0
  191. {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/generators/solr.py +0 -0
  192. {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/generators/spark.py +0 -0
  193. {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/generators/tableau.py +0 -0
  194. {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/generators/teradata.py +0 -0
  195. {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/helper.py +0 -0
  196. {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/jsonpath.py +0 -0
  197. {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/optimizer/__init__.py +0 -0
  198. {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/optimizer/canonicalize.py +0 -0
  199. {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/optimizer/eliminate_joins.py +0 -0
  200. {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/optimizer/eliminate_subqueries.py +0 -0
  201. {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/optimizer/isolate_table_selects.py +0 -0
  202. {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/optimizer/merge_subqueries.py +0 -0
  203. {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/optimizer/normalize.py +0 -0
  204. {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/optimizer/normalize_identifiers.py +0 -0
  205. {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/optimizer/optimize_joins.py +0 -0
  206. {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/optimizer/optimizer.py +0 -0
  207. {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/optimizer/qualify.py +0 -0
  208. {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/optimizer/resolver.py +0 -0
  209. {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/parsers/__init__.py +0 -0
  210. {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/parsers/athena.py +0 -0
  211. {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/parsers/base.py +0 -0
  212. {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/parsers/databricks.py +0 -0
  213. {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/parsers/dax.py +0 -0
  214. {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/parsers/doris.py +0 -0
  215. {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/parsers/drill.py +0 -0
  216. {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/parsers/druid.py +0 -0
  217. {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/parsers/dune.py +0 -0
  218. {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/parsers/exasol.py +0 -0
  219. {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/parsers/fabric.py +0 -0
  220. {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/parsers/hive.py +0 -0
  221. {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/parsers/materialize.py +0 -0
  222. {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/parsers/oracle.py +0 -0
  223. {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/parsers/presto.py +0 -0
  224. {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/parsers/redshift.py +0 -0
  225. {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/parsers/risingwave.py +0 -0
  226. {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/parsers/singlestore.py +0 -0
  227. {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/parsers/solr.py +0 -0
  228. {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/parsers/spark2.py +0 -0
  229. {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/parsers/starrocks.py +0 -0
  230. {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/parsers/tableau.py +0 -0
  231. {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/py.typed +0 -0
  232. {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/serde.py +0 -0
  233. {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/time.py +0 -0
  234. {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/trie.py +0 -0
  235. {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/typing/clickhouse.py +0 -0
  236. {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/typing/duckdb.py +0 -0
  237. {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/typing/postgres.py +0 -0
  238. {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/typing/presto.py +0 -0
  239. {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/typing/redshift.py +0 -0
  240. {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/typing/spark2.py +0 -0
  241. {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot/typing/tsql.py +0 -0
  242. {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot.egg-info/dependency_links.txt +0 -0
  243. {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot.egg-info/top_level.txt +0 -0
  244. {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglot.png +0 -0
  245. {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglotc/MANIFEST.in +0 -0
  246. {sqlglot-30.14.0 → sqlglot-30.16.0}/sqlglotc/pyproject.toml +0 -0
  247. {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/__init__.py +0 -0
  248. {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/dialects/__init__.py +0 -0
  249. {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/dialects/test_athena.py +0 -0
  250. {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/dialects/test_dax.py +0 -0
  251. {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/dialects/test_dialect.py +0 -0
  252. {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/dialects/test_dremio.py +0 -0
  253. {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/dialects/test_drill.py +0 -0
  254. {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/dialects/test_druid.py +0 -0
  255. {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/dialects/test_dune.py +0 -0
  256. {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/dialects/test_exasol.py +0 -0
  257. {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/dialects/test_fabric.py +0 -0
  258. {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/dialects/test_hive.py +0 -0
  259. {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/dialects/test_materialize.py +0 -0
  260. {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/dialects/test_pipe_syntax.py +0 -0
  261. {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/dialects/test_presto.py +0 -0
  262. {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/dialects/test_prql.py +0 -0
  263. {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/dialects/test_redshift.py +0 -0
  264. {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/dialects/test_risingwave.py +0 -0
  265. {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/dialects/test_singlestore.py +0 -0
  266. {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/dialects/test_solr.py +0 -0
  267. {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/dialects/test_tableau.py +0 -0
  268. {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/dialects/test_teradata.py +0 -0
  269. {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/fixtures/identity.sql +0 -0
  270. {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/fixtures/jsonpath/LICENSE +0 -0
  271. {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/fixtures/jsonpath/cts.json +0 -0
  272. {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/fixtures/optimizer/annotate_types.sql +0 -0
  273. {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/fixtures/optimizer/canonicalize.sql +0 -0
  274. {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/fixtures/optimizer/eliminate_ctes.sql +0 -0
  275. {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/fixtures/optimizer/eliminate_joins.sql +0 -0
  276. {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/fixtures/optimizer/eliminate_subqueries.sql +0 -0
  277. {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/fixtures/optimizer/isolate_table_selects.sql +0 -0
  278. {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/fixtures/optimizer/merge_subqueries.sql +0 -0
  279. {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/fixtures/optimizer/normalize.sql +0 -0
  280. {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/fixtures/optimizer/normalize_identifiers.sql +0 -0
  281. {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/fixtures/optimizer/optimize_joins.sql +0 -0
  282. {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/fixtures/optimizer/optimizer.sql +0 -0
  283. {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/fixtures/optimizer/pushdown_cte_alias_columns.sql +0 -0
  284. {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/fixtures/optimizer/qualify_columns__with_invisible.sql +0 -0
  285. {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/fixtures/optimizer/qualify_columns_ddl.sql +0 -0
  286. {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/fixtures/optimizer/quote_identifiers.sql +0 -0
  287. {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/fixtures/optimizer/tpc-ds/call_center.csv.gz +0 -0
  288. {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/fixtures/optimizer/tpc-ds/catalog_page.csv.gz +0 -0
  289. {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/fixtures/optimizer/tpc-ds/catalog_returns.csv.gz +0 -0
  290. {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/fixtures/optimizer/tpc-ds/catalog_sales.csv.gz +0 -0
  291. {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/fixtures/optimizer/tpc-ds/customer.csv.gz +0 -0
  292. {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/fixtures/optimizer/tpc-ds/customer_address.csv.gz +0 -0
  293. {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/fixtures/optimizer/tpc-ds/customer_demographics.csv.gz +0 -0
  294. {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/fixtures/optimizer/tpc-ds/date_dim.csv.gz +0 -0
  295. {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/fixtures/optimizer/tpc-ds/household_demographics.csv.gz +0 -0
  296. {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/fixtures/optimizer/tpc-ds/income_band.csv.gz +0 -0
  297. {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/fixtures/optimizer/tpc-ds/inventory.csv.gz +0 -0
  298. {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/fixtures/optimizer/tpc-ds/item.csv.gz +0 -0
  299. {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/fixtures/optimizer/tpc-ds/promotion.csv.gz +0 -0
  300. {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/fixtures/optimizer/tpc-ds/reason.csv.gz +0 -0
  301. {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/fixtures/optimizer/tpc-ds/ship_mode.csv.gz +0 -0
  302. {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/fixtures/optimizer/tpc-ds/store.csv.gz +0 -0
  303. {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/fixtures/optimizer/tpc-ds/store_returns.csv.gz +0 -0
  304. {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/fixtures/optimizer/tpc-ds/store_sales.csv.gz +0 -0
  305. {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/fixtures/optimizer/tpc-ds/time_dim.csv.gz +0 -0
  306. {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/fixtures/optimizer/tpc-ds/tpc-ds.sql +0 -0
  307. {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/fixtures/optimizer/tpc-ds/warehouse.csv.gz +0 -0
  308. {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/fixtures/optimizer/tpc-ds/web_page.csv.gz +0 -0
  309. {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/fixtures/optimizer/tpc-ds/web_returns.csv.gz +0 -0
  310. {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/fixtures/optimizer/tpc-ds/web_sales.csv.gz +0 -0
  311. {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/fixtures/optimizer/tpc-ds/web_site.csv.gz +0 -0
  312. {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/fixtures/optimizer/tpc-h/customer.csv.gz +0 -0
  313. {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/fixtures/optimizer/tpc-h/lineitem.csv.gz +0 -0
  314. {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/fixtures/optimizer/tpc-h/nation.csv.gz +0 -0
  315. {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/fixtures/optimizer/tpc-h/orders.csv.gz +0 -0
  316. {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/fixtures/optimizer/tpc-h/part.csv.gz +0 -0
  317. {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/fixtures/optimizer/tpc-h/partsupp.csv.gz +0 -0
  318. {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/fixtures/optimizer/tpc-h/region.csv.gz +0 -0
  319. {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/fixtures/optimizer/tpc-h/supplier.csv.gz +0 -0
  320. {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/fixtures/optimizer/tpc-h/tpc-h.sql +0 -0
  321. {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/fixtures/partial.sql +0 -0
  322. {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/fixtures/pretty.sql +0 -0
  323. {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/gen_fixtures.py +0 -0
  324. {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/helpers.py +0 -0
  325. {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/leakcheck.py +0 -0
  326. {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/sqlglot/__init__.py +0 -0
  327. {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/test_build.py +0 -0
  328. {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/test_dialect_entry_points.py +0 -0
  329. {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/test_dialect_imports.py +0 -0
  330. {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/test_diff.py +0 -0
  331. {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/test_docs.py +0 -0
  332. {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/test_errors.py +0 -0
  333. {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/test_generator.py +0 -0
  334. {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/test_helper.py +0 -0
  335. {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/test_integration_loader.py +0 -0
  336. {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/test_jsonpath.py +0 -0
  337. {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/test_schema.py +0 -0
  338. {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/test_serde.py +0 -0
  339. {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/test_time.py +0 -0
  340. {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/test_transforms.py +0 -0
  341. {sqlglot-30.14.0 → sqlglot-30.16.0}/tests/test_transpile.py +0 -0
@@ -148,3 +148,9 @@ sqlglot/_version.py
148
148
 
149
149
  # UV lock file
150
150
  uv.lock
151
+
152
+ # pi (dev. assistant / worktrees)
153
+ .worktrees/
154
+ .pi/
155
+ .pi-subagents/
156
+ .pi-loop.json.lock
@@ -1,6 +1,113 @@
1
1
  Changelog
2
2
  =========
3
3
 
4
+ ## [v30.14.0] - 2026-07-27
5
+ ### :boom: BREAKING CHANGES
6
+ - due to [`a715f9f`](https://github.com/tobymao/sqlglot/commit/a715f9f9aa1ba640f558c7602af9a63fc35d8697) - type annotation for databricks NANVL, SIGN, SHIFTLEFT, SIGNUM, SHUFFLE *(PR [#7896](https://github.com/tobymao/sqlglot/pull/7896) by [@fivetran-amrutabhimsenayachit](https://github.com/fivetran-amrutabhimsenayachit))*:
7
+
8
+ type annotation for databricks NANVL, SIGN, SHIFTLEFT, SIGNUM, SHUFFLE (#7896)
9
+
10
+ - due to [`acb635a`](https://github.com/tobymao/sqlglot/commit/acb635a9d5a1e2bdcd4d18e44a63830f10583240) - don't normalize quoted derived output aliases in qualify_outputs *(PR [#7921](https://github.com/tobymao/sqlglot/pull/7921) by [@georgesittas](https://github.com/georgesittas))*:
11
+
12
+ don't normalize quoted derived output aliases in qualify_outputs (#7921)
13
+
14
+ - due to [`c090f35`](https://github.com/tobymao/sqlglot/commit/c090f35c8625d5bb1371a1c0c75ba434f4df6b95) - dedupe colliding star expanded aliases *(PR [#7872](https://github.com/tobymao/sqlglot/pull/7872) by [@fivetran-kwoodbeck](https://github.com/fivetran-kwoodbeck))*:
15
+
16
+ dedupe colliding star expanded aliases (#7872)
17
+
18
+ - due to [`1b442c9`](https://github.com/tobymao/sqlglot/commit/1b442c97deafa067733ff0590f7a612e66ae8aed) - handle non-literal star ILIKE patterns and Snowflake backslash escapes *(PR [#7918](https://github.com/tobymao/sqlglot/pull/7918) by [@georgesittas](https://github.com/georgesittas))*:
19
+
20
+ handle non-literal star ILIKE patterns and Snowflake backslash escapes (#7918)
21
+
22
+ - due to [`66316e3`](https://github.com/tobymao/sqlglot/commit/66316e335fd617d2f3ab8c412ae7a87356431c97) - parse single-digit hour/minute/second without padding CLAUDE *(PR [#7925](https://github.com/tobymao/sqlglot/pull/7925) by [@deepyaman](https://github.com/deepyaman))*:
23
+
24
+ parse single-digit hour/minute/second without padding CLAUDE (#7925)
25
+
26
+ - due to [`c75b7b6`](https://github.com/tobymao/sqlglot/commit/c75b7b610e182fedba20758853d227b81bc1cb34) - annotate unhex for duckdb *(PR [#7930](https://github.com/tobymao/sqlglot/pull/7930) by [@vaishnavi-polekar](https://github.com/vaishnavi-polekar))*:
27
+
28
+ annotate unhex for duckdb (#7930)
29
+
30
+ - due to [`88c4b4a`](https://github.com/tobymao/sqlglot/commit/88c4b4a6f0372978f8ec58c872f0a7f26570bfe3) - parse and annotate duckdb FROM_HEX *(PR [#7931](https://github.com/tobymao/sqlglot/pull/7931) by [@geooo109](https://github.com/geooo109))*:
31
+
32
+ parse and annotate duckdb FROM_HEX (#7931)
33
+
34
+ - due to [`a7725f2`](https://github.com/tobymao/sqlglot/commit/a7725f2a1944bc853deddf8acec29a01946615dd) - annotate convert_tz for mysql *(PR [#7932](https://github.com/tobymao/sqlglot/pull/7932) by [@PiyaDaswadkar](https://github.com/PiyaDaswadkar))*:
35
+
36
+ annotate convert_tz for mysql (#7932)
37
+
38
+ - due to [`85e0b7c`](https://github.com/tobymao/sqlglot/commit/85e0b7c89f3009fe4fbde381df30a1931a975fb4) - annotate UTC_DATE for MySQL *(PR [#7935](https://github.com/tobymao/sqlglot/pull/7935) by [@PiyaDaswadkar](https://github.com/PiyaDaswadkar))*:
39
+
40
+ annotate UTC_DATE for MySQL (#7935)
41
+
42
+ - due to [`7fbb14f`](https://github.com/tobymao/sqlglot/commit/7fbb14f804e601598f3b398276e9d07b9a2d6dbc) - annotate utc_time for mysql *(PR [#7936](https://github.com/tobymao/sqlglot/pull/7936) by [@PiyaDaswadkar](https://github.com/PiyaDaswadkar))*:
43
+
44
+ annotate utc_time for mysql (#7936)
45
+
46
+ - due to [`212fe55`](https://github.com/tobymao/sqlglot/commit/212fe552375e5ef8432a5ed0dd107278075922e8) - annotate utc_timestamp for mysql *(PR [#7937](https://github.com/tobymao/sqlglot/pull/7937) by [@PiyaDaswadkar](https://github.com/PiyaDaswadkar))*:
47
+
48
+ annotate utc_timestamp for mysql (#7937)
49
+
50
+ - due to [`166cd4d`](https://github.com/tobymao/sqlglot/commit/166cd4de90e272c89f14eb7d04d2989d75ef6742) - annotate substringindex for mysql *(PR [#7945](https://github.com/tobymao/sqlglot/pull/7945) by [@PiyaDaswadkar](https://github.com/PiyaDaswadkar))*:
51
+
52
+ annotate substringindex for mysql (#7945)
53
+
54
+ - due to [`26078eb`](https://github.com/tobymao/sqlglot/commit/26078eb7ca56645521fe6f9d60da67d7e9f7e82b) - annotate unhex for mysql *(PR [#7944](https://github.com/tobymao/sqlglot/pull/7944) by [@PiyaDaswadkar](https://github.com/PiyaDaswadkar))*:
55
+
56
+ annotate unhex for mysql (#7944)
57
+
58
+ - due to [`33de21f`](https://github.com/tobymao/sqlglot/commit/33de21fc21cdc05755a2de39318b292c10ccec0f) - annotate regexpsubstr for mysql *(PR [#7946](https://github.com/tobymao/sqlglot/pull/7946) by [@PiyaDaswadkar](https://github.com/PiyaDaswadkar))*:
59
+
60
+ annotate regexpsubstr for mysql (#7946)
61
+
62
+ - due to [`2aae7f7`](https://github.com/tobymao/sqlglot/commit/2aae7f7605ed38fe0950d004cb9defc1dd9621e5) - preserve x IS NOT NULL instead of normalizing to NOT x IS NULL *(PR [#7938](https://github.com/tobymao/sqlglot/pull/7938) by [@geooo109](https://github.com/geooo109))*:
63
+
64
+ preserve x IS NOT NULL instead of normalizing to NOT x IS NULL (#7938)
65
+
66
+
67
+ ### :sparkles: New Features
68
+ - [`c402094`](https://github.com/tobymao/sqlglot/commit/c4020942b711eb0f5c8a182ff580b31541aed07f) - **duckdb**: transpile BigQuery ARRAY_CONCAT_AGG to DuckDB *(PR [#7891](https://github.com/tobymao/sqlglot/pull/7891) by [@sirockin](https://github.com/sirockin))*
69
+ - [`8be76d2`](https://github.com/tobymao/sqlglot/commit/8be76d20a133ee818cffd52e04366fdc74d6a89e) - **duckdb**: convert ARRAY_AGG IGNORE NULLS to FILTER clause *(PR [#7893](https://github.com/tobymao/sqlglot/pull/7893) by [@sirockin](https://github.com/sirockin))*
70
+ - [`a715f9f`](https://github.com/tobymao/sqlglot/commit/a715f9f9aa1ba640f558c7602af9a63fc35d8697) - **optimizer**: type annotation for databricks NANVL, SIGN, SHIFTLEFT, SIGNUM, SHUFFLE *(PR [#7896](https://github.com/tobymao/sqlglot/pull/7896) by [@fivetran-amrutabhimsenayachit](https://github.com/fivetran-amrutabhimsenayachit))*
71
+ - [`ee5a989`](https://github.com/tobymao/sqlglot/commit/ee5a989cd5b756c10068837887f34ffe8606ce7f) - **mysql**: support INSERT ... SET ... syntax closes [#7927](https://github.com/tobymao/sqlglot/pull/7927) *(PR [#7929](https://github.com/tobymao/sqlglot/pull/7929) by [@georgesittas](https://github.com/georgesittas))*
72
+ - :arrow_lower_right: *addresses issue [#7927](https://github.com/tobymao/sqlglot/issues/7927) opened by [@samerdokas](https://github.com/samerdokas)*
73
+ - [`c75b7b6`](https://github.com/tobymao/sqlglot/commit/c75b7b610e182fedba20758853d227b81bc1cb34) - **optimizer**: annotate unhex for duckdb *(PR [#7930](https://github.com/tobymao/sqlglot/pull/7930) by [@vaishnavi-polekar](https://github.com/vaishnavi-polekar))*
74
+ - [`88c4b4a`](https://github.com/tobymao/sqlglot/commit/88c4b4a6f0372978f8ec58c872f0a7f26570bfe3) - **optimizer**: parse and annotate duckdb FROM_HEX *(PR [#7931](https://github.com/tobymao/sqlglot/pull/7931) by [@geooo109](https://github.com/geooo109))*
75
+ - [`3cd3e58`](https://github.com/tobymao/sqlglot/commit/3cd3e58e10dcdf941f14765889641a5974e550ae) - **duckdb**: transpile BigQuery IN UNNEST(array) to ARRAY_CONTAINS *(PR [#7892](https://github.com/tobymao/sqlglot/pull/7892) by [@sirockin](https://github.com/sirockin))*
76
+ - [`a7725f2`](https://github.com/tobymao/sqlglot/commit/a7725f2a1944bc853deddf8acec29a01946615dd) - **optimizer**: annotate convert_tz for mysql *(PR [#7932](https://github.com/tobymao/sqlglot/pull/7932) by [@PiyaDaswadkar](https://github.com/PiyaDaswadkar))*
77
+ - [`85e0b7c`](https://github.com/tobymao/sqlglot/commit/85e0b7c89f3009fe4fbde381df30a1931a975fb4) - **optimizer**: annotate UTC_DATE for MySQL *(PR [#7935](https://github.com/tobymao/sqlglot/pull/7935) by [@PiyaDaswadkar](https://github.com/PiyaDaswadkar))*
78
+ - [`7fbb14f`](https://github.com/tobymao/sqlglot/commit/7fbb14f804e601598f3b398276e9d07b9a2d6dbc) - **optimizer**: annotate utc_time for mysql *(PR [#7936](https://github.com/tobymao/sqlglot/pull/7936) by [@PiyaDaswadkar](https://github.com/PiyaDaswadkar))*
79
+ - [`212fe55`](https://github.com/tobymao/sqlglot/commit/212fe552375e5ef8432a5ed0dd107278075922e8) - **optimizer**: annotate utc_timestamp for mysql *(PR [#7937](https://github.com/tobymao/sqlglot/pull/7937) by [@PiyaDaswadkar](https://github.com/PiyaDaswadkar))*
80
+ - [`6bb78c9`](https://github.com/tobymao/sqlglot/commit/6bb78c9aa8982b1c69378f797f02c8f248af97b4) - **snowflake**: add support for input => select ... kwarg syntax *(commit by [@georgesittas](https://github.com/georgesittas))*
81
+ - [`166cd4d`](https://github.com/tobymao/sqlglot/commit/166cd4de90e272c89f14eb7d04d2989d75ef6742) - **optimizer**: annotate substringindex for mysql *(PR [#7945](https://github.com/tobymao/sqlglot/pull/7945) by [@PiyaDaswadkar](https://github.com/PiyaDaswadkar))*
82
+ - [`26078eb`](https://github.com/tobymao/sqlglot/commit/26078eb7ca56645521fe6f9d60da67d7e9f7e82b) - **optimizer**: annotate unhex for mysql *(PR [#7944](https://github.com/tobymao/sqlglot/pull/7944) by [@PiyaDaswadkar](https://github.com/PiyaDaswadkar))*
83
+ - [`33de21f`](https://github.com/tobymao/sqlglot/commit/33de21fc21cdc05755a2de39318b292c10ccec0f) - **optimizer**: annotate regexpsubstr for mysql *(PR [#7946](https://github.com/tobymao/sqlglot/pull/7946) by [@PiyaDaswadkar](https://github.com/PiyaDaswadkar))*
84
+ - [`2aae7f7`](https://github.com/tobymao/sqlglot/commit/2aae7f7605ed38fe0950d004cb9defc1dd9621e5) - **postgres**: preserve x IS NOT NULL instead of normalizing to NOT x IS NULL *(PR [#7938](https://github.com/tobymao/sqlglot/pull/7938) by [@geooo109](https://github.com/geooo109))*
85
+ - :arrow_lower_right: *addresses issue [#7909](https://github.com/tobymao/sqlglot/issues/7909) opened by [@tonywasson](https://github.com/tonywasson)*
86
+
87
+ ### :bug: Bug Fixes
88
+ - [`c368c5e`](https://github.com/tobymao/sqlglot/commit/c368c5eb2d84133a18f38ff98946b112c81f060d) - **duckdb**: handle ORDER BY and LIMIT for bq ARRAY_CONCAT_AGG *(PR [#7920](https://github.com/tobymao/sqlglot/pull/7920) by [@geooo109](https://github.com/geooo109))*
89
+ - [`acb635a`](https://github.com/tobymao/sqlglot/commit/acb635a9d5a1e2bdcd4d18e44a63830f10583240) - **optimizer**: don't normalize quoted derived output aliases in qualify_outputs *(PR [#7921](https://github.com/tobymao/sqlglot/pull/7921) by [@georgesittas](https://github.com/georgesittas))*
90
+ - :arrow_lower_right: *fixes issue [#7919](https://github.com/tobymao/sqlglot/issues/7919) opened by [@baruchoxman](https://github.com/baruchoxman)*
91
+ - [`c090f35`](https://github.com/tobymao/sqlglot/commit/c090f35c8625d5bb1371a1c0c75ba434f4df6b95) - **optimizer**: dedupe colliding star expanded aliases *(PR [#7872](https://github.com/tobymao/sqlglot/pull/7872) by [@fivetran-kwoodbeck](https://github.com/fivetran-kwoodbeck))*
92
+ - [`1b442c9`](https://github.com/tobymao/sqlglot/commit/1b442c97deafa067733ff0590f7a612e66ae8aed) - handle non-literal star ILIKE patterns and Snowflake backslash escapes *(PR [#7918](https://github.com/tobymao/sqlglot/pull/7918) by [@georgesittas](https://github.com/georgesittas))*
93
+ - [`66316e3`](https://github.com/tobymao/sqlglot/commit/66316e335fd617d2f3ab8c412ae7a87356431c97) - **hive**: parse single-digit hour/minute/second without padding CLAUDE *(PR [#7925](https://github.com/tobymao/sqlglot/pull/7925) by [@deepyaman](https://github.com/deepyaman))*
94
+ - [`e265dca`](https://github.com/tobymao/sqlglot/commit/e265dcafd6a28bdfb43a6491777b433b49a1ebd7) - **optimizer**: canonicalize unaliased scalar subquery projections *(PR [#7928](https://github.com/tobymao/sqlglot/pull/7928) by [@fivetran-kwoodbeck](https://github.com/fivetran-kwoodbeck))*
95
+ - [`b0a8635`](https://github.com/tobymao/sqlglot/commit/b0a8635ff3fcd769743c4848651497cce6acee19) - **parser**: treat `TokenType.OUT` as an identifier token *(PR [#7933](https://github.com/tobymao/sqlglot/pull/7933) by [@georgesittas](https://github.com/georgesittas))*
96
+ - [`ba0bff3`](https://github.com/tobymao/sqlglot/commit/ba0bff3d9164217f06cfcf9fadbdfd35ae84eefe) - **jsonpath**: preserve falsey union members *(PR [#7957](https://github.com/tobymao/sqlglot/pull/7957) by [@dev-willbird1936](https://github.com/dev-willbird1936))*
97
+ - :arrow_lower_right: *fixes issue [#7956](https://github.com/tobymao/sqlglot/issues/7956) opened by [@dev-willbird1936](https://github.com/dev-willbird1936)*
98
+ - [`b9fd4c9`](https://github.com/tobymao/sqlglot/commit/b9fd4c9a5d3e5aa4ccc5dff395cbde3227f18e5a) - **typing**: on_qualify expects a `Table` argument *(commit by [@georgesittas](https://github.com/georgesittas))*
99
+
100
+ ### :zap: Performance Improvements
101
+ - [`1a38c05`](https://github.com/tobymao/sqlglot/commit/1a38c056a1f47cfc07c9bef4ed11b795a91f947e) - **optimizer**: speed up merge_subqueries *(PR [#7924](https://github.com/tobymao/sqlglot/pull/7924) by [@fivetran-kwoodbeck](https://github.com/fivetran-kwoodbeck))*
102
+ - [`b8180fd`](https://github.com/tobymao/sqlglot/commit/b8180fdb8c2617b7e51e1c9491a76cae852eb87b) - **optimizer**: speed up merge_subqueries *(PR [#7924](https://github.com/tobymao/sqlglot/pull/7924) by [@fivetran-kwoodbeck](https://github.com/fivetran-kwoodbeck))*
103
+
104
+ ### :wrench: Chores
105
+ - [`cda0147`](https://github.com/tobymao/sqlglot/commit/cda0147754257779c4c103d617c04d2deb6979b9) - **generator**: refactor ARRAY_AGG tests and bq -> duckdb transpilation *(PR [#7922](https://github.com/tobymao/sqlglot/pull/7922) by [@geooo109](https://github.com/geooo109))*
106
+ - [`f37d1b5`](https://github.com/tobymao/sqlglot/commit/f37d1b5d6305ff293f7b1757ce1253c3299d8e88) - **duckdb**: refactor transpilation of IN UNNEST *(commit by [@geooo109](https://github.com/geooo109))*
107
+ - [`296d8b0`](https://github.com/tobymao/sqlglot/commit/296d8b02e7f7b4d0634194ed367ac3ce49a03714) - polish README file *(PR [#7947](https://github.com/tobymao/sqlglot/pull/7947) by [@georgesittas](https://github.com/georgesittas))*
108
+ - [`29c651b`](https://github.com/tobymao/sqlglot/commit/29c651b85309693924b8c034501e6a2733d14588) - retrigger v30.14.0 release *(commit by [@georgesittas](https://github.com/georgesittas))*
109
+
110
+
4
111
  ## [v30.13.0] - 2026-07-20
5
112
  ### :boom: BREAKING CHANGES
6
113
  - due to [`58f5bf9`](https://github.com/tobymao/sqlglot/commit/58f5bf9b40dda34784bcb2d3bf0a04f02490de12) - databricks type annotation for REGEXP_COUNT, REGEXP_EXTRACT_ALL *(PR [#7797](https://github.com/tobymao/sqlglot/pull/7797) by [@fivetran-amrutabhimsenayachit](https://github.com/fivetran-amrutabhimsenayachit))*:
@@ -15078,3 +15185,4 @@ pip install "sqlglot[c]" # compiled — faster, but no subclassing
15078
15185
  [v30.11.0]: https://github.com/tobymao/sqlglot/compare/v30.10.0...v30.11.0
15079
15186
  [v30.12.0]: https://github.com/tobymao/sqlglot/compare/v30.11.0...v30.12.0
15080
15187
  [v30.13.0]: https://github.com/tobymao/sqlglot/compare/v30.12.0...v30.13.0
15188
+ [v30.14.0]: https://github.com/tobymao/sqlglot/compare/v30.13.0...v30.14.0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: sqlglot
3
- Version: 30.14.0
3
+ Version: 30.16.0
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
@@ -34,10 +34,10 @@ Requires-Dist: types-pytz; extra == "dev"
34
34
  Requires-Dist: typing_extensions; extra == "dev"
35
35
  Requires-Dist: pyperf; extra == "dev"
36
36
  Provides-Extra: c
37
- Requires-Dist: sqlglotc==30.14.0; python_version >= "3.10" and extra == "c"
37
+ Requires-Dist: sqlglotc==30.16.0; python_version >= "3.10" and extra == "c"
38
38
  Provides-Extra: rs
39
39
  Requires-Dist: sqlglotrs==0.13.0; extra == "rs"
40
- Requires-Dist: sqlglotc==30.14.0; python_version >= "3.10" and extra == "rs"
40
+ Requires-Dist: sqlglotc==30.16.0; python_version >= "3.10" and extra == "rs"
41
41
  Dynamic: license-file
42
42
  Dynamic: provides-extra
43
43
 
@@ -18,7 +18,7 @@ version_tuple: tuple[int | str, ...]
18
18
  commit_id: str | None
19
19
  __commit_id__: str | None
20
20
 
21
- __version__ = version = '30.14.0'
22
- __version_tuple__ = version_tuple = (30, 14, 0)
21
+ __version__ = version = '30.16.0'
22
+ __version_tuple__ = version_tuple = (30, 16, 0)
23
23
 
24
- __commit_id__ = commit_id = 'g29c651b85'
24
+ __commit_id__ = commit_id = 'gbbfb497f1'
@@ -0,0 +1,307 @@
1
+ from __future__ import annotations
2
+
3
+ import string
4
+
5
+ from sqlglot.dialects.dialect import Dialect, DialectType
6
+ from sqlglot.errors import TokenError
7
+ from sqlglot.tokens import Token, TokenType
8
+
9
+
10
+ ALPHABET = string.ascii_lowercase
11
+ ALPHABET_SIZE = len(ALPHABET)
12
+ ANONYMIZED_TYPES = {
13
+ TokenType.BIT_STRING,
14
+ TokenType.BYTE_STRING,
15
+ TokenType.HEX_STRING,
16
+ TokenType.HEREDOC_STRING,
17
+ TokenType.IDENTIFIER,
18
+ TokenType.NATIONAL_STRING,
19
+ TokenType.NUMBER,
20
+ TokenType.RAW_STRING,
21
+ TokenType.STRING,
22
+ TokenType.UNICODE_STRING,
23
+ TokenType.VAR,
24
+ }
25
+ QUOTED_TYPES = ANONYMIZED_TYPES - {TokenType.NUMBER, TokenType.VAR}
26
+ REWRITTEN_TYPES = {TokenType.HINT, TokenType.UNKNOWN}
27
+
28
+
29
+ def anonymize(
30
+ sql_or_tokens: list[Token] | str,
31
+ dialect: DialectType = None,
32
+ ) -> list[Token]:
33
+ """Replaces sensitive tokens (identifiers, strings, numbers) with fixed-width,
34
+ length-preserving, consistent aliases, and blanks out comments and hint bodies. When a
35
+ SQL string is given, it is tokenized with `dialect` first; any un-tokenized remainder
36
+ (e.g. an unterminated literal) is appended as a blanked UNKNOWN token. Mutates and
37
+ returns `sql_or_tokens`.
38
+
39
+ Args:
40
+ sql_or_tokens: The SQL string to anonymize, or its token list.
41
+ dialect: The dialect used to tokenize a SQL string.
42
+ """
43
+ dialect = Dialect.get_or_raise(dialect)
44
+ tokenizer_class = dialect.tokenizer_class
45
+ parser_class = dialect.parser_class
46
+
47
+ errored = False
48
+ if isinstance(sql_or_tokens, str):
49
+ sql = sql_or_tokens
50
+ tokenizer = dialect.tokenizer()
51
+ try:
52
+ tokens = tokenizer.tokenize(sql)
53
+ except TokenError:
54
+ tokens = tokenizer.tokens
55
+ errored = True
56
+ else:
57
+ tokens = sql_or_tokens
58
+ sql = None
59
+
60
+ hint_start = tokenizer_class.HINT_START
61
+ hint_end = tokenizer_class._COMMENTS.get(hint_start)
62
+ nested = tokenizer_class.NESTED_COMMENTS
63
+
64
+ seen: dict[tuple[bool, str], str] = {}
65
+ counter = 0
66
+
67
+ for i, token in enumerate(tokens):
68
+ token.comments = [_blank(comment) for comment in token.comments]
69
+
70
+ if token.token_type == TokenType.HINT:
71
+ # A hint's text is the whole /*+ ... */ comment, so its body is blanked as well
72
+ text, stop = _blank_comment(token.text, 0, hint_start, hint_end, nested)
73
+ token.text = text + _blank(token.text[stop:])
74
+ continue
75
+
76
+ if (
77
+ token.token_type == TokenType.VAR
78
+ and i + 1 < len(tokens)
79
+ and tokens[i + 1].token_type == TokenType.L_PAREN
80
+ ):
81
+ # A function name can live in either registry, e.g. JSON_OBJECT is only in
82
+ # FUNCTION_PARSERS. They're consulted separately to avoid building their union
83
+ name = token.text.upper()
84
+ if name in parser_class.FUNCTIONS or name in parser_class.FUNCTION_PARSERS:
85
+ continue
86
+ if token.token_type not in ANONYMIZED_TYPES:
87
+ continue
88
+ if not token.text:
89
+ continue
90
+
91
+ is_number = token.token_type == TokenType.NUMBER
92
+ key = (is_number, token.text)
93
+ alias = seen.get(key)
94
+ if alias is None:
95
+ seen[key] = (
96
+ _number_alias(counter, token.text) if is_number else _alias(counter, token.text)
97
+ )
98
+ counter += 1
99
+ token.text = seen[key]
100
+
101
+ if sql is not None and errored:
102
+ start = tokens[-1].end + 1 if tokens else 0
103
+ length = len(sql)
104
+ while start < length and sql[start].isspace():
105
+ start += 1
106
+ if start < length:
107
+ # The first two characters are kept so that the delimiter the tokenizer choked
108
+ # on is still visible, e.g. 'u, /*, $$, `u
109
+ tokens.append(
110
+ Token(
111
+ TokenType.UNKNOWN,
112
+ sql[start : start + 2] + "." * (length - start - 2),
113
+ start=start,
114
+ end=length - 1,
115
+ line=sql.count("\n", 0, start) + 1,
116
+ col=start - sql.rfind("\n", 0, start),
117
+ )
118
+ )
119
+
120
+ return tokens
121
+
122
+
123
+ def render(sql: str, tokens: list[Token], dialect: DialectType = None) -> str:
124
+ """Recreates the (anonymized) SQL string from the original `sql` and token positions.
125
+
126
+ Every token is rendered over its own source span, so the result is always as long as
127
+ `sql`: a token that wasn't anonymized is emitted verbatim, keeping the spelling the
128
+ tokenizer normalized away, and an anonymized one has its alias fitted between the
129
+ quotes of its span. The gaps between tokens hold only whitespace and comments, so
130
+ they're redacted rather than reconstructed: comment markers and whitespace survive,
131
+ everything else is blanked. That covers anything the tokenizer didn't reach as well,
132
+ which is a trailing gap whenever `anonymize` wasn't the one to tokenize `sql`.
133
+
134
+ Args:
135
+ sql: The original SQL string.
136
+ tokens: The anonymized tokens to render.
137
+ dialect: The dialect used to identify comments and quotes in `sql`.
138
+ """
139
+ tokenizer_class = Dialect.get_or_raise(dialect).tokenizer_class
140
+ comments = sorted(tokenizer_class._COMMENTS.items(), key=lambda c: len(c[0]), reverse=True)
141
+ nested = tokenizer_class.NESTED_COMMENTS
142
+ quotes = sorted(
143
+ {
144
+ **tokenizer_class._QUOTES,
145
+ **{start: end for start, (end, _) in tokenizer_class._FORMAT_STRINGS.items()},
146
+ **tokenizer_class._IDENTIFIERS,
147
+ }.items(),
148
+ key=lambda quote: (len(quote[0]), len(quote[1])),
149
+ reverse=True,
150
+ )
151
+
152
+ result = []
153
+ prev = 0
154
+
155
+ for token in tokens:
156
+ result.append(_redact(sql[prev : token.start], comments, nested))
157
+ prev = token.end + 1
158
+ span = sql[token.start : prev]
159
+ if token.token_type in REWRITTEN_TYPES:
160
+ # Blanked in place by `anonymize`, or synthesized by it, so already span-shaped
161
+ result.append(token.text)
162
+ elif token.token_type in ANONYMIZED_TYPES:
163
+ result.append(_fit(span, token.text, quotes, token.token_type))
164
+ else:
165
+ result.append(span)
166
+
167
+ result.append(_redact(sql[prev:], comments, nested))
168
+
169
+ return "".join(result)
170
+
171
+
172
+ def _alias(counter: int, text: str) -> str:
173
+ digits = []
174
+ while counter:
175
+ counter, digit = divmod(counter, ALPHABET_SIZE)
176
+ digits.append(ALPHABET[digit])
177
+
178
+ letters = "".join(reversed(digits)).rjust(sum(not char.isspace() for char in text), "a")
179
+
180
+ alias = []
181
+ i = 0
182
+ for char in text:
183
+ if char.isspace():
184
+ alias.append(char)
185
+ else:
186
+ alias.append(letters[i])
187
+ i += 1
188
+
189
+ return "".join(alias)
190
+
191
+
192
+ def _number_alias(counter: int, text: str) -> str:
193
+ if len(text) > 4000:
194
+ digits_seen = False
195
+ blanked = []
196
+ for char in text:
197
+ if char.isdigit():
198
+ blanked.append("0" if digits_seen else "1")
199
+ digits_seen = True
200
+ else:
201
+ blanked.append(char)
202
+ return "".join(blanked)
203
+
204
+ sep = "e" if "e" in text else ("E" if "E" in text else "")
205
+ mantissa, _, exponent = text.partition(sep) if sep else (text, "", "")
206
+ sign = ""
207
+ if exponent.startswith(("-", "+")):
208
+ sign, exponent = exponent[0], exponent[1:]
209
+ exponent_length = len(exponent)
210
+
211
+ integer, dot, fraction = mantissa.partition(".")
212
+ integer_length = len(integer)
213
+ digits = integer_length + len(fraction)
214
+ mantissa_value = 10 ** (digits - 1) + counter % (9 * 10 ** (digits - 1))
215
+ result = str(mantissa_value)
216
+ if dot:
217
+ result = result[:integer_length] + "." + result[integer_length:]
218
+ if sep:
219
+ # The exponent marker is kept even when there are no digits after it, e.g. 1e
220
+ result += sep + sign
221
+ if exponent_length:
222
+ exponent_value = 10 ** (exponent_length - 1) + (counter // (9 * 10 ** (digits - 1))) % (
223
+ 9 * 10 ** (exponent_length - 1)
224
+ )
225
+ result += str(exponent_value)
226
+
227
+ return result
228
+
229
+
230
+ def _fit(span: str, alias: str, quotes: list[tuple[str, str]], token_type: TokenType) -> str:
231
+ """Fits `alias` into the quoted region of `span`, so the two are always the same length."""
232
+ start = end = 0
233
+
234
+ if token_type in QUOTED_TYPES:
235
+ for open_quote, close_quote in quotes:
236
+ if (
237
+ len(span) >= len(open_quote) + len(close_quote)
238
+ and span.startswith(open_quote)
239
+ and span.endswith(close_quote)
240
+ ):
241
+ start, end = len(open_quote), len(close_quote)
242
+
243
+ if token_type == TokenType.HEREDOC_STRING:
244
+ # A heredoc's tag is part of its delimiter, e.g. $tag$body$tag$
245
+ open_end = span.find(close_quote, start)
246
+ close_start = span.rfind(open_quote, 0, len(span) - end)
247
+ if start <= open_end < close_start:
248
+ start, end = open_end + len(close_quote), len(span) - close_start
249
+
250
+ break
251
+
252
+ width = len(span) - start - end
253
+ pad = "0" if token_type == TokenType.NUMBER else "a"
254
+
255
+ return span[:start] + alias[:width].rjust(width, pad) + span[len(span) - end :]
256
+
257
+
258
+ def _blank(sql: str) -> str:
259
+ return "".join(char if char.isspace() else "." for char in sql)
260
+
261
+
262
+ def _blank_comment(sql: str, i: int, start: str, end: str | None, nested: bool) -> tuple[str, int]:
263
+ """Blanks the body of the comment at `i`, returning its text and the index past it."""
264
+ body = i + len(start)
265
+
266
+ if not end:
267
+ stop = sql.find("\n", body)
268
+ stop = len(sql) if stop == -1 else stop
269
+ return start + _blank(sql[body:stop]), stop
270
+
271
+ depth = 1
272
+ j = body
273
+ while j < len(sql):
274
+ if nested and sql.startswith(start, j):
275
+ depth += 1
276
+ j += len(start)
277
+ elif sql.startswith(end, j):
278
+ j += len(end)
279
+ depth -= 1
280
+ if not depth:
281
+ return start + _blank(sql[body : j - len(end)]) + end, j
282
+ else:
283
+ j += 1
284
+
285
+ return start + _blank(sql[body:]), len(sql)
286
+
287
+
288
+ def _redact(sql: str, comments: list[tuple[str, str | None]], nested: bool) -> str:
289
+ if not sql or sql.isspace():
290
+ return sql
291
+
292
+ result = []
293
+ i = 0
294
+ length = len(sql)
295
+
296
+ while i < length:
297
+ for start, end in comments:
298
+ if sql.startswith(start, i):
299
+ text, i = _blank_comment(sql, i, start, end, nested)
300
+ result.append(text)
301
+ break
302
+ else:
303
+ char = sql[i]
304
+ result.append(char if char.isspace() else ".")
305
+ i += 1
306
+
307
+ return "".join(result)
@@ -193,11 +193,8 @@ class BigQuery(Dialect):
193
193
  "EXCEPTION": TokenType.COMMAND,
194
194
  "EXPORT": TokenType.EXPORT,
195
195
  "FLOAT64": TokenType.DOUBLE,
196
- "FOR SYSTEM TIME": TokenType.TIMESTAMP_SNAPSHOT,
197
- "FOR SYSTEM_TIME": TokenType.TIMESTAMP_SNAPSHOT,
198
196
  "LOOP": TokenType.COMMAND,
199
197
  "MODEL": TokenType.MODEL,
200
- "NOT DETERMINISTIC": TokenType.VOLATILE,
201
198
  "RECORD": TokenType.STRUCT,
202
199
  "REPEAT": TokenType.COMMAND,
203
200
  "TIMESTAMP": TokenType.TIMESTAMPTZ,
@@ -17,7 +17,6 @@ class ClickHouse(Dialect):
17
17
  NORMALIZE_FUNCTIONS: bool | str = False
18
18
  NULL_ORDERING = "nulls_are_last"
19
19
  SUPPORTS_USER_DEFINED_TYPES = False
20
- SAFE_DIVISION = True
21
20
  LOG_BASE_FIRST: bool | None = None
22
21
  FORCE_EARLY_ALIAS_REF_EXPANSION = True
23
22
  PRESERVE_ORIGINAL_NAMES = True
@@ -24,6 +24,7 @@ from sqlglot.helper import (
24
24
  ensure_list,
25
25
  )
26
26
  from sqlglot.jsonpath import ALL_JSON_PATH_PARTS, JSONPathTokenizer, parse as parse_json_path
27
+ from sqlglot.optimizer.scope import find_all_in_scope
27
28
  from sqlglot.parser import Parser
28
29
  from sqlglot.parsers.base import BaseParser
29
30
  from sqlglot.time import TIMEZONES, format_time, subsecond_precision
@@ -1700,7 +1701,7 @@ def timestamptrunc_sql(
1700
1701
  func: str = "DATE_TRUNC", zone: bool = False
1701
1702
  ) -> t.Callable[[Generator, exp.TimestampTrunc], str]:
1702
1703
  def _timestamptrunc_sql(self: Generator, expression: exp.TimestampTrunc) -> str:
1703
- args = [unit_to_str(expression), expression.this]
1704
+ args = [weekstart_unit_to_str(self, expression), expression.this]
1704
1705
  if zone:
1705
1706
  args.append(expression.args.get("zone"))
1706
1707
  return self.func(func, *args)
@@ -1993,6 +1994,23 @@ def ts_or_ds_add_cast(expression: exp.TsOrDsAdd) -> exp.TsOrDsAdd:
1993
1994
  return expression
1994
1995
 
1995
1996
 
1997
+ def remove_ts_or_ds_to_date(
1998
+ to_sql: t.Callable[[Generator, exp.Expr], str] | None = None,
1999
+ args: tuple[str, ...] = ("this",),
2000
+ ) -> t.Callable[[Generator, exp.Func], str]:
2001
+ def func(self: Generator, expression: exp.Func) -> str:
2002
+ for arg_key in args:
2003
+ arg = expression.args.get(arg_key)
2004
+ if isinstance(arg, (exp.TsOrDsToDate, exp.TsOrDsToTimestamp)) and not arg.args.get(
2005
+ "format"
2006
+ ):
2007
+ expression.set(arg_key, arg.this)
2008
+
2009
+ return to_sql(self, expression) if to_sql else self.function_fallback_sql(expression)
2010
+
2011
+ return func
2012
+
2013
+
1996
2014
  def date_delta_sql(name: str, cast: bool = False) -> t.Callable[[Generator, DATE_ADD_OR_DIFF], str]:
1997
2015
  def _delta_sql(self: Generator, expression: DATE_ADD_OR_DIFF) -> str:
1998
2016
  if cast and isinstance(expression, exp.TsOrDsAdd):
@@ -2043,12 +2061,28 @@ def unit_to_str(expression: exp.Expr, default: str = "DAY") -> exp.Expr | None:
2043
2061
  if not unit:
2044
2062
  return exp.Literal.string(default) if default else None
2045
2063
 
2064
+ if isinstance(unit, exp.WeekStart):
2065
+ # WEEK(<day>) is BigQuery-only syntax, so it degrades to the plain WEEK unit. Unlike
2066
+ # Generator.weekstart_name, this can't warn about a changed week start (no generator
2067
+ # access here) - callers that need the warning should use weekstart_unit_to_str
2068
+ return exp.Literal.string("WEEK")
2069
+
2046
2070
  if isinstance(unit, exp.Placeholder) or type(unit) not in (exp.Var, exp.Literal):
2047
2071
  return unit
2048
2072
 
2049
2073
  return exp.Literal.string(unit.name)
2050
2074
 
2051
2075
 
2076
+ def weekstart_unit_to_str(
2077
+ self: Generator, expression: exp.Expr, default: str = "DAY"
2078
+ ) -> exp.Expr | None:
2079
+ unit = expression.args.get("unit")
2080
+ if isinstance(unit, exp.WeekStart):
2081
+ return exp.Literal.string(self.weekstart_name(unit))
2082
+
2083
+ return unit_to_str(expression, default)
2084
+
2085
+
2052
2086
  def unit_to_var(expression: exp.Expr, default: str = "DAY") -> exp.Expr | None:
2053
2087
  unit = expression.args.get("unit")
2054
2088
 
@@ -2072,10 +2106,14 @@ WEEK_START_DAY_TO_DOW = {
2072
2106
  }
2073
2107
 
2074
2108
 
2109
+ def week_offset_to_dow(offset: int) -> int:
2110
+ """Convert a dialect's WEEK_OFFSET (days relative to Monday) to the ISO day number of its week start."""
2111
+ return offset % 7 + 1
2112
+
2113
+
2075
2114
  def week_unit_to_dow(unit: exp.Expr | None) -> int | None:
2076
2115
  """
2077
- Compute the week start day for a week-ish diff unit, e.g BigQuery's WEEK(<day>)
2078
- or ISOWEEK unit parts.
2116
+ Compute the week start day for a week-ish diff unit, e.g BigQuery's WEEK(<day>) or ISOWEEK unit parts.
2079
2117
 
2080
2118
  Args:
2081
2119
  unit: The unit expression (Var for WEEK/ISOWEEK or WeekStart)
@@ -2147,7 +2185,7 @@ def merge_without_target_sql(self: Generator, expression: exp.Merge) -> str:
2147
2185
  then: exp.Insert | exp.Update | None = when.args.get("then")
2148
2186
  if then:
2149
2187
  if isinstance(then, exp.Update):
2150
- for equals in then.find_all(exp.EQ):
2188
+ for equals in find_all_in_scope(then, exp.EQ):
2151
2189
  equal_lhs = equals.this
2152
2190
  if (
2153
2191
  isinstance(equal_lhs, exp.Column)
@@ -2175,7 +2213,11 @@ def build_json_extract_path(
2175
2213
  for arg in args[1:]:
2176
2214
  if not isinstance(arg, exp.Literal):
2177
2215
  # We use the fallback parser because we can't really transpile non-literals safely
2178
- return expr_type.from_arg_list(args)
2216
+ return expr_type(
2217
+ this=seq_get(args, 0),
2218
+ expression=seq_get(args, 1),
2219
+ expressions=list(args[2:]) or None,
2220
+ )
2179
2221
 
2180
2222
  text = arg.name
2181
2223
  if is_int(text) and (not arrow_req_json_type or not arg.is_string):
@@ -67,12 +67,6 @@ class Dremio(Dialect):
67
67
  class Tokenizer(tokens.Tokenizer):
68
68
  COMMENTS = ["--", "//", ("/*", "*/")]
69
69
 
70
- KEYWORDS = {
71
- **tokens.Tokenizer.KEYWORDS,
72
- "AT SNAPSHOT": tokens.TokenType.VERSION_SNAPSHOT,
73
- "AT TIMESTAMP": tokens.TokenType.TIMESTAMP_SNAPSHOT,
74
- }
75
-
76
70
  Parser = DremioParser
77
71
 
78
72
  Generator = DremioGenerator
@@ -16,7 +16,6 @@ from sqlglot.typing.duckdb import EXPRESSION_METADATA
16
16
  class DuckDB(Dialect):
17
17
  NULL_ORDERING = "nulls_are_last"
18
18
  SUPPORTS_USER_DEFINED_TYPES = True
19
- SAFE_DIVISION = True
20
19
  INDEX_OFFSET = 1
21
20
  CONCAT_COALESCE = True
22
21
  CONCAT_WS_COALESCE = True
@@ -109,8 +109,6 @@ class Hive(Dialect):
109
109
  "MINUS": TokenType.EXCEPT,
110
110
  "MSCK REPAIR": TokenType.COMMAND,
111
111
  "REFRESH": TokenType.REFRESH,
112
- "TIMESTAMP AS OF": TokenType.TIMESTAMP_SNAPSHOT,
113
- "VERSION AS OF": TokenType.VERSION_SNAPSHOT,
114
112
  "SERDEPROPERTIES": TokenType.SERDE_PROPERTIES,
115
113
  }
116
114
 
@@ -96,7 +96,6 @@ class MySQL(Dialect):
96
96
  "SERIAL": TokenType.SERIAL,
97
97
  "SIGNED": TokenType.BIGINT,
98
98
  "SIGNED INTEGER": TokenType.BIGINT,
99
- "SOUNDS LIKE": TokenType.SOUNDS_LIKE,
100
99
  "START": TokenType.BEGIN,
101
100
  "TIMESTAMP": TokenType.TIMESTAMPTZ,
102
101
  "TINYBLOB": TokenType.TINYBLOB,
@@ -14,6 +14,7 @@ class StarRocks(MySQL):
14
14
  KEYWORDS = {
15
15
  **MySQL.Tokenizer.KEYWORDS,
16
16
  "LARGEINT": TokenType.INT128,
17
+ "REFRESH": TokenType.REFRESH,
17
18
  }
18
19
 
19
20
  Parser = StarRocksParser