@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,252 @@
1
+ -- Reserved `quereus.*` tag namespace validation (schema/reserved-tags.ts).
2
+ -- PoC wiring: `apply schema X` on a LOGICAL schema validates the reserved tags
3
+ -- on each logical table (`logical-table` site) and its constraints
4
+ -- (`logical-constraint` site) for shape + site. Unknown / mis-sited / malformed
5
+ -- keys fail the deploy loudly; an empty `quereus.lens.ack` rationale is only a
6
+ -- warning (deploy still succeeds). No reserved tag's *semantics* are read here.
7
+
8
+ -- Shared basis: a physical schema the logical schemas align against by name.
9
+ declare schema cars_basis {
10
+ table Car {
11
+ id integer primary key,
12
+ vin text
13
+ }
14
+ }
15
+
16
+ -- run
17
+
18
+ apply schema cars_basis;
19
+
20
+ -- run
21
+
22
+ insert into cars_basis.Car values (1, 'VIN001'), (2, 'VIN002');
23
+
24
+ -- run
25
+
26
+ -- ===================================
27
+ -- 1. Unknown reserved key on a logical table → error at apply
28
+ -- (`quereus.update.taget` is a typo of `target`)
29
+ -- ===================================
30
+
31
+ declare logical schema bad_unknown {
32
+ table Car {
33
+ id integer primary key,
34
+ vin text
35
+ } with tags ("quereus.update.taget" = 'Car')
36
+ }
37
+
38
+ -- run
39
+
40
+ apply schema bad_unknown;
41
+ -- error: unknown reserved tag
42
+
43
+ -- ===================================
44
+ -- 2. Mis-sited reserved key on a logical table → error at apply
45
+ -- (`quereus.lens.writable` is legal only on a logical column, never on the
46
+ -- logical table itself)
47
+ -- ===================================
48
+
49
+ declare logical schema bad_site {
50
+ table Car {
51
+ id integer primary key,
52
+ vin text
53
+ } with tags ("quereus.lens.writable" = true)
54
+ }
55
+
56
+ -- run
57
+
58
+ apply schema bad_site;
59
+ -- error: not allowed
60
+
61
+ -- ===================================
62
+ -- 2b. The retired `quereus.update.default_for.<col>` key → unknown at apply
63
+ -- (the first-class `with defaults (…)` view clause replaced it; a stray
64
+ -- occurrence is an unknown key now, no longer a mis-site)
65
+ -- ===================================
66
+
67
+ declare logical schema bad_retired {
68
+ table Car {
69
+ id integer primary key,
70
+ vin text
71
+ } with tags ("quereus.update.default_for.vin" = '0')
72
+ }
73
+
74
+ -- run
75
+
76
+ apply schema bad_retired;
77
+ -- error: unknown reserved tag
78
+
79
+ -- ===================================
80
+ -- 3. Empty lens.ack rationale → WARNING (deploy succeeds), not an error
81
+ -- ===================================
82
+
83
+ declare logical schema warn_ack {
84
+ table Car {
85
+ id integer primary key,
86
+ vin text
87
+ } with tags ("quereus.lens.ack.no-backing-index:vin" = '')
88
+ }
89
+
90
+ -- run
91
+
92
+ apply schema warn_ack;
93
+
94
+ -- run
95
+
96
+ -- Deploy succeeded despite the empty-rationale warning; reads work.
97
+ select * from warn_ack.Car order by id;
98
+ → [{"id": 1, "vin": "VIN001"}, {"id": 2, "vin": "VIN002"}]
99
+
100
+ -- ===================================
101
+ -- 4. Valid lens.ack at a logical table → no diagnostic; deploy succeeds
102
+ -- ===================================
103
+
104
+ declare logical schema ok_ack {
105
+ table Car {
106
+ id integer primary key,
107
+ vin text
108
+ } with tags ("quereus.lens.ack.no-backing-index:vin" = 'low-write table; commit-time scan is acceptable')
109
+ }
110
+
111
+ -- run
112
+
113
+ apply schema ok_ack;
114
+
115
+ -- run
116
+
117
+ select vin from ok_ack.Car where id = 1;
118
+ → [{"vin": "VIN001"}]
119
+
120
+ -- ===================================
121
+ -- 5. Valid lens.ack on a logical CONSTRAINT → deploy succeeds
122
+ -- ===================================
123
+
124
+ declare logical schema ok_ack_con {
125
+ table Car {
126
+ id integer primary key,
127
+ vin text,
128
+ constraint uq_vin unique (vin) with tags ("quereus.lens.ack.no-backing-index:vin" = 'acceptable')
129
+ }
130
+ }
131
+
132
+ -- run
133
+
134
+ apply schema ok_ack_con;
135
+
136
+ -- run
137
+
138
+ select * from ok_ack_con.Car order by id;
139
+ → [{"id": 1, "vin": "VIN001"}, {"id": 2, "vin": "VIN002"}]
140
+
141
+ -- ===================================
142
+ -- 6. Free-form user tag on a logical table → untouched, deploy succeeds
143
+ -- ===================================
144
+
145
+ declare logical schema user_tag {
146
+ table Car {
147
+ id integer primary key,
148
+ vin text
149
+ } with tags (display_name = 'Cars')
150
+ }
151
+
152
+ -- run
153
+
154
+ apply schema user_tag;
155
+
156
+ -- run
157
+
158
+ select vin from user_tag.Car order by id;
159
+ → [{"vin": "VIN001"}, {"vin": "VIN002"}]
160
+
161
+ -- ===================================
162
+ -- 7. Base-table DML statement tags (`insert/update/delete … with tags (…)`)
163
+ -- validate at the `dml-stmt` site at builder entry — the same hard error
164
+ -- the view-mediated path raises (93.4-view-mutation.sqllogic covers that
165
+ -- path). No reserved key is currently legal at the DML-statement site, so
166
+ -- every `quereus.*` key there is rejected: unknown key →
167
+ -- unknown-reserved-tag; known-but-mis-sited key → tag-not-allowed-here.
168
+ -- Free-form keys pass untouched. A rejected statement writes nothing.
169
+ -- ===================================
170
+
171
+ create table dml_tags (id integer primary key, note text);
172
+
173
+ -- run
174
+
175
+ insert into dml_tags values (1, 'seed');
176
+
177
+ -- run
178
+
179
+ -- unknown reserved key on a base-table INSERT → error; nothing written.
180
+ insert into dml_tags with tags ("quereus.bogus" = 1) values (2, 'x');
181
+ -- error: unknown reserved tag
182
+
183
+ select * from dml_tags order by id;
184
+ → [{"id": 1, "note": "seed"}]
185
+
186
+ -- the retired statement-level `quereus.update.default_for.<col>` key is unknown
187
+ -- on a base-table UPDATE too (the view path already rejects it); row unchanged.
188
+ update dml_tags with tags ("quereus.update.default_for.note" = '0') set note = 'changed' where id = 1;
189
+ -- error: unknown reserved tag
190
+
191
+ select note from dml_tags where id = 1;
192
+ → [{"note": "seed"}]
193
+
194
+ -- a KNOWN reserved key mis-sited on a DML statement → tag-not-allowed-here
195
+ -- (distinct from the unknown-key error); row still present.
196
+ delete from dml_tags with tags ("quereus.id" = 'x') where id = 1;
197
+ -- error: not allowed on a DML statement
198
+
199
+ select count(*) as n from dml_tags;
200
+ → [{"n": 1}]
201
+
202
+ -- free-form statement tags (outside quereus.*) are untouched — the write lands.
203
+ insert into dml_tags with tags (provenance = 'import', audit = true) values (3, 'y');
204
+
205
+ -- run
206
+
207
+ select id from dml_tags order by id;
208
+ → [{"id": 1}, {"id": 3}]
209
+
210
+ -- mixed free-form + reserved still fails atomically — nothing written.
211
+ insert into dml_tags with tags (audit = true, "quereus.bogus" = 1) values (4, 'z');
212
+ -- error: unknown reserved tag
213
+
214
+ select id from dml_tags order by id;
215
+ → [{"id": 1}, {"id": 3}]
216
+
217
+ -- nested DML: a reserved statement tag on DML inside a CTE validates at the
218
+ -- nested statement's own builder entry.
219
+ with w as (insert into dml_tags with tags ("quereus.bogus" = 1) values (5, 'c') returning *) select id from w;
220
+ -- error: unknown reserved tag
221
+
222
+ select id from dml_tags order by id;
223
+ → [{"id": 1}, {"id": 3}]
224
+
225
+ -- DML as INSERT source: the inner statement's reserved tag validates at the
226
+ -- inner statement's own builder entry; neither table is written.
227
+ create table dml_sink (id integer primary key, note text);
228
+
229
+ -- run
230
+
231
+ insert into dml_sink insert into dml_tags with tags ("quereus.bogus" = 1) values (9, 'q') returning *;
232
+ -- error: unknown reserved tag
233
+
234
+ select count(*) as n from dml_sink;
235
+ → [{"n": 0}]
236
+
237
+ select id from dml_tags order by id;
238
+ → [{"id": 1}, {"id": 3}]
239
+
240
+ -- view-mediated write with free-form statement tags: the single-source lowering
241
+ -- clones the statement (tags ride along) and re-enters the base builder, where
242
+ -- re-validation is a no-op — the write lands exactly once.
243
+ create view dml_v as select id, note from dml_tags;
244
+
245
+ -- run
246
+
247
+ insert into dml_v with tags (audit = true) values (7, 'via view');
248
+
249
+ -- run
250
+
251
+ select id from dml_tags order by id;
252
+ → [{"id": 1}, {"id": 3}, {"id": 7}]
@@ -0,0 +1,329 @@
1
+ -- 53.1-materialized-view-write-through.sqllogic — DML targeting a materialized-view
2
+ -- *name* is rewritten to target the MV's source table (write-through via view
3
+ -- updateability) and re-planned through the ordinary base-table builder. The source
4
+ -- write then fires the existing row-time maintenance hook, so the backing is brought
5
+ -- into sync within the same statement/transaction: a subsequent read of the MV sees
6
+ -- the write (reads-own-writes), and a rollback reverts source + backing in lockstep.
7
+ --
8
+ -- A write-through to an MV is observably identical to writing the source and reading
9
+ -- the MV. Modeled on the plain-view 93.4-view-mutation.sqllogic; the per-column
10
+ -- writeability rules (passthrough writeable, computed read-only) and RETURNING
11
+ -- rejection are inherited verbatim from view updateability.
12
+
13
+ -- ===================================
14
+ -- 1. Round-trip (insert / update / delete) through a passthrough MV.
15
+ -- ===================================
16
+
17
+ create table t (id integer primary key, x integer);
18
+ insert into t values (1, 10), (2, 20);
19
+ create materialized view m as select id, x from t;
20
+
21
+ select id, x from m order by id;
22
+ → [{"id":1,"x":10},{"id":2,"x":20}]
23
+
24
+ -- INSERT through the MV lands in the source and is reflected in the MV
25
+ insert into m (id, x) values (3, 30);
26
+ select id, x from m order by id;
27
+ → [{"id":1,"x":10},{"id":2,"x":20},{"id":3,"x":30}]
28
+ select id, x from t order by id;
29
+ → [{"id":1,"x":10},{"id":2,"x":20},{"id":3,"x":30}]
30
+
31
+ -- UPDATE through the MV (a projected column) routes to the source and re-keys the backing
32
+ update m set x = 99 where id = 2;
33
+ select id, x from m order by id;
34
+ → [{"id":1,"x":10},{"id":2,"x":99},{"id":3,"x":30}]
35
+
36
+ -- DELETE through the MV removes the source row and its backing entry
37
+ delete from m where id = 1;
38
+ select id, x from m order by id;
39
+ → [{"id":2,"x":99},{"id":3,"x":30}]
40
+
41
+ -- ===================================
42
+ -- 2. Reads-own-writes + rollback in lockstep. A write through the MV inside an open
43
+ -- transaction is visible to a later read of the MV before commit, and rollback
44
+ -- discards BOTH the source write and the backing delta.
45
+ -- ===================================
46
+
47
+ begin;
48
+ insert into m (id, x) values (4, 40);
49
+ -- reads-own-writes: the write is visible through the MV mid-transaction
50
+ select id, x from m order by id;
51
+ → [{"id":2,"x":99},{"id":3,"x":30},{"id":4,"x":40}]
52
+ rollback;
53
+ -- rollback reverts the source AND the backing together
54
+ select id, x from m order by id;
55
+ → [{"id":2,"x":99},{"id":3,"x":30}]
56
+ select id, x from t order by id;
57
+ → [{"id":2,"x":99},{"id":3,"x":30}]
58
+
59
+ -- a committed write-through persists
60
+ begin;
61
+ insert into m (id, x) values (5, 50);
62
+ commit;
63
+ select id, x from m order by id;
64
+ → [{"id":2,"x":99},{"id":3,"x":30},{"id":5,"x":50}]
65
+
66
+ -- ===================================
67
+ -- 3. Rename / reorder projection — the rewrite maps each MV column to its base column.
68
+ -- ===================================
69
+
70
+ create table u (uid integer primary key, name text);
71
+ insert into u values (1, 'Ann');
72
+ create materialized view uv as select uid as user_id, name as full_name from u;
73
+ select user_id, full_name from uv order by user_id;
74
+ → [{"user_id":1,"full_name":"Ann"}]
75
+
76
+ insert into uv (user_id, full_name) values (2, 'Bo');
77
+ update uv set full_name = 'Bob' where user_id = 2;
78
+ select user_id, full_name from uv order by user_id;
79
+ → [{"user_id":1,"full_name":"Ann"},{"user_id":2,"full_name":"Bob"}]
80
+ -- the writes landed on the base under the base column names
81
+ select uid, name from u order by uid;
82
+ → [{"uid":1,"name":"Ann"},{"uid":2,"name":"Bob"}]
83
+
84
+ -- ===================================
85
+ -- 4. Filtered MV (equality predicate on a projected column): constant-FD default for
86
+ -- an omitted predicate column, predicate-scope transition on update, and a
87
+ -- plan-time predicate-contradiction rejection.
88
+ -- ===================================
89
+
90
+ create table task (id integer primary key, x integer, status text);
91
+ insert into task values (1, 10, 'open'), (2, 20, 'open'), (3, 30, 'closed');
92
+ create materialized view opentasks as select id, x, status from task where status = 'open';
93
+ select id, x, status from opentasks order by id;
94
+ → [{"id":1,"x":10,"status":"open"},{"id":2,"x":20,"status":"open"}]
95
+
96
+ -- INSERT omitting the predicate column: the selection predicate supplies status='open'
97
+ -- on the base via the constant-FD path
98
+ insert into opentasks (id, x) values (4, 40);
99
+ select id, x, status from opentasks order by id;
100
+ → [{"id":1,"x":10,"status":"open"},{"id":2,"x":20,"status":"open"},{"id":4,"x":40,"status":"open"}]
101
+ -- the base row carries the defaulted predicate value
102
+ select id, status from task where id = 4;
103
+ → [{"id":4,"status":"open"}]
104
+
105
+ -- INSERT that provably contradicts the selection predicate is rejected at plan time
106
+ insert into opentasks (id, x, status) values (5, 50, 'closed');
107
+ -- error: contradicts its selection predicate
108
+
109
+ -- UPDATE carrying a row out of the WHERE scope removes it from the MV (maintenance
110
+ -- predicate-scope transition: delete old image, no new image upserted); the base row
111
+ -- survives with its new value
112
+ update opentasks set status = 'closed' where id = 1;
113
+ select id, x, status from opentasks order by id;
114
+ → [{"id":2,"x":20,"status":"open"},{"id":4,"x":40,"status":"open"}]
115
+ select id, status from task where id = 1;
116
+ → [{"id":1,"status":"closed"}]
117
+
118
+ -- ===================================
119
+ -- 5. Delete identity by a non-PK projected column removes exactly the matching backing
120
+ -- row(s). The projection includes the source PK, so the base delete is exact.
121
+ -- ===================================
122
+
123
+ create table d (id integer primary key, label text, x integer);
124
+ insert into d values (1, 'a', 10), (2, 'b', 20), (3, 'a', 30);
125
+ create materialized view dv as select id, label, x from d;
126
+ delete from dv where label = 'a';
127
+ select id, label, x from dv order by id;
128
+ → [{"id":2,"label":"b","x":20}]
129
+ select id, label from d order by id;
130
+ → [{"id":2,"label":"b"}]
131
+
132
+ -- ===================================
133
+ -- 6. RETURNING through an MV is shipped (inherited from view updateability — an MV
134
+ -- is a single-source projection, so the rewrite carries the RETURNING onto the
135
+ -- base op). The deleted view-projected row is returned (`*` → all view columns,
136
+ -- OLD image).
137
+ -- ===================================
138
+
139
+ create table r (id integer primary key, x integer);
140
+ insert into r values (1, 10);
141
+ create materialized view rv as select id, x from r;
142
+ delete from rv where id = 1 returning *;
143
+ → [{"id":1,"x":10}]
144
+
145
+ -- ===================================
146
+ -- 7. Per-column lineage on the MV write-through spine (the single-source spine, so
147
+ -- it consumes inverses exactly as a plain view does): an INVERSE-profile column
148
+ -- (`y = x + 1`) is writable and stores the inverted base value, an OPAQUE column
149
+ -- (`z = x * 2`) is read-only (computed/non-invertible diagnostic), reads are
150
+ -- unaffected, and a write to the passthrough column still propagates. Every write
151
+ -- re-derives the computed columns via maintenance (reads-own-writes).
152
+ -- (Needs materialized-view-rowtime-expression-projections so the body is creatable.)
153
+ -- ===================================
154
+
155
+ create table e (id integer primary key, x integer);
156
+ insert into e values (1, 10), (2, 20);
157
+ create materialized view ev as select id, x, x + 1 as y, x * 2 as z from e;
158
+ select id, x, y, z from ev order by id;
159
+ → [{"id":1,"x":10,"y":11,"z":20},{"id":2,"x":20,"y":21,"z":40}]
160
+
161
+ -- a write to the OPAQUE column z is rejected (read-only / non-invertible)
162
+ update ev set z = 99 where id = 1;
163
+ -- error: non-invertible
164
+
165
+ -- a write to the INVERSE-profile column y now propagates: it stores the inverted
166
+ -- base value (y = 99 ⇒ x = 98) and the computed columns re-derive (z = 196).
167
+ update ev set y = 99 where id = 1;
168
+ select id, x, y, z from ev order by id;
169
+ → [{"id":1,"x":98,"y":99,"z":196},{"id":2,"x":20,"y":21,"z":40}]
170
+
171
+ -- a write to the passthrough column still propagates; the computed columns re-derive
172
+ update ev set x = 100 where id = 1;
173
+ select id, x, y, z from ev order by id;
174
+ → [{"id":1,"x":100,"y":101,"z":200},{"id":2,"x":20,"y":21,"z":40}]
175
+
176
+ -- insert specifying only the passthrough columns works; y/z are derived by maintenance
177
+ insert into ev (id, x) values (3, 30);
178
+ select id, x, y, z from ev order by id;
179
+ → [{"id":1,"x":100,"y":101,"z":200},{"id":2,"x":20,"y":21,"z":40},{"id":3,"x":30,"y":31,"z":60}]
180
+
181
+ -- ===================================
182
+ -- 8. Bulk multi-row write-through — an INSERT…SELECT source, a multi-row UPDATE, and a
183
+ -- multi-row DELETE all produce correct backing contents under per-statement
184
+ -- maintenance batching.
185
+ -- ===================================
186
+
187
+ create table b (id integer primary key, x integer);
188
+ insert into b values (1, 1);
189
+ create materialized view bv as select id, x from b;
190
+
191
+ create table src (id integer primary key, x integer);
192
+ insert into src values (10, 100), (11, 110), (12, 120);
193
+
194
+ -- INSERT … SELECT through the MV
195
+ insert into bv select id, x from src;
196
+ select id, x from bv order by id;
197
+ → [{"id":1,"x":1},{"id":10,"x":100},{"id":11,"x":110},{"id":12,"x":120}]
198
+
199
+ -- multi-row UPDATE through the MV
200
+ update bv set x = x + 1000 where id >= 10;
201
+ select id, x from bv order by id;
202
+ → [{"id":1,"x":1},{"id":10,"x":1100},{"id":11,"x":1110},{"id":12,"x":1120}]
203
+
204
+ -- multi-row DELETE through the MV
205
+ delete from bv where id >= 11;
206
+ select id, x from bv order by id;
207
+ → [{"id":1,"x":1},{"id":10,"x":1100}]
208
+
209
+ -- ===================================
210
+ -- 9. MV-over-MV write-through. Write-through to a level-1 MV over a real table routes
211
+ -- to the base AND cascades to the level-2 MV. Write-through to the level-2 MV
212
+ -- itself (whose source is a materialized view) is rejected cleanly — its rewrite
213
+ -- would target the inner MV's read-only backing table. (The source→backing
214
+ -- maintenance cascade is the read/maintain direction and is unaffected.)
215
+ -- ===================================
216
+
217
+ create table base (id integer primary key, x integer);
218
+ insert into base values (1, 10);
219
+ create materialized view inner_mv as select id, x from base;
220
+ create materialized view outer_mv as select id, x from inner_mv;
221
+
222
+ -- write-through to the level-1 MV routes to base and cascades to the level-2 MV
223
+ insert into inner_mv (id, x) values (2, 20);
224
+ select id, x from outer_mv order by id;
225
+ → [{"id":1,"x":10},{"id":2,"x":20}]
226
+
227
+ -- write-through to the level-2 MV (source is a materialized view) is rejected
228
+ insert into outer_mv (id, x) values (3, 30);
229
+ -- error: reads a materialized view
230
+ update outer_mv set x = 99 where id = 1;
231
+ -- error: reads a materialized view
232
+ delete from outer_mv where id = 1;
233
+ -- error: reads a materialized view
234
+
235
+ -- the rejected writes changed nothing; the chain is intact
236
+ select id, x from outer_mv order by id;
237
+ → [{"id":1,"x":10},{"id":2,"x":20}]
238
+
239
+ -- ===================================
240
+ -- 10. Plain view over a materialized view — the same guard's broader reach. A plain
241
+ -- `view ... select ... from <mv>` resolves its body source to the MV's backing
242
+ -- table at plan time, so a write-through would target that read-only backing.
243
+ -- Write-through is rejected with the same diagnostic as the MV-over-MV case
244
+ -- (this closes a pre-existing latent hole, not just the MV path). Reads through
245
+ -- the plain view are unaffected.
246
+ -- ===================================
247
+
248
+ -- inner_mv from §9 still holds {1,10},{2,20}
249
+ create view pv as select id, x from inner_mv;
250
+ select id, x from pv order by id;
251
+ → [{"id":1,"x":10},{"id":2,"x":20}]
252
+
253
+ insert into pv (id, x) values (4, 40);
254
+ -- error: reads a materialized view
255
+ update pv set x = 99 where id = 1;
256
+ -- error: reads a materialized view
257
+ delete from pv where id = 1;
258
+ -- error: reads a materialized view
259
+
260
+ -- the rejected writes changed nothing
261
+ select id, x from pv order by id;
262
+ → [{"id":1,"x":10},{"id":2,"x":20}]
263
+
264
+ -- ===================================
265
+ -- 11. Aggregate (non-updatable) body. An aggregate-bodied MV is creatable and
266
+ -- maintained (the residual-recompute arm), but its body is NOT row-decomposable
267
+ -- for write-through, so user DML against the MV name is rejected at PLAN time.
268
+ -- The diagnostic names the target as a *materialized view* (not a plain "view") —
269
+ -- the body-shape reject threads the target's kind. The reject is plan-time, so
270
+ -- the MV contents are untouched and the source stays directly writable + maintained.
271
+ -- (Runs in both memory and store suites; the 'x'/'y' group keys carry no
272
+ -- case-variant collision, so the store's NOCASE backing-key default is moot.)
273
+ -- ===================================
274
+
275
+ create table words (id integer primary key, w text);
276
+ insert into words values (1, 'x'), (2, 'y'), (3, 'x');
277
+ create materialized view wcount as select w, count(*) as n from words group by w;
278
+ select w, n from wcount order by w;
279
+ → [{"w":"x","n":2},{"w":"y","n":1}]
280
+
281
+ -- insert / update / delete against the aggregate MV are all rejected at plan time,
282
+ -- naming it a materialized view
283
+ insert into wcount (w, n) values ('z', 1);
284
+ -- error: cannot write through materialized view
285
+ update wcount set n = 99 where w = 'x';
286
+ -- error: cannot write through materialized view
287
+ delete from wcount where w = 'y';
288
+ -- error: cannot write through materialized view
289
+
290
+ -- the rejected writes changed nothing
291
+ select w, n from wcount order by w;
292
+ → [{"w":"x","n":2},{"w":"y","n":1}]
293
+
294
+ -- the source remains directly writable and the MV maintains incrementally
295
+ insert into words values (4, 'y');
296
+ select w, n from wcount order by w;
297
+ → [{"w":"x","n":2},{"w":"y","n":2}]
298
+
299
+ -- ===================================
300
+ -- 12. Subquery-in-FROM body. An MV whose body wraps its base in a derived-table
301
+ -- subquery is creatable + maintained, but write-through rejects it at the
302
+ -- single-base-source branch (the inner filters/projections live in the plan,
303
+ -- not in the rewrite-driving selectAst). That branch — distinct from the
304
+ -- aggregate (classifyViewBody) reject in § 11 — must ALSO name the target a
305
+ -- *materialized view*, not a plain "view": every body-shape reject in
306
+ -- analyzeView threads the target's kind, so a maintained table reaching this
307
+ -- branch is not misnamed. Plan-time reject; MV contents untouched.
308
+ -- ===================================
309
+
310
+ create table nums (id integer primary key, v integer);
311
+ insert into nums values (1, 10), (2, 20);
312
+ create materialized view sqmv as select id, v from (select id, v from nums);
313
+ select id, v from sqmv order by id;
314
+ → [{"id":1,"v":10},{"id":2,"v":20}]
315
+
316
+ -- write-through is rejected at the single-base-source branch, naming it a materialized view
317
+ insert into sqmv (id, v) values (3, 30);
318
+ -- error: cannot write through materialized view
319
+ update sqmv set v = 99 where id = 1;
320
+ -- error: cannot write through materialized view
321
+ delete from sqmv where id = 2;
322
+ -- error: cannot write through materialized view
323
+
324
+ -- the rejected writes changed nothing; the source stays writable + maintained
325
+ select id, v from sqmv order by id;
326
+ → [{"id":1,"v":10},{"id":2,"v":20}]
327
+ insert into nums values (3, 30);
328
+ select id, v from sqmv order by id;
329
+ → [{"id":1,"v":10},{"id":2,"v":20},{"id":3,"v":30}]