@quereus/quereus 4.4.1 → 4.5.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/README.md +1 -1
- package/dist/src/core/database-materialized-views-analysis.d.ts.map +1 -1
- package/dist/src/core/database-materialized-views-analysis.js +1 -0
- package/dist/src/core/database-materialized-views-analysis.js.map +1 -1
- package/dist/src/func/builtins/scalar.d.ts.map +1 -1
- package/dist/src/func/builtins/scalar.js +92 -3
- package/dist/src/func/builtins/scalar.js.map +1 -1
- package/dist/src/func/registration.d.ts +4 -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 +3 -3
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +2 -2
- package/dist/src/index.js.map +1 -1
- package/dist/src/planner/analysis/coarsened-key.d.ts +4 -3
- package/dist/src/planner/analysis/coarsened-key.d.ts.map +1 -1
- package/dist/src/planner/analysis/coarsened-key.js +37 -3
- package/dist/src/planner/analysis/coarsened-key.js.map +1 -1
- package/dist/src/planner/analysis/comparison-collation.d.ts +33 -3
- package/dist/src/planner/analysis/comparison-collation.d.ts.map +1 -1
- package/dist/src/planner/analysis/comparison-collation.js +36 -2
- package/dist/src/planner/analysis/comparison-collation.js.map +1 -1
- package/dist/src/planner/analysis/coverage-prover.d.ts +13 -2
- package/dist/src/planner/analysis/coverage-prover.d.ts.map +1 -1
- package/dist/src/planner/analysis/coverage-prover.js +10 -14
- package/dist/src/planner/analysis/coverage-prover.js.map +1 -1
- package/dist/src/planner/analysis/predicate-conjuncts.d.ts +10 -4
- package/dist/src/planner/analysis/predicate-conjuncts.d.ts.map +1 -1
- package/dist/src/planner/analysis/predicate-conjuncts.js +28 -7
- package/dist/src/planner/analysis/predicate-conjuncts.js.map +1 -1
- package/dist/src/planner/analysis/query-rewrite-matcher.d.ts.map +1 -1
- package/dist/src/planner/analysis/query-rewrite-matcher.js +8 -27
- package/dist/src/planner/analysis/query-rewrite-matcher.js.map +1 -1
- package/dist/src/planner/analysis/scalar-subqueries.d.ts +22 -3
- package/dist/src/planner/analysis/scalar-subqueries.d.ts.map +1 -1
- package/dist/src/planner/analysis/scalar-subqueries.js +32 -3
- package/dist/src/planner/analysis/scalar-subqueries.js.map +1 -1
- package/dist/src/planner/analysis/set-op-type-merge.d.ts +64 -0
- package/dist/src/planner/analysis/set-op-type-merge.d.ts.map +1 -0
- package/dist/src/planner/analysis/set-op-type-merge.js +97 -0
- package/dist/src/planner/analysis/set-op-type-merge.js.map +1 -0
- package/dist/src/planner/building/coercion.d.ts +78 -0
- package/dist/src/planner/building/coercion.d.ts.map +1 -0
- package/dist/src/planner/building/coercion.js +137 -0
- package/dist/src/planner/building/coercion.js.map +1 -0
- package/dist/src/planner/building/constraint-builder.d.ts.map +1 -1
- package/dist/src/planner/building/constraint-builder.js +5 -18
- package/dist/src/planner/building/constraint-builder.js.map +1 -1
- package/dist/src/planner/building/expression.d.ts.map +1 -1
- package/dist/src/planner/building/expression.js +1 -104
- package/dist/src/planner/building/expression.js.map +1 -1
- package/dist/src/planner/building/function-call.d.ts.map +1 -1
- package/dist/src/planner/building/function-call.js +8 -0
- package/dist/src/planner/building/function-call.js.map +1 -1
- package/dist/src/planner/building/select-compound.d.ts.map +1 -1
- package/dist/src/planner/building/select-compound.js +10 -6
- package/dist/src/planner/building/select-compound.js.map +1 -1
- package/dist/src/planner/cost/conjunct-cost.d.ts +42 -0
- package/dist/src/planner/cost/conjunct-cost.d.ts.map +1 -0
- package/dist/src/planner/cost/conjunct-cost.js +62 -0
- package/dist/src/planner/cost/conjunct-cost.js.map +1 -0
- package/dist/src/planner/mutation/propagate.d.ts.map +1 -1
- package/dist/src/planner/mutation/propagate.js +1 -0
- package/dist/src/planner/mutation/propagate.js.map +1 -1
- package/dist/src/planner/nodes/async-gather-node.d.ts.map +1 -1
- package/dist/src/planner/nodes/async-gather-node.js +19 -8
- package/dist/src/planner/nodes/async-gather-node.js.map +1 -1
- package/dist/src/planner/nodes/bloom-join-node.d.ts +2 -0
- package/dist/src/planner/nodes/bloom-join-node.d.ts.map +1 -1
- package/dist/src/planner/nodes/bloom-join-node.js +10 -5
- package/dist/src/planner/nodes/bloom-join-node.js.map +1 -1
- package/dist/src/planner/nodes/join-node.d.ts +5 -0
- package/dist/src/planner/nodes/join-node.d.ts.map +1 -1
- package/dist/src/planner/nodes/join-node.js +8 -1
- package/dist/src/planner/nodes/join-node.js.map +1 -1
- package/dist/src/planner/nodes/join-utils.d.ts +57 -0
- package/dist/src/planner/nodes/join-utils.d.ts.map +1 -1
- package/dist/src/planner/nodes/join-utils.js +47 -0
- package/dist/src/planner/nodes/join-utils.js.map +1 -1
- package/dist/src/planner/nodes/key-set-semi-join-node.d.ts +87 -0
- package/dist/src/planner/nodes/key-set-semi-join-node.d.ts.map +1 -0
- package/dist/src/planner/nodes/key-set-semi-join-node.js +137 -0
- package/dist/src/planner/nodes/key-set-semi-join-node.js.map +1 -0
- package/dist/src/planner/nodes/merge-join-node.d.ts +2 -0
- package/dist/src/planner/nodes/merge-join-node.d.ts.map +1 -1
- package/dist/src/planner/nodes/merge-join-node.js +14 -6
- package/dist/src/planner/nodes/merge-join-node.js.map +1 -1
- package/dist/src/planner/nodes/plan-node-type.d.ts +1 -0
- package/dist/src/planner/nodes/plan-node-type.d.ts.map +1 -1
- package/dist/src/planner/nodes/plan-node-type.js +1 -0
- package/dist/src/planner/nodes/plan-node-type.js.map +1 -1
- package/dist/src/planner/nodes/set-operation-node.d.ts +68 -16
- package/dist/src/planner/nodes/set-operation-node.d.ts.map +1 -1
- package/dist/src/planner/nodes/set-operation-node.js +147 -26
- package/dist/src/planner/nodes/set-operation-node.js.map +1 -1
- package/dist/src/planner/nodes/table-access-nodes.d.ts +19 -1
- package/dist/src/planner/nodes/table-access-nodes.d.ts.map +1 -1
- package/dist/src/planner/nodes/table-access-nodes.js +13 -2
- package/dist/src/planner/nodes/table-access-nodes.js.map +1 -1
- package/dist/src/planner/optimizer.d.ts.map +1 -1
- package/dist/src/planner/optimizer.js +49 -0
- package/dist/src/planner/optimizer.js.map +1 -1
- package/dist/src/planner/rules/access/rule-key-set-seek.d.ts +68 -0
- package/dist/src/planner/rules/access/rule-key-set-seek.d.ts.map +1 -0
- package/dist/src/planner/rules/access/rule-key-set-seek.js +408 -0
- package/dist/src/planner/rules/access/rule-key-set-seek.js.map +1 -0
- package/dist/src/planner/rules/access/rule-monotonic-range-access.d.ts.map +1 -1
- package/dist/src/planner/rules/access/rule-monotonic-range-access.js +2 -2
- package/dist/src/planner/rules/access/rule-monotonic-range-access.js.map +1 -1
- package/dist/src/planner/rules/access/rule-select-access-path.d.ts +27 -0
- package/dist/src/planner/rules/access/rule-select-access-path.d.ts.map +1 -1
- package/dist/src/planner/rules/access/rule-select-access-path.js +31 -11
- package/dist/src/planner/rules/access/rule-select-access-path.js.map +1 -1
- package/dist/src/planner/rules/join/equi-pair-extractor.d.ts +67 -41
- package/dist/src/planner/rules/join/equi-pair-extractor.d.ts.map +1 -1
- package/dist/src/planner/rules/join/equi-pair-extractor.js +72 -36
- package/dist/src/planner/rules/join/equi-pair-extractor.js.map +1 -1
- package/dist/src/planner/rules/join/rule-join-physical-selection.d.ts.map +1 -1
- package/dist/src/planner/rules/join/rule-join-physical-selection.js +14 -2
- package/dist/src/planner/rules/join/rule-join-physical-selection.js.map +1 -1
- package/dist/src/planner/rules/join/rule-monotonic-merge-join.d.ts.map +1 -1
- package/dist/src/planner/rules/join/rule-monotonic-merge-join.js +11 -1
- package/dist/src/planner/rules/join/rule-monotonic-merge-join.js.map +1 -1
- package/dist/src/planner/rules/predicate/rule-empty-relation-folding.d.ts +1 -1
- package/dist/src/planner/rules/predicate/rule-empty-relation-folding.js +1 -1
- package/dist/src/planner/rules/predicate/rule-filter-conjunct-ordering.d.ts +30 -0
- package/dist/src/planner/rules/predicate/rule-filter-conjunct-ordering.d.ts.map +1 -0
- package/dist/src/planner/rules/predicate/rule-filter-conjunct-ordering.js +63 -0
- package/dist/src/planner/rules/predicate/rule-filter-conjunct-ordering.js.map +1 -0
- package/dist/src/planner/rules/predicate/rule-filter-selectivity.d.ts +17 -1
- package/dist/src/planner/rules/predicate/rule-filter-selectivity.d.ts.map +1 -1
- package/dist/src/planner/rules/predicate/rule-filter-selectivity.js +206 -12
- package/dist/src/planner/rules/predicate/rule-filter-selectivity.js.map +1 -1
- package/dist/src/planner/rules/predicate/rule-predicate-pushdown.d.ts +3 -1
- package/dist/src/planner/rules/predicate/rule-predicate-pushdown.d.ts.map +1 -1
- package/dist/src/planner/rules/predicate/rule-predicate-pushdown.js +13 -1
- package/dist/src/planner/rules/predicate/rule-predicate-pushdown.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 +18 -3
- package/dist/src/planner/rules/retrieve/rule-grow-retrieve.js.map +1 -1
- package/dist/src/planner/rules/shared/index-style-context.d.ts +17 -0
- package/dist/src/planner/rules/shared/index-style-context.d.ts.map +1 -1
- package/dist/src/planner/rules/shared/index-style-context.js +7 -0
- package/dist/src/planner/rules/shared/index-style-context.js.map +1 -1
- package/dist/src/planner/rules/subquery/rule-subquery-decorrelation.d.ts +24 -6
- package/dist/src/planner/rules/subquery/rule-subquery-decorrelation.d.ts.map +1 -1
- package/dist/src/planner/rules/subquery/rule-subquery-decorrelation.js +175 -60
- package/dist/src/planner/rules/subquery/rule-subquery-decorrelation.js.map +1 -1
- package/dist/src/planner/stats/catalog-stats.d.ts +52 -0
- package/dist/src/planner/stats/catalog-stats.d.ts.map +1 -1
- package/dist/src/planner/stats/catalog-stats.js +151 -5
- package/dist/src/planner/stats/catalog-stats.js.map +1 -1
- package/dist/src/planner/stats/index.d.ts +15 -0
- package/dist/src/planner/stats/index.d.ts.map +1 -1
- package/dist/src/planner/stats/index.js.map +1 -1
- package/dist/src/planner/stats/selectivity-combine.d.ts +53 -0
- package/dist/src/planner/stats/selectivity-combine.d.ts.map +1 -0
- package/dist/src/planner/stats/selectivity-combine.js +75 -0
- package/dist/src/planner/stats/selectivity-combine.js.map +1 -0
- package/dist/src/planner/util/column-origins.d.ts +58 -0
- package/dist/src/planner/util/column-origins.d.ts.map +1 -0
- package/dist/src/planner/util/column-origins.js +90 -0
- package/dist/src/planner/util/column-origins.js.map +1 -0
- package/dist/src/runtime/deferred-constraint-queue.d.ts +40 -0
- package/dist/src/runtime/deferred-constraint-queue.d.ts.map +1 -1
- package/dist/src/runtime/deferred-constraint-queue.js +90 -9
- package/dist/src/runtime/deferred-constraint-queue.js.map +1 -1
- package/dist/src/runtime/emit/alter-table.d.ts.map +1 -1
- package/dist/src/runtime/emit/alter-table.js +6 -0
- package/dist/src/runtime/emit/alter-table.js.map +1 -1
- package/dist/src/runtime/emit/asof-scan.d.ts.map +1 -1
- package/dist/src/runtime/emit/asof-scan.js +8 -3
- package/dist/src/runtime/emit/asof-scan.js.map +1 -1
- package/dist/src/runtime/emit/between.d.ts.map +1 -1
- package/dist/src/runtime/emit/between.js +4 -38
- package/dist/src/runtime/emit/between.js.map +1 -1
- package/dist/src/runtime/emit/binary.d.ts.map +1 -1
- package/dist/src/runtime/emit/binary.js +2 -23
- package/dist/src/runtime/emit/binary.js.map +1 -1
- package/dist/src/runtime/emit/bloom-join.d.ts.map +1 -1
- package/dist/src/runtime/emit/bloom-join.js +6 -35
- package/dist/src/runtime/emit/bloom-join.js.map +1 -1
- package/dist/src/runtime/emit/case.d.ts.map +1 -1
- package/dist/src/runtime/emit/case.js +40 -6
- package/dist/src/runtime/emit/case.js.map +1 -1
- package/dist/src/runtime/emit/constraint-check.d.ts.map +1 -1
- package/dist/src/runtime/emit/constraint-check.js +32 -8
- package/dist/src/runtime/emit/constraint-check.js.map +1 -1
- package/dist/src/runtime/emit/dml-executor.d.ts.map +1 -1
- package/dist/src/runtime/emit/dml-executor.js +26 -23
- package/dist/src/runtime/emit/dml-executor.js.map +1 -1
- package/dist/src/runtime/emit/filter.d.ts +18 -0
- package/dist/src/runtime/emit/filter.d.ts.map +1 -1
- package/dist/src/runtime/emit/filter.js +52 -10
- package/dist/src/runtime/emit/filter.js.map +1 -1
- package/dist/src/runtime/emit/join-key-extractor.d.ts +46 -0
- package/dist/src/runtime/emit/join-key-extractor.d.ts.map +1 -0
- package/dist/src/runtime/emit/join-key-extractor.js +60 -0
- package/dist/src/runtime/emit/join-key-extractor.js.map +1 -0
- package/dist/src/runtime/emit/join.d.ts.map +1 -1
- package/dist/src/runtime/emit/join.js +36 -15
- package/dist/src/runtime/emit/join.js.map +1 -1
- package/dist/src/runtime/emit/key-set-semi-join.d.ts +29 -0
- package/dist/src/runtime/emit/key-set-semi-join.d.ts.map +1 -0
- package/dist/src/runtime/emit/key-set-semi-join.js +143 -0
- package/dist/src/runtime/emit/key-set-semi-join.js.map +1 -0
- package/dist/src/runtime/emit/merge-join.d.ts.map +1 -1
- package/dist/src/runtime/emit/merge-join.js +15 -8
- package/dist/src/runtime/emit/merge-join.js.map +1 -1
- package/dist/src/runtime/emit/operand-comparator.d.ts +40 -0
- package/dist/src/runtime/emit/operand-comparator.d.ts.map +1 -0
- package/dist/src/runtime/emit/operand-comparator.js +59 -0
- package/dist/src/runtime/emit/operand-comparator.js.map +1 -0
- package/dist/src/runtime/emit/scan.d.ts.map +1 -1
- package/dist/src/runtime/emit/scan.js +11 -2
- package/dist/src/runtime/emit/scan.js.map +1 -1
- package/dist/src/runtime/parallel-driver.d.ts +5 -2
- package/dist/src/runtime/parallel-driver.d.ts.map +1 -1
- package/dist/src/runtime/parallel-driver.js +6 -2
- package/dist/src/runtime/parallel-driver.js.map +1 -1
- package/dist/src/runtime/register.d.ts.map +1 -1
- package/dist/src/runtime/register.js +2 -0
- package/dist/src/runtime/register.js.map +1 -1
- package/dist/src/runtime/types.d.ts +7 -0
- package/dist/src/runtime/types.d.ts.map +1 -1
- package/dist/src/runtime/types.js.map +1 -1
- package/dist/src/schema/function.d.ts +9 -0
- package/dist/src/schema/function.d.ts.map +1 -1
- package/dist/src/schema/function.js.map +1 -1
- package/dist/src/types/builtin-types.d.ts.map +1 -1
- package/dist/src/types/builtin-types.js +30 -4
- package/dist/src/types/builtin-types.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 +31 -0
- package/dist/src/util/comparison.js.map +1 -1
- package/dist/src/vtab/best-access-plan.d.ts +87 -0
- package/dist/src/vtab/best-access-plan.d.ts.map +1 -1
- package/dist/src/vtab/best-access-plan.js +87 -0
- package/dist/src/vtab/best-access-plan.js.map +1 -1
- package/dist/src/vtab/memory/layer/base.d.ts +6 -4
- package/dist/src/vtab/memory/layer/base.d.ts.map +1 -1
- package/dist/src/vtab/memory/layer/base.js +6 -4
- package/dist/src/vtab/memory/layer/base.js.map +1 -1
- package/dist/src/vtab/memory/layer/manager.d.ts +60 -18
- package/dist/src/vtab/memory/layer/manager.d.ts.map +1 -1
- package/dist/src/vtab/memory/layer/manager.js +100 -39
- package/dist/src/vtab/memory/layer/manager.js.map +1 -1
- package/dist/src/vtab/memory/layer/transaction.d.ts +15 -6
- package/dist/src/vtab/memory/layer/transaction.d.ts.map +1 -1
- package/dist/src/vtab/memory/layer/transaction.js +26 -11
- package/dist/src/vtab/memory/layer/transaction.js.map +1 -1
- package/dist/src/vtab/memory/module.d.ts +14 -2
- package/dist/src/vtab/memory/module.d.ts.map +1 -1
- package/dist/src/vtab/memory/module.js +51 -39
- package/dist/src/vtab/memory/module.js.map +1 -1
- package/dist/src/vtab/memory/table.d.ts +1 -1
- package/dist/src/vtab/memory/table.d.ts.map +1 -1
- package/dist/src/vtab/memory/table.js +9 -2
- package/dist/src/vtab/memory/table.js.map +1 -1
- package/dist/src/vtab/table.d.ts +9 -1
- package/dist/src/vtab/table.d.ts.map +1 -1
- package/dist/src/vtab/table.js.map +1 -1
- package/package.json +3 -3
|
@@ -8,7 +8,7 @@ import { MemoryTableConnection } from './connection.js';
|
|
|
8
8
|
import { MemoryVirtualTableConnection } from '../connection.js';
|
|
9
9
|
import { QuereusError } from '../../../common/errors.js';
|
|
10
10
|
import { ConflictResolution } from '../../../common/constants.js';
|
|
11
|
-
import { buildUniqueConstraintSchema, buildForeignKeyConstraintSchema, buildCheckConstraintSchema, validateForeignKeyOverExistingRows, maintainedTableUniqueViolationError } from '../../../schema/constraint-builder.js';
|
|
11
|
+
import { buildUniqueConstraintSchema, buildForeignKeyConstraintSchema, buildCheckConstraintSchema, validateForeignKeyOverExistingRows, maintainedTableUniqueViolationError, formatKeyValue } from '../../../schema/constraint-builder.js';
|
|
12
12
|
import { indexEnforcesUnique, uniqueEnforcementCollations, uniqueEnforcementComparators } from '../../../schema/unique-enforcement.js';
|
|
13
13
|
import { generateIndexDDL, generateDropIndexDDL } from '../../../schema/ddl-generator.js';
|
|
14
14
|
import { compareSqlValues, rowsValueIdentical, normalizeCollationName, comparisonSemanticsDiffer } from '../../../util/comparison.js';
|
|
@@ -1974,8 +1974,15 @@ export class MemoryTableManager {
|
|
|
1974
1974
|
* Apply a single-attribute ALTER COLUMN change (NOT NULL, DEFAULT, DATA TYPE).
|
|
1975
1975
|
* The caller supplies exactly one populated change; multi-attribute combinations
|
|
1976
1976
|
* are rejected by the runtime before reaching this method.
|
|
1977
|
+
*
|
|
1978
|
+
* `validateOnly` runs everything up to (and including) the pre-mutation validation
|
|
1979
|
+
* passes — the effective-row NULL / conversion scans, the re-keyed UNIQUE probe, and
|
|
1980
|
+
* the primary-key re-key legality/representability passes — and returns before the
|
|
1981
|
+
* first mutation, throwing exactly what the real application would throw. The
|
|
1982
|
+
* isolation layer uses it to pre-flight an overlay's migration before the shared
|
|
1983
|
+
* underlying table mutates irreversibly (see `VirtualTable.alterSchema`).
|
|
1977
1984
|
*/
|
|
1978
|
-
async alterColumn(change, rows) {
|
|
1985
|
+
async alterColumn(change, rows, validateOnly = false) {
|
|
1979
1986
|
if (this.isReadOnly)
|
|
1980
1987
|
throw new QuereusError(`Table '${this._tableName}' is read-only`, StatusCode.READONLY);
|
|
1981
1988
|
const lockKey = `MemoryTable.SchemaChange:${this.schemaName}.${this._tableName}`;
|
|
@@ -2246,17 +2253,19 @@ export class MemoryTableManager {
|
|
|
2246
2253
|
}
|
|
2247
2254
|
else if (structuresRekeyed) {
|
|
2248
2255
|
await this.validateRekeyedUniqueStructures(finalNewTableSchema, colIndex, rows);
|
|
2249
|
-
//
|
|
2250
|
-
//
|
|
2251
|
-
//
|
|
2252
|
-
//
|
|
2253
|
-
//
|
|
2254
|
-
// committed row that collide only under the new collation" is checked by neither
|
|
2255
|
-
// side. Rejecting it here would need the wrapper to expose its overlay's PK set, not
|
|
2256
|
-
// just its merged rows.
|
|
2256
|
+
// Unlike the secondary-structure pass above — which only ever judges the effective
|
|
2257
|
+
// rows — the PK pass judges TWO row sets: the effective rows (`rows` when a wrapper
|
|
2258
|
+
// supplies them) decide whether the change is LEGAL, and this manager's own layer
|
|
2259
|
+
// chain decides whether the re-keyed trees can PHYSICALLY carry it. See
|
|
2260
|
+
// `validateRekeyedPrimaryKey` for why the sets differ and which status each raises.
|
|
2257
2261
|
if (pkColumnRekeyed)
|
|
2258
|
-
this.validateRekeyedPrimaryKey(finalNewTableSchema);
|
|
2262
|
+
await this.validateRekeyedPrimaryKey(finalNewTableSchema, rows);
|
|
2259
2263
|
}
|
|
2264
|
+
// Dry run ends here: everything above validates without mutating (the one earlier
|
|
2265
|
+
// side effect, ensureSchemaChangeSafety's committed-layer drain, is semantically
|
|
2266
|
+
// neutral bookkeeping), and everything below mutates. See the method doc.
|
|
2267
|
+
if (validateOnly)
|
|
2268
|
+
return;
|
|
2260
2269
|
this.baseLayer.updateSchema(finalNewTableSchema);
|
|
2261
2270
|
// Both arms rebuild the base's structures under the schema `updateSchema` above just
|
|
2262
2271
|
// swapped in — each MemoryIndex rebuilds its comparator from the CURRENT schema's
|
|
@@ -3116,21 +3125,35 @@ export class MemoryTableManager {
|
|
|
3116
3125
|
* PRIMARY KEY arm of the `alter column … set collate` pre-pass. Runs before anything is
|
|
3117
3126
|
* mutated, so a rejection leaves the table, the schema and the transaction untouched.
|
|
3118
3127
|
*
|
|
3119
|
-
*
|
|
3120
|
-
*
|
|
3121
|
-
*
|
|
3122
|
-
*
|
|
3128
|
+
* Asks two questions, in order, over two DIFFERENT row sets:
|
|
3129
|
+
*
|
|
3130
|
+
* 1. **Is the change legal at all?** — probes the rows the DDL transaction can SEE: the
|
|
3131
|
+
* wrapper-supplied `rows` when a wrapper module (the isolation layer) holds the
|
|
3132
|
+
* transaction's pending rows outside this manager, otherwise this manager's own
|
|
3133
|
+
* layered view ({@link effectiveDdlRows}). A duplicate here is visible to a `select`
|
|
3134
|
+
* in this transaction, so the change is simply illegal → `CONSTRAINT`, naming the
|
|
3135
|
+
* colliding key.
|
|
3136
|
+
* 2. **Can the structures physically carry it?** — probes every layer of this manager's
|
|
3137
|
+
* own chain. The primary tree is a map, not a multi-map, so — unlike a secondary
|
|
3138
|
+
* index — no tree that a `rollback` / `rollback to savepoint` could restore may hold
|
|
3139
|
+
* two rows whose keys collapse under the new comparator. A collision confined to
|
|
3140
|
+
* committed rows the transaction has DELETED is therefore refused by physical
|
|
3141
|
+
* necessity, not because the data is invalid: the base must keep both rows for a
|
|
3142
|
+
* rollback, and a base re-keyed under the new collation could not represent the pair
|
|
3143
|
+
* at all → `BUSY` with the same "commit/rollback and retry" posture as
|
|
3144
|
+
* {@link ensureSchemaChangeSafety}. The persistent store backend refuses the same
|
|
3145
|
+
* shape for the same reason (its committed rows equally survive a rollback — see
|
|
3146
|
+
* `backlog/bug-store-pk-collate-rejects-deleted-row-collision`); accepting it would
|
|
3147
|
+
* take transaction-scoped DDL (`backlog/feat-transactional-ddl-native-backends`),
|
|
3148
|
+
* which Quereus does not have.
|
|
3123
3149
|
*
|
|
3124
|
-
*
|
|
3125
|
-
*
|
|
3126
|
-
*
|
|
3127
|
-
*
|
|
3128
|
-
*
|
|
3129
|
-
* represent the pair at all. Committing (or rolling back) settles the transaction and
|
|
3130
|
-
* the ALTER can be retried — the same "commit/rollback and retry" posture as
|
|
3131
|
-
* {@link ensureSchemaChangeSafety}.
|
|
3150
|
+
* The passes judge different sets because a wrapper's effective stream and this manager's
|
|
3151
|
+
* layers genuinely diverge: staged inserts exist only in the stream, deleted committed
|
|
3152
|
+
* rows only in the layers. When `rows` is supplied, the view layer holds the COMMITTED
|
|
3153
|
+
* rows — not a subset of what pass 1 judged — so pass 2 starts AT the view; when `rows`
|
|
3154
|
+
* is absent, pass 1 judged exactly the view's rows and pass 2 starts at its parent.
|
|
3132
3155
|
*
|
|
3133
|
-
*
|
|
3156
|
+
* Pass 2 is deliberately conservative. The chain holds one immutable layer per statement
|
|
3134
3157
|
* boundary (see `MemoryTableConnection.createSavepoint`'s eager path), so it rejects any
|
|
3135
3158
|
* transaction that has held a colliding pair at ANY statement boundary — even one whose
|
|
3136
3159
|
* final view is clean and whose intermediate layer no savepoint can reach. Narrowing that
|
|
@@ -3142,40 +3165,78 @@ export class MemoryTableManager {
|
|
|
3142
3165
|
* with no collisions anywhere in the chain, every primary key resolves to at most one row
|
|
3143
3166
|
* in each layer under the new comparator.
|
|
3144
3167
|
*/
|
|
3145
|
-
validateRekeyedPrimaryKey(newSchema) {
|
|
3168
|
+
async validateRekeyedPrimaryKey(newSchema, rows) {
|
|
3146
3169
|
const newPkFunctions = createPrimaryKeyFunctions(newSchema, this.collationResolver);
|
|
3147
3170
|
const connection = this.ddlConnection();
|
|
3148
3171
|
const view = connection
|
|
3149
3172
|
? (connection.pendingTransactionLayer ?? connection.readLayer)
|
|
3150
3173
|
: this.baseLayer;
|
|
3151
|
-
this.
|
|
3174
|
+
await this.assertNoPrimaryKeyCollisionInRows(rows ? rows() : this.effectiveDdlRows(), newPkFunctions, primaryKeyArity(newSchema) !== 1);
|
|
3152
3175
|
// `ensureSchemaChangeSafety` has already drained every committed layer into the base and
|
|
3153
|
-
// rejected sibling connections with open work, so
|
|
3154
|
-
//
|
|
3155
|
-
for (let layer = view.getParent(); layer; layer = layer.getParent()) {
|
|
3156
|
-
this.
|
|
3157
|
-
+ `rows this transaction has removed still collide under the new collation and must survive a rollback. `
|
|
3158
|
-
+ `Commit/rollback and retry.`);
|
|
3176
|
+
// rejected sibling connections with open work, so this walk covers the transaction's own
|
|
3177
|
+
// layers plus the base — every tree a rollback could restore.
|
|
3178
|
+
for (let layer = rows ? view : view.getParent(); layer; layer = layer.getParent()) {
|
|
3179
|
+
this.assertNoPrimaryKeyCollisionInLayer(layer, newPkFunctions);
|
|
3159
3180
|
}
|
|
3160
3181
|
}
|
|
3161
3182
|
/**
|
|
3162
|
-
*
|
|
3183
|
+
* A duplicate-key detector over the new primary key functions: feed it rows, and it returns
|
|
3184
|
+
* the key the moment one repeats. Shared by both arms of {@link validateRekeyedPrimaryKey}
|
|
3185
|
+
* so the async (effective-row) arm and the sync (layer-tree) arm cannot disagree about what
|
|
3186
|
+
* counts as a collision.
|
|
3187
|
+
*
|
|
3188
|
+
* NOTE: the probe holds every row it has seen, because the BTree derives its key from the
|
|
3189
|
+
* stored value — so an ALTER over a large table transiently doubles that table's row
|
|
3190
|
+
* references. If a wide table ever makes this the memory peak, key the probe by the PK
|
|
3191
|
+
* encoding (`primaryKeyFunctions.encode`) into a `Set` instead of by the row.
|
|
3192
|
+
*/
|
|
3193
|
+
makePrimaryKeyProbe(pkFunctions) {
|
|
3194
|
+
const probe = new BTree((row) => pkFunctions.extractFromRow(row), pkFunctions.compare);
|
|
3195
|
+
return (row) => {
|
|
3196
|
+
const key = pkFunctions.extractFromRow(row);
|
|
3197
|
+
if (probe.get(key) !== undefined)
|
|
3198
|
+
return key;
|
|
3199
|
+
probe.insert(row);
|
|
3200
|
+
return undefined;
|
|
3201
|
+
};
|
|
3202
|
+
}
|
|
3203
|
+
/**
|
|
3204
|
+
* Legality arm of {@link validateRekeyedPrimaryKey}: raises `CONSTRAINT`, naming the key,
|
|
3205
|
+
* when two of the rows the DDL transaction can SEE share a primary key under `pkFunctions`.
|
|
3206
|
+
* Takes a wrapper's merged async stream or this manager's own synchronous layered view.
|
|
3207
|
+
*/
|
|
3208
|
+
async assertNoPrimaryKeyCollisionInRows(rows, pkFunctions, keyIsTuple) {
|
|
3209
|
+
const seen = this.makePrimaryKeyProbe(pkFunctions);
|
|
3210
|
+
for await (const row of rows) {
|
|
3211
|
+
const key = seen(row);
|
|
3212
|
+
if (key === undefined)
|
|
3213
|
+
continue;
|
|
3214
|
+
const keyDesc = keyParts(key, keyIsTuple).map(formatKeyValue).join(', ');
|
|
3215
|
+
throw new QuereusError(`UNIQUE constraint failed: ${this._tableName} primary key collides under new collation (key: ${keyDesc})`, StatusCode.CONSTRAINT);
|
|
3216
|
+
}
|
|
3217
|
+
}
|
|
3218
|
+
/**
|
|
3219
|
+
* Representability arm of {@link validateRekeyedPrimaryKey}: raises `BUSY` when two of
|
|
3220
|
+
* `layer`'s physical rows share a primary key under `pkFunctions`. Its rows are ones a
|
|
3221
|
+
* rollback could restore, not ones the transaction can see, so this is never a statement
|
|
3222
|
+
* about the data's validity — hence the retryable status and wording.
|
|
3163
3223
|
*
|
|
3164
3224
|
* NOTE: O(rows) per layer, so O(layers × rows) for a whole chain — one more full pass than
|
|
3165
3225
|
* the base rebuild the caller is about to do anyway. Fine for a statement this rare; if a
|
|
3166
3226
|
* deep savepoint stack over a large table ever makes an ALTER slow, note that a layer's rows
|
|
3167
3227
|
* differ from its parent's only at the keys it wrote, so the walk can be narrowed to those.
|
|
3168
3228
|
*/
|
|
3169
|
-
|
|
3229
|
+
assertNoPrimaryKeyCollisionInLayer(layer, pkFunctions) {
|
|
3170
3230
|
const tree = layer.getModificationTree('primary');
|
|
3171
3231
|
if (!tree)
|
|
3172
3232
|
return;
|
|
3173
|
-
const
|
|
3233
|
+
const seen = this.makePrimaryKeyProbe(pkFunctions);
|
|
3174
3234
|
for (const row of iteratePrimaryRows(tree)) {
|
|
3175
|
-
|
|
3176
|
-
|
|
3177
|
-
|
|
3178
|
-
|
|
3235
|
+
if (seen(row) !== undefined) {
|
|
3236
|
+
throw new QuereusError(`Cannot change the collation of a primary key column of table ${this._tableName}: `
|
|
3237
|
+
+ `rows this transaction has removed still collide under the new collation and must survive a rollback. `
|
|
3238
|
+
+ `Commit/rollback and retry.`, StatusCode.BUSY);
|
|
3239
|
+
}
|
|
3179
3240
|
}
|
|
3180
3241
|
}
|
|
3181
3242
|
/**
|