@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,1468 @@
1
+ -- Authored inverses at the lens boundary (docs/lens.md § Computed and
2
+ -- Generated Columns; docs/vu-inverses.md § Authored inverses;
3
+ -- ticket `authored-inverse-lens-prover`).
4
+ --
5
+ -- Covers the prover's law treatment for `with inverse` columns through the full
6
+ -- SQL pipeline: the acknowledgeable `lens.getput-lossy` advisory (+ ack and
7
+ -- escalation governance), the `lens.putget-violation` hard error for an inverse
8
+ -- the forward provably does not reproduce, the bijective-enumeration advisory
9
+ -- suppression, the `inverse` disposition column on quereus_effective_lens, and
10
+ -- writable-intent satisfaction by an authored inverse. (Fingerprint mechanics
11
+ -- are unit-tested in test/lens-ack.spec.ts.)
12
+
13
+ -- ===================================
14
+ -- 1. Code-collapse lens: a non-injective forward with an authored inverse
15
+ -- deploys with the lens.getput-lossy advisory; PutGet holds by enumeration;
16
+ -- write-through normalizes the basis value (GetPut surrendered).
17
+ -- ===================================
18
+
19
+ declare schema ai1b {
20
+ table Item (
21
+ id integer primary key,
22
+ code text not null check (code in ('A1', 'A2', 'B1', 'B2', 'C1'))
23
+ )
24
+ }
25
+
26
+ -- run
27
+
28
+ apply schema ai1b;
29
+
30
+ -- run
31
+
32
+ insert into ai1b.Item values (1, 'A2'), (2, 'B2');
33
+
34
+ -- run
35
+
36
+ declare logical schema ai1x {
37
+ table Item (
38
+ id integer primary key,
39
+ grp text null check (grp in ('A', 'B', 'C'))
40
+ )
41
+ }
42
+
43
+ -- run
44
+
45
+ declare lens for ai1x over ai1b {
46
+ view Item as select id, substr(code, 1, 1) as grp
47
+ with inverse (code = new.grp || '1')
48
+ from ai1b.Item
49
+ }
50
+
51
+ -- run
52
+
53
+ apply schema ai1x;
54
+
55
+ -- run
56
+
57
+ -- The advisory fires, sited at the authored column.
58
+ select code, "column", status from quereus_lens_advisories('ai1x') where code = 'lens.getput-lossy';
59
+ → [{"code": "lens.getput-lossy", "column": "grp", "status": "active"}]
60
+
61
+ -- Reads collapse the basis codes through the forward.
62
+ select * from ai1x.Item order by id;
63
+ → [{"id": 1, "grp": "A"}, {"id": 2, "grp": "B"}]
64
+
65
+ -- effective-lens reports the authored disposition.
66
+ select logical_column, inverse from quereus_effective_lens('ai1x', 'Item') order by logical_column;
67
+ → [{"logical_column": "grp", "inverse": "authored"}, {"logical_column": "id", "inverse": "inferred"}]
68
+
69
+ -- run
70
+
71
+ -- UPDATE lowers through the authored put.
72
+ update ai1x.Item set grp = 'C' where id = 1;
73
+ select code from ai1b.Item where id = 1;
74
+ → [{"code": "C1"}]
75
+
76
+ -- GetPut surrendered: writing the read value back normalizes B2 → B1 (the
77
+ -- inverse's representative) — exactly what the advisory warns about.
78
+ update ai1x.Item set grp = grp where id = 2;
79
+ select code from ai1b.Item where id = 2;
80
+ → [{"code": "B1"}]
81
+
82
+ -- INSERT evaluates the put per supplied row.
83
+ insert into ai1x.Item (id, grp) values (3, 'A');
84
+ select code from ai1b.Item where id = 3;
85
+ → [{"code": "A1"}]
86
+
87
+ -- run
88
+
89
+ -- The logical CHECK is enforced at the lens boundary over the written image.
90
+ insert into ai1x.Item (id, grp) values (4, 'Z');
91
+ -- error: check
92
+
93
+ -- ===================================
94
+ -- 2. An in-source ack suppresses the advisory (unconditional — no fingerprint)
95
+ -- ===================================
96
+
97
+ declare logical schema ai2x {
98
+ table Item (
99
+ id integer primary key,
100
+ grp text null check (grp in ('A', 'B', 'C'))
101
+ ) with tags (
102
+ "quereus.lens.ack.getput-lossy:grp" = 'collapse to the 1-suffix representative is intentional'
103
+ )
104
+ }
105
+
106
+ -- run
107
+
108
+ declare lens for ai2x over ai1b {
109
+ view Item as select id, substr(code, 1, 1) as grp
110
+ with inverse (code = new.grp || '1')
111
+ from ai1b.Item
112
+ }
113
+
114
+ -- run
115
+
116
+ apply schema ai2x;
117
+
118
+ -- run
119
+
120
+ select code, status, rationale from quereus_lens_advisories('ai2x') where code = 'lens.getput-lossy';
121
+ → [{"code": "lens.getput-lossy", "status": "acknowledged-unconditional", "rationale": "collapse to the 1-suffix representative is intentional"}]
122
+
123
+ -- ===================================
124
+ -- 3. Escalation: require-ack makes the un-acknowledged advisory a deploy error
125
+ -- ===================================
126
+
127
+ declare logical schema ai3x {
128
+ table Item (
129
+ id integer primary key,
130
+ grp text null check (grp in ('A', 'B', 'C'))
131
+ ) with tags (
132
+ "quereus.lens.policy.require-ack" = 'lens.getput-lossy'
133
+ )
134
+ }
135
+
136
+ -- run
137
+
138
+ declare lens for ai3x over ai1b {
139
+ view Item as select id, substr(code, 1, 1) as grp
140
+ with inverse (code = new.grp || '1')
141
+ from ai1b.Item
142
+ }
143
+
144
+ -- run
145
+
146
+ apply schema ai3x;
147
+ -- error: lens.getput-lossy
148
+
149
+ -- ===================================
150
+ -- 4. Escalation: error-on is a hard error an ack cannot suppress
151
+ -- ===================================
152
+
153
+ declare logical schema ai4x {
154
+ table Item (
155
+ id integer primary key,
156
+ grp text null check (grp in ('A', 'B', 'C'))
157
+ ) with tags (
158
+ "quereus.lens.policy.error-on" = 'lens.getput-lossy',
159
+ "quereus.lens.ack.getput-lossy:grp" = 'attempted suppression of a hard policy'
160
+ )
161
+ }
162
+
163
+ -- run
164
+
165
+ declare lens for ai4x over ai1b {
166
+ view Item as select id, substr(code, 1, 1) as grp
167
+ with inverse (code = new.grp || '1')
168
+ from ai1b.Item
169
+ }
170
+
171
+ -- run
172
+
173
+ apply schema ai4x;
174
+ -- error: lens.getput-lossy
175
+
176
+ -- ===================================
177
+ -- 5. A deliberately wrong inverse reds lens.putget-violation at deploy:
178
+ -- inverse('A') = 'B1' but forward('B1') = 'B' ≠ 'A'.
179
+ -- ===================================
180
+
181
+ declare logical schema ai5x {
182
+ table Item (
183
+ id integer primary key,
184
+ grp text null check (grp in ('A', 'B'))
185
+ )
186
+ }
187
+
188
+ -- run
189
+
190
+ declare lens for ai5x over ai1b {
191
+ view Item as select id, substr(code, 1, 1) as grp
192
+ with inverse (code = case new.grp when 'A' then 'B1' else new.grp || '1' end)
193
+ from ai1b.Item
194
+ }
195
+
196
+ -- run
197
+
198
+ apply schema ai5x;
199
+ -- error: lens.putget-violation
200
+
201
+ -- ===================================
202
+ -- 6. A bijective enumerable mapping emits no advisory (forward proved injective
203
+ -- over the basis CHECK domain, image inside the logical domain) — and GetPut
204
+ -- operationally holds: write-back leaves the basis unchanged.
205
+ -- ===================================
206
+
207
+ declare schema ai6b {
208
+ table Item (
209
+ id integer primary key,
210
+ code text not null check (code in ('a', 'b', 'c'))
211
+ )
212
+ }
213
+
214
+ -- run
215
+
216
+ apply schema ai6b;
217
+
218
+ -- run
219
+
220
+ insert into ai6b.Item values (1, 'b');
221
+
222
+ -- run
223
+
224
+ declare logical schema ai6x {
225
+ table Item (
226
+ id integer primary key,
227
+ grp text null check (grp in ('A', 'B', 'C'))
228
+ )
229
+ }
230
+
231
+ -- run
232
+
233
+ declare lens for ai6x over ai6b {
234
+ view Item as select id, upper(code) as grp
235
+ with inverse (code = lower(new.grp))
236
+ from ai6b.Item
237
+ }
238
+
239
+ -- run
240
+
241
+ apply schema ai6x;
242
+
243
+ -- run
244
+
245
+ select count(*) as n from quereus_lens_advisories('ai6x') where code = 'lens.getput-lossy';
246
+ → [{"n": 0}]
247
+
248
+ -- GetPut: writing the read value back leaves the basis byte-identical.
249
+ update ai6x.Item set grp = grp where id = 1;
250
+ select code from ai6b.Item where id = 1;
251
+ → [{"code": "b"}]
252
+
253
+ -- PutGet write-through.
254
+ update ai6x.Item set grp = 'C' where id = 1;
255
+ select code from ai6b.Item where id = 1;
256
+ → [{"code": "c"}]
257
+
258
+ -- ===================================
259
+ -- 7. effective-lens `inverse` dispositions across a mixed table:
260
+ -- authored / inferred (covered + gap-filled) / none (computed, read-only).
261
+ -- ===================================
262
+
263
+ declare schema ai7b {
264
+ table T (
265
+ id integer primary key,
266
+ name text null,
267
+ code text not null check (code in ('a', 'b'))
268
+ )
269
+ }
270
+
271
+ -- run
272
+
273
+ apply schema ai7b;
274
+
275
+ -- run
276
+
277
+ insert into ai7b.T values (1, 'ada', 'a');
278
+
279
+ -- run
280
+
281
+ declare logical schema ai7x {
282
+ table T (
283
+ id integer primary key,
284
+ name text null,
285
+ grp text null check (grp in ('A', 'B')),
286
+ shout text null
287
+ )
288
+ }
289
+
290
+ -- run
291
+
292
+ -- `name` is gap-filled (identity ⇒ inferred); `shout` is computed with no
293
+ -- inverse (none); `grp` carries the authored put (authored).
294
+ declare lens for ai7x over ai7b {
295
+ view T as select id, upper(code) as grp
296
+ with inverse (code = lower(new.grp)),
297
+ upper(name) as shout
298
+ from ai7b.T
299
+ }
300
+
301
+ -- run
302
+
303
+ apply schema ai7x;
304
+
305
+ -- run
306
+
307
+ select logical_column, source, inverse from quereus_effective_lens('ai7x', 'T') order by logical_column;
308
+ → [{"logical_column": "grp", "source": "override", "inverse": "authored"}, {"logical_column": "id", "source": "override", "inverse": "inferred"}, {"logical_column": "name", "source": "default", "inverse": "inferred"}, {"logical_column": "shout", "source": "override", "inverse": "none"}]
309
+
310
+ -- run
311
+
312
+ select * from ai7x.T;
313
+ → [{"id": 1, "name": "ada", "grp": "A", "shout": "ADA"}]
314
+
315
+ -- ===================================
316
+ -- 8. quereus.lens.writable = true is satisfied by an authored inverse — no
317
+ -- lens.non-invertible (the column is writable through the supplied put).
318
+ -- ===================================
319
+
320
+ declare schema ai8b {
321
+ table Core (
322
+ id integer primary key,
323
+ speed integer not null
324
+ )
325
+ }
326
+
327
+ -- run
328
+
329
+ apply schema ai8b;
330
+
331
+ -- run
332
+
333
+ insert into ai8b.Core values (1, 30);
334
+
335
+ -- run
336
+
337
+ declare logical schema ai8x {
338
+ table Car (
339
+ id integer primary key,
340
+ mph integer null with tags ("quereus.lens.writable" = true)
341
+ )
342
+ }
343
+
344
+ -- run
345
+
346
+ declare lens for ai8x over ai8b {
347
+ view Car as select id, speed * 3 as mph
348
+ with inverse (speed = new.mph / 3)
349
+ from ai8b.Core
350
+ }
351
+
352
+ -- run
353
+
354
+ apply schema ai8x;
355
+
356
+ -- run
357
+
358
+ select * from ai8x.Car;
359
+ → [{"id": 1, "mph": 90}]
360
+
361
+ update ai8x.Car set mph = 120 where id = 1;
362
+ select speed from ai8b.Core where id = 1;
363
+ → [{"speed": 40}]
364
+
365
+ -- ===================================
366
+ -- 9. Out-of-fragment body (join) + authored inverse + writable intent:
367
+ -- degrade-to-safe holds — no branch fires (no lens.non-invertible, no
368
+ -- advisory), the documented completeness gap is not regressed.
369
+ -- ===================================
370
+
371
+ declare schema ai9b {
372
+ table Core (
373
+ id integer primary key,
374
+ code text not null
375
+ )
376
+ table Aux (
377
+ id integer primary key,
378
+ tag text null
379
+ )
380
+ }
381
+
382
+ -- run
383
+
384
+ apply schema ai9b;
385
+
386
+ -- run
387
+
388
+ insert into ai9b.Core values (1, 'x');
389
+ insert into ai9b.Aux values (1, 't');
390
+
391
+ -- run
392
+
393
+ declare logical schema ai9x {
394
+ table V (
395
+ id integer primary key,
396
+ label text null with tags ("quereus.lens.writable" = true)
397
+ )
398
+ }
399
+
400
+ -- run
401
+
402
+ declare lens for ai9x over ai9b {
403
+ view V as select Core.id as id, upper(Core.code) as label
404
+ with inverse (code = lower(new.label))
405
+ from ai9b.Core inner join ai9b.Aux on Core.id = Aux.id
406
+ }
407
+
408
+ -- run
409
+
410
+ apply schema ai9x;
411
+
412
+ -- run
413
+
414
+ select count(*) as n from quereus_lens_advisories('ai9x') where code = 'lens.getput-lossy';
415
+ → [{"n": 0}]
416
+
417
+ select * from ai9x.V;
418
+ → [{"id": 1, "label": "X"}]
419
+
420
+ -- ===================================
421
+ -- 10. A non-constant-foldable inverse (subquery) over an enumerable domain
422
+ -- degrades to safe — deploys with the advisory, never a crash; the
423
+ -- mutation-time lowering still consumes the subquery put.
424
+ -- ===================================
425
+
426
+ declare schema ai10b {
427
+ table Item (
428
+ id integer primary key,
429
+ code text not null
430
+ )
431
+ table Lk (
432
+ grp text primary key,
433
+ rep text not null
434
+ )
435
+ }
436
+
437
+ -- run
438
+
439
+ apply schema ai10b;
440
+
441
+ -- run
442
+
443
+ insert into ai10b.Item values (1, 'A1');
444
+ insert into ai10b.Lk values ('A', 'A1'), ('B', 'B1');
445
+
446
+ -- run
447
+
448
+ declare logical schema ai10x {
449
+ table Item (
450
+ id integer primary key,
451
+ grp text null check (grp in ('A', 'B'))
452
+ )
453
+ }
454
+
455
+ -- run
456
+
457
+ declare lens for ai10x over ai10b {
458
+ view Item as select id, substr(code, 1, 1) as grp
459
+ with inverse (code = (select rep from ai10b.Lk where Lk.grp = new.grp))
460
+ from ai10b.Item
461
+ }
462
+
463
+ -- run
464
+
465
+ apply schema ai10x;
466
+
467
+ -- run
468
+
469
+ -- Degrade-to-safe: the composition is not const-foldable, so PutGet is
470
+ -- unverified (no error) and the advisory stands (not proved bijective).
471
+ select code, status from quereus_lens_advisories('ai10x') where code = 'lens.getput-lossy';
472
+ → [{"code": "lens.getput-lossy", "status": "active"}]
473
+
474
+ -- The mutation-time put still evaluates the subquery per write.
475
+ update ai10x.Item set grp = 'B' where id = 1;
476
+ select code from ai10b.Item where id = 1;
477
+ → [{"code": "B1"}]
478
+
479
+ -- ===================================
480
+ -- 11. Bijectivity suppression requires the inverse's images to land INSIDE the
481
+ -- basis domain. Here PutGet holds ('z' hits the forward's else arm) and the
482
+ -- forward alone is injective over the basis domain ('a'→'A', 'b'→'B'), but
483
+ -- inverse('B') = 'z' escapes the basis CHECK — the pair is not a bijection
484
+ -- (GetPut fails for stored 'b'), so the advisory must stand.
485
+ -- ===================================
486
+
487
+ declare schema ai11b {
488
+ table Item (
489
+ id integer primary key,
490
+ code text not null check (code in ('a', 'b'))
491
+ )
492
+ }
493
+
494
+ -- run
495
+
496
+ apply schema ai11b;
497
+
498
+ -- run
499
+
500
+ insert into ai11b.Item values (1, 'b');
501
+
502
+ -- run
503
+
504
+ declare logical schema ai11x {
505
+ table Item (
506
+ id integer primary key,
507
+ grp text null check (grp in ('A', 'B'))
508
+ )
509
+ }
510
+
511
+ -- run
512
+
513
+ declare lens for ai11x over ai11b {
514
+ view Item as select id, case code when 'a' then 'A' else 'B' end as grp
515
+ with inverse (code = case new.grp when 'A' then 'a' else 'z' end)
516
+ from ai11b.Item
517
+ }
518
+
519
+ -- run
520
+
521
+ apply schema ai11x;
522
+
523
+ -- run
524
+
525
+ select code, "column", status from quereus_lens_advisories('ai11x') where code = 'lens.getput-lossy';
526
+ → [{"code": "lens.getput-lossy", "column": "grp", "status": "active"}]
527
+
528
+ -- The surrendered GetPut is operationally visible: write-back of the read
529
+ -- value puts 'z', which the basis CHECK rejects.
530
+ update ai11x.Item set grp = grp where id = 1;
531
+ -- error: check
532
+
533
+ -- ===================================
534
+ -- 12. A logical CHECK over an authored column on a join body reds
535
+ -- lens.unrealizable-constraint at deploy: the forward substitution is
536
+ -- row-local only on a single-source body. (Here the forward happens to read
537
+ -- only the put member — a conservative over-block — but the slot AST cannot
538
+ -- prove that, and a cross-side forward would otherwise deploy a CHECK that
539
+ -- silently never enforces; see the next scenario's shape.)
540
+ -- ===================================
541
+
542
+ declare schema ai12b {
543
+ table Core (
544
+ id integer primary key,
545
+ code text not null
546
+ )
547
+ table Aux (
548
+ id integer primary key,
549
+ tag text null
550
+ )
551
+ }
552
+
553
+ -- run
554
+
555
+ apply schema ai12b;
556
+
557
+ -- run
558
+
559
+ insert into ai12b.Core values (1, 'x');
560
+ insert into ai12b.Aux values (1, 't');
561
+
562
+ -- run
563
+
564
+ declare logical schema ai12x {
565
+ table V (
566
+ id integer primary key,
567
+ label text null check (label in ('X', 'Y'))
568
+ )
569
+ }
570
+
571
+ -- run
572
+
573
+ declare lens for ai12x over ai12b {
574
+ view V as select Core.id as id, upper(Core.code) as label
575
+ with inverse (code = lower(new.label))
576
+ from ai12b.Core inner join ai12b.Aux on Core.id = Aux.id
577
+ }
578
+
579
+ -- run
580
+
581
+ apply schema ai12x;
582
+ -- error: lens.unrealizable-constraint
583
+
584
+ -- ===================================
585
+ -- 13. Read-only gate: a NON-injective authored inverse as the logical PK keeps
586
+ -- the table read-only. The reconstructibility verdict is now the bijection
587
+ -- check, not the bare-column test: substr(code,1,1) collapses A1/A2 so the
588
+ -- forward is not injective — the authored PK column is neither bare-
589
+ -- reconstructible nor bijective-authored, so the PK is not reconstructible and
590
+ -- the table deploys read-only (contrast scenario 18, where a *proven*
591
+ -- bijection makes the authored PK reconstructible ⇒ writable). The lossy
592
+ -- advisory is suppressed because the put never runs on a read-only table.
593
+ -- ===================================
594
+
595
+ declare schema ai13b {
596
+ table Item (
597
+ code text primary key check (code in ('A1', 'A2', 'B1'))
598
+ )
599
+ }
600
+
601
+ -- run
602
+
603
+ apply schema ai13b;
604
+
605
+ -- run
606
+
607
+ declare logical schema ai13x {
608
+ table Item (
609
+ grp text primary key check (grp in ('A', 'B'))
610
+ )
611
+ }
612
+
613
+ -- run
614
+
615
+ -- substr collapses A1/A2 — NOT injective over the basis domain, so absent the
616
+ -- read-only gate the advisory would fire (scenario 1 pins exactly that).
617
+ declare lens for ai13x over ai13b {
618
+ view Item as select substr(code, 1, 1) as grp
619
+ with inverse (code = new.grp || '1')
620
+ from ai13b.Item
621
+ }
622
+
623
+ -- run
624
+
625
+ apply schema ai13x;
626
+
627
+ -- run
628
+
629
+ select count(*) as n from quereus_lens_advisories('ai13x') where code = 'lens.getput-lossy';
630
+ → [{"n": 0}]
631
+
632
+ -- run
633
+
634
+ insert into ai13x.Item values ('A');
635
+ -- error: read-only
636
+
637
+ -- ===================================
638
+ -- 14. The PutGet error is NOT read-only-gated: the same read-only shape with a
639
+ -- provably wrong inverse still blocks the deploy (a declared write path
640
+ -- that loses the written value is an authoring error regardless).
641
+ -- ===================================
642
+
643
+ declare logical schema ai14x {
644
+ table Item (
645
+ grp text primary key check (grp in ('A', 'B'))
646
+ )
647
+ }
648
+
649
+ -- run
650
+
651
+ declare lens for ai14x over ai13b {
652
+ view Item as select substr(code, 1, 1) as grp
653
+ with inverse (code = case new.grp when 'A' then 'B1' else new.grp || '1' end)
654
+ from ai13b.Item
655
+ }
656
+
657
+ -- run
658
+
659
+ apply schema ai14x;
660
+ -- error: lens.putget-violation
661
+
662
+ -- ===================================
663
+ -- 15. The motivating leak for the single-source gate above: a cross-side
664
+ -- forward (reads Aux.tag, put writes Core.code). Were the CHECK admitted,
665
+ -- the substituted NEW.tag would resolve NULL on the Core-member write and
666
+ -- the CHECK would pass vacuously — an out-of-domain write would land
667
+ -- silently. The deploy must reject instead.
668
+ -- ===================================
669
+
670
+ declare logical schema ai15x {
671
+ table V (
672
+ id integer primary key,
673
+ label text null check (label in ('Xt', 'Yt'))
674
+ )
675
+ }
676
+
677
+ -- run
678
+
679
+ declare lens for ai15x over ai12b {
680
+ view V as select Core.id as id, upper(Core.code) || Aux.tag as label
681
+ with inverse (code = lower(substr(new.label, 1, 1)))
682
+ from ai12b.Core inner join ai12b.Aux on Core.id = Aux.id
683
+ }
684
+
685
+ -- run
686
+
687
+ apply schema ai15x;
688
+ -- error: lens.unrealizable-constraint
689
+
690
+ -- ===================================
691
+ -- 16. Without a logical CHECK on the authored column, the same join-body
692
+ -- authored inverse still deploys and writes through (the single-source gate
693
+ -- constrains only CHECK realizability, not the write path).
694
+ -- ===================================
695
+
696
+ declare logical schema ai16x {
697
+ table V (
698
+ id integer primary key,
699
+ label text null
700
+ )
701
+ }
702
+
703
+ -- run
704
+
705
+ declare lens for ai16x over ai12b {
706
+ view V as select Core.id as id, upper(Core.code) as label
707
+ with inverse (code = lower(new.label))
708
+ from ai12b.Core inner join ai12b.Aux on Core.id = Aux.id
709
+ }
710
+
711
+ -- run
712
+
713
+ apply schema ai16x;
714
+
715
+ -- run
716
+
717
+ update ai16x.V set label = 'Y' where id = 1;
718
+ select code from ai12b.Core where id = 1;
719
+ → [{"code": "y"}]
720
+
721
+ -- ===================================
722
+ -- 17. The enumeration honors the column's full declared CHECK surface: a range
723
+ -- CHECK narrows the in-list (3 is excluded), so an inverse that is only
724
+ -- correct for the surviving values {1, 2} deploys clean — enumerating the
725
+ -- excluded value would red a false lens.putget-violation. Integer domain.
726
+ -- ===================================
727
+
728
+ declare schema ai17b {
729
+ table Item (
730
+ id integer primary key,
731
+ k integer not null
732
+ )
733
+ }
734
+
735
+ -- run
736
+
737
+ apply schema ai17b;
738
+
739
+ -- run
740
+
741
+ insert into ai17b.Item values (1, 0);
742
+
743
+ -- run
744
+
745
+ declare logical schema ai17x {
746
+ table Item (
747
+ id integer primary key,
748
+ n integer null check (n in (1, 2, 3)),
749
+ check (n < 3)
750
+ )
751
+ }
752
+
753
+ -- run
754
+
755
+ -- inverse(3) would store 99 and read back 100 ≠ 3 — but 3 is outside the
756
+ -- effective domain, so the composition is never evaluated for it.
757
+ declare lens for ai17x over ai17b {
758
+ view Item as select id, k + 1 as n
759
+ with inverse (k = case when new.n < 3 then new.n - 1 else 99 end)
760
+ from ai17b.Item
761
+ }
762
+
763
+ -- run
764
+
765
+ apply schema ai17x;
766
+
767
+ -- run
768
+
769
+ -- No basis-side CHECK domain ⇒ bijectivity unproven ⇒ the advisory stands.
770
+ select code, "column", status from quereus_lens_advisories('ai17x') where code = 'lens.getput-lossy';
771
+ → [{"code": "lens.getput-lossy", "column": "n", "status": "active"}]
772
+
773
+ -- run
774
+
775
+ update ai17x.Item set n = 2 where id = 1;
776
+ select k from ai17b.Item where id = 1;
777
+ → [{"k": 1}]
778
+
779
+ -- Both declared CHECKs enforce over the written image (NEW.k + 1).
780
+ update ai17x.Item set n = 3 where id = 1;
781
+ -- error: check
782
+
783
+ -- ===================================
784
+ -- 18. PK over a PROVEN-BIJECTIVE authored inverse → WRITABLE. The logical PK is
785
+ -- the authored column itself; the forward/inverse pair is proved a bijection
786
+ -- between the basis and logical CHECK domains, AND the put-target basis column
787
+ -- is a declared basis key, so the key is `proved` by bijection transport. The
788
+ -- table deploys writable (no lens.pk-not-reconstructible), with zero runtime
789
+ -- key enforcement (no lens.no-backing-index) and no lens.getput-lossy. Full
790
+ -- keyed CRUD goes through the authored put: the forward in WHERE locates the
791
+ -- row, the inverse in SET/VALUES writes the basis cell.
792
+ --
793
+ -- Integer keys (not text) so the behaviour is identical under the memory and
794
+ -- LevelDB-store backends: the store assigns a single-column TEXT primary key
795
+ -- NOCASE collation, under which a text CHECK in-list is not value-discriminating
796
+ -- and so cannot witness a bijection — the integer-keyed shape proves cleanly on
797
+ -- both. (The text upper/lower bijection is covered by scenario 6 and the unit
798
+ -- specs.)
799
+ -- ===================================
800
+
801
+ declare schema bpk_b {
802
+ table Item (
803
+ k integer primary key check (k in (1, 2, 3))
804
+ )
805
+ }
806
+
807
+ -- run
808
+
809
+ apply schema bpk_b;
810
+
811
+ -- run
812
+
813
+ insert into bpk_b.Item values (2);
814
+
815
+ -- run
816
+
817
+ declare logical schema bpk_x {
818
+ table Item (
819
+ n integer primary key check (n in (11, 12, 13))
820
+ )
821
+ }
822
+
823
+ -- run
824
+
825
+ declare lens for bpk_x over bpk_b {
826
+ view Item as select k + 10 as n
827
+ with inverse (k = new.n - 10)
828
+ from bpk_b.Item
829
+ }
830
+
831
+ -- run
832
+
833
+ apply schema bpk_x;
834
+
835
+ -- run
836
+
837
+ -- No advisories at all: bijective (no getput-lossy), reconstructible (no
838
+ -- pk-not-reconstructible), proved by transport (no no-backing-index).
839
+ select count(*) as n from quereus_lens_advisories('bpk_x');
840
+ → [{"n": 0}]
841
+
842
+ -- Read transports the basis key through the forward.
843
+ select * from bpk_x.Item;
844
+ → [{"n": 12}]
845
+
846
+ -- run
847
+
848
+ -- INSERT through the authored put: 11 stores k = 1.
849
+ insert into bpk_x.Item values (11);
850
+ select k from bpk_b.Item order by k;
851
+ → [{"k": 1}, {"k": 2}]
852
+
853
+ -- run
854
+
855
+ -- UPDATE by the authored key: forward in WHERE (k + 10 = 12), put in SET (k = 13 - 10).
856
+ update bpk_x.Item set n = 13 where n = 12;
857
+ select k from bpk_b.Item where k = 3;
858
+ → [{"k": 3}]
859
+
860
+ -- run
861
+
862
+ -- DELETE by the authored key.
863
+ delete from bpk_x.Item where n = 11;
864
+ select count(*) as cnt from bpk_b.Item where k = 1;
865
+ → [{"cnt": 0}]
866
+
867
+ -- run
868
+
869
+ -- GetPut still byte-stable (bijection): writing the read value back leaves the
870
+ -- basis unchanged.
871
+ update bpk_x.Item set n = n where n = 13;
872
+ select k from bpk_b.Item where k = 3;
873
+ → [{"k": 3}]
874
+
875
+ -- ===================================
876
+ -- 19. A bijective authored inverse whose put-target basis column is NOT a basis
877
+ -- key keeps the table writable (the bijection still proves, so the PK column
878
+ -- is reconstructible — no lens.pk-not-reconstructible) but does NOT classify
879
+ -- `proved`: two basis rows could share the value (`k` is NOT NULL + CHECK, but
880
+ -- the basis PK is the unrelated `id`), so the logical key is not intrinsically
881
+ -- unique. It enforces commit-time and emits lens.no-backing-index. The
882
+ -- columnsFormDeclaredKey gate over the put target is load-bearing here.
883
+ -- ===================================
884
+
885
+ declare schema nbk_b {
886
+ table Item (
887
+ id integer primary key,
888
+ k integer not null check (k in (1, 2, 3))
889
+ )
890
+ }
891
+
892
+ -- run
893
+
894
+ apply schema nbk_b;
895
+
896
+ -- run
897
+
898
+ declare logical schema nbk_x {
899
+ table Item (
900
+ n integer primary key check (n in (11, 12, 13))
901
+ )
902
+ }
903
+
904
+ -- run
905
+
906
+ declare lens for nbk_x over nbk_b {
907
+ view Item as select k + 10 as n
908
+ with inverse (k = new.n - 10)
909
+ from nbk_b.Item
910
+ }
911
+
912
+ -- run
913
+
914
+ apply schema nbk_x;
915
+
916
+ -- run
917
+
918
+ -- Writable (bijective ⇒ reconstructible): no read-only advisory.
919
+ select count(*) as cnt from quereus_lens_advisories('nbk_x') where code = 'lens.pk-not-reconstructible';
920
+ → [{"cnt": 0}]
921
+
922
+ -- Not proved (put-target is not a basis key): commit-time enforcement, so the
923
+ -- no-backing-index advisory fires, sited at the primary key.
924
+ select code, "constraint", "column" from quereus_lens_advisories('nbk_x') where code = 'lens.no-backing-index';
925
+ → [{"code": "lens.no-backing-index", "constraint": "primary key", "column": null}]
926
+
927
+ -- Bijection still proved ⇒ no getput-lossy.
928
+ select count(*) as cnt from quereus_lens_advisories('nbk_x') where code = 'lens.getput-lossy';
929
+ → [{"cnt": 0}]
930
+
931
+ -- ===================================
932
+ -- 20. A logical UNIQUE over a PROVEN-BIJECTIVE authored inverse is REALIZABLE.
933
+ -- The authored column is not the PK (the table is keyed and writable via the
934
+ -- real PK `id`), so the UNIQUE classifies on its own. The forward/inverse pair
935
+ -- is proved a bijection, AND the put-target basis column `code` carries a
936
+ -- declared basis UNIQUE — so the logical UNIQUE is `proved` by bijection
937
+ -- transport: zero runtime enforcement, no lens.unrealizable-constraint, no
938
+ -- lens.no-backing-index, no lens.getput-lossy. A duplicate is forbidden by the
939
+ -- basis UNIQUE through the write-through (the proved key relies on it, exactly
940
+ -- as the design intends). Integer +10 affine bijection (backend-agnostic, like
941
+ -- scenario 18). The logical UNIQUE column is NOT NULL: the bijection-transport
942
+ -- proof requires it (a nullable key would be conditionally unique and defers to
943
+ -- commit-time per the prereq's transport guard).
944
+ -- ===================================
945
+
946
+ declare schema buprv_b {
947
+ table Item (
948
+ id integer primary key,
949
+ code integer not null unique check (code in (1, 2, 3))
950
+ )
951
+ }
952
+
953
+ -- run
954
+
955
+ apply schema buprv_b;
956
+
957
+ -- run
958
+
959
+ insert into buprv_b.Item values (1, 1);
960
+
961
+ -- run
962
+
963
+ declare logical schema buprv_x {
964
+ table Item (
965
+ id integer primary key,
966
+ grp integer not null check (grp in (11, 12, 13)),
967
+ unique (grp)
968
+ )
969
+ }
970
+
971
+ -- run
972
+
973
+ declare lens for buprv_x over buprv_b {
974
+ view Item as select id, code + 10 as grp
975
+ with inverse (code = new.grp - 10)
976
+ from buprv_b.Item
977
+ }
978
+
979
+ -- run
980
+
981
+ apply schema buprv_x;
982
+
983
+ -- run
984
+
985
+ -- Clean deploy: proved by transport (no unrealizable, no no-backing-index, no
986
+ -- getput-lossy), reconstructible PK (no pk-not-reconstructible).
987
+ select count(*) as n from quereus_lens_advisories('buprv_x');
988
+ → [{"n": 0}]
989
+
990
+ -- run
991
+
992
+ -- Read transports the basis key through the forward.
993
+ select * from buprv_x.Item order by id;
994
+ → [{"id": 1, "grp": 11}]
995
+
996
+ -- run
997
+
998
+ -- A second row whose grp maps to an existing code (grp 11 → code 1) is forbidden by
999
+ -- the basis UNIQUE through the write-through — distinct id, so the basis PK does not
1000
+ -- catch it. The proved logical UNIQUE adds no runtime scan; the basis UNIQUE is the
1001
+ -- enforcer.
1002
+ insert into buprv_x.Item values (2, 11);
1003
+ -- error: unique
1004
+
1005
+ -- run
1006
+
1007
+ -- A distinct grp lands.
1008
+ insert into buprv_x.Item values (3, 12);
1009
+ select code from buprv_b.Item order by code;
1010
+ → [{"code": 1}, {"code": 2}]
1011
+
1012
+ -- ===================================
1013
+ -- 21. Commit-time fallback: the same bijective authored UNIQUE, but the put-target
1014
+ -- basis column has a CHECK + NOT NULL yet NO basis UNIQUE/PK over it — so the
1015
+ -- bijection-transport proof fails (no declared basis key) and findBasisCovering
1016
+ -- finds nothing (the authored projection has no bare basis column to map). The
1017
+ -- UNIQUE is still REALIZABLE: it enforces commit-time over the logical forward
1018
+ -- image, deploying with lens.no-backing-index (NOT lens.unrealizable-constraint).
1019
+ -- A logical-key duplicate ABORTs via the O(n) count scan.
1020
+ -- ===================================
1021
+
1022
+ declare schema buct_b {
1023
+ table Item (
1024
+ id integer primary key,
1025
+ code integer not null check (code in (1, 2, 3))
1026
+ )
1027
+ }
1028
+
1029
+ -- run
1030
+
1031
+ apply schema buct_b;
1032
+
1033
+ -- run
1034
+
1035
+ insert into buct_b.Item values (1, 1);
1036
+
1037
+ -- run
1038
+
1039
+ declare logical schema buct_x {
1040
+ table Item (
1041
+ id integer primary key,
1042
+ grp integer not null check (grp in (11, 12, 13)),
1043
+ unique (grp)
1044
+ )
1045
+ }
1046
+
1047
+ -- run
1048
+
1049
+ declare lens for buct_x over buct_b {
1050
+ view Item as select id, code + 10 as grp
1051
+ with inverse (code = new.grp - 10)
1052
+ from buct_b.Item
1053
+ }
1054
+
1055
+ -- run
1056
+
1057
+ apply schema buct_x;
1058
+
1059
+ -- run
1060
+
1061
+ -- Realizable, not proved: exactly one active no-backing-index advisory, sited at the
1062
+ -- unique constraint (the put target is not a basis key).
1063
+ select code, "constraint", status from quereus_lens_advisories('buct_x') where code = 'lens.no-backing-index';
1064
+ → [{"code": "lens.no-backing-index", "constraint": "unique", "status": "active"}]
1065
+
1066
+ -- run
1067
+
1068
+ -- Neither unrealizable nor lossy: the bijection still proves the round-trip.
1069
+ select count(*) as n from quereus_lens_advisories('buct_x') where code in ('lens.unrealizable-constraint', 'lens.getput-lossy');
1070
+ → [{"n": 0}]
1071
+
1072
+ -- run
1073
+
1074
+ -- Read transports the basis key.
1075
+ select * from buct_x.Item order by id;
1076
+ → [{"id": 1, "grp": 11}]
1077
+
1078
+ -- run
1079
+
1080
+ -- A logical-key duplicate (grp 11 → code 1, distinct id) ABORTs via the commit-time
1081
+ -- count scan — the basis has no UNIQUE on code, so only the logical scan catches it.
1082
+ insert into buct_x.Item values (2, 11);
1083
+ -- error: constraint
1084
+
1085
+ -- run
1086
+
1087
+ -- A distinct grp lands (grp 12 → code 2).
1088
+ insert into buct_x.Item values (3, 12);
1089
+ select code from buct_b.Item order by code;
1090
+ → [{"code": 1}, {"code": 2}]
1091
+
1092
+ -- run
1093
+
1094
+ -- A key-changing UPDATE that creates a duplicate (grp 12 → 11, colliding with id 1)
1095
+ -- also ABORTs via the commit-time scan (the constraint fires on INSERT|UPDATE; the
1096
+ -- NEW side is the authored forward image NEW.code + 10). The row is unchanged.
1097
+ update buct_x.Item set grp = 11 where grp = 12;
1098
+ -- error: constraint
1099
+
1100
+ -- run
1101
+
1102
+ select grp from buct_x.Item order by grp;
1103
+ → [{"grp": 11}, {"grp": 12}]
1104
+
1105
+ -- ===================================
1106
+ -- 22. A NON-INJECTIVE (lossy) authored UNIQUE still reds lens.unrealizable-constraint
1107
+ -- — the motivating safety case. substr(code,1,1) collapses A1/A2 → A, so the
1108
+ -- forward is not injective and the authored column is NOT in the bijective set;
1109
+ -- uniqueness over a value with no proven write path is neither provable nor
1110
+ -- enforceable, so the gate stays closed for it.
1111
+ -- ===================================
1112
+
1113
+ declare schema bunj_b {
1114
+ table Item (
1115
+ id integer primary key,
1116
+ code text not null check (code in ('A1', 'A2', 'B1'))
1117
+ )
1118
+ }
1119
+
1120
+ -- run
1121
+
1122
+ apply schema bunj_b;
1123
+
1124
+ -- run
1125
+
1126
+ declare logical schema bunj_x {
1127
+ table Item (
1128
+ id integer primary key,
1129
+ grp text null check (grp in ('A', 'B')),
1130
+ unique (grp)
1131
+ )
1132
+ }
1133
+
1134
+ -- run
1135
+
1136
+ declare lens for bunj_x over bunj_b {
1137
+ view Item as select id, substr(code, 1, 1) as grp
1138
+ with inverse (code = new.grp || '1')
1139
+ from bunj_b.Item
1140
+ }
1141
+
1142
+ -- run
1143
+
1144
+ apply schema bunj_x;
1145
+ -- error: lens.unrealizable-constraint
1146
+
1147
+ -- ===================================
1148
+ -- 23. Conflict-action rejection: a bijective authored UNIQUE that classifies
1149
+ -- commit-time (no basis key over the put target) with `on conflict replace`
1150
+ -- still reds lens.unenforceable-conflict-action — the commit-time count scan can
1151
+ -- only ABORT, never REPLACE. The realizability gate is lifted, but the
1152
+ -- conflict-action gate downstream still fires.
1153
+ -- ===================================
1154
+
1155
+ declare schema buca_b {
1156
+ table Item (
1157
+ id integer primary key,
1158
+ code integer not null check (code in (1, 2, 3))
1159
+ )
1160
+ }
1161
+
1162
+ -- run
1163
+
1164
+ apply schema buca_b;
1165
+
1166
+ -- run
1167
+
1168
+ declare logical schema buca_x {
1169
+ table Item (
1170
+ id integer primary key,
1171
+ grp integer not null check (grp in (11, 12, 13)),
1172
+ unique (grp) on conflict replace
1173
+ )
1174
+ }
1175
+
1176
+ -- run
1177
+
1178
+ declare lens for buca_x over buca_b {
1179
+ view Item as select id, code + 10 as grp
1180
+ with inverse (code = new.grp - 10)
1181
+ from buca_b.Item
1182
+ }
1183
+
1184
+ -- run
1185
+
1186
+ apply schema buca_x;
1187
+ -- error: lens.unenforceable-conflict-action
1188
+
1189
+ -- ===================================
1190
+ -- 24. Multi-column commit-time UNIQUE mixing a bare-reconstructible column and a
1191
+ -- bijective authored column. unique(tag, grp): `tag` is a plain rename (bare,
1192
+ -- NEW.tag) and `grp` is the +10 affine bijection (authored, NEW.code + 10). No
1193
+ -- basis key over the put targets ⇒ commit-time. Exercises the per-column NEW-side
1194
+ -- synthesis: the count predicate must read `_u.tag = NEW.tag and _u.grp =
1195
+ -- NEW.code + 10` so a logical-domain tuple is compared to a logical-domain tuple.
1196
+ -- Distinct tuples land; a duplicate logical tuple ABORTs.
1197
+ -- ===================================
1198
+
1199
+ declare schema bumix_b {
1200
+ table Item (
1201
+ id integer primary key,
1202
+ tag text not null,
1203
+ code integer not null check (code in (1, 2, 3))
1204
+ )
1205
+ }
1206
+
1207
+ -- run
1208
+
1209
+ apply schema bumix_b;
1210
+
1211
+ -- run
1212
+
1213
+ declare logical schema bumix_x {
1214
+ table Item (
1215
+ id integer primary key,
1216
+ tag text not null,
1217
+ grp integer not null check (grp in (11, 12, 13)),
1218
+ unique (tag, grp)
1219
+ )
1220
+ }
1221
+
1222
+ -- run
1223
+
1224
+ declare lens for bumix_x over bumix_b {
1225
+ view Item as select id, tag, code + 10 as grp
1226
+ with inverse (code = new.grp - 10)
1227
+ from bumix_b.Item
1228
+ }
1229
+
1230
+ -- run
1231
+
1232
+ apply schema bumix_x;
1233
+
1234
+ -- run
1235
+
1236
+ -- Commit-time (mixed bare + authored key): one no-backing-index, no unrealizable.
1237
+ select code, "constraint", status from quereus_lens_advisories('bumix_x') where code = 'lens.no-backing-index';
1238
+ → [{"code": "lens.no-backing-index", "constraint": "unique", "status": "active"}]
1239
+
1240
+ -- run
1241
+
1242
+ -- Distinct logical tuples all land: (a,11), (a,12) differ in grp; (b,11) differs in tag.
1243
+ insert into bumix_x.Item values (1, 'a', 11), (2, 'a', 12), (3, 'b', 11);
1244
+ select id, tag, code from bumix_b.Item order by id;
1245
+ → [{"id": 1, "tag": "a", "code": 1}, {"id": 2, "tag": "a", "code": 2}, {"id": 3, "tag": "b", "code": 1}]
1246
+
1247
+ -- run
1248
+
1249
+ -- A duplicate logical tuple (a, 11) → (tag a, code 1) ABORTs via the commit-time scan
1250
+ -- over the mixed NEW side (NEW.tag and NEW.code + 10).
1251
+ insert into bumix_x.Item values (4, 'a', 11);
1252
+ -- error: constraint
1253
+
1254
+ -- ===================================
1255
+ -- 25. Conflict-action rejection on a PROVED-by-TRANSPORT key — the headline repro.
1256
+ -- A bare-reconstructible rename (`code as grp`) whose put-target basis column
1257
+ -- carries a declared basis UNIQUE classifies `proved` (a basis NOT-NULL UNIQUE is
1258
+ -- itself a relation key, so the body proves the logical key directly). But the
1259
+ -- basis UNIQUE — not the logical key — governs a write-through: a duplicate `grp`
1260
+ -- maps to a duplicate `code`, which the basis UNIQUE resolves by its OWN action
1261
+ -- (here ABORT). So a logical `unique (grp) on conflict replace` the basis UNIQUE
1262
+ -- does not carry would be silently dropped — it reds lens.unenforceable-conflict-
1263
+ -- action. (Before the fix this deployed clean, dropping the declared REPLACE.)
1264
+ -- ===================================
1265
+
1266
+ declare schema tca25_b {
1267
+ table t (
1268
+ id integer primary key,
1269
+ code integer not null unique check (code in (1, 2, 3))
1270
+ )
1271
+ }
1272
+
1273
+ -- run
1274
+
1275
+ apply schema tca25_b;
1276
+
1277
+ -- run
1278
+
1279
+ declare logical schema tca25_x {
1280
+ table t (
1281
+ id integer primary key,
1282
+ grp integer not null check (grp in (1, 2, 3)),
1283
+ unique (grp) on conflict replace
1284
+ )
1285
+ }
1286
+
1287
+ -- run
1288
+
1289
+ declare lens for tca25_x over tca25_b {
1290
+ view t as select id, code as grp from tca25_b.t
1291
+ }
1292
+
1293
+ -- run
1294
+
1295
+ apply schema tca25_x;
1296
+ -- error: lens.unenforceable-conflict-action
1297
+
1298
+ -- ===================================
1299
+ -- 26. The same rejection over an AUTHORED-bijective transport key (+10 affine), to
1300
+ -- pin the authored arm of the transport proof too (the body cannot prove a `code
1301
+ -- + 10` key, so this reaches the transport classification, not the body-proved
1302
+ -- one). Basis UNIQUE on the put target (ABORT), logical `unique (grp) on conflict
1303
+ -- replace` ⇒ red.
1304
+ -- ===================================
1305
+
1306
+ declare schema tca26_b {
1307
+ table t (
1308
+ id integer primary key,
1309
+ code integer not null unique check (code in (1, 2, 3))
1310
+ )
1311
+ }
1312
+
1313
+ -- run
1314
+
1315
+ apply schema tca26_b;
1316
+
1317
+ -- run
1318
+
1319
+ declare logical schema tca26_x {
1320
+ table t (
1321
+ id integer primary key,
1322
+ grp integer not null check (grp in (11, 12, 13)),
1323
+ unique (grp) on conflict replace
1324
+ )
1325
+ }
1326
+
1327
+ -- run
1328
+
1329
+ declare lens for tca26_x over tca26_b {
1330
+ view t as select id, code + 10 as grp
1331
+ with inverse (code = new.grp - 10)
1332
+ from tca26_b.t
1333
+ }
1334
+
1335
+ -- run
1336
+
1337
+ apply schema tca26_x;
1338
+ -- error: lens.unenforceable-conflict-action
1339
+
1340
+ -- ===================================
1341
+ -- 27. A MATCHING basis-UNIQUE action deploys clean and the write-through honors
1342
+ -- REPLACE for free — the positive case the rejecter must NOT block. Basis UNIQUE
1343
+ -- `on conflict replace`, logical `unique (grp) on conflict replace`: the actions
1344
+ -- agree, so the key stays `proved` with zero advisories, and a duplicate `code`
1345
+ -- REPLACES via the basis UNIQUE (not ABORT). This is the documented remediation.
1346
+ -- ===================================
1347
+
1348
+ declare schema tca27_b {
1349
+ table t (
1350
+ id integer primary key,
1351
+ code integer not null unique on conflict replace check (code in (1, 2, 3))
1352
+ )
1353
+ }
1354
+
1355
+ -- run
1356
+
1357
+ apply schema tca27_b;
1358
+
1359
+ -- run
1360
+
1361
+ declare logical schema tca27_x {
1362
+ table t (
1363
+ id integer primary key,
1364
+ grp integer not null check (grp in (1, 2, 3)),
1365
+ unique (grp) on conflict replace
1366
+ )
1367
+ }
1368
+
1369
+ -- run
1370
+
1371
+ declare lens for tca27_x over tca27_b {
1372
+ view t as select id, code as grp from tca27_b.t
1373
+ }
1374
+
1375
+ -- run
1376
+
1377
+ apply schema tca27_x;
1378
+
1379
+ -- run
1380
+
1381
+ -- Clean deploy: matching actions ⇒ proved transport, no advisories.
1382
+ select count(*) as n from quereus_lens_advisories('tca27_x');
1383
+ → [{"n": 0}]
1384
+
1385
+ -- run
1386
+
1387
+ -- The write honors REPLACE through the basis UNIQUE: (2, 1) replaces (1, 1) on the
1388
+ -- duplicate code, leaving one basis row (the later id) rather than ABORTing.
1389
+ insert into tca27_x.t (id, grp) values (1, 1);
1390
+ insert into tca27_x.t (id, grp) values (2, 1);
1391
+ select id, code from tca27_b.t order by id;
1392
+ → [{"id": 2, "code": 1}]
1393
+
1394
+ -- ===================================
1395
+ -- 28. PK transport variant. A logical PK over an authored-bijective column mapping to
1396
+ -- the basis PK is `proved` by transport — the basis PK governs a write-through.
1397
+ -- 28a: a logical PK `on conflict replace` over a plain-ABORT basis PK reds.
1398
+ -- ===================================
1399
+
1400
+ declare schema tca28a_b {
1401
+ table t (
1402
+ k integer primary key check (k in (1, 2, 3))
1403
+ )
1404
+ }
1405
+
1406
+ -- run
1407
+
1408
+ apply schema tca28a_b;
1409
+
1410
+ -- run
1411
+
1412
+ declare logical schema tca28a_x {
1413
+ table t (
1414
+ n integer primary key on conflict replace check (n in (11, 12, 13))
1415
+ )
1416
+ }
1417
+
1418
+ -- run
1419
+
1420
+ declare lens for tca28a_x over tca28a_b {
1421
+ view t as select k + 10 as n
1422
+ with inverse (k = new.n - 10)
1423
+ from tca28a_b.t
1424
+ }
1425
+
1426
+ -- run
1427
+
1428
+ apply schema tca28a_x;
1429
+ -- error: lens.unenforceable-conflict-action
1430
+
1431
+ -- ===================================
1432
+ -- 28b. A matching basis PK action deploys clean — confirms the PK arm's positive case.
1433
+ -- ===================================
1434
+
1435
+ declare schema tca28b_b {
1436
+ table t (
1437
+ k integer primary key on conflict replace check (k in (1, 2, 3))
1438
+ )
1439
+ }
1440
+
1441
+ -- run
1442
+
1443
+ apply schema tca28b_b;
1444
+
1445
+ -- run
1446
+
1447
+ declare logical schema tca28b_x {
1448
+ table t (
1449
+ n integer primary key on conflict replace check (n in (11, 12, 13))
1450
+ )
1451
+ }
1452
+
1453
+ -- run
1454
+
1455
+ declare lens for tca28b_x over tca28b_b {
1456
+ view t as select k + 10 as n
1457
+ with inverse (k = new.n - 10)
1458
+ from tca28b_b.t
1459
+ }
1460
+
1461
+ -- run
1462
+
1463
+ apply schema tca28b_x;
1464
+
1465
+ -- run
1466
+
1467
+ select count(*) as n from quereus_lens_advisories('tca28b_x');
1468
+ → [{"n": 0}]