@quereus/quereus 4.8.0 → 4.10.0
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.
- package/dist/src/core/database.d.ts +6 -0
- package/dist/src/core/database.d.ts.map +1 -1
- package/dist/src/core/database.js +45 -5
- package/dist/src/core/database.js.map +1 -1
- package/dist/src/core/statement.d.ts.map +1 -1
- package/dist/src/core/statement.js +74 -15
- package/dist/src/core/statement.js.map +1 -1
- package/dist/src/func/builtins/aggregate.d.ts.map +1 -1
- package/dist/src/func/builtins/aggregate.js +88 -35
- package/dist/src/func/builtins/aggregate.js.map +1 -1
- package/dist/src/func/builtins/conversion.d.ts +5 -0
- package/dist/src/func/builtins/conversion.d.ts.map +1 -1
- package/dist/src/func/builtins/conversion.js +16 -2
- package/dist/src/func/builtins/conversion.js.map +1 -1
- package/dist/src/func/builtins/explain.d.ts.map +1 -1
- package/dist/src/func/builtins/explain.js +9 -2
- package/dist/src/func/builtins/explain.js.map +1 -1
- package/dist/src/func/builtins/index.d.ts.map +1 -1
- package/dist/src/func/builtins/index.js +5 -2
- package/dist/src/func/builtins/index.js.map +1 -1
- package/dist/src/func/builtins/scalar.d.ts.map +1 -1
- package/dist/src/func/builtins/scalar.js +4 -2
- package/dist/src/func/builtins/scalar.js.map +1 -1
- package/dist/src/func/builtins/string.d.ts +2 -0
- package/dist/src/func/builtins/string.d.ts.map +1 -1
- package/dist/src/func/builtins/string.js +60 -4
- package/dist/src/func/builtins/string.js.map +1 -1
- package/dist/src/func/registration.d.ts +6 -0
- package/dist/src/func/registration.d.ts.map +1 -1
- package/dist/src/func/registration.js +1 -0
- package/dist/src/func/registration.js.map +1 -1
- package/dist/src/index.d.ts +7 -3
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +21 -2
- package/dist/src/index.js.map +1 -1
- package/dist/src/planner/building/constraint-builder.js +1 -1
- package/dist/src/planner/building/constraint-builder.js.map +1 -1
- package/dist/src/planner/nodes/scalar.d.ts.map +1 -1
- package/dist/src/planner/nodes/scalar.js +13 -1
- package/dist/src/planner/nodes/scalar.js.map +1 -1
- package/dist/src/planner/rules/retrieve/rule-grow-retrieve.d.ts.map +1 -1
- package/dist/src/planner/rules/retrieve/rule-grow-retrieve.js +121 -51
- package/dist/src/planner/rules/retrieve/rule-grow-retrieve.js.map +1 -1
- package/dist/src/planner/rules/shared/index-style-context.d.ts +14 -4
- package/dist/src/planner/rules/shared/index-style-context.d.ts.map +1 -1
- package/dist/src/planner/rules/shared/index-style-context.js +14 -4
- package/dist/src/planner/rules/shared/index-style-context.js.map +1 -1
- package/dist/src/runtime/emission-context.d.ts +14 -1
- package/dist/src/runtime/emission-context.d.ts.map +1 -1
- package/dist/src/runtime/emission-context.js +17 -5
- package/dist/src/runtime/emission-context.js.map +1 -1
- package/dist/src/runtime/emit/aggregate-setup.d.ts +44 -8
- package/dist/src/runtime/emit/aggregate-setup.d.ts.map +1 -1
- package/dist/src/runtime/emit/aggregate-setup.js +79 -15
- package/dist/src/runtime/emit/aggregate-setup.js.map +1 -1
- package/dist/src/runtime/emit/aggregate.d.ts.map +1 -1
- package/dist/src/runtime/emit/aggregate.js +21 -106
- package/dist/src/runtime/emit/aggregate.js.map +1 -1
- package/dist/src/runtime/emit/alter-table.d.ts.map +1 -1
- package/dist/src/runtime/emit/alter-table.js +212 -155
- package/dist/src/runtime/emit/alter-table.js.map +1 -1
- package/dist/src/runtime/emit/asof-scan.js +1 -1
- package/dist/src/runtime/emit/asof-scan.js.map +1 -1
- package/dist/src/runtime/emit/assertion-drop-guard.d.ts +26 -12
- package/dist/src/runtime/emit/assertion-drop-guard.d.ts.map +1 -1
- package/dist/src/runtime/emit/assertion-drop-guard.js +45 -26
- package/dist/src/runtime/emit/assertion-drop-guard.js.map +1 -1
- package/dist/src/runtime/emit/assertion-rename-helpers.d.ts +6 -6
- package/dist/src/runtime/emit/assertion-rename-helpers.d.ts.map +1 -1
- package/dist/src/runtime/emit/assertion-rename-helpers.js +18 -20
- package/dist/src/runtime/emit/assertion-rename-helpers.js.map +1 -1
- package/dist/src/runtime/emit/between.d.ts +2 -0
- package/dist/src/runtime/emit/between.d.ts.map +1 -1
- package/dist/src/runtime/emit/between.js +7 -8
- package/dist/src/runtime/emit/between.js.map +1 -1
- package/dist/src/runtime/emit/binary.d.ts +27 -5
- package/dist/src/runtime/emit/binary.d.ts.map +1 -1
- package/dist/src/runtime/emit/binary.js +278 -187
- package/dist/src/runtime/emit/binary.js.map +1 -1
- package/dist/src/runtime/emit/case.d.ts +34 -0
- package/dist/src/runtime/emit/case.d.ts.map +1 -1
- package/dist/src/runtime/emit/case.js +18 -11
- package/dist/src/runtime/emit/case.js.map +1 -1
- package/dist/src/runtime/emit/cast.d.ts +2 -0
- package/dist/src/runtime/emit/cast.d.ts.map +1 -1
- package/dist/src/runtime/emit/cast.js +7 -5
- package/dist/src/runtime/emit/cast.js.map +1 -1
- package/dist/src/runtime/emit/column-reference.d.ts +3 -1
- package/dist/src/runtime/emit/column-reference.d.ts.map +1 -1
- package/dist/src/runtime/emit/column-reference.js +6 -2
- package/dist/src/runtime/emit/column-reference.js.map +1 -1
- package/dist/src/runtime/emit/column-rename-cascade.d.ts +84 -0
- package/dist/src/runtime/emit/column-rename-cascade.d.ts.map +1 -0
- package/dist/src/runtime/emit/column-rename-cascade.js +134 -0
- package/dist/src/runtime/emit/column-rename-cascade.js.map +1 -0
- package/dist/src/runtime/emit/dml-executor.d.ts.map +1 -1
- package/dist/src/runtime/emit/dml-executor.js +21 -0
- package/dist/src/runtime/emit/dml-executor.js.map +1 -1
- package/dist/src/runtime/emit/drop-column-guards.d.ts +82 -53
- package/dist/src/runtime/emit/drop-column-guards.d.ts.map +1 -1
- package/dist/src/runtime/emit/drop-column-guards.js +155 -90
- package/dist/src/runtime/emit/drop-column-guards.js.map +1 -1
- package/dist/src/runtime/emit/drop-table.d.ts.map +1 -1
- package/dist/src/runtime/emit/drop-table.js +5 -0
- package/dist/src/runtime/emit/drop-table.js.map +1 -1
- package/dist/src/runtime/emit/drop-view.d.ts.map +1 -1
- package/dist/src/runtime/emit/drop-view.js +5 -0
- package/dist/src/runtime/emit/drop-view.js.map +1 -1
- package/dist/src/runtime/emit/expression-drop-guard.d.ts +57 -0
- package/dist/src/runtime/emit/expression-drop-guard.d.ts.map +1 -0
- package/dist/src/runtime/emit/expression-drop-guard.js +82 -0
- package/dist/src/runtime/emit/expression-drop-guard.js.map +1 -0
- package/dist/src/runtime/emit/filter.d.ts +1 -1
- package/dist/src/runtime/emit/filter.js +1 -1
- package/dist/src/runtime/emit/hash-aggregate.d.ts.map +1 -1
- package/dist/src/runtime/emit/hash-aggregate.js +18 -88
- package/dist/src/runtime/emit/hash-aggregate.js.map +1 -1
- package/dist/src/runtime/emit/literal.d.ts +14 -1
- package/dist/src/runtime/emit/literal.d.ts.map +1 -1
- package/dist/src/runtime/emit/literal.js +33 -7
- package/dist/src/runtime/emit/literal.js.map +1 -1
- package/dist/src/runtime/emit/materialized-view-helpers.d.ts +33 -10
- package/dist/src/runtime/emit/materialized-view-helpers.d.ts.map +1 -1
- package/dist/src/runtime/emit/materialized-view-helpers.js +158 -49
- package/dist/src/runtime/emit/materialized-view-helpers.js.map +1 -1
- package/dist/src/runtime/emit/materialized-view.d.ts.map +1 -1
- package/dist/src/runtime/emit/materialized-view.js +3 -0
- package/dist/src/runtime/emit/materialized-view.js.map +1 -1
- package/dist/src/runtime/emit/parameter.d.ts +3 -1
- package/dist/src/runtime/emit/parameter.d.ts.map +1 -1
- package/dist/src/runtime/emit/parameter.js +7 -2
- package/dist/src/runtime/emit/parameter.js.map +1 -1
- package/dist/src/runtime/emit/scalar-function.d.ts +29 -1
- package/dist/src/runtime/emit/scalar-function.d.ts.map +1 -1
- package/dist/src/runtime/emit/scalar-function.js +66 -16
- package/dist/src/runtime/emit/scalar-function.js.map +1 -1
- package/dist/src/runtime/emit/scalar-op.d.ts +63 -0
- package/dist/src/runtime/emit/scalar-op.d.ts.map +1 -0
- package/dist/src/runtime/emit/scalar-op.js +37 -0
- package/dist/src/runtime/emit/scalar-op.js.map +1 -0
- package/dist/src/runtime/emit/scan.d.ts.map +1 -1
- package/dist/src/runtime/emit/scan.js +19 -1
- package/dist/src/runtime/emit/scan.js.map +1 -1
- package/dist/src/runtime/emit/temporal-arithmetic.d.ts +18 -8
- package/dist/src/runtime/emit/temporal-arithmetic.d.ts.map +1 -1
- package/dist/src/runtime/emit/temporal-arithmetic.js +29 -311
- package/dist/src/runtime/emit/temporal-arithmetic.js.map +1 -1
- package/dist/src/runtime/emit/unary.d.ts +2 -0
- package/dist/src/runtime/emit/unary.d.ts.map +1 -1
- package/dist/src/runtime/emit/unary.js +125 -53
- package/dist/src/runtime/emit/unary.js.map +1 -1
- package/dist/src/runtime/emitters.d.ts +22 -0
- package/dist/src/runtime/emitters.d.ts.map +1 -1
- package/dist/src/runtime/emitters.js +29 -0
- package/dist/src/runtime/emitters.js.map +1 -1
- package/dist/src/runtime/scalar-fusion.d.ts +47 -0
- package/dist/src/runtime/scalar-fusion.d.ts.map +1 -0
- package/dist/src/runtime/scalar-fusion.js +275 -0
- package/dist/src/runtime/scalar-fusion.js.map +1 -0
- package/dist/src/runtime/strict-flags.d.ts +9 -0
- package/dist/src/runtime/strict-flags.d.ts.map +1 -1
- package/dist/src/runtime/strict-flags.js +9 -0
- package/dist/src/runtime/strict-flags.js.map +1 -1
- package/dist/src/runtime/strict-fork.js +2 -2
- package/dist/src/runtime/strict-fork.js.map +1 -1
- package/dist/src/runtime/strict-representation.d.ts +78 -0
- package/dist/src/runtime/strict-representation.d.ts.map +1 -0
- package/dist/src/runtime/strict-representation.js +159 -0
- package/dist/src/runtime/strict-representation.js.map +1 -0
- package/dist/src/schema/assertion.d.ts +58 -0
- package/dist/src/schema/assertion.d.ts.map +1 -1
- package/dist/src/schema/assertion.js +78 -0
- package/dist/src/schema/assertion.js.map +1 -1
- package/dist/src/schema/catalog-persistability.d.ts +11 -3
- package/dist/src/schema/catalog-persistability.d.ts.map +1 -1
- package/dist/src/schema/catalog-persistability.js +48 -29
- package/dist/src/schema/catalog-persistability.js.map +1 -1
- package/dist/src/schema/catalog.d.ts +22 -0
- package/dist/src/schema/catalog.d.ts.map +1 -1
- package/dist/src/schema/catalog.js +4 -1
- package/dist/src/schema/catalog.js.map +1 -1
- package/dist/src/schema/column-republication.d.ts +126 -0
- package/dist/src/schema/column-republication.d.ts.map +1 -0
- package/dist/src/schema/column-republication.js +121 -0
- package/dist/src/schema/column-republication.js.map +1 -0
- package/dist/src/schema/column-source-resolver.d.ts +29 -6
- package/dist/src/schema/column-source-resolver.d.ts.map +1 -1
- package/dist/src/schema/column-source-resolver.js +78 -9
- package/dist/src/schema/column-source-resolver.js.map +1 -1
- package/dist/src/schema/expression-dependents.d.ts +160 -0
- package/dist/src/schema/expression-dependents.d.ts.map +1 -0
- package/dist/src/schema/expression-dependents.js +228 -0
- package/dist/src/schema/expression-dependents.js.map +1 -0
- package/dist/src/schema/function.d.ts +15 -0
- package/dist/src/schema/function.d.ts.map +1 -1
- package/dist/src/schema/function.js.map +1 -1
- package/dist/src/schema/object-dependency-closure.d.ts +127 -0
- package/dist/src/schema/object-dependency-closure.d.ts.map +1 -0
- package/dist/src/schema/object-dependency-closure.js +117 -0
- package/dist/src/schema/object-dependency-closure.js.map +1 -0
- package/dist/src/schema/object-ref-resolver.d.ts +83 -0
- package/dist/src/schema/object-ref-resolver.d.ts.map +1 -0
- package/dist/src/schema/object-ref-resolver.js +135 -0
- package/dist/src/schema/object-ref-resolver.js.map +1 -0
- package/dist/src/schema/rename/column-rename.d.ts +228 -0
- package/dist/src/schema/rename/column-rename.d.ts.map +1 -0
- package/dist/src/schema/rename/column-rename.js +1225 -0
- package/dist/src/schema/rename/column-rename.js.map +1 -0
- package/dist/src/schema/rename/self-qualifier-strip.d.ts +29 -0
- package/dist/src/schema/rename/self-qualifier-strip.d.ts.map +1 -0
- package/dist/src/schema/rename/self-qualifier-strip.js +267 -0
- package/dist/src/schema/rename/self-qualifier-strip.js.map +1 -0
- package/dist/src/schema/rename/shared.d.ts +108 -0
- package/dist/src/schema/rename/shared.d.ts.map +1 -0
- package/dist/src/schema/rename/shared.js +49 -0
- package/dist/src/schema/rename/shared.js.map +1 -0
- package/dist/src/schema/rename/table-rename.d.ts +263 -0
- package/dist/src/schema/rename/table-rename.d.ts.map +1 -0
- package/dist/src/schema/rename/table-rename.js +860 -0
- package/dist/src/schema/rename/table-rename.js.map +1 -0
- package/dist/src/schema/rename-rewriter.d.ts +18 -278
- package/dist/src/schema/rename-rewriter.d.ts.map +1 -1
- package/dist/src/schema/rename-rewriter.js +17 -1506
- package/dist/src/schema/rename-rewriter.js.map +1 -1
- package/dist/src/schema/schema-differ.d.ts.map +1 -1
- package/dist/src/schema/schema-differ.js +228 -21
- package/dist/src/schema/schema-differ.js.map +1 -1
- package/dist/src/types/builtin-types.d.ts.map +1 -1
- package/dist/src/types/builtin-types.js +29 -36
- package/dist/src/types/builtin-types.js.map +1 -1
- package/dist/src/types/cast-semantics.d.ts +7 -5
- package/dist/src/types/cast-semantics.d.ts.map +1 -1
- package/dist/src/types/cast-semantics.js +20 -9
- package/dist/src/types/cast-semantics.js.map +1 -1
- package/dist/src/types/index.d.ts +1 -1
- package/dist/src/types/index.d.ts.map +1 -1
- package/dist/src/types/index.js +1 -1
- package/dist/src/types/index.js.map +1 -1
- package/dist/src/types/registry.d.ts.map +1 -1
- package/dist/src/types/registry.js +2 -1
- package/dist/src/types/registry.js.map +1 -1
- package/dist/src/types/temporal-ops.d.ts +119 -0
- package/dist/src/types/temporal-ops.d.ts.map +1 -0
- package/dist/src/types/temporal-ops.js +348 -0
- package/dist/src/types/temporal-ops.js.map +1 -0
- package/dist/src/types/temporal-types.d.ts +11 -0
- package/dist/src/types/temporal-types.d.ts.map +1 -1
- package/dist/src/types/temporal-types.js +87 -0
- package/dist/src/types/temporal-types.js.map +1 -1
- package/dist/src/util/affinity.d.ts +2 -1
- package/dist/src/util/affinity.d.ts.map +1 -1
- package/dist/src/util/affinity.js +16 -5
- package/dist/src/util/affinity.js.map +1 -1
- package/dist/src/util/ast-spine-clone.d.ts +2 -2
- package/dist/src/util/ast-spine-clone.js +2 -2
- package/dist/src/util/coercion.d.ts +22 -7
- package/dist/src/util/coercion.d.ts.map +1 -1
- package/dist/src/util/coercion.js +28 -15
- package/dist/src/util/coercion.js.map +1 -1
- package/dist/src/util/comparison.d.ts +25 -0
- package/dist/src/util/comparison.d.ts.map +1 -1
- package/dist/src/util/comparison.js +25 -0
- package/dist/src/util/comparison.js.map +1 -1
- package/dist/src/util/key-tuple-codec.d.ts +12 -3
- package/dist/src/util/key-tuple-codec.d.ts.map +1 -1
- package/dist/src/util/key-tuple-codec.js.map +1 -1
- package/dist/src/util/numeric-canonical.d.ts +26 -0
- package/dist/src/util/numeric-canonical.d.ts.map +1 -0
- package/dist/src/util/numeric-canonical.js +66 -0
- package/dist/src/util/numeric-canonical.js.map +1 -0
- package/dist/src/util/value-text.d.ts +48 -0
- package/dist/src/util/value-text.d.ts.map +1 -0
- package/dist/src/util/value-text.js +35 -0
- package/dist/src/util/value-text.js.map +1 -0
- package/dist/src/vtab/memory/layer/manager.d.ts.map +1 -1
- package/dist/src/vtab/memory/layer/manager.js +14 -5
- package/dist/src/vtab/memory/layer/manager.js.map +1 -1
- package/dist/src/vtab/module.d.ts +25 -0
- package/dist/src/vtab/module.d.ts.map +1 -1
- package/package.json +4 -3
|
@@ -777,14 +777,30 @@ function hasApplicableConstraints(db, mt) {
|
|
|
777
777
|
* the LIVE record here. So the live record is swapped for a constraint-stripped
|
|
778
778
|
* clone for the duration of the scans (the ADD COLUMN intermediate-schema
|
|
779
779
|
* discipline, see `runtime/emit/alter-table.ts`), then restored.
|
|
780
|
+
*
|
|
781
|
+
* `validationColumns` (the reshape arms only, {@link previewReshapedColumns})
|
|
782
|
+
* overrides the clone's column list with the attributes the reshape is ABOUT TO
|
|
783
|
+
* land, so a CHECK / FK resolves its affinity and collation from the final
|
|
784
|
+
* declared shape rather than the one being replaced. Comparison semantics are a
|
|
785
|
+
* function of the DECLARED column attributes, and the reshape's `retype` /
|
|
786
|
+
* `recollate` module ops run after this scan (they convert stored rows, so they
|
|
787
|
+
* must); without the override this scan would evaluate `v < '9'` on a column
|
|
788
|
+
* moving TEXT → INTEGER as a text comparison and admit a row that violates the
|
|
789
|
+
* constraint under the type it is about to have. Omitted (⇒ `mt.columns`) on
|
|
790
|
+
* every non-reshape path, so those stay byte-identical.
|
|
780
791
|
*/
|
|
781
|
-
async function validateDeclaredConstraintsOverContents(db, mt) {
|
|
792
|
+
async function validateDeclaredConstraintsOverContents(db, mt, validationColumns) {
|
|
782
793
|
const applicableChecks = mt.checkConstraints.filter(c => (c.operations & (RowOpFlag.INSERT | RowOpFlag.UPDATE)) !== 0);
|
|
783
794
|
const fks = mt.foreignKeys ?? [];
|
|
784
795
|
if (applicableChecks.length === 0 && fks.length === 0)
|
|
785
796
|
return;
|
|
786
797
|
const schema = db.schemaManager.getSchemaOrFail(mt.schemaName);
|
|
787
|
-
const stripped = {
|
|
798
|
+
const stripped = {
|
|
799
|
+
...mt,
|
|
800
|
+
columns: validationColumns ?? mt.columns,
|
|
801
|
+
checkConstraints: Object.freeze([]),
|
|
802
|
+
foreignKeys: undefined,
|
|
803
|
+
};
|
|
788
804
|
schema.addTable(stripped);
|
|
789
805
|
try {
|
|
790
806
|
await validateChecksOverExistingRows(db, mt, applicableChecks, (check, exprSql) => maintainedTableCheckViolationError(mt.schemaName, mt.name, check.name ?? `_check_${mt.checkConstraints.indexOf(check)}`, exprSql));
|
|
@@ -1079,8 +1095,11 @@ discardBackingOnFailure = false) {
|
|
|
1079
1095
|
changes = await host.applyMaintenance(conn, [{ kind: 'replace-all', rows }]);
|
|
1080
1096
|
// Declared CHECK / child-side FK over the reconciled (derived) row set —
|
|
1081
1097
|
// inside this try so a violation restores the prior record; the pending
|
|
1082
|
-
// reconcile writes roll back with the failing statement.
|
|
1083
|
-
|
|
1098
|
+
// reconcile writes roll back with the failing statement. On the reshape arm
|
|
1099
|
+
// the scan resolves against the attributes the post-reconcile ops below are
|
|
1100
|
+
// about to land, keeping this path identical to the refresh reshape arm
|
|
1101
|
+
// (`reshapeBackingInPlace` → `rebuildBacking`).
|
|
1102
|
+
await validateDeclaredConstraintsOverContents(db, live, reshapePlan ? previewReshapedColumns(live, shape) : undefined);
|
|
1084
1103
|
if (reshapePlan && reshapePlan.postReconcileOps.length > 0) {
|
|
1085
1104
|
// Data-validating attribute ops (retype / recollate / tighten NOT NULL)
|
|
1086
1105
|
// must validate the RECONCILED body rows, not the stale backing — but the
|
|
@@ -1320,8 +1339,14 @@ export async function createMaintainedTable(db, stmt) {
|
|
|
1320
1339
|
* behavior. The caller is responsible for staleness re-validation when relevant;
|
|
1321
1340
|
* this helper assumes the derivation body plans. Throws if the table is missing
|
|
1322
1341
|
* from the catalog.
|
|
1342
|
+
*
|
|
1343
|
+
* `validationColumns` is the reshape arm's column preview
|
|
1344
|
+
* ({@link previewReshapedColumns}) — the type/collation attributes the reshape's
|
|
1345
|
+
* still-pending post-reconcile ops are about to land — forwarded to the scan so
|
|
1346
|
+
* the CHECK / FK resolve against the final declared shape. `undefined` on every
|
|
1347
|
+
* other path (and on a reshape that shifts neither attribute).
|
|
1323
1348
|
*/
|
|
1324
|
-
export async function rebuildBacking(db, mv) {
|
|
1349
|
+
export async function rebuildBacking(db, mv, validationColumns) {
|
|
1325
1350
|
const bodySql = astToString(mv.derivation.selectAst);
|
|
1326
1351
|
const rows = await collectBodyRows(db, mv.schemaName, bodySql);
|
|
1327
1352
|
const backing = db.schemaManager.getTable(mv.schemaName, mv.name);
|
|
@@ -1367,23 +1392,15 @@ export async function rebuildBacking(db, mv) {
|
|
|
1367
1392
|
// leaving the pre-refresh committed contents intact (the MV stays stale, so the
|
|
1368
1393
|
// next read re-validates rather than serving the rejected set).
|
|
1369
1394
|
//
|
|
1370
|
-
//
|
|
1371
|
-
//
|
|
1372
|
-
//
|
|
1373
|
-
// `recollate`
|
|
1374
|
-
//
|
|
1375
|
-
//
|
|
1376
|
-
//
|
|
1377
|
-
//
|
|
1378
|
-
|
|
1379
|
-
// row '10' — lexicographic-true then numeric-false) passes here and is retyped into
|
|
1380
|
-
// violation. Not closed: this commit is load-bearing (commit-first parity + the
|
|
1381
|
-
// post-reconcile ops scan committed contents), and the attach reshape path uses the
|
|
1382
|
-
// identical ordering. See docs/materialized-views.md § REFRESH MATERIALIZED VIEW
|
|
1383
|
-
// "Known limitation — collation-sensitive CHECK" / "… type-sensitive CHECK" and
|
|
1384
|
-
// maintained-table-refresh-revalidation.spec.ts § "reshape arm: collation-
|
|
1385
|
-
// sensitive CHECK" / "reshape arm: type-sensitive CHECK".
|
|
1386
|
-
await validateDeclaredConstraintsOverContents(db, backing);
|
|
1395
|
+
// On the reshape arm `validationColumns` carries the attributes the reshape is
|
|
1396
|
+
// about to land ({@link previewReshapedColumns}), so a CHECK / FK is evaluated
|
|
1397
|
+
// under the column's FINAL type and collation even though the `retype` /
|
|
1398
|
+
// `recollate` module ops still run post-reconcile in reshapeBackingInPlace. That
|
|
1399
|
+
// keeps this commit's ordering exactly as it was — the scan stays before the
|
|
1400
|
+
// commit, the post-reconcile ops still scan committed contents — while removing
|
|
1401
|
+
// the wrong-semantics gap. The attach reshape path passes the same preview at its
|
|
1402
|
+
// own call site, so both arms reject identically.
|
|
1403
|
+
await validateDeclaredConstraintsOverContents(db, backing, validationColumns);
|
|
1387
1404
|
await conn.commit();
|
|
1388
1405
|
}
|
|
1389
1406
|
/**
|
|
@@ -2111,6 +2128,76 @@ function reshapeOpToChange(op) {
|
|
|
2111
2128
|
function graftReshapedRecord(moduleSchema, source) {
|
|
2112
2129
|
return { ...moduleSchema, derivation: source.derivation, tags: source.tags };
|
|
2113
2130
|
}
|
|
2131
|
+
/**
|
|
2132
|
+
* The column list a reshape is ABOUT TO land, for the declared-constraint scan that
|
|
2133
|
+
* runs mid-reshape ({@link validateDeclaredConstraintsOverContents}).
|
|
2134
|
+
*
|
|
2135
|
+
* A reshape's data-validating ops (`retype` / `recollate`) must run AFTER the data
|
|
2136
|
+
* reconcile — they convert/re-key STORED rows, so running them first would validate
|
|
2137
|
+
* the about-to-be-discarded contents and throw spuriously. But a SQL comparison
|
|
2138
|
+
* takes its type affinity and its collation from the column's DECLARED attributes,
|
|
2139
|
+
* so a scan against the live (pre-op) record evaluates a declared CHECK under the
|
|
2140
|
+
* attributes the reshape is replacing: `check (v < '9')` on a column moving
|
|
2141
|
+
* TEXT → INTEGER compares as text ('10' < '9' is true) and never as the numeric
|
|
2142
|
+
* comparison it is becoming. Previewing the attributes fixes the semantics without
|
|
2143
|
+
* moving a single op — the scan stays exactly where it was, still before the commit.
|
|
2144
|
+
*
|
|
2145
|
+
* Maps `live`'s columns onto `shape`'s **by name** (names and order already agree:
|
|
2146
|
+
* the reshape's pre-reconcile batch has applied every rename / add / drop before
|
|
2147
|
+
* either caller reaches this) and overrides only `logicalType` and `collation`.
|
|
2148
|
+
* Returns `undefined` when neither attribute shifts, so a reshape with no
|
|
2149
|
+
* `retype`/`recollate` — and every non-reshape path — behaves exactly as before.
|
|
2150
|
+
*
|
|
2151
|
+
* Deliberately NOT previewed:
|
|
2152
|
+
* - **`notNull`.** The tighten-NOT-NULL op stays a post-reconcile module op and
|
|
2153
|
+
* keeps validating there. Declaring `notNull` early would let the optimizer fold
|
|
2154
|
+
* a nullability-sensitive CHECK into a vacuous pass — the same class of unsound
|
|
2155
|
+
* folding the caller's constraint-stripped-clone swap exists to prevent.
|
|
2156
|
+
* - **`defaultValue` and the generated-column attributes.** A reshape never moves
|
|
2157
|
+
* them, so previewing them could only introduce drift.
|
|
2158
|
+
*
|
|
2159
|
+
* Physical-PK columns need no special handling: `describePhysicalPkChange` refuses
|
|
2160
|
+
* a reshape whose key column changes type or collation, so a previewed attribute
|
|
2161
|
+
* can never desynchronize the key encoding `assertRefreshRowsAreSet` or the host's
|
|
2162
|
+
* keyed diff rely on.
|
|
2163
|
+
*
|
|
2164
|
+
* NOTE: the scan sees the rebuilt values in their PRE-conversion physical form but
|
|
2165
|
+
* under the POST-conversion declared type. These agree in practice — the target
|
|
2166
|
+
* attribute is derived FROM the body's own output type, so the body already emits
|
|
2167
|
+
* values of the new type. A retype whose conversion genuinely rewrites the value
|
|
2168
|
+
* (a text → date canonicalization turning '2024-06-05T00:00:00Z' into '2024-06-05')
|
|
2169
|
+
* would have the CHECK see the un-normalized spelling. Not chased; revisit if a
|
|
2170
|
+
* value-rewriting conversion is ever added to the reshape's op set.
|
|
2171
|
+
*
|
|
2172
|
+
* NOTE: with the preview in place, a body emitting a value that does not conform to
|
|
2173
|
+
* its own declared output type now trips the physical-representation checker
|
|
2174
|
+
* (`QUEREUS_REPR_STRICT`) at this scan rather than sliding through. That is a
|
|
2175
|
+
* genuine defect surfacing at the earliest honest point, not a regression.
|
|
2176
|
+
*
|
|
2177
|
+
* NOTE: this RE-DERIVES the attribute shift from live-vs-shape rather than reading
|
|
2178
|
+
* `ReshapePlan.postReconcileOps`, which is the authoritative list of the `retype` /
|
|
2179
|
+
* `recollate` ops that will actually run. The two agree today because the
|
|
2180
|
+
* pre-reconcile structural ops preserve attributes exactly ({@link backingColumnDef}
|
|
2181
|
+
* carries type + collation through a rename, and an `add` lands the shape column's
|
|
2182
|
+
* own attributes), so every live-vs-shape shift has a queued op and vice versa. If a
|
|
2183
|
+
* structural op ever stops preserving an attribute, this would preview an attribute
|
|
2184
|
+
* no op lands and the scan would reject rows the finished reshape accepts — build the
|
|
2185
|
+
* preview from `postReconcileOps` then.
|
|
2186
|
+
*/
|
|
2187
|
+
function previewReshapedColumns(live, shape) {
|
|
2188
|
+
const byName = new Map(shape.columns.map(c => [c.name.toLowerCase(), c]));
|
|
2189
|
+
let shifted = false;
|
|
2190
|
+
const preview = live.columns.map(col => {
|
|
2191
|
+
const target = byName.get(col.name.toLowerCase());
|
|
2192
|
+
if (!target)
|
|
2193
|
+
return col;
|
|
2194
|
+
if (backingTypeMatches(col, target) && backingCollationMatches(col, target))
|
|
2195
|
+
return col;
|
|
2196
|
+
shifted = true;
|
|
2197
|
+
return { ...col, logicalType: target.logicalType, collation: target.collation };
|
|
2198
|
+
});
|
|
2199
|
+
return shifted ? Object.freeze(preview) : undefined;
|
|
2200
|
+
}
|
|
2114
2201
|
/**
|
|
2115
2202
|
* The sited error a refresh raises when the re-derived body shape cannot be
|
|
2116
2203
|
* reconciled onto the live maintained table in place — an interleaving column
|
|
@@ -2209,8 +2296,10 @@ async function reshapeBackingInPlace(db, mv, shape, plan) {
|
|
|
2209
2296
|
let live = graftReshapedRecord(current, mv);
|
|
2210
2297
|
schema.addTable(live);
|
|
2211
2298
|
// Data reconcile: re-run the body and swap contents (the identity-preserving
|
|
2212
|
-
// data-only path — same host, same incarnation).
|
|
2213
|
-
|
|
2299
|
+
// data-only path — same host, same incarnation). The column preview lets that
|
|
2300
|
+
// path's declared-constraint scan resolve against the type/collation the
|
|
2301
|
+
// post-reconcile ops below will land, not the ones they replace.
|
|
2302
|
+
await rebuildBacking(db, live, previewReshapedColumns(live, shape));
|
|
2214
2303
|
// Post-reconcile data-validating ops (retype / recollate / tighten NOT NULL): the
|
|
2215
2304
|
// reconciled body rows satisfy the new attribute where the discarded backing
|
|
2216
2305
|
// might not, so each validates the fresh data, not the stale rows. Re-register
|
|
@@ -2221,14 +2310,14 @@ async function reshapeBackingInPlace(db, mv, shape, plan) {
|
|
|
2221
2310
|
// partial throw. Per-op registration keeps the catalog tracking the module so a
|
|
2222
2311
|
// mid-batch failure leaves a coherent, re-runnable table.
|
|
2223
2312
|
//
|
|
2224
|
-
//
|
|
2225
|
-
//
|
|
2226
|
-
//
|
|
2227
|
-
//
|
|
2228
|
-
//
|
|
2229
|
-
//
|
|
2230
|
-
//
|
|
2231
|
-
//
|
|
2313
|
+
// These ops still run after step 3's rebuildBacking has validated + committed,
|
|
2314
|
+
// but the declared-CHECK/FK scan inside that step is no longer blind to them:
|
|
2315
|
+
// the `previewReshapedColumns` argument above hands it the type/collation each
|
|
2316
|
+
// `retype` / `recollate` here is about to land, so a constraint whose truth
|
|
2317
|
+
// flips under the new attribute (`v <> 'abc'` recollated BINARY → NOCASE over
|
|
2318
|
+
// 'ABC'; `v < '9'` retyped TEXT → INTEGER over '10') is rejected there, before
|
|
2319
|
+
// the commit, with nothing written. A tighten-NOT-NULL is deliberately NOT
|
|
2320
|
+
// previewed and keeps validating right here — see previewReshapedColumns.
|
|
2232
2321
|
for (const op of plan.postReconcileOps) {
|
|
2233
2322
|
current = await module.alterTable(db, mv.schemaName, mv.name, reshapeOpToChange(op));
|
|
2234
2323
|
live = graftReshapedRecord(current, mv);
|
|
@@ -2393,8 +2482,9 @@ function maintainedTablesOf(schema) {
|
|
|
2393
2482
|
/**
|
|
2394
2483
|
* Rewrites every dependent materialized view in `schema` after a source TABLE
|
|
2395
2484
|
* RENAME — the MV mirror of the plain-view loop in `propagateTableRenameInSchema`
|
|
2396
|
-
* ("MV ≡ faster view"): the caller
|
|
2397
|
-
* `
|
|
2485
|
+
* ("MV ≡ faster view"): the caller calls this once per schema in the catalog with
|
|
2486
|
+
* `target` bound to THAT schema's home path, and the body `selectAst` is mutated
|
|
2487
|
+
* in place by the same `renameTableInAst` walker. An MV is
|
|
2398
2488
|
* processed when its body AST changed, its `insert defaults` clause changed (an
|
|
2399
2489
|
* expr subquery can name the renamed table even when the body doesn't), OR its
|
|
2400
2490
|
* `sourceTables` carries the old base — the latter catches a body that reads the
|
|
@@ -2409,8 +2499,9 @@ function maintainedTablesOf(schema) {
|
|
|
2409
2499
|
* `materialized_view_modified`. Failures mark the MV stale and propagation
|
|
2410
2500
|
* continues — best-effort, like the rest of the rename propagation.
|
|
2411
2501
|
*/
|
|
2412
|
-
export async function propagateTableRenameToMaterializedViews(db, schema,
|
|
2413
|
-
const
|
|
2502
|
+
export async function propagateTableRenameToMaterializedViews(db, schema, preStale, target) {
|
|
2503
|
+
const { oldName, newName } = target;
|
|
2504
|
+
const schemaLower = target.schemaName.toLowerCase();
|
|
2414
2505
|
const oldBase = `${schemaLower}.${oldName.toLowerCase()}`;
|
|
2415
2506
|
const newBase = `${schemaLower}.${newName.toLowerCase()}`;
|
|
2416
2507
|
for (const mv of maintainedTablesOf(schema)) {
|
|
@@ -2419,7 +2510,7 @@ export async function propagateTableRenameToMaterializedViews(db, schema, rename
|
|
|
2419
2510
|
// The body walk also descends the trailing `with defaults (…)` clause
|
|
2420
2511
|
// (now on `selectAst.defaults`), so a defaults-expr subquery naming the
|
|
2421
2512
|
// renamed table flips `bodyChanged` even when the body never names it.
|
|
2422
|
-
const bodyChanged = renameTableInAst(d.selectAst,
|
|
2513
|
+
const bodyChanged = renameTableInAst(d.selectAst, target);
|
|
2423
2514
|
if (!bodyChanged && !d.sourceTables.includes(oldBase))
|
|
2424
2515
|
continue;
|
|
2425
2516
|
const covers = d.covers
|
|
@@ -2440,7 +2531,10 @@ export async function propagateTableRenameToMaterializedViews(db, schema, rename
|
|
|
2440
2531
|
/**
|
|
2441
2532
|
* Rewrites every dependent materialized view in `schema` after a source COLUMN
|
|
2442
2533
|
* RENAME — the MV mirror of the plain-view loop in `propagateColumnRenameInSchema`
|
|
2443
|
-
* (
|
|
2534
|
+
* (called once per schema PER CASCADE ROUND — the target may be the renamed table
|
|
2535
|
+
* or a view/MV whose published names a prior round shifted, see
|
|
2536
|
+
* `column-rename-cascade.ts` — with that schema's resolver, same in-place
|
|
2537
|
+
* `renameColumnInAst` walk).
|
|
2444
2538
|
* The body walk also descends the trailing `with defaults (…)` clause (now on
|
|
2445
2539
|
* `selectAst.defaults`): the clause target is typically a projected-away NOT NULL
|
|
2446
2540
|
* column the body never mentions, so its rewrite still flips `bodyChanged` and
|
|
@@ -2452,14 +2546,14 @@ export async function propagateTableRenameToMaterializedViews(db, schema, rename
|
|
|
2452
2546
|
* (a bare passthrough projection of the renamed column — plain-view parity),
|
|
2453
2547
|
* which {@link applyMaterializedViewRewrite} carries onto the live backing table.
|
|
2454
2548
|
*/
|
|
2455
|
-
export async function propagateColumnRenameToMaterializedViews(db, schema,
|
|
2549
|
+
export async function propagateColumnRenameToMaterializedViews(db, schema, tableName, oldCol, newCol, preStale, resolve, targetKey, resolveColumnInSource) {
|
|
2456
2550
|
for (const mv of maintainedTablesOf(schema)) {
|
|
2457
2551
|
try {
|
|
2458
2552
|
const d = mv.derivation;
|
|
2459
2553
|
// `resolveColumnInSource` keeps the body walk scope-aware for a defaults-expr
|
|
2460
2554
|
// subquery referencing a like-named column on its own FROM — plain-view /
|
|
2461
2555
|
// differ-reconcile parity (see `renameColumnInAst`).
|
|
2462
|
-
const bodyChanged = renameColumnInAst(d.selectAst, tableName, oldCol, newCol,
|
|
2556
|
+
const bodyChanged = renameColumnInAst(d.selectAst, tableName, oldCol, newCol, resolve, targetKey, 'none', resolveColumnInSource);
|
|
2463
2557
|
if (!bodyChanged)
|
|
2464
2558
|
continue;
|
|
2465
2559
|
await applyMaterializedViewRewrite(db, schema, mv, {}, preStale, /*renamedColumns*/ true);
|
|
@@ -2580,10 +2674,22 @@ async function restoreMaterializedViewLive(db, schema, mv, backingNames) {
|
|
|
2580
2674
|
* sql, sourceTables) is unchanged here — `stale` is runtime state, not persisted.
|
|
2581
2675
|
* Walks all schemas (the listener marks cross-schema dependents too), in creation
|
|
2582
2676
|
* order — topological for same-schema MV chains, so a producer restores before its
|
|
2583
|
-
* consumer is examined. A chained MV
|
|
2584
|
-
*
|
|
2585
|
-
*
|
|
2586
|
-
*
|
|
2677
|
+
* consumer is examined. A chained MV normally follows a producer's shifted output
|
|
2678
|
+
* name through the cascade driver's later rounds (`column-rename-cascade.ts`); one
|
|
2679
|
+
* whose body still references a renamed-away name (a mid-statement rewrite
|
|
2680
|
+
* failure) fails shape derivation here and stays stale.
|
|
2681
|
+
*
|
|
2682
|
+
* NOTE: the walk is schema-by-schema, then creation order WITHIN a schema, so a
|
|
2683
|
+
* CROSS-schema MV chain is only topological when the producer's schema is iterated
|
|
2684
|
+
* first. Harmless today — a consumer whose body does not itself name the renamed
|
|
2685
|
+
* object is skipped by the propagation entirely and only ever reaches this pass, and
|
|
2686
|
+
* a producer whose own NAME did not change re-plans fine either way (verified for
|
|
2687
|
+
* both verbs in `test/schema/rename-cross-schema.spec.ts`). If a producer's output
|
|
2688
|
+
* names can shift while its consumer lives in an earlier-iterated schema, this pass
|
|
2689
|
+
* needs a topological order (or a second round) rather than catalog order.
|
|
2690
|
+
*
|
|
2691
|
+
* Best-effort like the rest of the propagation: a per-MV failure logs, leaves that MV
|
|
2692
|
+
* stale, and continues.
|
|
2587
2693
|
*
|
|
2588
2694
|
* NOTE: firing no `materialized_view_modified` is deliberate, but
|
|
2589
2695
|
* {@link renameShiftedBackingColumns} (run from the shared restore tail) DOES change the
|
|
@@ -2653,11 +2759,14 @@ function sameSourceTables(a, b) {
|
|
|
2653
2759
|
* difference (count / types / PK) is NOT a rename outcome — throw so the caller's
|
|
2654
2760
|
* failure path leaves the MV stale rather than rebuilding data here.
|
|
2655
2761
|
*
|
|
2656
|
-
* The backing `table_modified` fired on a real rename deliberately cascades
|
|
2657
|
-
* chained MV
|
|
2658
|
-
*
|
|
2659
|
-
*
|
|
2660
|
-
*
|
|
2762
|
+
* The backing `table_modified` fired on a real rename deliberately cascades to
|
|
2763
|
+
* the manager's listener (a chained MV referencing the OLD output name is marked
|
|
2764
|
+
* stale), and cached plans scanning the backing directly recompile against the
|
|
2765
|
+
* new names. Within a RENAME COLUMN statement that staleness is transient: the
|
|
2766
|
+
* cascade driver (`column-rename-cascade.ts`) re-runs the propagation with this
|
|
2767
|
+
* MV as the target, so the chained body is rewritten and restored in a later
|
|
2768
|
+
* round — the staleness diagnostic remains only for a body the cascade could not
|
|
2769
|
+
* rewrite (a mid-statement failure).
|
|
2661
2770
|
*/
|
|
2662
2771
|
async function renameShiftedBackingColumns(db, schema, mv, bodySql, preDerivedShape) {
|
|
2663
2772
|
const shape = preDerivedShape ?? deriveBackingShape(db, mv.schemaName, bodySql, mv.derivation.columns);
|