@quereus/quereus 4.20.0 → 4.20.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (400) hide show
  1. package/README.md +2 -0
  2. package/dist/src/common/types.d.ts +4 -4
  3. package/dist/src/index.d.ts +1 -1
  4. package/dist/src/index.d.ts.map +1 -1
  5. package/dist/src/index.js +3 -2
  6. package/dist/src/index.js.map +1 -1
  7. package/dist/src/schema/catalog-rendering.js +13 -1
  8. package/dist/src/schema/catalog-rendering.js.map +1 -1
  9. package/dist/src/schema/catalog.d.ts +35 -2
  10. package/dist/src/schema/catalog.d.ts.map +1 -1
  11. package/dist/src/schema/catalog.js +42 -33
  12. package/dist/src/schema/catalog.js.map +1 -1
  13. package/dist/src/schema/schema-differ.d.ts +1 -1
  14. package/dist/src/schema/schema-differ.d.ts.map +1 -1
  15. package/dist/src/schema/schema-differ.js +195 -33
  16. package/dist/src/schema/schema-differ.js.map +1 -1
  17. package/dist/src/schema/unique-enforcement.d.ts +23 -1
  18. package/dist/src/schema/unique-enforcement.d.ts.map +1 -1
  19. package/dist/src/schema/unique-enforcement.js +43 -1
  20. package/dist/src/schema/unique-enforcement.js.map +1 -1
  21. package/dist/src/vtab/memory/layer/manager.d.ts +15 -12
  22. package/dist/src/vtab/memory/layer/manager.d.ts.map +1 -1
  23. package/dist/src/vtab/memory/layer/manager.js +87 -100
  24. package/dist/src/vtab/memory/layer/manager.js.map +1 -1
  25. package/package.json +7 -4
  26. package/test/README.md +173 -0
  27. package/test/logic/01-basic.sqllogic +39 -0
  28. package/test/logic/01.1-select-projection-extras.sqllogic +130 -0
  29. package/test/logic/01.2-strings.sqllogic +43 -0
  30. package/test/logic/01.5-insert-select.sqllogic +237 -0
  31. package/test/logic/01.6-update-extras.sqllogic +118 -0
  32. package/test/logic/01.7-update-from.sqllogic +67 -0
  33. package/test/logic/01.8-delete-extras.sqllogic +122 -0
  34. package/test/logic/01.8.1-delete-range-cow.sqllogic +115 -0
  35. package/test/logic/01.9-query-expr-dml-gates.sqllogic +32 -0
  36. package/test/logic/01.9-query-expr-dml.sqllogic +171 -0
  37. package/test/logic/01.9-query-expr-values.sqllogic +111 -0
  38. package/test/logic/01.9.1-limit-over-dml-subquery.sqllogic +119 -0
  39. package/test/logic/02-filters.sqllogic +54 -0
  40. package/test/logic/02-smoke.sqllogic +62 -0
  41. package/test/logic/02.1-bind-parameters.sqllogic +223 -0
  42. package/test/logic/03-expressions.sqllogic +190 -0
  43. package/test/logic/03.1-quoted-identifiers.sqllogic +55 -0
  44. package/test/logic/03.4-defaults.sqllogic +554 -0
  45. package/test/logic/03.4.1-default-edge-cases.sqllogic +99 -0
  46. package/test/logic/03.5-tvf.sqllogic +61 -0
  47. package/test/logic/03.6-type-system.sqllogic +544 -0
  48. package/test/logic/03.6.1-numeric-text-comparison-coercion.sqllogic +244 -0
  49. package/test/logic/03.6.2-value-to-text.sqllogic +224 -0
  50. package/test/logic/03.7-bigint-mixed-arithmetic.sqllogic +65 -0
  51. package/test/logic/03.8-not-precedence.sqllogic +255 -0
  52. package/test/logic/03.9-is-bool-predicate.sqllogic +150 -0
  53. package/test/logic/03.9.1-is-bool-predicate-partial-index.sqllogic +34 -0
  54. package/test/logic/04-order-by.sqllogic +38 -0
  55. package/test/logic/04-transactions.sqllogic +239 -0
  56. package/test/logic/04a-savepoint-lazy-attach.sqllogic +122 -0
  57. package/test/logic/05-vtab_memory.sqllogic +50 -0
  58. package/test/logic/05.0.1-vtab-memory-unique-index-collation.sqllogic +34 -0
  59. package/test/logic/05.1-composite-pk-range-scan.sqllogic +147 -0
  60. package/test/logic/05.1.1-secondary-index-range-scan.sqllogic +56 -0
  61. package/test/logic/05.2-cast-seek-correctness.sqllogic +124 -0
  62. package/test/logic/06-builtin_functions.sqllogic +149 -0
  63. package/test/logic/06.1-string-functions.sqllogic +92 -0
  64. package/test/logic/06.1.3-like-glob-edges.sqllogic +53 -0
  65. package/test/logic/06.2-math-functions.sqllogic +82 -0
  66. package/test/logic/06.3-schema.sqllogic +48 -0
  67. package/test/logic/06.3.1-schema-all-schemas.sqllogic +39 -0
  68. package/test/logic/06.3.2-schema-foreign-keys.sqllogic +208 -0
  69. package/test/logic/06.3.3-introspection-tags.sqllogic +202 -0
  70. package/test/logic/06.3.3.1-introspection-tags-index.sqllogic +74 -0
  71. package/test/logic/06.3.4-view-info.sqllogic +378 -0
  72. package/test/logic/06.3.5-column-info.sqllogic +347 -0
  73. package/test/logic/06.3.6-schema-views.sqllogic +29 -0
  74. package/test/logic/06.4-schema-search-path.sqllogic +354 -0
  75. package/test/logic/06.4.1-schema-case-insensitive.sqllogic +83 -0
  76. package/test/logic/06.4.2-collation-extras.sqllogic +472 -0
  77. package/test/logic/06.4.2.1-collation-index-access-paths.sqllogic +140 -0
  78. package/test/logic/06.4.3-write-path-collation.sqllogic +99 -0
  79. package/test/logic/06.4.4-comparison-collation-precedence.sqllogic +342 -0
  80. package/test/logic/06.4.5-any-collate-declared-keys.sqllogic +92 -0
  81. package/test/logic/06.5-polymorphic-types.sqllogic +169 -0
  82. package/test/logic/06.5.1-conversion-functions.sqllogic +173 -0
  83. package/test/logic/06.5.2-scalar-minmax.sqllogic +16 -0
  84. package/test/logic/06.5.3-undeclared-return-type-comparison.sqllogic +244 -0
  85. package/test/logic/06.5.4-declared-return-type-builtins.sqllogic +288 -0
  86. package/test/logic/06.6-aggregate-extended.sqllogic +78 -0
  87. package/test/logic/06.7-json-extended.sqllogic +53 -0
  88. package/test/logic/06.8-json-path-operators.sqllogic +99 -0
  89. package/test/logic/06.9-json-canonical-key.sqllogic +65 -0
  90. package/test/logic/06.9.1-json-coerce-once.sqllogic +417 -0
  91. package/test/logic/06.9.1.1-json-coerce-once-index.sqllogic +39 -0
  92. package/test/logic/06.9.2-json-structural-equality.sqllogic +382 -0
  93. package/test/logic/06.9.2.1-json-structural-equality-index.sqllogic +76 -0
  94. package/test/logic/06.9.3-json-index-range-seek.sqllogic +205 -0
  95. package/test/logic/07-aggregates.sqllogic +193 -0
  96. package/test/logic/07.1-aggregate-filter-clause.sqllogic +12 -0
  97. package/test/logic/07.2-aggregate-order-by.sqllogic +11 -0
  98. package/test/logic/07.3-group-by-extras.sqllogic +602 -0
  99. package/test/logic/07.3.1-group-by-order-by-key.sqllogic +164 -0
  100. package/test/logic/07.3.2-grouped-select-list-shape.sqllogic +231 -0
  101. package/test/logic/07.4-group-by-filter-composite-pk.sqllogic +120 -0
  102. package/test/logic/07.5-sum-mixed-exact-and-float.sqllogic +151 -0
  103. package/test/logic/07.5-window.sqllogic +1941 -0
  104. package/test/logic/07.5.1-window-named.sqllogic +13 -0
  105. package/test/logic/07.5.2-window-nth-value.sqllogic +13 -0
  106. package/test/logic/07.6-subqueries.sqllogic +78 -0
  107. package/test/logic/07.6.1-subquery-extras.sqllogic +93 -0
  108. package/test/logic/07.7-and-or-short-circuit.sqllogic +58 -0
  109. package/test/logic/07.7-in-subquery-caching.sqllogic +174 -0
  110. package/test/logic/07.7-scalar-agg-decorrelation.sqllogic +197 -0
  111. package/test/logic/07.7.1-in-extras.sqllogic +158 -0
  112. package/test/logic/07.7.1-scalar-agg-decorrelation-filter.sqllogic +105 -0
  113. package/test/logic/07.7.2-scalar-agg-decorrelation-nested.sqllogic +115 -0
  114. package/test/logic/07.7.3-exists-in-select-decorrelation.sqllogic +107 -0
  115. package/test/logic/07.7.4-where-conjunct-ordering.sqllogic +121 -0
  116. package/test/logic/07.7.5-filter-lost-under-index-order.sqllogic +134 -0
  117. package/test/logic/07.7.6-correlated-predicate-scope.sqllogic +178 -0
  118. package/test/logic/07.7.7-join-source-scope-shadowing.sqllogic +137 -0
  119. package/test/logic/07.7.8-correlated-ref-to-computed-column.sqllogic +165 -0
  120. package/test/logic/07.7.9-conjunct-monotonicity.sqllogic +200 -0
  121. package/test/logic/07.8-correlated-subquery-edges.sqllogic +71 -0
  122. package/test/logic/07.8.1-correlated-in-decorrelation-gates.sqllogic +156 -0
  123. package/test/logic/07.9-in-value-list.sqllogic +154 -0
  124. package/test/logic/07.9.1-in-value-list-composite-index.sqllogic +38 -0
  125. package/test/logic/08-views.sqllogic +64 -0
  126. package/test/logic/08.1-semi-anti-join.sqllogic +191 -0
  127. package/test/logic/08.1-view-edge-cases.sqllogic +118 -0
  128. package/test/logic/08.1.1-uncorrelated-in-semijoin.sqllogic +251 -0
  129. package/test/logic/08.2-existence-flag-semijoin-recovery.sqllogic +197 -0
  130. package/test/logic/08.3-existence-flag-inner-recovery.sqllogic +102 -0
  131. package/test/logic/08.4-key-set-semi-join.sqllogic +447 -0
  132. package/test/logic/09-set_operations.sqllogic +244 -0
  133. package/test/logic/09.1-set-op-cross-collation.sqllogic +230 -0
  134. package/test/logic/10-distinct_datatypes.sqllogic +127 -0
  135. package/test/logic/10.1-ddl-lifecycle.sqllogic +203 -0
  136. package/test/logic/10.1.1-create-table-syntax-edges.sqllogic +47 -0
  137. package/test/logic/10.1.2-ddl-in-transaction.sqllogic +143 -0
  138. package/test/logic/10.1.2.1-add-constraint-in-transaction.sqllogic +59 -0
  139. package/test/logic/10.1.3-ddl-drop-in-transaction.sqllogic +187 -0
  140. package/test/logic/10.1.3.1-drop-constraint-in-transaction.sqllogic +45 -0
  141. package/test/logic/10.1.4-create-table-duplicate-constraint-names.sqllogic +149 -0
  142. package/test/logic/10.1.4-ddl-transaction-policy.sqllogic +314 -0
  143. package/test/logic/10.1.5-alter-add-constraint-minted-name-disambiguation.sqllogic +219 -0
  144. package/test/logic/10.1.5-create-index-lifecycle.sqllogic +72 -0
  145. package/test/logic/10.1.6-ddl-transaction-policy-index.sqllogic +143 -0
  146. package/test/logic/10.1.7-create-table-default-type-check.sqllogic +119 -0
  147. package/test/logic/10.1.8-alter-add-check-existing-rows.sqllogic +117 -0
  148. package/test/logic/10.2-column-features.sqllogic +365 -0
  149. package/test/logic/10.2.1-table-options-rejection.sqllogic +63 -0
  150. package/test/logic/10.2.2-default-collation-memory.sqllogic +30 -0
  151. package/test/logic/10.3-function-features.sqllogic +247 -0
  152. package/test/logic/10.4-schema-scale.sqllogic +168 -0
  153. package/test/logic/10.4.1-schema-scale-indexes.sqllogic +121 -0
  154. package/test/logic/10.5-indexes.sqllogic +164 -0
  155. package/test/logic/10.5.1-partial-indexes.sqllogic +526 -0
  156. package/test/logic/10.5.2-expression-indexes.sqllogic +34 -0
  157. package/test/logic/10.5.3-desc-index-ordering.sqllogic +130 -0
  158. package/test/logic/10.5.4-composite-pk-index-update-phantom.sqllogic +55 -0
  159. package/test/logic/10.5.5-index-name-uniqueness.sqllogic +76 -0
  160. package/test/logic/10.5.6-minmax-index-boundary.sqllogic +204 -0
  161. package/test/logic/10.5.7-implicit-unique-index-lifecycle.sqllogic +1216 -0
  162. package/test/logic/10.6-distinct-edge-cases.sqllogic +119 -0
  163. package/test/logic/100-predicate-normalization-edge-cases.sqllogic +238 -0
  164. package/test/logic/100.1-where-extras.sqllogic +163 -0
  165. package/test/logic/100.1.1-where-join-on-order-indexed.sqllogic +35 -0
  166. package/test/logic/101-builtin-mutation-kills.sqllogic +974 -0
  167. package/test/logic/101-transaction-edge-cases.sqllogic +395 -0
  168. package/test/logic/102-schema-catalog-edge-cases.sqllogic +252 -0
  169. package/test/logic/102-unique-constraints.sqllogic +145 -0
  170. package/test/logic/102.0.1-schema-catalog-indexed-table.sqllogic +32 -0
  171. package/test/logic/102.1-unique-edge-cases.sqllogic +111 -0
  172. package/test/logic/102.1.1-unique-index-creation-edge-cases.sqllogic +75 -0
  173. package/test/logic/102.2-unique-collation.sqllogic +181 -0
  174. package/test/logic/102.2.1-unique-collation-index-derived.sqllogic +305 -0
  175. package/test/logic/103-database-options-edge-cases.sqllogic +108 -0
  176. package/test/logic/103.1-pragma-boolean-values.sqllogic +126 -0
  177. package/test/logic/104-emit-mutation-kills.sqllogic +236 -0
  178. package/test/logic/105-vtab-memory-mutation-kills.sqllogic +754 -0
  179. package/test/logic/105.1-vtab-memory-index-mutation-kills.sqllogic +540 -0
  180. package/test/logic/106-constraint-extractor-mutation-kills.sqllogic +350 -0
  181. package/test/logic/107-temporal-arithmetic-mutation-kills.sqllogic +833 -0
  182. package/test/logic/108-cardinality-estimation.sqllogic +146 -0
  183. package/test/logic/108.1-analyze-name-resolution.sqllogic +102 -0
  184. package/test/logic/109-aggregate-physical-selection.sqllogic +103 -0
  185. package/test/logic/11-joins.sqllogic +86 -0
  186. package/test/logic/11.1-join-using.sqllogic +267 -0
  187. package/test/logic/11.2-comma-join.sqllogic +35 -0
  188. package/test/logic/11.3-index-nested-loop-join.sqllogic +305 -0
  189. package/test/logic/11.3-mismatched-collation-join.sqllogic +74 -0
  190. package/test/logic/11.4-hash-join-side-swap.sqllogic +118 -0
  191. package/test/logic/110-scan-emitter-mutation-kills.sqllogic +121 -0
  192. package/test/logic/110.1-scan-emitter-index-scan-kills.sqllogic +47 -0
  193. package/test/logic/12-empty-primary-key.sqllogic +124 -0
  194. package/test/logic/12-join_padding_order.sqllogic +58 -0
  195. package/test/logic/12.1-orderby-index-consumption.sqllogic +40 -0
  196. package/test/logic/13-cte.sqllogic +137 -0
  197. package/test/logic/13.1-cte-multiple-recursive.sqllogic +104 -0
  198. package/test/logic/13.10-cte-qualified-name.sqllogic +136 -0
  199. package/test/logic/13.11-unreferenced-dml-cte.sqllogic +414 -0
  200. package/test/logic/13.12-nested-dml-cte-rejected.sqllogic +280 -0
  201. package/test/logic/13.2-cte-bind-params.sqllogic +98 -0
  202. package/test/logic/13.3-cte-edge-cases.sqllogic +120 -0
  203. package/test/logic/13.4-cte-extras.sqllogic +98 -0
  204. package/test/logic/13.5-cte-join-order.sqllogic +166 -0
  205. package/test/logic/13.6-cte-dml-runs-once.sqllogic +318 -0
  206. package/test/logic/13.7-cte-sibling-visibility.sqllogic +227 -0
  207. package/test/logic/13.8-insert-with-clause-visibility.sqllogic +254 -0
  208. package/test/logic/13.9-schema-authored-cte-isolation.sqllogic +328 -0
  209. package/test/logic/13.9.1-schema-authored-schema-path-isolation.sqllogic +408 -0
  210. package/test/logic/14-utilities.sqllogic +168 -0
  211. package/test/logic/15-timespan.sqllogic +279 -0
  212. package/test/logic/15.1-semantic-ordering.sqllogic +960 -0
  213. package/test/logic/15.1.1-json-check-coercion.sqllogic +178 -0
  214. package/test/logic/15.1.2-semantic-ordering-index.sqllogic +41 -0
  215. package/test/logic/15.1.3-declared-form-write-contract.sqllogic +519 -0
  216. package/test/logic/16-epoch.sqllogic +187 -0
  217. package/test/logic/17-weekday-modifier.sqllogic +78 -0
  218. package/test/logic/18-json-string-escapes.sqllogic +86 -0
  219. package/test/logic/18-strftime-extended-formats.sqllogic +68 -0
  220. package/test/logic/20-empty-single-row.sqllogic +261 -0
  221. package/test/logic/21-null-edge-cases.sqllogic +227 -0
  222. package/test/logic/21.1-where-null-comparisons.sqllogic +151 -0
  223. package/test/logic/21.1.1-where-null-comparisons-secondary-index.sqllogic +35 -0
  224. package/test/logic/21.2-between-edges.sqllogic +157 -0
  225. package/test/logic/22-boundary-values.sqllogic +175 -0
  226. package/test/logic/23-self-joins-duplicates.sqllogic +74 -0
  227. package/test/logic/24-builtin-branches.sqllogic +611 -0
  228. package/test/logic/24.1-substr-extras.sqllogic +75 -0
  229. package/test/logic/24.2-random-extras.sqllogic +39 -0
  230. package/test/logic/25-aggregate-edge-cases.sqllogic +289 -0
  231. package/test/logic/25.1-nested-aggregates.sqllogic +74 -0
  232. package/test/logic/25.2-having-edge-cases.sqllogic +318 -0
  233. package/test/logic/25.3-aggregate-isnull-empty.sqllogic +16 -0
  234. package/test/logic/25.4-groupby-fd-constant-empty.sqllogic +55 -0
  235. package/test/logic/25.5-ungrouped-aggregate-column-free-select-item.sqllogic +196 -0
  236. package/test/logic/26-join-edge-cases.sqllogic +333 -0
  237. package/test/logic/26.1-left-join-isnull-on-notnull.sqllogic +26 -0
  238. package/test/logic/26.2-left-join-on-vs-where.sqllogic +67 -0
  239. package/test/logic/26.3-join-on-constants.sqllogic +61 -0
  240. package/test/logic/26.4-join-on-is-null-nullable.sqllogic +44 -0
  241. package/test/logic/27-window-edge-cases.sqllogic +206 -0
  242. package/test/logic/27.1-window-groups-frame.sqllogic +13 -0
  243. package/test/logic/27.2-window-exclude.sqllogic +13 -0
  244. package/test/logic/27.3-window-json-aggregation.sqllogic +66 -0
  245. package/test/logic/28-set-ops-sort-edge-cases.sqllogic +444 -0
  246. package/test/logic/28.1-compound-limit-offset.sqllogic +143 -0
  247. package/test/logic/28.2-orderby-expression-extras.sqllogic +698 -0
  248. package/test/logic/28.2-set-op-branch-types.sqllogic +217 -0
  249. package/test/logic/29-constraint-edge-cases.sqllogic +442 -0
  250. package/test/logic/29.1-column-level-conflict-clause.sqllogic +171 -0
  251. package/test/logic/29.2-table-level-pk-conflict-clause.sqllogic +113 -0
  252. package/test/logic/40-constraints.sqllogic +418 -0
  253. package/test/logic/40.1-pk-desc-direction.sqllogic +76 -0
  254. package/test/logic/40.2-check-extras.sqllogic +683 -0
  255. package/test/logic/41-alter-table.sqllogic +191 -0
  256. package/test/logic/41-fk-cascade-conflict-and-self-ref.sqllogic +263 -0
  257. package/test/logic/41-fk-cross-schema.sqllogic +155 -0
  258. package/test/logic/41-fk-extended-targets.sqllogic +173 -0
  259. package/test/logic/41-foreign-keys.sqllogic +1001 -0
  260. package/test/logic/41-generated-column-errors.sqllogic +225 -0
  261. package/test/logic/41-generated-column-extras.sqllogic +598 -0
  262. package/test/logic/41-generated-column-scope.sqllogic +329 -0
  263. package/test/logic/41-generated-columns.sqllogic +361 -0
  264. package/test/logic/41.1-alter-pk.sqllogic +230 -0
  265. package/test/logic/41.1-fk-collation-conflict.sqllogic +277 -0
  266. package/test/logic/41.10-alter-drop-column-foreign-key.sqllogic +274 -0
  267. package/test/logic/41.10.1-alter-drop-column-unique-index.sqllogic +169 -0
  268. package/test/logic/41.10.2-alter-drop-column-check-and-assertion.sqllogic +1616 -0
  269. package/test/logic/41.10.3-alter-drop-column-referencing-fk.sqllogic +292 -0
  270. package/test/logic/41.10.4-drop-object-expression-dependents.sqllogic +602 -0
  271. package/test/logic/41.11-deferred-fk-with-rename.sqllogic +232 -0
  272. package/test/logic/41.12-alter-default-coercion.sqllogic +200 -0
  273. package/test/logic/41.13-alter-add-column-generated-backfill.sqllogic +566 -0
  274. package/test/logic/41.14-alter-add-column-subquery-backfill.sqllogic +129 -0
  275. package/test/logic/41.15-alter-column-default-type-check.sqllogic +178 -0
  276. package/test/logic/41.16-fk-unenforceable.sqllogic +364 -0
  277. package/test/logic/41.2-alter-column.sqllogic +382 -0
  278. package/test/logic/41.2.1-alter-column-retype-deleted-row-memory.sqllogic +32 -0
  279. package/test/logic/41.2.2-alter-column-retype-index-rebuild.sqllogic +77 -0
  280. package/test/logic/41.2.3-alter-column-set-not-null-pk-backfill.sqllogic +310 -0
  281. package/test/logic/41.2.3.1-alter-column-set-not-null-pk-backfill-secondary-index.sqllogic +37 -0
  282. package/test/logic/41.3-alter-add-column-unique.sqllogic +184 -0
  283. package/test/logic/41.3-alter-rename-propagation.sqllogic +2352 -0
  284. package/test/logic/41.3.1-alter-rename-index-propagation.sqllogic +94 -0
  285. package/test/logic/41.4-alter-add-column-constraints.sqllogic +855 -0
  286. package/test/logic/41.5-alter-misc.sqllogic +48 -0
  287. package/test/logic/41.5-cross-schema-foreign-keys.sqllogic +253 -0
  288. package/test/logic/41.6-alter-drop-rename-constraint.sqllogic +354 -0
  289. package/test/logic/41.6.1-alter-drop-constraint-index-derived.sqllogic +22 -0
  290. package/test/logic/41.7-alter-column-collate.sqllogic +105 -0
  291. package/test/logic/41.7.1-alter-column-collate-unique.sqllogic +45 -0
  292. package/test/logic/41.7.2-alter-column-collate-unique-store.sqllogic +208 -0
  293. package/test/logic/41.7.2.1-alter-column-collate-unique-index-store.sqllogic +114 -0
  294. package/test/logic/41.7.3-alter-column-retype-unique.sqllogic +293 -0
  295. package/test/logic/41.7.3.1-alter-column-retype-staged-rows-memory.sqllogic +41 -0
  296. package/test/logic/41.7.3.2-alter-column-retype-unique-index.sqllogic +72 -0
  297. package/test/logic/41.7.4-alter-column-retype-semantic-memory.sqllogic +445 -0
  298. package/test/logic/41.7.4.1-alter-column-retype-semantic-index-memory.sqllogic +91 -0
  299. package/test/logic/41.7.5-alter-column-collate-pk-staged-delete-memory.sqllogic +106 -0
  300. package/test/logic/41.8-alter-add-constraint-unique-fk.sqllogic +275 -0
  301. package/test/logic/41.8-alter-savepoint-staged-rows.sqllogic +443 -0
  302. package/test/logic/41.8.1-alter-rename-savepoint-staged-rows.sqllogic +408 -0
  303. package/test/logic/41.9-alter-constraint-body-change.sqllogic +180 -0
  304. package/test/logic/41.9-fk-restrict-batched.sqllogic +290 -0
  305. package/test/logic/42-committed-snapshot.sqllogic +254 -0
  306. package/test/logic/42-returning.sqllogic +159 -0
  307. package/test/logic/42.1-returning-extras.sqllogic +232 -0
  308. package/test/logic/42.2-returning-stored-row.sqllogic +165 -0
  309. package/test/logic/43-default-nullability.sqllogic +131 -0
  310. package/test/logic/43-transition-constraints.sqllogic +341 -0
  311. package/test/logic/43.1-default-collation.sqllogic +140 -0
  312. package/test/logic/43.1-notnull-or-conflict.sqllogic +79 -0
  313. package/test/logic/43.2-deferred-check-new-on-delete.sqllogic +95 -0
  314. package/test/logic/43.3-nullable-primary-key.sqllogic +587 -0
  315. package/test/logic/44-determinism-validation.sqllogic +164 -0
  316. package/test/logic/44-orthogonality.sqllogic +146 -0
  317. package/test/logic/44.1-nondeterministic-schema.sqllogic +316 -0
  318. package/test/logic/45-udf-determinism.sqllogic +39 -0
  319. package/test/logic/46-mutation-context.sqllogic +595 -0
  320. package/test/logic/47-upsert.sqllogic +255 -0
  321. package/test/logic/47.1-upsert-conflict-targets.sqllogic +169 -0
  322. package/test/logic/47.2-replace-and-or-clauses.sqllogic +164 -0
  323. package/test/logic/47.2.1-pk-replace-secondary-unique.sqllogic +374 -0
  324. package/test/logic/47.3-engine-or-fail.sqllogic +122 -0
  325. package/test/logic/47.3-upsert-conflict-target-collation.sqllogic +139 -0
  326. package/test/logic/47.3.1-upsert-conflict-index-derived-collation.sqllogic +25 -0
  327. package/test/logic/47.4-upsert-conflict-target-affinity.sqllogic +59 -0
  328. package/test/logic/47.5-upsert-do-update-constraints.sqllogic +440 -0
  329. package/test/logic/47.6-upsert-do-update-decomposed.sqllogic +100 -0
  330. package/test/logic/49-reference-graph.sqllogic +84 -0
  331. package/test/logic/50-declarative-schema.sqllogic +2550 -0
  332. package/test/logic/50-metadata-tags.sqllogic +1033 -0
  333. package/test/logic/50.0.1-metadata-tags-index.sqllogic +141 -0
  334. package/test/logic/50.1-declare-schema-pk.sqllogic +150 -0
  335. package/test/logic/50.2-declare-schema-renames.sqllogic +949 -0
  336. package/test/logic/50.2.1-declare-schema-index-renames.sqllogic +173 -0
  337. package/test/logic/50.3-declare-schema-duplicate-names.sqllogic +280 -0
  338. package/test/logic/50.4-declare-schema-apply-restore.sqllogic +192 -0
  339. package/test/logic/51-lens-foundation.sqllogic +147 -0
  340. package/test/logic/51-materialized-views.sqllogic +376 -0
  341. package/test/logic/51.5-materialized-views-coarsened-key.sqllogic +198 -0
  342. package/test/logic/51.7-maintained-table-attach-detach.sqllogic +468 -0
  343. package/test/logic/51.8-maintained-table-declared-constraints.sqllogic +440 -0
  344. package/test/logic/51.85-maintained-table-parent-fk.sqllogic +103 -0
  345. package/test/logic/51.9-maintained-table-secondary-unique.sqllogic +237 -0
  346. package/test/logic/51.9.1-maintained-table-partial-unique.sqllogic +36 -0
  347. package/test/logic/52-lens-overrides.sqllogic +566 -0
  348. package/test/logic/53-materialized-views-rowtime.sqllogic +1601 -0
  349. package/test/logic/53-reserved-tags.sqllogic +252 -0
  350. package/test/logic/53.1-materialized-view-write-through.sqllogic +329 -0
  351. package/test/logic/53.2-materialized-view-rename-propagation.sqllogic +483 -0
  352. package/test/logic/53.3-materialized-view-constraint-only-ddl.sqllogic +409 -0
  353. package/test/logic/53.3.1-materialized-view-index-ddl-irrelevance.sqllogic +29 -0
  354. package/test/logic/53.4-materialized-view-structural-alter-restore.sqllogic +436 -0
  355. package/test/logic/54-covering-mv-enforcement.sqllogic +314 -0
  356. package/test/logic/54.1-covering-mv-partial-enforcement.sqllogic +34 -0
  357. package/test/logic/55-internal-eviction-reporting.sqllogic +89 -0
  358. package/test/logic/55-lens-prover.sqllogic +202 -0
  359. package/test/logic/55.1-eviction-restrict-fk.sqllogic +148 -0
  360. package/test/logic/55.5-lens-authored-inverse.sqllogic +1468 -0
  361. package/test/logic/80-grow-retrieve-pass.sqllogic +79 -0
  362. package/test/logic/81-quickpick.sqllogic +24 -0
  363. package/test/logic/82-bloom-join.sqllogic +185 -0
  364. package/test/logic/83-merge-join.sqllogic +280 -0
  365. package/test/logic/84-asof-scan.sqllogic +238 -0
  366. package/test/logic/84-key-cardinality.sqllogic +50 -0
  367. package/test/logic/85-relational-const-folding.sqllogic +51 -0
  368. package/test/logic/86-scalar-cse.sqllogic +42 -0
  369. package/test/logic/90-error_paths.sqllogic +114 -0
  370. package/test/logic/90.1-parse-errors.sqllogic +77 -0
  371. package/test/logic/90.2-alter-table-errors.sqllogic +53 -0
  372. package/test/logic/90.2.1-alter-extra-errors.sqllogic +51 -0
  373. package/test/logic/90.3-expression-errors.sqllogic +43 -0
  374. package/test/logic/90.4-dml-errors.sqllogic +47 -0
  375. package/test/logic/90.5-unsupported-join-types.sqllogic +37 -0
  376. package/test/logic/90.5.1-right-full-join-read.sqllogic +157 -0
  377. package/test/logic/90.6-select-error-paths.sqllogic +57 -0
  378. package/test/logic/91-merge-join-edge-cases.sqllogic +159 -0
  379. package/test/logic/92-hash-aggregate-edge-cases.sqllogic +139 -0
  380. package/test/logic/93-ddl-view-edge-cases.sqllogic +104 -0
  381. package/test/logic/93.1-view-error-paths.sqllogic +74 -0
  382. package/test/logic/93.2-view-mutation-pending.sqllogic +108 -0
  383. package/test/logic/93.3-view-mutation-or-clause.sqllogic +60 -0
  384. package/test/logic/93.4-view-mutation.sqllogic +4881 -0
  385. package/test/logic/93.4.1-view-mutation-partial-unique-cardinality.sqllogic +31 -0
  386. package/test/logic/93.5-authored-inverse.sqllogic +415 -0
  387. package/test/logic/93.6-set-op-flagless-write.sqllogic +862 -0
  388. package/test/logic/94-tvf-edge-cases.sqllogic +58 -0
  389. package/test/logic/94.1-limit-offset-edge-cases.sqllogic +109 -0
  390. package/test/logic/94.2-limit-offset-extras.sqllogic +98 -0
  391. package/test/logic/95-assertions.sqllogic +1417 -0
  392. package/test/logic/96-subquery-edge-cases.sqllogic +276 -0
  393. package/test/logic/97-json-function-edge-cases.sqllogic +633 -0
  394. package/test/logic/97.1-json-blob-and-special-values.sqllogic +92 -0
  395. package/test/logic/98-temporal-edge-cases.sqllogic +515 -0
  396. package/test/logic/99-conversion-edge-cases.sqllogic +325 -0
  397. package/test/logic/99.0.1-schema-index-listing.sqllogic +21 -0
  398. package/test/logic/99.1-cast-syntax-extras.sqllogic +167 -0
  399. package/test/logic/drop-unique-index.sqllogic +88 -0
  400. package/test/logic/pushdown-test.sqllogic +36 -0
@@ -0,0 +1,2352 @@
1
+ -- adapted from SQLite test/alter.test and test/altertab.test
2
+ -- RENAME TABLE / RENAME COLUMN must propagate into dependent objects:
3
+ -- views, CHECK constraints, FOREIGN KEY references, CTEs in views.
4
+ -- (the index-definition cases live in 41.3.1-alter-rename-index-propagation)
5
+
6
+ -- ===================================
7
+ -- 1. RENAME TABLE referenced by a CHECK constraint
8
+ -- ===================================
9
+
10
+ create table t_chk (id integer primary key, v integer not null);
11
+ alter table t_chk add constraint c1 check ((select count(*) from t_chk) >= 0);
12
+
13
+ alter table t_chk rename to t_chk2;
14
+
15
+ insert into t_chk2 values (1, 10);
16
+
17
+ select count(*) as cnt from t_chk2;
18
+ → [{"cnt":1}]
19
+
20
+ drop table t_chk2;
21
+
22
+ -- ===================================
23
+ -- 2. RENAME TABLE / RENAME COLUMN referenced by a partial-index WHERE clause
24
+ -- ===================================
25
+ -- Lives in 41.3.1-alter-rename-index-propagation (bare and table-qualified
26
+ -- predicate, plus the RENAME COLUMN form); it needs standalone CREATE INDEX.
27
+
28
+ -- ===================================
29
+ -- 3. RENAME TABLE referenced by a FOREIGN KEY in another table
30
+ -- ===================================
31
+
32
+ pragma foreign_keys = true;
33
+
34
+ create table parent_t (id integer primary key, name text);
35
+ create table child_t (id integer primary key, pid integer not null references parent_t(id) on delete restrict on update restrict);
36
+
37
+ insert into parent_t values (1, 'p');
38
+ insert into child_t values (10, 1);
39
+
40
+ -- Force a checkpoint here so the deferred FK check from the legitimate insert
41
+ -- evaluates against the still-current parent_t before we rename it.
42
+ select count(*) as cnt from child_t;
43
+ → [{"cnt":1}]
44
+
45
+ alter table parent_t rename to parent_t2;
46
+
47
+ select count(*) as cnt from parent_t2;
48
+ → [{"cnt":1}]
49
+
50
+ -- FK still enforced under new parent name (bad pid → fail at commit)
51
+ insert into child_t values (11, 99);
52
+ -- error: CHECK constraint failed: _fk_child_t
53
+
54
+ -- valid child reference still works under the new parent name
55
+ insert into child_t values (12, 1);
56
+
57
+ select count(*) as cnt from child_t;
58
+ → [{"cnt":2}]
59
+
60
+ drop table child_t;
61
+ drop table parent_t2;
62
+
63
+ -- ===================================
64
+ -- 4. RENAME TABLE referenced inside a view's SELECT
65
+ -- ===================================
66
+
67
+ create table tv_src (id integer primary key, name text);
68
+ insert into tv_src values (1, 'a');
69
+
70
+ create view vv as select id, name from tv_src;
71
+
72
+ alter table tv_src rename to tv_src2;
73
+
74
+ select * from vv;
75
+ → [{"id":1,"name":"a"}]
76
+
77
+ drop view vv;
78
+ drop table tv_src2;
79
+
80
+ -- ===================================
81
+ -- 5. RENAME COLUMN propagates into a view's projection / WHERE
82
+ -- ===================================
83
+
84
+ create table t_vc (id integer primary key, old_n text);
85
+ insert into t_vc values (1, 'a'), (2, 'b');
86
+
87
+ create view v_vc as select id, old_n from t_vc where old_n is not null;
88
+
89
+ alter table t_vc rename column old_n to new_n;
90
+
91
+ select * from v_vc order by id;
92
+ → [{"id":1,"new_n":"a"},{"id":2,"new_n":"b"}]
93
+
94
+ drop view v_vc;
95
+ drop table t_vc;
96
+
97
+ -- ===================================
98
+ -- 6. RENAME COLUMN referenced inside a CTE in a view
99
+ -- ===================================
100
+
101
+ create table t_cte (id integer primary key, k integer not null);
102
+ insert into t_cte values (1, 10), (2, 20);
103
+
104
+ create view v_cte as with c as (select k from t_cte) select k from c;
105
+
106
+ alter table t_cte rename column k to kk;
107
+
108
+ select * from v_cte order by kk;
109
+ → [{"kk":10},{"kk":20}]
110
+
111
+ drop view v_cte;
112
+ drop table t_cte;
113
+
114
+ -- ===================================
115
+ -- 6a. Aliased CTE projection does NOT propagate
116
+ -- ===================================
117
+
118
+ create table t_a (id integer primary key, k integer not null);
119
+ insert into t_a values (1, 10);
120
+
121
+ create view v_a as with c as (select k as kk_alias from t_a) select kk_alias from c;
122
+
123
+ alter table t_a rename column k to kk;
124
+
125
+ select * from v_a;
126
+ → [{"kk_alias":10}]
127
+
128
+ drop view v_a;
129
+ drop table t_a;
130
+
131
+ -- ===================================
132
+ -- 6b. Explicit CTE column list stops propagation
133
+ -- ===================================
134
+
135
+ create table t_x (id integer primary key, k integer not null);
136
+ insert into t_x values (1, 5);
137
+
138
+ create view v_cl as with c(x) as (select k from t_x) select x from c;
139
+
140
+ alter table t_x rename column k to kk;
141
+
142
+ select * from v_cl;
143
+ → [{"x":5}]
144
+
145
+ drop view v_cl;
146
+ drop table t_x;
147
+
148
+ -- ===================================
149
+ -- 6c. Multi-CTE chain propagates through every link
150
+ -- ===================================
151
+
152
+ create table t_chain (id integer primary key, k integer not null);
153
+ insert into t_chain values (1, 7), (2, 8);
154
+
155
+ create view v_chain as with a as (select k from t_chain), b as (select k from a) select k from b;
156
+
157
+ alter table t_chain rename column k to kk;
158
+
159
+ select * from v_chain order by kk;
160
+ → [{"kk":7},{"kk":8}]
161
+
162
+ drop view v_chain;
163
+ drop table t_chain;
164
+
165
+ -- ===================================
166
+ -- 6d. CTE inside a subquery in the view body
167
+ -- ===================================
168
+
169
+ create table t_sub (id integer primary key, k integer not null);
170
+ insert into t_sub values (1, 42);
171
+
172
+ create view v_sub as select * from (with c as (select k from t_sub) select k from c) s;
173
+
174
+ alter table t_sub rename column k to kk;
175
+
176
+ select * from v_sub;
177
+ → [{"kk":42}]
178
+
179
+ drop view v_sub;
180
+ drop table t_sub;
181
+
182
+ -- ===================================
183
+ -- 6e. CTE body using select * (star passthrough)
184
+ -- ===================================
185
+
186
+ create table t_star (id integer primary key, k integer not null);
187
+ insert into t_star values (1, 99);
188
+
189
+ create view v_star as with c as (select * from t_star) select k from c;
190
+
191
+ alter table t_star rename column k to kk;
192
+
193
+ select kk from v_star;
194
+ → [{"kk":99}]
195
+
196
+ drop view v_star;
197
+ drop table t_star;
198
+
199
+ -- ===================================
200
+ -- 6f. Qualified outer reference to an exposing CTE
201
+ -- ===================================
202
+
203
+ create table t_q (id integer primary key, k integer not null);
204
+ insert into t_q values (1, 5);
205
+
206
+ create view v_q as with c as (select k from t_q) select c.k from c;
207
+
208
+ alter table t_q rename column k to kk;
209
+
210
+ select * from v_q;
211
+ → [{"kk":5}]
212
+
213
+ drop view v_q;
214
+ drop table t_q;
215
+
216
+ -- ===================================
217
+ -- 6g. CTE shadowing the renamed table by name (non-exposing)
218
+ -- ===================================
219
+ -- The outer FROM refers to the CTE, not the real table; the rename must NOT
220
+ -- rewrite the unqualified `k` in the outer SELECT into `kk`.
221
+
222
+ create table t_shadow (id integer primary key, k integer not null);
223
+ insert into t_shadow values (1, 100);
224
+
225
+ create view v_shadow as with t_shadow as (select 0 as k) select k from t_shadow;
226
+
227
+ alter table t_shadow rename column k to kk;
228
+
229
+ select * from v_shadow;
230
+ → [{"k":0}]
231
+
232
+ drop view v_shadow;
233
+ drop table t_shadow;
234
+
235
+ -- ===================================
236
+ -- 6h. Aliased shadowing CTE — qualified ref resolves to CTE column
237
+ -- ===================================
238
+ -- `from t_shadow2 as a` where `t_shadow2` is a non-exposing shadowing CTE:
239
+ -- the qualified `a.k` resolves to the CTE column and must NOT be rewritten.
240
+
241
+ create table t_shadow2 (id integer primary key, k integer not null);
242
+ insert into t_shadow2 values (1, 100);
243
+
244
+ create view v_shadow2 as with t_shadow2 as (select 0 as k) select a.k from t_shadow2 as a;
245
+
246
+ alter table t_shadow2 rename column k to kk;
247
+
248
+ select * from v_shadow2;
249
+ → [{"k":0}]
250
+
251
+ drop view v_shadow2;
252
+ drop table t_shadow2;
253
+
254
+ -- ===================================
255
+ -- 6i. Sibling-CTE shadowing inside a multi-WITH
256
+ -- ===================================
257
+ -- The second sibling shadows the renamed table by name; its body sees the
258
+ -- first sibling (also a CTE). Outer ref must NOT rewrite to `kk`.
259
+
260
+ create table t_sib (id integer primary key, k integer not null);
261
+ insert into t_sib values (1, 999);
262
+
263
+ create view v_sib as with a as (select 0 as k), t_sib as (select k from a) select k from t_sib;
264
+
265
+ alter table t_sib rename column k to kk;
266
+
267
+ select * from v_sib;
268
+ → [{"k":0}]
269
+
270
+ drop view v_sib;
271
+ drop table t_sib;
272
+
273
+ -- ===================================
274
+ -- 6j. Recursive CTE shadowing the renamed table — no column list
275
+ -- ===================================
276
+ -- The recursive step's `from t_rec` is a self-reference to the CTE, not
277
+ -- the renamed real table. Without pre-registering the CTE name for
278
+ -- `with recursive`, the inner `select k+1 from t_rec where k < 3` would
279
+ -- mis-bind `t_rec` as the renamed table and rewrite the unqualified `k`s
280
+ -- to `kk`, corrupting the recursive step.
281
+
282
+ create table t_rec (id integer primary key, k integer not null);
283
+ insert into t_rec values (1, 0);
284
+
285
+ create view v_rec as
286
+ with recursive t_rec as (
287
+ select 0 as k
288
+ union all
289
+ select k+1 from t_rec where k < 3
290
+ ) select k from t_rec;
291
+
292
+ alter table t_rec rename column k to kk;
293
+
294
+ select k from v_rec order by k;
295
+ → [{"k":0},{"k":1},{"k":2},{"k":3}]
296
+
297
+ drop view v_rec;
298
+ drop table t_rec;
299
+
300
+ -- ===================================
301
+ -- 6k. Recursive CTE shadowing the renamed table — explicit column list
302
+ -- ===================================
303
+ -- Same shape as 6j with an explicit column list `t_rec_cl(k)`. The
304
+ -- column-list short-circuits exposure analysis; the recursive
305
+ -- self-reference inside the body must still resolve to the CTE.
306
+
307
+ create table t_rec_cl (id integer primary key, k integer not null);
308
+ insert into t_rec_cl values (1, 0);
309
+
310
+ create view v_rec_cl as
311
+ with recursive t_rec_cl(k) as (
312
+ select 0
313
+ union all
314
+ select k+1 from t_rec_cl where k < 3
315
+ ) select k from t_rec_cl;
316
+
317
+ alter table t_rec_cl rename column k to kk;
318
+
319
+ select k from v_rec_cl order by k;
320
+ → [{"k":0},{"k":1},{"k":2},{"k":3}]
321
+
322
+ drop view v_rec_cl;
323
+ drop table t_rec_cl;
324
+
325
+ -- ===================================
326
+ -- 6l. Sibling recursive CTEs where one sibling shadows the renamed table
327
+ -- ===================================
328
+ -- Two siblings inside a `with recursive`: the first is a regular CTE, the
329
+ -- second has the same name as the renamed table and self-references in its
330
+ -- recursive step. Pre-registration must happen per-iteration so the second
331
+ -- sibling's body sees itself (not the renamed real table).
332
+
333
+ create table t_rsib (id integer primary key, k integer not null);
334
+ insert into t_rsib values (1, 0);
335
+
336
+ create view v_rsib as
337
+ with recursive a as (select 0 as k),
338
+ t_rsib as (
339
+ select k from a
340
+ union all
341
+ select k+1 from t_rsib where k < 2
342
+ )
343
+ select k from t_rsib;
344
+
345
+ alter table t_rsib rename column k to kk;
346
+
347
+ select k from v_rsib order by k;
348
+ → [{"k":0},{"k":1},{"k":2}]
349
+
350
+ drop view v_rsib;
351
+ drop table t_rsib;
352
+
353
+ -- ===================================
354
+ -- 6m. Non-exposing shadowing CTE — unaliased qualified ref
355
+ -- ===================================
356
+ -- `from t_shadow3` is a non-exposing shadowing CTE; the qualified
357
+ -- `t_shadow3.k` resolves to the CTE column and must NOT be rewritten,
358
+ -- even though the qualifier textually matches the renamed table.
359
+
360
+ create table t_shadow3 (id integer primary key, k integer not null);
361
+ insert into t_shadow3 values (1, 100);
362
+
363
+ create view v_shadow3 as
364
+ with t_shadow3 as (select 0 as k) select t_shadow3.k from t_shadow3;
365
+
366
+ alter table t_shadow3 rename column k to kk;
367
+
368
+ select * from v_shadow3;
369
+ → [{"k":0}]
370
+
371
+ drop view v_shadow3;
372
+ drop table t_shadow3;
373
+
374
+ -- ===================================
375
+ -- 6n. Sibling shadowing CTE — qualified ref
376
+ -- ===================================
377
+ -- A sibling CTE with the renamed table's name shadows the real table;
378
+ -- a qualified ref against the shadowing source name must not rewrite.
379
+
380
+ create table t_sib2 (id integer primary key, k integer not null);
381
+ insert into t_sib2 values (1, 999);
382
+
383
+ create view v_sib2 as
384
+ with a as (select 0 as k), t_sib2 as (select k from a)
385
+ select t_sib2.k from t_sib2;
386
+
387
+ alter table t_sib2 rename column k to kk;
388
+
389
+ select * from v_sib2;
390
+ → [{"k":0}]
391
+
392
+ drop view v_sib2;
393
+ drop table t_sib2;
394
+
395
+ -- ===================================
396
+ -- 6o. Recursive shadowing CTE — qualified ref in recursive step
397
+ -- ===================================
398
+ -- Inside the recursive step, qualified `t_rec2.k` refers to the CTE
399
+ -- (pre-registered for `with recursive`), not the renamed real table.
400
+
401
+ create table t_rec2 (id integer primary key, k integer not null);
402
+ insert into t_rec2 values (1, 0);
403
+
404
+ create view v_rec2 as
405
+ with recursive t_rec2 as (
406
+ select 0 as k
407
+ union all
408
+ select t_rec2.k+1 from t_rec2 where t_rec2.k < 3
409
+ ) select k from t_rec2;
410
+
411
+ alter table t_rec2 rename column k to kk;
412
+
413
+ select k from v_rec2 order by k;
414
+ → [{"k":0},{"k":1},{"k":2},{"k":3}]
415
+
416
+ drop view v_rec2;
417
+ drop table t_rec2;
418
+
419
+ -- ===================================
420
+ -- 6p. Non-exposing shadowing CTE — alias equals the table name
421
+ -- ===================================
422
+ -- `from t_self as t_self` with a non-exposing shadowing CTE: the alias
423
+ -- text matches the renamed table name. The qualifier resolves to the
424
+ -- CTE row source via the alias, so `t_self.k` must NOT be rewritten.
425
+
426
+ create table t_self (id integer primary key, k integer not null);
427
+ insert into t_self values (1, 100);
428
+
429
+ create view v_self as
430
+ with t_self as (select 0 as k) select t_self.k from t_self as t_self;
431
+
432
+ alter table t_self rename column k to kk;
433
+
434
+ select * from v_self;
435
+ → [{"k":0}]
436
+
437
+ drop view v_self;
438
+ drop table t_self;
439
+
440
+ -- ===================================
441
+ -- 7. RENAME COLUMN referenced inside an index expression
442
+ -- ===================================
443
+ -- Lives in 41.3.1-alter-rename-index-propagation (an index over an expression is
444
+ -- still rejected outright); it needs standalone CREATE INDEX.
445
+
446
+ -- ===================================
447
+ -- 8. Aliased renamed table inside a view body
448
+ -- ===================================
449
+
450
+ create table tv_src3 (id integer primary key, name text);
451
+ insert into tv_src3 values (1, 'a'), (2, 'b');
452
+
453
+ create view va as select x.id, x.name from tv_src3 as x;
454
+
455
+ alter table tv_src3 rename to tv_src3_renamed;
456
+
457
+ select * from va order by id;
458
+ → [{"id":1,"name":"a"},{"id":2,"name":"b"}]
459
+
460
+ drop view va;
461
+ drop table tv_src3_renamed;
462
+
463
+ -- ===================================
464
+ -- 9. Renaming a table referenced by a CHECK on a different table
465
+ -- ===================================
466
+
467
+ create table a_smoke (id integer primary key);
468
+ create table b_smoke (id integer primary key, check ((select count(*) from a_smoke) >= 0));
469
+
470
+ alter table a_smoke rename to a_smoke2;
471
+
472
+ insert into b_smoke values (1);
473
+
474
+ select count(*) as cnt from b_smoke;
475
+ → [{"cnt":1}]
476
+
477
+ drop table b_smoke;
478
+ drop table a_smoke2;
479
+
480
+ -- ===================================
481
+ -- 10. Renaming a column referenced by another table's CHECK
482
+ -- ===================================
483
+
484
+ create table p_col (id integer primary key, k integer not null);
485
+ insert into p_col values (1, 1);
486
+
487
+ create table c_col (
488
+ id integer primary key,
489
+ check ((select count(*) from p_col where p_col.k > 0) >= 0)
490
+ );
491
+
492
+ alter table p_col rename column k to kk;
493
+
494
+ insert into c_col values (1);
495
+
496
+ select count(*) as cnt from c_col;
497
+ → [{"cnt":1}]
498
+
499
+ drop table c_col;
500
+ drop table p_col;
501
+
502
+ -- ===================================
503
+ -- 10b. Renaming a column referenced by the same table's column-level CHECK
504
+ -- ===================================
505
+
506
+ create table t_cchk (id integer primary key, v integer check (v > 0));
507
+
508
+ alter table t_cchk rename column v to vv;
509
+
510
+ -- The CHECK must still enforce after the rename. Pre-fix this trips
511
+ -- "Column not found: v" at plan time; post-fix the CHECK rewrites to
512
+ -- (vv > 0) and the negative insert is rejected as a CHECK violation.
513
+ insert into t_cchk values (1, -5);
514
+ -- error: CHECK constraint failed
515
+
516
+ -- Valid insert succeeds against the renamed column.
517
+ insert into t_cchk values (2, 7);
518
+
519
+ select count(*) as cnt from t_cchk;
520
+ → [{"cnt":1}]
521
+
522
+ drop table t_cchk;
523
+
524
+ -- Same shape, but the CHECK is table-level *and unqualified*:
525
+ -- the AST is still produced with col.table === undefined.
526
+ create table t_tchk (id integer primary key, v integer, check (v > 0));
527
+
528
+ alter table t_tchk rename column v to vv;
529
+
530
+ insert into t_tchk values (1, -5);
531
+ -- error: CHECK constraint failed
532
+
533
+ insert into t_tchk values (2, 7);
534
+
535
+ select count(*) as cnt from t_tchk;
536
+ → [{"cnt":1}]
537
+
538
+ drop table t_tchk;
539
+
540
+ -- ===================================
541
+ -- 11. Renaming a column propagates into another table's FK referencedColumnNames
542
+ -- ===================================
543
+
544
+ pragma foreign_keys = true;
545
+
546
+ create table p_fk (k integer primary key, v text);
547
+ create table c_fk (id integer primary key, pk integer not null references p_fk(k) on delete restrict on update restrict);
548
+
549
+ insert into p_fk values (1, 'a');
550
+ insert into c_fk values (10, 1);
551
+
552
+ -- Force a checkpoint so the existing deferred FK check resolves against the
553
+ -- still-current parent column name before we rename it.
554
+ select count(*) as cnt from c_fk;
555
+ → [{"cnt":1}]
556
+
557
+ alter table p_fk rename column k to kk;
558
+
559
+ -- FK still enforced under new parent column name
560
+ insert into c_fk values (11, 99);
561
+ -- error: CHECK constraint failed: _fk_c_fk
562
+
563
+ -- Valid child reference still works
564
+ insert into c_fk values (12, 1);
565
+
566
+ select count(*) as cnt from c_fk;
567
+ → [{"cnt":2}]
568
+
569
+ drop table c_fk;
570
+ drop table p_fk;
571
+
572
+ -- ===================================
573
+ -- 12. Inner non-exposing CTE shadows an outer exposing CTE (precedence)
574
+ -- ===================================
575
+ -- The outer WITH declares an exposing same-name CTE (its body projects
576
+ -- the renamed column). A nested subquery has its own WITH that declares
577
+ -- a non-exposing same-name CTE. The subquery's `from t_nest` must bind
578
+ -- to the inner non-exposing CTE (innermost wins), and its `t_nest.k`
579
+ -- must NOT rewrite to `t_nest.kk`.
580
+
581
+ create table t_nest (id integer primary key, k integer not null);
582
+ insert into t_nest values (1, 100);
583
+
584
+ create view v_nest as
585
+ with t_nest as (select t_nest.k from t_nest)
586
+ select x from (
587
+ with t_nest as (select 0 as k)
588
+ select t_nest.k as x from t_nest
589
+ ) s;
590
+
591
+ alter table t_nest rename column k to kk;
592
+
593
+ select * from v_nest;
594
+ → [{"x":0}]
595
+
596
+ drop view v_nest;
597
+ drop table t_nest;
598
+
599
+ -- ===================================
600
+ -- 13. Shadowing CTE inside a derived-table subquery — unqualified ref
601
+ -- ===================================
602
+ -- Outer FROM has the renamed real table (so the outer frame's `qualifiers`
603
+ -- has it). A nested derived-table subquery introduces a same-name
604
+ -- non-exposing CTE; the inner unqualified `k` must resolve to the inner
605
+ -- CTE row source, not to the outer real-table binding, and therefore
606
+ -- must NOT rewrite.
607
+
608
+ create table t_exb (id integer primary key, k integer not null);
609
+ insert into t_exb values (1, 50);
610
+
611
+ create view v_exb as
612
+ select t_exb.k as outer_k, s.inner_k
613
+ from t_exb
614
+ cross join (with t_exb as (select 0 as k) select k as inner_k from t_exb) s;
615
+
616
+ alter table t_exb rename column k to kk;
617
+
618
+ select * from v_exb;
619
+ → [{"outer_k":50,"inner_k":0}]
620
+
621
+ drop view v_exb;
622
+ drop table t_exb;
623
+
624
+ -- ===================================
625
+ -- 14. Nested alias rebinding — inner alias shadows outer same-letter alias
626
+ -- ===================================
627
+ -- Outer `from t_alia as a` binds `a` to the renamed table. A subquery
628
+ -- has `from t_alia_other as a` — its inner `a` rebinds to a different
629
+ -- table. The qualified `a.k` inside the subquery refers to t_alia_other,
630
+ -- so it must NOT rewrite to `a.kk`.
631
+
632
+ create table t_alia (id integer primary key, k integer not null);
633
+ create table t_alia_other (id integer primary key, k integer not null);
634
+ insert into t_alia values (1, 10);
635
+ insert into t_alia_other values (2, 20);
636
+
637
+ create view v_alia as
638
+ select (select a.k from t_alia_other as a where a.id = 2) as inner_k
639
+ from t_alia as a;
640
+
641
+ alter table t_alia rename column k to kk;
642
+
643
+ select * from v_alia;
644
+ → [{"inner_k":20}]
645
+
646
+ drop view v_alia;
647
+ drop table t_alia;
648
+ drop table t_alia_other;
649
+
650
+ -- ===================================
651
+ -- 15. CHECK subquery with like-named column on another table — unqualified
652
+ -- ===================================
653
+ -- The CHECK body has `(select min(v) from t_chksub_u) > 0`. The inner `v`
654
+ -- legitimately binds to `t_chksub_u.v` — the inner FROM exposes a
655
+ -- like-named column. Without the schema-aware shadowing check the
656
+ -- CHECK-seed binding to `t_chksub.v` would capture the unqualified ref
657
+ -- and rewrite it to `vv`, leaving the CHECK referencing a non-existent
658
+ -- column on `t_chksub_u`.
659
+
660
+ create table t_chksub_u (id integer primary key, v integer);
661
+ insert into t_chksub_u values (1, 5);
662
+
663
+ create table t_chksub (id integer primary key, v integer,
664
+ check ((select min(v) from t_chksub_u) > 0));
665
+
666
+ alter table t_chksub rename column v to vv;
667
+
668
+ insert into t_chksub values (1, 10);
669
+
670
+ select count(*) as cnt from t_chksub;
671
+ → [{"cnt":1}]
672
+
673
+ drop table t_chksub;
674
+ drop table t_chksub_u;
675
+
676
+ -- ===================================
677
+ -- 16. CHECK subquery with correlated outer ref — owner column legitimately captured
678
+ -- ===================================
679
+ -- The other table doesn't expose `v`, so the unqualified `v` inside the
680
+ -- subquery is a correlated outer ref to `t_corr.v`. The walk falls past
681
+ -- the inner frame (callback returns false for `t_corr_u`) and the seed
682
+ -- captures the ref — so the rewrite to `vv` must happen.
683
+
684
+ create table t_corr_u (id integer primary key);
685
+ create table t_corr (id integer primary key, v integer,
686
+ check ((select count(*) from t_corr_u where t_corr_u.id < v) >= 0));
687
+
688
+ alter table t_corr rename column v to vv;
689
+
690
+ insert into t_corr values (1, 10);
691
+
692
+ select count(*) as cnt from t_corr;
693
+ → [{"cnt":1}]
694
+
695
+ drop table t_corr;
696
+ drop table t_corr_u;
697
+
698
+ -- (Case 17 from the ticket — CTE-shadow inside a CHECK subquery — is
699
+ -- impossible to construct: Quereus's parser only accepts `(SELECT ...)`
700
+ -- as a scalar subquery, not `(WITH … SELECT …)`. The CTE-shadow path is
701
+ -- already covered by cases 6f, 6g, 6m, 6n, 12, and 13 in the non-CHECK
702
+ -- propagation path.)
703
+
704
+ -- ===================================
705
+ -- 18. RENAME COLUMN rewrites a view's `with defaults` target
706
+ -- ===================================
707
+ -- The dominant clause use case: the defaulted NOT NULL column is projected
708
+ -- away, so the body rewrite alone never touches the view — the clause rewrite
709
+ -- must both fire (clause-only change still propagates) and rewrite
710
+ -- `created` → `created_at`, or the write-through errors with
711
+ -- "'with defaults (created = …)' names column 'created'".
712
+
713
+ create table t_vd (id integer primary key, name text, created integer not null);
714
+ create view v_vd as select id, name from t_vd with defaults (created = 99);
715
+
716
+ alter table t_vd rename column created to created_at;
717
+
718
+ insert into v_vd values (1, 'x');
719
+
720
+ select id, name, created_at from t_vd;
721
+ → [{"id":1,"name":"x","created_at":99}]
722
+
723
+ -- insertability derivation reads the rewritten clause from the catalog
724
+ select is_insertable_into from view_info('v_vd');
725
+ → [{"is_insertable_into":"YES"}]
726
+
727
+ drop view v_vd;
728
+ drop table t_vd;
729
+
730
+ -- ===================================
731
+ -- 19. RENAME TO of a table referenced inside an `with defaults` expr subquery
732
+ -- ===================================
733
+ -- The clause expr is appended to VALUES rows, so it cannot reference base
734
+ -- columns at top level — but a subquery inside it can reference any table.
735
+ -- Pre-fix the stale reference errored "Table 'aud_t' not found".
736
+
737
+ create table aud_t (c integer primary key);
738
+ insert into aud_t values (5);
739
+
740
+ create table t_vd2 (id integer primary key, ts integer not null);
741
+ create view v_vd2 as select id from t_vd2 with defaults (ts = (select max(c) from aud_t));
742
+
743
+ alter table aud_t rename to aud_t2;
744
+
745
+ insert into v_vd2 values (10);
746
+
747
+ select id, ts from t_vd2;
748
+ → [{"id":10,"ts":5}]
749
+
750
+ drop view v_vd2;
751
+ drop table t_vd2;
752
+ drop table aud_t2;
753
+
754
+ -- ===================================
755
+ -- 20. RENAME COLUMN inside an `with defaults` expr subquery
756
+ -- ===================================
757
+ -- The renamed table is NOT a FROM table of the view, so the clause's expr gets
758
+ -- the plain scope-aware walk — the subquery's `c` must still rewrite to `c2`.
759
+
760
+ create table aud_c (c integer primary key);
761
+ insert into aud_c values (7);
762
+
763
+ create table t_vd3 (id integer primary key, ts integer not null);
764
+ create view v_vd3 as select id from t_vd3 with defaults (ts = (select max(c) from aud_c));
765
+
766
+ alter table aud_c rename column c to c2;
767
+
768
+ insert into v_vd3 values (11);
769
+
770
+ select id, ts from t_vd3;
771
+ → [{"id":11,"ts":7}]
772
+
773
+ drop view v_vd3;
774
+ drop table t_vd3;
775
+ drop table aud_c;
776
+
777
+ -- ===================================
778
+ -- 21. RENAME COLUMN hitting both a view's body and its `with defaults` target
779
+ -- ===================================
780
+ -- The defaulted column is also projected, so one rename rewrites the body
781
+ -- projection AND the clause target; inserting with a column list omits it and
782
+ -- the default lands under the new name.
783
+
784
+ create table t_vd4 (id integer primary key, v integer not null);
785
+ create view v_vd4 as select id, v from t_vd4 with defaults (v = 42);
786
+
787
+ alter table t_vd4 rename column v to w;
788
+
789
+ insert into v_vd4 (id) values (1);
790
+
791
+ select id, w from t_vd4;
792
+ → [{"id":1,"w":42}]
793
+
794
+ select id, w from v_vd4;
795
+ → [{"id":1,"w":42}]
796
+
797
+ drop view v_vd4;
798
+ drop table t_vd4;
799
+
800
+ -- ===================================
801
+ -- 22. RENAME COLUMN on a same-named table in ANOTHER schema must NOT rewrite
802
+ -- the clause (FROM-table scoping is schema-aware)
803
+ -- ===================================
804
+ -- The view's FROM table is temp.t_vd5; renaming main.t_vd5's column must leave
805
+ -- the clause alone — the scope-aware walk binds the clause to temp.t_vd5 (a
806
+ -- schema-qualified FROM source), so a bare-name collision in another schema
807
+ -- cannot false-rewrite the target and break inserts.
808
+
809
+ create table temp.t_vd5 (id integer primary key, name text, created integer not null);
810
+ create table t_vd5 (id integer primary key, created integer not null);
811
+ create view v_vd5 as select id, name from temp.t_vd5 with defaults (created = 99);
812
+
813
+ alter table t_vd5 rename column created to created_at;
814
+
815
+ -- the clause still targets temp.t_vd5.created, which did not rename
816
+ insert into v_vd5 values (1, 'x');
817
+
818
+ select id, name, created from temp.t_vd5;
819
+ → [{"id":1,"name":"x","created":99}]
820
+
821
+ drop view v_vd5;
822
+ drop table t_vd5;
823
+ drop table temp.t_vd5;
824
+
825
+ -- ===================================
826
+ -- 23. RENAME COLUMN must NOT false-capture a like-named column inside a
827
+ -- `with defaults` expr subquery (forward scope-aware resolver)
828
+ -- ===================================
829
+ -- The renamed column (t_vd6.cap) shares its name with lim_vd6.cap, which the
830
+ -- clause's subquery references. The forward walk descends `select.defaults`: the
831
+ -- body projection `cap` rewrites to `cap_new`, but an enclosing FROM seed would
832
+ -- ALSO false-capture the inner `cap` → `cap_new` and the write-through subquery
833
+ -- `select max(cap_new) from lim_vd6` would then error ("no such column"). The
834
+ -- threaded `resolveColumnInSource` keeps the inner ref bound to lim_vd6
835
+ -- (declared-side / differ parity, see schema-differ.spec.ts).
836
+
837
+ create table lim_vd6 (id integer primary key, cap integer);
838
+ insert into lim_vd6 values (1, 50);
839
+
840
+ create table t_vd6 (id integer primary key, cap integer, ts integer not null);
841
+ create view v_vd6 as select id, cap from t_vd6 with defaults (ts = (select max(cap) from lim_vd6));
842
+
843
+ alter table t_vd6 rename column cap to cap_new;
844
+
845
+ -- the projected body column followed the rename (id, cap_new); the inner subquery
846
+ -- still targets lim_vd6.cap — a false-capture would break the default evaluation.
847
+ insert into v_vd6 (id, cap_new) values (9, 7);
848
+
849
+ select id, cap_new, ts from t_vd6;
850
+ → [{"id":9,"cap_new":7,"ts":50}]
851
+
852
+ drop view v_vd6;
853
+ drop table t_vd6;
854
+ drop table lim_vd6;
855
+
856
+ -- ===================================
857
+ -- 24. RENAME COLUMN rewrites a `new.<col>` reference in the table's own CHECK
858
+ -- ===================================
859
+ -- A CHECK may name the row being written explicitly (docs/sql-ddl.md § CHECK
860
+ -- Constraints); unqualified columns mean the same row implicitly, and §10b above
861
+ -- already pins that spelling. Pre-fix the qualified one was left alone, so after the
862
+ -- rename every write failed at plan time with "new.a isn't a column".
863
+ --
864
+ -- Both halves matter: the violating insert must still be REJECTED (proving the
865
+ -- constraint still enforces, not merely that it parses) and the conforming one accepted.
866
+
867
+ create table t_rinew (id integer primary key, a integer, constraint chk_rinew check (new.a > 0));
868
+
869
+ alter table t_rinew rename column a to z;
870
+
871
+ insert into t_rinew values (1, -5);
872
+ -- error: CHECK constraint failed: chk_rinew
873
+
874
+ insert into t_rinew values (2, 7);
875
+
876
+ select id, z from t_rinew;
877
+ → [{"id":2,"z":7}]
878
+
879
+ drop table t_rinew;
880
+
881
+ -- ===================================
882
+ -- 25. Same for `old.<col>` in a DELETE-only CHECK, verified by an actual DELETE
883
+ -- ===================================
884
+ -- `check on delete` sees only the OLD row image, so the rename has to follow the
885
+ -- `old.` qualifier or the table becomes undeletable.
886
+
887
+ create table t_riold (id integer primary key, a integer, constraint chk_riold check on delete (old.a > 0));
888
+ insert into t_riold values (1, 5), (2, -1);
889
+
890
+ alter table t_riold rename column a to z;
891
+
892
+ -- deleting the row that violates the rule is still refused...
893
+ delete from t_riold where id = 2;
894
+ -- error: CHECK constraint failed: chk_riold
895
+
896
+ -- ...and deleting the conforming row still succeeds.
897
+ delete from t_riold where id = 1;
898
+
899
+ select id, z from t_riold;
900
+ → [{"id":2,"z":-1}]
901
+
902
+ drop table t_riold;
903
+
904
+ -- ===================================
905
+ -- 26. A case-folded `NEW.A` follows the rename too
906
+ -- ===================================
907
+
908
+ create table t_ricase (id integer primary key, a integer, constraint chk_ricase check (NEW.A > 0));
909
+
910
+ alter table t_ricase rename column a to z;
911
+
912
+ insert into t_ricase values (1, -3);
913
+ -- error: CHECK constraint failed: chk_ricase
914
+
915
+ insert into t_ricase values (2, 4);
916
+
917
+ select id, z from t_ricase;
918
+ → [{"id":2,"z":4}]
919
+
920
+ drop table t_ricase;
921
+
922
+ -- ===================================
923
+ -- 27. A `new` REBOUND BY AN INNER FROM is not a row image and must NOT rewrite
924
+ -- ===================================
925
+ -- `new` and `old` are not reserved words in this parser, so `create table "new" (…)` is
926
+ -- legal and a CHECK subquery may read from it. Rewriting `"new".a` → `"new".z` there
927
+ -- would leave the CHECK naming a column that table does not have, and the next write
928
+ -- would fail at plan time. This is why the row-image match consults the scope stack
929
+ -- instead of matching the qualifier by name alone. Mirror of §15.
930
+
931
+ create table "new" (a integer primary key);
932
+ insert into "new" values (3);
933
+
934
+ create table t_rishadow (id integer primary key, a integer,
935
+ check ((select max("new".a) from "new") >= 0));
936
+
937
+ alter table t_rishadow rename column a to z;
938
+
939
+ -- the CHECK still evaluates (against the "new" table), so the write goes through
940
+ insert into t_rishadow values (1, 7);
941
+
942
+ select id, z from t_rishadow;
943
+ → [{"id":1,"z":7}]
944
+
945
+ drop table t_rishadow;
946
+ drop table "new";
947
+
948
+ -- ===================================
949
+ -- 28. `new` rebound by an ALIAS, or by a CTE name, is likewise not a row image
950
+ -- ===================================
951
+ -- §27 covers the rebind-by-unaliased-source shape only. A FROM source can bind the
952
+ -- name three other ways, and each has to suppress the row-image rewrite the same
953
+ -- way; these two are the reachable ones (`select … from U as "new"`, and a
954
+ -- `with "new" as (…)` clause). Rewriting `"new".a` → `"new".z` in either would name a
955
+ -- column the aliased/CTE row source does not have, and the next write would fail at
956
+ -- plan time.
957
+
958
+ create table u_rialias (k integer primary key, a integer);
959
+ insert into u_rialias values (1, 4);
960
+
961
+ create table t_rialias (id integer primary key, a integer,
962
+ check ((select max("new".a) from u_rialias as "new") >= 0));
963
+
964
+ alter table t_rialias rename column a to z;
965
+
966
+ insert into t_rialias values (1, 7);
967
+
968
+ select id, z from t_rialias;
969
+ → [{"id":1,"z":7}]
970
+
971
+ drop table t_rialias;
972
+ drop table u_rialias;
973
+
974
+ create table t_ricte (id integer primary key, a integer,
975
+ check ((with "new" as (select 1 as a) select max("new".a) from "new") >= 0));
976
+
977
+ alter table t_ricte rename column a to z;
978
+
979
+ insert into t_ricte values (1, 7);
980
+
981
+ select id, z from t_ricte;
982
+ → [{"id":1,"z":7}]
983
+
984
+ drop table t_ricte;
985
+
986
+ -- ===================================
987
+ -- 29. RENAME COLUMN rewrites a `new.<col>` reference in a sibling column's DEFAULT
988
+ -- ===================================
989
+ -- A column DEFAULT names its siblings through the row-image qualifier — the same
990
+ -- namespace §24 pins for a CHECK, and decided by the same walk. Pre-fix the rewrite
991
+ -- pass never looked at `table.columns` at all, so after the rename every insert failed
992
+ -- at plan time with "new.a isn't a column" and the table could accept no new rows.
993
+ --
994
+ -- Both halves matter: the post-rename insert must succeed AND the default must still
995
+ -- compute the right value from the renamed column.
996
+
997
+ create table t_rdnew (id integer primary key, a integer, b integer default (new.a + 1));
998
+
999
+ insert into t_rdnew (id, a) values (1, 5);
1000
+
1001
+ alter table t_rdnew rename column a to z;
1002
+
1003
+ insert into t_rdnew (id, z) values (2, 7);
1004
+
1005
+ select id, z, b from t_rdnew order by id;
1006
+ → [{"id":1,"z":5,"b":6},{"id":2,"z":7,"b":8}]
1007
+
1008
+ drop table t_rdnew;
1009
+
1010
+ -- ===================================
1011
+ -- 30. A case-folded `NEW.A` in a DEFAULT follows the rename too
1012
+ -- ===================================
1013
+ -- Mirror of §26 for the DEFAULT arm — the same walk decides both, so the folding is
1014
+ -- shared rather than re-implemented.
1015
+
1016
+ create table t_rdcase (id integer primary key, a integer, b integer default (NEW.A + 1));
1017
+
1018
+ alter table t_rdcase rename column a to z;
1019
+
1020
+ insert into t_rdcase (id, z) values (1, 7);
1021
+
1022
+ select id, z, b from t_rdcase;
1023
+ → [{"id":1,"z":7,"b":8}]
1024
+
1025
+ drop table t_rdcase;
1026
+
1027
+ -- ===================================
1028
+ -- 31. A DEFAULT installed by `alter column … set default` follows the rename
1029
+ -- ===================================
1030
+ -- `SET DEFAULT` writes the very same `ColumnSchema.defaultValue` field the inline
1031
+ -- spelling does, so it is not a separate gap — pinned here so a future refactor that
1032
+ -- splits the two storage paths trips this test.
1033
+
1034
+ create table t_rdset (id integer primary key, a integer, b integer);
1035
+
1036
+ alter table t_rdset alter column b set default (new.a + 1);
1037
+
1038
+ alter table t_rdset rename column a to z;
1039
+
1040
+ insert into t_rdset (id, z) values (2, 7);
1041
+
1042
+ select id, z, b from t_rdset;
1043
+ → [{"id":2,"z":7,"b":8}]
1044
+
1045
+ drop table t_rdset;
1046
+
1047
+ -- ===================================
1048
+ -- 32. RENAME COLUMN rewrites a generated column's expression
1049
+ -- ===================================
1050
+ -- A generated column's body reads its siblings BARE (`generated always as (a + 1)`) —
1051
+ -- it has no FROM clause, so the unqualified name binds to the owning table exactly as
1052
+ -- it does inside a CHECK. Pre-fix the rename left it naming `a` and the next insert
1053
+ -- failed with "Column not found: a".
1054
+ --
1055
+ -- Deliberately NOT table-qualified (`generated always as (t.a + 1)`): that spelling
1056
+ -- fails on insert with or without a rename, tracked by
1057
+ -- `bug-generated-column-own-table-qualified-reference-unusable`.
1058
+
1059
+ create table t_rgen (id integer primary key, a integer, g integer generated always as (a + 1));
1060
+
1061
+ insert into t_rgen (id, a) values (1, 5);
1062
+
1063
+ alter table t_rgen rename column a to z;
1064
+
1065
+ insert into t_rgen (id, z) values (2, 7);
1066
+
1067
+ select id, z, g from t_rgen order by id;
1068
+ → [{"id":1,"z":5,"g":6},{"id":2,"z":7,"g":8}]
1069
+
1070
+ drop table t_rgen;
1071
+
1072
+ -- ===================================
1073
+ -- 33. A DEFAULT and a generated expression on the same table both follow one rename
1074
+ -- ===================================
1075
+ -- The two fields are rewritten by one pass over `table.columns`; this pins that
1076
+ -- neither arm short-circuits the other.
1077
+
1078
+ create table t_rboth (id integer primary key, a integer,
1079
+ b integer default (new.a + 1),
1080
+ g integer generated always as (a * 2));
1081
+
1082
+ insert into t_rboth (id, a) values (1, 5);
1083
+
1084
+ alter table t_rboth rename column a to z;
1085
+
1086
+ insert into t_rboth (id, z) values (2, 7);
1087
+
1088
+ select id, z, b, g from t_rboth order by id;
1089
+ → [{"id":1,"z":5,"b":6,"g":10},{"id":2,"z":7,"b":8,"g":14}]
1090
+
1091
+ drop table t_rboth;
1092
+
1093
+ -- ===================================
1094
+ -- 34. A DEFAULT's subquery reading a like-named column on ANOTHER table must NOT rewrite
1095
+ -- ===================================
1096
+ -- The rewrite is scope-AWARE, not a depth-blind name match: the inner `v` binds to
1097
+ -- `u_dsub.v`, so renaming this table's own `v` must leave it alone. Rewriting it would
1098
+ -- leave the default naming a column `u_dsub` does not have. Mirror of the CHECK case
1099
+ -- at §15 for the DEFAULT arm.
1100
+
1101
+ create table u_dsub (k integer primary key, v integer);
1102
+ insert into u_dsub values (1, 11);
1103
+
1104
+ create table t_dsub (id integer primary key, v integer,
1105
+ w integer default ((select min(v) from u_dsub)));
1106
+
1107
+ alter table t_dsub rename column v to vz;
1108
+
1109
+ insert into t_dsub (id, vz) values (1, 2);
1110
+
1111
+ select id, vz, w from t_dsub;
1112
+ → [{"id":1,"vz":2,"w":11}]
1113
+
1114
+ drop table t_dsub;
1115
+ drop table u_dsub;
1116
+
1117
+ -- ===================================
1118
+ -- 35. A DEFAULT on ANOTHER table reaching the renamed column through a subquery DOES rewrite
1119
+ -- ===================================
1120
+ -- The other half of §34: here the inner `a` genuinely binds to the renamed table's
1121
+ -- column (it is the subquery's own FROM source), so the rename must follow it or
1122
+ -- `u_xdef` becomes uninsertable. The unseeded walk decides this arm — an unqualified
1123
+ -- ref in someone else's default binds inside its own subquery's FROM, never to the
1124
+ -- renamed table implicitly.
1125
+
1126
+ create table t_xdef (id integer primary key, a integer);
1127
+ insert into t_xdef values (1, 42);
1128
+
1129
+ create table u_xdef (id integer primary key, c integer default ((select max(a) from t_xdef)));
1130
+
1131
+ alter table t_xdef rename column a to z;
1132
+
1133
+ insert into u_xdef (id) values (1);
1134
+
1135
+ select id, c from u_xdef;
1136
+ → [{"id":1,"c":42}]
1137
+
1138
+ drop table u_xdef;
1139
+ drop table t_xdef;
1140
+
1141
+ -- ===================================
1142
+ -- 36. A `new` REBOUND BY AN INNER FROM inside a DEFAULT is not a row image
1143
+ -- ===================================
1144
+ -- Mirror of §27 for the DEFAULT arm: `create table "new" (…)` is legal, so a default's
1145
+ -- subquery may read from it. Rewriting `"new".a` → `"new".z` would leave the default
1146
+ -- naming a column that table does not have and the next insert would fail at plan time.
1147
+
1148
+ create table "new" (a integer primary key);
1149
+ insert into "new" values (3);
1150
+
1151
+ create table t_dshadow (id integer primary key, a integer,
1152
+ b integer default ((select max("new".a) from "new")));
1153
+
1154
+ alter table t_dshadow rename column a to z;
1155
+
1156
+ insert into t_dshadow (id, z) values (1, 7);
1157
+
1158
+ select id, z, b from t_dshadow;
1159
+ → [{"id":1,"z":7,"b":3}]
1160
+
1161
+ drop table t_dshadow;
1162
+ drop table "new";
1163
+
1164
+ -- ===================================
1165
+ -- 37. A NESTED subquery in another object binds its inner ref to the INNER source
1166
+ -- ===================================
1167
+ -- §34-35 pin the one-level cases. The nesting below is what distinguishes a
1168
+ -- scope-aware walk from a "the renamed table is somewhere in scope" one: the inner
1169
+ -- `max(a)` binds to `u_xnest`, while the OUTER frame is the renamed table. Only the
1170
+ -- column-source resolver can tell the two apart — without it the inner ref is rewritten
1171
+ -- to `max(z)`, which then resolves against the outer frame instead and the expression
1172
+ -- silently starts reading a different table's column (no error, wrong value).
1173
+ --
1174
+ -- Both arms of the foreign-object rewrite are pinned: a DEFAULT (this ticket's arm) and
1175
+ -- a CHECK (the arm next to it, which had the same hole).
1176
+
1177
+ create table t_xnest (id integer primary key, a integer);
1178
+ insert into t_xnest values (1, 1);
1179
+
1180
+ create table u_xnest (id integer primary key, a integer);
1181
+ insert into u_xnest values (1, 99);
1182
+
1183
+ create table x_xnest (id integer primary key,
1184
+ c integer default ((select (select max(a) from u_xnest) from t_xnest limit 1)));
1185
+
1186
+ create table y_xnest (id integer primary key, n integer,
1187
+ check (n < (select (select max(a) from u_xnest) from t_xnest limit 1)));
1188
+
1189
+ alter table t_xnest rename column a to z;
1190
+
1191
+ -- 99 (u_xnest.a), not 1 (t_xnest.z): the inner ref was left alone.
1192
+ insert into x_xnest (id) values (1);
1193
+
1194
+ select id, c from x_xnest;
1195
+ → [{"id":1,"c":99}]
1196
+
1197
+ -- Same for the CHECK: `n < 99` passes; a rewritten inner ref would compare against 1.
1198
+ insert into y_xnest (id, n) values (1, 1);
1199
+
1200
+ select id, n from y_xnest;
1201
+ → [{"id":1,"n":1}]
1202
+
1203
+ drop table y_xnest;
1204
+ drop table x_xnest;
1205
+ drop table u_xnest;
1206
+ drop table t_xnest;
1207
+
1208
+ -- ===================================
1209
+ -- 38. RENAME TO rewrites a table named inside ANOTHER table's column DEFAULT
1210
+ -- ===================================
1211
+ -- The table-rename pass walks CHECK expressions and index predicates; the two
1212
+ -- expressions a column carries — a DEFAULT and a generated body — were invisible to
1213
+ -- it, so pre-fix `t_tdef` accepted no rows at all after the rename, failing with
1214
+ -- "Table 'u_tdef' not found in schema path: main" — an error naming a table the user
1215
+ -- renamed in a different statement.
1216
+
1217
+ create table u_tdef (k integer primary key, v integer);
1218
+ insert into u_tdef values (1, 42);
1219
+
1220
+ create table t_tdef (id integer primary key, w integer default ((select min(v) from u_tdef)));
1221
+
1222
+ alter table u_tdef rename to u_tdef2;
1223
+
1224
+ insert into t_tdef (id) values (1);
1225
+
1226
+ select id, w from t_tdef;
1227
+ → [{"id":1,"w":42}]
1228
+
1229
+ -- The renamed table is what the default now reads: change it and the next default follows.
1230
+ insert into u_tdef2 values (2, 7);
1231
+
1232
+ insert into t_tdef (id) values (2);
1233
+
1234
+ select id, w from t_tdef where id = 2;
1235
+ → [{"id":2,"w":7}]
1236
+
1237
+ drop table t_tdef;
1238
+ drop table u_tdef2;
1239
+
1240
+ -- ===================================
1241
+ -- 39. RENAME TO follows a SELF-referencing DEFAULT on the renamed table itself
1242
+ -- ===================================
1243
+ -- The renamed table's own default names the renamed table. `runRenameTable` rewrites
1244
+ -- the renamed table's schema BEFORE the catalog swap, so no listener — and, on a store
1245
+ -- backend, no persisted DDL bundle — ever observes a default naming the vanished old
1246
+ -- name. Unlike the column verb there is no seeded/unseeded split: the same walk decides
1247
+ -- this arm and §38.
1248
+
1249
+ create table t_self (id integer primary key, w integer default ((select count(*) from t_self)));
1250
+
1251
+ insert into t_self (id) values (1);
1252
+
1253
+ alter table t_self rename to t_self9;
1254
+
1255
+ insert into t_self9 (id) values (2);
1256
+
1257
+ select id, w from t_self9;
1258
+ → [{"id":1,"w":0},{"id":2,"w":1}]
1259
+
1260
+ drop table t_self9;
1261
+
1262
+ -- ===================================
1263
+ -- 40. RENAME TO rewrites a generated column's expression
1264
+ -- ===================================
1265
+ -- The other of the two expressions a column carries. The cross-table subquery must be
1266
+ -- QUALIFIED here (`u_tgen.v`, not a bare `v`): the generated-column dependency check
1267
+ -- rejects an unqualified foreign ref at create time ("Column 'v' referenced by generated
1268
+ -- column 'gg' not found in table 'g_tgen'"), so only the qualified shape is reachable.
1269
+
1270
+ create table u_tgen (k integer primary key, v integer);
1271
+ insert into u_tgen values (1, 10);
1272
+
1273
+ create table g_tgen (id integer primary key,
1274
+ gg integer generated always as ((select min(u_tgen.v) from u_tgen) + id));
1275
+
1276
+ alter table u_tgen rename to u_tgen2;
1277
+
1278
+ insert into g_tgen (id) values (5);
1279
+
1280
+ select id, gg from g_tgen;
1281
+ → [{"id":5,"gg":15}]
1282
+
1283
+ drop table g_tgen;
1284
+ drop table u_tgen2;
1285
+
1286
+ -- ===================================
1287
+ -- 41. RENAME TO must NOT rewrite a same-named table in ANOTHER schema inside a DEFAULT
1288
+ -- ===================================
1289
+ -- The rewrite is schema-aware: the default's subquery reads temp.u_tsch, so renaming
1290
+ -- main.u_tsch must leave it alone. Rewriting it would leave the default naming a table
1291
+ -- temp does not have and `t_tsch` would stop accepting rows.
1292
+ --
1293
+ -- The alias/CTE shadowing shapes are pinned in §42-§47 below: the table walker is
1294
+ -- scope-aware, so a name the body itself binds (a CTE, a FROM alias, a subquery source)
1295
+ -- is not a reference and is left untouched across all four arms (checks, predicates,
1296
+ -- defaults, generated bodies).
1297
+
1298
+ create table temp.u_tsch (k integer primary key, v integer);
1299
+ insert into temp.u_tsch values (1, 11);
1300
+
1301
+ create table u_tsch (k integer primary key, v integer);
1302
+ insert into u_tsch values (1, 22);
1303
+
1304
+ create table t_tsch (id integer primary key, w integer default ((select min(v) from temp.u_tsch)));
1305
+
1306
+ alter table u_tsch rename to u_tsch2;
1307
+
1308
+ insert into t_tsch (id) values (1);
1309
+
1310
+ select id, w from t_tsch;
1311
+ → [{"id":1,"w":11}]
1312
+
1313
+ drop table t_tsch;
1314
+ drop table u_tsch2;
1315
+ drop table temp.u_tsch;
1316
+
1317
+ -- ===================================
1318
+ -- 42. RENAME TO leaves a view CTE that SHADOWS the old name untouched
1319
+ -- ===================================
1320
+ -- The `from zap` inside the view resolves to the view's own CTE, not the real table,
1321
+ -- so the rename must not touch the body. Pre-fix the walk rewrote it to `from zap2`,
1322
+ -- silently repointing the view at the real (renamed) table while its declared CTE
1323
+ -- went unused.
1324
+
1325
+ create table zap (id integer primary key, k integer);
1326
+ insert into zap values (1, 100);
1327
+
1328
+ create view v_shadow as with zap as (select 1 as k) select k from zap;
1329
+
1330
+ alter table zap rename to zap2;
1331
+
1332
+ -- the view still returns its CTE's row, not the renamed table's
1333
+ select k from v_shadow;
1334
+ → [{"k":1}]
1335
+
1336
+ -- and the real table is reachable under its new name
1337
+ select k from zap2;
1338
+ → [{"k":100}]
1339
+
1340
+ drop view v_shadow;
1341
+ drop table zap2;
1342
+
1343
+ -- ===================================
1344
+ -- 43. DROP TABLE is NOT refused for an assertion whose body only DECLARES a same-named CTE
1345
+ -- ===================================
1346
+ -- The drop guard runs the same walk read-only, so it inherited the over-match as a
1347
+ -- FALSE REFUSAL: an assertion that merely declares `with zap as (…)` blocked
1348
+ -- `drop table zap`. The walk is scope-aware now, so the drop goes through — and the
1349
+ -- assertion (which never read the real table) keeps evaluating on later writes.
1350
+
1351
+ create table zap (id integer primary key, k integer);
1352
+ create table t_asrt_other (id integer primary key);
1353
+
1354
+ create assertion a_shadow check (not exists (with zap as (select 1 as k) select k from zap where k < 0));
1355
+
1356
+ drop table zap;
1357
+
1358
+ -- writes elsewhere still recompile and pass the assertion
1359
+ insert into t_asrt_other values (1);
1360
+
1361
+ select count(*) as cnt from t_asrt_other;
1362
+ → [{"cnt":1}]
1363
+
1364
+ drop assertion a_shadow;
1365
+ drop table t_asrt_other;
1366
+
1367
+ -- ===================================
1368
+ -- 44. An ALIASED SUBQUERY SOURCE named like the renamed table is untouched
1369
+ -- ===================================
1370
+ -- `(select 5 as k) zap` binds the name to the derived table; `zap.k` resolves through
1371
+ -- that alias. Pre-fix the qualified ref rewrote to `zap2.k` (while the alias stayed
1372
+ -- `zap`), leaving the view unplannable.
1373
+
1374
+ create table zap (id integer primary key, k integer);
1375
+ insert into zap values (1, 100);
1376
+
1377
+ create view v_sub as select zap.k from (select 5 as k) zap;
1378
+
1379
+ alter table zap rename to zap2;
1380
+
1381
+ select k from v_sub;
1382
+ → [{"k":5}]
1383
+
1384
+ drop view v_sub;
1385
+ drop table zap2;
1386
+
1387
+ -- ===================================
1388
+ -- 45. An ALIASED TABLE SOURCE `from other zap` binds `zap.k` to OTHER, not the renamed table
1389
+ -- ===================================
1390
+ -- The alias `zap` qualifies rows of t_alias_other; renaming the real `zap` must leave
1391
+ -- both the alias and the qualified ref alone.
1392
+
1393
+ create table zap (id integer primary key, k integer);
1394
+ insert into zap values (1, 100);
1395
+
1396
+ create table t_alias_other (id integer primary key, k integer);
1397
+ insert into t_alias_other values (1, 7);
1398
+
1399
+ create view v_alias as select zap.k from t_alias_other zap;
1400
+
1401
+ alter table zap rename to zap3;
1402
+
1403
+ select k from v_alias;
1404
+ → [{"k":7}]
1405
+
1406
+ drop view v_alias;
1407
+ drop table t_alias_other;
1408
+ drop table zap3;
1409
+
1410
+ -- ===================================
1411
+ -- 46. Positive regressions: genuine references still rewrite under shadow-adjacent shapes
1412
+ -- ===================================
1413
+ -- Scope-awareness must not under-match: (a) a `from zap` inside a CTE BODY is a real
1414
+ -- reference (the CTE's own name is not in scope in a non-recursive body); (b) a
1415
+ -- schema-qualified `main.zap` is never a CTE, even where a same-named CTE is in scope;
1416
+ -- (c) an aliased real source `from zap z` still reads the real table.
1417
+
1418
+ create table zap (id integer primary key, k integer);
1419
+ insert into zap values (1, 42);
1420
+
1421
+ create view v_pos1 as with c as (select k from zap) select k from c;
1422
+ -- (The three-part `main.zap.k` COLUMN ref is pinned at the AST level in
1423
+ -- test/schema/table-rename-scope.spec.ts; the planner does not resolve that
1424
+ -- spelling in a view body today.)
1425
+ create view v_pos2 as with zap as (select 1 as k) select k from main.zap;
1426
+ create view v_pos3 as select z.k from zap z;
1427
+
1428
+ alter table zap rename to zap4;
1429
+
1430
+ select k from v_pos1;
1431
+ → [{"k":42}]
1432
+
1433
+ select k from v_pos2;
1434
+ → [{"k":42}]
1435
+
1436
+ select k from v_pos3;
1437
+ → [{"k":42}]
1438
+
1439
+ drop view v_pos3;
1440
+ drop view v_pos2;
1441
+ drop view v_pos1;
1442
+ drop table zap4;
1443
+
1444
+ -- ===================================
1445
+ -- 47. RENAME of a table literally named `new` leaves its CHECK's row image alone
1446
+ -- ===================================
1447
+ -- `new` is not a reserved word, so `create table "new"` is legal — and inside that
1448
+ -- table's own CHECK, `new.a` names the ROW BEING WRITTEN, not the table. Pre-fix the
1449
+ -- rename rewrote the qualifier to the new table name; now the row image survives and
1450
+ -- the constraint keeps enforcing. (The partial-index mirror — where `new.x` IS a real
1451
+ -- reference — lives in 41.3.1 §8.)
1452
+
1453
+ create table "new" (id integer primary key, a integer, constraint chk_fresh check (new.a > 0));
1454
+
1455
+ alter table "new" rename to fresh;
1456
+
1457
+ insert into fresh values (1, -5);
1458
+ -- error: CHECK constraint failed: chk_fresh
1459
+
1460
+ insert into fresh values (2, 5);
1461
+
1462
+ select id, a from fresh;
1463
+ → [{"id":2,"a":5}]
1464
+
1465
+ drop table fresh;
1466
+
1467
+ -- ===================================
1468
+ -- 48. Dependents in ANOTHER schema follow the rename (views + assertions)
1469
+ -- ===================================
1470
+ -- The propagation used to rewrite dependent views / materialized views /
1471
+ -- assertions only while iterating the renamed table's OWN schema, so a `temp`
1472
+ -- view over `main.t` kept naming a table that no longer existed and every read
1473
+ -- of it failed (an assertion in that position broke every WRITE). Every schema
1474
+ -- is walked now; what decides a match is whether the reference RESOLVES to the
1475
+ -- renamed object under the walked body's own home schema path.
1476
+
1477
+ create table main.xs_cs (id integer primary key, x integer not null);
1478
+ insert into main.xs_cs values (1, 10);
1479
+ create view temp.v_cs as select id, x from main.xs_cs;
1480
+ create assertion temp.a_cs check (not exists (select 1 from main.xs_cs where x < 0));
1481
+
1482
+ alter table main.xs_cs rename to xs_cs2;
1483
+
1484
+ -- The view body followed the rename and still reads.
1485
+ select id, x from temp.v_cs;
1486
+ → [{"id":1,"x":10}]
1487
+
1488
+ -- The assertion followed it too: writes still succeed…
1489
+ insert into main.xs_cs2 values (2, 20);
1490
+
1491
+ -- …and the rule is still enforced.
1492
+ insert into main.xs_cs2 values (3, -1);
1493
+ -- error: Assertion
1494
+
1495
+ -- Column verb, same cross-schema dependents.
1496
+ alter table main.xs_cs2 rename column x to y;
1497
+
1498
+ select id, y from temp.v_cs order by id;
1499
+ → [{"id":1,"y":10},{"id":2,"y":20}]
1500
+
1501
+ insert into main.xs_cs2 values (4, -1);
1502
+ -- error: Assertion
1503
+
1504
+ drop assertion temp.a_cs;
1505
+ drop view temp.v_cs;
1506
+ drop table main.xs_cs2;
1507
+
1508
+ -- ===================================
1509
+ -- 49. …but only when the reference actually resolves to the renamed table
1510
+ -- ===================================
1511
+ -- A `temp`-owned view whose bare `t` means `temp.t` must NOT follow a rename of
1512
+ -- the same-named `main.t`; the converse — a bare name in `temp` that falls
1513
+ -- through the home path to `main` because `temp` has no such table — must.
1514
+
1515
+ create table main.dup_cs (id integer primary key, x integer);
1516
+ create table temp.dup_cs (id integer primary key, x integer);
1517
+ insert into temp.dup_cs values (1, 111);
1518
+ -- The view's home is temp, so its bare `dup_cs` binds temp.dup_cs.
1519
+ create view temp.v_bare as select id, x from dup_cs;
1520
+
1521
+ -- `temp` holds no `only_main`, so this bare name falls through to main.
1522
+ create table main.only_main (id integer primary key, x integer);
1523
+ insert into main.only_main values (1, 222);
1524
+ create view temp.v_fall as select id, x from only_main;
1525
+
1526
+ alter table main.dup_cs rename to dup_cs2;
1527
+ alter table main.only_main rename to only_main2;
1528
+
1529
+ -- Untouched: still reading temp.dup_cs.
1530
+ select id, x from temp.v_bare;
1531
+ → [{"id":1,"x":111}]
1532
+
1533
+ -- Rewritten: follows main.only_main → main.only_main2.
1534
+ select id, x from temp.v_fall;
1535
+ → [{"id":1,"x":222}]
1536
+
1537
+ drop view temp.v_fall;
1538
+ drop view temp.v_bare;
1539
+ drop table main.only_main2;
1540
+ drop table temp.dup_cs;
1541
+ drop table main.dup_cs2;
1542
+
1543
+ -- ===================================
1544
+ -- 50. RENAME COLUMN cascades through a view-over-view chain
1545
+ -- ===================================
1546
+ -- Rewriting v1's body also shifts the name v1 PUBLISHES (x → y), so v2 —
1547
+ -- which reads v1, not the renamed table — must be rewritten in a second
1548
+ -- round. Pre-fix v2's body kept naming `x` and every read of it failed.
1549
+
1550
+ create table w_c50 (id integer primary key, x integer);
1551
+ insert into w_c50 values (1, 10);
1552
+
1553
+ create view v1_c50 as select id, x from w_c50;
1554
+ create view v2_c50 as select id, x from v1_c50;
1555
+
1556
+ alter table w_c50 rename column x to y;
1557
+
1558
+ select id, y from v2_c50;
1559
+ → [{"id":1,"y":10}]
1560
+
1561
+ -- the old name is gone at every level
1562
+ select x from v2_c50;
1563
+ -- error: not found
1564
+
1565
+ drop view v2_c50;
1566
+ drop view v1_c50;
1567
+ drop table w_c50;
1568
+
1569
+ -- ===================================
1570
+ -- 51. Three-level chain: every body follows
1571
+ -- ===================================
1572
+
1573
+ create table t_c51 (id integer primary key, x integer);
1574
+ insert into t_c51 values (1, 42);
1575
+
1576
+ create view c51_a as select id, x from t_c51;
1577
+ create view c51_b as select id, x from c51_a;
1578
+ create view c51_c as select id, x from c51_b;
1579
+
1580
+ alter table t_c51 rename column x to y;
1581
+
1582
+ select id, y from c51_c;
1583
+ → [{"id":1,"y":42}]
1584
+
1585
+ drop view c51_c;
1586
+ drop view c51_b;
1587
+ drop view c51_a;
1588
+ drop table t_c51;
1589
+
1590
+ -- ===================================
1591
+ -- 52. An ALIASED republish does NOT cascade
1592
+ -- ===================================
1593
+ -- `x as x` keeps publishing `x` after the rename (the alias pins the output
1594
+ -- name), so the reader must NOT be rewritten — the sharpest false-positive
1595
+ -- case for a syntactic "bare x in the result columns" shortcut.
1596
+
1597
+ create table w_c52 (id integer primary key, x integer);
1598
+ insert into w_c52 values (1, 5);
1599
+
1600
+ create view v1_c52 as select id, x as x from w_c52;
1601
+ create view v2_c52 as select id, x from v1_c52;
1602
+
1603
+ alter table w_c52 rename column x to y;
1604
+
1605
+ -- v1 still publishes `x`; v2 still reads it
1606
+ select id, x from v2_c52;
1607
+ → [{"id":1,"x":5}]
1608
+
1609
+ drop view v2_c52;
1610
+ drop view v1_c52;
1611
+ drop table w_c52;
1612
+
1613
+ -- ===================================
1614
+ -- 53. An explicit view column list stops the cascade
1615
+ -- ===================================
1616
+ -- `create view v(a, b)` publishes `a, b` regardless of the body — the same
1617
+ -- guard an explicit CTE column list is for the in-body exposure analysis.
1618
+
1619
+ create table w_c53 (id integer primary key, x integer);
1620
+ insert into w_c53 values (3, 8);
1621
+
1622
+ create view v1_c53 (a, b) as select id, x from w_c53;
1623
+ create view v2_c53 as select a, b from v1_c53;
1624
+
1625
+ alter table w_c53 rename column x to y;
1626
+
1627
+ select a, b from v2_c53;
1628
+ → [{"a":3,"b":8}]
1629
+
1630
+ drop view v2_c53;
1631
+ drop view v1_c53;
1632
+ drop table w_c53;
1633
+
1634
+ -- ===================================
1635
+ -- 54. A `select *` view republishes the renamed column — readers follow
1636
+ -- ===================================
1637
+ -- The star body never names the column, so the round-1 rewrite leaves it
1638
+ -- untouched — yet its published names shift with the base table's. This is
1639
+ -- the case a "look for a bare x in the result columns" shortcut gets wrong.
1640
+
1641
+ create table w_c54 (id integer primary key, x integer);
1642
+ insert into w_c54 values (2, 7);
1643
+
1644
+ create view v1_c54 as select * from w_c54;
1645
+ create view v2_c54 as select id, x from v1_c54;
1646
+
1647
+ alter table w_c54 rename column x to y;
1648
+
1649
+ select id, y from v2_c54;
1650
+ → [{"id":2,"y":7}]
1651
+
1652
+ drop view v2_c54;
1653
+ drop view v1_c54;
1654
+ drop table w_c54;
1655
+
1656
+ -- ===================================
1657
+ -- 55. A reader of the view that does NOT touch the renamed column is untouched
1658
+ -- ===================================
1659
+
1660
+ create table w_c55 (id integer primary key, x integer);
1661
+ insert into w_c55 values (1, 9);
1662
+
1663
+ create view v1_c55 as select id, x from w_c55;
1664
+ create view v2_c55 as select id from v1_c55;
1665
+
1666
+ alter table w_c55 rename column x to y;
1667
+
1668
+ select id from v2_c55;
1669
+ → [{"id":1}]
1670
+
1671
+ drop view v2_c55;
1672
+ drop view v1_c55;
1673
+ drop table w_c55;
1674
+
1675
+ -- ===================================
1676
+ -- 56. Published-name collision REFUSES the rename, before any side effect
1677
+ -- ===================================
1678
+ -- v1 publishes `x` (a passthrough of the renamed column) AND its own `y`;
1679
+ -- following the rename would make it publish two `y`s, mirroring the
1680
+ -- base-verb refusal of a rename that collides with an existing column.
1681
+ -- The statement must be a clean no-op: the table keeps `x` and v1 still reads.
1682
+
1683
+ create table w_c56 (id integer primary key, x integer);
1684
+ insert into w_c56 values (1, 4);
1685
+
1686
+ create view v1_c56 as select x, id as y from w_c56;
1687
+
1688
+ alter table w_c56 rename column x to y;
1689
+ -- error: already publishes a column named 'y'
1690
+
1691
+ -- clean no-op: the base column and the view are untouched
1692
+ select x, y from v1_c56;
1693
+ → [{"x":4,"y":1}]
1694
+
1695
+ drop view v1_c56;
1696
+ drop table w_c56;
1697
+
1698
+ -- ===================================
1699
+ -- 57. The cascade crosses schemas, and a body touched by TWO rounds settles
1700
+ -- ===================================
1701
+ -- main.t → main.v1 → temp.v2: the second round must reach dependents in every
1702
+ -- schema, exactly like the first. The `vb` view is touched twice — round 1
1703
+ -- rewrites its subquery on the base table, round 2 its projection through v1.
1704
+
1705
+ create table w_c57 (id integer primary key, x integer);
1706
+ insert into w_c57 values (1, 77);
1707
+
1708
+ create view v1_c57 as select id, x from w_c57;
1709
+ create view temp.v2_c57 as select id, x from main.v1_c57;
1710
+ create view vb_c57 as select v1_c57.x as through_view, (select max(w_c57.x) from w_c57) as direct from v1_c57;
1711
+
1712
+ alter table w_c57 rename column x to y;
1713
+
1714
+ select id, y from temp.v2_c57;
1715
+ → [{"id":1,"y":77}]
1716
+
1717
+ select through_view, direct from vb_c57;
1718
+ → [{"through_view":77,"direct":77}]
1719
+
1720
+ drop view vb_c57;
1721
+ drop view temp.v2_c57;
1722
+ drop view v1_c57;
1723
+ drop table w_c57;
1724
+
1725
+ -- ===================================
1726
+ -- 58. Round order must not matter: the reader sits in an EARLIER-iterated
1727
+ -- schema (main) than the view it reads (temp)
1728
+ -- ===================================
1729
+ -- Within one schema a reader is always created after — and therefore iterated
1730
+ -- after — its dependency; putting the reader in main and the shifted view in
1731
+ -- temp exercises the reader-before-dependency visit order. Correctness cannot
1732
+ -- depend on it: the reader's reference is rewritten only in the round AFTER
1733
+ -- the view's shift is discovered.
1734
+
1735
+ create table temp.w_c58 (id integer primary key, x integer);
1736
+ insert into temp.w_c58 values (1, 21);
1737
+
1738
+ create view temp.v1_c58 as select id, x from temp.w_c58;
1739
+ create view main.v2_c58 as select id, x from temp.v1_c58;
1740
+
1741
+ alter table temp.w_c58 rename column x to y;
1742
+
1743
+ select id, y from main.v2_c58;
1744
+ → [{"id":1,"y":21}]
1745
+
1746
+ drop view main.v2_c58;
1747
+ drop view temp.v1_c58;
1748
+ drop table temp.w_c58;
1749
+
1750
+ -- ===================================
1751
+ -- 59. A case-only respelling is not a published-name collision
1752
+ -- ===================================
1753
+ -- `x` → `X` renames the column to a name every dependent already publishes —
1754
+ -- but that name IS the renamed column, not a second one, so the cascade's
1755
+ -- collision refusal must not fire. Both levels follow the new spelling.
1756
+
1757
+ create table w_c59 (id integer primary key, x integer);
1758
+ insert into w_c59 values (1, 6);
1759
+
1760
+ create view v1_c59 as select id, x from w_c59;
1761
+ create view v2_c59 as select x from v1_c59;
1762
+
1763
+ alter table w_c59 rename column x to X;
1764
+
1765
+ select X from v2_c59;
1766
+ → [{"X":6}]
1767
+
1768
+ drop view v2_c59;
1769
+ drop view v1_c59;
1770
+ drop table w_c59;
1771
+
1772
+ -- ===================================
1773
+ -- 60. The rewrite preserves what a reference resolves to when the NEW name
1774
+ -- is already taken earlier on the body's home path (collision)
1775
+ -- ===================================
1776
+ -- A temp-owned body reading bare `t_c60` means main.t_c60 (temp holds none).
1777
+ -- After `alter table main.t_c60 rename to t2_c60`, the bare new name would
1778
+ -- resolve to the pre-existing temp.t2_c60 instead — so the propagation adds
1779
+ -- the schema qualifier and every dependent keeps reading the renamed table.
1780
+ -- (§49 covers the no-collision half: bare rewrites stay unqualified there.)
1781
+
1782
+ create table main.t_c60 (id integer primary key, x integer);
1783
+ insert into main.t_c60 values (1, 10);
1784
+ -- The collision: temp already holds the rename target's name.
1785
+ create table temp.t2_c60 (id integer primary key, x integer);
1786
+ insert into temp.t2_c60 values (99, 999);
1787
+
1788
+ create view temp.v_c60 as select id, x from t_c60;
1789
+ create materialized view temp.mv_c60 as select id, x from t_c60;
1790
+ create assertion temp.a_c60 check (not exists (select 1 from t_c60 where x < 0));
1791
+
1792
+ alter table main.t_c60 rename to t2_c60;
1793
+
1794
+ -- The view still reads the renamed table, not temp.t2_c60.
1795
+ select id, x from temp.v_c60;
1796
+ → [{"id":1,"x":10}]
1797
+
1798
+ -- REFRESH re-plans the MV body from its stored text — the path that exposed a
1799
+ -- mis-bound bare reference — and must not swap in temp.t2_c60's rows.
1800
+ refresh materialized view temp.mv_c60;
1801
+
1802
+ select id, x from temp.mv_c60;
1803
+ → [{"id":1,"x":10}]
1804
+
1805
+ -- The assertion still enforces against the renamed table…
1806
+ insert into main.t2_c60 values (2, -1);
1807
+ -- error: Assertion
1808
+
1809
+ -- …and is NOT watching the same-named temp table.
1810
+ insert into temp.t2_c60 values (2, -1);
1811
+
1812
+ drop assertion temp.a_c60;
1813
+ drop materialized view temp.mv_c60;
1814
+ drop view temp.v_c60;
1815
+ drop table main.t2_c60;
1816
+ drop table temp.t2_c60;
1817
+
1818
+ -- ===================================
1819
+ -- 61. An inner reference binding a VIEW that exposes the old name is not
1820
+ -- false-captured by the rename
1821
+ -- ===================================
1822
+ -- The seeded CHECK walk stops at any inner FROM frame whose sources already
1823
+ -- expose the renamed column — otherwise the outer seed captures a name that
1824
+ -- legitimately binds inside the subquery. `buildColumnSourceResolver` answers
1825
+ -- that "does this source expose this column?" question for a VIEW (its explicit
1826
+ -- column list, else its body's projections and stars), not only for a table, so
1827
+ -- a view over ANOTHER table shields its own `v` exactly as that table would.
1828
+ -- The DROP COLUMN mirror of this case is 41.10.2 §36; the two verbs share the
1829
+ -- one resolver, which is what keeps them from drifting apart.
1830
+
1831
+ create table t_c61 (id integer primary key, v integer);
1832
+ create table u_c61 (id integer primary key, v integer);
1833
+ create view uv_c61 as select v from u_c61;
1834
+
1835
+ alter table t_c61 add constraint ck_c61 check (id < (select max(v) from uv_c61));
1836
+ insert into u_c61 values (1, 50);
1837
+
1838
+ alter table t_c61 rename column v to z;
1839
+
1840
+ -- The CHECK's `v` still names the view's column, so the constraint keeps
1841
+ -- enforcing the rule it was written for.
1842
+ insert into t_c61 values (10, 1);
1843
+
1844
+ select id, z from t_c61;
1845
+ → [{"id":10,"z":1}]
1846
+
1847
+ insert into t_c61 values (99, 2);
1848
+ -- error: ck_c61
1849
+
1850
+ -- The renamed column is the one the rename actually moved.
1851
+ insert into t_c61 (id, z) values (11, 7);
1852
+ select count(*) as c from t_c61;
1853
+ → [{"c":2}]
1854
+
1855
+ drop table t_c61;
1856
+ drop view uv_c61;
1857
+ drop table u_c61;
1858
+
1859
+ -- ===================================
1860
+ -- 62. Renaming a column of a table called "new" / "old" leaves OTHER tables'
1861
+ -- row-image qualifiers untouched
1862
+ -- ===================================
1863
+ -- Inside a CHECK, a column DEFAULT or a generated body, a bare unbound `new.<col>` /
1864
+ -- `old.<col>` names the row being written — that TABLE'S OWN row image, never a
1865
+ -- catalog table. So renaming a column of a real table called "new" must not touch
1866
+ -- another table's `new.v`: pre-fix it did, the other table's CHECK/DEFAULT then named
1867
+ -- a column it does not have, and every later write to it failed with an error naming
1868
+ -- neither the table nor the statement that broke it. §24/§29 pin the OWN-table rewrite
1869
+ -- (the qualifier follows its own table's rename); this section pins the foreign no-op.
1870
+
1871
+ create table "new" (id integer primary key, v integer);
1872
+ create table nwck_c62 (id integer primary key, v integer, constraint ck_c62 check (new.v > 0));
1873
+ create table nwdf_c62 (id integer primary key, v integer, d integer default (new.v + 1));
1874
+ insert into nwck_c62 values (1, 5);
1875
+ insert into nwdf_c62 (id, v) values (1, 4);
1876
+
1877
+ alter table "new" rename column v to w;
1878
+
1879
+ -- Both tables still writable: their qualifiers still name their own row images.
1880
+ -- (No generated-body arm: a generated expression rejects the `new.` qualifier
1881
+ -- outright — `new.v isn't a column` — so it cannot carry a foreign row image.
1882
+ -- The walker-level cell is pinned by test/schema/row-image-context-matrix.spec.ts.)
1883
+ insert into nwck_c62 values (2, 7);
1884
+ insert into nwdf_c62 (id, v) values (2, 9);
1885
+ select id, d from nwdf_c62 order by id;
1886
+ → [{"id":1,"d":5},{"id":2,"d":10}]
1887
+
1888
+ -- ...and the CHECK still enforces.
1889
+ insert into nwck_c62 values (3, -1);
1890
+ -- error: ck_c62
1891
+
1892
+ drop table nwdf_c62;
1893
+ drop table nwck_c62;
1894
+ drop table "new";
1895
+
1896
+ -- `old.` behaves identically.
1897
+ create table "old" (id integer primary key, v integer);
1898
+ create table odck_c62 (id integer primary key, v integer,
1899
+ constraint ckod_c62 check on update (old.v >= 0));
1900
+ insert into odck_c62 values (1, 5);
1901
+
1902
+ alter table "old" rename column v to w;
1903
+
1904
+ update odck_c62 set v = 6 where id = 1;
1905
+ select v from odck_c62;
1906
+ → [{"v":6}]
1907
+
1908
+ drop table odck_c62;
1909
+ drop table "old";
1910
+
1911
+ -- Controls: a GENUINE reference to the table called "new" still rewrites. A
1912
+ -- FROM-bound subquery reference (bare and qualified alike) is not a row image —
1913
+ -- the qualifier binds through the subquery's FROM, so the rename follows it.
1914
+ create table "new" (id integer primary key, v integer);
1915
+ insert into "new" values (1, 10);
1916
+ create table r_c62 (id integer primary key, n integer,
1917
+ constraint ckr_c62 check (n < (select max(v) from "new")));
1918
+ create table rq_c62 (id integer primary key, n integer,
1919
+ constraint ckrq_c62 check (n < (select max("new".v) from "new")));
1920
+
1921
+ alter table "new" rename column v to w;
1922
+
1923
+ insert into r_c62 values (1, 5);
1924
+ insert into rq_c62 values (1, 5);
1925
+ insert into r_c62 values (2, 99);
1926
+ -- error: ckr_c62
1927
+ insert into rq_c62 values (2, 99);
1928
+ -- error: ckrq_c62
1929
+
1930
+ -- ...and the OWN-table row image of "new" itself still follows its own rename
1931
+ -- (§24's shape, on a table that happens to be called "new").
1932
+ alter table "new" add constraint cknw_c62 check (new.w >= 0);
1933
+ alter table "new" rename column w to x;
1934
+ insert into "new" values (2, 20);
1935
+ insert into "new" values (3, -1);
1936
+ -- error: cknw_c62
1937
+
1938
+ drop table rq_c62;
1939
+ drop table r_c62;
1940
+ drop table "new";
1941
+
1942
+ -- ===================================
1943
+ -- 63. A `with inverse` expression's `new.` refs are inert to renames of a
1944
+ -- table called "new"
1945
+ -- ===================================
1946
+ -- Inside a result column's `with inverse (…)` clause, `new.<x>` names an OUTPUT
1947
+ -- column of the enclosing select (docs/sql-select.md § Result-column inverses) —
1948
+ -- written-row context sitting inside a view body. Neither a column rename nor a
1949
+ -- table rename of a real table called "new" may touch it; pre-fix both corrupted
1950
+ -- the clause and every later write through the view failed validation.
1951
+
1952
+ create table "new" (id integer primary key, v integer);
1953
+ create table people_c63 (id integer primary key, code5 text);
1954
+ create view vp_c63 as
1955
+ select id, case code5 when 'A1' then 'A' end as v
1956
+ with inverse (code5 = case new.v when 'A' then 'A1' end)
1957
+ from people_c63;
1958
+ insert into vp_c63 (id, v) values (1, 'A');
1959
+
1960
+ alter table "new" rename column v to w;
1961
+
1962
+ insert into vp_c63 (id, v) values (2, 'A');
1963
+ select id, code5 from people_c63 order by id;
1964
+ → [{"id":1,"code5":"A1"},{"id":2,"code5":"A1"}]
1965
+
1966
+ alter table "new" rename to fresh_c63;
1967
+
1968
+ insert into vp_c63 (id, v) values (3, 'A');
1969
+ select count(*) as c from people_c63;
1970
+ → [{"c":3}]
1971
+
1972
+ drop view vp_c63;
1973
+ drop table people_c63;
1974
+ drop table fresh_c63;
1975
+
1976
+ -- The same shape one level in from a seeded CHECK — the inverse clause of a
1977
+ -- subquery select inside another table's own CHECK is that INNER select's
1978
+ -- written-row namespace, not the outer table's, so the outer rename leaves its
1979
+ -- `new.a` alone (the inner output `a` is an alias and does not shift).
1980
+ create table src_c63 (id integer primary key, a integer);
1981
+ create table ck8_c63 (id integer primary key, a integer,
1982
+ constraint c8_c63 check (a < (select count(*)
1983
+ from (select id as a with inverse (id = new.a) from src_c63)) + 100));
1984
+
1985
+ alter table ck8_c63 rename column a to b;
1986
+
1987
+ insert into ck8_c63 (id, b) values (1, 0);
1988
+ select id, b from ck8_c63;
1989
+ → [{"id":1,"b":0}]
1990
+
1991
+ drop table ck8_c63;
1992
+ drop table src_c63;
1993
+
1994
+ -- ===================================
1995
+ -- 64. The output-name shift stops at a NESTED select's own inverse clause
1996
+ -- ===================================
1997
+ -- When a rename shifts the enclosing select's published output name, sibling
1998
+ -- `new.<old>` refs in its inverse clauses follow (§'s above). A subquery inside
1999
+ -- such an expression may be a select with its OWN inverse clause, whose `new.`
2000
+ -- refs belong to THAT select's outputs — the pass must not reach into it.
2001
+
2002
+ create table b_c64 (id integer primary key, v integer);
2003
+ create table c_c64 (id integer primary key, v integer);
2004
+ create view vw_c64 as
2005
+ select id, v
2006
+ with inverse (v = new.v + (select count(*)
2007
+ from (select v with inverse (v = new.v) from c_c64)))
2008
+ from b_c64;
2009
+ insert into c_c64 values (1, 1);
2010
+
2011
+ alter table b_c64 rename column v to w;
2012
+
2013
+ -- The outer output shifted v → w (readers follow, §54), so the outer `new.v`
2014
+ -- followed the shift; the inner select still publishes `v`, so its own `new.v`
2015
+ -- must not have moved. The write-through evaluates the outer clause:
2016
+ -- base w = new.w + count over c_c64 = 41 + 1.
2017
+ insert into vw_c64 (id, w) values (1, 41);
2018
+ select id, w from b_c64;
2019
+ → [{"id":1,"w":42}]
2020
+
2021
+ drop view vw_c64;
2022
+ drop table c_c64;
2023
+ drop table b_c64;
2024
+
2025
+ -- ===================================
2026
+ -- 65. RENAME COLUMN follows through an ALIASED FROM source
2027
+ -- ===================================
2028
+ -- A FROM alias adds a qualifier; it does not take the source's columns out of
2029
+ -- scope. So a bare `x` under `from t a` binds `t.x` and must follow the rename,
2030
+ -- and a bare star over an aliased source republishes like any other star — the
2031
+ -- cascade re-targets on it. Before the scope walk bound aliased sources, both
2032
+ -- bodies were left naming a column that no longer existed and every read of the
2033
+ -- view failed with `Column not found: x`.
2034
+
2035
+ create table al_c65 (id integer primary key, x integer);
2036
+ insert into al_c65 values (1, 5);
2037
+
2038
+ -- Bare ref under an alias, and a star over an aliased source.
2039
+ create view alv_c65 as select id, x from al_c65 a;
2040
+ create view als_c65 as select * from al_c65 a;
2041
+ -- A second-level reader pins the CASCADE: als_c65's published name shifts, so
2042
+ -- this body must be re-targeted too.
2043
+ create view alr_c65 as select x from als_c65;
2044
+ -- run
2045
+
2046
+ alter table al_c65 rename column x to z;
2047
+
2048
+ select id, z from alv_c65;
2049
+ → [{"id":1,"z":5}]
2050
+
2051
+ select id, z from als_c65;
2052
+ → [{"id":1,"z":5}]
2053
+
2054
+ select z from alr_c65;
2055
+ → [{"z":5}]
2056
+
2057
+ drop view alr_c65;
2058
+ drop view als_c65;
2059
+ drop view alv_c65;
2060
+ drop table al_c65;
2061
+ -- run
2062
+
2063
+ -- A MATERIALIZED view over an aliased source is a second site on the same walk:
2064
+ -- its body rewrite carries the shifted output name onto the backing table in
2065
+ -- place, so the star has to be recognised as a passthrough there too.
2066
+ create table alm_c65 (id integer primary key, x integer);
2067
+ insert into alm_c65 values (1, 5);
2068
+ create materialized view almv_c65 as select * from alm_c65 a;
2069
+ -- run
2070
+
2071
+ alter table alm_c65 rename column x to z;
2072
+
2073
+ select id, z from almv_c65;
2074
+ → [{"id":1,"z":5}]
2075
+
2076
+ drop materialized view almv_c65;
2077
+ drop table alm_c65;
2078
+ -- run
2079
+
2080
+ -- Guard rail: the widened binding must not capture a bare name that binds
2081
+ -- elsewhere. The inner `x` here belongs to the aliased alo_c65, so the rename of
2082
+ -- ali_c65.x must leave it alone and the view must keep planning.
2083
+ create table ali_c65 (id integer primary key, x integer);
2084
+ create table alo_c65 (id integer primary key, x integer);
2085
+ insert into ali_c65 values (1, 5);
2086
+ insert into alo_c65 values (1, 9);
2087
+ create view alg_c65 as select id, (select max(x) from alo_c65 b) as m from ali_c65;
2088
+ -- run
2089
+
2090
+ alter table ali_c65 rename column x to z;
2091
+
2092
+ select id, m from alg_c65;
2093
+ → [{"id":1,"m":9}]
2094
+
2095
+ drop view alg_c65;
2096
+ drop table alo_c65;
2097
+ drop table ali_c65;
2098
+ -- run
2099
+
2100
+ -- A `with defaults` target is the third site on the widened binding, and the one
2101
+ -- least like a body reference: the clause names a projected-away base column and
2102
+ -- rides the walk as a synthetic bare ref (see § 18 for the unaliased spelling), so
2103
+ -- an aliased FROM used to leave it un-rewritten and the write-through then failed
2104
+ -- with "'with defaults (created = …)' names column 'created'".
2105
+ create table ald_c65 (id integer primary key, name text, created integer not null);
2106
+ create view alvd_c65 as select id, name from ald_c65 a with defaults (created = 99);
2107
+ -- run
2108
+
2109
+ alter table ald_c65 rename column created to created_at;
2110
+
2111
+ insert into alvd_c65 values (1, 'x');
2112
+
2113
+ select id, name, created_at from ald_c65;
2114
+ → [{"id":1,"name":"x","created_at":99}]
2115
+
2116
+ drop view alvd_c65;
2117
+ drop table ald_c65;
2118
+ -- run
2119
+
2120
+ -- ...and the `with inverse` ASSIGNMENT TARGET, the fourth site: also a bare
2121
+ -- base-column name riding the walk as a synthetic probe (§ 63 covers the clause's
2122
+ -- `new.` refs, which stay inert either way). Under an aliased FROM the target used
2123
+ -- to be left naming the old column, and every write through the view then failed.
2124
+ create table ali2_c65 (id integer primary key, code5 text);
2125
+ create view alvi_c65 as
2126
+ select id, case code5 when 'A1' then 'A' end as v
2127
+ with inverse (code5 = case new.v when 'A' then 'A1' end)
2128
+ from ali2_c65 a;
2129
+ insert into alvi_c65 (id, v) values (1, 'A');
2130
+ -- run
2131
+
2132
+ alter table ali2_c65 rename column code5 to code6;
2133
+
2134
+ insert into alvi_c65 (id, v) values (2, 'A');
2135
+
2136
+ select id, code6 from ali2_c65 order by id;
2137
+ → [{"id":1,"code6":"A1"},{"id":2,"code6":"A1"}]
2138
+
2139
+ drop view alvi_c65;
2140
+ drop table ali2_c65;
2141
+ -- run
2142
+
2143
+ -- ===================================
2144
+ -- 66. A rename must not change what an UNTOUCHED reference resolves to
2145
+ -- ===================================
2146
+ -- The mirror of §60. There the rename REWROTE a reference and had to keep it
2147
+ -- pointing at the renamed table; here it rewrites nothing at all, but the name
2148
+ -- it CREATES captures a reference whose body never mentions the renamed table.
2149
+ -- A temp-owned body reading bare `k_c66` means main.k_c66 (temp holds none);
2150
+ -- `alter table temp.o_c66 rename to k_c66` puts a `k_c66` in temp, earlier on
2151
+ -- that body's home path. Every dependent must keep reading main.k_c66.
2152
+
2153
+ create table main.k_c66 (id integer primary key, x integer);
2154
+ insert into main.k_c66 values (1, 10);
2155
+ -- The capture: renaming this onto `k_c66` shadows main.k_c66 for temp-owned bodies.
2156
+ create table temp.o_c66 (id integer primary key, x integer);
2157
+ insert into temp.o_c66 values (99, 999);
2158
+
2159
+ create view temp.v_c66 as select id, x from k_c66;
2160
+ create materialized view temp.mv_c66 as select id, x from k_c66;
2161
+ create assertion temp.a_c66 check (not exists (select 1 from k_c66 where x < 0));
2162
+ -- A main-owned body reading the same bare name: main leads its own home path,
2163
+ -- so nothing can capture it and its stored text must not churn.
2164
+ create view main.vm_c66 as select id, x from k_c66;
2165
+
2166
+ alter table temp.o_c66 rename to k_c66;
2167
+
2168
+ select id, x from temp.v_c66;
2169
+ → [{"id":1,"x":10}]
2170
+
2171
+ select id, x from main.vm_c66;
2172
+ → [{"id":1,"x":10}]
2173
+
2174
+ -- The already-materialized rows mask a re-bind until the stored body re-plans.
2175
+ refresh materialized view temp.mv_c66;
2176
+
2177
+ select id, x from temp.mv_c66;
2178
+ → [{"id":1,"x":10}]
2179
+
2180
+ -- The assertion still enforces against main.k_c66…
2181
+ insert into main.k_c66 values (2, -1);
2182
+ -- error: Assertion
2183
+
2184
+ -- …and is NOT watching the table that took its name.
2185
+ insert into temp.k_c66 values (2, -1);
2186
+
2187
+ drop view main.vm_c66;
2188
+ drop assertion temp.a_c66;
2189
+ drop materialized view temp.mv_c66;
2190
+ drop view temp.v_c66;
2191
+ drop table temp.k_c66;
2192
+ drop table main.k_c66;
2193
+
2194
+ -- ===================================
2195
+ -- 67. A rename must not change what a body QUALIFIER binds
2196
+ -- ===================================
2197
+ -- Inside one body, the bare qualifier an unaliased FROM source exposes must
2198
+ -- keep binding that source. Renaming a source onto a name already live as a
2199
+ -- qualifier in that part of the body pins the pre-rename spelling as an
2200
+ -- explicit alias (`from t2 as t`), so `t.x` keeps reading the renamed table
2201
+ -- instead of collapsing onto whichever same-spelled source wins.
2202
+
2203
+ -- Sibling source in another schema: the join must not become self-referential.
2204
+ create table main.qa_c67 (id integer primary key, x integer);
2205
+ insert into main.qa_c67 values (1, 10);
2206
+ create table temp.qb_c67 (id integer primary key, x integer);
2207
+ insert into temp.qb_c67 values (2, 20);
2208
+ create view temp.qv_c67 as select qa_c67.x as a, qb_c67.x as b from qa_c67 join temp.qb_c67 on qa_c67.id = qb_c67.id - 1;
2209
+
2210
+ select * from temp.qv_c67;
2211
+ → [{"a": 10, "b": 20}]
2212
+
2213
+ alter table main.qa_c67 rename to qb_c67;
2214
+
2215
+ select * from temp.qv_c67;
2216
+ → [{"a": 10, "b": 20}]
2217
+
2218
+ drop view temp.qv_c67;
2219
+ drop table temp.qb_c67;
2220
+ drop table main.qb_c67;
2221
+ -- run
2222
+
2223
+ -- Sibling's alias, single schema: b must keep reading the aliased table.
2224
+ create table qt_c67 (id integer primary key, x integer);
2225
+ insert into qt_c67 values (1, 10);
2226
+ create table qu_c67 (id integer primary key, x integer);
2227
+ insert into qu_c67 values (1, 77);
2228
+ create view qw_c67 as select qt_c67.x as a, z.x as b from qt_c67 join qu_c67 as z on qt_c67.id = z.id;
2229
+
2230
+ alter table qt_c67 rename to z;
2231
+
2232
+ select * from qw_c67;
2233
+ → [{"a": 10, "b": 77}]
2234
+
2235
+ drop view qw_c67;
2236
+ drop table qu_c67;
2237
+ drop table z;
2238
+ -- run
2239
+
2240
+ -- CTE the body declares: the renamed source is schema-qualified as well as
2241
+ -- aliased (a bare source spelling the CTE's name would bind the CTE outright).
2242
+ create table qc_c67 (id integer primary key, x integer);
2243
+ insert into qc_c67 values (1, 10);
2244
+ create view qcv_c67 as with c as (select 1 as id, 999 as x) select qc_c67.x as a, c.x as b from qc_c67 join c on qc_c67.id = c.id;
2245
+
2246
+ alter table qc_c67 rename to c;
2247
+
2248
+ select * from qcv_c67;
2249
+ → [{"a": 10, "b": 999}]
2250
+
2251
+ drop view qcv_c67;
2252
+ drop table c;
2253
+ -- run
2254
+
2255
+ -- Enclosing frame's qualifier: the correlated EXISTS must stay correlated.
2256
+ -- id 7 has no match in the renamed table, so a lost correlation would admit it.
2257
+ create table main.qe_c67 (id integer primary key, x integer);
2258
+ insert into main.qe_c67 values (1, 10);
2259
+ create table temp.qf_c67 (id integer primary key, x integer);
2260
+ insert into temp.qf_c67 values (1, 20), (7, 70);
2261
+ create view temp.qev_c67 as select qf_c67.x as a from temp.qf_c67 where exists (select 1 from qe_c67 where qe_c67.id = qf_c67.id);
2262
+
2263
+ alter table main.qe_c67 rename to qf_c67;
2264
+
2265
+ select * from temp.qev_c67 order by a;
2266
+ → [{"a": 20}]
2267
+
2268
+ drop view temp.qev_c67;
2269
+ drop table temp.qf_c67;
2270
+ drop table main.qf_c67;
2271
+ -- run
2272
+
2273
+ -- Deep capture: an alias of the new name INSIDE a correlated subquery would
2274
+ -- capture the outer qualifier's new spelling — the outer source aliases too.
2275
+ create table qg_c67 (id integer primary key, x integer);
2276
+ insert into qg_c67 values (1, 10), (2, 20);
2277
+ create table qh_c67 (id integer primary key);
2278
+ insert into qh_c67 values (1);
2279
+ create view qgv_c67 as select qg_c67.x from qg_c67 where exists (select 1 from qh_c67 as g2 where g2.id = qg_c67.id);
2280
+
2281
+ alter table qg_c67 rename to g2;
2282
+
2283
+ select * from qgv_c67;
2284
+ → [{"x": 10}]
2285
+
2286
+ drop view qgv_c67;
2287
+ drop table qh_c67;
2288
+ drop table g2;
2289
+ -- run
2290
+
2291
+ -- Control: a source that already carries an author alias needs no pin — the
2292
+ -- alias is the qualifier and a rename never moves it.
2293
+ create table qi_c67 (id integer primary key, x integer);
2294
+ insert into qi_c67 values (1, 10);
2295
+ create table temp.qj_c67 (id integer primary key, x integer);
2296
+ insert into temp.qj_c67 values (1, 20);
2297
+ create view temp.qiv_c67 as select tt.x as a, qj_c67.x as b from qi_c67 as tt join temp.qj_c67 on tt.id = qj_c67.id;
2298
+
2299
+ alter table qi_c67 rename to qj_c67;
2300
+
2301
+ select * from temp.qiv_c67;
2302
+ → [{"a": 10, "b": 20}]
2303
+
2304
+ drop view temp.qiv_c67;
2305
+ drop table temp.qj_c67;
2306
+ drop table main.qj_c67;
2307
+ -- run
2308
+
2309
+ -- Materialized-view twin: a maintained body is rewritten by the same walk, so
2310
+ -- the pin must survive the re-hash and re-plan the refresh performs.
2311
+ create table qm_c67 (id integer primary key, x integer);
2312
+ insert into qm_c67 values (1, 10);
2313
+ create table qn_c67 (id integer primary key, x integer);
2314
+ insert into qn_c67 values (1, 77);
2315
+ create materialized view qmv_c67 as select qm_c67.id as k, qm_c67.x as a, z_c67.x as b from qm_c67 join qn_c67 as z_c67 on qm_c67.id = z_c67.id;
2316
+
2317
+ select * from qmv_c67;
2318
+ → [{"k": 1, "a": 10, "b": 77}]
2319
+
2320
+ alter table qm_c67 rename to z_c67;
2321
+
2322
+ -- The stored rows mask a re-bind until the body re-plans.
2323
+ refresh materialized view qmv_c67;
2324
+
2325
+ select * from qmv_c67;
2326
+ → [{"k": 1, "a": 10, "b": 77}]
2327
+
2328
+ drop materialized view qmv_c67;
2329
+ drop table qn_c67;
2330
+ drop table z_c67;
2331
+ -- run
2332
+
2333
+ -- Assertion twin: the stored CHECK body goes through the same walk, so its
2334
+ -- qualifiers must keep binding what they bound.
2335
+ create table qp_c67 (id integer primary key, x integer);
2336
+ insert into qp_c67 values (1, 10);
2337
+ create table qq_c67 (id integer primary key, x integer);
2338
+ insert into qq_c67 values (1, 77), (2, 77), (3, 77);
2339
+ create assertion qa_c67 check (not exists (select 1 from qp_c67 join qq_c67 as w_c67 on qp_c67.id = w_c67.id where qp_c67.x < 0));
2340
+
2341
+ alter table qp_c67 rename to w_c67;
2342
+
2343
+ -- Still watching the renamed table…
2344
+ insert into w_c67 values (2, -1);
2345
+ -- error: Assertion
2346
+
2347
+ -- …and not the sibling whose alias it now spells.
2348
+ insert into qq_c67 values (4, -1);
2349
+
2350
+ drop assertion qa_c67;
2351
+ drop table qq_c67;
2352
+ drop table w_c67;