@quereus/quereus 4.20.1 → 4.20.2

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 (377) hide show
  1. package/README.md +2 -0
  2. package/package.json +7 -4
  3. package/test/README.md +173 -0
  4. package/test/logic/01-basic.sqllogic +39 -0
  5. package/test/logic/01.1-select-projection-extras.sqllogic +130 -0
  6. package/test/logic/01.2-strings.sqllogic +43 -0
  7. package/test/logic/01.5-insert-select.sqllogic +237 -0
  8. package/test/logic/01.6-update-extras.sqllogic +118 -0
  9. package/test/logic/01.7-update-from.sqllogic +67 -0
  10. package/test/logic/01.8-delete-extras.sqllogic +122 -0
  11. package/test/logic/01.8.1-delete-range-cow.sqllogic +115 -0
  12. package/test/logic/01.9-query-expr-dml-gates.sqllogic +32 -0
  13. package/test/logic/01.9-query-expr-dml.sqllogic +171 -0
  14. package/test/logic/01.9-query-expr-values.sqllogic +111 -0
  15. package/test/logic/01.9.1-limit-over-dml-subquery.sqllogic +119 -0
  16. package/test/logic/02-filters.sqllogic +54 -0
  17. package/test/logic/02-smoke.sqllogic +62 -0
  18. package/test/logic/02.1-bind-parameters.sqllogic +223 -0
  19. package/test/logic/03-expressions.sqllogic +190 -0
  20. package/test/logic/03.1-quoted-identifiers.sqllogic +55 -0
  21. package/test/logic/03.4-defaults.sqllogic +554 -0
  22. package/test/logic/03.4.1-default-edge-cases.sqllogic +99 -0
  23. package/test/logic/03.5-tvf.sqllogic +61 -0
  24. package/test/logic/03.6-type-system.sqllogic +544 -0
  25. package/test/logic/03.6.1-numeric-text-comparison-coercion.sqllogic +244 -0
  26. package/test/logic/03.6.2-value-to-text.sqllogic +224 -0
  27. package/test/logic/03.7-bigint-mixed-arithmetic.sqllogic +65 -0
  28. package/test/logic/03.8-not-precedence.sqllogic +255 -0
  29. package/test/logic/03.9-is-bool-predicate.sqllogic +150 -0
  30. package/test/logic/03.9.1-is-bool-predicate-partial-index.sqllogic +34 -0
  31. package/test/logic/04-order-by.sqllogic +38 -0
  32. package/test/logic/04-transactions.sqllogic +239 -0
  33. package/test/logic/04a-savepoint-lazy-attach.sqllogic +122 -0
  34. package/test/logic/05-vtab_memory.sqllogic +50 -0
  35. package/test/logic/05.0.1-vtab-memory-unique-index-collation.sqllogic +34 -0
  36. package/test/logic/05.1-composite-pk-range-scan.sqllogic +147 -0
  37. package/test/logic/05.1.1-secondary-index-range-scan.sqllogic +56 -0
  38. package/test/logic/05.2-cast-seek-correctness.sqllogic +124 -0
  39. package/test/logic/06-builtin_functions.sqllogic +149 -0
  40. package/test/logic/06.1-string-functions.sqllogic +92 -0
  41. package/test/logic/06.1.3-like-glob-edges.sqllogic +53 -0
  42. package/test/logic/06.2-math-functions.sqllogic +82 -0
  43. package/test/logic/06.3-schema.sqllogic +48 -0
  44. package/test/logic/06.3.1-schema-all-schemas.sqllogic +39 -0
  45. package/test/logic/06.3.2-schema-foreign-keys.sqllogic +208 -0
  46. package/test/logic/06.3.3-introspection-tags.sqllogic +202 -0
  47. package/test/logic/06.3.3.1-introspection-tags-index.sqllogic +74 -0
  48. package/test/logic/06.3.4-view-info.sqllogic +378 -0
  49. package/test/logic/06.3.5-column-info.sqllogic +347 -0
  50. package/test/logic/06.3.6-schema-views.sqllogic +29 -0
  51. package/test/logic/06.4-schema-search-path.sqllogic +354 -0
  52. package/test/logic/06.4.1-schema-case-insensitive.sqllogic +83 -0
  53. package/test/logic/06.4.2-collation-extras.sqllogic +472 -0
  54. package/test/logic/06.4.2.1-collation-index-access-paths.sqllogic +140 -0
  55. package/test/logic/06.4.3-write-path-collation.sqllogic +99 -0
  56. package/test/logic/06.4.4-comparison-collation-precedence.sqllogic +342 -0
  57. package/test/logic/06.4.5-any-collate-declared-keys.sqllogic +92 -0
  58. package/test/logic/06.5-polymorphic-types.sqllogic +169 -0
  59. package/test/logic/06.5.1-conversion-functions.sqllogic +173 -0
  60. package/test/logic/06.5.2-scalar-minmax.sqllogic +16 -0
  61. package/test/logic/06.5.3-undeclared-return-type-comparison.sqllogic +244 -0
  62. package/test/logic/06.5.4-declared-return-type-builtins.sqllogic +288 -0
  63. package/test/logic/06.6-aggregate-extended.sqllogic +78 -0
  64. package/test/logic/06.7-json-extended.sqllogic +53 -0
  65. package/test/logic/06.8-json-path-operators.sqllogic +99 -0
  66. package/test/logic/06.9-json-canonical-key.sqllogic +65 -0
  67. package/test/logic/06.9.1-json-coerce-once.sqllogic +417 -0
  68. package/test/logic/06.9.1.1-json-coerce-once-index.sqllogic +39 -0
  69. package/test/logic/06.9.2-json-structural-equality.sqllogic +382 -0
  70. package/test/logic/06.9.2.1-json-structural-equality-index.sqllogic +76 -0
  71. package/test/logic/06.9.3-json-index-range-seek.sqllogic +205 -0
  72. package/test/logic/07-aggregates.sqllogic +193 -0
  73. package/test/logic/07.1-aggregate-filter-clause.sqllogic +12 -0
  74. package/test/logic/07.2-aggregate-order-by.sqllogic +11 -0
  75. package/test/logic/07.3-group-by-extras.sqllogic +602 -0
  76. package/test/logic/07.3.1-group-by-order-by-key.sqllogic +164 -0
  77. package/test/logic/07.3.2-grouped-select-list-shape.sqllogic +231 -0
  78. package/test/logic/07.4-group-by-filter-composite-pk.sqllogic +120 -0
  79. package/test/logic/07.5-sum-mixed-exact-and-float.sqllogic +151 -0
  80. package/test/logic/07.5-window.sqllogic +1941 -0
  81. package/test/logic/07.5.1-window-named.sqllogic +13 -0
  82. package/test/logic/07.5.2-window-nth-value.sqllogic +13 -0
  83. package/test/logic/07.6-subqueries.sqllogic +78 -0
  84. package/test/logic/07.6.1-subquery-extras.sqllogic +93 -0
  85. package/test/logic/07.7-and-or-short-circuit.sqllogic +58 -0
  86. package/test/logic/07.7-in-subquery-caching.sqllogic +174 -0
  87. package/test/logic/07.7-scalar-agg-decorrelation.sqllogic +197 -0
  88. package/test/logic/07.7.1-in-extras.sqllogic +158 -0
  89. package/test/logic/07.7.1-scalar-agg-decorrelation-filter.sqllogic +105 -0
  90. package/test/logic/07.7.2-scalar-agg-decorrelation-nested.sqllogic +115 -0
  91. package/test/logic/07.7.3-exists-in-select-decorrelation.sqllogic +107 -0
  92. package/test/logic/07.7.4-where-conjunct-ordering.sqllogic +121 -0
  93. package/test/logic/07.7.5-filter-lost-under-index-order.sqllogic +134 -0
  94. package/test/logic/07.7.6-correlated-predicate-scope.sqllogic +178 -0
  95. package/test/logic/07.7.7-join-source-scope-shadowing.sqllogic +137 -0
  96. package/test/logic/07.7.8-correlated-ref-to-computed-column.sqllogic +165 -0
  97. package/test/logic/07.7.9-conjunct-monotonicity.sqllogic +200 -0
  98. package/test/logic/07.8-correlated-subquery-edges.sqllogic +71 -0
  99. package/test/logic/07.8.1-correlated-in-decorrelation-gates.sqllogic +156 -0
  100. package/test/logic/07.9-in-value-list.sqllogic +154 -0
  101. package/test/logic/07.9.1-in-value-list-composite-index.sqllogic +38 -0
  102. package/test/logic/08-views.sqllogic +64 -0
  103. package/test/logic/08.1-semi-anti-join.sqllogic +191 -0
  104. package/test/logic/08.1-view-edge-cases.sqllogic +118 -0
  105. package/test/logic/08.1.1-uncorrelated-in-semijoin.sqllogic +251 -0
  106. package/test/logic/08.2-existence-flag-semijoin-recovery.sqllogic +197 -0
  107. package/test/logic/08.3-existence-flag-inner-recovery.sqllogic +102 -0
  108. package/test/logic/08.4-key-set-semi-join.sqllogic +447 -0
  109. package/test/logic/09-set_operations.sqllogic +244 -0
  110. package/test/logic/09.1-set-op-cross-collation.sqllogic +230 -0
  111. package/test/logic/10-distinct_datatypes.sqllogic +127 -0
  112. package/test/logic/10.1-ddl-lifecycle.sqllogic +203 -0
  113. package/test/logic/10.1.1-create-table-syntax-edges.sqllogic +47 -0
  114. package/test/logic/10.1.2-ddl-in-transaction.sqllogic +143 -0
  115. package/test/logic/10.1.2.1-add-constraint-in-transaction.sqllogic +59 -0
  116. package/test/logic/10.1.3-ddl-drop-in-transaction.sqllogic +187 -0
  117. package/test/logic/10.1.3.1-drop-constraint-in-transaction.sqllogic +45 -0
  118. package/test/logic/10.1.4-create-table-duplicate-constraint-names.sqllogic +149 -0
  119. package/test/logic/10.1.4-ddl-transaction-policy.sqllogic +314 -0
  120. package/test/logic/10.1.5-alter-add-constraint-minted-name-disambiguation.sqllogic +219 -0
  121. package/test/logic/10.1.5-create-index-lifecycle.sqllogic +72 -0
  122. package/test/logic/10.1.6-ddl-transaction-policy-index.sqllogic +143 -0
  123. package/test/logic/10.1.7-create-table-default-type-check.sqllogic +119 -0
  124. package/test/logic/10.1.8-alter-add-check-existing-rows.sqllogic +117 -0
  125. package/test/logic/10.2-column-features.sqllogic +365 -0
  126. package/test/logic/10.2.1-table-options-rejection.sqllogic +63 -0
  127. package/test/logic/10.2.2-default-collation-memory.sqllogic +30 -0
  128. package/test/logic/10.3-function-features.sqllogic +247 -0
  129. package/test/logic/10.4-schema-scale.sqllogic +168 -0
  130. package/test/logic/10.4.1-schema-scale-indexes.sqllogic +121 -0
  131. package/test/logic/10.5-indexes.sqllogic +164 -0
  132. package/test/logic/10.5.1-partial-indexes.sqllogic +526 -0
  133. package/test/logic/10.5.2-expression-indexes.sqllogic +34 -0
  134. package/test/logic/10.5.3-desc-index-ordering.sqllogic +130 -0
  135. package/test/logic/10.5.4-composite-pk-index-update-phantom.sqllogic +55 -0
  136. package/test/logic/10.5.5-index-name-uniqueness.sqllogic +76 -0
  137. package/test/logic/10.5.6-minmax-index-boundary.sqllogic +204 -0
  138. package/test/logic/10.5.7-implicit-unique-index-lifecycle.sqllogic +1216 -0
  139. package/test/logic/10.6-distinct-edge-cases.sqllogic +119 -0
  140. package/test/logic/100-predicate-normalization-edge-cases.sqllogic +238 -0
  141. package/test/logic/100.1-where-extras.sqllogic +163 -0
  142. package/test/logic/100.1.1-where-join-on-order-indexed.sqllogic +35 -0
  143. package/test/logic/101-builtin-mutation-kills.sqllogic +974 -0
  144. package/test/logic/101-transaction-edge-cases.sqllogic +395 -0
  145. package/test/logic/102-schema-catalog-edge-cases.sqllogic +252 -0
  146. package/test/logic/102-unique-constraints.sqllogic +145 -0
  147. package/test/logic/102.0.1-schema-catalog-indexed-table.sqllogic +32 -0
  148. package/test/logic/102.1-unique-edge-cases.sqllogic +111 -0
  149. package/test/logic/102.1.1-unique-index-creation-edge-cases.sqllogic +75 -0
  150. package/test/logic/102.2-unique-collation.sqllogic +181 -0
  151. package/test/logic/102.2.1-unique-collation-index-derived.sqllogic +305 -0
  152. package/test/logic/103-database-options-edge-cases.sqllogic +108 -0
  153. package/test/logic/103.1-pragma-boolean-values.sqllogic +126 -0
  154. package/test/logic/104-emit-mutation-kills.sqllogic +236 -0
  155. package/test/logic/105-vtab-memory-mutation-kills.sqllogic +754 -0
  156. package/test/logic/105.1-vtab-memory-index-mutation-kills.sqllogic +540 -0
  157. package/test/logic/106-constraint-extractor-mutation-kills.sqllogic +350 -0
  158. package/test/logic/107-temporal-arithmetic-mutation-kills.sqllogic +833 -0
  159. package/test/logic/108-cardinality-estimation.sqllogic +146 -0
  160. package/test/logic/108.1-analyze-name-resolution.sqllogic +102 -0
  161. package/test/logic/109-aggregate-physical-selection.sqllogic +103 -0
  162. package/test/logic/11-joins.sqllogic +86 -0
  163. package/test/logic/11.1-join-using.sqllogic +267 -0
  164. package/test/logic/11.2-comma-join.sqllogic +35 -0
  165. package/test/logic/11.3-index-nested-loop-join.sqllogic +305 -0
  166. package/test/logic/11.3-mismatched-collation-join.sqllogic +74 -0
  167. package/test/logic/11.4-hash-join-side-swap.sqllogic +118 -0
  168. package/test/logic/110-scan-emitter-mutation-kills.sqllogic +121 -0
  169. package/test/logic/110.1-scan-emitter-index-scan-kills.sqllogic +47 -0
  170. package/test/logic/12-empty-primary-key.sqllogic +124 -0
  171. package/test/logic/12-join_padding_order.sqllogic +58 -0
  172. package/test/logic/12.1-orderby-index-consumption.sqllogic +40 -0
  173. package/test/logic/13-cte.sqllogic +137 -0
  174. package/test/logic/13.1-cte-multiple-recursive.sqllogic +104 -0
  175. package/test/logic/13.10-cte-qualified-name.sqllogic +136 -0
  176. package/test/logic/13.11-unreferenced-dml-cte.sqllogic +414 -0
  177. package/test/logic/13.12-nested-dml-cte-rejected.sqllogic +280 -0
  178. package/test/logic/13.2-cte-bind-params.sqllogic +98 -0
  179. package/test/logic/13.3-cte-edge-cases.sqllogic +120 -0
  180. package/test/logic/13.4-cte-extras.sqllogic +98 -0
  181. package/test/logic/13.5-cte-join-order.sqllogic +166 -0
  182. package/test/logic/13.6-cte-dml-runs-once.sqllogic +318 -0
  183. package/test/logic/13.7-cte-sibling-visibility.sqllogic +227 -0
  184. package/test/logic/13.8-insert-with-clause-visibility.sqllogic +254 -0
  185. package/test/logic/13.9-schema-authored-cte-isolation.sqllogic +328 -0
  186. package/test/logic/13.9.1-schema-authored-schema-path-isolation.sqllogic +408 -0
  187. package/test/logic/14-utilities.sqllogic +168 -0
  188. package/test/logic/15-timespan.sqllogic +279 -0
  189. package/test/logic/15.1-semantic-ordering.sqllogic +960 -0
  190. package/test/logic/15.1.1-json-check-coercion.sqllogic +178 -0
  191. package/test/logic/15.1.2-semantic-ordering-index.sqllogic +41 -0
  192. package/test/logic/15.1.3-declared-form-write-contract.sqllogic +519 -0
  193. package/test/logic/16-epoch.sqllogic +187 -0
  194. package/test/logic/17-weekday-modifier.sqllogic +78 -0
  195. package/test/logic/18-json-string-escapes.sqllogic +86 -0
  196. package/test/logic/18-strftime-extended-formats.sqllogic +68 -0
  197. package/test/logic/20-empty-single-row.sqllogic +261 -0
  198. package/test/logic/21-null-edge-cases.sqllogic +227 -0
  199. package/test/logic/21.1-where-null-comparisons.sqllogic +151 -0
  200. package/test/logic/21.1.1-where-null-comparisons-secondary-index.sqllogic +35 -0
  201. package/test/logic/21.2-between-edges.sqllogic +157 -0
  202. package/test/logic/22-boundary-values.sqllogic +175 -0
  203. package/test/logic/23-self-joins-duplicates.sqllogic +74 -0
  204. package/test/logic/24-builtin-branches.sqllogic +611 -0
  205. package/test/logic/24.1-substr-extras.sqllogic +75 -0
  206. package/test/logic/24.2-random-extras.sqllogic +39 -0
  207. package/test/logic/25-aggregate-edge-cases.sqllogic +289 -0
  208. package/test/logic/25.1-nested-aggregates.sqllogic +74 -0
  209. package/test/logic/25.2-having-edge-cases.sqllogic +318 -0
  210. package/test/logic/25.3-aggregate-isnull-empty.sqllogic +16 -0
  211. package/test/logic/25.4-groupby-fd-constant-empty.sqllogic +55 -0
  212. package/test/logic/25.5-ungrouped-aggregate-column-free-select-item.sqllogic +196 -0
  213. package/test/logic/26-join-edge-cases.sqllogic +333 -0
  214. package/test/logic/26.1-left-join-isnull-on-notnull.sqllogic +26 -0
  215. package/test/logic/26.2-left-join-on-vs-where.sqllogic +67 -0
  216. package/test/logic/26.3-join-on-constants.sqllogic +61 -0
  217. package/test/logic/26.4-join-on-is-null-nullable.sqllogic +44 -0
  218. package/test/logic/27-window-edge-cases.sqllogic +206 -0
  219. package/test/logic/27.1-window-groups-frame.sqllogic +13 -0
  220. package/test/logic/27.2-window-exclude.sqllogic +13 -0
  221. package/test/logic/27.3-window-json-aggregation.sqllogic +66 -0
  222. package/test/logic/28-set-ops-sort-edge-cases.sqllogic +444 -0
  223. package/test/logic/28.1-compound-limit-offset.sqllogic +143 -0
  224. package/test/logic/28.2-orderby-expression-extras.sqllogic +698 -0
  225. package/test/logic/28.2-set-op-branch-types.sqllogic +217 -0
  226. package/test/logic/29-constraint-edge-cases.sqllogic +442 -0
  227. package/test/logic/29.1-column-level-conflict-clause.sqllogic +171 -0
  228. package/test/logic/29.2-table-level-pk-conflict-clause.sqllogic +113 -0
  229. package/test/logic/40-constraints.sqllogic +418 -0
  230. package/test/logic/40.1-pk-desc-direction.sqllogic +76 -0
  231. package/test/logic/40.2-check-extras.sqllogic +683 -0
  232. package/test/logic/41-alter-table.sqllogic +191 -0
  233. package/test/logic/41-fk-cascade-conflict-and-self-ref.sqllogic +263 -0
  234. package/test/logic/41-fk-cross-schema.sqllogic +155 -0
  235. package/test/logic/41-fk-extended-targets.sqllogic +173 -0
  236. package/test/logic/41-foreign-keys.sqllogic +1001 -0
  237. package/test/logic/41-generated-column-errors.sqllogic +225 -0
  238. package/test/logic/41-generated-column-extras.sqllogic +598 -0
  239. package/test/logic/41-generated-column-scope.sqllogic +329 -0
  240. package/test/logic/41-generated-columns.sqllogic +361 -0
  241. package/test/logic/41.1-alter-pk.sqllogic +230 -0
  242. package/test/logic/41.1-fk-collation-conflict.sqllogic +277 -0
  243. package/test/logic/41.10-alter-drop-column-foreign-key.sqllogic +274 -0
  244. package/test/logic/41.10.1-alter-drop-column-unique-index.sqllogic +169 -0
  245. package/test/logic/41.10.2-alter-drop-column-check-and-assertion.sqllogic +1616 -0
  246. package/test/logic/41.10.3-alter-drop-column-referencing-fk.sqllogic +292 -0
  247. package/test/logic/41.10.4-drop-object-expression-dependents.sqllogic +602 -0
  248. package/test/logic/41.11-deferred-fk-with-rename.sqllogic +232 -0
  249. package/test/logic/41.12-alter-default-coercion.sqllogic +200 -0
  250. package/test/logic/41.13-alter-add-column-generated-backfill.sqllogic +566 -0
  251. package/test/logic/41.14-alter-add-column-subquery-backfill.sqllogic +129 -0
  252. package/test/logic/41.15-alter-column-default-type-check.sqllogic +178 -0
  253. package/test/logic/41.16-fk-unenforceable.sqllogic +364 -0
  254. package/test/logic/41.2-alter-column.sqllogic +382 -0
  255. package/test/logic/41.2.1-alter-column-retype-deleted-row-memory.sqllogic +32 -0
  256. package/test/logic/41.2.2-alter-column-retype-index-rebuild.sqllogic +77 -0
  257. package/test/logic/41.2.3-alter-column-set-not-null-pk-backfill.sqllogic +310 -0
  258. package/test/logic/41.2.3.1-alter-column-set-not-null-pk-backfill-secondary-index.sqllogic +37 -0
  259. package/test/logic/41.3-alter-add-column-unique.sqllogic +184 -0
  260. package/test/logic/41.3-alter-rename-propagation.sqllogic +2352 -0
  261. package/test/logic/41.3.1-alter-rename-index-propagation.sqllogic +94 -0
  262. package/test/logic/41.4-alter-add-column-constraints.sqllogic +855 -0
  263. package/test/logic/41.5-alter-misc.sqllogic +48 -0
  264. package/test/logic/41.5-cross-schema-foreign-keys.sqllogic +253 -0
  265. package/test/logic/41.6-alter-drop-rename-constraint.sqllogic +354 -0
  266. package/test/logic/41.6.1-alter-drop-constraint-index-derived.sqllogic +22 -0
  267. package/test/logic/41.7-alter-column-collate.sqllogic +105 -0
  268. package/test/logic/41.7.1-alter-column-collate-unique.sqllogic +45 -0
  269. package/test/logic/41.7.2-alter-column-collate-unique-store.sqllogic +208 -0
  270. package/test/logic/41.7.2.1-alter-column-collate-unique-index-store.sqllogic +114 -0
  271. package/test/logic/41.7.3-alter-column-retype-unique.sqllogic +293 -0
  272. package/test/logic/41.7.3.1-alter-column-retype-staged-rows-memory.sqllogic +41 -0
  273. package/test/logic/41.7.3.2-alter-column-retype-unique-index.sqllogic +72 -0
  274. package/test/logic/41.7.4-alter-column-retype-semantic-memory.sqllogic +445 -0
  275. package/test/logic/41.7.4.1-alter-column-retype-semantic-index-memory.sqllogic +91 -0
  276. package/test/logic/41.7.5-alter-column-collate-pk-staged-delete-memory.sqllogic +106 -0
  277. package/test/logic/41.8-alter-add-constraint-unique-fk.sqllogic +275 -0
  278. package/test/logic/41.8-alter-savepoint-staged-rows.sqllogic +443 -0
  279. package/test/logic/41.8.1-alter-rename-savepoint-staged-rows.sqllogic +408 -0
  280. package/test/logic/41.9-alter-constraint-body-change.sqllogic +180 -0
  281. package/test/logic/41.9-fk-restrict-batched.sqllogic +290 -0
  282. package/test/logic/42-committed-snapshot.sqllogic +254 -0
  283. package/test/logic/42-returning.sqllogic +159 -0
  284. package/test/logic/42.1-returning-extras.sqllogic +232 -0
  285. package/test/logic/42.2-returning-stored-row.sqllogic +165 -0
  286. package/test/logic/43-default-nullability.sqllogic +131 -0
  287. package/test/logic/43-transition-constraints.sqllogic +341 -0
  288. package/test/logic/43.1-default-collation.sqllogic +140 -0
  289. package/test/logic/43.1-notnull-or-conflict.sqllogic +79 -0
  290. package/test/logic/43.2-deferred-check-new-on-delete.sqllogic +95 -0
  291. package/test/logic/43.3-nullable-primary-key.sqllogic +587 -0
  292. package/test/logic/44-determinism-validation.sqllogic +164 -0
  293. package/test/logic/44-orthogonality.sqllogic +146 -0
  294. package/test/logic/44.1-nondeterministic-schema.sqllogic +316 -0
  295. package/test/logic/45-udf-determinism.sqllogic +39 -0
  296. package/test/logic/46-mutation-context.sqllogic +595 -0
  297. package/test/logic/47-upsert.sqllogic +255 -0
  298. package/test/logic/47.1-upsert-conflict-targets.sqllogic +169 -0
  299. package/test/logic/47.2-replace-and-or-clauses.sqllogic +164 -0
  300. package/test/logic/47.2.1-pk-replace-secondary-unique.sqllogic +374 -0
  301. package/test/logic/47.3-engine-or-fail.sqllogic +122 -0
  302. package/test/logic/47.3-upsert-conflict-target-collation.sqllogic +139 -0
  303. package/test/logic/47.3.1-upsert-conflict-index-derived-collation.sqllogic +25 -0
  304. package/test/logic/47.4-upsert-conflict-target-affinity.sqllogic +59 -0
  305. package/test/logic/47.5-upsert-do-update-constraints.sqllogic +440 -0
  306. package/test/logic/47.6-upsert-do-update-decomposed.sqllogic +100 -0
  307. package/test/logic/49-reference-graph.sqllogic +84 -0
  308. package/test/logic/50-declarative-schema.sqllogic +2550 -0
  309. package/test/logic/50-metadata-tags.sqllogic +1033 -0
  310. package/test/logic/50.0.1-metadata-tags-index.sqllogic +141 -0
  311. package/test/logic/50.1-declare-schema-pk.sqllogic +150 -0
  312. package/test/logic/50.2-declare-schema-renames.sqllogic +949 -0
  313. package/test/logic/50.2.1-declare-schema-index-renames.sqllogic +173 -0
  314. package/test/logic/50.3-declare-schema-duplicate-names.sqllogic +280 -0
  315. package/test/logic/50.4-declare-schema-apply-restore.sqllogic +192 -0
  316. package/test/logic/51-lens-foundation.sqllogic +147 -0
  317. package/test/logic/51-materialized-views.sqllogic +376 -0
  318. package/test/logic/51.5-materialized-views-coarsened-key.sqllogic +198 -0
  319. package/test/logic/51.7-maintained-table-attach-detach.sqllogic +468 -0
  320. package/test/logic/51.8-maintained-table-declared-constraints.sqllogic +440 -0
  321. package/test/logic/51.85-maintained-table-parent-fk.sqllogic +103 -0
  322. package/test/logic/51.9-maintained-table-secondary-unique.sqllogic +237 -0
  323. package/test/logic/51.9.1-maintained-table-partial-unique.sqllogic +36 -0
  324. package/test/logic/52-lens-overrides.sqllogic +566 -0
  325. package/test/logic/53-materialized-views-rowtime.sqllogic +1601 -0
  326. package/test/logic/53-reserved-tags.sqllogic +252 -0
  327. package/test/logic/53.1-materialized-view-write-through.sqllogic +329 -0
  328. package/test/logic/53.2-materialized-view-rename-propagation.sqllogic +483 -0
  329. package/test/logic/53.3-materialized-view-constraint-only-ddl.sqllogic +409 -0
  330. package/test/logic/53.3.1-materialized-view-index-ddl-irrelevance.sqllogic +29 -0
  331. package/test/logic/53.4-materialized-view-structural-alter-restore.sqllogic +436 -0
  332. package/test/logic/54-covering-mv-enforcement.sqllogic +314 -0
  333. package/test/logic/54.1-covering-mv-partial-enforcement.sqllogic +34 -0
  334. package/test/logic/55-internal-eviction-reporting.sqllogic +89 -0
  335. package/test/logic/55-lens-prover.sqllogic +202 -0
  336. package/test/logic/55.1-eviction-restrict-fk.sqllogic +148 -0
  337. package/test/logic/55.5-lens-authored-inverse.sqllogic +1468 -0
  338. package/test/logic/80-grow-retrieve-pass.sqllogic +79 -0
  339. package/test/logic/81-quickpick.sqllogic +24 -0
  340. package/test/logic/82-bloom-join.sqllogic +185 -0
  341. package/test/logic/83-merge-join.sqllogic +280 -0
  342. package/test/logic/84-asof-scan.sqllogic +238 -0
  343. package/test/logic/84-key-cardinality.sqllogic +50 -0
  344. package/test/logic/85-relational-const-folding.sqllogic +51 -0
  345. package/test/logic/86-scalar-cse.sqllogic +42 -0
  346. package/test/logic/90-error_paths.sqllogic +114 -0
  347. package/test/logic/90.1-parse-errors.sqllogic +77 -0
  348. package/test/logic/90.2-alter-table-errors.sqllogic +53 -0
  349. package/test/logic/90.2.1-alter-extra-errors.sqllogic +51 -0
  350. package/test/logic/90.3-expression-errors.sqllogic +43 -0
  351. package/test/logic/90.4-dml-errors.sqllogic +47 -0
  352. package/test/logic/90.5-unsupported-join-types.sqllogic +37 -0
  353. package/test/logic/90.5.1-right-full-join-read.sqllogic +157 -0
  354. package/test/logic/90.6-select-error-paths.sqllogic +57 -0
  355. package/test/logic/91-merge-join-edge-cases.sqllogic +159 -0
  356. package/test/logic/92-hash-aggregate-edge-cases.sqllogic +139 -0
  357. package/test/logic/93-ddl-view-edge-cases.sqllogic +104 -0
  358. package/test/logic/93.1-view-error-paths.sqllogic +74 -0
  359. package/test/logic/93.2-view-mutation-pending.sqllogic +108 -0
  360. package/test/logic/93.3-view-mutation-or-clause.sqllogic +60 -0
  361. package/test/logic/93.4-view-mutation.sqllogic +4881 -0
  362. package/test/logic/93.4.1-view-mutation-partial-unique-cardinality.sqllogic +31 -0
  363. package/test/logic/93.5-authored-inverse.sqllogic +415 -0
  364. package/test/logic/93.6-set-op-flagless-write.sqllogic +862 -0
  365. package/test/logic/94-tvf-edge-cases.sqllogic +58 -0
  366. package/test/logic/94.1-limit-offset-edge-cases.sqllogic +109 -0
  367. package/test/logic/94.2-limit-offset-extras.sqllogic +98 -0
  368. package/test/logic/95-assertions.sqllogic +1417 -0
  369. package/test/logic/96-subquery-edge-cases.sqllogic +276 -0
  370. package/test/logic/97-json-function-edge-cases.sqllogic +633 -0
  371. package/test/logic/97.1-json-blob-and-special-values.sqllogic +92 -0
  372. package/test/logic/98-temporal-edge-cases.sqllogic +515 -0
  373. package/test/logic/99-conversion-edge-cases.sqllogic +325 -0
  374. package/test/logic/99.0.1-schema-index-listing.sqllogic +21 -0
  375. package/test/logic/99.1-cast-syntax-extras.sqllogic +167 -0
  376. package/test/logic/drop-unique-index.sqllogic +88 -0
  377. package/test/logic/pushdown-test.sqllogic +36 -0
@@ -0,0 +1,833 @@
1
+ -- 107-temporal-arithmetic-mutation-kills.sqllogic
2
+ -- Mutation-killing tests for temporal arithmetic and comparison paths in
3
+ -- binary.ts and temporal-arithmetic.ts.
4
+
5
+ -- ============================================================
6
+ -- DATE + TIMESPAN arithmetic
7
+ -- ============================================================
8
+
9
+ -- Basic addition
10
+ SELECT date('2024-01-15') + timespan('P10D') as result;
11
+ → [{"result":"2024-01-25"}]
12
+
13
+ -- Month addition
14
+ SELECT date('2024-01-15') + timespan('P3M') as result;
15
+ → [{"result":"2024-04-15"}]
16
+
17
+ -- Year addition
18
+ SELECT date('2024-01-15') + timespan('P1Y') as result;
19
+ → [{"result":"2025-01-15"}]
20
+
21
+ -- Month rollover: Jan 31 + 1 month (leap year)
22
+ SELECT date('2024-01-31') + timespan('P1M') as result;
23
+ → [{"result":"2024-02-29"}]
24
+
25
+ -- Month rollover: Jan 31 + 1 month (non-leap year)
26
+ SELECT date('2023-01-31') + timespan('P1M') as result;
27
+ → [{"result":"2023-02-28"}]
28
+
29
+ -- Leap year: Feb 29 + 1 year
30
+ SELECT date('2024-02-29') + timespan('P1Y') as result;
31
+ → [{"result":"2025-02-28"}]
32
+
33
+ -- Negative timespan
34
+ SELECT date('2024-03-15') + timespan('-P10D') as result;
35
+ → [{"result":"2024-03-05"}]
36
+
37
+ -- Zero timespan is identity
38
+ SELECT date('2024-06-15') + timespan('PT0S') as result;
39
+ → [{"result":"2024-06-15"}]
40
+
41
+ -- ============================================================
42
+ -- TIMESPAN + DATE (commutative)
43
+ -- ============================================================
44
+
45
+ SELECT timespan('P10D') + date('2024-01-15') as result;
46
+ → [{"result":"2024-01-25"}]
47
+
48
+ SELECT timespan('P2M') + date('2024-01-31') as result;
49
+ → [{"result":"2024-03-31"}]
50
+
51
+ -- ============================================================
52
+ -- DATE - TIMESPAN
53
+ -- ============================================================
54
+
55
+ SELECT date('2024-01-25') - timespan('P10D') as result;
56
+ → [{"result":"2024-01-15"}]
57
+
58
+ SELECT date('2024-03-31') - timespan('P1M') as result;
59
+ → [{"result":"2024-02-29"}]
60
+
61
+ -- Subtracting negative timespan (effectively adds)
62
+ SELECT date('2024-01-15') - timespan('-P10D') as result;
63
+ → [{"result":"2024-01-25"}]
64
+
65
+ -- ============================================================
66
+ -- DATE - DATE → TIMESPAN
67
+ -- ============================================================
68
+
69
+ -- Same date → zero
70
+ SELECT date('2024-01-15') - date('2024-01-15') as result;
71
+ → [{"result":"PT0S"}]
72
+
73
+ -- Later - earlier
74
+ SELECT date('2024-01-25') - date('2024-01-15') as result;
75
+ → [{"result":"P10D"}]
76
+
77
+ -- Earlier - later → negative
78
+ SELECT date('2024-01-15') - date('2024-01-25') as result;
79
+ → [{"result":"-P10D"}]
80
+
81
+ -- ============================================================
82
+ -- DATETIME + TIMESPAN
83
+ -- ============================================================
84
+
85
+ SELECT datetime('2024-01-15T10:00:00') + timespan('PT2H') as result;
86
+ → [{"result":"2024-01-15T12:00:00"}]
87
+
88
+ -- Crossing midnight
89
+ SELECT datetime('2024-01-15T23:00:00') + timespan('PT2H') as result;
90
+ → [{"result":"2024-01-16T01:00:00"}]
91
+
92
+ -- Month rollover in datetime
93
+ SELECT datetime('2024-01-31T12:00:00') + timespan('P1M') as result;
94
+ → [{"result":"2024-02-29T12:00:00"}]
95
+
96
+ -- Negative timespan on datetime
97
+ SELECT datetime('2024-01-15T12:00:00') + timespan('-PT3H') as result;
98
+ → [{"result":"2024-01-15T09:00:00"}]
99
+
100
+ -- ============================================================
101
+ -- TIMESPAN + DATETIME (commutative)
102
+ -- ============================================================
103
+
104
+ SELECT timespan('PT2H') + datetime('2024-01-15T10:00:00') as result;
105
+ → [{"result":"2024-01-15T12:00:00"}]
106
+
107
+ -- ============================================================
108
+ -- DATETIME - TIMESPAN
109
+ -- ============================================================
110
+
111
+ SELECT datetime('2024-01-15T12:00:00') - timespan('PT2H') as result;
112
+ → [{"result":"2024-01-15T10:00:00"}]
113
+
114
+ -- Across day boundary
115
+ SELECT datetime('2024-01-16T01:00:00') - timespan('PT2H') as result;
116
+ → [{"result":"2024-01-15T23:00:00"}]
117
+
118
+ -- ============================================================
119
+ -- DATETIME - DATETIME → TIMESPAN
120
+ -- ============================================================
121
+
122
+ SELECT datetime('2024-01-15T12:00:00') - datetime('2024-01-15T12:00:00') as result;
123
+ → [{"result":"PT0S"}]
124
+
125
+ SELECT datetime('2024-01-25T00:00:00') - datetime('2024-01-15T00:00:00') as result;
126
+ → [{"result":"P10D"}]
127
+
128
+ -- ============================================================
129
+ -- Mixed DATE/DATETIME subtraction
130
+ -- ============================================================
131
+
132
+ -- A DATE facing a DATETIME is read as that date at midnight
133
+ SELECT date('2024-01-25') - datetime('2024-01-15T10:00:00') as result;
134
+ → [{"result":"P9DT14H"}]
135
+
136
+ SELECT datetime('2024-01-25T10:00:00') - date('2024-01-15') as result;
137
+ → [{"result":"P10DT10H"}]
138
+
139
+ SELECT date('2024-01-25') - date('2024-01-15') as result;
140
+ → [{"result":"P10D"}]
141
+
142
+ -- ============================================================
143
+ -- TIME + TIMESPAN
144
+ -- ============================================================
145
+
146
+ SELECT time('10:00:00') + timespan('PT2H') as result;
147
+ → [{"result":"12:00:00"}]
148
+
149
+ SELECT time('10:00:00') + timespan('PT30M') as result;
150
+ → [{"result":"10:30:00"}]
151
+
152
+ -- Wrap around midnight
153
+ SELECT time('23:00:00') + timespan('PT2H') as result;
154
+ → [{"result":"01:00:00"}]
155
+
156
+ -- ============================================================
157
+ -- TIMESPAN + TIME (commutative)
158
+ -- ============================================================
159
+
160
+ SELECT timespan('PT2H') + time('10:00:00') as result;
161
+ → [{"result":"12:00:00"}]
162
+
163
+ -- ============================================================
164
+ -- TIME - TIMESPAN
165
+ -- ============================================================
166
+
167
+ SELECT time('12:00:00') - timespan('PT2H') as result;
168
+ → [{"result":"10:00:00"}]
169
+
170
+ -- Wrap before midnight
171
+ SELECT time('01:00:00') - timespan('PT2H') as result;
172
+ → [{"result":"23:00:00"}]
173
+
174
+ -- ============================================================
175
+ -- TIME - TIME → TIMESPAN
176
+ -- ============================================================
177
+
178
+ SELECT time('12:00:00') - time('12:00:00') as result;
179
+ → [{"result":"PT0S"}]
180
+
181
+ SELECT time('14:00:00') - time('12:00:00') as result;
182
+ → [{"result":"PT2H"}]
183
+
184
+ SELECT time('10:00:00') - time('12:00:00') as result;
185
+ → [{"result":"-PT2H"}]
186
+
187
+ -- ============================================================
188
+ -- TIMESPAN + TIMESPAN
189
+ -- ============================================================
190
+
191
+ SELECT timespan('PT1H') + timespan('PT30M') as result;
192
+ → [{"result":"PT1H30M"}]
193
+
194
+ SELECT timespan('P1D') + timespan('PT12H') as result;
195
+ → [{"result":"P1DT12H"}]
196
+
197
+ -- Adding zero
198
+ SELECT timespan('PT1H') + timespan('PT0S') as result;
199
+ → [{"result":"PT1H"}]
200
+
201
+ -- ============================================================
202
+ -- TIMESPAN - TIMESPAN
203
+ -- ============================================================
204
+
205
+ SELECT timespan('PT2H') - timespan('PT30M') as result;
206
+ → [{"result":"PT1H30M"}]
207
+
208
+ -- Subtracting equal → zero
209
+ SELECT timespan('PT1H') - timespan('PT1H') as result;
210
+ → [{"result":"PT0S"}]
211
+
212
+ -- Subtracting larger → negative
213
+ SELECT timespan('PT30M') - timespan('PT1H') as result;
214
+ → [{"result":"-PT30M"}]
215
+
216
+ -- ============================================================
217
+ -- TIMESPAN * NUMBER
218
+ -- ============================================================
219
+
220
+ SELECT timespan('PT1H') * 2 as result;
221
+ → [{"result":"PT7200S"}]
222
+
223
+ SELECT timespan('PT1H') * 0.5 as result;
224
+ → [{"result":"PT1800S"}]
225
+
226
+ -- Times zero
227
+ SELECT timespan('PT1H') * 0 as result;
228
+ → [{"result":"PT0S"}]
229
+
230
+ -- Calendar-unit scaling
231
+ SELECT timespan('P1Y') * 2 as result;
232
+ → [{"result":"P2Y"}]
233
+
234
+ -- ============================================================
235
+ -- NUMBER * TIMESPAN (commutative)
236
+ -- ============================================================
237
+
238
+ SELECT 2 * timespan('PT1H') as result;
239
+ → [{"result":"PT7200S"}]
240
+
241
+ SELECT 3 * timespan('P1M') as result;
242
+ → [{"result":"P3M"}]
243
+
244
+ -- ============================================================
245
+ -- TIMESPAN / NUMBER
246
+ -- ============================================================
247
+
248
+ SELECT timespan('PT2H') / 2 as result;
249
+ → [{"result":"PT3600S"}]
250
+
251
+ -- Divide by zero returns null
252
+ SELECT timespan('PT1H') / 0 as result;
253
+ → [{"result":null}]
254
+
255
+ -- Calendar-unit division
256
+ SELECT timespan('P6M') / 2 as result;
257
+ → [{"result":"P3M"}]
258
+
259
+ -- ============================================================
260
+ -- TIMESPAN / TIMESPAN → NUMBER
261
+ -- ============================================================
262
+
263
+ SELECT timespan('PT2H') / timespan('PT1H') as result;
264
+ → [{"result":2}]
265
+
266
+ SELECT timespan('PT30M') / timespan('PT1H') as result;
267
+ → [{"result":0.5}]
268
+
269
+ -- Divide by zero timespan → null
270
+ SELECT timespan('PT1H') / timespan('PT0S') as result;
271
+ → [{"result":null}]
272
+
273
+ -- Calendar unit ratio → null
274
+ SELECT timespan('P1Y') / timespan('P1M') as result;
275
+ → [{"result":null}]
276
+
277
+ -- ============================================================
278
+ -- NULL propagation — temporal operand with NULL
279
+ -- ============================================================
280
+
281
+ SELECT date('2024-01-15') + null as result;
282
+ → [{"result":null}]
283
+
284
+ SELECT null + date('2024-01-15') as result;
285
+ → [{"result":null}]
286
+
287
+ SELECT null - date('2024-01-15') as result;
288
+ → [{"result":null}]
289
+
290
+ SELECT datetime('2024-01-15T12:00:00') + null as result;
291
+ → [{"result":null}]
292
+
293
+ SELECT null + timespan('PT1H') as result;
294
+ → [{"result":null}]
295
+
296
+ SELECT timespan('PT1H') * null as result;
297
+ → [{"result":null}]
298
+
299
+ SELECT timespan('PT1H') / null as result;
300
+ → [{"result":null}]
301
+
302
+ SELECT null * timespan('PT1H') as result;
303
+ → [{"result":null}]
304
+
305
+ SELECT timespan('PT1H') - null as result;
306
+ → [{"result":null}]
307
+
308
+ SELECT null / timespan('PT1H') as result;
309
+ → [{"result":null}]
310
+
311
+ SELECT time('10:00:00') - null as result;
312
+ → [{"result":null}]
313
+
314
+ -- ============================================================
315
+ -- Chained temporal arithmetic
316
+ --
317
+ -- The declared result type of the inner expression is what the outer operator
318
+ -- specializes on (types/temporal-ops.ts). Before that table existed the planner
319
+ -- announced the LEFT operand's type for every temporal pair, so the inner
320
+ -- `date - date` claimed DATE while holding a duration string.
321
+ -- ============================================================
322
+
323
+ -- (DATE - DATE) is a TIMESPAN, so the outer + is TIMESPAN + TIMESPAN
324
+ SELECT (date('2024-01-20') - date('2024-01-15')) + timespan('P1D') as result;
325
+ → [{"result":"P6D"}]
326
+
327
+ -- (DATE + TIMESPAN) is a DATE, so the outer - is DATE - DATE → a TIMESPAN
328
+ SELECT (date('2024-01-20') + timespan('P1D')) - date('2024-01-15') as result;
329
+ → [{"result":"P6D"}]
330
+
331
+ -- (TIMESPAN / TIMESPAN) is a REAL, so the outer + is plain numeric arithmetic
332
+ SELECT (timespan('PT2H') / timespan('PT1H')) + 1 as result;
333
+ → [{"result":3}]
334
+
335
+ -- (TIMESPAN - TIMESPAN) is a TIMESPAN
336
+ SELECT (timespan('PT2H') - timespan('PT30M')) + timespan('PT30M') as result;
337
+ → [{"result":"PT2H"}]
338
+
339
+ -- (NUMBER * TIMESPAN) is a TIMESPAN, so the outer + finds no NUMBER case.
340
+ -- Returned null before the result type was fixed: the inner expression was
341
+ -- announced INTEGER, the outer + took the numeric fast path, and `'PT7200S' + 3`
342
+ -- produced a non-finite value. An error is the honest answer.
343
+ SELECT (2 * timespan('PT1H')) + 3 as result;
344
+ -- error: Unsupported temporal operation
345
+
346
+ -- ============================================================
347
+ -- Unsupported combinations still raise, byte for byte
348
+ -- ============================================================
349
+
350
+ SELECT date('2024-01-15') + date('2024-01-16') as result;
351
+ -- error: Unsupported temporal operation
352
+
353
+ SELECT date('2024-01-15') * 2 as result;
354
+ -- error: Unsupported temporal operation
355
+
356
+ SELECT time('10:00:00') - date('2024-01-15') as result;
357
+ -- error: Unsupported temporal operation
358
+
359
+ SELECT timespan('PT1H') % timespan('PT1H') as result;
360
+ -- error: Unsupported temporal operation
361
+
362
+ SELECT date('2024-01-15') - 5 as result;
363
+ -- error: Unsupported temporal operation
364
+
365
+ -- A number past 2^53 is a bigint, which the `*` / `/` number cases reject.
366
+ -- Preserved as found — see the NOTE on scaleTimespan in types/temporal-ops.ts.
367
+ SELECT timespan('PT1H') * 9007199254740993 as result;
368
+ -- error: Unsupported temporal operation
369
+
370
+ -- ============================================================
371
+ -- Operands whose declared type settles nothing keep sniffing values at runtime
372
+ -- ============================================================
373
+
374
+ -- TEXT operand: no plan-time kind, so the pair falls back to runtime shape probes,
375
+ -- which find no (undefined, date) case.
376
+ SELECT 'not-a-date' - date('2024-01-15') as result;
377
+ -- error: Unsupported temporal operation
378
+
379
+ -- ...and the same fallback still succeeds when the TEXT value does look temporal
380
+ SELECT timespan('PT1H') + 'PT1H' as result;
381
+ → [{"result":"PT2H"}]
382
+
383
+ -- ============================================================
384
+ -- TIMESTAMP is deliberately outside the table
385
+ --
386
+ -- It is an integer instant, not a string temporal, and appears in no case — so
387
+ -- `ts + 1` keeps taking the runtime-sniffed path (both values look numeric, so
388
+ -- nothing temporal matches) and plain numeric arithmetic answers.
389
+ -- ============================================================
390
+
391
+ CREATE TABLE ts_int (id INTEGER PRIMARY KEY, t TIMESTAMP);
392
+ INSERT INTO ts_int VALUES (1, 1705276800000);
393
+ -- run
394
+
395
+ SELECT t + 1 as result FROM ts_int;
396
+ → [{"result":1705276800001}]
397
+
398
+ SELECT t - t as result FROM ts_int;
399
+ → [{"result":0}]
400
+
401
+ DROP TABLE ts_int;
402
+
403
+ -- ============================================================
404
+ -- DATETIME - DATETIME keeps the time of day
405
+ --
406
+ -- The difference is the full elapsed gap — days plus the time-of-day remainder —
407
+ -- never whole calendar days. The largest unit stays `day`.
408
+ -- ============================================================
409
+
410
+ SELECT datetime('2024-01-20T10:00:00') - datetime('2024-01-15T08:00:00') as result;
411
+ → [{"result":"P5DT2H"}]
412
+
413
+ -- Negative mirror
414
+ SELECT datetime('2024-01-15T08:00:00') - datetime('2024-01-20T10:00:00') as result;
415
+ → [{"result":"-P5DT2H"}]
416
+
417
+ -- Under a day apart but across midnight: two hours, not a calendar day
418
+ SELECT datetime('2024-01-16T01:00:00') - datetime('2024-01-15T23:00:00') as result;
419
+ → [{"result":"PT2H"}]
420
+
421
+ -- Sub-second gap
422
+ SELECT datetime('2024-01-15T00:00:00.500') - datetime('2024-01-15T00:00:00') as result;
423
+ → [{"result":"PT0.5S"}]
424
+
425
+ -- Over a year apart: still days, never years/months/weeks. Load-bearing, not cosmetic —
426
+ -- `TIMESPAN / TIMESPAN` returns NULL once either side carries calendar units, so a
427
+ -- years-shaped difference would silently break division on long gaps.
428
+ SELECT datetime('2025-03-01T10:00:00') - datetime('2024-01-15T08:00:00') as result;
429
+ → [{"result":"P411DT2H"}]
430
+
431
+ SELECT (datetime('2025-03-01T10:00:00') - datetime('2024-01-15T08:00:00')) / timespan('PT1H') as result;
432
+ → [{"result":9866}]
433
+
434
+ -- ============================================================
435
+ -- TIMESPAN comparisons (semantic, not lexicographic)
436
+ -- ============================================================
437
+
438
+ -- Create table with timespan column for comparison tests
439
+ CREATE TABLE ts_test (id INTEGER PRIMARY KEY, dur TIMESPAN);
440
+ INSERT INTO ts_test VALUES (1, 'PT30M'), (2, 'PT1H'), (3, 'PT2H'), (4, 'P1D'), (5, 'PT0S');
441
+ -- run
442
+
443
+ -- Equality with equivalent representations
444
+ SELECT id FROM ts_test WHERE dur = 'PT60M';
445
+ → [{"id":2}]
446
+
447
+ -- Less-than
448
+ SELECT id FROM ts_test WHERE dur < 'PT1H' ORDER BY id;
449
+ → [{"id":1},{"id":5}]
450
+
451
+ -- Greater-than
452
+ SELECT id FROM ts_test WHERE dur > 'PT1H' ORDER BY id;
453
+ → [{"id":3},{"id":4}]
454
+
455
+ -- Less-than-or-equal
456
+ SELECT id FROM ts_test WHERE dur <= 'PT1H' ORDER BY id;
457
+ → [{"id":1},{"id":2},{"id":5}]
458
+
459
+ -- Greater-than-or-equal
460
+ SELECT id FROM ts_test WHERE dur >= 'PT1H' ORDER BY id;
461
+ → [{"id":2},{"id":3},{"id":4}]
462
+
463
+ -- Not-equal
464
+ SELECT id FROM ts_test WHERE dur != 'PT1H' ORDER BY id;
465
+ → [{"id":1},{"id":3},{"id":4},{"id":5}]
466
+
467
+ -- ORDER BY with timespans: semantic (elapsed-time) order, matching `<`/`>` above
468
+ -- (see docs/types.md "Semantic ordering"; was lexicographic before that ruling)
469
+ SELECT id, dur FROM ts_test ORDER BY dur;
470
+ → [{"id":5,"dur":"PT0S"},{"id":1,"dur":"PT30M"},{"id":2,"dur":"PT1H"},{"id":3,"dur":"PT2H"},{"id":4,"dur":"P1D"}]
471
+
472
+ -- MIN / MAX aggregation ranks by elapsed time, same as ORDER BY / `<` above
473
+ -- (the aggregate binds to the argument's TIMESPAN type at emit — docs/types.md
474
+ -- "Semantic ordering"). Text order would report mn=P1D, mx=PT30M.
475
+ SELECT min(dur) as mn, max(dur) as mx FROM ts_test;
476
+ → [{"mn":"PT0S","mx":"P1D"}]
477
+
478
+ -- min/max agree with the ordering sites: order by … limit 1 (asc and desc)
479
+ SELECT (min(dur) = (SELECT dur FROM ts_test ORDER BY dur LIMIT 1)) as min_agrees,
480
+ (max(dur) = (SELECT dur FROM ts_test ORDER BY dur DESC LIMIT 1)) as max_agrees
481
+ FROM ts_test;
482
+ → [{"min_agrees":true,"max_agrees":true}]
483
+
484
+ -- DISTINCT dedup is already semantic; the DISTINCT form must match the plain form
485
+ SELECT min(distinct dur) as mn, max(distinct dur) as mx FROM ts_test;
486
+ → [{"mn":"PT0S","mx":"P1D"}]
487
+
488
+ DROP TABLE ts_test;
489
+
490
+ -- GROUP BY shape (hash aggregate): the bound comparator must reach the grouped
491
+ -- path too, not just the single-group stream aggregate.
492
+ CREATE TABLE ts_grp (id INTEGER PRIMARY KEY, g INTEGER, dur TIMESPAN);
493
+ INSERT INTO ts_grp VALUES
494
+ (1, 1, 'PT30M'), (2, 1, 'PT2H'), (3, 1, 'PT90M'),
495
+ (4, 2, 'P1D'), (5, 2, 'PT10M');
496
+ -- run
497
+
498
+ SELECT g, min(dur) as mn, max(dur) as mx FROM ts_grp GROUP BY g ORDER BY g;
499
+ → [{"g":1,"mn":"PT30M","mx":"PT2H"},{"g":2,"mn":"PT10M","mx":"P1D"}]
500
+
501
+ DROP TABLE ts_grp;
502
+
503
+ -- Materialized view over TIMESPAN min/max: store-maintained values must rank by
504
+ -- the same semantic comparator as direct evaluation, through BOTH maintenance
505
+ -- arms — the delta merge on insert and the tighten residual fallback on a
506
+ -- delete of the extreme.
507
+ CREATE TABLE ts_src (id INTEGER PRIMARY KEY, g INTEGER, dur TIMESPAN);
508
+ INSERT INTO ts_src VALUES (1, 1, 'PT30M'), (2, 1, 'PT2H'), (3, 1, 'PT90M');
509
+ CREATE MATERIALIZED VIEW ts_mv AS
510
+ SELECT g, count(*) AS c, min(dur) AS mn, max(dur) AS mx FROM ts_src GROUP BY g;
511
+ -- run
512
+
513
+ -- (a) create-fill: stored equals the directly-evaluated body (text order would
514
+ -- store mn=PT2H, mx=PT90M).
515
+ SELECT g, c, mn, mx FROM ts_mv ORDER BY g;
516
+ → [{"g":1,"c":3,"mn":"PT30M","mx":"PT2H"}]
517
+
518
+ -- (b) an insert exercises the delta merge path. 'P1D' is chosen because its text
519
+ -- and elapsed-time orders disagree against BOTH stored extrema: it sorts before
520
+ -- 'PT30M' textually (a text merge would wrongly drop mn to P1D) yet is the longest
521
+ -- duration here (a text merge would wrongly leave mx at PT2H).
522
+ INSERT INTO ts_src VALUES (4, 1, 'P1D');
523
+ SELECT g, c, mn, mx FROM ts_mv ORDER BY g;
524
+ → [{"g":1,"c":4,"mn":"PT30M","mx":"P1D"}]
525
+
526
+ -- stored and direct agree after the delta merge
527
+ SELECT g, count(*) AS c, min(dur) AS mn, max(dur) AS mx FROM ts_src GROUP BY g ORDER BY g;
528
+ → [{"g":1,"c":4,"mn":"PT30M","mx":"P1D"}]
529
+
530
+ -- (c) a delete of the extreme exercises the tighten residual fallback (min/max
531
+ -- cannot retract arithmetically — the group re-derives from live source state).
532
+ DELETE FROM ts_src WHERE id = 4;
533
+ SELECT g, c, mn, mx FROM ts_mv ORDER BY g;
534
+ → [{"g":1,"c":3,"mn":"PT30M","mx":"PT2H"}]
535
+
536
+ DROP MATERIALIZED VIEW ts_mv;
537
+ DROP TABLE ts_src;
538
+
539
+ -- ============================================================
540
+ -- Semantic ordering reaches a COMPUTED difference, not just a declared column
541
+ --
542
+ -- Everything above orders a column DECLARED timespan. `date - date` produces the
543
+ -- same duration strings, and until the operation table (types/temporal-ops.ts)
544
+ -- gave it a TIMESPAN result type the planner announced DATE — so every ordering
545
+ -- site fell back to text order and disagreed with the `<`/`>` results above.
546
+ -- Each expectation below is a value the old announcement got wrong: text order
547
+ -- ranks 'P15D' before 'P1D' before 'P9D'.
548
+ -- ============================================================
549
+
550
+ CREATE TABLE spans (id INTEGER PRIMARY KEY, a DATE NOT NULL, b DATE NOT NULL);
551
+ INSERT INTO spans VALUES
552
+ (1, '2024-01-20', '2024-01-05'),
553
+ (2, '2024-01-20', '2024-01-11'),
554
+ (3, '2024-01-20', '2024-01-19');
555
+ -- run
556
+
557
+ SELECT id, a - b AS g FROM spans ORDER BY (a - b);
558
+ → [{"id":3,"g":"P1D"},{"id":2,"g":"P9D"},{"id":1,"g":"P15D"}]
559
+
560
+ SELECT min(a - b) AS mn, max(a - b) AS mx FROM spans;
561
+ → [{"mn":"P1D","mx":"P15D"}]
562
+
563
+ SELECT DISTINCT (a - b) AS g FROM spans ORDER BY 1;
564
+ → [{"g":"P1D"},{"g":"P9D"},{"g":"P15D"}]
565
+
566
+ -- the computed difference and a declared TIMESPAN literal rank against each other
567
+ SELECT id FROM spans WHERE (a - b) > timespan('P8D') ORDER BY id;
568
+ → [{"id":1},{"id":2}]
569
+
570
+ -- a materialized view over the computed difference stores and orders it the same way
571
+ CREATE MATERIALIZED VIEW spans_mv AS SELECT id, (a - b) AS g FROM spans;
572
+ -- run
573
+
574
+ SELECT id, g FROM spans_mv ORDER BY g;
575
+ → [{"id":3,"g":"P1D"},{"id":2,"g":"P9D"},{"id":1,"g":"P15D"}]
576
+
577
+ DROP MATERIALIZED VIEW spans_mv;
578
+ DROP TABLE spans;
579
+
580
+ -- ============================================================
581
+ -- Dividing a calendar duration truncates the sub-month remainder
582
+ --
583
+ -- months have no fixed day count, so the remainder cannot cascade to days.
584
+ -- See the NOTE on divideDuration in src/types/temporal-ops.ts.
585
+ -- ============================================================
586
+
587
+ SELECT timespan('P1Y2M') / 2 AS result;
588
+ → [{"result":"P7M"}]
589
+
590
+ SELECT timespan('P1M') / 2 AS result;
591
+ → [{"result":"PT0S"}]
592
+
593
+ -- ============================================================
594
+ -- The three emit-time arms, over COLUMNS
595
+ --
596
+ -- Every case above operates on literals, which constant-fold before a row is ever
597
+ -- scanned. These run the same shapes per row instead, so each of the three arms of
598
+ -- the temporal branch in runtime/emit/binary.ts is exercised where it matters:
599
+ -- arm 1 both declared kinds resolve and the operation table has a case
600
+ -- arm 2 both resolve and the table has NO case (a constant-throw body)
601
+ -- arm 3 a declared type settles nothing, so runtime value sniffing decides
602
+ -- The emitted note for each is asserted in test/runtime/scalar-op-spec.spec.ts.
603
+ -- ============================================================
604
+
605
+ CREATE TABLE arms (
606
+ id INTEGER PRIMARY KEY,
607
+ dt DATE, dt2 DATE,
608
+ sp TIMESPAN, sp2 TIMESPAN,
609
+ txt TEXT,
610
+ n INTEGER
611
+ );
612
+ INSERT INTO arms VALUES
613
+ (1, '2024-01-20', '2024-01-15', 'P1D', 'PT12H', 'PT1H', 2),
614
+ (2, '2024-03-01', '2024-02-01', 'P2D', 'PT6H', 'P3D', 3);
615
+ -- run
616
+
617
+ -- arm 1: DATE + TIMESPAN, case fixed at emit
618
+ SELECT id, dt + sp AS r FROM arms ORDER BY id;
619
+ → [{"id":1,"r":"2024-01-21"},{"id":2,"r":"2024-03-03"}]
620
+
621
+ -- arm 1: DATE - DATE announces TIMESPAN, and the value agrees
622
+ SELECT id, dt - dt2 AS r FROM arms ORDER BY id;
623
+ → [{"id":1,"r":"P5D"},{"id":2,"r":"P29D"}]
624
+
625
+ -- arm 1: TIMESPAN * NUMBER
626
+ SELECT id, sp2 * n AS r FROM arms ORDER BY id;
627
+ → [{"id":1,"r":"PT86400S"},{"id":2,"r":"PT64800S"}]
628
+
629
+ -- arm 3: a TEXT operand settles nothing at emit, so the value decides — and this
630
+ -- value does look like a duration, so the (timespan, timespan) case still applies
631
+ SELECT id, txt + sp AS r FROM arms ORDER BY id;
632
+ → [{"id":1,"r":"P1DT1H"},{"id":2,"r":"P5D"}]
633
+
634
+ -- Deep chain: every level specializes on the level below's announced type.
635
+ -- (dt + sp) is a DATE, minus dt2 is a TIMESPAN, plus sp2 is a TIMESPAN.
636
+ SELECT id, dt + sp - dt2 + sp2 AS r FROM arms ORDER BY id;
637
+ → [{"id":1,"r":"P6DT12H"},{"id":2,"r":"P31DT6H"}]
638
+
639
+ -- ============================================================
640
+ -- arm 1, the rest of the operation table, over COLUMNS
641
+ --
642
+ -- The cases above reach four of the table's entries. The remainder — TIME and
643
+ -- DATETIME shifts, the commuted TIMESPAN-first forms, mixed DATE/DATETIME
644
+ -- differences, and the two division cases — are otherwise pinned only by literal
645
+ -- expressions, which constant-fold before a row is scanned. These run them per row,
646
+ -- so a wrong entry in the emit-time lookup cannot hide behind the folder.
647
+ -- ============================================================
648
+
649
+ CREATE TABLE arms2 (
650
+ id INTEGER PRIMARY KEY,
651
+ dt DATE,
652
+ dtm DATETIME, dtm2 DATETIME,
653
+ tm TIME, tm2 TIME,
654
+ sp TIMESPAN, sp2 TIMESPAN,
655
+ n INTEGER
656
+ );
657
+ INSERT INTO arms2 VALUES
658
+ (1, '2024-01-15', '2024-01-20T08:15:00', '2024-01-10T06:00:00', '10:30:00', '08:00:00', 'PT1H30M', 'PT30M', 3);
659
+ -- run
660
+
661
+ -- TIME ± TIMESPAN, and the commuted TIMESPAN + TIME
662
+ SELECT tm + sp AS a, tm - sp AS b, sp + tm AS c FROM arms2;
663
+ → [{"a":"12:00:00","b":"09:00:00","c":"12:00:00"}]
664
+
665
+ -- DATETIME ± TIMESPAN, and the commuted TIMESPAN + DATETIME
666
+ SELECT dtm + sp AS a, dtm - sp AS b, sp + dtm AS c FROM arms2;
667
+ → [{"a":"2024-01-20T09:45:00","b":"2024-01-20T06:45:00","c":"2024-01-20T09:45:00"}]
668
+
669
+ -- the commuted TIMESPAN + DATE. PT30M carries no whole days, and a DATE has no time
670
+ -- of day to carry them into, so the date is unchanged — the same sub-day truncation
671
+ -- `date('2024-01-15') + timespan('PT30M')` shows as a literal.
672
+ SELECT sp2 + dt AS r FROM arms2;
673
+ → [{"r":"2024-01-15"}]
674
+
675
+ -- TIME - TIME
676
+ SELECT tm - tm2 AS r FROM arms2;
677
+ → [{"r":"PT2H30M"}]
678
+
679
+ -- the three mixed DATE/DATETIME differences, each the full elapsed gap (a DATE reads as midnight)
680
+ SELECT dtm - dtm2 AS a, dtm - dt AS b, dt - dtm2 AS c FROM arms2;
681
+ → [{"a":"P10DT2H15M","b":"P5DT8H15M","c":"P4DT18H"}]
682
+
683
+ -- TIMESPAN ± TIMESPAN
684
+ SELECT sp + sp2 AS a, sp - sp2 AS b FROM arms2;
685
+ → [{"a":"PT2H","b":"PT1H"}]
686
+
687
+ -- TIMESPAN / TIMESPAN announces REAL, TIMESPAN / NUMBER announces TIMESPAN,
688
+ -- and NUMBER * TIMESPAN is the commuted scale case
689
+ SELECT sp / sp2 AS a, sp / n AS b, n * sp AS c FROM arms2;
690
+ → [{"a":3,"b":"PT1800S","c":"PT16200S"}]
691
+
692
+ -- A view body is emitted like any other scalar op, so the specialized arm applies there too
693
+ CREATE VIEW arms2_v AS SELECT id, dtm + sp AS shifted FROM arms2;
694
+ -- run
695
+ SELECT shifted FROM arms2_v;
696
+ → [{"shifted":"2024-01-20T09:45:00"}]
697
+ DROP VIEW arms2_v;
698
+
699
+ DROP TABLE arms2;
700
+
701
+ -- A CHECK constraint is another scalar-op site: the specialized body decides the verdict
702
+ CREATE TABLE arm_check (
703
+ id INTEGER PRIMARY KEY,
704
+ dt DATE,
705
+ sp TIMESPAN,
706
+ CHECK (dt + sp > dt)
707
+ );
708
+ -- run
709
+ INSERT INTO arm_check VALUES (1, '2024-01-15', 'P1D');
710
+ -- run
711
+ SELECT dt + sp AS r FROM arm_check;
712
+ → [{"r":"2024-01-16"}]
713
+
714
+ -- a negative shift moves the date backwards, so the constraint rejects the row
715
+ INSERT INTO arm_check VALUES (2, '2024-01-15', '-P1D');
716
+ -- error: CHECK constraint
717
+
718
+ DROP TABLE arm_check;
719
+
720
+ -- arm 2: no case for DATE + DATE. The throw is per row, not at emit — so a query
721
+ -- that never evaluates the expression still succeeds (next three).
722
+ SELECT id, dt + dt2 AS r FROM arms ORDER BY id;
723
+ -- error: Unsupported temporal operation
724
+
725
+ -- ...guarded by a CASE that never selects it
726
+ SELECT id, CASE WHEN 0 THEN dt + dt2 ELSE 'skipped' END AS r FROM arms ORDER BY id;
727
+ → [{"id":1,"r":"skipped"},{"id":2,"r":"skipped"}]
728
+
729
+ -- ...filtered out before evaluation
730
+ SELECT dt + dt2 AS r FROM arms WHERE 1 = 0;
731
+ → []
732
+
733
+ -- ...or over no rows at all
734
+ CREATE TABLE arms_empty (id INTEGER PRIMARY KEY, dt DATE, dt2 DATE);
735
+ -- run
736
+ SELECT dt + dt2 AS r FROM arms_empty;
737
+ → []
738
+ DROP TABLE arms_empty;
739
+
740
+ -- ============================================================
741
+ -- NULL short-circuits ahead of the arm choice, on all three arms
742
+ --
743
+ -- All three bodies null-check before doing anything else, so a NULL operand is
744
+ -- NULL rather than an error — including on arm 2, where a non-NULL pair throws.
745
+ -- ============================================================
746
+
747
+ CREATE TABLE arm_nulls (id INTEGER PRIMARY KEY, dt DATE NULL, dt2 DATE NULL, sp TIMESPAN NULL, txt TEXT NULL, n INTEGER NULL);
748
+ INSERT INTO arm_nulls VALUES (1, null, null, null, null, null);
749
+ -- run
750
+
751
+ -- arm 1 (date, timespan) with a NULL operand
752
+ SELECT dt + sp AS r FROM arm_nulls;
753
+ → [{"r":null}]
754
+
755
+ -- arm 1 (timespan, number) with a NULL operand
756
+ SELECT sp * n AS r FROM arm_nulls;
757
+ → [{"r":null}]
758
+
759
+ -- arm 2 (date, date) — no case exists, yet NULL still wins over the throw
760
+ SELECT dt + dt2 AS r FROM arm_nulls;
761
+ → [{"r":null}]
762
+
763
+ -- arm 3 (text, date)
764
+ SELECT txt - dt AS r FROM arm_nulls;
765
+ → [{"r":null}]
766
+
767
+ DROP TABLE arm_nulls;
768
+
769
+ -- ============================================================
770
+ -- A bigint on the NUMBER side of `*` / `/`
771
+ --
772
+ -- `sp * big` resolves to the (timespan, number) case at emit, and the case's own
773
+ -- `typeof n === 'number'` guard then rejects the bigint — the same error the
774
+ -- value-sniffed path produced, reached by a different route. This is the one place
775
+ -- that guard is reachable (see the NOTE on scaleTimespan in types/temporal-ops.ts).
776
+ -- ============================================================
777
+
778
+ CREATE TABLE bigmul (id INTEGER PRIMARY KEY, sp TIMESPAN, big INTEGER);
779
+ INSERT INTO bigmul VALUES (1, 'PT1H', 9007199254740993);
780
+ -- run
781
+
782
+ SELECT sp * big AS r FROM bigmul;
783
+ -- error: Unsupported temporal operation
784
+
785
+ SELECT sp / big AS r FROM bigmul;
786
+ -- error: Unsupported temporal operation
787
+
788
+ DROP TABLE bigmul;
789
+
790
+ -- ============================================================
791
+ -- A DATE-declared column cannot hold a value that is not a DATE
792
+ --
793
+ -- The specialized arm trusts the declared type: a DATE-typed operand holding a
794
+ -- non-parseable string would return null where value sniffing raised
795
+ -- `Unsupported temporal operation`. These pin the two ways a caller might try to
796
+ -- manufacture such a value — write-side coercion rejects the insert outright, and a
797
+ -- failed CAST yields NULL rather than the garbage string — so the divergence is not
798
+ -- reachable through SQL. Only a misbehaving virtual table could produce one.
799
+ -- ============================================================
800
+
801
+ CREATE TABLE trust (id INTEGER PRIMARY KEY, dt DATE, sp TIMESPAN);
802
+ -- run
803
+
804
+ INSERT INTO trust VALUES (1, 'garbage', 'PT1H');
805
+ -- error: Cannot convert 'garbage' to DATE
806
+
807
+ INSERT INTO trust VALUES (2, '2024-01-15', 'PT1H');
808
+ -- run
809
+
810
+ -- a failed cast is NULL, so the null check answers before the declared type matters
811
+ SELECT cast('garbage' as DATE) + sp AS r FROM trust;
812
+ → [{"r":null}]
813
+
814
+ DROP TABLE trust;
815
+
816
+ DROP TABLE arms;
817
+
818
+ -- ============================================================
819
+ -- Temporal arithmetic in WHERE clause (ensures dispatch path is exercised)
820
+ -- ============================================================
821
+
822
+ CREATE TABLE events (id INTEGER PRIMARY KEY, dt DATE);
823
+ INSERT INTO events VALUES (1, '2024-01-10'), (2, '2024-01-20'), (3, '2024-02-15');
824
+ -- run
825
+
826
+ -- Filter using date arithmetic
827
+ SELECT id FROM events WHERE dt + timespan('P10D') > date('2024-01-25') ORDER BY id;
828
+ → [{"id":2},{"id":3}]
829
+
830
+ SELECT id FROM events WHERE dt - timespan('P5D') < date('2024-01-10') ORDER BY id;
831
+ → [{"id":1}]
832
+
833
+ DROP TABLE events;