sqlglot 27.3.1__tar.gz → 27.4.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 (226) hide show
  1. {sqlglot-27.3.1 → sqlglot-27.4.0}/CHANGELOG.md +15 -0
  2. {sqlglot-27.3.1 → sqlglot-27.4.0}/PKG-INFO +1 -1
  3. {sqlglot-27.3.1 → sqlglot-27.4.0}/sqlglot/_version.py +2 -2
  4. {sqlglot-27.3.1 → sqlglot-27.4.0}/sqlglot/dialects/bigquery.py +26 -0
  5. {sqlglot-27.3.1 → sqlglot-27.4.0}/sqlglot/dialects/exasol.py +24 -0
  6. {sqlglot-27.3.1 → sqlglot-27.4.0}/sqlglot/dialects/snowflake.py +14 -0
  7. {sqlglot-27.3.1 → sqlglot-27.4.0}/sqlglot/dialects/sqlite.py +22 -1
  8. {sqlglot-27.3.1 → sqlglot-27.4.0}/sqlglot/expressions.py +1 -1
  9. {sqlglot-27.3.1 → sqlglot-27.4.0}/sqlglot/generator.py +3 -1
  10. {sqlglot-27.3.1 → sqlglot-27.4.0}/sqlglot/optimizer/annotate_types.py +8 -3
  11. {sqlglot-27.3.1 → sqlglot-27.4.0}/sqlglot/optimizer/optimize_joins.py +2 -1
  12. {sqlglot-27.3.1 → sqlglot-27.4.0}/sqlglot/parser.py +5 -1
  13. {sqlglot-27.3.1 → sqlglot-27.4.0}/sqlglot.egg-info/PKG-INFO +1 -1
  14. {sqlglot-27.3.1 → sqlglot-27.4.0}/tests/dialects/test_bigquery.py +8 -0
  15. {sqlglot-27.3.1 → sqlglot-27.4.0}/tests/dialects/test_exasol.py +82 -0
  16. {sqlglot-27.3.1 → sqlglot-27.4.0}/tests/dialects/test_hive.py +15 -0
  17. {sqlglot-27.3.1 → sqlglot-27.4.0}/tests/dialects/test_sqlite.py +16 -0
  18. {sqlglot-27.3.1 → sqlglot-27.4.0}/tests/fixtures/optimizer/optimize_joins.sql +6 -0
  19. {sqlglot-27.3.1 → sqlglot-27.4.0}/tests/test_optimizer.py +6 -1
  20. {sqlglot-27.3.1 → sqlglot-27.4.0}/.gitignore +0 -0
  21. {sqlglot-27.3.1 → sqlglot-27.4.0}/.gitpod.yml +0 -0
  22. {sqlglot-27.3.1 → sqlglot-27.4.0}/.pre-commit-config.yaml +0 -0
  23. {sqlglot-27.3.1 → sqlglot-27.4.0}/CONTRIBUTING.md +0 -0
  24. {sqlglot-27.3.1 → sqlglot-27.4.0}/LICENSE +0 -0
  25. {sqlglot-27.3.1 → sqlglot-27.4.0}/MANIFEST.in +0 -0
  26. {sqlglot-27.3.1 → sqlglot-27.4.0}/Makefile +0 -0
  27. {sqlglot-27.3.1 → sqlglot-27.4.0}/README.md +0 -0
  28. {sqlglot-27.3.1 → sqlglot-27.4.0}/pyproject.toml +0 -0
  29. {sqlglot-27.3.1 → sqlglot-27.4.0}/setup.cfg +0 -0
  30. {sqlglot-27.3.1 → sqlglot-27.4.0}/setup.py +0 -0
  31. {sqlglot-27.3.1 → sqlglot-27.4.0}/sqlglot/__init__.py +0 -0
  32. {sqlglot-27.3.1 → sqlglot-27.4.0}/sqlglot/__main__.py +0 -0
  33. {sqlglot-27.3.1 → sqlglot-27.4.0}/sqlglot/_typing.py +0 -0
  34. {sqlglot-27.3.1 → sqlglot-27.4.0}/sqlglot/dialects/__init__.py +0 -0
  35. {sqlglot-27.3.1 → sqlglot-27.4.0}/sqlglot/dialects/athena.py +0 -0
  36. {sqlglot-27.3.1 → sqlglot-27.4.0}/sqlglot/dialects/clickhouse.py +0 -0
  37. {sqlglot-27.3.1 → sqlglot-27.4.0}/sqlglot/dialects/databricks.py +0 -0
  38. {sqlglot-27.3.1 → sqlglot-27.4.0}/sqlglot/dialects/dialect.py +0 -0
  39. {sqlglot-27.3.1 → sqlglot-27.4.0}/sqlglot/dialects/doris.py +0 -0
  40. {sqlglot-27.3.1 → sqlglot-27.4.0}/sqlglot/dialects/dremio.py +0 -0
  41. {sqlglot-27.3.1 → sqlglot-27.4.0}/sqlglot/dialects/drill.py +0 -0
  42. {sqlglot-27.3.1 → sqlglot-27.4.0}/sqlglot/dialects/druid.py +0 -0
  43. {sqlglot-27.3.1 → sqlglot-27.4.0}/sqlglot/dialects/duckdb.py +0 -0
  44. {sqlglot-27.3.1 → sqlglot-27.4.0}/sqlglot/dialects/dune.py +0 -0
  45. {sqlglot-27.3.1 → sqlglot-27.4.0}/sqlglot/dialects/fabric.py +0 -0
  46. {sqlglot-27.3.1 → sqlglot-27.4.0}/sqlglot/dialects/hive.py +0 -0
  47. {sqlglot-27.3.1 → sqlglot-27.4.0}/sqlglot/dialects/materialize.py +0 -0
  48. {sqlglot-27.3.1 → sqlglot-27.4.0}/sqlglot/dialects/mysql.py +0 -0
  49. {sqlglot-27.3.1 → sqlglot-27.4.0}/sqlglot/dialects/oracle.py +0 -0
  50. {sqlglot-27.3.1 → sqlglot-27.4.0}/sqlglot/dialects/postgres.py +0 -0
  51. {sqlglot-27.3.1 → sqlglot-27.4.0}/sqlglot/dialects/presto.py +0 -0
  52. {sqlglot-27.3.1 → sqlglot-27.4.0}/sqlglot/dialects/prql.py +0 -0
  53. {sqlglot-27.3.1 → sqlglot-27.4.0}/sqlglot/dialects/redshift.py +0 -0
  54. {sqlglot-27.3.1 → sqlglot-27.4.0}/sqlglot/dialects/risingwave.py +0 -0
  55. {sqlglot-27.3.1 → sqlglot-27.4.0}/sqlglot/dialects/singlestore.py +0 -0
  56. {sqlglot-27.3.1 → sqlglot-27.4.0}/sqlglot/dialects/spark.py +0 -0
  57. {sqlglot-27.3.1 → sqlglot-27.4.0}/sqlglot/dialects/spark2.py +0 -0
  58. {sqlglot-27.3.1 → sqlglot-27.4.0}/sqlglot/dialects/starrocks.py +0 -0
  59. {sqlglot-27.3.1 → sqlglot-27.4.0}/sqlglot/dialects/tableau.py +0 -0
  60. {sqlglot-27.3.1 → sqlglot-27.4.0}/sqlglot/dialects/teradata.py +0 -0
  61. {sqlglot-27.3.1 → sqlglot-27.4.0}/sqlglot/dialects/trino.py +0 -0
  62. {sqlglot-27.3.1 → sqlglot-27.4.0}/sqlglot/dialects/tsql.py +0 -0
  63. {sqlglot-27.3.1 → sqlglot-27.4.0}/sqlglot/diff.py +0 -0
  64. {sqlglot-27.3.1 → sqlglot-27.4.0}/sqlglot/errors.py +0 -0
  65. {sqlglot-27.3.1 → sqlglot-27.4.0}/sqlglot/executor/__init__.py +0 -0
  66. {sqlglot-27.3.1 → sqlglot-27.4.0}/sqlglot/executor/context.py +0 -0
  67. {sqlglot-27.3.1 → sqlglot-27.4.0}/sqlglot/executor/env.py +0 -0
  68. {sqlglot-27.3.1 → sqlglot-27.4.0}/sqlglot/executor/python.py +0 -0
  69. {sqlglot-27.3.1 → sqlglot-27.4.0}/sqlglot/executor/table.py +0 -0
  70. {sqlglot-27.3.1 → sqlglot-27.4.0}/sqlglot/helper.py +0 -0
  71. {sqlglot-27.3.1 → sqlglot-27.4.0}/sqlglot/jsonpath.py +0 -0
  72. {sqlglot-27.3.1 → sqlglot-27.4.0}/sqlglot/lineage.py +0 -0
  73. {sqlglot-27.3.1 → sqlglot-27.4.0}/sqlglot/optimizer/__init__.py +0 -0
  74. {sqlglot-27.3.1 → sqlglot-27.4.0}/sqlglot/optimizer/canonicalize.py +0 -0
  75. {sqlglot-27.3.1 → sqlglot-27.4.0}/sqlglot/optimizer/eliminate_ctes.py +0 -0
  76. {sqlglot-27.3.1 → sqlglot-27.4.0}/sqlglot/optimizer/eliminate_joins.py +0 -0
  77. {sqlglot-27.3.1 → sqlglot-27.4.0}/sqlglot/optimizer/eliminate_subqueries.py +0 -0
  78. {sqlglot-27.3.1 → sqlglot-27.4.0}/sqlglot/optimizer/isolate_table_selects.py +0 -0
  79. {sqlglot-27.3.1 → sqlglot-27.4.0}/sqlglot/optimizer/merge_subqueries.py +0 -0
  80. {sqlglot-27.3.1 → sqlglot-27.4.0}/sqlglot/optimizer/normalize.py +0 -0
  81. {sqlglot-27.3.1 → sqlglot-27.4.0}/sqlglot/optimizer/normalize_identifiers.py +0 -0
  82. {sqlglot-27.3.1 → sqlglot-27.4.0}/sqlglot/optimizer/optimizer.py +0 -0
  83. {sqlglot-27.3.1 → sqlglot-27.4.0}/sqlglot/optimizer/pushdown_predicates.py +0 -0
  84. {sqlglot-27.3.1 → sqlglot-27.4.0}/sqlglot/optimizer/pushdown_projections.py +0 -0
  85. {sqlglot-27.3.1 → sqlglot-27.4.0}/sqlglot/optimizer/qualify.py +0 -0
  86. {sqlglot-27.3.1 → sqlglot-27.4.0}/sqlglot/optimizer/qualify_columns.py +0 -0
  87. {sqlglot-27.3.1 → sqlglot-27.4.0}/sqlglot/optimizer/qualify_tables.py +0 -0
  88. {sqlglot-27.3.1 → sqlglot-27.4.0}/sqlglot/optimizer/scope.py +0 -0
  89. {sqlglot-27.3.1 → sqlglot-27.4.0}/sqlglot/optimizer/simplify.py +0 -0
  90. {sqlglot-27.3.1 → sqlglot-27.4.0}/sqlglot/optimizer/unnest_subqueries.py +0 -0
  91. {sqlglot-27.3.1 → sqlglot-27.4.0}/sqlglot/planner.py +0 -0
  92. {sqlglot-27.3.1 → sqlglot-27.4.0}/sqlglot/py.typed +0 -0
  93. {sqlglot-27.3.1 → sqlglot-27.4.0}/sqlglot/schema.py +0 -0
  94. {sqlglot-27.3.1 → sqlglot-27.4.0}/sqlglot/serde.py +0 -0
  95. {sqlglot-27.3.1 → sqlglot-27.4.0}/sqlglot/time.py +0 -0
  96. {sqlglot-27.3.1 → sqlglot-27.4.0}/sqlglot/tokens.py +0 -0
  97. {sqlglot-27.3.1 → sqlglot-27.4.0}/sqlglot/transforms.py +0 -0
  98. {sqlglot-27.3.1 → sqlglot-27.4.0}/sqlglot/trie.py +0 -0
  99. {sqlglot-27.3.1 → sqlglot-27.4.0}/sqlglot.egg-info/SOURCES.txt +0 -0
  100. {sqlglot-27.3.1 → sqlglot-27.4.0}/sqlglot.egg-info/dependency_links.txt +0 -0
  101. {sqlglot-27.3.1 → sqlglot-27.4.0}/sqlglot.egg-info/requires.txt +0 -0
  102. {sqlglot-27.3.1 → sqlglot-27.4.0}/sqlglot.egg-info/top_level.txt +0 -0
  103. {sqlglot-27.3.1 → sqlglot-27.4.0}/sqlglot.png +0 -0
  104. {sqlglot-27.3.1 → sqlglot-27.4.0}/sqlglotrs/Cargo.lock +0 -0
  105. {sqlglot-27.3.1 → sqlglot-27.4.0}/sqlglotrs/Cargo.toml +0 -0
  106. {sqlglot-27.3.1 → sqlglot-27.4.0}/sqlglotrs/benches/dialect_settings.json +0 -0
  107. {sqlglot-27.3.1 → sqlglot-27.4.0}/sqlglotrs/benches/long.rs +0 -0
  108. {sqlglot-27.3.1 → sqlglot-27.4.0}/sqlglotrs/benches/token_type_settings.json +0 -0
  109. {sqlglot-27.3.1 → sqlglot-27.4.0}/sqlglotrs/benches/tokenizer_dialect_settings.json +0 -0
  110. {sqlglot-27.3.1 → sqlglot-27.4.0}/sqlglotrs/benches/tokenizer_settings.json +0 -0
  111. {sqlglot-27.3.1 → sqlglot-27.4.0}/sqlglotrs/pyproject.toml +0 -0
  112. {sqlglot-27.3.1 → sqlglot-27.4.0}/sqlglotrs/src/lib.rs +0 -0
  113. {sqlglot-27.3.1 → sqlglot-27.4.0}/sqlglotrs/src/settings.rs +0 -0
  114. {sqlglot-27.3.1 → sqlglot-27.4.0}/sqlglotrs/src/token.rs +0 -0
  115. {sqlglot-27.3.1 → sqlglot-27.4.0}/sqlglotrs/src/tokenizer.rs +0 -0
  116. {sqlglot-27.3.1 → sqlglot-27.4.0}/sqlglotrs/src/trie.rs +0 -0
  117. {sqlglot-27.3.1 → sqlglot-27.4.0}/tests/__init__.py +0 -0
  118. {sqlglot-27.3.1 → sqlglot-27.4.0}/tests/dialects/__init__.py +0 -0
  119. {sqlglot-27.3.1 → sqlglot-27.4.0}/tests/dialects/test_athena.py +0 -0
  120. {sqlglot-27.3.1 → sqlglot-27.4.0}/tests/dialects/test_clickhouse.py +0 -0
  121. {sqlglot-27.3.1 → sqlglot-27.4.0}/tests/dialects/test_databricks.py +0 -0
  122. {sqlglot-27.3.1 → sqlglot-27.4.0}/tests/dialects/test_dialect.py +0 -0
  123. {sqlglot-27.3.1 → sqlglot-27.4.0}/tests/dialects/test_doris.py +0 -0
  124. {sqlglot-27.3.1 → sqlglot-27.4.0}/tests/dialects/test_dremio.py +0 -0
  125. {sqlglot-27.3.1 → sqlglot-27.4.0}/tests/dialects/test_drill.py +0 -0
  126. {sqlglot-27.3.1 → sqlglot-27.4.0}/tests/dialects/test_druid.py +0 -0
  127. {sqlglot-27.3.1 → sqlglot-27.4.0}/tests/dialects/test_duckdb.py +0 -0
  128. {sqlglot-27.3.1 → sqlglot-27.4.0}/tests/dialects/test_dune.py +0 -0
  129. {sqlglot-27.3.1 → sqlglot-27.4.0}/tests/dialects/test_fabric.py +0 -0
  130. {sqlglot-27.3.1 → sqlglot-27.4.0}/tests/dialects/test_materialize.py +0 -0
  131. {sqlglot-27.3.1 → sqlglot-27.4.0}/tests/dialects/test_mysql.py +0 -0
  132. {sqlglot-27.3.1 → sqlglot-27.4.0}/tests/dialects/test_oracle.py +0 -0
  133. {sqlglot-27.3.1 → sqlglot-27.4.0}/tests/dialects/test_pipe_syntax.py +0 -0
  134. {sqlglot-27.3.1 → sqlglot-27.4.0}/tests/dialects/test_postgres.py +0 -0
  135. {sqlglot-27.3.1 → sqlglot-27.4.0}/tests/dialects/test_presto.py +0 -0
  136. {sqlglot-27.3.1 → sqlglot-27.4.0}/tests/dialects/test_prql.py +0 -0
  137. {sqlglot-27.3.1 → sqlglot-27.4.0}/tests/dialects/test_redshift.py +0 -0
  138. {sqlglot-27.3.1 → sqlglot-27.4.0}/tests/dialects/test_risingwave.py +0 -0
  139. {sqlglot-27.3.1 → sqlglot-27.4.0}/tests/dialects/test_singlestore.py +0 -0
  140. {sqlglot-27.3.1 → sqlglot-27.4.0}/tests/dialects/test_snowflake.py +0 -0
  141. {sqlglot-27.3.1 → sqlglot-27.4.0}/tests/dialects/test_spark.py +0 -0
  142. {sqlglot-27.3.1 → sqlglot-27.4.0}/tests/dialects/test_starrocks.py +0 -0
  143. {sqlglot-27.3.1 → sqlglot-27.4.0}/tests/dialects/test_tableau.py +0 -0
  144. {sqlglot-27.3.1 → sqlglot-27.4.0}/tests/dialects/test_teradata.py +0 -0
  145. {sqlglot-27.3.1 → sqlglot-27.4.0}/tests/dialects/test_trino.py +0 -0
  146. {sqlglot-27.3.1 → sqlglot-27.4.0}/tests/dialects/test_tsql.py +0 -0
  147. {sqlglot-27.3.1 → sqlglot-27.4.0}/tests/fixtures/identity.sql +0 -0
  148. {sqlglot-27.3.1 → sqlglot-27.4.0}/tests/fixtures/jsonpath/LICENSE +0 -0
  149. {sqlglot-27.3.1 → sqlglot-27.4.0}/tests/fixtures/jsonpath/cts.json +0 -0
  150. {sqlglot-27.3.1 → sqlglot-27.4.0}/tests/fixtures/optimizer/annotate_functions.sql +0 -0
  151. {sqlglot-27.3.1 → sqlglot-27.4.0}/tests/fixtures/optimizer/annotate_types.sql +0 -0
  152. {sqlglot-27.3.1 → sqlglot-27.4.0}/tests/fixtures/optimizer/canonicalize.sql +0 -0
  153. {sqlglot-27.3.1 → sqlglot-27.4.0}/tests/fixtures/optimizer/eliminate_ctes.sql +0 -0
  154. {sqlglot-27.3.1 → sqlglot-27.4.0}/tests/fixtures/optimizer/eliminate_joins.sql +0 -0
  155. {sqlglot-27.3.1 → sqlglot-27.4.0}/tests/fixtures/optimizer/eliminate_subqueries.sql +0 -0
  156. {sqlglot-27.3.1 → sqlglot-27.4.0}/tests/fixtures/optimizer/isolate_table_selects.sql +0 -0
  157. {sqlglot-27.3.1 → sqlglot-27.4.0}/tests/fixtures/optimizer/merge_subqueries.sql +0 -0
  158. {sqlglot-27.3.1 → sqlglot-27.4.0}/tests/fixtures/optimizer/normalize.sql +0 -0
  159. {sqlglot-27.3.1 → sqlglot-27.4.0}/tests/fixtures/optimizer/normalize_identifiers.sql +0 -0
  160. {sqlglot-27.3.1 → sqlglot-27.4.0}/tests/fixtures/optimizer/optimizer.sql +0 -0
  161. {sqlglot-27.3.1 → sqlglot-27.4.0}/tests/fixtures/optimizer/pushdown_cte_alias_columns.sql +0 -0
  162. {sqlglot-27.3.1 → sqlglot-27.4.0}/tests/fixtures/optimizer/pushdown_predicates.sql +0 -0
  163. {sqlglot-27.3.1 → sqlglot-27.4.0}/tests/fixtures/optimizer/pushdown_projections.sql +0 -0
  164. {sqlglot-27.3.1 → sqlglot-27.4.0}/tests/fixtures/optimizer/qualify_columns.sql +0 -0
  165. {sqlglot-27.3.1 → sqlglot-27.4.0}/tests/fixtures/optimizer/qualify_columns__invalid.sql +0 -0
  166. {sqlglot-27.3.1 → sqlglot-27.4.0}/tests/fixtures/optimizer/qualify_columns__with_invisible.sql +0 -0
  167. {sqlglot-27.3.1 → sqlglot-27.4.0}/tests/fixtures/optimizer/qualify_columns_ddl.sql +0 -0
  168. {sqlglot-27.3.1 → sqlglot-27.4.0}/tests/fixtures/optimizer/qualify_tables.sql +0 -0
  169. {sqlglot-27.3.1 → sqlglot-27.4.0}/tests/fixtures/optimizer/quote_identifiers.sql +0 -0
  170. {sqlglot-27.3.1 → sqlglot-27.4.0}/tests/fixtures/optimizer/simplify.sql +0 -0
  171. {sqlglot-27.3.1 → sqlglot-27.4.0}/tests/fixtures/optimizer/tpc-ds/call_center.csv.gz +0 -0
  172. {sqlglot-27.3.1 → sqlglot-27.4.0}/tests/fixtures/optimizer/tpc-ds/catalog_page.csv.gz +0 -0
  173. {sqlglot-27.3.1 → sqlglot-27.4.0}/tests/fixtures/optimizer/tpc-ds/catalog_returns.csv.gz +0 -0
  174. {sqlglot-27.3.1 → sqlglot-27.4.0}/tests/fixtures/optimizer/tpc-ds/catalog_sales.csv.gz +0 -0
  175. {sqlglot-27.3.1 → sqlglot-27.4.0}/tests/fixtures/optimizer/tpc-ds/customer.csv.gz +0 -0
  176. {sqlglot-27.3.1 → sqlglot-27.4.0}/tests/fixtures/optimizer/tpc-ds/customer_address.csv.gz +0 -0
  177. {sqlglot-27.3.1 → sqlglot-27.4.0}/tests/fixtures/optimizer/tpc-ds/customer_demographics.csv.gz +0 -0
  178. {sqlglot-27.3.1 → sqlglot-27.4.0}/tests/fixtures/optimizer/tpc-ds/date_dim.csv.gz +0 -0
  179. {sqlglot-27.3.1 → sqlglot-27.4.0}/tests/fixtures/optimizer/tpc-ds/household_demographics.csv.gz +0 -0
  180. {sqlglot-27.3.1 → sqlglot-27.4.0}/tests/fixtures/optimizer/tpc-ds/income_band.csv.gz +0 -0
  181. {sqlglot-27.3.1 → sqlglot-27.4.0}/tests/fixtures/optimizer/tpc-ds/inventory.csv.gz +0 -0
  182. {sqlglot-27.3.1 → sqlglot-27.4.0}/tests/fixtures/optimizer/tpc-ds/item.csv.gz +0 -0
  183. {sqlglot-27.3.1 → sqlglot-27.4.0}/tests/fixtures/optimizer/tpc-ds/promotion.csv.gz +0 -0
  184. {sqlglot-27.3.1 → sqlglot-27.4.0}/tests/fixtures/optimizer/tpc-ds/reason.csv.gz +0 -0
  185. {sqlglot-27.3.1 → sqlglot-27.4.0}/tests/fixtures/optimizer/tpc-ds/ship_mode.csv.gz +0 -0
  186. {sqlglot-27.3.1 → sqlglot-27.4.0}/tests/fixtures/optimizer/tpc-ds/store.csv.gz +0 -0
  187. {sqlglot-27.3.1 → sqlglot-27.4.0}/tests/fixtures/optimizer/tpc-ds/store_returns.csv.gz +0 -0
  188. {sqlglot-27.3.1 → sqlglot-27.4.0}/tests/fixtures/optimizer/tpc-ds/store_sales.csv.gz +0 -0
  189. {sqlglot-27.3.1 → sqlglot-27.4.0}/tests/fixtures/optimizer/tpc-ds/time_dim.csv.gz +0 -0
  190. {sqlglot-27.3.1 → sqlglot-27.4.0}/tests/fixtures/optimizer/tpc-ds/tpc-ds.sql +0 -0
  191. {sqlglot-27.3.1 → sqlglot-27.4.0}/tests/fixtures/optimizer/tpc-ds/warehouse.csv.gz +0 -0
  192. {sqlglot-27.3.1 → sqlglot-27.4.0}/tests/fixtures/optimizer/tpc-ds/web_page.csv.gz +0 -0
  193. {sqlglot-27.3.1 → sqlglot-27.4.0}/tests/fixtures/optimizer/tpc-ds/web_returns.csv.gz +0 -0
  194. {sqlglot-27.3.1 → sqlglot-27.4.0}/tests/fixtures/optimizer/tpc-ds/web_sales.csv.gz +0 -0
  195. {sqlglot-27.3.1 → sqlglot-27.4.0}/tests/fixtures/optimizer/tpc-ds/web_site.csv.gz +0 -0
  196. {sqlglot-27.3.1 → sqlglot-27.4.0}/tests/fixtures/optimizer/tpc-h/customer.csv.gz +0 -0
  197. {sqlglot-27.3.1 → sqlglot-27.4.0}/tests/fixtures/optimizer/tpc-h/lineitem.csv.gz +0 -0
  198. {sqlglot-27.3.1 → sqlglot-27.4.0}/tests/fixtures/optimizer/tpc-h/nation.csv.gz +0 -0
  199. {sqlglot-27.3.1 → sqlglot-27.4.0}/tests/fixtures/optimizer/tpc-h/orders.csv.gz +0 -0
  200. {sqlglot-27.3.1 → sqlglot-27.4.0}/tests/fixtures/optimizer/tpc-h/part.csv.gz +0 -0
  201. {sqlglot-27.3.1 → sqlglot-27.4.0}/tests/fixtures/optimizer/tpc-h/partsupp.csv.gz +0 -0
  202. {sqlglot-27.3.1 → sqlglot-27.4.0}/tests/fixtures/optimizer/tpc-h/region.csv.gz +0 -0
  203. {sqlglot-27.3.1 → sqlglot-27.4.0}/tests/fixtures/optimizer/tpc-h/supplier.csv.gz +0 -0
  204. {sqlglot-27.3.1 → sqlglot-27.4.0}/tests/fixtures/optimizer/tpc-h/tpc-h.sql +0 -0
  205. {sqlglot-27.3.1 → sqlglot-27.4.0}/tests/fixtures/optimizer/unnest_subqueries.sql +0 -0
  206. {sqlglot-27.3.1 → sqlglot-27.4.0}/tests/fixtures/partial.sql +0 -0
  207. {sqlglot-27.3.1 → sqlglot-27.4.0}/tests/fixtures/pretty.sql +0 -0
  208. {sqlglot-27.3.1 → sqlglot-27.4.0}/tests/gen_fixtures.py +0 -0
  209. {sqlglot-27.3.1 → sqlglot-27.4.0}/tests/helpers.py +0 -0
  210. {sqlglot-27.3.1 → sqlglot-27.4.0}/tests/test_build.py +0 -0
  211. {sqlglot-27.3.1 → sqlglot-27.4.0}/tests/test_dialect_imports.py +0 -0
  212. {sqlglot-27.3.1 → sqlglot-27.4.0}/tests/test_diff.py +0 -0
  213. {sqlglot-27.3.1 → sqlglot-27.4.0}/tests/test_docs.py +0 -0
  214. {sqlglot-27.3.1 → sqlglot-27.4.0}/tests/test_executor.py +0 -0
  215. {sqlglot-27.3.1 → sqlglot-27.4.0}/tests/test_expressions.py +0 -0
  216. {sqlglot-27.3.1 → sqlglot-27.4.0}/tests/test_generator.py +0 -0
  217. {sqlglot-27.3.1 → sqlglot-27.4.0}/tests/test_helper.py +0 -0
  218. {sqlglot-27.3.1 → sqlglot-27.4.0}/tests/test_jsonpath.py +0 -0
  219. {sqlglot-27.3.1 → sqlglot-27.4.0}/tests/test_lineage.py +0 -0
  220. {sqlglot-27.3.1 → sqlglot-27.4.0}/tests/test_parser.py +0 -0
  221. {sqlglot-27.3.1 → sqlglot-27.4.0}/tests/test_schema.py +0 -0
  222. {sqlglot-27.3.1 → sqlglot-27.4.0}/tests/test_serde.py +0 -0
  223. {sqlglot-27.3.1 → sqlglot-27.4.0}/tests/test_time.py +0 -0
  224. {sqlglot-27.3.1 → sqlglot-27.4.0}/tests/test_tokens.py +0 -0
  225. {sqlglot-27.3.1 → sqlglot-27.4.0}/tests/test_transforms.py +0 -0
  226. {sqlglot-27.3.1 → sqlglot-27.4.0}/tests/test_transpile.py +0 -0
@@ -1,6 +1,20 @@
1
1
  Changelog
2
2
  =========
3
3
 
4
+ ## [v27.3.1] - 2025-07-24
5
+ ### :boom: BREAKING CHANGES
6
+ - due to [`48703c4`](https://github.com/tobymao/sqlglot/commit/48703c4fadd9f24de151a63d1bfa74f4b8e71133) - temporarily move VARCHAR length inference logic to Fabric *(commit by [@georgesittas](https://github.com/georgesittas))*:
7
+
8
+ temporarily move VARCHAR length inference logic to Fabric
9
+
10
+
11
+ ### :sparkles: New Features
12
+ - [`4cc321c`](https://github.com/tobymao/sqlglot/commit/4cc321cc1995d538ab0c48a7a0a473c31e76ddff) - **singlestore**: Added initial implementation of SingleStore dialect *(PR [#5447](https://github.com/tobymao/sqlglot/pull/5447) by [@AdalbertMemSQL](https://github.com/AdalbertMemSQL))*
13
+
14
+ ### :wrench: Chores
15
+ - [`48703c4`](https://github.com/tobymao/sqlglot/commit/48703c4fadd9f24de151a63d1bfa74f4b8e71133) - **tsql**: temporarily move VARCHAR length inference logic to Fabric *(commit by [@georgesittas](https://github.com/georgesittas))*
16
+
17
+
4
18
  ## [v27.3.0] - 2025-07-24
5
19
  ### :boom: BREAKING CHANGES
6
20
  - due to [`d7ccb48`](https://github.com/tobymao/sqlglot/commit/d7ccb48e542c49258e31cc4df45f49beebc2e238) - week/quarter support *(PR [#5374](https://github.com/tobymao/sqlglot/pull/5374) by [@eakmanrq](https://github.com/eakmanrq))*:
@@ -6291,3 +6305,4 @@ Changelog
6291
6305
  [v27.1.0]: https://github.com/tobymao/sqlglot/compare/v26.31.2...v27.1.0
6292
6306
  [v27.2.0]: https://github.com/tobymao/sqlglot/compare/v27.1.0...v27.2.0
6293
6307
  [v27.3.0]: https://github.com/tobymao/sqlglot/compare/v27.0.1...v27.3.0
6308
+ [v27.3.1]: https://github.com/tobymao/sqlglot/compare/v27.3.0...v27.3.1
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: sqlglot
3
- Version: 27.3.1
3
+ Version: 27.4.0
4
4
  Summary: An easily customizable SQL parser and transpiler
5
5
  Author-email: Toby Mao <toby.mao@gmail.com>
6
6
  License: MIT License
@@ -17,5 +17,5 @@ __version__: str
17
17
  __version_tuple__: VERSION_TUPLE
18
18
  version_tuple: VERSION_TUPLE
19
19
 
20
- __version__ = version = '27.3.1'
21
- __version_tuple__ = version_tuple = (27, 3, 1)
20
+ __version__ = version = '27.4.0'
21
+ __version_tuple__ = version_tuple = (27, 4, 0)
@@ -365,6 +365,31 @@ def _annotate_concat(self: TypeAnnotator, expression: exp.Concat) -> exp.Concat:
365
365
  return annotated
366
366
 
367
367
 
368
+ def _annotate_array(self: TypeAnnotator, expression: exp.Array) -> exp.Array:
369
+ array_args = expression.expressions
370
+
371
+ # BigQuery behaves as follows:
372
+ #
373
+ # SELECT t, TYPEOF(t) FROM (SELECT 'foo') AS t -- foo, STRUCT<STRING>
374
+ # SELECT ARRAY(SELECT 'foo'), TYPEOF(ARRAY(SELECT 'foo')) -- foo, ARRAY<STRING>
375
+ if (
376
+ len(array_args) == 1
377
+ and isinstance(select := array_args[0].unnest(), exp.Select)
378
+ and (query_type := select.meta.get("query_type")) is not None
379
+ and query_type.is_type(exp.DataType.Type.STRUCT)
380
+ and len(query_type.expressions) == 1
381
+ ):
382
+ projection_type = query_type.expressions[0].kind.copy()
383
+ array_type = exp.DataType(
384
+ this=exp.DataType.Type.ARRAY,
385
+ expressions=[projection_type],
386
+ nested=True,
387
+ )
388
+ return self._annotate_with_type(expression, array_type)
389
+
390
+ return self._annotate_by_args(expression, "expressions", array=True)
391
+
392
+
368
393
  class BigQuery(Dialect):
369
394
  WEEK_OFFSET = -1
370
395
  UNNEST_COLUMN_ONLY = True
@@ -445,6 +470,7 @@ class BigQuery(Dialect):
445
470
  exp.Substring,
446
471
  )
447
472
  },
473
+ exp.Array: _annotate_array,
448
474
  exp.ArrayConcat: lambda self, e: self._annotate_by_args(e, "this", "expressions"),
449
475
  exp.Ascii: lambda self, e: self._annotate_with_type(e, exp.DataType.Type.BIGINT),
450
476
  exp.BitwiseAndAgg: lambda self, e: self._annotate_with_type(e, exp.DataType.Type.BIGINT),
@@ -13,6 +13,12 @@ from sqlglot.generator import unsupported_args
13
13
  from sqlglot.tokens import TokenType
14
14
 
15
15
 
16
+ def _sha2_sql(self: Exasol.Generator, expression: exp.SHA2) -> str:
17
+ length = expression.text("length")
18
+ func_name = "HASH_SHA256" if length == "256" else "HASH_SHA512"
19
+ return self.func(func_name, expression.this)
20
+
21
+
16
22
  class Exasol(Dialect):
17
23
  TIME_MAPPING = {
18
24
  "yyyy": "%Y",
@@ -59,6 +65,10 @@ class Exasol(Dialect):
59
65
  "BIT_RSHIFT": binary_from_function(exp.BitwiseRightShift),
60
66
  "EVERY": lambda args: exp.All(this=seq_get(args, 0)),
61
67
  "EDIT_DISTANCE": exp.Levenshtein.from_arg_list,
68
+ "HASH_SHA": exp.SHA.from_arg_list,
69
+ "HASH_SHA1": exp.SHA.from_arg_list,
70
+ "HASH_MD5": exp.MD5.from_arg_list,
71
+ "HASHTYPE_MD5": exp.MD5Digest.from_arg_list,
62
72
  "REGEXP_REPLACE": lambda args: exp.RegexpReplace(
63
73
  this=seq_get(args, 0),
64
74
  expression=seq_get(args, 1),
@@ -66,6 +76,12 @@ class Exasol(Dialect):
66
76
  position=seq_get(args, 3),
67
77
  occurrence=seq_get(args, 4),
68
78
  ),
79
+ "HASH_SHA256": lambda args: exp.SHA2(
80
+ this=seq_get(args, 0), length=exp.Literal.number(256)
81
+ ),
82
+ "HASH_SHA512": lambda args: exp.SHA2(
83
+ this=seq_get(args, 0), length=exp.Literal.number(512)
84
+ ),
69
85
  "VAR_POP": exp.VariancePop.from_arg_list,
70
86
  "APPROXIMATE_COUNT_DISTINCT": exp.ApproxDistinct.from_arg_list,
71
87
  "TO_CHAR": build_formatted_time(exp.ToChar, "exasol"),
@@ -173,6 +189,14 @@ class Exasol(Dialect):
173
189
  self, e, func_name="INSTR", supports_position=True, supports_occurrence=True
174
190
  )
175
191
  ),
192
+ # https://docs.exasol.com/db/latest/sql_references/functions/alphabeticallistfunctions/hash_sha%5B1%5D.htm#HASH_SHA%5B1%5D
193
+ exp.SHA: rename_func("HASH_SHA"),
194
+ # https://docs.exasol.com/db/latest/sql_references/functions/alphabeticallistfunctions/hash_sha256.htm
195
+ # https://docs.exasol.com/db/latest/sql_references/functions/alphabeticallistfunctions/hash_sha512.htm
196
+ exp.SHA2: _sha2_sql,
197
+ exp.MD5: rename_func("HASH_MD5"),
198
+ # https://docs.exasol.com/db/latest/sql_references/functions/alphabeticallistfunctions/hashtype_md5.htm
199
+ exp.MD5Digest: rename_func("HASHTYPE_MD5"),
176
200
  # https://docs.exasol.com/db/latest/sql/create_view.htm
177
201
  exp.CommentColumnConstraint: lambda self, e: f"COMMENT IS {self.sql(e, 'this')}",
178
202
  }
@@ -1673,3 +1673,17 @@ class Snowflake(Dialect):
1673
1673
  to=exp.DataType(this=exp.DataType.Type.DATE),
1674
1674
  )
1675
1675
  return self.sql(expr)
1676
+
1677
+ def dot_sql(self, expression: exp.Dot) -> str:
1678
+ this = expression.this
1679
+
1680
+ if not this.type:
1681
+ from sqlglot.optimizer.annotate_types import annotate_types
1682
+
1683
+ this = annotate_types(this, dialect=self.dialect)
1684
+
1685
+ if not isinstance(this, exp.Dot) and this.is_type(exp.DataType.Type.STRUCT):
1686
+ # Generate colon notation for the top level STRUCT
1687
+ return f"{self.sql(this)}:{self.sql(expression, 'expression')}"
1688
+
1689
+ return super().dot_sql(expression)
@@ -96,7 +96,12 @@ class SQLite(Dialect):
96
96
 
97
97
  NESTED_COMMENTS = False
98
98
 
99
- KEYWORDS = tokens.Tokenizer.KEYWORDS.copy()
99
+ KEYWORDS = {
100
+ **tokens.Tokenizer.KEYWORDS,
101
+ "ATTACH": TokenType.ATTACH,
102
+ "DETACH": TokenType.DETACH,
103
+ }
104
+
100
105
  KEYWORDS.pop("/*+")
101
106
 
102
107
  COMMANDS = {*tokens.Tokenizer.COMMANDS, TokenType.REPLACE}
@@ -114,6 +119,12 @@ class SQLite(Dialect):
114
119
  "TIME": lambda args: exp.Anonymous(this="TIME", expressions=args),
115
120
  }
116
121
 
122
+ STATEMENT_PARSERS = {
123
+ **parser.Parser.STATEMENT_PARSERS,
124
+ TokenType.ATTACH: lambda self: self._parse_attach_detach(),
125
+ TokenType.DETACH: lambda self: self._parse_attach_detach(is_attach=False),
126
+ }
127
+
117
128
  def _parse_unique(self) -> exp.UniqueColumnConstraint:
118
129
  # Do not consume more tokens if UNIQUE is used as a standalone constraint, e.g:
119
130
  # CREATE TABLE foo (bar TEXT UNIQUE REFERENCES baz ...)
@@ -122,6 +133,16 @@ class SQLite(Dialect):
122
133
 
123
134
  return super()._parse_unique()
124
135
 
136
+ def _parse_attach_detach(self, is_attach=True) -> exp.Attach | exp.Detach:
137
+ self._match(TokenType.DATABASE)
138
+ this = self._parse_expression()
139
+
140
+ return (
141
+ self.expression(exp.Attach, this=this)
142
+ if is_attach
143
+ else self.expression(exp.Detach, this=this)
144
+ )
145
+
125
146
  class Generator(generator.Generator):
126
147
  JOIN_HINTS = False
127
148
  TABLE_HINTS = False
@@ -4942,7 +4942,7 @@ class AddConstraint(Expression):
4942
4942
 
4943
4943
 
4944
4944
  class AddPartition(Expression):
4945
- arg_types = {"this": True, "exists": False}
4945
+ arg_types = {"this": True, "exists": False, "location": False}
4946
4946
 
4947
4947
 
4948
4948
  class AttachOption(Expression):
@@ -3549,7 +3549,9 @@ class Generator(metaclass=_Generator):
3549
3549
 
3550
3550
  def addpartition_sql(self, expression: exp.AddPartition) -> str:
3551
3551
  exists = "IF NOT EXISTS " if expression.args.get("exists") else ""
3552
- return f"ADD {exists}{self.sql(expression.this)}"
3552
+ location = self.sql(expression, "location")
3553
+ location = f" {location}" if location else ""
3554
+ return f"ADD {exists}{self.sql(expression.this)}{location}"
3553
3555
 
3554
3556
  def distinct_sql(self, expression: exp.Distinct) -> str:
3555
3557
  this = self.expressions(expression, flat=True)
@@ -313,9 +313,11 @@ class TypeAnnotator(metaclass=_TypeAnnotator):
313
313
  elif (
314
314
  isinstance(source, Scope)
315
315
  and isinstance(source.expression, exp.Query)
316
- and source.expression.is_type(exp.DataType.Type.STRUCT)
316
+ and (
317
+ source.expression.meta.get("query_type") or exp.DataType.build("UNKNOWN")
318
+ ).is_type(exp.DataType.Type.STRUCT)
317
319
  ):
318
- self._set_type(table_column, source.expression.type)
320
+ self._set_type(table_column, source.expression.meta["query_type"])
319
321
 
320
322
  # Then (possibly) annotate the remaining expressions in the scope
321
323
  self._maybe_annotate(scope.expression)
@@ -335,7 +337,10 @@ class TypeAnnotator(metaclass=_TypeAnnotator):
335
337
  for cd in struct_type.expressions
336
338
  if cd.kind
337
339
  ):
338
- self._set_type(scope.expression, struct_type)
340
+ # We don't use `_set_type` on purpose here. If we annotated the query directly, then
341
+ # using it in other contexts (e.g., ARRAY(<query>)) could result in incorrect type
342
+ # annotations, i.e., it shouldn't be interpreted as a STRUCT value.
343
+ scope.expression.meta["query_type"] = struct_type
339
344
 
340
345
  def _maybe_annotate(self, expression: E) -> E:
341
346
  if id(expression) in self._visited:
@@ -79,7 +79,8 @@ def normalize(expression):
79
79
  if join.kind == "CROSS":
80
80
  join.set("on", None)
81
81
  else:
82
- join.set("kind", None)
82
+ if join.kind in ("INNER", "OUTER"):
83
+ join.set("kind", None)
83
84
 
84
85
  if not join.args.get("on") and not join.args.get("using"):
85
86
  join.set("on", exp.true())
@@ -7394,7 +7394,11 @@ class Parser(metaclass=_Parser):
7394
7394
  exists = self._parse_exists(not_=True)
7395
7395
  if self._match_pair(TokenType.PARTITION, TokenType.L_PAREN, advance=False):
7396
7396
  return self.expression(
7397
- exp.AddPartition, exists=exists, this=self._parse_field(any_token=True)
7397
+ exp.AddPartition,
7398
+ exists=exists,
7399
+ this=self._parse_field(any_token=True),
7400
+ location=self._match_text_seq("LOCATION", advance=False)
7401
+ and self._parse_property(),
7398
7402
  )
7399
7403
 
7400
7404
  return None
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: sqlglot
3
- Version: 27.3.1
3
+ Version: 27.4.0
4
4
  Summary: An easily customizable SQL parser and transpiler
5
5
  Author-email: Toby Mao <toby.mao@gmail.com>
6
6
  License: MIT License
@@ -1762,6 +1762,14 @@ WHERE
1762
1762
  self.validate_identity("ARRAY_LAST(['a', 'b'])")
1763
1763
  self.validate_identity("JSON_TYPE(PARSE_JSON('1'))")
1764
1764
 
1765
+ self.validate_all(
1766
+ "SELECT CAST(col AS STRUCT<fld1 STRUCT<fld2 INT>>).fld1.fld2",
1767
+ write={
1768
+ "bigquery": "SELECT CAST(col AS STRUCT<fld1 STRUCT<fld2 INT64>>).fld1.fld2",
1769
+ "snowflake": "SELECT CAST(col AS OBJECT(fld1 OBJECT(fld2 INT))):fld1.fld2",
1770
+ },
1771
+ )
1772
+
1765
1773
  def test_errors(self):
1766
1774
  with self.assertRaises(ParseError):
1767
1775
  self.parse_one("SELECT * FROM a - b.c.d2")
@@ -398,3 +398,85 @@ class TestExasol(Validator):
398
398
  "exasol": 'CREATE OR REPLACE VIEW "schema"."v" ("col" COMMENT IS \'desc\') AS SELECT "src_col" AS "col"',
399
399
  },
400
400
  )
401
+ self.validate_all(
402
+ "HASH_SHA(x)",
403
+ read={
404
+ "clickhouse": "SHA1(x)",
405
+ "exasol": "HASH_SHA1(x)",
406
+ "presto": "SHA1(x)",
407
+ "trino": "SHA1(x)",
408
+ },
409
+ write={
410
+ "exasol": "HASH_SHA(x)",
411
+ "clickhouse": "SHA1(x)",
412
+ "bigquery": "SHA1(x)",
413
+ "": "SHA(x)",
414
+ "presto": "SHA1(x)",
415
+ "trino": "SHA1(x)",
416
+ },
417
+ )
418
+ self.validate_all(
419
+ "HASH_MD5(x)",
420
+ write={
421
+ "exasol": "HASH_MD5(x)",
422
+ "": "MD5(x)",
423
+ "bigquery": "TO_HEX(MD5(x))",
424
+ "clickhouse": "LOWER(HEX(MD5(x)))",
425
+ "hive": "MD5(x)",
426
+ "presto": "LOWER(TO_HEX(MD5(x)))",
427
+ "spark": "MD5(x)",
428
+ "trino": "LOWER(TO_HEX(MD5(x)))",
429
+ },
430
+ )
431
+ self.validate_all(
432
+ "HASHTYPE_MD5(x)",
433
+ write={
434
+ "exasol": "HASHTYPE_MD5(x)",
435
+ "": "MD5_DIGEST(x)",
436
+ "bigquery": "MD5(x)",
437
+ "clickhouse": "MD5(x)",
438
+ "hive": "UNHEX(MD5(x))",
439
+ "presto": "MD5(x)",
440
+ "spark": "UNHEX(MD5(x))",
441
+ "trino": "MD5(x)",
442
+ },
443
+ )
444
+
445
+ self.validate_all(
446
+ "HASH_SHA256(x)",
447
+ read={
448
+ "clickhouse": "SHA256(x)",
449
+ "presto": "SHA256(x)",
450
+ "trino": "SHA256(x)",
451
+ "postgres": "SHA256(x)",
452
+ "duckdb": "SHA256(x)",
453
+ },
454
+ write={
455
+ "exasol": "HASH_SHA256(x)",
456
+ "bigquery": "SHA256(x)",
457
+ "spark2": "SHA2(x, 256)",
458
+ "clickhouse": "SHA256(x)",
459
+ "postgres": "SHA256(x)",
460
+ "presto": "SHA256(x)",
461
+ "redshift": "SHA2(x, 256)",
462
+ "trino": "SHA256(x)",
463
+ "duckdb": "SHA256(x)",
464
+ "snowflake": "SHA2(x, 256)",
465
+ },
466
+ )
467
+ self.validate_all(
468
+ "HASH_SHA512(x)",
469
+ read={
470
+ "clickhouse": "SHA512(x)",
471
+ "presto": "SHA512(x)",
472
+ "trino": "SHA512(x)",
473
+ },
474
+ write={
475
+ "exasol": "HASH_SHA512(x)",
476
+ "clickhouse": "SHA512(x)",
477
+ "bigquery": "SHA512(x)",
478
+ "spark2": "SHA2(x, 512)",
479
+ "presto": "SHA512(x)",
480
+ "trino": "SHA512(x)",
481
+ },
482
+ )
@@ -216,6 +216,21 @@ class TestHive(Validator):
216
216
  },
217
217
  )
218
218
 
219
+ self.validate_all(
220
+ "ALTER TABLE db.example_table ADD PARTITION(col_a = 'a') LOCATION 'b'",
221
+ read={
222
+ "spark2": "ALTER TABLE db.example_table ADD PARTITION(col_a = 'a') LOCATION 'b'",
223
+ "spark": "ALTER TABLE db.example_table ADD PARTITION(col_a = 'a') LOCATION 'b'",
224
+ "databricks": "ALTER TABLE db.example_table ADD PARTITION(col_a = 'a') LOCATION 'b'",
225
+ },
226
+ write={
227
+ "hive": "ALTER TABLE db.example_table ADD PARTITION(col_a = 'a') LOCATION 'b'",
228
+ "spark2": "ALTER TABLE db.example_table ADD PARTITION(col_a = 'a') LOCATION 'b'",
229
+ "spark": "ALTER TABLE db.example_table ADD PARTITION(col_a = 'a') LOCATION 'b'",
230
+ "databricks": "ALTER TABLE db.example_table ADD PARTITION(col_a = 'a') LOCATION 'b'",
231
+ },
232
+ )
233
+
219
234
  def test_lateral_view(self):
220
235
  self.validate_all(
221
236
  "SELECT a, b FROM x LATERAL VIEW EXPLODE(y) t AS a LATERAL VIEW EXPLODE(z) u AS b",
@@ -122,6 +122,22 @@ class TestSQLite(Validator):
122
122
  'CREATE TABLE "foo t" ("foo t id" TEXT NOT NULL PRIMARY KEY)',
123
123
  )
124
124
  self.validate_identity("REPLACE INTO foo (x, y) VALUES (1, 2)", check_command_warning=True)
125
+ self.validate_identity(
126
+ "ATTACH DATABASE 'foo' AS schema_name", "ATTACH 'foo' AS schema_name"
127
+ )
128
+ self.validate_identity(
129
+ "ATTACH DATABASE NOT EXISTS(SELECT 1) AS schema_name",
130
+ "ATTACH NOT EXISTS(SELECT 1) AS schema_name",
131
+ )
132
+ self.validate_identity(
133
+ "ATTACH DATABASE IIF(NOT EXISTS(SELECT 1), 'foo1', 'foo2') AS schema_name",
134
+ "ATTACH IIF(NOT EXISTS(SELECT 1), 'foo1', 'foo2') AS schema_name",
135
+ )
136
+ self.validate_identity(
137
+ "ATTACH DATABASE 'foo' || '.foo2' AS schema_name",
138
+ "ATTACH 'foo' || '.foo2' AS schema_name",
139
+ )
140
+ self.validate_identity("DETACH DATABASE schema_name", "DETACH schema_name")
125
141
 
126
142
  def test_strftime(self):
127
143
  self.validate_identity("SELECT STRFTIME('%Y/%m/%d', 'now')")
@@ -36,3 +36,9 @@ SELECT * FROM x JOIN z USING (id);
36
36
 
37
37
  SELECT * FROM x CROSS JOIN z ON TRUE;
38
38
  SELECT * FROM x CROSS JOIN z;
39
+
40
+ SELECT * FROM x LEFT ANTI JOIN y ON x.a = y.a;
41
+ SELECT * FROM x LEFT ANTI JOIN y ON x.a = y.a;
42
+
43
+ SELECT * FROM x LEFT SEMI JOIN y ON x.a = y.a;
44
+ SELECT * FROM x LEFT SEMI JOIN y ON x.a = y.a;
@@ -1589,7 +1589,7 @@ FROM READ_CSV('tests/fixtures/optimizer/tpc-h/nation.csv.gz', 'delimiter', '|')
1589
1589
  schema = {"d": {"s": {"t": {"c1": "int64", "c2": "struct<f1 int64, f2 string>"}}}}
1590
1590
 
1591
1591
  def _annotate(query: str) -> exp.Expression:
1592
- expression = parse_one(example_query, dialect=dialect)
1592
+ expression = parse_one(query, dialect=dialect)
1593
1593
  qual = optimizer.qualify.qualify(expression, schema=schema, dialect=dialect)
1594
1594
  return optimizer.annotate_types.annotate_types(qual, schema=schema, dialect=dialect)
1595
1595
 
@@ -1620,3 +1620,8 @@ FROM READ_CSV('tests/fixtures/optimizer/tpc-h/nation.csv.gz', 'delimiter', '|')
1620
1620
  annotated = _annotate(example_query)
1621
1621
 
1622
1622
  self.assertTrue(annotated.selects[0].is_type("UNKNOWN"))
1623
+
1624
+ for query in ("SELECT 'foo'", "(SELECT 'foo')"):
1625
+ query = f"SELECT ARRAY({query})"
1626
+ with self.subTest(f"Annotating '{query}' in BigQuery"):
1627
+ self.assertTrue(_annotate(query).selects[0].is_type("ARRAY<VARCHAR>"))
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes