@quereus/quereus 4.20.1 → 4.20.3

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 (380) hide show
  1. package/README.md +2 -0
  2. package/dist/src/schema/schema-differ.d.ts.map +1 -1
  3. package/dist/src/schema/schema-differ.js +17 -69
  4. package/dist/src/schema/schema-differ.js.map +1 -1
  5. package/package.json +7 -4
  6. package/test/README.md +173 -0
  7. package/test/logic/01-basic.sqllogic +39 -0
  8. package/test/logic/01.1-select-projection-extras.sqllogic +130 -0
  9. package/test/logic/01.2-strings.sqllogic +43 -0
  10. package/test/logic/01.5-insert-select.sqllogic +237 -0
  11. package/test/logic/01.6-update-extras.sqllogic +118 -0
  12. package/test/logic/01.7-update-from.sqllogic +67 -0
  13. package/test/logic/01.8-delete-extras.sqllogic +122 -0
  14. package/test/logic/01.8.1-delete-range-cow.sqllogic +115 -0
  15. package/test/logic/01.9-query-expr-dml-gates.sqllogic +32 -0
  16. package/test/logic/01.9-query-expr-dml.sqllogic +171 -0
  17. package/test/logic/01.9-query-expr-values.sqllogic +111 -0
  18. package/test/logic/01.9.1-limit-over-dml-subquery.sqllogic +119 -0
  19. package/test/logic/02-filters.sqllogic +54 -0
  20. package/test/logic/02-smoke.sqllogic +62 -0
  21. package/test/logic/02.1-bind-parameters.sqllogic +223 -0
  22. package/test/logic/03-expressions.sqllogic +190 -0
  23. package/test/logic/03.1-quoted-identifiers.sqllogic +55 -0
  24. package/test/logic/03.4-defaults.sqllogic +554 -0
  25. package/test/logic/03.4.1-default-edge-cases.sqllogic +99 -0
  26. package/test/logic/03.5-tvf.sqllogic +61 -0
  27. package/test/logic/03.6-type-system.sqllogic +544 -0
  28. package/test/logic/03.6.1-numeric-text-comparison-coercion.sqllogic +244 -0
  29. package/test/logic/03.6.2-value-to-text.sqllogic +224 -0
  30. package/test/logic/03.7-bigint-mixed-arithmetic.sqllogic +65 -0
  31. package/test/logic/03.8-not-precedence.sqllogic +255 -0
  32. package/test/logic/03.9-is-bool-predicate.sqllogic +150 -0
  33. package/test/logic/03.9.1-is-bool-predicate-partial-index.sqllogic +34 -0
  34. package/test/logic/04-order-by.sqllogic +38 -0
  35. package/test/logic/04-transactions.sqllogic +239 -0
  36. package/test/logic/04a-savepoint-lazy-attach.sqllogic +122 -0
  37. package/test/logic/05-vtab_memory.sqllogic +50 -0
  38. package/test/logic/05.0.1-vtab-memory-unique-index-collation.sqllogic +34 -0
  39. package/test/logic/05.1-composite-pk-range-scan.sqllogic +147 -0
  40. package/test/logic/05.1.1-secondary-index-range-scan.sqllogic +56 -0
  41. package/test/logic/05.2-cast-seek-correctness.sqllogic +124 -0
  42. package/test/logic/06-builtin_functions.sqllogic +149 -0
  43. package/test/logic/06.1-string-functions.sqllogic +92 -0
  44. package/test/logic/06.1.3-like-glob-edges.sqllogic +53 -0
  45. package/test/logic/06.2-math-functions.sqllogic +82 -0
  46. package/test/logic/06.3-schema.sqllogic +48 -0
  47. package/test/logic/06.3.1-schema-all-schemas.sqllogic +39 -0
  48. package/test/logic/06.3.2-schema-foreign-keys.sqllogic +208 -0
  49. package/test/logic/06.3.3-introspection-tags.sqllogic +202 -0
  50. package/test/logic/06.3.3.1-introspection-tags-index.sqllogic +74 -0
  51. package/test/logic/06.3.4-view-info.sqllogic +378 -0
  52. package/test/logic/06.3.5-column-info.sqllogic +347 -0
  53. package/test/logic/06.3.6-schema-views.sqllogic +29 -0
  54. package/test/logic/06.4-schema-search-path.sqllogic +354 -0
  55. package/test/logic/06.4.1-schema-case-insensitive.sqllogic +83 -0
  56. package/test/logic/06.4.2-collation-extras.sqllogic +472 -0
  57. package/test/logic/06.4.2.1-collation-index-access-paths.sqllogic +140 -0
  58. package/test/logic/06.4.3-write-path-collation.sqllogic +99 -0
  59. package/test/logic/06.4.4-comparison-collation-precedence.sqllogic +342 -0
  60. package/test/logic/06.4.5-any-collate-declared-keys.sqllogic +92 -0
  61. package/test/logic/06.5-polymorphic-types.sqllogic +169 -0
  62. package/test/logic/06.5.1-conversion-functions.sqllogic +173 -0
  63. package/test/logic/06.5.2-scalar-minmax.sqllogic +16 -0
  64. package/test/logic/06.5.3-undeclared-return-type-comparison.sqllogic +244 -0
  65. package/test/logic/06.5.4-declared-return-type-builtins.sqllogic +288 -0
  66. package/test/logic/06.6-aggregate-extended.sqllogic +78 -0
  67. package/test/logic/06.7-json-extended.sqllogic +53 -0
  68. package/test/logic/06.8-json-path-operators.sqllogic +99 -0
  69. package/test/logic/06.9-json-canonical-key.sqllogic +65 -0
  70. package/test/logic/06.9.1-json-coerce-once.sqllogic +417 -0
  71. package/test/logic/06.9.1.1-json-coerce-once-index.sqllogic +39 -0
  72. package/test/logic/06.9.2-json-structural-equality.sqllogic +382 -0
  73. package/test/logic/06.9.2.1-json-structural-equality-index.sqllogic +76 -0
  74. package/test/logic/06.9.3-json-index-range-seek.sqllogic +205 -0
  75. package/test/logic/07-aggregates.sqllogic +193 -0
  76. package/test/logic/07.1-aggregate-filter-clause.sqllogic +12 -0
  77. package/test/logic/07.2-aggregate-order-by.sqllogic +11 -0
  78. package/test/logic/07.3-group-by-extras.sqllogic +602 -0
  79. package/test/logic/07.3.1-group-by-order-by-key.sqllogic +164 -0
  80. package/test/logic/07.3.2-grouped-select-list-shape.sqllogic +231 -0
  81. package/test/logic/07.4-group-by-filter-composite-pk.sqllogic +120 -0
  82. package/test/logic/07.5-sum-mixed-exact-and-float.sqllogic +151 -0
  83. package/test/logic/07.5-window.sqllogic +1941 -0
  84. package/test/logic/07.5.1-window-named.sqllogic +13 -0
  85. package/test/logic/07.5.2-window-nth-value.sqllogic +13 -0
  86. package/test/logic/07.6-subqueries.sqllogic +78 -0
  87. package/test/logic/07.6.1-subquery-extras.sqllogic +93 -0
  88. package/test/logic/07.7-and-or-short-circuit.sqllogic +58 -0
  89. package/test/logic/07.7-in-subquery-caching.sqllogic +174 -0
  90. package/test/logic/07.7-scalar-agg-decorrelation.sqllogic +197 -0
  91. package/test/logic/07.7.1-in-extras.sqllogic +158 -0
  92. package/test/logic/07.7.1-scalar-agg-decorrelation-filter.sqllogic +105 -0
  93. package/test/logic/07.7.2-scalar-agg-decorrelation-nested.sqllogic +115 -0
  94. package/test/logic/07.7.3-exists-in-select-decorrelation.sqllogic +107 -0
  95. package/test/logic/07.7.4-where-conjunct-ordering.sqllogic +121 -0
  96. package/test/logic/07.7.5-filter-lost-under-index-order.sqllogic +134 -0
  97. package/test/logic/07.7.6-correlated-predicate-scope.sqllogic +178 -0
  98. package/test/logic/07.7.7-join-source-scope-shadowing.sqllogic +137 -0
  99. package/test/logic/07.7.8-correlated-ref-to-computed-column.sqllogic +165 -0
  100. package/test/logic/07.7.9-conjunct-monotonicity.sqllogic +200 -0
  101. package/test/logic/07.8-correlated-subquery-edges.sqllogic +71 -0
  102. package/test/logic/07.8.1-correlated-in-decorrelation-gates.sqllogic +156 -0
  103. package/test/logic/07.9-in-value-list.sqllogic +154 -0
  104. package/test/logic/07.9.1-in-value-list-composite-index.sqllogic +38 -0
  105. package/test/logic/08-views.sqllogic +64 -0
  106. package/test/logic/08.1-semi-anti-join.sqllogic +191 -0
  107. package/test/logic/08.1-view-edge-cases.sqllogic +118 -0
  108. package/test/logic/08.1.1-uncorrelated-in-semijoin.sqllogic +251 -0
  109. package/test/logic/08.2-existence-flag-semijoin-recovery.sqllogic +197 -0
  110. package/test/logic/08.3-existence-flag-inner-recovery.sqllogic +102 -0
  111. package/test/logic/08.4-key-set-semi-join.sqllogic +447 -0
  112. package/test/logic/09-set_operations.sqllogic +244 -0
  113. package/test/logic/09.1-set-op-cross-collation.sqllogic +230 -0
  114. package/test/logic/10-distinct_datatypes.sqllogic +127 -0
  115. package/test/logic/10.1-ddl-lifecycle.sqllogic +203 -0
  116. package/test/logic/10.1.1-create-table-syntax-edges.sqllogic +47 -0
  117. package/test/logic/10.1.2-ddl-in-transaction.sqllogic +143 -0
  118. package/test/logic/10.1.2.1-add-constraint-in-transaction.sqllogic +59 -0
  119. package/test/logic/10.1.3-ddl-drop-in-transaction.sqllogic +187 -0
  120. package/test/logic/10.1.3.1-drop-constraint-in-transaction.sqllogic +45 -0
  121. package/test/logic/10.1.4-create-table-duplicate-constraint-names.sqllogic +149 -0
  122. package/test/logic/10.1.4-ddl-transaction-policy.sqllogic +314 -0
  123. package/test/logic/10.1.5-alter-add-constraint-minted-name-disambiguation.sqllogic +219 -0
  124. package/test/logic/10.1.5-create-index-lifecycle.sqllogic +72 -0
  125. package/test/logic/10.1.6-ddl-transaction-policy-index.sqllogic +143 -0
  126. package/test/logic/10.1.7-create-table-default-type-check.sqllogic +119 -0
  127. package/test/logic/10.1.8-alter-add-check-existing-rows.sqllogic +117 -0
  128. package/test/logic/10.2-column-features.sqllogic +365 -0
  129. package/test/logic/10.2.1-table-options-rejection.sqllogic +63 -0
  130. package/test/logic/10.2.2-default-collation-memory.sqllogic +30 -0
  131. package/test/logic/10.3-function-features.sqllogic +247 -0
  132. package/test/logic/10.4-schema-scale.sqllogic +168 -0
  133. package/test/logic/10.4.1-schema-scale-indexes.sqllogic +121 -0
  134. package/test/logic/10.5-indexes.sqllogic +164 -0
  135. package/test/logic/10.5.1-partial-indexes.sqllogic +526 -0
  136. package/test/logic/10.5.2-expression-indexes.sqllogic +34 -0
  137. package/test/logic/10.5.3-desc-index-ordering.sqllogic +130 -0
  138. package/test/logic/10.5.4-composite-pk-index-update-phantom.sqllogic +55 -0
  139. package/test/logic/10.5.5-index-name-uniqueness.sqllogic +76 -0
  140. package/test/logic/10.5.6-minmax-index-boundary.sqllogic +204 -0
  141. package/test/logic/10.5.7-implicit-unique-index-lifecycle.sqllogic +1216 -0
  142. package/test/logic/10.6-distinct-edge-cases.sqllogic +119 -0
  143. package/test/logic/100-predicate-normalization-edge-cases.sqllogic +238 -0
  144. package/test/logic/100.1-where-extras.sqllogic +163 -0
  145. package/test/logic/100.1.1-where-join-on-order-indexed.sqllogic +35 -0
  146. package/test/logic/101-builtin-mutation-kills.sqllogic +974 -0
  147. package/test/logic/101-transaction-edge-cases.sqllogic +395 -0
  148. package/test/logic/102-schema-catalog-edge-cases.sqllogic +252 -0
  149. package/test/logic/102-unique-constraints.sqllogic +145 -0
  150. package/test/logic/102.0.1-schema-catalog-indexed-table.sqllogic +32 -0
  151. package/test/logic/102.1-unique-edge-cases.sqllogic +111 -0
  152. package/test/logic/102.1.1-unique-index-creation-edge-cases.sqllogic +75 -0
  153. package/test/logic/102.2-unique-collation.sqllogic +181 -0
  154. package/test/logic/102.2.1-unique-collation-index-derived.sqllogic +305 -0
  155. package/test/logic/103-database-options-edge-cases.sqllogic +108 -0
  156. package/test/logic/103.1-pragma-boolean-values.sqllogic +126 -0
  157. package/test/logic/104-emit-mutation-kills.sqllogic +236 -0
  158. package/test/logic/105-vtab-memory-mutation-kills.sqllogic +754 -0
  159. package/test/logic/105.1-vtab-memory-index-mutation-kills.sqllogic +540 -0
  160. package/test/logic/106-constraint-extractor-mutation-kills.sqllogic +350 -0
  161. package/test/logic/107-temporal-arithmetic-mutation-kills.sqllogic +833 -0
  162. package/test/logic/108-cardinality-estimation.sqllogic +146 -0
  163. package/test/logic/108.1-analyze-name-resolution.sqllogic +102 -0
  164. package/test/logic/109-aggregate-physical-selection.sqllogic +103 -0
  165. package/test/logic/11-joins.sqllogic +86 -0
  166. package/test/logic/11.1-join-using.sqllogic +267 -0
  167. package/test/logic/11.2-comma-join.sqllogic +35 -0
  168. package/test/logic/11.3-index-nested-loop-join.sqllogic +305 -0
  169. package/test/logic/11.3-mismatched-collation-join.sqllogic +74 -0
  170. package/test/logic/11.4-hash-join-side-swap.sqllogic +118 -0
  171. package/test/logic/110-scan-emitter-mutation-kills.sqllogic +121 -0
  172. package/test/logic/110.1-scan-emitter-index-scan-kills.sqllogic +47 -0
  173. package/test/logic/12-empty-primary-key.sqllogic +124 -0
  174. package/test/logic/12-join_padding_order.sqllogic +58 -0
  175. package/test/logic/12.1-orderby-index-consumption.sqllogic +40 -0
  176. package/test/logic/13-cte.sqllogic +137 -0
  177. package/test/logic/13.1-cte-multiple-recursive.sqllogic +104 -0
  178. package/test/logic/13.10-cte-qualified-name.sqllogic +136 -0
  179. package/test/logic/13.11-unreferenced-dml-cte.sqllogic +414 -0
  180. package/test/logic/13.12-nested-dml-cte-rejected.sqllogic +280 -0
  181. package/test/logic/13.2-cte-bind-params.sqllogic +98 -0
  182. package/test/logic/13.3-cte-edge-cases.sqllogic +120 -0
  183. package/test/logic/13.4-cte-extras.sqllogic +98 -0
  184. package/test/logic/13.5-cte-join-order.sqllogic +166 -0
  185. package/test/logic/13.6-cte-dml-runs-once.sqllogic +318 -0
  186. package/test/logic/13.7-cte-sibling-visibility.sqllogic +227 -0
  187. package/test/logic/13.8-insert-with-clause-visibility.sqllogic +254 -0
  188. package/test/logic/13.9-schema-authored-cte-isolation.sqllogic +328 -0
  189. package/test/logic/13.9.1-schema-authored-schema-path-isolation.sqllogic +408 -0
  190. package/test/logic/14-utilities.sqllogic +168 -0
  191. package/test/logic/15-timespan.sqllogic +279 -0
  192. package/test/logic/15.1-semantic-ordering.sqllogic +960 -0
  193. package/test/logic/15.1.1-json-check-coercion.sqllogic +178 -0
  194. package/test/logic/15.1.2-semantic-ordering-index.sqllogic +41 -0
  195. package/test/logic/15.1.3-declared-form-write-contract.sqllogic +519 -0
  196. package/test/logic/16-epoch.sqllogic +187 -0
  197. package/test/logic/17-weekday-modifier.sqllogic +78 -0
  198. package/test/logic/18-json-string-escapes.sqllogic +86 -0
  199. package/test/logic/18-strftime-extended-formats.sqllogic +68 -0
  200. package/test/logic/20-empty-single-row.sqllogic +261 -0
  201. package/test/logic/21-null-edge-cases.sqllogic +227 -0
  202. package/test/logic/21.1-where-null-comparisons.sqllogic +151 -0
  203. package/test/logic/21.1.1-where-null-comparisons-secondary-index.sqllogic +35 -0
  204. package/test/logic/21.2-between-edges.sqllogic +157 -0
  205. package/test/logic/22-boundary-values.sqllogic +175 -0
  206. package/test/logic/23-self-joins-duplicates.sqllogic +74 -0
  207. package/test/logic/24-builtin-branches.sqllogic +611 -0
  208. package/test/logic/24.1-substr-extras.sqllogic +75 -0
  209. package/test/logic/24.2-random-extras.sqllogic +39 -0
  210. package/test/logic/25-aggregate-edge-cases.sqllogic +289 -0
  211. package/test/logic/25.1-nested-aggregates.sqllogic +74 -0
  212. package/test/logic/25.2-having-edge-cases.sqllogic +318 -0
  213. package/test/logic/25.3-aggregate-isnull-empty.sqllogic +16 -0
  214. package/test/logic/25.4-groupby-fd-constant-empty.sqllogic +55 -0
  215. package/test/logic/25.5-ungrouped-aggregate-column-free-select-item.sqllogic +196 -0
  216. package/test/logic/26-join-edge-cases.sqllogic +333 -0
  217. package/test/logic/26.1-left-join-isnull-on-notnull.sqllogic +26 -0
  218. package/test/logic/26.2-left-join-on-vs-where.sqllogic +67 -0
  219. package/test/logic/26.3-join-on-constants.sqllogic +61 -0
  220. package/test/logic/26.4-join-on-is-null-nullable.sqllogic +44 -0
  221. package/test/logic/27-window-edge-cases.sqllogic +206 -0
  222. package/test/logic/27.1-window-groups-frame.sqllogic +13 -0
  223. package/test/logic/27.2-window-exclude.sqllogic +13 -0
  224. package/test/logic/27.3-window-json-aggregation.sqllogic +66 -0
  225. package/test/logic/28-set-ops-sort-edge-cases.sqllogic +444 -0
  226. package/test/logic/28.1-compound-limit-offset.sqllogic +143 -0
  227. package/test/logic/28.2-orderby-expression-extras.sqllogic +698 -0
  228. package/test/logic/28.2-set-op-branch-types.sqllogic +217 -0
  229. package/test/logic/29-constraint-edge-cases.sqllogic +442 -0
  230. package/test/logic/29.1-column-level-conflict-clause.sqllogic +171 -0
  231. package/test/logic/29.2-table-level-pk-conflict-clause.sqllogic +113 -0
  232. package/test/logic/40-constraints.sqllogic +418 -0
  233. package/test/logic/40.1-pk-desc-direction.sqllogic +76 -0
  234. package/test/logic/40.2-check-extras.sqllogic +683 -0
  235. package/test/logic/41-alter-table.sqllogic +191 -0
  236. package/test/logic/41-fk-cascade-conflict-and-self-ref.sqllogic +263 -0
  237. package/test/logic/41-fk-cross-schema.sqllogic +155 -0
  238. package/test/logic/41-fk-extended-targets.sqllogic +173 -0
  239. package/test/logic/41-foreign-keys.sqllogic +1001 -0
  240. package/test/logic/41-generated-column-errors.sqllogic +225 -0
  241. package/test/logic/41-generated-column-extras.sqllogic +598 -0
  242. package/test/logic/41-generated-column-scope.sqllogic +329 -0
  243. package/test/logic/41-generated-columns.sqllogic +361 -0
  244. package/test/logic/41.1-alter-pk.sqllogic +230 -0
  245. package/test/logic/41.1-fk-collation-conflict.sqllogic +277 -0
  246. package/test/logic/41.10-alter-drop-column-foreign-key.sqllogic +274 -0
  247. package/test/logic/41.10.1-alter-drop-column-unique-index.sqllogic +169 -0
  248. package/test/logic/41.10.2-alter-drop-column-check-and-assertion.sqllogic +1616 -0
  249. package/test/logic/41.10.3-alter-drop-column-referencing-fk.sqllogic +292 -0
  250. package/test/logic/41.10.4-drop-object-expression-dependents.sqllogic +602 -0
  251. package/test/logic/41.11-deferred-fk-with-rename.sqllogic +232 -0
  252. package/test/logic/41.12-alter-default-coercion.sqllogic +200 -0
  253. package/test/logic/41.13-alter-add-column-generated-backfill.sqllogic +566 -0
  254. package/test/logic/41.14-alter-add-column-subquery-backfill.sqllogic +129 -0
  255. package/test/logic/41.15-alter-column-default-type-check.sqllogic +178 -0
  256. package/test/logic/41.16-fk-unenforceable.sqllogic +364 -0
  257. package/test/logic/41.2-alter-column.sqllogic +382 -0
  258. package/test/logic/41.2.1-alter-column-retype-deleted-row-memory.sqllogic +32 -0
  259. package/test/logic/41.2.2-alter-column-retype-index-rebuild.sqllogic +77 -0
  260. package/test/logic/41.2.3-alter-column-set-not-null-pk-backfill.sqllogic +310 -0
  261. package/test/logic/41.2.3.1-alter-column-set-not-null-pk-backfill-secondary-index.sqllogic +37 -0
  262. package/test/logic/41.3-alter-add-column-unique.sqllogic +184 -0
  263. package/test/logic/41.3-alter-rename-propagation.sqllogic +2352 -0
  264. package/test/logic/41.3.1-alter-rename-index-propagation.sqllogic +94 -0
  265. package/test/logic/41.4-alter-add-column-constraints.sqllogic +855 -0
  266. package/test/logic/41.5-alter-misc.sqllogic +48 -0
  267. package/test/logic/41.5-cross-schema-foreign-keys.sqllogic +253 -0
  268. package/test/logic/41.6-alter-drop-rename-constraint.sqllogic +354 -0
  269. package/test/logic/41.6.1-alter-drop-constraint-index-derived.sqllogic +22 -0
  270. package/test/logic/41.7-alter-column-collate.sqllogic +105 -0
  271. package/test/logic/41.7.1-alter-column-collate-unique.sqllogic +45 -0
  272. package/test/logic/41.7.2-alter-column-collate-unique-store.sqllogic +208 -0
  273. package/test/logic/41.7.2.1-alter-column-collate-unique-index-store.sqllogic +114 -0
  274. package/test/logic/41.7.3-alter-column-retype-unique.sqllogic +293 -0
  275. package/test/logic/41.7.3.1-alter-column-retype-staged-rows-memory.sqllogic +41 -0
  276. package/test/logic/41.7.3.2-alter-column-retype-unique-index.sqllogic +72 -0
  277. package/test/logic/41.7.4-alter-column-retype-semantic-memory.sqllogic +445 -0
  278. package/test/logic/41.7.4.1-alter-column-retype-semantic-index-memory.sqllogic +91 -0
  279. package/test/logic/41.7.5-alter-column-collate-pk-staged-delete-memory.sqllogic +106 -0
  280. package/test/logic/41.8-alter-add-constraint-unique-fk.sqllogic +275 -0
  281. package/test/logic/41.8-alter-savepoint-staged-rows.sqllogic +443 -0
  282. package/test/logic/41.8.1-alter-rename-savepoint-staged-rows.sqllogic +408 -0
  283. package/test/logic/41.9-alter-constraint-body-change.sqllogic +180 -0
  284. package/test/logic/41.9-fk-restrict-batched.sqllogic +290 -0
  285. package/test/logic/42-committed-snapshot.sqllogic +254 -0
  286. package/test/logic/42-returning.sqllogic +159 -0
  287. package/test/logic/42.1-returning-extras.sqllogic +232 -0
  288. package/test/logic/42.2-returning-stored-row.sqllogic +165 -0
  289. package/test/logic/43-default-nullability.sqllogic +131 -0
  290. package/test/logic/43-transition-constraints.sqllogic +341 -0
  291. package/test/logic/43.1-default-collation.sqllogic +140 -0
  292. package/test/logic/43.1-notnull-or-conflict.sqllogic +79 -0
  293. package/test/logic/43.2-deferred-check-new-on-delete.sqllogic +95 -0
  294. package/test/logic/43.3-nullable-primary-key.sqllogic +587 -0
  295. package/test/logic/44-determinism-validation.sqllogic +164 -0
  296. package/test/logic/44-orthogonality.sqllogic +146 -0
  297. package/test/logic/44.1-nondeterministic-schema.sqllogic +316 -0
  298. package/test/logic/45-udf-determinism.sqllogic +39 -0
  299. package/test/logic/46-mutation-context.sqllogic +595 -0
  300. package/test/logic/47-upsert.sqllogic +255 -0
  301. package/test/logic/47.1-upsert-conflict-targets.sqllogic +169 -0
  302. package/test/logic/47.2-replace-and-or-clauses.sqllogic +164 -0
  303. package/test/logic/47.2.1-pk-replace-secondary-unique.sqllogic +374 -0
  304. package/test/logic/47.3-engine-or-fail.sqllogic +122 -0
  305. package/test/logic/47.3-upsert-conflict-target-collation.sqllogic +139 -0
  306. package/test/logic/47.3.1-upsert-conflict-index-derived-collation.sqllogic +25 -0
  307. package/test/logic/47.4-upsert-conflict-target-affinity.sqllogic +59 -0
  308. package/test/logic/47.5-upsert-do-update-constraints.sqllogic +440 -0
  309. package/test/logic/47.6-upsert-do-update-decomposed.sqllogic +100 -0
  310. package/test/logic/49-reference-graph.sqllogic +84 -0
  311. package/test/logic/50-declarative-schema.sqllogic +2550 -0
  312. package/test/logic/50-metadata-tags.sqllogic +1033 -0
  313. package/test/logic/50.0.1-metadata-tags-index.sqllogic +141 -0
  314. package/test/logic/50.1-declare-schema-pk.sqllogic +150 -0
  315. package/test/logic/50.2-declare-schema-renames.sqllogic +949 -0
  316. package/test/logic/50.2.1-declare-schema-index-renames.sqllogic +210 -0
  317. package/test/logic/50.3-declare-schema-duplicate-names.sqllogic +280 -0
  318. package/test/logic/50.4-declare-schema-apply-restore.sqllogic +192 -0
  319. package/test/logic/51-lens-foundation.sqllogic +147 -0
  320. package/test/logic/51-materialized-views.sqllogic +376 -0
  321. package/test/logic/51.5-materialized-views-coarsened-key.sqllogic +198 -0
  322. package/test/logic/51.7-maintained-table-attach-detach.sqllogic +468 -0
  323. package/test/logic/51.8-maintained-table-declared-constraints.sqllogic +440 -0
  324. package/test/logic/51.85-maintained-table-parent-fk.sqllogic +103 -0
  325. package/test/logic/51.9-maintained-table-secondary-unique.sqllogic +237 -0
  326. package/test/logic/51.9.1-maintained-table-partial-unique.sqllogic +36 -0
  327. package/test/logic/52-lens-overrides.sqllogic +566 -0
  328. package/test/logic/53-materialized-views-rowtime.sqllogic +1601 -0
  329. package/test/logic/53-reserved-tags.sqllogic +252 -0
  330. package/test/logic/53.1-materialized-view-write-through.sqllogic +329 -0
  331. package/test/logic/53.2-materialized-view-rename-propagation.sqllogic +483 -0
  332. package/test/logic/53.3-materialized-view-constraint-only-ddl.sqllogic +409 -0
  333. package/test/logic/53.3.1-materialized-view-index-ddl-irrelevance.sqllogic +29 -0
  334. package/test/logic/53.4-materialized-view-structural-alter-restore.sqllogic +436 -0
  335. package/test/logic/54-covering-mv-enforcement.sqllogic +314 -0
  336. package/test/logic/54.1-covering-mv-partial-enforcement.sqllogic +34 -0
  337. package/test/logic/55-internal-eviction-reporting.sqllogic +89 -0
  338. package/test/logic/55-lens-prover.sqllogic +202 -0
  339. package/test/logic/55.1-eviction-restrict-fk.sqllogic +148 -0
  340. package/test/logic/55.5-lens-authored-inverse.sqllogic +1468 -0
  341. package/test/logic/80-grow-retrieve-pass.sqllogic +79 -0
  342. package/test/logic/81-quickpick.sqllogic +24 -0
  343. package/test/logic/82-bloom-join.sqllogic +185 -0
  344. package/test/logic/83-merge-join.sqllogic +280 -0
  345. package/test/logic/84-asof-scan.sqllogic +238 -0
  346. package/test/logic/84-key-cardinality.sqllogic +50 -0
  347. package/test/logic/85-relational-const-folding.sqllogic +51 -0
  348. package/test/logic/86-scalar-cse.sqllogic +42 -0
  349. package/test/logic/90-error_paths.sqllogic +114 -0
  350. package/test/logic/90.1-parse-errors.sqllogic +77 -0
  351. package/test/logic/90.2-alter-table-errors.sqllogic +53 -0
  352. package/test/logic/90.2.1-alter-extra-errors.sqllogic +51 -0
  353. package/test/logic/90.3-expression-errors.sqllogic +43 -0
  354. package/test/logic/90.4-dml-errors.sqllogic +47 -0
  355. package/test/logic/90.5-unsupported-join-types.sqllogic +37 -0
  356. package/test/logic/90.5.1-right-full-join-read.sqllogic +157 -0
  357. package/test/logic/90.6-select-error-paths.sqllogic +57 -0
  358. package/test/logic/91-merge-join-edge-cases.sqllogic +159 -0
  359. package/test/logic/92-hash-aggregate-edge-cases.sqllogic +139 -0
  360. package/test/logic/93-ddl-view-edge-cases.sqllogic +104 -0
  361. package/test/logic/93.1-view-error-paths.sqllogic +74 -0
  362. package/test/logic/93.2-view-mutation-pending.sqllogic +108 -0
  363. package/test/logic/93.3-view-mutation-or-clause.sqllogic +60 -0
  364. package/test/logic/93.4-view-mutation.sqllogic +4881 -0
  365. package/test/logic/93.4.1-view-mutation-partial-unique-cardinality.sqllogic +31 -0
  366. package/test/logic/93.5-authored-inverse.sqllogic +415 -0
  367. package/test/logic/93.6-set-op-flagless-write.sqllogic +862 -0
  368. package/test/logic/94-tvf-edge-cases.sqllogic +58 -0
  369. package/test/logic/94.1-limit-offset-edge-cases.sqllogic +109 -0
  370. package/test/logic/94.2-limit-offset-extras.sqllogic +98 -0
  371. package/test/logic/95-assertions.sqllogic +1417 -0
  372. package/test/logic/96-subquery-edge-cases.sqllogic +276 -0
  373. package/test/logic/97-json-function-edge-cases.sqllogic +633 -0
  374. package/test/logic/97.1-json-blob-and-special-values.sqllogic +92 -0
  375. package/test/logic/98-temporal-edge-cases.sqllogic +515 -0
  376. package/test/logic/99-conversion-edge-cases.sqllogic +325 -0
  377. package/test/logic/99.0.1-schema-index-listing.sqllogic +21 -0
  378. package/test/logic/99.1-cast-syntax-extras.sqllogic +167 -0
  379. package/test/logic/drop-unique-index.sqllogic +88 -0
  380. package/test/logic/pushdown-test.sqllogic +36 -0
@@ -0,0 +1,333 @@
1
+ -- join-edge-cases.sqllogic - Edge-case tests for join subsystem
2
+
3
+ -- ==================================
4
+ -- Setup
5
+ -- ==================================
6
+
7
+ create table je_a (id integer primary key, x integer, y integer, label text);
8
+ create table je_b (id integer primary key, x integer, y integer, tag text);
9
+
10
+ insert into je_a values (1, 10, 100, 'a1'), (2, 20, 200, 'a2'), (3, 30, 300, 'a3'), (4, 10, 400, 'a4');
11
+ insert into je_b values (1, 10, 100, 'b1'), (2, 20, 999, 'b2'), (3, 99, 100, 'b3'), (4, 10, 400, 'b4');
12
+
13
+ -- ==================================
14
+ -- 1. Complex residual predicates post-join
15
+ -- ==================================
16
+
17
+ -- ON with equality + inequality: only rows where x matches AND a.y < b.y
18
+ select a.id as aid, b.id as bid
19
+ from je_a a join je_b b on a.x = b.x and a.y < b.y
20
+ order by aid, bid;
21
+ → [{"aid":1,"bid":4},{"aid":2,"bid":2}]
22
+
23
+ -- ON equality + residual inequality the other direction
24
+ select a.id as aid, b.id as bid
25
+ from je_a a join je_b b on a.x = b.x and a.y > b.y
26
+ order by aid, bid;
27
+ → [{"aid":4,"bid":1}]
28
+
29
+ -- ON equality + non-trivial expression residual
30
+ select a.id as aid, b.id as bid
31
+ from je_a a join je_b b on a.x = b.x and (a.y + b.y) > 300
32
+ order by aid, bid;
33
+ → [{"aid":1,"bid":4},{"aid":2,"bid":2},{"aid":4,"bid":1},{"aid":4,"bid":4}]
34
+
35
+ -- LEFT JOIN with residual: unmatched rows should still appear with nulls
36
+ select a.id as aid, a.label, b.id as bid, b.tag
37
+ from je_a a left join je_b b on a.x = b.x and a.y = b.y
38
+ order by aid;
39
+ → [{"aid":1,"label":"a1","bid":1,"tag":"b1"},{"aid":2,"label":"a2","bid":null,"tag":null},{"aid":3,"label":"a3","bid":null,"tag":null},{"aid":4,"label":"a4","bid":4,"tag":"b4"}]
40
+
41
+ -- ==================================
42
+ -- 2. Cross joins with filter expressions
43
+ -- ==================================
44
+
45
+ create table je_cx (id integer primary key, v integer);
46
+ create table je_cy (id integer primary key, v integer);
47
+ insert into je_cx values (1, 3), (2, 7), (3, 5);
48
+ insert into je_cy values (1, 4), (2, 6);
49
+
50
+ -- Cross join with arithmetic filter
51
+ select cx.id as cxid, cy.id as cyid, cx.v + cy.v as total
52
+ from je_cx cx cross join je_cy cy
53
+ where cx.v + cy.v > 10
54
+ order by cxid, cyid;
55
+ → [{"cxid":2,"cyid":1,"total":11},{"cxid":2,"cyid":2,"total":13},{"cxid":3,"cyid":2,"total":11}]
56
+
57
+ -- Cross join producing full cartesian (no filter)
58
+ select count(*) as cnt from je_cx cross join je_cy;
59
+ → [{"cnt":6}]
60
+
61
+ -- Cross join with filter eliminating all rows
62
+ select cx.id as cxid, cy.id as cyid
63
+ from je_cx cx cross join je_cy cy
64
+ where cx.v + cy.v > 100;
65
+ → []
66
+
67
+ drop table je_cx;
68
+ drop table je_cy;
69
+
70
+ -- ==================================
71
+ -- 3. Join with all-NULL columns on both sides
72
+ -- ==================================
73
+
74
+ create table je_nl (id integer primary key, k integer null, val text);
75
+ create table je_nr (id integer primary key, k integer null, val text);
76
+
77
+ insert into je_nl values (1, null, 'L1'), (2, null, 'L2');
78
+ insert into je_nr values (1, null, 'R1'), (2, null, 'R2'), (3, null, 'R3');
79
+
80
+ -- Inner join on all-NULL keys: zero rows (NULL != NULL)
81
+ select nl.id as lid, nr.id as rid
82
+ from je_nl nl join je_nr nr on nl.k = nr.k;
83
+ → []
84
+
85
+ -- Left join on all-NULL keys: all left rows, right side null-padded
86
+ select nl.id as lid, nl.val as lval, nr.id as rid, nr.val as rval
87
+ from je_nl nl left join je_nr nr on nl.k = nr.k
88
+ order by lid;
89
+ → [{"lid":1,"lval":"L1","rid":null,"rval":null},{"lid":2,"lval":"L2","rid":null,"rval":null}]
90
+
91
+ -- Mixed: some non-null keys on left, all-null on right
92
+ insert into je_nl values (3, 5, 'L3');
93
+ insert into je_nr values (4, 5, 'R4');
94
+
95
+ select nl.id as lid, nr.id as rid
96
+ from je_nl nl join je_nr nr on nl.k = nr.k
97
+ order by lid;
98
+ → [{"lid":3,"rid":4}]
99
+
100
+ -- Left join: null-key rows unmatched, non-null key matched
101
+ select nl.id as lid, nr.id as rid
102
+ from je_nl nl left join je_nr nr on nl.k = nr.k
103
+ order by lid;
104
+ → [{"lid":1,"rid":null},{"lid":2,"rid":null},{"lid":3,"rid":4}]
105
+
106
+ drop table je_nl;
107
+ drop table je_nr;
108
+
109
+ -- ==================================
110
+ -- 4. Multi-condition join keys with partial NULLs
111
+ -- ==================================
112
+
113
+ create table je_mc1 (id integer primary key, a integer null, b integer null, v text);
114
+ create table je_mc2 (id integer primary key, a integer null, b integer null, w text);
115
+
116
+ insert into je_mc1 values (1, 1, 10, 'm1'), (2, 2, null, 'm2'), (3, null, 30, 'm3'), (4, null, null, 'm4'), (5, 1, 10, 'm5');
117
+ insert into je_mc2 values (1, 1, 10, 'n1'), (2, 2, null, 'n2'), (3, null, 30, 'n3'), (4, 1, 10, 'n4');
118
+
119
+ -- Multi-key inner join: only rows where BOTH keys match (non-null)
120
+ select mc1.id as m1id, mc2.id as m2id
121
+ from je_mc1 mc1 join je_mc2 mc2 on mc1.a = mc2.a and mc1.b = mc2.b
122
+ order by m1id, m2id;
123
+ → [{"m1id":1,"m2id":1},{"m1id":1,"m2id":4},{"m1id":5,"m2id":1},{"m1id":5,"m2id":4}]
124
+
125
+ -- Partial NULL match (a=2, b=NULL): should NOT match (NULL != NULL)
126
+ select mc1.id as m1id, mc2.id as m2id
127
+ from je_mc1 mc1 join je_mc2 mc2 on mc1.a = mc2.a and mc1.b = mc2.b
128
+ where mc1.id = 2;
129
+ → []
130
+
131
+ -- Left join with multi-key: null-key rows get padding
132
+ select mc1.id as m1id, mc1.v, mc2.id as m2id, mc2.w
133
+ from je_mc1 mc1 left join je_mc2 mc2 on mc1.a = mc2.a and mc1.b = mc2.b
134
+ order by m1id, m2id;
135
+ → [{"m1id":1,"v":"m1","m2id":1,"w":"n1"},{"m1id":1,"v":"m1","m2id":4,"w":"n4"},{"m1id":2,"v":"m2","m2id":null,"w":null},{"m1id":3,"v":"m3","m2id":null,"w":null},{"m1id":4,"v":"m4","m2id":null,"w":null},{"m1id":5,"v":"m5","m2id":1,"w":"n1"},{"m1id":5,"v":"m5","m2id":4,"w":"n4"}]
136
+
137
+ drop table je_mc1;
138
+ drop table je_mc2;
139
+
140
+ -- ==================================
141
+ -- 5. Self-join with duplicate keys (combinatorial explosion)
142
+ -- ==================================
143
+
144
+ create table je_dup (id integer primary key, grp integer);
145
+ insert into je_dup values (1, 1), (2, 1), (3, 1), (4, 2), (5, 2);
146
+
147
+ -- Self-join on grp: group 1 has 3 rows → 3*3=9 pairs; group 2 has 2 rows → 2*2=4 pairs; total=13
148
+ select count(*) as cnt from je_dup a join je_dup b on a.grp = b.grp;
149
+ → [{"cnt":13}]
150
+
151
+ -- Verify actual pairs for group 1 (3x3)
152
+ select a.id as aid, b.id as bid
153
+ from je_dup a join je_dup b on a.grp = b.grp
154
+ where a.grp = 1
155
+ order by aid, bid;
156
+ → [{"aid":1,"bid":1},{"aid":1,"bid":2},{"aid":1,"bid":3},{"aid":2,"bid":1},{"aid":2,"bid":2},{"aid":2,"bid":3},{"aid":3,"bid":1},{"aid":3,"bid":2},{"aid":3,"bid":3}]
157
+
158
+ -- Self-join excluding self-matches (a.id != b.id)
159
+ select count(*) as cnt from je_dup a join je_dup b on a.grp = b.grp and a.id != b.id;
160
+ → [{"cnt":8}]
161
+
162
+ -- Self-join with inequality: only a.id < b.id (unique pairs)
163
+ select a.id as aid, b.id as bid
164
+ from je_dup a join je_dup b on a.grp = b.grp and a.id < b.id
165
+ order by aid, bid;
166
+ → [{"aid":1,"bid":2},{"aid":1,"bid":3},{"aid":2,"bid":3},{"aid":4,"bid":5}]
167
+
168
+ drop table je_dup;
169
+
170
+ -- ==================================
171
+ -- 6. Semi/anti join with empty subquery table
172
+ -- ==================================
173
+
174
+ create table je_main (id integer primary key, val text);
175
+ create table je_empty (id integer primary key, ref_id integer);
176
+
177
+ insert into je_main values (1, 'one'), (2, 'two'), (3, 'three');
178
+ -- je_empty has no rows
179
+
180
+ -- EXISTS on empty table: eliminates all rows
181
+ select id, val from je_main where exists (select 1 from je_empty where je_empty.ref_id = je_main.id);
182
+ → []
183
+
184
+ -- NOT EXISTS on empty table: keeps all rows
185
+ select id, val from je_main where not exists (select 1 from je_empty where je_empty.ref_id = je_main.id) order by id;
186
+ → [{"id":1,"val":"one"},{"id":2,"val":"two"},{"id":3,"val":"three"}]
187
+
188
+ -- IN with empty subquery: no matches
189
+ select id, val from je_main where id in (select ref_id from je_empty);
190
+ → []
191
+
192
+ -- NOT IN with empty subquery: all rows returned
193
+ select id, val from je_main where id not in (select ref_id from je_empty) order by id;
194
+ → [{"id":1,"val":"one"},{"id":2,"val":"two"},{"id":3,"val":"three"}]
195
+
196
+ -- Uncorrelated EXISTS on empty: eliminates all
197
+ select id, val from je_main where exists (select 1 from je_empty);
198
+ → []
199
+
200
+ -- Uncorrelated NOT EXISTS on empty: keeps all
201
+ select id, val from je_main where not exists (select 1 from je_empty) order by id;
202
+ → [{"id":1,"val":"one"},{"id":2,"val":"two"},{"id":3,"val":"three"}]
203
+
204
+ drop table je_main;
205
+ drop table je_empty;
206
+
207
+ -- ==================================
208
+ -- 7. Join reordering correctness (three-way join)
209
+ -- ==================================
210
+
211
+ create table je_t1 (id integer primary key, val integer);
212
+ create table je_t2 (id integer primary key, t1_id integer, val integer);
213
+ create table je_t3 (id integer primary key, t2_id integer, val integer);
214
+
215
+ insert into je_t1 values (1, 10), (2, 20), (3, 30);
216
+ insert into je_t2 values (10, 1, 100), (20, 2, 200), (30, 3, 300), (40, 1, 400);
217
+ insert into je_t3 values (100, 10, 1000), (200, 20, 2000), (300, 40, 3000);
218
+
219
+ -- Three-way join: t1 → t2 → t3
220
+ select t1.id as t1id, t2.id as t2id, t3.id as t3id
221
+ from je_t1 t1
222
+ join je_t2 t2 on t2.t1_id = t1.id
223
+ join je_t3 t3 on t3.t2_id = t2.id
224
+ order by t1id, t2id, t3id;
225
+ → [{"t1id":1,"t2id":10,"t3id":100},{"t1id":1,"t2id":40,"t3id":300},{"t1id":2,"t2id":20,"t3id":200}]
226
+
227
+ -- Same join with different FROM order: t3 → t2 → t1 (should produce same results)
228
+ select t1.id as t1id, t2.id as t2id, t3.id as t3id
229
+ from je_t3 t3
230
+ join je_t2 t2 on t3.t2_id = t2.id
231
+ join je_t1 t1 on t2.t1_id = t1.id
232
+ order by t1id, t2id, t3id;
233
+ → [{"t1id":1,"t2id":10,"t3id":100},{"t1id":1,"t2id":40,"t3id":300},{"t1id":2,"t2id":20,"t3id":200}]
234
+
235
+ -- Mixed order: t2 → t1 → t3
236
+ select t1.id as t1id, t2.id as t2id, t3.id as t3id
237
+ from je_t2 t2
238
+ join je_t1 t1 on t2.t1_id = t1.id
239
+ join je_t3 t3 on t3.t2_id = t2.id
240
+ order by t1id, t2id, t3id;
241
+ → [{"t1id":1,"t2id":10,"t3id":100},{"t1id":1,"t2id":40,"t3id":300},{"t1id":2,"t2id":20,"t3id":200}]
242
+
243
+ -- Three-way with predicate that could be misattributed
244
+ select t1.id as t1id, t2.id as t2id, t3.id as t3id
245
+ from je_t1 t1
246
+ join je_t2 t2 on t2.t1_id = t1.id
247
+ join je_t3 t3 on t3.t2_id = t2.id
248
+ where t1.val > 10 and t3.val < 3000
249
+ order by t1id, t2id, t3id;
250
+ → [{"t1id":2,"t2id":20,"t3id":200}]
251
+
252
+ -- Three-way LEFT JOIN: unmatched rows preserved
253
+ select t1.id as t1id, t2.id as t2id, t3.id as t3id
254
+ from je_t1 t1
255
+ left join je_t2 t2 on t2.t1_id = t1.id
256
+ left join je_t3 t3 on t3.t2_id = t2.id
257
+ order by t1id, t2id, t3id;
258
+ → [{"t1id":1,"t2id":10,"t3id":100},{"t1id":1,"t2id":40,"t3id":300},{"t1id":2,"t2id":20,"t3id":200},{"t1id":3,"t2id":30,"t3id":null}]
259
+
260
+ drop table je_t1;
261
+ drop table je_t2;
262
+ drop table je_t3;
263
+
264
+ -- ==================================
265
+ -- 8. Outer join + aggregate interaction
266
+ -- ==================================
267
+
268
+ create table je_orders (id integer primary key, customer text);
269
+ create table je_items (id integer primary key, order_id integer, amount integer);
270
+
271
+ insert into je_orders values (1, 'Alice'), (2, 'Bob'), (3, 'Carol');
272
+ insert into je_items values (10, 1, 50), (20, 1, 30), (30, 2, 100);
273
+ -- Carol (order 3) has no items
274
+
275
+ -- count(items.col) should NOT count null-padded rows
276
+ select o.customer, count(i.id) as item_count
277
+ from je_orders o left join je_items i on i.order_id = o.id
278
+ group by o.customer
279
+ order by o.customer;
280
+ → [{"customer":"Alice","item_count":2},{"customer":"Bob","item_count":1},{"customer":"Carol","item_count":0}]
281
+
282
+ -- count(*) SHOULD count null-padded rows (one row per unmatched left)
283
+ select o.customer, count(*) as row_count
284
+ from je_orders o left join je_items i on i.order_id = o.id
285
+ group by o.customer
286
+ order by o.customer;
287
+ → [{"customer":"Alice","row_count":2},{"customer":"Bob","row_count":1},{"customer":"Carol","row_count":1}]
288
+
289
+ -- sum on nullable side: NULL for unmatched groups
290
+ select o.customer, sum(i.amount) as total
291
+ from je_orders o left join je_items i on i.order_id = o.id
292
+ group by o.customer
293
+ order by o.customer;
294
+ → [{"customer":"Alice","total":80},{"customer":"Bob","total":100},{"customer":"Carol","total":null}]
295
+
296
+ -- coalesce to handle null aggregate
297
+ select o.customer, coalesce(sum(i.amount), 0) as total
298
+ from je_orders o left join je_items i on i.order_id = o.id
299
+ group by o.customer
300
+ order by o.customer;
301
+ → [{"customer":"Alice","total":80},{"customer":"Bob","total":100},{"customer":"Carol","total":0}]
302
+
303
+ -- avg on nullable side: null for empty group
304
+ select o.customer, avg(i.amount) as avg_amount
305
+ from je_orders o left join je_items i on i.order_id = o.id
306
+ group by o.customer
307
+ order by o.customer;
308
+ → [{"customer":"Alice","avg_amount":40},{"customer":"Bob","avg_amount":100},{"customer":"Carol","avg_amount":null}]
309
+
310
+ -- max/min on nullable side
311
+ select o.customer, max(i.amount) as mx, min(i.amount) as mn
312
+ from je_orders o left join je_items i on i.order_id = o.id
313
+ group by o.customer
314
+ order by o.customer;
315
+ → [{"customer":"Alice","mx":50,"mn":30},{"customer":"Bob","mx":100,"mn":100},{"customer":"Carol","mx":null,"mn":null}]
316
+
317
+ -- HAVING with outer join aggregate: filter out groups with zero items
318
+ select o.customer, count(i.id) as item_count
319
+ from je_orders o left join je_items i on i.order_id = o.id
320
+ group by o.customer
321
+ having count(i.id) > 0
322
+ order by o.customer;
323
+ → [{"customer":"Alice","item_count":2},{"customer":"Bob","item_count":1}]
324
+
325
+ drop table je_orders;
326
+ drop table je_items;
327
+
328
+ -- ==================================
329
+ -- Cleanup
330
+ -- ==================================
331
+
332
+ drop table je_a;
333
+ drop table je_b;
@@ -0,0 +1,26 @@
1
+ -- adapted from SQLite test/notnull2.test
2
+ -- LEFT JOIN with IS NULL predicates over NOT NULL columns.
3
+ -- Most of notnull2.test asserts planner step-counts (internal); the
4
+ -- observable subset is LEFT JOIN behavior — captured here.
5
+
6
+ create table lj_t1 (a integer primary key, b text);
7
+ create table lj_t2 (c integer not null, d integer not null);
8
+
9
+ insert into lj_t1 values (1, 'x'), (2, 'y'), (3, 'z');
10
+ insert into lj_t2 values (1, 10), (2, 20);
11
+
12
+ -- d is NOT NULL; predicate `d is null` filters to no rows
13
+ select count(*) as cnt from lj_t1 left join lj_t2 on a = c where d is null;
14
+ → [{"cnt":1}]
15
+
16
+ -- ON IS NULL against NOT NULL left-side column never matches → all left rows
17
+ -- get NULL right-side
18
+ select a, c, d from lj_t1 left join lj_t2 on a is null order by a;
19
+ → [{"a":1,"c":null,"d":null},{"a":2,"c":null,"d":null},{"a":3,"c":null,"d":null}]
20
+
21
+ -- LEFT JOIN on derived NOT-NULL constant column; IS NULL never matches
22
+ select t.c, d from (select 3 as c) t left join lj_t2 on t.c is null;
23
+ → [{"c":3,"d":null}]
24
+
25
+ drop table lj_t2;
26
+ drop table lj_t1;
@@ -0,0 +1,67 @@
1
+ -- adapted from SQLite test/join4.test, join5.test
2
+ -- Distinction between ON-clause and WHERE-clause filtering on LEFT JOIN.
3
+ -- ON-clause restricts which right rows match (left rows always preserved);
4
+ -- WHERE-clause runs after the join and filters out NULL-padded rows.
5
+
6
+ create table ow_l (id integer primary key, grp integer);
7
+ create table ow_r (id integer primary key, l_id integer, val text);
8
+
9
+ insert into ow_l values (1, 10), (2, 20), (3, 30);
10
+ insert into ow_r values (100, 1, 'r1'), (101, 2, 'r2');
11
+ -- run
12
+
13
+ -- ON-clause filter: left rows preserved, right side is NULL when filter excludes them
14
+ select ow_l.id as lid, ow_r.id as rid from ow_l left join ow_r on ow_l.id = ow_r.l_id and ow_r.val = 'r1' order by lid;
15
+ → [{"lid":1,"rid":100},{"lid":2,"rid":null},{"lid":3,"rid":null}]
16
+
17
+ -- WHERE-clause filter: NULL-padded rows where val is null are removed
18
+ select ow_l.id as lid, ow_r.id as rid from ow_l left join ow_r on ow_l.id = ow_r.l_id where ow_r.val = 'r1' order by lid;
19
+ → [{"lid":1,"rid":100}]
20
+
21
+ -- ON-clause inequality: still preserves left rows
22
+ select ow_l.id as lid, ow_r.id as rid from ow_l left join ow_r on ow_l.id = ow_r.l_id and ow_r.id > 100 order by lid;
23
+ → [{"lid":1,"rid":null},{"lid":2,"rid":101},{"lid":3,"rid":null}]
24
+
25
+ -- WHERE IS NULL on right side: keeps only unmatched left rows (anti-join idiom)
26
+ select ow_l.id as lid from ow_l left join ow_r on ow_l.id = ow_r.l_id where ow_r.id is null order by lid;
27
+ → [{"lid":3}]
28
+
29
+ -- WHERE IS NOT NULL on right side: keeps only matched rows (essentially inner join)
30
+ select ow_l.id as lid, ow_r.id as rid from ow_l left join ow_r on ow_l.id = ow_r.l_id where ow_r.id is not null order by lid;
31
+ → [{"lid":1,"rid":100},{"lid":2,"rid":101}]
32
+
33
+ -- ON-clause filter combined with WHERE on left-side column
34
+ select ow_l.id as lid, ow_r.id as rid from ow_l left join ow_r on ow_l.id = ow_r.l_id and ow_r.val = 'r1' where ow_l.grp >= 20 order by lid;
35
+ → [{"lid":2,"rid":null},{"lid":3,"rid":null}]
36
+
37
+ -- HAVING on count post-LEFT JOIN: zero-count groups excluded.
38
+ -- SELECT-list aliases survive on grouped column references too.
39
+ select ow_l.id as lid, count(ow_r.id) as cnt from ow_l left join ow_r on ow_l.id = ow_r.l_id group by ow_l.id having count(ow_r.id) > 0 order by ow_l.id;
40
+ → [{"lid":1,"cnt":1},{"lid":2,"cnt":1}]
41
+
42
+ -- Pushdown asymmetry (rule-join-predicate-pushdown), pinned end-to-end.
43
+ -- A WHERE on the PRESERVED side may be evaluated before the join: an ow_l row it
44
+ -- rejects would have produced only rows the WHERE rejects anyway.
45
+ select ow_l.id as lid, ow_r.id as rid from ow_l left join ow_r on ow_l.id = ow_r.l_id where ow_l.grp >= 20 order by lid;
46
+ → [{"lid":2,"rid":101},{"lid":3,"rid":null}]
47
+
48
+ -- A WHERE on the NULL-EXTENDED side may NOT: evaluating `ow_r.val = 'r1'` before the
49
+ -- join turns it into the ON-clause case above, which KEEPS lid 2 and 3 NULL-padded.
50
+ select ow_l.id as lid, ow_r.id as rid from ow_l left join ow_r on ow_l.id = ow_r.l_id where ow_r.val = 'r1' order by lid;
51
+ → [{"lid":1,"rid":100}]
52
+
53
+ -- Both at once: the preserved-side conjunct is pushable, the null-extended one is not,
54
+ -- and the pair must still compose to the post-join semantics.
55
+ select ow_l.id as lid, ow_r.id as rid from ow_l left join ow_r on ow_l.id = ow_r.l_id where ow_l.grp >= 20 and ow_r.val = 'r2' order by lid;
56
+ → [{"lid":2,"rid":101}]
57
+
58
+ -- Mirror on a RIGHT join: ow_l is the null-extended side there, so its WHERE stays above
59
+ -- while the preserved (ow_r) side's is pushable.
60
+ select ow_l.id as lid, ow_r.id as rid from ow_l right join ow_r on ow_l.id = ow_r.l_id where ow_l.grp = 10 order by rid;
61
+ → [{"lid":1,"rid":100}]
62
+
63
+ select ow_l.id as lid, ow_r.id as rid from ow_l right join ow_r on ow_l.id = ow_r.l_id where ow_r.val = 'r2' order by rid;
64
+ → [{"lid":2,"rid":101}]
65
+
66
+ drop table ow_l;
67
+ drop table ow_r;
@@ -0,0 +1,61 @@
1
+ -- adapted from SQLite test/join5.test, joinF.test
2
+ -- Constant predicates in ON clause: 1, 0, NULL, true, false in INNER and LEFT JOINs.
3
+
4
+ create table cc_l (id integer primary key, val text);
5
+ create table cc_r (id integer primary key, ref integer, val text);
6
+
7
+ insert into cc_l values (1, 'a'), (2, 'b'), (3, 'c');
8
+ insert into cc_r values (10, 1, 'r1'), (20, 1, 'r2'), (30, 3, 'r3');
9
+
10
+ -- INNER JOIN ON 1 (always true) is a cartesian product
11
+ select count(*) as cnt from cc_l join cc_r on 1;
12
+ → [{"cnt":9}]
13
+
14
+ -- INNER JOIN ON 0 (always false) yields no rows
15
+ select count(*) as cnt from cc_l join cc_r on 0;
16
+ → [{"cnt":0}]
17
+
18
+ -- INNER JOIN ON NULL (unknown -> false) yields no rows
19
+ select count(*) as cnt from cc_l join cc_r on null;
20
+ → [{"cnt":0}]
21
+
22
+ -- LEFT JOIN ON 1 = full cartesian, all left rows match
23
+ select cc_l.id as lid, cc_r.id as rid
24
+ from cc_l left join cc_r on 1
25
+ order by lid, rid;
26
+ → [{"lid":1,"rid":10},{"lid":1,"rid":20},{"lid":1,"rid":30},{"lid":2,"rid":10},{"lid":2,"rid":20},{"lid":2,"rid":30},{"lid":3,"rid":10},{"lid":3,"rid":20},{"lid":3,"rid":30}]
27
+
28
+ -- LEFT JOIN ON 0 = no right matches, all left rows preserved with NULL
29
+ select cc_l.id as lid, cc_r.id as rid
30
+ from cc_l left join cc_r on 0
31
+ order by lid;
32
+ → [{"lid":1,"rid":null},{"lid":2,"rid":null},{"lid":3,"rid":null}]
33
+
34
+ -- LEFT JOIN ON NULL = same as ON 0 (unknown is not a match)
35
+ select cc_l.id as lid, cc_r.id as rid
36
+ from cc_l left join cc_r on null
37
+ order by lid;
38
+ → [{"lid":1,"rid":null},{"lid":2,"rid":null},{"lid":3,"rid":null}]
39
+
40
+ -- LEFT JOIN ON true (literal) behaves like ON 1
41
+ select count(*) as cnt from cc_l left join cc_r on true;
42
+ → [{"cnt":9}]
43
+
44
+ -- LEFT JOIN ON false (literal) behaves like ON 0
45
+ select count(*) as cnt from cc_l left join cc_r on false;
46
+ → [{"cnt":3}]
47
+
48
+ -- Three-way LEFT JOIN with constant ON in the middle
49
+ create table cc_t3 (id integer primary key, w integer);
50
+ insert into cc_t3 values (1000, 1);
51
+
52
+ select cc_l.id as lid, cc_r.id as rid, cc_t3.id as tid
53
+ from cc_l
54
+ left join cc_r on cc_l.id = cc_r.ref
55
+ left join cc_t3 on 1
56
+ order by lid, rid, tid;
57
+ → [{"lid":1,"rid":10,"tid":1000},{"lid":1,"rid":20,"tid":1000},{"lid":2,"rid":null,"tid":1000},{"lid":3,"rid":30,"tid":1000}]
58
+
59
+ drop table cc_l;
60
+ drop table cc_r;
61
+ drop table cc_t3;
@@ -0,0 +1,44 @@
1
+ -- adapted from SQLite test/joinE.test
2
+ -- ON IS NULL / IS NOT NULL on nullable columns in INNER and LEFT joins.
3
+ -- Companion to 26.1-left-join-isnull-on-notnull.sqllogic which covers the
4
+ -- NOT-NULL-column case.
5
+
6
+ create table jn_a (id integer primary key, k integer null, v text);
7
+ create table jn_b (id integer primary key, k integer null, v text);
8
+
9
+ insert into jn_a values (1, 10, 'a1'), (2, null, 'a2'), (3, null, 'a3');
10
+ insert into jn_b values (10, 10, 'b1'), (20, null, 'b2'), (30, null, 'b3'), (40, 99, 'b4');
11
+
12
+ -- INNER JOIN ON a.k IS NULL: matches only left rows whose key is null,
13
+ -- crossed with every right row (the predicate is independent of right side)
14
+ select jn_a.id as aid, jn_b.id as bid
15
+ from jn_a join jn_b on jn_a.k is null
16
+ order by aid, bid;
17
+ → [{"aid":2,"bid":10},{"aid":2,"bid":20},{"aid":2,"bid":30},{"aid":2,"bid":40},{"aid":3,"bid":10},{"aid":3,"bid":20},{"aid":3,"bid":30},{"aid":3,"bid":40}]
18
+
19
+ -- INNER JOIN ON a.k IS NULL AND b.k IS NULL: only null-key rows from both sides
20
+ select jn_a.id as aid, jn_b.id as bid
21
+ from jn_a join jn_b on jn_a.k is null and jn_b.k is null
22
+ order by aid, bid;
23
+ → [{"aid":2,"bid":20},{"aid":2,"bid":30},{"aid":3,"bid":20},{"aid":3,"bid":30}]
24
+
25
+ -- LEFT JOIN ON a.k IS NULL: non-null-keyed left rows get padded
26
+ select jn_a.id as aid, jn_b.id as bid
27
+ from jn_a left join jn_b on jn_a.k is null and jn_b.k = 10
28
+ order by aid, bid;
29
+ → [{"aid":1,"bid":null},{"aid":2,"bid":10},{"aid":3,"bid":10}]
30
+
31
+ -- INNER JOIN ON regular equality with explicit IS NULL fallback
32
+ select jn_a.id as aid, jn_b.id as bid
33
+ from jn_a join jn_b on jn_a.k = jn_b.k or (jn_a.k is null and jn_b.k is null)
34
+ order by aid, bid;
35
+ → [{"aid":1,"bid":10},{"aid":2,"bid":20},{"aid":2,"bid":30},{"aid":3,"bid":20},{"aid":3,"bid":30}]
36
+
37
+ -- LEFT JOIN ON IS NOT NULL on right key
38
+ select jn_a.id as aid, jn_b.id as bid
39
+ from jn_a left join jn_b on jn_a.id = jn_b.id - 9 and jn_b.k is not null
40
+ order by aid, bid;
41
+ → [{"aid":1,"bid":10},{"aid":2,"bid":null},{"aid":3,"bid":null}]
42
+
43
+ drop table jn_a;
44
+ drop table jn_b;