sqlglot 27.18.0__tar.gz → 27.20.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 (228) hide show
  1. {sqlglot-27.18.0 → sqlglot-27.20.0}/CHANGELOG.md +84 -0
  2. {sqlglot-27.18.0 → sqlglot-27.20.0}/Makefile +8 -2
  3. {sqlglot-27.18.0 → sqlglot-27.20.0}/PKG-INFO +3 -1
  4. {sqlglot-27.18.0 → sqlglot-27.20.0}/README.md +2 -0
  5. {sqlglot-27.18.0 → sqlglot-27.20.0}/sqlglot/_version.py +3 -3
  6. {sqlglot-27.18.0 → sqlglot-27.20.0}/sqlglot/dialects/bigquery.py +25 -9
  7. {sqlglot-27.18.0 → sqlglot-27.20.0}/sqlglot/dialects/snowflake.py +31 -0
  8. {sqlglot-27.18.0 → sqlglot-27.20.0}/sqlglot/dialects/sqlite.py +9 -0
  9. {sqlglot-27.18.0 → sqlglot-27.20.0}/sqlglot/dialects/starrocks.py +3 -0
  10. {sqlglot-27.18.0 → sqlglot-27.20.0}/sqlglot/expressions.py +92 -25
  11. {sqlglot-27.18.0 → sqlglot-27.20.0}/sqlglot/generator.py +3 -0
  12. {sqlglot-27.18.0 → sqlglot-27.20.0}/sqlglot/helper.py +0 -18
  13. {sqlglot-27.18.0 → sqlglot-27.20.0}/sqlglot/parser.py +3 -1
  14. {sqlglot-27.18.0 → sqlglot-27.20.0}/sqlglot.egg-info/PKG-INFO +3 -1
  15. {sqlglot-27.18.0 → sqlglot-27.20.0}/tests/dialects/test_bigquery.py +1 -0
  16. {sqlglot-27.18.0 → sqlglot-27.20.0}/tests/dialects/test_databricks.py +4 -0
  17. {sqlglot-27.18.0 → sqlglot-27.20.0}/tests/dialects/test_snowflake.py +48 -0
  18. {sqlglot-27.18.0 → sqlglot-27.20.0}/tests/dialects/test_sqlite.py +1 -0
  19. {sqlglot-27.18.0 → sqlglot-27.20.0}/tests/dialects/test_starrocks.py +3 -0
  20. {sqlglot-27.18.0 → sqlglot-27.20.0}/tests/fixtures/optimizer/annotate_functions.sql +104 -0
  21. {sqlglot-27.18.0 → sqlglot-27.20.0}/tests/test_expressions.py +8 -0
  22. {sqlglot-27.18.0 → sqlglot-27.20.0}/tests/test_parser.py +21 -0
  23. {sqlglot-27.18.0 → sqlglot-27.20.0}/.gitignore +0 -0
  24. {sqlglot-27.18.0 → sqlglot-27.20.0}/.gitpod.yml +0 -0
  25. {sqlglot-27.18.0 → sqlglot-27.20.0}/.pre-commit-config.yaml +0 -0
  26. {sqlglot-27.18.0 → sqlglot-27.20.0}/CONTRIBUTING.md +0 -0
  27. {sqlglot-27.18.0 → sqlglot-27.20.0}/LICENSE +0 -0
  28. {sqlglot-27.18.0 → sqlglot-27.20.0}/MANIFEST.in +0 -0
  29. {sqlglot-27.18.0 → sqlglot-27.20.0}/pyproject.toml +0 -0
  30. {sqlglot-27.18.0 → sqlglot-27.20.0}/setup.cfg +0 -0
  31. {sqlglot-27.18.0 → sqlglot-27.20.0}/setup.py +0 -0
  32. {sqlglot-27.18.0 → sqlglot-27.20.0}/sqlglot/__init__.py +0 -0
  33. {sqlglot-27.18.0 → sqlglot-27.20.0}/sqlglot/__main__.py +0 -0
  34. {sqlglot-27.18.0 → sqlglot-27.20.0}/sqlglot/_typing.py +0 -0
  35. {sqlglot-27.18.0 → sqlglot-27.20.0}/sqlglot/dialects/__init__.py +0 -0
  36. {sqlglot-27.18.0 → sqlglot-27.20.0}/sqlglot/dialects/athena.py +0 -0
  37. {sqlglot-27.18.0 → sqlglot-27.20.0}/sqlglot/dialects/clickhouse.py +0 -0
  38. {sqlglot-27.18.0 → sqlglot-27.20.0}/sqlglot/dialects/databricks.py +0 -0
  39. {sqlglot-27.18.0 → sqlglot-27.20.0}/sqlglot/dialects/dialect.py +0 -0
  40. {sqlglot-27.18.0 → sqlglot-27.20.0}/sqlglot/dialects/doris.py +0 -0
  41. {sqlglot-27.18.0 → sqlglot-27.20.0}/sqlglot/dialects/dremio.py +0 -0
  42. {sqlglot-27.18.0 → sqlglot-27.20.0}/sqlglot/dialects/drill.py +0 -0
  43. {sqlglot-27.18.0 → sqlglot-27.20.0}/sqlglot/dialects/druid.py +0 -0
  44. {sqlglot-27.18.0 → sqlglot-27.20.0}/sqlglot/dialects/duckdb.py +0 -0
  45. {sqlglot-27.18.0 → sqlglot-27.20.0}/sqlglot/dialects/dune.py +0 -0
  46. {sqlglot-27.18.0 → sqlglot-27.20.0}/sqlglot/dialects/exasol.py +0 -0
  47. {sqlglot-27.18.0 → sqlglot-27.20.0}/sqlglot/dialects/fabric.py +0 -0
  48. {sqlglot-27.18.0 → sqlglot-27.20.0}/sqlglot/dialects/hive.py +0 -0
  49. {sqlglot-27.18.0 → sqlglot-27.20.0}/sqlglot/dialects/materialize.py +0 -0
  50. {sqlglot-27.18.0 → sqlglot-27.20.0}/sqlglot/dialects/mysql.py +0 -0
  51. {sqlglot-27.18.0 → sqlglot-27.20.0}/sqlglot/dialects/oracle.py +0 -0
  52. {sqlglot-27.18.0 → sqlglot-27.20.0}/sqlglot/dialects/postgres.py +0 -0
  53. {sqlglot-27.18.0 → sqlglot-27.20.0}/sqlglot/dialects/presto.py +0 -0
  54. {sqlglot-27.18.0 → sqlglot-27.20.0}/sqlglot/dialects/prql.py +0 -0
  55. {sqlglot-27.18.0 → sqlglot-27.20.0}/sqlglot/dialects/redshift.py +0 -0
  56. {sqlglot-27.18.0 → sqlglot-27.20.0}/sqlglot/dialects/risingwave.py +0 -0
  57. {sqlglot-27.18.0 → sqlglot-27.20.0}/sqlglot/dialects/singlestore.py +0 -0
  58. {sqlglot-27.18.0 → sqlglot-27.20.0}/sqlglot/dialects/solr.py +0 -0
  59. {sqlglot-27.18.0 → sqlglot-27.20.0}/sqlglot/dialects/spark.py +0 -0
  60. {sqlglot-27.18.0 → sqlglot-27.20.0}/sqlglot/dialects/spark2.py +0 -0
  61. {sqlglot-27.18.0 → sqlglot-27.20.0}/sqlglot/dialects/tableau.py +0 -0
  62. {sqlglot-27.18.0 → sqlglot-27.20.0}/sqlglot/dialects/teradata.py +0 -0
  63. {sqlglot-27.18.0 → sqlglot-27.20.0}/sqlglot/dialects/trino.py +0 -0
  64. {sqlglot-27.18.0 → sqlglot-27.20.0}/sqlglot/dialects/tsql.py +0 -0
  65. {sqlglot-27.18.0 → sqlglot-27.20.0}/sqlglot/diff.py +0 -0
  66. {sqlglot-27.18.0 → sqlglot-27.20.0}/sqlglot/errors.py +0 -0
  67. {sqlglot-27.18.0 → sqlglot-27.20.0}/sqlglot/executor/__init__.py +0 -0
  68. {sqlglot-27.18.0 → sqlglot-27.20.0}/sqlglot/executor/context.py +0 -0
  69. {sqlglot-27.18.0 → sqlglot-27.20.0}/sqlglot/executor/env.py +0 -0
  70. {sqlglot-27.18.0 → sqlglot-27.20.0}/sqlglot/executor/python.py +0 -0
  71. {sqlglot-27.18.0 → sqlglot-27.20.0}/sqlglot/executor/table.py +0 -0
  72. {sqlglot-27.18.0 → sqlglot-27.20.0}/sqlglot/jsonpath.py +0 -0
  73. {sqlglot-27.18.0 → sqlglot-27.20.0}/sqlglot/lineage.py +0 -0
  74. {sqlglot-27.18.0 → sqlglot-27.20.0}/sqlglot/optimizer/__init__.py +0 -0
  75. {sqlglot-27.18.0 → sqlglot-27.20.0}/sqlglot/optimizer/annotate_types.py +0 -0
  76. {sqlglot-27.18.0 → sqlglot-27.20.0}/sqlglot/optimizer/canonicalize.py +0 -0
  77. {sqlglot-27.18.0 → sqlglot-27.20.0}/sqlglot/optimizer/eliminate_ctes.py +0 -0
  78. {sqlglot-27.18.0 → sqlglot-27.20.0}/sqlglot/optimizer/eliminate_joins.py +0 -0
  79. {sqlglot-27.18.0 → sqlglot-27.20.0}/sqlglot/optimizer/eliminate_subqueries.py +0 -0
  80. {sqlglot-27.18.0 → sqlglot-27.20.0}/sqlglot/optimizer/isolate_table_selects.py +0 -0
  81. {sqlglot-27.18.0 → sqlglot-27.20.0}/sqlglot/optimizer/merge_subqueries.py +0 -0
  82. {sqlglot-27.18.0 → sqlglot-27.20.0}/sqlglot/optimizer/normalize.py +0 -0
  83. {sqlglot-27.18.0 → sqlglot-27.20.0}/sqlglot/optimizer/normalize_identifiers.py +0 -0
  84. {sqlglot-27.18.0 → sqlglot-27.20.0}/sqlglot/optimizer/optimize_joins.py +0 -0
  85. {sqlglot-27.18.0 → sqlglot-27.20.0}/sqlglot/optimizer/optimizer.py +0 -0
  86. {sqlglot-27.18.0 → sqlglot-27.20.0}/sqlglot/optimizer/pushdown_predicates.py +0 -0
  87. {sqlglot-27.18.0 → sqlglot-27.20.0}/sqlglot/optimizer/pushdown_projections.py +0 -0
  88. {sqlglot-27.18.0 → sqlglot-27.20.0}/sqlglot/optimizer/qualify.py +0 -0
  89. {sqlglot-27.18.0 → sqlglot-27.20.0}/sqlglot/optimizer/qualify_columns.py +0 -0
  90. {sqlglot-27.18.0 → sqlglot-27.20.0}/sqlglot/optimizer/qualify_tables.py +0 -0
  91. {sqlglot-27.18.0 → sqlglot-27.20.0}/sqlglot/optimizer/scope.py +0 -0
  92. {sqlglot-27.18.0 → sqlglot-27.20.0}/sqlglot/optimizer/simplify.py +0 -0
  93. {sqlglot-27.18.0 → sqlglot-27.20.0}/sqlglot/optimizer/unnest_subqueries.py +0 -0
  94. {sqlglot-27.18.0 → sqlglot-27.20.0}/sqlglot/planner.py +0 -0
  95. {sqlglot-27.18.0 → sqlglot-27.20.0}/sqlglot/py.typed +0 -0
  96. {sqlglot-27.18.0 → sqlglot-27.20.0}/sqlglot/schema.py +0 -0
  97. {sqlglot-27.18.0 → sqlglot-27.20.0}/sqlglot/serde.py +0 -0
  98. {sqlglot-27.18.0 → sqlglot-27.20.0}/sqlglot/time.py +0 -0
  99. {sqlglot-27.18.0 → sqlglot-27.20.0}/sqlglot/tokens.py +0 -0
  100. {sqlglot-27.18.0 → sqlglot-27.20.0}/sqlglot/transforms.py +0 -0
  101. {sqlglot-27.18.0 → sqlglot-27.20.0}/sqlglot/trie.py +0 -0
  102. {sqlglot-27.18.0 → sqlglot-27.20.0}/sqlglot.egg-info/SOURCES.txt +0 -0
  103. {sqlglot-27.18.0 → sqlglot-27.20.0}/sqlglot.egg-info/dependency_links.txt +0 -0
  104. {sqlglot-27.18.0 → sqlglot-27.20.0}/sqlglot.egg-info/requires.txt +0 -0
  105. {sqlglot-27.18.0 → sqlglot-27.20.0}/sqlglot.egg-info/top_level.txt +0 -0
  106. {sqlglot-27.18.0 → sqlglot-27.20.0}/sqlglot.png +0 -0
  107. {sqlglot-27.18.0 → sqlglot-27.20.0}/sqlglotrs/Cargo.lock +0 -0
  108. {sqlglot-27.18.0 → sqlglot-27.20.0}/sqlglotrs/Cargo.toml +0 -0
  109. {sqlglot-27.18.0 → sqlglot-27.20.0}/sqlglotrs/benches/dialect_settings.json +0 -0
  110. {sqlglot-27.18.0 → sqlglot-27.20.0}/sqlglotrs/benches/long.rs +0 -0
  111. {sqlglot-27.18.0 → sqlglot-27.20.0}/sqlglotrs/benches/token_type_settings.json +0 -0
  112. {sqlglot-27.18.0 → sqlglot-27.20.0}/sqlglotrs/benches/tokenizer_dialect_settings.json +0 -0
  113. {sqlglot-27.18.0 → sqlglot-27.20.0}/sqlglotrs/benches/tokenizer_settings.json +0 -0
  114. {sqlglot-27.18.0 → sqlglot-27.20.0}/sqlglotrs/pyproject.toml +0 -0
  115. {sqlglot-27.18.0 → sqlglot-27.20.0}/sqlglotrs/src/lib.rs +0 -0
  116. {sqlglot-27.18.0 → sqlglot-27.20.0}/sqlglotrs/src/settings.rs +0 -0
  117. {sqlglot-27.18.0 → sqlglot-27.20.0}/sqlglotrs/src/token.rs +0 -0
  118. {sqlglot-27.18.0 → sqlglot-27.20.0}/sqlglotrs/src/tokenizer.rs +0 -0
  119. {sqlglot-27.18.0 → sqlglot-27.20.0}/sqlglotrs/src/trie.rs +0 -0
  120. {sqlglot-27.18.0 → sqlglot-27.20.0}/tests/__init__.py +0 -0
  121. {sqlglot-27.18.0 → sqlglot-27.20.0}/tests/dialects/__init__.py +0 -0
  122. {sqlglot-27.18.0 → sqlglot-27.20.0}/tests/dialects/test_athena.py +0 -0
  123. {sqlglot-27.18.0 → sqlglot-27.20.0}/tests/dialects/test_clickhouse.py +0 -0
  124. {sqlglot-27.18.0 → sqlglot-27.20.0}/tests/dialects/test_dialect.py +0 -0
  125. {sqlglot-27.18.0 → sqlglot-27.20.0}/tests/dialects/test_doris.py +0 -0
  126. {sqlglot-27.18.0 → sqlglot-27.20.0}/tests/dialects/test_dremio.py +0 -0
  127. {sqlglot-27.18.0 → sqlglot-27.20.0}/tests/dialects/test_drill.py +0 -0
  128. {sqlglot-27.18.0 → sqlglot-27.20.0}/tests/dialects/test_druid.py +0 -0
  129. {sqlglot-27.18.0 → sqlglot-27.20.0}/tests/dialects/test_duckdb.py +0 -0
  130. {sqlglot-27.18.0 → sqlglot-27.20.0}/tests/dialects/test_dune.py +0 -0
  131. {sqlglot-27.18.0 → sqlglot-27.20.0}/tests/dialects/test_exasol.py +0 -0
  132. {sqlglot-27.18.0 → sqlglot-27.20.0}/tests/dialects/test_fabric.py +0 -0
  133. {sqlglot-27.18.0 → sqlglot-27.20.0}/tests/dialects/test_hive.py +0 -0
  134. {sqlglot-27.18.0 → sqlglot-27.20.0}/tests/dialects/test_materialize.py +0 -0
  135. {sqlglot-27.18.0 → sqlglot-27.20.0}/tests/dialects/test_mysql.py +0 -0
  136. {sqlglot-27.18.0 → sqlglot-27.20.0}/tests/dialects/test_oracle.py +0 -0
  137. {sqlglot-27.18.0 → sqlglot-27.20.0}/tests/dialects/test_pipe_syntax.py +0 -0
  138. {sqlglot-27.18.0 → sqlglot-27.20.0}/tests/dialects/test_postgres.py +0 -0
  139. {sqlglot-27.18.0 → sqlglot-27.20.0}/tests/dialects/test_presto.py +0 -0
  140. {sqlglot-27.18.0 → sqlglot-27.20.0}/tests/dialects/test_prql.py +0 -0
  141. {sqlglot-27.18.0 → sqlglot-27.20.0}/tests/dialects/test_redshift.py +0 -0
  142. {sqlglot-27.18.0 → sqlglot-27.20.0}/tests/dialects/test_risingwave.py +0 -0
  143. {sqlglot-27.18.0 → sqlglot-27.20.0}/tests/dialects/test_singlestore.py +0 -0
  144. {sqlglot-27.18.0 → sqlglot-27.20.0}/tests/dialects/test_solr.py +0 -0
  145. {sqlglot-27.18.0 → sqlglot-27.20.0}/tests/dialects/test_spark.py +0 -0
  146. {sqlglot-27.18.0 → sqlglot-27.20.0}/tests/dialects/test_tableau.py +0 -0
  147. {sqlglot-27.18.0 → sqlglot-27.20.0}/tests/dialects/test_teradata.py +0 -0
  148. {sqlglot-27.18.0 → sqlglot-27.20.0}/tests/dialects/test_trino.py +0 -0
  149. {sqlglot-27.18.0 → sqlglot-27.20.0}/tests/dialects/test_tsql.py +0 -0
  150. {sqlglot-27.18.0 → sqlglot-27.20.0}/tests/fixtures/identity.sql +0 -0
  151. {sqlglot-27.18.0 → sqlglot-27.20.0}/tests/fixtures/jsonpath/LICENSE +0 -0
  152. {sqlglot-27.18.0 → sqlglot-27.20.0}/tests/fixtures/jsonpath/cts.json +0 -0
  153. {sqlglot-27.18.0 → sqlglot-27.20.0}/tests/fixtures/optimizer/annotate_types.sql +0 -0
  154. {sqlglot-27.18.0 → sqlglot-27.20.0}/tests/fixtures/optimizer/canonicalize.sql +0 -0
  155. {sqlglot-27.18.0 → sqlglot-27.20.0}/tests/fixtures/optimizer/eliminate_ctes.sql +0 -0
  156. {sqlglot-27.18.0 → sqlglot-27.20.0}/tests/fixtures/optimizer/eliminate_joins.sql +0 -0
  157. {sqlglot-27.18.0 → sqlglot-27.20.0}/tests/fixtures/optimizer/eliminate_subqueries.sql +0 -0
  158. {sqlglot-27.18.0 → sqlglot-27.20.0}/tests/fixtures/optimizer/isolate_table_selects.sql +0 -0
  159. {sqlglot-27.18.0 → sqlglot-27.20.0}/tests/fixtures/optimizer/merge_subqueries.sql +0 -0
  160. {sqlglot-27.18.0 → sqlglot-27.20.0}/tests/fixtures/optimizer/normalize.sql +0 -0
  161. {sqlglot-27.18.0 → sqlglot-27.20.0}/tests/fixtures/optimizer/normalize_identifiers.sql +0 -0
  162. {sqlglot-27.18.0 → sqlglot-27.20.0}/tests/fixtures/optimizer/optimize_joins.sql +0 -0
  163. {sqlglot-27.18.0 → sqlglot-27.20.0}/tests/fixtures/optimizer/optimizer.sql +0 -0
  164. {sqlglot-27.18.0 → sqlglot-27.20.0}/tests/fixtures/optimizer/pushdown_cte_alias_columns.sql +0 -0
  165. {sqlglot-27.18.0 → sqlglot-27.20.0}/tests/fixtures/optimizer/pushdown_predicates.sql +0 -0
  166. {sqlglot-27.18.0 → sqlglot-27.20.0}/tests/fixtures/optimizer/pushdown_projections.sql +0 -0
  167. {sqlglot-27.18.0 → sqlglot-27.20.0}/tests/fixtures/optimizer/qualify_columns.sql +0 -0
  168. {sqlglot-27.18.0 → sqlglot-27.20.0}/tests/fixtures/optimizer/qualify_columns__invalid.sql +0 -0
  169. {sqlglot-27.18.0 → sqlglot-27.20.0}/tests/fixtures/optimizer/qualify_columns__with_invisible.sql +0 -0
  170. {sqlglot-27.18.0 → sqlglot-27.20.0}/tests/fixtures/optimizer/qualify_columns_ddl.sql +0 -0
  171. {sqlglot-27.18.0 → sqlglot-27.20.0}/tests/fixtures/optimizer/qualify_tables.sql +0 -0
  172. {sqlglot-27.18.0 → sqlglot-27.20.0}/tests/fixtures/optimizer/quote_identifiers.sql +0 -0
  173. {sqlglot-27.18.0 → sqlglot-27.20.0}/tests/fixtures/optimizer/simplify.sql +0 -0
  174. {sqlglot-27.18.0 → sqlglot-27.20.0}/tests/fixtures/optimizer/tpc-ds/call_center.csv.gz +0 -0
  175. {sqlglot-27.18.0 → sqlglot-27.20.0}/tests/fixtures/optimizer/tpc-ds/catalog_page.csv.gz +0 -0
  176. {sqlglot-27.18.0 → sqlglot-27.20.0}/tests/fixtures/optimizer/tpc-ds/catalog_returns.csv.gz +0 -0
  177. {sqlglot-27.18.0 → sqlglot-27.20.0}/tests/fixtures/optimizer/tpc-ds/catalog_sales.csv.gz +0 -0
  178. {sqlglot-27.18.0 → sqlglot-27.20.0}/tests/fixtures/optimizer/tpc-ds/customer.csv.gz +0 -0
  179. {sqlglot-27.18.0 → sqlglot-27.20.0}/tests/fixtures/optimizer/tpc-ds/customer_address.csv.gz +0 -0
  180. {sqlglot-27.18.0 → sqlglot-27.20.0}/tests/fixtures/optimizer/tpc-ds/customer_demographics.csv.gz +0 -0
  181. {sqlglot-27.18.0 → sqlglot-27.20.0}/tests/fixtures/optimizer/tpc-ds/date_dim.csv.gz +0 -0
  182. {sqlglot-27.18.0 → sqlglot-27.20.0}/tests/fixtures/optimizer/tpc-ds/household_demographics.csv.gz +0 -0
  183. {sqlglot-27.18.0 → sqlglot-27.20.0}/tests/fixtures/optimizer/tpc-ds/income_band.csv.gz +0 -0
  184. {sqlglot-27.18.0 → sqlglot-27.20.0}/tests/fixtures/optimizer/tpc-ds/inventory.csv.gz +0 -0
  185. {sqlglot-27.18.0 → sqlglot-27.20.0}/tests/fixtures/optimizer/tpc-ds/item.csv.gz +0 -0
  186. {sqlglot-27.18.0 → sqlglot-27.20.0}/tests/fixtures/optimizer/tpc-ds/promotion.csv.gz +0 -0
  187. {sqlglot-27.18.0 → sqlglot-27.20.0}/tests/fixtures/optimizer/tpc-ds/reason.csv.gz +0 -0
  188. {sqlglot-27.18.0 → sqlglot-27.20.0}/tests/fixtures/optimizer/tpc-ds/ship_mode.csv.gz +0 -0
  189. {sqlglot-27.18.0 → sqlglot-27.20.0}/tests/fixtures/optimizer/tpc-ds/store.csv.gz +0 -0
  190. {sqlglot-27.18.0 → sqlglot-27.20.0}/tests/fixtures/optimizer/tpc-ds/store_returns.csv.gz +0 -0
  191. {sqlglot-27.18.0 → sqlglot-27.20.0}/tests/fixtures/optimizer/tpc-ds/store_sales.csv.gz +0 -0
  192. {sqlglot-27.18.0 → sqlglot-27.20.0}/tests/fixtures/optimizer/tpc-ds/time_dim.csv.gz +0 -0
  193. {sqlglot-27.18.0 → sqlglot-27.20.0}/tests/fixtures/optimizer/tpc-ds/tpc-ds.sql +0 -0
  194. {sqlglot-27.18.0 → sqlglot-27.20.0}/tests/fixtures/optimizer/tpc-ds/warehouse.csv.gz +0 -0
  195. {sqlglot-27.18.0 → sqlglot-27.20.0}/tests/fixtures/optimizer/tpc-ds/web_page.csv.gz +0 -0
  196. {sqlglot-27.18.0 → sqlglot-27.20.0}/tests/fixtures/optimizer/tpc-ds/web_returns.csv.gz +0 -0
  197. {sqlglot-27.18.0 → sqlglot-27.20.0}/tests/fixtures/optimizer/tpc-ds/web_sales.csv.gz +0 -0
  198. {sqlglot-27.18.0 → sqlglot-27.20.0}/tests/fixtures/optimizer/tpc-ds/web_site.csv.gz +0 -0
  199. {sqlglot-27.18.0 → sqlglot-27.20.0}/tests/fixtures/optimizer/tpc-h/customer.csv.gz +0 -0
  200. {sqlglot-27.18.0 → sqlglot-27.20.0}/tests/fixtures/optimizer/tpc-h/lineitem.csv.gz +0 -0
  201. {sqlglot-27.18.0 → sqlglot-27.20.0}/tests/fixtures/optimizer/tpc-h/nation.csv.gz +0 -0
  202. {sqlglot-27.18.0 → sqlglot-27.20.0}/tests/fixtures/optimizer/tpc-h/orders.csv.gz +0 -0
  203. {sqlglot-27.18.0 → sqlglot-27.20.0}/tests/fixtures/optimizer/tpc-h/part.csv.gz +0 -0
  204. {sqlglot-27.18.0 → sqlglot-27.20.0}/tests/fixtures/optimizer/tpc-h/partsupp.csv.gz +0 -0
  205. {sqlglot-27.18.0 → sqlglot-27.20.0}/tests/fixtures/optimizer/tpc-h/region.csv.gz +0 -0
  206. {sqlglot-27.18.0 → sqlglot-27.20.0}/tests/fixtures/optimizer/tpc-h/supplier.csv.gz +0 -0
  207. {sqlglot-27.18.0 → sqlglot-27.20.0}/tests/fixtures/optimizer/tpc-h/tpc-h.sql +0 -0
  208. {sqlglot-27.18.0 → sqlglot-27.20.0}/tests/fixtures/optimizer/unnest_subqueries.sql +0 -0
  209. {sqlglot-27.18.0 → sqlglot-27.20.0}/tests/fixtures/partial.sql +0 -0
  210. {sqlglot-27.18.0 → sqlglot-27.20.0}/tests/fixtures/pretty.sql +0 -0
  211. {sqlglot-27.18.0 → sqlglot-27.20.0}/tests/gen_fixtures.py +0 -0
  212. {sqlglot-27.18.0 → sqlglot-27.20.0}/tests/helpers.py +0 -0
  213. {sqlglot-27.18.0 → sqlglot-27.20.0}/tests/test_build.py +0 -0
  214. {sqlglot-27.18.0 → sqlglot-27.20.0}/tests/test_dialect_imports.py +0 -0
  215. {sqlglot-27.18.0 → sqlglot-27.20.0}/tests/test_diff.py +0 -0
  216. {sqlglot-27.18.0 → sqlglot-27.20.0}/tests/test_docs.py +0 -0
  217. {sqlglot-27.18.0 → sqlglot-27.20.0}/tests/test_executor.py +0 -0
  218. {sqlglot-27.18.0 → sqlglot-27.20.0}/tests/test_generator.py +0 -0
  219. {sqlglot-27.18.0 → sqlglot-27.20.0}/tests/test_helper.py +0 -0
  220. {sqlglot-27.18.0 → sqlglot-27.20.0}/tests/test_jsonpath.py +0 -0
  221. {sqlglot-27.18.0 → sqlglot-27.20.0}/tests/test_lineage.py +0 -0
  222. {sqlglot-27.18.0 → sqlglot-27.20.0}/tests/test_optimizer.py +0 -0
  223. {sqlglot-27.18.0 → sqlglot-27.20.0}/tests/test_schema.py +0 -0
  224. {sqlglot-27.18.0 → sqlglot-27.20.0}/tests/test_serde.py +0 -0
  225. {sqlglot-27.18.0 → sqlglot-27.20.0}/tests/test_time.py +0 -0
  226. {sqlglot-27.18.0 → sqlglot-27.20.0}/tests/test_tokens.py +0 -0
  227. {sqlglot-27.18.0 → sqlglot-27.20.0}/tests/test_transforms.py +0 -0
  228. {sqlglot-27.18.0 → sqlglot-27.20.0}/tests/test_transpile.py +0 -0
@@ -1,6 +1,88 @@
1
1
  Changelog
2
2
  =========
3
3
 
4
+ ## [v27.19.0] - 2025-09-26
5
+ ### :boom: BREAKING CHANGES
6
+ - due to [`68473ac`](https://github.com/tobymao/sqlglot/commit/68473ac3ec8dc76512dc76819892a1b0324c7ddc) - Annotate type for snowflake PARSE_URL function *(PR [#5962](https://github.com/tobymao/sqlglot/pull/5962) by [@fivetran-amrutabhimsenayachit](https://github.com/fivetran-amrutabhimsenayachit))*:
7
+
8
+ Annotate type for snowflake PARSE_URL function (#5962)
9
+
10
+ - due to [`b015a9d`](https://github.com/tobymao/sqlglot/commit/b015a9d944d0a87069a7750ad74953c399d7da34) - annotate type for Snowflake REGEXP_INSTR function *(commit by [@fivetran-BradfordPaskewitz](https://github.com/fivetran-BradfordPaskewitz))*:
11
+
12
+ annotate type for Snowflake REGEXP_INSTR function
13
+
14
+ - due to [`1f29ba7`](https://github.com/tobymao/sqlglot/commit/1f29ba710f4213beb1a2f993244d7d824f3536ce) - annotate type for Snowflake PARSE_IP function *(PR [#5961](https://github.com/tobymao/sqlglot/pull/5961) by [@fivetran-BradfordPaskewitz](https://github.com/fivetran-BradfordPaskewitz))*:
15
+
16
+ annotate type for Snowflake PARSE_IP function (#5961)
17
+
18
+ - due to [`bf45d5d`](https://github.com/tobymao/sqlglot/commit/bf45d5d3cb0c0f380824019eb32ec29049268a61) - annotate types for Snowflake RTRIMMED_LENGTH function *(PR [#5968](https://github.com/tobymao/sqlglot/pull/5968) by [@fivetran-BradfordPaskewitz](https://github.com/fivetran-BradfordPaskewitz))*:
19
+
20
+ annotate types for Snowflake RTRIMMED_LENGTH function (#5968)
21
+
22
+ - due to [`13caa69`](https://github.com/tobymao/sqlglot/commit/13caa6991f003ad7abb590073451e591b6fd888c) - Annotate type for snowflake POSITION function *(PR [#5964](https://github.com/tobymao/sqlglot/pull/5964) by [@fivetran-amrutabhimsenayachit](https://github.com/fivetran-amrutabhimsenayachit))*:
23
+
24
+ Annotate type for snowflake POSITION function (#5964)
25
+
26
+
27
+ ### :sparkles: New Features
28
+ - [`88e4e4c`](https://github.com/tobymao/sqlglot/commit/88e4e4c55f3a113127eb3c82c0be46c29bcf15ab) - **optimizer**: Annotate type for OCTET_LENGTH function *(PR [#5960](https://github.com/tobymao/sqlglot/pull/5960) by [@fivetran-amrutabhimsenayachit](https://github.com/fivetran-amrutabhimsenayachit))*
29
+ - [`68473ac`](https://github.com/tobymao/sqlglot/commit/68473ac3ec8dc76512dc76819892a1b0324c7ddc) - **optimizer**: Annotate type for snowflake PARSE_URL function *(PR [#5962](https://github.com/tobymao/sqlglot/pull/5962) by [@fivetran-amrutabhimsenayachit](https://github.com/fivetran-amrutabhimsenayachit))*
30
+ - [`b015a9d`](https://github.com/tobymao/sqlglot/commit/b015a9d944d0a87069a7750ad74953c399d7da34) - **optimizer**: annotate type for Snowflake REGEXP_INSTR function *(commit by [@fivetran-BradfordPaskewitz](https://github.com/fivetran-BradfordPaskewitz))*
31
+ - [`1f29ba7`](https://github.com/tobymao/sqlglot/commit/1f29ba710f4213beb1a2f993244d7d824f3536ce) - **optimizer**: annotate type for Snowflake PARSE_IP function *(PR [#5961](https://github.com/tobymao/sqlglot/pull/5961) by [@fivetran-BradfordPaskewitz](https://github.com/fivetran-BradfordPaskewitz))*
32
+ - [`bf45d5d`](https://github.com/tobymao/sqlglot/commit/bf45d5d3cb0c0f380824019eb32ec29049268a61) - **optimizer**: annotate types for Snowflake RTRIMMED_LENGTH function *(PR [#5968](https://github.com/tobymao/sqlglot/pull/5968) by [@fivetran-BradfordPaskewitz](https://github.com/fivetran-BradfordPaskewitz))*
33
+ - [`13caa69`](https://github.com/tobymao/sqlglot/commit/13caa6991f003ad7abb590073451e591b6fd888c) - **optimizer**: Annotate type for snowflake POSITION function *(PR [#5964](https://github.com/tobymao/sqlglot/pull/5964) by [@fivetran-amrutabhimsenayachit](https://github.com/fivetran-amrutabhimsenayachit))*
34
+ - [`1471306`](https://github.com/tobymao/sqlglot/commit/1471306ed317830c294e3654075f55424d14bf5a) - support parse into grant principal and privilege *(PR [#5971](https://github.com/tobymao/sqlglot/pull/5971) by [@eakmanrq](https://github.com/eakmanrq))*
35
+
36
+ ### :bug: Bug Fixes
37
+ - [`5432976`](https://github.com/tobymao/sqlglot/commit/543297680755344185e0f306843bc4909f4f75ed) - **bigquery**: allow GRANT as an id var *(PR [#5965](https://github.com/tobymao/sqlglot/pull/5965) by [@treysp](https://github.com/treysp))*
38
+
39
+ ### :wrench: Chores
40
+ - [`1514bc6`](https://github.com/tobymao/sqlglot/commit/1514bc640ec129a96aedd9e89bfd5d61e832d6b1) - **optimizer**: add type inference tests for Snowflake RPAD function *(PR [#5967](https://github.com/tobymao/sqlglot/pull/5967) by [@fivetran-BradfordPaskewitz](https://github.com/fivetran-BradfordPaskewitz))*
41
+ - [`050b89d`](https://github.com/tobymao/sqlglot/commit/050b89deb9be842f2ddd07c78ea201ec4eae4779) - **optimizer**: Annotate type for snowflake regexp function *(PR [#5970](https://github.com/tobymao/sqlglot/pull/5970) by [@fivetran-amrutabhimsenayachit](https://github.com/fivetran-amrutabhimsenayachit))*
42
+
43
+
44
+ ## [v27.18.0] - 2025-09-25
45
+ ### :boom: BREAKING CHANGES
46
+ - due to [`7f13eaf`](https://github.com/tobymao/sqlglot/commit/7f13eaf7769a3381a56c9209af590835be2f95cd) - Annotate type for snowflake DECOMPRESS_BINARY function *(PR [#5945](https://github.com/tobymao/sqlglot/pull/5945) by [@fivetran-amrutabhimsenayachit](https://github.com/fivetran-amrutabhimsenayachit))*:
47
+
48
+ Annotate type for snowflake DECOMPRESS_BINARY function (#5945)
49
+
50
+ - due to [`be12b29`](https://github.com/tobymao/sqlglot/commit/be12b29b5a7bd6d6e09dbd8c17086bd77c19abc0) - Annotate type for snowflake DECOMPRESS_STRING function *(PR [#5947](https://github.com/tobymao/sqlglot/pull/5947) by [@fivetran-amrutabhimsenayachit](https://github.com/fivetran-amrutabhimsenayachit))*:
51
+
52
+ Annotate type for snowflake DECOMPRESS_STRING function (#5947)
53
+
54
+ - due to [`1573fef`](https://github.com/tobymao/sqlglot/commit/1573fefac27b5b1215e3d458f8ccf1b9dadbb772) - annotate types for Snowflake JAROWINKLER_SIMILARITY function *(PR [#5950](https://github.com/tobymao/sqlglot/pull/5950) by [@fivetran-BradfordPaskewitz](https://github.com/fivetran-BradfordPaskewitz))*:
55
+
56
+ annotate types for Snowflake JAROWINKLER_SIMILARITY function (#5950)
57
+
58
+ - due to [`883c6ab`](https://github.com/tobymao/sqlglot/commit/883c6abe589865f478d95604e8d670e57afd04af) - annotate type for Snowflake COLLATION function *(PR [#5939](https://github.com/tobymao/sqlglot/pull/5939) by [@fivetran-BradfordPaskewitz](https://github.com/fivetran-BradfordPaskewitz))*:
59
+
60
+ annotate type for Snowflake COLLATION function (#5939)
61
+
62
+
63
+ ### :sparkles: New Features
64
+ - [`7f13eaf`](https://github.com/tobymao/sqlglot/commit/7f13eaf7769a3381a56c9209af590835be2f95cd) - **optimizer**: Annotate type for snowflake DECOMPRESS_BINARY function *(PR [#5945](https://github.com/tobymao/sqlglot/pull/5945) by [@fivetran-amrutabhimsenayachit](https://github.com/fivetran-amrutabhimsenayachit))*
65
+ - [`be12b29`](https://github.com/tobymao/sqlglot/commit/be12b29b5a7bd6d6e09dbd8c17086bd77c19abc0) - **optimizer**: Annotate type for snowflake DECOMPRESS_STRING function *(PR [#5947](https://github.com/tobymao/sqlglot/pull/5947) by [@fivetran-amrutabhimsenayachit](https://github.com/fivetran-amrutabhimsenayachit))*
66
+ - [`a55fce5`](https://github.com/tobymao/sqlglot/commit/a55fce5310a50af132c5d06bb299fe3f025442c4) - **optimizer**: Annotate type for snowflake LPAD function *(PR [#5948](https://github.com/tobymao/sqlglot/pull/5948) by [@fivetran-amrutabhimsenayachit](https://github.com/fivetran-amrutabhimsenayachit))*
67
+ - [`05e07aa`](https://github.com/tobymao/sqlglot/commit/05e07aa740d7977a6b42ec15ae4fa9c2168a15f5) - **optimizer**: annotate type for Snowflake INSERT function *(PR [#5942](https://github.com/tobymao/sqlglot/pull/5942) by [@fivetran-BradfordPaskewitz](https://github.com/fivetran-BradfordPaskewitz))*
68
+ - [`6268e10`](https://github.com/tobymao/sqlglot/commit/6268e107a947badaa00508544f5389412806ecd0) - **solr**: initial dialect implementation *(PR [#5946](https://github.com/tobymao/sqlglot/pull/5946) by [@aadel](https://github.com/aadel))*
69
+ - [`1573fef`](https://github.com/tobymao/sqlglot/commit/1573fefac27b5b1215e3d458f8ccf1b9dadbb772) - **optimizer**: annotate types for Snowflake JAROWINKLER_SIMILARITY function *(PR [#5950](https://github.com/tobymao/sqlglot/pull/5950) by [@fivetran-BradfordPaskewitz](https://github.com/fivetran-BradfordPaskewitz))*
70
+ - [`883c6ab`](https://github.com/tobymao/sqlglot/commit/883c6abe589865f478d95604e8d670e57afd04af) - **optimizer**: annotate type for Snowflake COLLATION function *(PR [#5939](https://github.com/tobymao/sqlglot/pull/5939) by [@fivetran-BradfordPaskewitz](https://github.com/fivetran-BradfordPaskewitz))*
71
+ - [`627c18d`](https://github.com/tobymao/sqlglot/commit/627c18d7da6bf644bc14c0f17963dea0be20604a) - **mysql**: add valid INTERVAL units *(PR [#5951](https://github.com/tobymao/sqlglot/pull/5951) by [@geooo109](https://github.com/geooo109))*
72
+
73
+ ### :bug: Bug Fixes
74
+ - [`3846d4d`](https://github.com/tobymao/sqlglot/commit/3846d4dcdf8cbf8e90b2661083a567ab0547ad3c) - **solr**: properly support OR alternative operator *(commit by [@georgesittas](https://github.com/georgesittas))*
75
+ - [`df428d5`](https://github.com/tobymao/sqlglot/commit/df428d516113a47ae50d04cd50a250830589c072) - **parser**: interval identifier followed by END *(PR [#5944](https://github.com/tobymao/sqlglot/pull/5944) by [@geooo109](https://github.com/geooo109))*
76
+ - [`e178d16`](https://github.com/tobymao/sqlglot/commit/e178d1674a71e6f35a6acfa8f4a317f0fe2e4516) - **duckdb**: UNNEST as table *(PR [#5953](https://github.com/tobymao/sqlglot/pull/5953) by [@geooo109](https://github.com/geooo109))*
77
+ - :arrow_lower_right: *fixes issue [#5952](https://github.com/tobymao/sqlglot/issues/5952) opened by [@denis-komarov](https://github.com/denis-komarov)*
78
+ - [`24feb8e`](https://github.com/tobymao/sqlglot/commit/24feb8ee0bc43f3f14fd768c9a0d986355becea2) - **parser**: parse `UPDATE` clauses in any order *(PR [#5958](https://github.com/tobymao/sqlglot/pull/5958) by [@georgesittas](https://github.com/georgesittas))*
79
+ - :arrow_lower_right: *fixes issue [#5956](https://github.com/tobymao/sqlglot/issues/5956) opened by [@sfc-gh-clathrope](https://github.com/sfc-gh-clathrope)*
80
+ - [`980f99a`](https://github.com/tobymao/sqlglot/commit/980f99a4cc0613012a189ee5636af37ec736040c) - **snowflake**: properly generate inferred `STRUCT` data types *(PR [#5954](https://github.com/tobymao/sqlglot/pull/5954) by [@georgesittas](https://github.com/georgesittas))*
81
+
82
+ ### :wrench: Chores
83
+ - [`c18aaf8`](https://github.com/tobymao/sqlglot/commit/c18aaf80fd7375e89dfc8863da619d84f3257353) - cleanup *(commit by [@tobymao](https://github.com/tobymao))*
84
+
85
+
4
86
  ## [v27.17.0] - 2025-09-23
5
87
  ### :boom: BREAKING CHANGES
6
88
  - due to [`f4ad258`](https://github.com/tobymao/sqlglot/commit/f4ad25882951de4e4442dfd5189a56d5a1c5e630) - Annotate types for Snowflake BASE64_DECODE_BINARY function *(PR [#5917](https://github.com/tobymao/sqlglot/pull/5917) by [@fivetran-amrutabhimsenayachit](https://github.com/fivetran-amrutabhimsenayachit))*:
@@ -7477,3 +7559,5 @@ Changelog
7477
7559
  [v27.16.2]: https://github.com/tobymao/sqlglot/compare/v27.16.1...v27.16.2
7478
7560
  [v27.16.3]: https://github.com/tobymao/sqlglot/compare/v27.16.2...v27.16.3
7479
7561
  [v27.17.0]: https://github.com/tobymao/sqlglot/compare/v27.16.3...v27.17.0
7562
+ [v27.18.0]: https://github.com/tobymao/sqlglot/compare/v27.17.0...v27.18.0
7563
+ [v27.19.0]: https://github.com/tobymao/sqlglot/compare/v27.18.0...v27.19.0
@@ -1,7 +1,13 @@
1
1
  .PHONY: install install-dev install-pre-commit test unit style check docs docs-serve
2
2
 
3
+ ifdef UV
4
+ PIP := uv pip
5
+ else
6
+ PIP := pip
7
+ endif
8
+
3
9
  install:
4
- pip install -e .
10
+ $(PIP) install -e .
5
11
 
6
12
  bench: install-dev-rs-release
7
13
  python -m benchmarks.bench
@@ -17,7 +23,7 @@ install-dev-rs:
17
23
  cd sqlglotrs/ && python -m maturin develop
18
24
 
19
25
  install-dev-core:
20
- pip install -e ".[dev]"
26
+ $(PIP) install -e ".[dev]"
21
27
 
22
28
  install-dev: install-dev-core install-dev-rs
23
29
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: sqlglot
3
- Version: 27.18.0
3
+ Version: 27.20.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
@@ -89,12 +89,14 @@ pip3 install "sqlglot[rs]"
89
89
  Or with a local checkout:
90
90
 
91
91
  ```
92
+ # Optionally prefix with UV=1 to use uv for the installation
92
93
  make install
93
94
  ```
94
95
 
95
96
  Requirements for development (optional):
96
97
 
97
98
  ```
99
+ # Optionally prefix with UV=1 to use uv for the installation
98
100
  make install-dev
99
101
  ```
100
102
 
@@ -50,12 +50,14 @@ pip3 install "sqlglot[rs]"
50
50
  Or with a local checkout:
51
51
 
52
52
  ```
53
+ # Optionally prefix with UV=1 to use uv for the installation
53
54
  make install
54
55
  ```
55
56
 
56
57
  Requirements for development (optional):
57
58
 
58
59
  ```
60
+ # Optionally prefix with UV=1 to use uv for the installation
59
61
  make install-dev
60
62
  ```
61
63
 
@@ -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 = '27.18.0'
32
- __version_tuple__ = version_tuple = (27, 18, 0)
31
+ __version__ = version = '27.20.0'
32
+ __version_tuple__ = version_tuple = (27, 20, 0)
33
33
 
34
- __commit_id__ = commit_id = 'g980f99a4c'
34
+ __commit_id__ = commit_id = 'g0d772e0b9'
@@ -754,15 +754,31 @@ class BigQuery(Dialect):
754
754
  SUPPORTS_IMPLICIT_UNNEST = True
755
755
  JOINS_HAVE_EQUAL_PRECEDENCE = True
756
756
 
757
- # BigQuery does not allow ASC/DESC to be used as an identifier
758
- ID_VAR_TOKENS = parser.Parser.ID_VAR_TOKENS - {TokenType.ASC, TokenType.DESC}
759
- ALIAS_TOKENS = parser.Parser.ALIAS_TOKENS - {TokenType.ASC, TokenType.DESC}
760
- TABLE_ALIAS_TOKENS = parser.Parser.TABLE_ALIAS_TOKENS - {TokenType.ASC, TokenType.DESC}
761
- COMMENT_TABLE_ALIAS_TOKENS = parser.Parser.COMMENT_TABLE_ALIAS_TOKENS - {
762
- TokenType.ASC,
763
- TokenType.DESC,
764
- }
765
- UPDATE_ALIAS_TOKENS = parser.Parser.UPDATE_ALIAS_TOKENS - {TokenType.ASC, TokenType.DESC}
757
+ # BigQuery does not allow ASC/DESC to be used as an identifier, allows GRANT as an identifier
758
+ ID_VAR_TOKENS = {
759
+ *parser.Parser.ID_VAR_TOKENS,
760
+ TokenType.GRANT,
761
+ } - {TokenType.ASC, TokenType.DESC}
762
+
763
+ ALIAS_TOKENS = {
764
+ *parser.Parser.ALIAS_TOKENS,
765
+ TokenType.GRANT,
766
+ } - {TokenType.ASC, TokenType.DESC}
767
+
768
+ TABLE_ALIAS_TOKENS = {
769
+ *parser.Parser.TABLE_ALIAS_TOKENS,
770
+ TokenType.GRANT,
771
+ } - {TokenType.ASC, TokenType.DESC}
772
+
773
+ COMMENT_TABLE_ALIAS_TOKENS = {
774
+ *parser.Parser.COMMENT_TABLE_ALIAS_TOKENS,
775
+ TokenType.GRANT,
776
+ } - {TokenType.ASC, TokenType.DESC}
777
+
778
+ UPDATE_ALIAS_TOKENS = {
779
+ *parser.Parser.UPDATE_ALIAS_TOKENS,
780
+ TokenType.GRANT,
781
+ } - {TokenType.ASC, TokenType.DESC}
766
782
 
767
783
  FUNCTIONS = {
768
784
  **parser.Parser.FUNCTIONS,
@@ -532,14 +532,18 @@ class Snowflake(Dialect):
532
532
  exp.DataType.Type.INT: {
533
533
  *Dialect.TYPE_TO_EXPRESSIONS[exp.DataType.Type.INT],
534
534
  exp.Ascii,
535
+ exp.ByteLength,
535
536
  exp.Length,
537
+ exp.RtrimmedLength,
536
538
  exp.BitLength,
537
539
  exp.Levenshtein,
538
540
  exp.JarowinklerSimilarity,
541
+ exp.StrPosition,
539
542
  },
540
543
  exp.DataType.Type.VARCHAR: {
541
544
  *Dialect.TYPE_TO_EXPRESSIONS[exp.DataType.Type.VARCHAR],
542
545
  exp.Base64DecodeString,
546
+ exp.TryBase64DecodeString,
543
547
  exp.Base64Encode,
544
548
  exp.DecompressString,
545
549
  exp.MD5,
@@ -550,6 +554,7 @@ class Snowflake(Dialect):
550
554
  exp.Collate,
551
555
  exp.Collation,
552
556
  exp.HexDecodeString,
557
+ exp.TryHexDecodeString,
553
558
  exp.HexEncode,
554
559
  exp.Initcap,
555
560
  exp.RegexpExtract,
@@ -558,12 +563,16 @@ class Snowflake(Dialect):
558
563
  exp.Replace,
559
564
  exp.SHA,
560
565
  exp.SHA2,
566
+ exp.Soundex,
561
567
  exp.Space,
568
+ exp.SplitPart,
562
569
  exp.Uuid,
563
570
  },
564
571
  exp.DataType.Type.BINARY: {
565
572
  *Dialect.TYPE_TO_EXPRESSIONS[exp.DataType.Type.BINARY],
566
573
  exp.Base64DecodeBinary,
574
+ exp.TryBase64DecodeBinary,
575
+ exp.TryHexDecodeBinary,
567
576
  exp.Compress,
568
577
  exp.DecompressBinary,
569
578
  exp.MD5Digest,
@@ -579,6 +588,13 @@ class Snowflake(Dialect):
579
588
  exp.DataType.Type.ARRAY: {
580
589
  exp.Split,
581
590
  },
591
+ exp.DataType.Type.OBJECT: {
592
+ exp.ParseUrl,
593
+ exp.ParseIp,
594
+ },
595
+ exp.DataType.Type.DECIMAL: {
596
+ exp.RegexpCount,
597
+ },
582
598
  }
583
599
 
584
600
  ANNOTATORS = {
@@ -600,6 +616,9 @@ class Snowflake(Dialect):
600
616
  },
601
617
  exp.ConcatWs: lambda self, e: self._annotate_by_args(e, "expressions"),
602
618
  exp.Reverse: _annotate_reverse,
619
+ exp.RegexpCount: lambda self, e: self._annotate_with_type(
620
+ e, exp.DataType.build("NUMBER", dialect="snowflake")
621
+ ),
603
622
  }
604
623
 
605
624
  TIME_MAPPING = {
@@ -732,6 +751,9 @@ class Snowflake(Dialect):
732
751
  "NULLIFZERO": _build_if_from_nullifzero,
733
752
  "OBJECT_CONSTRUCT": _build_object_construct,
734
753
  "OCTET_LENGTH": exp.ByteLength.from_arg_list,
754
+ "PARSE_URL": lambda args: exp.ParseUrl(
755
+ this=seq_get(args, 0), permissive=seq_get(args, 1)
756
+ ),
735
757
  "REGEXP_EXTRACT_ALL": _build_regexp_extract(exp.RegexpExtractAll),
736
758
  "REGEXP_REPLACE": _build_regexp_replace,
737
759
  "REGEXP_SUBSTR": _build_regexp_extract(exp.RegexpExtract),
@@ -783,6 +805,7 @@ class Snowflake(Dialect):
783
805
  FUNCTION_PARSERS = {
784
806
  **parser.Parser.FUNCTION_PARSERS,
785
807
  "DATE_PART": lambda self: self._parse_date_part(),
808
+ "DIRECTORY": lambda self: self._parse_directory(),
786
809
  "OBJECT_CONSTRUCT_KEEP_NULL": lambda self: self._parse_json_object(),
787
810
  "LISTAGG": lambda self: self._parse_string_agg(),
788
811
  "SEMANTIC_VIEW": lambda self: self._parse_semantic_view(),
@@ -892,6 +915,14 @@ class Snowflake(Dialect):
892
915
  ),
893
916
  }
894
917
 
918
+ def _parse_directory(self) -> exp.DirectoryStage:
919
+ table = self._parse_table_parts()
920
+
921
+ if isinstance(table, exp.Table):
922
+ table = table.this
923
+
924
+ return self.expression(exp.DirectoryStage, this=table)
925
+
895
926
  def _parse_use(self) -> exp.Use:
896
927
  if self._match_text_seq("SECONDARY", "ROLES"):
897
928
  this = self._match_texts(("ALL", "NONE")) and exp.var(self._prev.text.upper())
@@ -342,3 +342,12 @@ class SQLite(Dialect):
342
342
 
343
343
  def respectnulls_sql(self, expression: exp.RespectNulls) -> str:
344
344
  return self.sql(expression.this)
345
+
346
+ def windowspec_sql(self, expression: exp.WindowSpec) -> str:
347
+ if (
348
+ expression.text("kind").upper() == "RANGE"
349
+ and expression.text("start").upper() == "CURRENT ROW"
350
+ ):
351
+ return "RANGE CURRENT ROW"
352
+
353
+ return super().windowspec_sql(expression)
@@ -32,6 +32,7 @@ def st_distance_sphere(self, expression: exp.StDistance) -> str:
32
32
 
33
33
  class StarRocks(MySQL):
34
34
  STRICT_JSON_PATH_SYNTAX = False
35
+ INDEX_OFFSET = 1
35
36
 
36
37
  class Tokenizer(MySQL.Tokenizer):
37
38
  KEYWORDS = {
@@ -49,6 +50,7 @@ class StarRocks(MySQL):
49
50
  "DATE_DIFF": lambda args: exp.DateDiff(
50
51
  this=seq_get(args, 1), expression=seq_get(args, 2), unit=seq_get(args, 0)
51
52
  ),
53
+ "ARRAY_FLATTEN": exp.Flatten.from_arg_list,
52
54
  "REGEXP": exp.RegexpLike.from_arg_list,
53
55
  }
54
56
 
@@ -152,6 +154,7 @@ class StarRocks(MySQL):
152
154
  exp.DateDiff: lambda self, e: self.func(
153
155
  "DATE_DIFF", unit_to_str(e), e.this, e.expression
154
156
  ),
157
+ exp.Flatten: rename_func("ARRAY_FLATTEN"),
155
158
  exp.JSONExtractScalar: arrow_json_extract_sql,
156
159
  exp.JSONExtract: arrow_json_extract_sql,
157
160
  exp.Property: property_sql,
@@ -120,19 +120,43 @@ class Expression(metaclass=_Expression):
120
120
  def __eq__(self, other) -> bool:
121
121
  return type(self) is type(other) and hash(self) == hash(other)
122
122
 
123
- @property
124
- def hashable_args(self) -> t.Any:
125
- return frozenset(
126
- (k, tuple(_norm_arg(a) for a in v) if type(v) is list else _norm_arg(v))
127
- for k, v in self.args.items()
128
- if not (v is None or v is False or (type(v) is list and not v))
129
- )
130
-
131
123
  def __hash__(self) -> int:
132
- if self._hash is not None:
133
- return self._hash
134
-
135
- return hash((self.__class__, self.hashable_args))
124
+ if self._hash is None:
125
+ nodes = []
126
+ queue = deque([self])
127
+
128
+ while queue:
129
+ node = queue.popleft()
130
+ nodes.append(node)
131
+
132
+ for v in node.iter_expressions():
133
+ if v._hash is None:
134
+ queue.append(v)
135
+
136
+ for node in reversed(nodes):
137
+ hash_ = hash(node.key)
138
+ t = type(node)
139
+
140
+ if t is Literal or t is Identifier:
141
+ for k, v in sorted(node.args.items()):
142
+ if v:
143
+ hash_ = hash((hash_, k, v))
144
+ else:
145
+ for k, v in sorted(node.args.items()):
146
+ t = type(v)
147
+
148
+ if t is list:
149
+ for x in v:
150
+ if x is not None and x is not False:
151
+ hash_ = hash((hash_, k, x.lower() if type(x) is str else x))
152
+ else:
153
+ hash_ = hash((hash_, k))
154
+ elif v is not None and v is not False:
155
+ hash_ = hash((hash_, k, v.lower() if t is str else v))
156
+
157
+ node._hash = hash_
158
+ assert self._hash
159
+ return self._hash
136
160
 
137
161
  def __reduce__(self) -> t.Tuple[t.Callable, t.Tuple[t.List[t.Dict[str, t.Any]]]]:
138
162
  from sqlglot.serde import dump, load
@@ -369,6 +393,12 @@ class Expression(metaclass=_Expression):
369
393
  overwrite: assuming an index is given, this determines whether to overwrite the
370
394
  list entry instead of only inserting a new value (i.e., like list.insert).
371
395
  """
396
+ expression: t.Optional[Expression] = self
397
+
398
+ while expression and expression._hash is not None:
399
+ expression._hash = None
400
+ expression = expression.parent
401
+
372
402
  if index is not None:
373
403
  expressions = self.args.get(arg_key) or []
374
404
 
@@ -2235,10 +2265,14 @@ class Prior(Expression):
2235
2265
 
2236
2266
 
2237
2267
  class Directory(Expression):
2238
- # https://spark.apache.org/docs/3.0.0-preview/sql-ref-syntax-dml-insert-overwrite-directory-hive.html
2239
2268
  arg_types = {"this": True, "local": False, "row_format": False}
2240
2269
 
2241
2270
 
2271
+ # https://docs.snowflake.com/en/user-guide/data-load-dirtables-query
2272
+ class DirectoryStage(Expression):
2273
+ pass
2274
+
2275
+
2242
2276
  class ForeignKey(Expression):
2243
2277
  arg_types = {
2244
2278
  "expressions": False,
@@ -2298,10 +2332,6 @@ class Identifier(Expression):
2298
2332
  def quoted(self) -> bool:
2299
2333
  return bool(self.args.get("quoted"))
2300
2334
 
2301
- @property
2302
- def hashable_args(self) -> t.Any:
2303
- return (self.this, self.quoted)
2304
-
2305
2335
  @property
2306
2336
  def output_name(self) -> str:
2307
2337
  return self.name
@@ -2536,10 +2566,6 @@ class LimitOptions(Expression):
2536
2566
  class Literal(Condition):
2537
2567
  arg_types = {"this": True, "is_string": True}
2538
2568
 
2539
- @property
2540
- def hashable_args(self) -> t.Any:
2541
- return (self.this, self.args.get("is_string"))
2542
-
2543
2569
  @classmethod
2544
2570
  def number(cls, number) -> Literal:
2545
2571
  return cls(this=str(number), is_string=False)
@@ -6427,14 +6453,36 @@ class Base64DecodeBinary(Func):
6427
6453
  arg_types = {"this": True, "alphabet": False}
6428
6454
 
6429
6455
 
6456
+ # https://docs.snowflake.com/en/sql-reference/functions/base64_decode_string
6430
6457
  class Base64DecodeString(Func):
6431
6458
  arg_types = {"this": True, "alphabet": False}
6432
6459
 
6433
6460
 
6461
+ # https://docs.snowflake.com/en/sql-reference/functions/base64_encode
6434
6462
  class Base64Encode(Func):
6435
6463
  arg_types = {"this": True, "max_line_length": False, "alphabet": False}
6436
6464
 
6437
6465
 
6466
+ # https://docs.snowflake.com/en/sql-reference/functions/try_base64_decode_binary
6467
+ class TryBase64DecodeBinary(Func):
6468
+ arg_types = {"this": True, "alphabet": False}
6469
+
6470
+
6471
+ # https://docs.snowflake.com/en/sql-reference/functions/try_base64_decode_string
6472
+ class TryBase64DecodeString(Func):
6473
+ arg_types = {"this": True, "alphabet": False}
6474
+
6475
+
6476
+ # https://docs.snowflake.com/en/sql-reference/functions/try_hex_decode_binary
6477
+ class TryHexDecodeBinary(Func):
6478
+ pass
6479
+
6480
+
6481
+ # https://docs.snowflake.com/en/sql-reference/functions/try_hex_decode_string
6482
+ class TryHexDecodeString(Func):
6483
+ pass
6484
+
6485
+
6438
6486
  # https://trino.io/docs/current/functions/datetime.html#from_iso8601_timestamp
6439
6487
  class FromISO8601Timestamp(Func):
6440
6488
  _sql_names = ["FROM_ISO8601_TIMESTAMP"]
@@ -6888,6 +6936,16 @@ class ParseJSON(Func):
6888
6936
  arg_types = {"this": True, "expression": False, "safe": False}
6889
6937
 
6890
6938
 
6939
+ # Snowflake: https://docs.snowflake.com/en/sql-reference/functions/parse_url
6940
+ # Databricks: https://docs.databricks.com/aws/en/sql/language-manual/functions/parse_url
6941
+ class ParseUrl(Func):
6942
+ arg_types = {"this": True, "part_to_extract": False, "key": False, "permissive": False}
6943
+
6944
+
6945
+ class ParseIp(Func):
6946
+ arg_types = {"this": True, "type": True, "permissive": False}
6947
+
6948
+
6891
6949
  class ParseTime(Func):
6892
6950
  arg_types = {"this": True, "format": True}
6893
6951
 
@@ -6918,6 +6976,10 @@ class Length(Func):
6918
6976
  _sql_names = ["LENGTH", "LEN", "CHAR_LENGTH", "CHARACTER_LENGTH"]
6919
6977
 
6920
6978
 
6979
+ class RtrimmedLength(Func):
6980
+ pass
6981
+
6982
+
6921
6983
  class BitLength(Func):
6922
6984
  pass
6923
6985
 
@@ -7235,6 +7297,15 @@ class RegexpSplit(Func):
7235
7297
  arg_types = {"this": True, "expression": True, "limit": False}
7236
7298
 
7237
7299
 
7300
+ class RegexpCount(Func):
7301
+ arg_types = {
7302
+ "this": True,
7303
+ "expression": True,
7304
+ "position": False,
7305
+ "parameters": False,
7306
+ }
7307
+
7308
+
7238
7309
  class Repeat(Func):
7239
7310
  arg_types = {"this": True, "times": True}
7240
7311
 
@@ -7698,10 +7769,6 @@ class TableColumn(Expression):
7698
7769
  pass
7699
7770
 
7700
7771
 
7701
- def _norm_arg(arg):
7702
- return arg.lower() if type(arg) is str else arg
7703
-
7704
-
7705
7772
  ALL_FUNCTIONS = subclasses(__name__, Func, (AggFunc, Anonymous, Func))
7706
7773
  FUNCTION_BY_NAME = {name: func for func in ALL_FUNCTIONS for name in func.sql_names()}
7707
7774
 
@@ -5334,3 +5334,6 @@ class Generator(metaclass=_Generator):
5334
5334
  def modelattribute_sql(self, expression: exp.ModelAttribute) -> str:
5335
5335
  self.unsupported("The model!attribute syntax is not supported")
5336
5336
  return ""
5337
+
5338
+ def directorystage_sql(self, expression: exp.DirectoryStage) -> str:
5339
+ return self.func("DIRECTORY", expression.this)
@@ -226,31 +226,13 @@ def while_changing(expression: Expression, func: t.Callable[[Expression], E]) ->
226
226
  Returns:
227
227
  The transformed expression.
228
228
  """
229
- end_hash: t.Optional[int] = None
230
229
 
231
230
  while True:
232
- # No need to walk the AST– we've already cached the hashes in the previous iteration
233
- if end_hash is None:
234
- for n in reversed(tuple(expression.walk())):
235
- n._hash = hash(n)
236
-
237
231
  start_hash = hash(expression)
238
232
  expression = func(expression)
239
-
240
- expression_nodes = tuple(expression.walk())
241
-
242
- # Uncache previous caches so we can recompute them
243
- for n in reversed(expression_nodes):
244
- n._hash = None
245
- n._hash = hash(n)
246
-
247
233
  end_hash = hash(expression)
248
234
 
249
235
  if start_hash == end_hash:
250
- # ... and reset the hash so we don't risk it becoming out of date if a mutation happens
251
- for n in expression_nodes:
252
- n._hash = None
253
-
254
236
  break
255
237
 
256
238
  return expression
@@ -809,6 +809,8 @@ class Parser(metaclass=_Parser):
809
809
  exp.DataType: lambda self: self._parse_types(allow_identifiers=False, schema=True),
810
810
  exp.Expression: lambda self: self._parse_expression(),
811
811
  exp.From: lambda self: self._parse_from(joins=True),
812
+ exp.GrantPrincipal: lambda self: self._parse_grant_principal(),
813
+ exp.GrantPrivilege: lambda self: self._parse_grant_privilege(),
812
814
  exp.Group: lambda self: self._parse_group(),
813
815
  exp.Having: lambda self: self._parse_having(),
814
816
  exp.Hint: lambda self: self._parse_hint_body(),
@@ -1409,7 +1411,7 @@ class Parser(metaclass=_Parser):
1409
1411
 
1410
1412
  VIEW_ATTRIBUTES = {"ENCRYPTION", "SCHEMABINDING", "VIEW_METADATA"}
1411
1413
 
1412
- WINDOW_ALIAS_TOKENS = ID_VAR_TOKENS - {TokenType.ROWS}
1414
+ WINDOW_ALIAS_TOKENS = ID_VAR_TOKENS - {TokenType.RANGE, TokenType.ROWS}
1413
1415
  WINDOW_BEFORE_PAREN_TOKENS = {TokenType.OVER}
1414
1416
  WINDOW_SIDES = {"FOLLOWING", "PRECEDING"}
1415
1417
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: sqlglot
3
- Version: 27.18.0
3
+ Version: 27.20.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
@@ -89,12 +89,14 @@ pip3 install "sqlglot[rs]"
89
89
  Or with a local checkout:
90
90
 
91
91
  ```
92
+ # Optionally prefix with UV=1 to use uv for the installation
92
93
  make install
93
94
  ```
94
95
 
95
96
  Requirements for development (optional):
96
97
 
97
98
  ```
99
+ # Optionally prefix with UV=1 to use uv for the installation
98
100
  make install-dev
99
101
  ```
100
102
 
@@ -1813,6 +1813,7 @@ WHERE
1813
1813
  self.validate_identity("TO_JSON(9999999999, stringify_wide_numbers => FALSE)")
1814
1814
  self.validate_identity("RANGE_BUCKET(20, [0, 10, 20, 30, 40])")
1815
1815
  self.validate_identity("SELECT TRANSLATE(MODEL, 'in', 't') FROM (SELECT 'input' AS MODEL)")
1816
+ self.validate_identity("SELECT GRANT FROM (SELECT 'input' AS GRANT)")
1816
1817
 
1817
1818
  def test_errors(self):
1818
1819
  with self.assertRaises(ParseError):
@@ -37,6 +37,10 @@ class TestDatabricks(Validator):
37
37
  self.validate_identity("CREATE TABLE foo (x DATE GENERATED ALWAYS AS (CAST(y AS DATE)))")
38
38
  self.validate_identity("TRUNCATE TABLE t1 PARTITION(age = 10, name = 'test', address)")
39
39
  self.validate_identity("SELECT PARSE_JSON('{}')")
40
+
41
+ self.validate_identity("PARSE_URL('https://example.com/path')")
42
+ self.validate_identity("PARSE_URL('https://example.com/path', 'HOST')")
43
+ self.validate_identity("PARSE_URL('https://example.com/path', 'QUERY', 'param')")
40
44
  self.validate_identity(
41
45
  "CREATE TABLE IF NOT EXISTS db.table (a TIMESTAMP, b BOOLEAN GENERATED ALWAYS AS (NOT a IS NULL)) USING DELTA"
42
46
  )