@quereus/store 4.5.0 → 4.7.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 +34 -6
- package/dist/src/common/encoding.d.ts +4 -3
- package/dist/src/common/encoding.d.ts.map +1 -1
- package/dist/src/common/encoding.js +17 -13
- package/dist/src/common/encoding.js.map +1 -1
- package/dist/src/common/events.d.ts +31 -25
- package/dist/src/common/events.d.ts.map +1 -1
- package/dist/src/common/events.js +38 -39
- package/dist/src/common/events.js.map +1 -1
- package/dist/src/common/implicit-unique-index.d.ts +80 -0
- package/dist/src/common/implicit-unique-index.d.ts.map +1 -0
- package/dist/src/common/implicit-unique-index.js +148 -0
- package/dist/src/common/implicit-unique-index.js.map +1 -0
- package/dist/src/common/index.d.ts +7 -3
- package/dist/src/common/index.d.ts.map +1 -1
- package/dist/src/common/index.js +5 -2
- package/dist/src/common/index.js.map +1 -1
- package/dist/src/common/json-key.d.ts +30 -2
- package/dist/src/common/json-key.d.ts.map +1 -1
- package/dist/src/common/json-key.js +49 -2
- package/dist/src/common/json-key.js.map +1 -1
- package/dist/src/common/key-builder.d.ts +40 -20
- package/dist/src/common/key-builder.d.ts.map +1 -1
- package/dist/src/common/key-builder.js +31 -23
- package/dist/src/common/key-builder.js.map +1 -1
- package/dist/src/common/kv-store.d.ts +10 -0
- package/dist/src/common/kv-store.d.ts.map +1 -1
- package/dist/src/common/pk-key-resolution.d.ts +348 -0
- package/dist/src/common/pk-key-resolution.d.ts.map +1 -0
- package/dist/src/common/pk-key-resolution.js +481 -0
- package/dist/src/common/pk-key-resolution.js.map +1 -0
- package/dist/src/common/store-module-access-plan.d.ts +32 -0
- package/dist/src/common/store-module-access-plan.d.ts.map +1 -0
- package/dist/src/common/store-module-access-plan.js +428 -0
- package/dist/src/common/store-module-access-plan.js.map +1 -0
- package/dist/src/common/store-module-alter-column.d.ts +23 -0
- package/dist/src/common/store-module-alter-column.d.ts.map +1 -0
- package/dist/src/common/store-module-alter-column.js +389 -0
- package/dist/src/common/store-module-alter-column.js.map +1 -0
- package/dist/src/common/store-module-alter.d.ts +55 -0
- package/dist/src/common/store-module-alter.d.ts.map +1 -0
- package/dist/src/common/store-module-alter.js +504 -0
- package/dist/src/common/store-module-alter.js.map +1 -0
- package/dist/src/common/store-module-base.d.ts +268 -0
- package/dist/src/common/store-module-base.d.ts.map +1 -0
- package/dist/src/common/store-module-base.js +362 -0
- package/dist/src/common/store-module-base.js.map +1 -0
- package/dist/src/common/store-module-catalog.d.ts +269 -0
- package/dist/src/common/store-module-catalog.d.ts.map +1 -0
- package/dist/src/common/store-module-catalog.js +462 -0
- package/dist/src/common/store-module-catalog.js.map +1 -0
- package/dist/src/common/store-module-index-build.d.ts +88 -0
- package/dist/src/common/store-module-index-build.d.ts.map +1 -0
- package/dist/src/common/store-module-index-build.js +280 -0
- package/dist/src/common/store-module-index-build.js.map +1 -0
- package/dist/src/common/store-module-index.d.ts +116 -0
- package/dist/src/common/store-module-index.d.ts.map +1 -0
- package/dist/src/common/store-module-index.js +373 -0
- package/dist/src/common/store-module-index.js.map +1 -0
- package/dist/src/common/store-module-rename.d.ts +49 -0
- package/dist/src/common/store-module-rename.d.ts.map +1 -0
- package/dist/src/common/store-module-rename.js +268 -0
- package/dist/src/common/store-module-rename.js.map +1 -0
- package/dist/src/common/store-module-schema-rewrite.d.ts +57 -0
- package/dist/src/common/store-module-schema-rewrite.d.ts.map +1 -0
- package/dist/src/common/store-module-schema-rewrite.js +140 -0
- package/dist/src/common/store-module-schema-rewrite.js.map +1 -0
- package/dist/src/common/store-module-schema-sync.d.ts +232 -0
- package/dist/src/common/store-module-schema-sync.d.ts.map +1 -0
- package/dist/src/common/store-module-schema-sync.js +529 -0
- package/dist/src/common/store-module-schema-sync.js.map +1 -0
- package/dist/src/common/store-module.d.ts +43 -909
- package/dist/src/common/store-module.d.ts.map +1 -1
- package/dist/src/common/store-module.js +184 -3276
- package/dist/src/common/store-module.js.map +1 -1
- package/dist/src/common/store-table-base.d.ts +539 -0
- package/dist/src/common/store-table-base.d.ts.map +1 -0
- package/dist/src/common/store-table-base.js +900 -0
- package/dist/src/common/store-table-base.js.map +1 -0
- package/dist/src/common/store-table-constraints.d.ts +237 -0
- package/dist/src/common/store-table-constraints.d.ts.map +1 -0
- package/dist/src/common/store-table-constraints.js +624 -0
- package/dist/src/common/store-table-constraints.js.map +1 -0
- package/dist/src/common/store-table-scan.d.ts +452 -0
- package/dist/src/common/store-table-scan.d.ts.map +1 -0
- package/dist/src/common/store-table-scan.js +901 -0
- package/dist/src/common/store-table-scan.js.map +1 -0
- package/dist/src/common/store-table.d.ts +71 -1144
- package/dist/src/common/store-table.d.ts.map +1 -1
- package/dist/src/common/store-table.js +168 -2385
- package/dist/src/common/store-table.js.map +1 -1
- package/dist/src/testing/index.d.ts +12 -0
- package/dist/src/testing/index.d.ts.map +1 -0
- package/dist/src/testing/index.js +12 -0
- package/dist/src/testing/index.js.map +1 -0
- package/dist/src/testing/kv-assert.d.ts +19 -0
- package/dist/src/testing/kv-assert.d.ts.map +1 -0
- package/dist/src/testing/kv-assert.js +25 -0
- package/dist/src/testing/kv-assert.js.map +1 -0
- package/dist/src/testing/kv-conformance.d.ts.map +1 -1
- package/dist/src/testing/kv-conformance.js +1 -15
- package/dist/src/testing/kv-conformance.js.map +1 -1
- package/dist/src/testing/kv-provider-conformance.d.ts +54 -0
- package/dist/src/testing/kv-provider-conformance.d.ts.map +1 -0
- package/dist/src/testing/kv-provider-conformance.js +183 -0
- package/dist/src/testing/kv-provider-conformance.js.map +1 -0
- package/package.json +8 -8
|
@@ -0,0 +1,624 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Secondary-index maintenance and UNIQUE enforcement for the KVStore-backed
|
|
3
|
+
* virtual table — the two halves of keeping a table's indexes and uniqueness
|
|
4
|
+
* invariants true across a write. Index upkeep is how UNIQUE is enforced (a
|
|
5
|
+
* conflict is answered by a seek when an index soundly covers the constraint's
|
|
6
|
+
* enforcement collations, and by a data-store scan otherwise), and a REPLACE
|
|
7
|
+
* eviction needs both.
|
|
8
|
+
*
|
|
9
|
+
* Third layer of the store-table chain:
|
|
10
|
+
* StoreTableBase -> StoreTableScan -> StoreTableConstraints -> StoreTable
|
|
11
|
+
*/
|
|
12
|
+
import { ConflictResolution, compareSqlValues, resolveUniqueEnforcementCollations, uniqueEnforcementComparators, compilePredicate, maintainedTableUniqueViolationError, uniqueEnforcementCollations, } from '@quereus/quereus';
|
|
13
|
+
import { bytesToHex } from './bytes.js';
|
|
14
|
+
import { buildIndexKey, buildIndexPrefixBounds, buildFullScanBounds, } from './key-builder.js';
|
|
15
|
+
import { deserializeRow, } from './serialization.js';
|
|
16
|
+
import { columnCanHoldText, resolveIndexKeyCollations, resolveIndexKeyTransforms } from './pk-key-resolution.js';
|
|
17
|
+
import { implicitUniqueIndexName } from './implicit-unique-index.js';
|
|
18
|
+
import { StoreTableScan } from './store-table-scan.js';
|
|
19
|
+
/**
|
|
20
|
+
* Returned by {@link StoreTableConstraints.findUniqueConflictViaIndex} when the index
|
|
21
|
+
* cannot soundly answer the check and the caller must fall back to the full
|
|
22
|
+
* data-store scan. Distinct from `null`, which means "the index answered: no
|
|
23
|
+
* conflict".
|
|
24
|
+
*/
|
|
25
|
+
const INDEX_UNUSABLE = Symbol('store.uniqueIndexUnusable');
|
|
26
|
+
/**
|
|
27
|
+
* Index-maintenance and UNIQUE-enforcement layer of the generic KVStore-backed
|
|
28
|
+
* virtual table.
|
|
29
|
+
*
|
|
30
|
+
* Conflict detection compares under the constraint's ENFORCEMENT collations,
|
|
31
|
+
* which need not match the collations the index keys under — every index-seek
|
|
32
|
+
* shortcut here is gated on that agreement and falls back to the data-store scan
|
|
33
|
+
* when it cannot be shown.
|
|
34
|
+
*/
|
|
35
|
+
export class StoreTableConstraints extends StoreTableScan {
|
|
36
|
+
// Lazy cache of compiled partial-UNIQUE predicates. Keyed on the
|
|
37
|
+
// UniqueConstraintSchema object identity — UC schemas are frozen and a
|
|
38
|
+
// new constraint object after CREATE/DROP INDEX produces a fresh compile;
|
|
39
|
+
// the WeakMap lets the GC reclaim entries for retired constraints.
|
|
40
|
+
predicateCache = new WeakMap();
|
|
41
|
+
// Lazy cache of compiled partial-index predicates, keyed on the IndexSchema
|
|
42
|
+
// object identity (frozen; a CREATE/DROP INDEX or reopen produces a fresh
|
|
43
|
+
// object, so the WeakMap reclaims retired entries). Mirrors predicateCache but
|
|
44
|
+
// for secondary-index maintenance rather than UNIQUE enforcement.
|
|
45
|
+
indexPredicateCache = new WeakMap();
|
|
46
|
+
/**
|
|
47
|
+
* Update secondary indexes after a row change.
|
|
48
|
+
*
|
|
49
|
+
* For PK-change UPDATE, `oldPk` (where the existing entry lives) and `newPk`
|
|
50
|
+
* (where the relocated entry will live) differ; using a single pk for both
|
|
51
|
+
* sides leaks the old entry. Other paths pass the same pk for both.
|
|
52
|
+
*/
|
|
53
|
+
async updateSecondaryIndexes(inTransaction, oldRow, newRow, oldPk, newPk = oldPk) {
|
|
54
|
+
// Maintain the MATERIALIZED index set: the hidden `_uc_*` per-UNIQUE index must be
|
|
55
|
+
// kept in step with DML so the enforcement seek finds every live row.
|
|
56
|
+
const indexes = this.materializedSchema.indexes || [];
|
|
57
|
+
for (const index of indexes) {
|
|
58
|
+
const indexStore = await this.ensureIndexStore(index.name);
|
|
59
|
+
const indexCols = index.columns.map(c => c.index);
|
|
60
|
+
const indexDirections = index.columns.map(c => !!c.desc);
|
|
61
|
+
// Canonicalize semantic-ordering index members ('PT1H'/'PT60M' → one key) so a
|
|
62
|
+
// UNIQUE enforcement seek and delete-then-insert maintenance address one entry.
|
|
63
|
+
const indexTransforms = resolveIndexKeyTransforms(index, this.tableSchema.columns);
|
|
64
|
+
// Each index column keys under its OWN collation (index COLLATE ?? table column
|
|
65
|
+
// collation ?? BINARY) — the same resolution `buildIndexEntries` uses for the
|
|
66
|
+
// build/rebuild path; the two MUST agree or a maintenance delete misses the
|
|
67
|
+
// entry the build wrote and the index silently rots.
|
|
68
|
+
const indexCollations = resolveIndexKeyCollations(index, this.tableSchema.columns);
|
|
69
|
+
// Partial index: only rows the predicate unambiguously accepts are
|
|
70
|
+
// indexed (mirrors buildIndexEntries' build-time filtering). Guarding both
|
|
71
|
+
// halves keeps a row that transitions across the predicate scope on UPDATE
|
|
72
|
+
// correct — an in-scope→out-of-scope edit removes the old entry and adds
|
|
73
|
+
// none; the reverse adds without a stale delete. A full index (no
|
|
74
|
+
// predicate) always maintains its entry.
|
|
75
|
+
const predicate = this.compileIndexFor(index);
|
|
76
|
+
// Remove old index entry (only if the old row was within scope).
|
|
77
|
+
if (oldRow && (!predicate || predicate.evaluate(oldRow) === true)) {
|
|
78
|
+
const oldIndexValues = indexCols.map(i => oldRow[i]);
|
|
79
|
+
const oldIndexKey = buildIndexKey({ values: oldIndexValues, directions: indexDirections, collations: indexCollations, transforms: indexTransforms }, { values: oldPk, directions: this.pkDirections, collations: this.pkKeyCollations, transforms: this.pkKeyTransforms }, this.encodeOptions);
|
|
80
|
+
if (inTransaction && this.coordinator) {
|
|
81
|
+
this.coordinator.delete(oldIndexKey, indexStore);
|
|
82
|
+
}
|
|
83
|
+
else {
|
|
84
|
+
await indexStore.delete(oldIndexKey);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
// Add new index entry (only if the new row is within scope).
|
|
88
|
+
if (newRow && (!predicate || predicate.evaluate(newRow) === true)) {
|
|
89
|
+
const newIndexValues = indexCols.map(i => newRow[i]);
|
|
90
|
+
const newIndexKey = buildIndexKey({ values: newIndexValues, directions: indexDirections, collations: indexCollations, transforms: indexTransforms }, { values: newPk, directions: this.pkDirections, collations: this.pkKeyCollations, transforms: this.pkKeyTransforms }, this.encodeOptions);
|
|
91
|
+
// Index value = the row's encoded DATA key. The index-entry key can
|
|
92
|
+
// locate a row's byte window, but its PK suffix is not losslessly
|
|
93
|
+
// recoverable to SqlValues (a NOCASE/RTRIM PK column encodes lossily)
|
|
94
|
+
// and its length varies per entry in a range scan — so a scan resolves
|
|
95
|
+
// each entry back to its base row via this stored data key
|
|
96
|
+
// (`scanIndex` → `readEffectiveRowByKey(entry.value)`), never by
|
|
97
|
+
// decoding the suffix. `newPk` is the PK the entry is keyed under, so
|
|
98
|
+
// its data key byte-matches the data store's key for this row.
|
|
99
|
+
const dataKeyValue = this.encodeDataKey(newPk);
|
|
100
|
+
if (inTransaction && this.coordinator) {
|
|
101
|
+
this.coordinator.put(newIndexKey, dataKeyValue, indexStore);
|
|
102
|
+
}
|
|
103
|
+
else {
|
|
104
|
+
await indexStore.put(newIndexKey, dataKeyValue);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Returns the compiled predicate for a partial-UNIQUE constraint, or undefined
|
|
111
|
+
* when the constraint covers the full table. Compilation is memoized per
|
|
112
|
+
* UniqueConstraintSchema instance so the hot UNIQUE-check path doesn't recompile.
|
|
113
|
+
*/
|
|
114
|
+
compileFor(uc) {
|
|
115
|
+
if (!uc.predicate)
|
|
116
|
+
return undefined;
|
|
117
|
+
let compiled = this.predicateCache.get(uc);
|
|
118
|
+
if (!compiled) {
|
|
119
|
+
compiled = compilePredicate(uc.predicate, this.tableSchema.columns, this.tableSchema.name);
|
|
120
|
+
this.predicateCache.set(uc, compiled);
|
|
121
|
+
}
|
|
122
|
+
return compiled;
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Returns the compiled predicate for a partial secondary index, or undefined
|
|
126
|
+
* for a full index. Compilation is memoized per IndexSchema instance so the hot
|
|
127
|
+
* DML index-maintenance path doesn't recompile.
|
|
128
|
+
*/
|
|
129
|
+
compileIndexFor(index) {
|
|
130
|
+
if (!index.predicate)
|
|
131
|
+
return undefined;
|
|
132
|
+
let compiled = this.indexPredicateCache.get(index);
|
|
133
|
+
if (!compiled) {
|
|
134
|
+
compiled = compilePredicate(index.predicate, this.tableSchema.columns, this.tableSchema.name);
|
|
135
|
+
this.indexPredicateCache.set(index, compiled);
|
|
136
|
+
}
|
|
137
|
+
return compiled;
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* Check if two PK arrays name the same row. A semantic-ordering member compares
|
|
141
|
+
* through its type's `compare` (see {@link resolvePkSemanticEquality}) so
|
|
142
|
+
* differently-spelled equal values ('PT1H' / 'PT60M') answer "same row",
|
|
143
|
+
* agreeing with the physical key identity {@link encodeDataKey} produces; every
|
|
144
|
+
* other member keeps the original strict `!==`.
|
|
145
|
+
*/
|
|
146
|
+
keysEqual(a, b) {
|
|
147
|
+
if (a.length !== b.length)
|
|
148
|
+
return false;
|
|
149
|
+
for (let i = 0; i < a.length; i++) {
|
|
150
|
+
const semantic = this.pkSemanticEquality[i];
|
|
151
|
+
if (semantic ? semantic(a[i], b[i]) !== 0 : a[i] !== b[i])
|
|
152
|
+
return false;
|
|
153
|
+
}
|
|
154
|
+
return true;
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* Per-constrained-column comparison functions for one UNIQUE constraint: the
|
|
158
|
+
* type's `compare` for a semantic-ordering column (so 'PT1H' conflicts with
|
|
159
|
+
* 'PT60M', matching the memory backend's typed BTree), else the enforcement
|
|
160
|
+
* collation the caller resolved (`resolveUniqueEnforcementCollations`) through
|
|
161
|
+
* `compareSqlValuesFast` — the exact comparison every finder used before.
|
|
162
|
+
*
|
|
163
|
+
* Thin wrapper over the engine's `uniqueEnforcementComparators`, which memory
|
|
164
|
+
* and the isolation overlay share so the three backends cannot drift.
|
|
165
|
+
*/
|
|
166
|
+
uniqueColumnComparators(uc, collations) {
|
|
167
|
+
return uniqueEnforcementComparators(this.tableSchema.columns, uc.columns, collations);
|
|
168
|
+
}
|
|
169
|
+
/**
|
|
170
|
+
* Returns true if any column covered by a UNIQUE constraint differs between
|
|
171
|
+
* oldRow and newRow, or — for partial UNIQUE — any column referenced by the
|
|
172
|
+
* partial predicate differs (which can transition the row across the
|
|
173
|
+
* predicate scope and re-trigger the uniqueness check).
|
|
174
|
+
*/
|
|
175
|
+
uniqueColumnsChanged(oldRow, newRow) {
|
|
176
|
+
const ucs = this.tableSchema?.uniqueConstraints;
|
|
177
|
+
if (!ucs || ucs.length === 0)
|
|
178
|
+
return false;
|
|
179
|
+
for (const uc of ucs) {
|
|
180
|
+
for (const colIdx of uc.columns) {
|
|
181
|
+
if (compareSqlValues(oldRow[colIdx], newRow[colIdx]) !== 0)
|
|
182
|
+
return true;
|
|
183
|
+
}
|
|
184
|
+
if (uc.predicate) {
|
|
185
|
+
const compiled = this.compileFor(uc);
|
|
186
|
+
if (compiled) {
|
|
187
|
+
for (const colIdx of compiled.referencedColumns) {
|
|
188
|
+
if (compareSqlValues(oldRow[colIdx], newRow[colIdx]) !== 0)
|
|
189
|
+
return true;
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
return false;
|
|
195
|
+
}
|
|
196
|
+
/**
|
|
197
|
+
* Enforce table-level UNIQUE constraints against the prospective newRow.
|
|
198
|
+
* Honors `onConflict`: IGNORE returns an ok-with-undefined-row; REPLACE
|
|
199
|
+
* deletes the conflicting row(s) and continues; otherwise returns a
|
|
200
|
+
* constraint result. Returns null when all constraints pass.
|
|
201
|
+
*
|
|
202
|
+
* Rows whose PK is in `selfPks` are skipped (the row being inserted/updated).
|
|
203
|
+
* NULL in any covered column skips that constraint (multiple NULLs are allowed
|
|
204
|
+
* per SQL standard).
|
|
205
|
+
*
|
|
206
|
+
* Reads through the transaction coordinator's pending writes when active so
|
|
207
|
+
* intra-transaction duplicates are detected.
|
|
208
|
+
*
|
|
209
|
+
* REPLACE evictions (rows at OTHER PKs) are deleted from storage and pushed onto
|
|
210
|
+
* `evicted` so the DML executor runs the full delete pipeline for each
|
|
211
|
+
* (change-tracking, row-time MV maintenance, FK cascade, auto-events).
|
|
212
|
+
*/
|
|
213
|
+
async checkUniqueConstraints(inTransaction, newRow, selfPks, onConflict, evicted) {
|
|
214
|
+
const schema = this.tableSchema;
|
|
215
|
+
const uniqueConstraints = schema.uniqueConstraints;
|
|
216
|
+
if (!uniqueConstraints || uniqueConstraints.length === 0)
|
|
217
|
+
return null;
|
|
218
|
+
for (const uc of uniqueConstraints) {
|
|
219
|
+
if (uc.columns.some(idx => newRow[idx] === null))
|
|
220
|
+
continue;
|
|
221
|
+
// Partial UNIQUE: a row whose predicate is not unambiguously TRUE is
|
|
222
|
+
// outside the index's scope and contributes nothing to uniqueness.
|
|
223
|
+
const predicate = this.compileFor(uc);
|
|
224
|
+
if (predicate && predicate.evaluate(newRow) !== true)
|
|
225
|
+
continue;
|
|
226
|
+
const conflict = await this.findUniqueConflictFor(uc, predicate, newRow, selfPks);
|
|
227
|
+
if (!conflict)
|
|
228
|
+
continue;
|
|
229
|
+
// Resolve action per-constraint: statement OR > per-UC default > ABORT.
|
|
230
|
+
const effective = onConflict ?? uc.defaultConflict ?? ConflictResolution.ABORT;
|
|
231
|
+
if (effective === ConflictResolution.IGNORE) {
|
|
232
|
+
return { status: 'ok', row: undefined };
|
|
233
|
+
}
|
|
234
|
+
if (effective === ConflictResolution.REPLACE) {
|
|
235
|
+
await this.deleteRowAt(inTransaction, conflict.pk, conflict.row);
|
|
236
|
+
// Report the eviction so the executor runs its full delete pipeline —
|
|
237
|
+
// including the row-time covering-structure maintenance that drops the
|
|
238
|
+
// evicted source row's backing entry within this statement (else a later
|
|
239
|
+
// same-UC row sees a phantom). The executor processes the eviction before
|
|
240
|
+
// the writing row's own bookkeeping, so the backing delete still lands
|
|
241
|
+
// mid-statement.
|
|
242
|
+
evicted.push(conflict.row);
|
|
243
|
+
continue;
|
|
244
|
+
}
|
|
245
|
+
const colNames = uc.columns.map(i => schema.columns[i].name).join(', ');
|
|
246
|
+
return {
|
|
247
|
+
status: 'constraint',
|
|
248
|
+
constraint: 'unique',
|
|
249
|
+
message: `UNIQUE constraint failed: ${schema.name} (${colNames})`,
|
|
250
|
+
existingRow: conflict.row,
|
|
251
|
+
};
|
|
252
|
+
}
|
|
253
|
+
return null;
|
|
254
|
+
}
|
|
255
|
+
/**
|
|
256
|
+
* Route one UNIQUE constraint's conflict search to the cheapest SOUND finder,
|
|
257
|
+
* in descending preference:
|
|
258
|
+
*
|
|
259
|
+
* 1. A linked row-time covering MV — its backing table (hosted by any
|
|
260
|
+
* backing-host-capable module — memory by default, this store module under
|
|
261
|
+
* `using store` — queried through the db with reads-own-writes) answers the
|
|
262
|
+
* uniqueness question, mirroring the memory enforcement path.
|
|
263
|
+
* 2. A physical secondary index realizing the constraint — one prefix seek
|
|
264
|
+
* instead of a full table scan (see {@link findIndexForUniqueConstraint}).
|
|
265
|
+
* 3. The full data-store scan ({@link findUniqueConflict}) — always correct,
|
|
266
|
+
* O(rows) per checked row.
|
|
267
|
+
*
|
|
268
|
+
* Every finder returns the SAME `{pk, row}` shape, so the caller's conflict
|
|
269
|
+
* action (ABORT / IGNORE / REPLACE eviction) is finder-independent.
|
|
270
|
+
*/
|
|
271
|
+
async findUniqueConflictFor(uc, predicate, newRow, selfPks) {
|
|
272
|
+
const schema = this.tableSchema;
|
|
273
|
+
const coveringMv = this.db._findRowTimeCoveringStructure(schema.schemaName, schema.name, uc);
|
|
274
|
+
if (coveringMv)
|
|
275
|
+
return this.findUniqueConflictViaCoveringMv(coveringMv, uc, predicate, newRow, selfPks);
|
|
276
|
+
const index = this.findIndexForUniqueConstraint(uc);
|
|
277
|
+
if (index) {
|
|
278
|
+
const viaIndex = await this.findUniqueConflictViaIndex(index, uc, predicate, newRow, selfPks);
|
|
279
|
+
if (viaIndex !== INDEX_UNUSABLE)
|
|
280
|
+
return viaIndex;
|
|
281
|
+
}
|
|
282
|
+
return this.findUniqueConflict(uc, predicate, newRow, selfPks);
|
|
283
|
+
}
|
|
284
|
+
/**
|
|
285
|
+
* The `schema.indexes` entry whose physical index store can serve `uc`'s
|
|
286
|
+
* conflict search as a point seek, or undefined when none can.
|
|
287
|
+
*
|
|
288
|
+
* Every non-derived UNIQUE is realized by an index in the materialized schema
|
|
289
|
+
* — a hidden `_uc_*`, or the explicit index it reuses when one covers the same
|
|
290
|
+
* columns (see {@link withImplicitUniqueIndexes} /
|
|
291
|
+
* {@link findReusableIndexForUnique}) — so, like the memory backend, a plain
|
|
292
|
+
* column- or table-level `UNIQUE` is index-servable, not only an explicit
|
|
293
|
+
* `CREATE INDEX`. A UC is index-servable when:
|
|
294
|
+
*
|
|
295
|
+
* - it is index-derived (`derivedFromIndex`, from `CREATE UNIQUE INDEX`) and
|
|
296
|
+
* its named index is still present — the index's partial predicate then
|
|
297
|
+
* equals the constraint's by construction (`appendIndexToTableSchema`); or
|
|
298
|
+
* - some index's columns equal `uc.columns` positionally AND whose predicate
|
|
299
|
+
* is the SAME object as `uc.predicate` (reference identity — the implicit
|
|
300
|
+
* materializer sets it that way). For a FULL UNIQUE that is
|
|
301
|
+
* `undefined === undefined`, which also admits any user full index over the
|
|
302
|
+
* same columns. For a PARTIAL `unique(...) where p` it admits only the
|
|
303
|
+
* co-scoped `_uc_*` (which holds exactly the in-scope rows); an arbitrary
|
|
304
|
+
* user partial index with a DIFFERENT predicate object stays conservative
|
|
305
|
+
* (declined → full scan), because it physically omits rows the constraint
|
|
306
|
+
* still covers. The serving index need not be UNIQUE — a plain index over
|
|
307
|
+
* the constrained columns still holds every in-scope row.
|
|
308
|
+
*
|
|
309
|
+
* Collation guard (see {@link indexSeekHonorsEnforcementCollation}) may still
|
|
310
|
+
* reject the found index, which routes the check back to the full scan.
|
|
311
|
+
*/
|
|
312
|
+
findIndexForUniqueConstraint(uc) {
|
|
313
|
+
// NOTE: re-resolved for every constrained ROW written, and the collation guard
|
|
314
|
+
// below re-derives `uniqueEnforcementCollations` each time. Both are linear in
|
|
315
|
+
// `schema.indexes` / `uc.columns` and dwarfed by the seek's I/O, so this is fine
|
|
316
|
+
// now. If a table with many indexes ever shows up on an insert-heavy profile,
|
|
317
|
+
// memoize the (uc → index | undefined) resolution in a WeakMap keyed on the
|
|
318
|
+
// frozen UniqueConstraintSchema, as `predicateCache` above does — a CREATE/DROP
|
|
319
|
+
// INDEX yields fresh constraint objects, so such a cache invalidates itself.
|
|
320
|
+
// Reads the MATERIALIZED index set so the hidden `_uc_*` realizing a plain UNIQUE
|
|
321
|
+
// is visible (the engine-facing `tableSchema` carries only explicit/derived indexes).
|
|
322
|
+
const indexes = this.materializedSchema.indexes;
|
|
323
|
+
if (!indexes || indexes.length === 0)
|
|
324
|
+
return undefined;
|
|
325
|
+
let index;
|
|
326
|
+
if (uc.derivedFromIndex) {
|
|
327
|
+
index = indexes.find(ix => ix.name === uc.derivedFromIndex);
|
|
328
|
+
}
|
|
329
|
+
else {
|
|
330
|
+
// Among the column-set matches, prefer the constraint's OWN index by name
|
|
331
|
+
// (`implicitUniqueIndexName` — the `_uc_*` the materializer minted for it).
|
|
332
|
+
// `withImplicitUniqueIndexes` APPENDS `_uc_*` after the explicit indexes, so a
|
|
333
|
+
// bare first-match would land on an explicit index that
|
|
334
|
+
// `findReusableIndexForUnique` REFUSED for a collation mismatch — whose key
|
|
335
|
+
// bytes now differ from the enforcement collation, so seeking it would
|
|
336
|
+
// under-fetch and silently accept a duplicate. When no `_uc_*` exists the
|
|
337
|
+
// remaining match is the reuse-approved index, whose collations
|
|
338
|
+
// `indexCollationsMatchDeclared` proved equal to the declared ones.
|
|
339
|
+
const candidates = indexes.filter(ix => ix.predicate === uc.predicate
|
|
340
|
+
&& ix.columns.length === uc.columns.length
|
|
341
|
+
&& ix.columns.every((c, i) => c.index === uc.columns[i]));
|
|
342
|
+
const ownName = implicitUniqueIndexName(this.materializedSchema, uc).toLowerCase();
|
|
343
|
+
index = candidates.find(ix => ix.name.toLowerCase() === ownName) ?? candidates[0];
|
|
344
|
+
}
|
|
345
|
+
if (!index)
|
|
346
|
+
return undefined;
|
|
347
|
+
return this.indexSeekHonorsEnforcementCollation(index, uc) ? index : undefined;
|
|
348
|
+
}
|
|
349
|
+
/**
|
|
350
|
+
* True when a point seek into `index` returns a SUPERSET of `uc`'s true conflict
|
|
351
|
+
* set — the only condition under which the seek may replace the full scan.
|
|
352
|
+
*
|
|
353
|
+
* An index key's leading (index-column) bytes are encoded under the index's own
|
|
354
|
+
* per-column key collations (`resolveIndexKeyCollations`), and the constraint
|
|
355
|
+
* re-validates candidates under its enforcement collations
|
|
356
|
+
* (`uniqueEnforcementCollations` — the index's per-column COLLATE for an
|
|
357
|
+
* index-derived UC, else the declared column collation). For every index a
|
|
358
|
+
* *designed* path can hand this method, the two resolve identically by
|
|
359
|
+
* construction — the seek window is then exactly the C-equal set — so the check
|
|
360
|
+
* is a plain per-column equality of the two resolutions (upper-cased; never-text
|
|
361
|
+
* columns exempt, their bytes being type-native).
|
|
362
|
+
*
|
|
363
|
+
* Kept rather than deleted because one undesigned path can still disagree:
|
|
364
|
+
* `withImplicitUniqueIndexes` skips materializing a `_uc_*` whose NAME is already
|
|
365
|
+
* taken (a user index literally named `_uc_email`, or a named UC colliding with an
|
|
366
|
+
* index name), and the column-set fallback in
|
|
367
|
+
* {@link findIndexForUniqueConstraint} can then hand this a same-columns index
|
|
368
|
+
* whose key collations differ from the enforcement collations. A false `true`
|
|
369
|
+
* there silently accepts a duplicate; a decline only costs the full scan.
|
|
370
|
+
*/
|
|
371
|
+
indexSeekHonorsEnforcementCollation(index, uc) {
|
|
372
|
+
const schema = this.tableSchema;
|
|
373
|
+
const keyCollations = resolveIndexKeyCollations(index, schema.columns);
|
|
374
|
+
const enforcement = uniqueEnforcementCollations(schema, uc);
|
|
375
|
+
// Positions align: index.columns[i].index === uc.columns[i], guaranteed by the
|
|
376
|
+
// derived-UC construction (appendIndexToTableSchema) / the column-set match in
|
|
377
|
+
// findIndexForUniqueConstraint.
|
|
378
|
+
return uc.columns.every((colIdx, i) => {
|
|
379
|
+
if (!columnCanHoldText(schema.columns[colIdx]))
|
|
380
|
+
return true;
|
|
381
|
+
const key = keyCollations[i];
|
|
382
|
+
const C = (enforcement[i] ?? 'BINARY').toUpperCase();
|
|
383
|
+
return key !== undefined && key === C;
|
|
384
|
+
});
|
|
385
|
+
}
|
|
386
|
+
/**
|
|
387
|
+
* The index analogue of {@link findUniqueConflict}: seek the index realizing
|
|
388
|
+
* `uc` at the point formed by `newRow`'s constrained-column values, and
|
|
389
|
+
* re-validate each resolved candidate exactly as the full scan does.
|
|
390
|
+
*
|
|
391
|
+
* The seek encodes ALL of `uc.columns` (positionally aligned with the index's
|
|
392
|
+
* columns, guaranteed by `appendIndexToTableSchema` / the column-set match in
|
|
393
|
+
* {@link findIndexForUniqueConstraint}) as a leading prefix of the index key,
|
|
394
|
+
* under the same key collation and per-column DESC directions
|
|
395
|
+
* {@link updateSecondaryIndexes} used to write it. The remaining suffix is the
|
|
396
|
+
* row's PK, so the window spans every entry sharing those column values.
|
|
397
|
+
* {@link iterateEffective} merges this transaction's pending index puts/deletes
|
|
398
|
+
* over the committed entries, giving read-your-own-writes; each entry resolves
|
|
399
|
+
* to its LIVE row through the data key stored as the entry's value.
|
|
400
|
+
*
|
|
401
|
+
* The seek only narrows the CANDIDATE set to a superset (guaranteed by
|
|
402
|
+
* {@link indexSeekHonorsEnforcementCollation}); the authoritative comparison is
|
|
403
|
+
* the identical self-PK exclusion, per-column enforcement-collation compare,
|
|
404
|
+
* and partial-predicate scope check the full scan performs. A partial index
|
|
405
|
+
* already excludes out-of-scope rows physically — the predicate re-check is
|
|
406
|
+
* kept as defense in depth.
|
|
407
|
+
*
|
|
408
|
+
* Returns {@link INDEX_UNUSABLE} rather than a (possibly wrong) answer when an
|
|
409
|
+
* entry carries a legacy empty value.
|
|
410
|
+
*/
|
|
411
|
+
async findUniqueConflictViaIndex(index, uc, predicate, newRow, selfPks) {
|
|
412
|
+
const indexStore = await this.ensureIndexStore(index.name);
|
|
413
|
+
// Resolved once, above the candidate loop: the resolver throws on an
|
|
414
|
+
// unregistered name and cannot be inlined, so a per-candidate call would be
|
|
415
|
+
// pure overhead.
|
|
416
|
+
const collations = resolveUniqueEnforcementCollations(this.tableSchema, uc, this.collationResolver);
|
|
417
|
+
const compares = this.uniqueColumnComparators(uc, collations);
|
|
418
|
+
// Same per-column key collations and transforms `updateSecondaryIndexes` wrote
|
|
419
|
+
// the entries under, so the probe for 'A@x' lands on the window holding the
|
|
420
|
+
// NOCASE-keyed 'a@x' entry and the probe for 'PT60M' on the 'PT1H' one.
|
|
421
|
+
const bounds = buildIndexPrefixBounds(uc.columns.map(c => newRow[c]), this.encodeOptions, index.columns.map(c => !!c.desc), resolveIndexKeyCollations(index, this.tableSchema.columns), resolveIndexKeyTransforms(index, this.tableSchema.columns));
|
|
422
|
+
for await (const entry of this.iterateEffective(indexStore, bounds)) {
|
|
423
|
+
// A legacy index store (written before index values carried the data key)
|
|
424
|
+
// holds EMPTY values. `scanIndex` may skip such an entry — a read that
|
|
425
|
+
// returns too few rows. Skipping here would instead ACCEPT a duplicate, so
|
|
426
|
+
// abandon the index and let the caller full-scan. See the NOTE in
|
|
427
|
+
// `scanIndex` for the durable fix.
|
|
428
|
+
if (entry.value.length === 0)
|
|
429
|
+
return INDEX_UNUSABLE;
|
|
430
|
+
// Resolve to the LIVE row: a pending index delete normally suppresses the
|
|
431
|
+
// entry, but a committed entry can lag a row deleted this transaction.
|
|
432
|
+
const candidate = await this.readEffectiveRowByKey(entry.value);
|
|
433
|
+
if (!candidate)
|
|
434
|
+
continue;
|
|
435
|
+
const pk = this.extractPK(candidate);
|
|
436
|
+
if (selfPks.some(skip => this.keysEqual(pk, skip)))
|
|
437
|
+
continue;
|
|
438
|
+
if (uc.columns.some((c, i) => compares[i](newRow[c], candidate[c]) !== 0))
|
|
439
|
+
continue;
|
|
440
|
+
if (predicate && predicate.evaluate(candidate) !== true)
|
|
441
|
+
continue;
|
|
442
|
+
return { pk, row: candidate };
|
|
443
|
+
}
|
|
444
|
+
return null;
|
|
445
|
+
}
|
|
446
|
+
/**
|
|
447
|
+
* Scan committed + pending data rows for a row matching `newRow` on
|
|
448
|
+
* `uc.columns` whose PK is not in `selfPks`. For partial UNIQUE, candidates
|
|
449
|
+
* whose row does not satisfy the predicate are skipped. Returns the first
|
|
450
|
+
* match or null.
|
|
451
|
+
*/
|
|
452
|
+
async findUniqueConflict(uc, predicate, newRow, selfPks) {
|
|
453
|
+
const store = await this.ensureStore();
|
|
454
|
+
// Pending ops for THIS table's data store handle — the same handle the
|
|
455
|
+
// write path queues data ops under, so the merge sees only this table's
|
|
456
|
+
// pending state, never a sibling table's on the shared module coordinator.
|
|
457
|
+
const pending = this.coordinator?.isInTransaction()
|
|
458
|
+
? this.coordinator.getPendingOpsForStore(store)
|
|
459
|
+
: null;
|
|
460
|
+
const constrainedCols = uc.columns;
|
|
461
|
+
// One comparison collation per constrained column — the index's per-column
|
|
462
|
+
// COLLATE for an index-derived UNIQUE, else the declared column collation.
|
|
463
|
+
// Resolved once here, not per candidate row.
|
|
464
|
+
const collations = resolveUniqueEnforcementCollations(this.tableSchema, uc, this.collationResolver);
|
|
465
|
+
const compares = this.uniqueColumnComparators(uc, collations);
|
|
466
|
+
const matches = (candidate) => {
|
|
467
|
+
const pk = this.extractPK(candidate);
|
|
468
|
+
for (const skip of selfPks) {
|
|
469
|
+
if (this.keysEqual(pk, skip))
|
|
470
|
+
return null;
|
|
471
|
+
}
|
|
472
|
+
for (let i = 0; i < constrainedCols.length; i++) {
|
|
473
|
+
const idx = constrainedCols[i];
|
|
474
|
+
if (compares[i](newRow[idx], candidate[idx]) !== 0)
|
|
475
|
+
return null;
|
|
476
|
+
}
|
|
477
|
+
// Partial UNIQUE: candidate must also be in the predicate's scope to conflict.
|
|
478
|
+
if (predicate && predicate.evaluate(candidate) !== true)
|
|
479
|
+
return null;
|
|
480
|
+
return { pk, row: candidate };
|
|
481
|
+
};
|
|
482
|
+
const seen = new Set();
|
|
483
|
+
const bounds = buildFullScanBounds();
|
|
484
|
+
for await (const entry of store.iterate(bounds)) {
|
|
485
|
+
const hex = bytesToHex(entry.key);
|
|
486
|
+
seen.add(hex);
|
|
487
|
+
if (pending?.deletes.has(hex))
|
|
488
|
+
continue;
|
|
489
|
+
const overlay = pending?.puts.get(hex);
|
|
490
|
+
const value = overlay ? overlay.value : entry.value;
|
|
491
|
+
const found = matches(deserializeRow(value));
|
|
492
|
+
if (found)
|
|
493
|
+
return found;
|
|
494
|
+
}
|
|
495
|
+
if (pending) {
|
|
496
|
+
for (const [hex, op] of pending.puts) {
|
|
497
|
+
if (seen.has(hex))
|
|
498
|
+
continue;
|
|
499
|
+
const found = matches(deserializeRow(op.value));
|
|
500
|
+
if (found)
|
|
501
|
+
return found;
|
|
502
|
+
}
|
|
503
|
+
}
|
|
504
|
+
return null;
|
|
505
|
+
}
|
|
506
|
+
/**
|
|
507
|
+
* Find a UNIQUE conflict through a linked row-time covering MV's backing table
|
|
508
|
+
* (the store analogue of the memory `checkUniqueViaMaterializedView`). The
|
|
509
|
+
* backing scan yields candidate conflicting **source** PKs (reads-own-writes via
|
|
510
|
+
* the backing's coordinated connection); each is validated against the *live*
|
|
511
|
+
* store row (committed + this transaction's pending overlay) so a backing entry
|
|
512
|
+
* that lags a row deleted/updated internally this statement is skipped rather
|
|
513
|
+
* than raised as a false conflict. Returns the first real conflict or null.
|
|
514
|
+
*/
|
|
515
|
+
async findUniqueConflictViaCoveringMv(mv, uc, predicate, newRow, selfPks) {
|
|
516
|
+
const newSourcePk = this.extractPK(newRow);
|
|
517
|
+
// Resolved once, above the candidate loop.
|
|
518
|
+
const collations = resolveUniqueEnforcementCollations(this.tableSchema, uc, this.collationResolver);
|
|
519
|
+
const compares = this.uniqueColumnComparators(uc, collations);
|
|
520
|
+
const candidates = await this.db._lookupCoveringConflicts(mv, uc, newRow, newSourcePk);
|
|
521
|
+
for (const cand of candidates) {
|
|
522
|
+
const liveRow = await this.readLiveRowByPk(cand.pk);
|
|
523
|
+
if (!liveRow)
|
|
524
|
+
continue; // stale backing candidate (source row gone)
|
|
525
|
+
if (selfPks.some(pk => this.keysEqual(pk, cand.pk)))
|
|
526
|
+
continue;
|
|
527
|
+
// Re-validate under each column's enforcement collation (the index's
|
|
528
|
+
// per-column COLLATE for an index-derived UNIQUE, else declared) — see
|
|
529
|
+
// uniqueEnforcementCollations. The candidate generation
|
|
530
|
+
// (_lookupCoveringConflicts) narrows under the SOURCE column's declared
|
|
531
|
+
// collation, so for a FINER index (BINARY over a NOCASE column) it returns a
|
|
532
|
+
// superset this filters down correctly. A finer/incomparable index-derived
|
|
533
|
+
// UNIQUE whose declared candidate set could be a SUBSET (e.g. a coarser NOCASE
|
|
534
|
+
// index over a BINARY column) is declined upstream by the collation gate in
|
|
535
|
+
// findRowTimeCoveringStructure, so only BINARY-floor or equal-collation MVs
|
|
536
|
+
// reach here — the superset this re-validation can soundly filter.
|
|
537
|
+
if (uc.columns.some((c, i) => compares[i](newRow[c], liveRow[c]) !== 0))
|
|
538
|
+
continue;
|
|
539
|
+
if (predicate && predicate.evaluate(liveRow) !== true)
|
|
540
|
+
continue;
|
|
541
|
+
return { pk: cand.pk, row: liveRow };
|
|
542
|
+
}
|
|
543
|
+
return null;
|
|
544
|
+
}
|
|
545
|
+
/**
|
|
546
|
+
* Declared secondary-UNIQUE enforcement for maintenance writes — the store
|
|
547
|
+
* mirror of the memory manager's `enforceSecondaryUniqueOnMaintenance` (see
|
|
548
|
+
* `vtab/backing-host.ts` § Constraint validation for the contract and
|
|
549
|
+
* docs/mv-constraints.md § Derived-row constraint validation for the
|
|
550
|
+
* semantics). Called by `StoreBackingHost.applyMaintenance` AFTER the op
|
|
551
|
+
* batch lands in the coordinator's pending state: post-batch is load-bearing
|
|
552
|
+
* (a `replace-all` diff applies puts before deletes, so a per-op check would
|
|
553
|
+
* false-positive when the derived set moves a unique value between primary
|
|
554
|
+
* keys), and checking only the WRITTEN images is complete (pre-existing
|
|
555
|
+
* contents already satisfied the constraint).
|
|
556
|
+
*
|
|
557
|
+
* Reuses {@link findUniqueConflict} — pending-overlay reads, per-column
|
|
558
|
+
* collations, NULL-pass, partial-predicate scope, self-PK exclusion — with
|
|
559
|
+
* the covering-MV route deliberately bypassed: a covering MV over THIS table
|
|
560
|
+
* is cascade-maintained only after the batch returns, so it lags the batch
|
|
561
|
+
* and would miss a same-batch colliding pair. The conflict action is a hard
|
|
562
|
+
* abort (a derivation write carries no user OR clause, and a declared
|
|
563
|
+
* `on conflict replace`/`ignore` default must not evict or drop derived
|
|
564
|
+
* rows). Per-image cost is one effective full scan: unlike the DML path
|
|
565
|
+
* ({@link findUniqueConflictFor}), this one is NOT routed through
|
|
566
|
+
* {@link findUniqueConflictViaIndex}, because a backing table keeps no
|
|
567
|
+
* secondary indexes by design — there is never an index store to seek.
|
|
568
|
+
*
|
|
569
|
+
* Zero overhead when the table declares no secondary UNIQUE (every MV-sugar
|
|
570
|
+
* backing, and most maintained tables): one empty-array check.
|
|
571
|
+
*/
|
|
572
|
+
async enforceSecondaryUniqueForMaintenance(changes) {
|
|
573
|
+
const schema = this.tableSchema;
|
|
574
|
+
const ucs = schema?.uniqueConstraints;
|
|
575
|
+
if (!schema || !ucs || ucs.length === 0 || changes.length === 0)
|
|
576
|
+
return;
|
|
577
|
+
for (const change of changes) {
|
|
578
|
+
if (change.op === 'delete')
|
|
579
|
+
continue;
|
|
580
|
+
const newRow = change.newRow;
|
|
581
|
+
const selfPks = [this.extractPK(newRow)];
|
|
582
|
+
for (const uc of ucs) {
|
|
583
|
+
// SQL semantics: UNIQUE allows multiple NULLs.
|
|
584
|
+
if (uc.columns.some(idx => newRow[idx] === null))
|
|
585
|
+
continue;
|
|
586
|
+
// Partial UNIQUE: an out-of-scope image contributes nothing.
|
|
587
|
+
const predicate = this.compileFor(uc);
|
|
588
|
+
if (predicate && predicate.evaluate(newRow) !== true)
|
|
589
|
+
continue;
|
|
590
|
+
const conflict = await this.findUniqueConflict(uc, predicate, newRow, selfPks);
|
|
591
|
+
if (conflict) {
|
|
592
|
+
const colNames = uc.columns.map(i => schema.columns[i]?.name ?? String(i));
|
|
593
|
+
throw maintainedTableUniqueViolationError(schema.schemaName, schema.name, uc.name ?? `_uc_${colNames.join('_')}`, colNames, uc.columns.map(i => newRow[i]));
|
|
594
|
+
}
|
|
595
|
+
}
|
|
596
|
+
}
|
|
597
|
+
}
|
|
598
|
+
/**
|
|
599
|
+
* Fully delete the row at `pk` (data + secondary indexes + stats + delete event).
|
|
600
|
+
* Used by REPLACE conflict resolution to evict a conflicting unique row before
|
|
601
|
+
* the caller's insert/update proceeds.
|
|
602
|
+
*/
|
|
603
|
+
async deleteRowAt(inTransaction, pk, oldRow) {
|
|
604
|
+
const store = await this.ensureStore();
|
|
605
|
+
const key = this.encodeDataKey(pk);
|
|
606
|
+
if (inTransaction && this.coordinator) {
|
|
607
|
+
this.coordinator.delete(key, store);
|
|
608
|
+
}
|
|
609
|
+
else {
|
|
610
|
+
await store.delete(key);
|
|
611
|
+
}
|
|
612
|
+
await this.updateSecondaryIndexes(inTransaction, oldRow, null, pk);
|
|
613
|
+
this.trackMutation(-1, inTransaction);
|
|
614
|
+
const schema = this.tableSchema;
|
|
615
|
+
this.emitOrQueueDataChange(inTransaction, {
|
|
616
|
+
type: 'delete',
|
|
617
|
+
schemaName: schema.schemaName,
|
|
618
|
+
tableName: schema.name,
|
|
619
|
+
key: pk,
|
|
620
|
+
oldRow,
|
|
621
|
+
});
|
|
622
|
+
}
|
|
623
|
+
}
|
|
624
|
+
//# sourceMappingURL=store-table-constraints.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"store-table-constraints.js","sourceRoot":"","sources":["../../../src/common/store-table-constraints.ts"],"names":[],"mappings":"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"}
|