@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,373 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CREATE INDEX / DROP INDEX over a store-backed table, and the physical index stores
|
|
3
|
+
* they bring into (and out of) existence — including the hidden `_uc_*` stores that
|
|
4
|
+
* back a plain UNIQUE constraint, whose set is reconciled against the schema after
|
|
5
|
+
* every DDL that can change it.
|
|
6
|
+
*
|
|
7
|
+
* Fourth layer of the store-module chain:
|
|
8
|
+
* StoreModuleBase -> StoreModuleCatalog -> StoreModuleSchemaSync -> StoreModuleIndex
|
|
9
|
+
* -> StoreModuleAlterColumn -> StoreModuleAlter -> StoreModuleRename -> StoreModule
|
|
10
|
+
*/
|
|
11
|
+
import { QuereusError, StatusCode, appendIndexToTableSchema, generateDropIndexDDL, generateIndexDDL, } from '@quereus/quereus';
|
|
12
|
+
import { findReusableIndexForUnique, implicitUniqueIndexName } from './implicit-unique-index.js';
|
|
13
|
+
import { buildFullScanBounds, buildIndexStoreName } from './key-builder.js';
|
|
14
|
+
import { StoreModuleSchemaSync } from './store-module-schema-sync.js';
|
|
15
|
+
import { DEFAULT_MAX_BATCH_BYTES } from './store-module-base.js';
|
|
16
|
+
import { buildIndexEntries, validateUniqueIndexOverRows } from './store-module-index-build.js';
|
|
17
|
+
/**
|
|
18
|
+
* Map of `lowercased implicit index name → actual name` for every NON-DERIVED
|
|
19
|
+
* UNIQUE constraint of `schema` that needs a `_uc_*` of its own — the set of
|
|
20
|
+
* `_uc_*` stores that SHOULD exist for that schema. The diff of two such maps
|
|
21
|
+
* drives {@link reconcileImplicitUniqueIndexStores}.
|
|
22
|
+
*
|
|
23
|
+
* Reads `uniqueConstraints` for the NAMES (so it is correct whether or not
|
|
24
|
+
* `schema` is materialized) and `.indexes` for the REUSE decision, exactly as
|
|
25
|
+
* `withImplicitUniqueIndexes` does — the two must agree, or the reconcile would
|
|
26
|
+
* build a store no DML maintains, or tear down one that is still being seeked.
|
|
27
|
+
* A UC realized by an explicit index (`findReusableIndexForUnique`) contributes
|
|
28
|
+
* no entry, which is what makes `create index` / `drop index` over a constrained
|
|
29
|
+
* column a teardown / rebuild transition rather than a no-op.
|
|
30
|
+
*/
|
|
31
|
+
function implicitUniqueIndexNameMap(schema) {
|
|
32
|
+
const map = new Map();
|
|
33
|
+
for (const uc of schema.uniqueConstraints ?? []) {
|
|
34
|
+
if (uc.derivedFromIndex)
|
|
35
|
+
continue;
|
|
36
|
+
if (findReusableIndexForUnique(schema, uc))
|
|
37
|
+
continue;
|
|
38
|
+
const name = implicitUniqueIndexName(schema, uc);
|
|
39
|
+
map.set(name.toLowerCase(), name);
|
|
40
|
+
}
|
|
41
|
+
return map;
|
|
42
|
+
}
|
|
43
|
+
export class StoreModuleIndex extends StoreModuleSchemaSync {
|
|
44
|
+
/**
|
|
45
|
+
* Creates an index on a store-backed table.
|
|
46
|
+
*
|
|
47
|
+
* `rows` — an {@link EffectiveRowSource} supplied by a wrapper module (the isolation
|
|
48
|
+
* layer) — replaces this module's own rows as the set the UNIQUE duplicate check judges.
|
|
49
|
+
* When present the check runs UP FRONT, before `getIndexStore` opens the index-store
|
|
50
|
+
* directory, so a rejection leaves no directory behind; and `buildIndexEntries` then
|
|
51
|
+
* populates the physical index from this module's own (committed) rows with its in-pass
|
|
52
|
+
* dup check disabled. Those two row sets legitimately differ — the wrapper's transaction
|
|
53
|
+
* may have deleted a committed duplicate — and an index entry with no live row behind it
|
|
54
|
+
* is harmless (see the entry-resolution note in `buildIndexEntries`).
|
|
55
|
+
*/
|
|
56
|
+
async createIndex(db, schemaName, tableName, indexSchema, rows) {
|
|
57
|
+
const table = this.getOrReconnectTable(db, schemaName, tableName);
|
|
58
|
+
if (!table) {
|
|
59
|
+
throw new QuereusError(`Store table '${tableName}' not found in schema '${schemaName}'`, StatusCode.NOTFOUND);
|
|
60
|
+
}
|
|
61
|
+
// Reject when this new index's physical store name already names an existing
|
|
62
|
+
// store: a sibling table's data store (`{schema}.t_idx_<x>` == sibling table
|
|
63
|
+
// `t_idx_<x>`) or another table's index store (index-vs-index, e.g.
|
|
64
|
+
// `a.b_idx_c` vs `a_idx_b.c` both → `{schema}.a_idx_b_idx_c`). The new index
|
|
65
|
+
// is not yet registered in the schema or the table's cached schema at this
|
|
66
|
+
// point, so the candidate cannot self-collide. Must precede `getIndexStore`,
|
|
67
|
+
// which opens/creates the directory that `buildIndexEntries` then writes into.
|
|
68
|
+
const indexStoreName = buildIndexStoreName(schemaName, tableName, indexSchema.name);
|
|
69
|
+
this.assertStoreNameFree(db, schemaName, indexStoreName, `index store of new index '${indexSchema.name}' on table '${schemaName}.${tableName}'`);
|
|
70
|
+
const tableSchema = table.getSchema();
|
|
71
|
+
const keyCollation = (table.getConfig().collation || 'NOCASE').toUpperCase();
|
|
72
|
+
// Reject an index whose key collations cannot key (comparator-only or
|
|
73
|
+
// unregistered names) BEFORE the physical store is created — the same DDL-time
|
|
74
|
+
// check `StoreTableBase.validateKeyCollations` applies to every index at
|
|
75
|
+
// CREATE TABLE / rehydrate, run here up front so a rejection leaves no
|
|
76
|
+
// index-store directory behind (the post-build `updateSchema` would only catch
|
|
77
|
+
// it after the store exists).
|
|
78
|
+
table.assertIndexKeyCollationsCanKey(indexSchema);
|
|
79
|
+
// Wrapper-supplied rows are the judged set. Validate BEFORE `getIndexStore` so a
|
|
80
|
+
// rejection leaves no index-store directory behind, and disable the in-pass dup
|
|
81
|
+
// check below (which would judge this module's committed rows instead).
|
|
82
|
+
if (rows && indexSchema.unique) {
|
|
83
|
+
await validateUniqueIndexOverRows(rows(), tableSchema, indexSchema, db.getKeyNormalizerResolver());
|
|
84
|
+
}
|
|
85
|
+
// Create the index store
|
|
86
|
+
const indexStore = await this.provider.getIndexStore(schemaName, tableName, indexSchema.name);
|
|
87
|
+
// Build index entries for every row the table can currently SEE — committed
|
|
88
|
+
// rows merged with this transaction's pending writes (`iterateEffectiveEntries`).
|
|
89
|
+
// The committed-only stream would leave a row inserted earlier in an open
|
|
90
|
+
// transaction unindexed, and `StoreTable.findUniqueConflictViaIndex` trusts the
|
|
91
|
+
// index to hold every live row: a `CREATE UNIQUE INDEX` would miss a pending
|
|
92
|
+
// duplicate, and a later insert colliding with that pending row would be
|
|
93
|
+
// silently ACCEPTED. Entries written here for rows that a subsequent ROLLBACK
|
|
94
|
+
// discards are harmless: both readers resolve each entry to its live row and
|
|
95
|
+
// drop it when the row is gone or no longer matches (see `scanIndex`).
|
|
96
|
+
//
|
|
97
|
+
// The store is FRESHLY created above, so any build failure — a UNIQUE violation,
|
|
98
|
+
// an IO error, or a mid-stream flush failure now that the build is chunked — must
|
|
99
|
+
// tear the whole store down. Nothing else reclaims it: SchemaManager.createIndex
|
|
100
|
+
// wraps the error but does no teardown, so without this a rejected build leaks a
|
|
101
|
+
// partial/empty index-store directory. Mirrors dropIndex's teardown.
|
|
102
|
+
try {
|
|
103
|
+
await buildIndexEntries(table.iterateEffectiveEntries(buildFullScanBounds()), indexStore, tableSchema, indexSchema, keyCollation, db.getKeyNormalizerResolver(), rows !== undefined, table.getConfig().maxBatchBytes ?? DEFAULT_MAX_BATCH_BYTES);
|
|
104
|
+
}
|
|
105
|
+
catch (buildError) {
|
|
106
|
+
// Best-effort teardown: guard it against its own throw so a teardown failure
|
|
107
|
+
// never masks the original build error the caller must see.
|
|
108
|
+
try {
|
|
109
|
+
await this.tearDownIndexStore(schemaName, tableName, table, indexSchema.name);
|
|
110
|
+
}
|
|
111
|
+
catch (teardownError) {
|
|
112
|
+
console.warn(`[StoreModule] failed to tear down index store '${indexSchema.name}' on `
|
|
113
|
+
+ `table '${schemaName}.${tableName}' after a failed CREATE INDEX: ${String(teardownError)}`);
|
|
114
|
+
}
|
|
115
|
+
throw buildError;
|
|
116
|
+
}
|
|
117
|
+
// Refresh the connected table's cached schema so subsequent DML
|
|
118
|
+
// maintains the new index (the engine's schema registry is updated
|
|
119
|
+
// separately by SchemaManager.createIndex, but the StoreTable instance
|
|
120
|
+
// holds its own reference captured at connect time). The shared
|
|
121
|
+
// appendIndexToTableSchema also synthesizes the UNIQUE → derived
|
|
122
|
+
// uniqueConstraint entry so checkUniqueConstraints enforces it; the
|
|
123
|
+
// `derivedFromIndex` tag lets StoreModule.dropIndex filter it back out
|
|
124
|
+
// symmetrically (mirrors SchemaManager.dropIndex / MemoryTableManager.dropIndex).
|
|
125
|
+
const updatedSchema = appendIndexToTableSchema(tableSchema, indexSchema);
|
|
126
|
+
table.updateSchema(updatedSchema);
|
|
127
|
+
// Authoritative catalog write: persist the table's bundle now (including the
|
|
128
|
+
// new index), so the index survives close → reopen even when the table has
|
|
129
|
+
// no rows yet and was never lazily persisted. `markDdlSaved` suppresses the
|
|
130
|
+
// later lazy table-only write on first store access (StoreTable.ddlSaved), so
|
|
131
|
+
// this is the only catalog write the createIndex produces. SchemaManager fires
|
|
132
|
+
// a follow-up `table_modified` whose listener regenerates the SAME bundle and
|
|
133
|
+
// skips (identical) — see persistCatalogIfChanged.
|
|
134
|
+
await this.saveTableDDL(updatedSchema);
|
|
135
|
+
table.markDdlSaved();
|
|
136
|
+
// The new index may now REALIZE a plain UNIQUE over the same columns, which
|
|
137
|
+
// `updateSchema` above has already dropped from the materialized enforcement
|
|
138
|
+
// schema (`findReusableIndexForUnique`). Nothing maintains that `_uc_*` any more,
|
|
139
|
+
// so tear its physical store down — leaving it would rot into a store whose
|
|
140
|
+
// entries no longer track the rows, which a later `DROP INDEX` would hand back to
|
|
141
|
+
// the constraint as if current. A no-op for every index that covers no UNIQUE —
|
|
142
|
+
// which is what keeps the DDL-commit the teardown forces (see
|
|
143
|
+
// {@link reconcileImplicitUniqueIndexStores}) off every ordinary CREATE INDEX.
|
|
144
|
+
await this.reconcileImplicitUniqueIndexStores(db, schemaName, tableName, table, tableSchema);
|
|
145
|
+
// Emit schema change event. `updatedSchema` (not the pre-create
|
|
146
|
+
// `tableSchema`) is the owner the canonical CREATE INDEX renders against —
|
|
147
|
+
// it is only read for the table's qualified name and column names, but
|
|
148
|
+
// passing the post-create schema keeps the rendering consistent with what a
|
|
149
|
+
// receiving peer regenerates when it compares definitions.
|
|
150
|
+
this.eventEmitter?.emitSchemaChange({
|
|
151
|
+
type: 'create',
|
|
152
|
+
objectType: 'index',
|
|
153
|
+
schemaName,
|
|
154
|
+
objectName: indexSchema.name,
|
|
155
|
+
ddl: generateIndexDDL(indexSchema, updatedSchema),
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* Drops an index on a store-backed table.
|
|
160
|
+
*
|
|
161
|
+
* Mirrors createIndex: refreshes the connected StoreTable's cached
|
|
162
|
+
* tableSchema (removing the index entry and any UNIQUE constraint
|
|
163
|
+
* synthesized from it, tagged with `derivedFromIndex`), releases the
|
|
164
|
+
* cached index-store handle, and tears down the underlying index store.
|
|
165
|
+
*/
|
|
166
|
+
async dropIndex(db, schemaName, tableName, indexName) {
|
|
167
|
+
const table = this.getOrReconnectTable(db, schemaName, tableName);
|
|
168
|
+
if (!table) {
|
|
169
|
+
throw new QuereusError(`Store table '${tableName}' not found in schema '${schemaName}'`, StatusCode.NOTFOUND);
|
|
170
|
+
}
|
|
171
|
+
const tableSchema = table.getSchema();
|
|
172
|
+
const lowerIndexName = indexName.toLowerCase();
|
|
173
|
+
// Mirror SchemaManager.dropIndex: strip the index AND any UNIQUE
|
|
174
|
+
// constraint synthesized from it (tagged with `derivedFromIndex` by
|
|
175
|
+
// StoreModule.createIndex). Collapse uniqueConstraints to undefined
|
|
176
|
+
// when empty.
|
|
177
|
+
const updatedIndexes = Object.freeze((tableSchema.indexes ?? []).filter(idx => idx.name.toLowerCase() !== lowerIndexName));
|
|
178
|
+
const remainingUniqueConstraints = (tableSchema.uniqueConstraints ?? []).filter(uc => uc.derivedFromIndex?.toLowerCase() !== lowerIndexName);
|
|
179
|
+
const updatedSchema = {
|
|
180
|
+
...tableSchema,
|
|
181
|
+
indexes: updatedIndexes,
|
|
182
|
+
uniqueConstraints: remainingUniqueConstraints.length > 0
|
|
183
|
+
? Object.freeze(remainingUniqueConstraints)
|
|
184
|
+
: undefined,
|
|
185
|
+
};
|
|
186
|
+
// Update the cached schema BEFORE tearing down the store so that a
|
|
187
|
+
// failure of the physical drop doesn't leave the schema enforcing an
|
|
188
|
+
// index whose backing store has already been mutated.
|
|
189
|
+
table.updateSchema(updatedSchema);
|
|
190
|
+
// Rewrite the catalog bundle without the dropped index, before the physical
|
|
191
|
+
// teardown — so on reopen the index does not resurrect even if the store
|
|
192
|
+
// delete below fails. `markDdlSaved` keeps the lazy first-access save from
|
|
193
|
+
// re-writing the same bundle. SchemaManager's follow-up `table_modified`
|
|
194
|
+
// regenerates an identical bundle and skips.
|
|
195
|
+
await this.saveTableDDL(updatedSchema);
|
|
196
|
+
table.markDdlSaved();
|
|
197
|
+
// Drop the cached handle on the table side and tear down the underlying KVStore
|
|
198
|
+
// ({@link tearDownIndexStore}).
|
|
199
|
+
//
|
|
200
|
+
// Flush first: the coordinator keys buffered ops on the KVStore HANDLE, so ops
|
|
201
|
+
// this transaction queued against the index being dropped would be replayed into
|
|
202
|
+
// a closed store at commit and throw. Same posture (and same reason) as the
|
|
203
|
+
// teardown in `reconcileImplicitUniqueIndexStores` and the row-rewriting ALTER
|
|
204
|
+
// arms — see `StoreModuleBase.ddlCommitPendingOps`.
|
|
205
|
+
await this.ddlCommitPendingOps();
|
|
206
|
+
await this.tearDownIndexStore(schemaName, tableName, table, indexName);
|
|
207
|
+
// The dropped index may have been the structure REALIZING a plain UNIQUE over its
|
|
208
|
+
// columns; `updateSchema` above has re-materialized that constraint's own `_uc_*`,
|
|
209
|
+
// which has no physical store yet. Build it from the current rows so the very next
|
|
210
|
+
// insert is still enforced by a seek rather than an empty index. Deliberately AFTER
|
|
211
|
+
// the teardown: the build reads the DATA store, so the dropped index's store is
|
|
212
|
+
// dead weight by then. A no-op for every index no UNIQUE was reusing.
|
|
213
|
+
await this.reconcileImplicitUniqueIndexStores(db, schemaName, tableName, table, tableSchema);
|
|
214
|
+
this.eventEmitter?.emitSchemaChange({
|
|
215
|
+
type: 'drop',
|
|
216
|
+
objectType: 'index',
|
|
217
|
+
schemaName,
|
|
218
|
+
objectName: indexName,
|
|
219
|
+
ddl: generateDropIndexDDL(schemaName, indexName),
|
|
220
|
+
});
|
|
221
|
+
}
|
|
222
|
+
/**
|
|
223
|
+
* Clear and rebuild every secondary index of `schema` against the (already
|
|
224
|
+
* re-encoded) data store. Secondary-index keys embed the PK suffix, so they must
|
|
225
|
+
* be rewritten whenever the data-store PK key bytes change — which happens both
|
|
226
|
+
* on `ALTER PRIMARY KEY` (the PK columns change) and on an `ALTER COLUMN … SET
|
|
227
|
+
* COLLATE` on a PK member (a PK column's key collation changes). Shared by both
|
|
228
|
+
* arms so the clear-then-rebuild stays identical. `schema` must already be the
|
|
229
|
+
* post-ALTER schema (its `primaryKeyDefinition` + column collations drive the new
|
|
230
|
+
* PK-suffix encoding via {@link buildIndexEntries}). `normalizers` is the owning
|
|
231
|
+
* connection's `db.getKeyNormalizerResolver()` — see {@link buildIndexEntries}.
|
|
232
|
+
*
|
|
233
|
+
* NOTE: reads the data store committed-only and writes the index stores outside the
|
|
234
|
+
* coordinator. Sound only because every caller calls `StoreModuleBase.ddlCommitPendingOps`
|
|
235
|
+
* first, so this module's "committed" is "everything live". A caller that skips that
|
|
236
|
+
* flush would rebuild an index missing its transaction's pending rows.
|
|
237
|
+
*
|
|
238
|
+
* `skipDuplicateCheck` suppresses {@link buildIndexEntries}' in-pass UNIQUE check.
|
|
239
|
+
* Both ALTER COLUMN rebuild callers set it — the value-rewriting / key-transform
|
|
240
|
+
* arm and the PK re-key arm (`SET COLLATE` on a PK member): each runs a
|
|
241
|
+
* pre-mutation UNIQUE re-validation that already judged the ISSUING connection's
|
|
242
|
+
* effective rows (a wrapper's overlay included), and this rebuild sees only THIS
|
|
243
|
+
* module's committed rows — a set that may retain a row the wrapper's transaction
|
|
244
|
+
* has deleted, so judging it here would spuriously reject a duplicate pair the
|
|
245
|
+
* probe correctly accepted (and, worse, reject AFTER the data store was already
|
|
246
|
+
* re-keyed). Mirrors the memory module's deliberately non-enforcing base rebuild
|
|
247
|
+
* (the probe is the only guard). `ALTER PRIMARY KEY`'s rebuild still enforces:
|
|
248
|
+
* that arm has no effective-row UNIQUE probe of its own.
|
|
249
|
+
*/
|
|
250
|
+
async rebuildSecondaryIndexes(schemaName, tableName, table, schema, normalizers, skipDuplicateCheck = false) {
|
|
251
|
+
const keyCollation = (table.getConfig().collation || 'NOCASE').toUpperCase();
|
|
252
|
+
const dataStore = await this.getStore(schemaName, tableName, table.getConfig());
|
|
253
|
+
const maxBatchBytes = table.getConfig().maxBatchBytes ?? DEFAULT_MAX_BATCH_BYTES;
|
|
254
|
+
for (const indexSchema of schema.indexes ?? []) {
|
|
255
|
+
const indexStore = await this.getIndexStore(schemaName, tableName, indexSchema.name);
|
|
256
|
+
// NOTE: this clear pass buffers EVERY existing index key into one batch. It holds
|
|
257
|
+
// only KEYS (no values), so its peak is far below the value-bearing build pass and
|
|
258
|
+
// is left unbounded for now. Chunking it is harder than the build: it deletes from
|
|
259
|
+
// the SAME store it iterates, so a mid-iteration flush risks iterate-while-mutate
|
|
260
|
+
// semantics that differ per provider (LevelDB snapshots its iterator; IndexedDB may
|
|
261
|
+
// not). If the index key set ever dominates memory, chunk this with a snapshot-safe
|
|
262
|
+
// re-seek, not a naive mid-iteration flush.
|
|
263
|
+
const clearBatch = indexStore.batch();
|
|
264
|
+
for await (const entry of indexStore.iterate(buildFullScanBounds())) {
|
|
265
|
+
clearBatch.delete(entry.key);
|
|
266
|
+
}
|
|
267
|
+
await clearBatch.write();
|
|
268
|
+
await buildIndexEntries(dataStore.iterate(buildFullScanBounds()), indexStore, schema, indexSchema, keyCollation, normalizers, skipDuplicateCheck, maxBatchBytes);
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
/**
|
|
272
|
+
* Build / tear down the physical index stores backing implicit UNIQUE indexes
|
|
273
|
+
* (`_uc_*`) after a DDL statement, by diffing the implicit-index NAMES the old vs
|
|
274
|
+
* new schema call for ({@link implicitUniqueIndexNameMap}):
|
|
275
|
+
* - a name newly PRESENT (ADD CONSTRAINT UNIQUE, the target half of a
|
|
276
|
+
* RENAME CONSTRAINT / rename of an unnamed UC's column, or a DROP INDEX that
|
|
277
|
+
* retires the explicit index a UNIQUE was reusing) has its physical store
|
|
278
|
+
* populated from this module's effective rows;
|
|
279
|
+
* - a name newly ABSENT (DROP CONSTRAINT UNIQUE, the source half of a rename, or
|
|
280
|
+
* a CREATE INDEX whose new index now realizes the UNIQUE) has its store torn
|
|
281
|
+
* down, so nothing maintains it and a later rebuild does not reopen stale
|
|
282
|
+
* entries.
|
|
283
|
+
*
|
|
284
|
+
* The SCHEMA entry itself is materialized/removed by `withImplicitUniqueIndexes`
|
|
285
|
+
* on the caller's `table.updateSchema`; only the physical store needs this. Called
|
|
286
|
+
* after every ALTER TABLE and after `createIndex` / `dropIndex`, and a no-op
|
|
287
|
+
* whenever the implicit-index name set is unchanged — the common case, including
|
|
288
|
+
* every PK / collation / data-type ALTER (whose same-name physical re-encode is
|
|
289
|
+
* already done by {@link rebuildSecondaryIndexes}) and every CREATE / DROP INDEX
|
|
290
|
+
* that does not cover a plain UNIQUE's columns.
|
|
291
|
+
*
|
|
292
|
+
* `oldSchema` is the pre-DDL schema: its `uniqueConstraints` give the old names and
|
|
293
|
+
* its `.indexes` the old reuse decisions. Either the engine-facing or the
|
|
294
|
+
* materialized copy works — `findReusableIndexForUnique` skips a constraint's own
|
|
295
|
+
* `_uc_*`, so a materialized input yields the same name set.
|
|
296
|
+
*
|
|
297
|
+
* NOTE: the build populates from THIS module's own effective rows (committed + this
|
|
298
|
+
* transaction's pending), never a wrapper's — mirroring `createIndex`. Under the
|
|
299
|
+
* isolation layer the wrapper's rows are what ADD CONSTRAINT's validation judged;
|
|
300
|
+
* the physical index legitimately fills from this module's committed rows and an
|
|
301
|
+
* entry with no live row behind it is harmless (both readers resolve to the live
|
|
302
|
+
* row). Duplicates were already rejected by `validateUniqueOverExistingRows` (ADD)
|
|
303
|
+
* or cannot exist (RENAME leaves data unchanged), so the in-pass check is skipped.
|
|
304
|
+
*/
|
|
305
|
+
async reconcileImplicitUniqueIndexStores(db, schemaName, tableName, table, oldSchema) {
|
|
306
|
+
// Diff the constraint sets by implicit-index NAME (derived from `uniqueConstraints`,
|
|
307
|
+
// so the engine-facing schemas work directly); resolve the index SHAPE to build from
|
|
308
|
+
// the materialized enforcement schema.
|
|
309
|
+
const newSchema = table.getSchema();
|
|
310
|
+
const newMaterialized = table.getMaterializedSchema();
|
|
311
|
+
const oldNames = implicitUniqueIndexNameMap(oldSchema);
|
|
312
|
+
const newNames = implicitUniqueIndexNameMap(newSchema);
|
|
313
|
+
// Tear down each store whose implicit index no longer exists. A teardown closes
|
|
314
|
+
// and deletes a KVStore handle the module coordinator may still hold buffered ops
|
|
315
|
+
// against (pending ops are keyed on the HANDLE), and the eventual commit would
|
|
316
|
+
// write into the closed store and throw — so flush first, the same DDL-commit
|
|
317
|
+
// posture the row-rewriting ALTER arms take and what this module's declared
|
|
318
|
+
// `ddlTransactionality: 'auto-commit'` promises. Only when something is actually
|
|
319
|
+
// doomed: a pure BUILD writes index entries outside the coordinator and deletes
|
|
320
|
+
// nothing, so it must not force-commit the caller's transaction.
|
|
321
|
+
const doomed = [...oldNames].filter(([lower]) => !newNames.has(lower));
|
|
322
|
+
if (doomed.length > 0) {
|
|
323
|
+
await this.ddlCommitPendingOps();
|
|
324
|
+
for (const [, name] of doomed) {
|
|
325
|
+
await this.tearDownIndexStore(schemaName, tableName, table, name);
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
// Build each newly-materialized implicit index's store from effective rows.
|
|
329
|
+
for (const [lower, name] of newNames) {
|
|
330
|
+
if (oldNames.has(lower))
|
|
331
|
+
continue;
|
|
332
|
+
const indexSchema = (newMaterialized.indexes ?? []).find(ix => ix.name === name);
|
|
333
|
+
if (!indexSchema)
|
|
334
|
+
continue; // defensive — name is derived from the same UC set
|
|
335
|
+
// NOTE: no `assertStoreNameFree` here (unlike explicit `createIndex`): the name
|
|
336
|
+
// is engine-derived and deterministic, and the lazy first-write build path in
|
|
337
|
+
// `updateSecondaryIndexes` does not assert either — keep the two consistent.
|
|
338
|
+
// NOTE: no teardown-on-failure wrapper (unlike `createIndex`): an IO error mid-build
|
|
339
|
+
// leaves a partial `_uc_*` store while the constraint schema is already committed, so
|
|
340
|
+
// enforcement could under-report until the store is rebuilt. Tolerated because the
|
|
341
|
+
// build has no in-pass dup check (skipDuplicateCheck below) so the only failure is a
|
|
342
|
+
// genuine IO error — the same non-atomicity `rebuildSecondaryIndexes` documents; a
|
|
343
|
+
// re-run / reopen rebuilds. Add a try/catch teardown if this ever bites.
|
|
344
|
+
const keyCollation = (table.getConfig().collation || 'NOCASE').toUpperCase();
|
|
345
|
+
const indexStore = await this.provider.getIndexStore(schemaName, tableName, name);
|
|
346
|
+
await buildIndexEntries(table.iterateEffectiveEntries(buildFullScanBounds()), indexStore, newSchema, indexSchema, keyCollation, db.getKeyNormalizerResolver(), true, // dup rejection already owned by the arm (ADD validates; RENAME is data-preserving)
|
|
347
|
+
table.getConfig().maxBatchBytes ?? DEFAULT_MAX_BATCH_BYTES);
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
/**
|
|
351
|
+
* Close + delete one index's physical store: release the table's cached handle, then
|
|
352
|
+
* `deleteIndexStore` when the provider implements it (it closes the handle before
|
|
353
|
+
* removing the directory), else just `closeIndexStore`.
|
|
354
|
+
*
|
|
355
|
+
* The single teardown every path shares — `dropIndex`, `createIndex`'s build-failure
|
|
356
|
+
* rollback, the implicit `_uc_*` reconcile above, and `DROP COLUMN`'s removed-index
|
|
357
|
+
* pass (`StoreModuleAlter.alterDropColumn`). Each caller owns the surrounding
|
|
358
|
+
* posture, which deliberately differs: the DDL-commit flush (buffered ops are keyed
|
|
359
|
+
* on the KVStore HANDLE, so a doomed store's queued ops would replay into a closed
|
|
360
|
+
* store at commit — see `StoreModuleBase.ddlCommitPendingOps`) and, for
|
|
361
|
+
* `createIndex`, swallowing a teardown throw so it cannot mask the build error.
|
|
362
|
+
*/
|
|
363
|
+
async tearDownIndexStore(schemaName, tableName, table, indexName) {
|
|
364
|
+
await table.releaseIndexStore(indexName);
|
|
365
|
+
if (this.provider.deleteIndexStore) {
|
|
366
|
+
await this.provider.deleteIndexStore(schemaName, tableName, indexName);
|
|
367
|
+
}
|
|
368
|
+
else {
|
|
369
|
+
await this.provider.closeIndexStore(schemaName, tableName, indexName);
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
//# sourceMappingURL=store-module-index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"store-module-index.js","sourceRoot":"","sources":["../../../src/common/store-module-index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ALTER TABLE ... RENAME TO: the two-phase table rename. The first phase relocates the
|
|
3
|
+
* physical data / index / stats stores and writes the new catalog entry while leaving
|
|
4
|
+
* the old entry in place; the second, called by the engine once every dependent object
|
|
5
|
+
* has been rewritten, drains those dependent catalog writes and only then drops it.
|
|
6
|
+
*
|
|
7
|
+
* Seventh layer of the store-module chain:
|
|
8
|
+
* StoreModuleBase -> StoreModuleCatalog -> StoreModuleSchemaSync -> StoreModuleIndex
|
|
9
|
+
* -> StoreModuleAlterColumn -> StoreModuleAlter -> StoreModuleRename -> StoreModule
|
|
10
|
+
*/
|
|
11
|
+
import type { Database } from '@quereus/quereus';
|
|
12
|
+
import { StoreModuleAlter } from './store-module-alter.js';
|
|
13
|
+
export declare abstract class StoreModuleRename extends StoreModuleAlter {
|
|
14
|
+
/**
|
|
15
|
+
* Rename a store-backed table.
|
|
16
|
+
*
|
|
17
|
+
* Drops every in-memory reference to the old name (so the coordinator, open
|
|
18
|
+
* handles, and cached StoreTable instance don't linger with stale paths),
|
|
19
|
+
* delegates physical storage relocation to the provider, then rewrites the
|
|
20
|
+
* persistent catalog DDL under the new key. After this returns, the next
|
|
21
|
+
* access to `newName` will reconnect via `connect()` and open fresh stores
|
|
22
|
+
* against the moved directories.
|
|
23
|
+
*/
|
|
24
|
+
renameTable(db: Database, schemaName: string, oldName: string, newName: string, ddl?: string): Promise<void>;
|
|
25
|
+
/**
|
|
26
|
+
* Second phase of a two-phase RENAME TABLE (see {@link renameTable}). The engine calls
|
|
27
|
+
* this at the END of ALTER TABLE ... RENAME TO — AFTER its `propagateTableRename` has
|
|
28
|
+
* rewritten every dependent object that named `oldName` and enqueued their corrective
|
|
29
|
+
* catalog writes onto `StoreModuleBase.persistQueue`. `renameTable` deliberately left `oldName`'s
|
|
30
|
+
* catalog entry in place; here we drain those dependent writes to durability and only
|
|
31
|
+
* THEN drop the old entry. During the window both entries coexist on disk, so every
|
|
32
|
+
* dependent resolves against one of them and every intermediate catalog set rehydrates
|
|
33
|
+
* into a working database.
|
|
34
|
+
*
|
|
35
|
+
* The old-entry delete rides `persistQueue` behind the dependents' already-enqueued
|
|
36
|
+
* writes (FIFO), so it can only run after them, and the drain below awaits the whole
|
|
37
|
+
* chain. Errors are swallowed+logged (the `StoreModuleBase.enqueuePersist` contract): a failed
|
|
38
|
+
* delete leaves the old entry present — a visible, droppable orphan, strictly safer
|
|
39
|
+
* than a dependent stranded against a vanished table.
|
|
40
|
+
*
|
|
41
|
+
* NOTE: full cross-table atomicity — bundling this old-entry delete together with every
|
|
42
|
+
* dependent rewrite into one `provider.beginAtomicBatch` commit — would eliminate even
|
|
43
|
+
* the transient two-entry window (and the physical-move orphan `renameTableStores`
|
|
44
|
+
* leaves), but only on atomic providers, and the dependent set is known only to the
|
|
45
|
+
* engine post-propagate. That is the atomic-provider hardening path; out of scope here.
|
|
46
|
+
*/
|
|
47
|
+
finalizeRename(_db: Database, schemaName: string, oldName: string, _newName: string): Promise<void>;
|
|
48
|
+
}
|
|
49
|
+
//# sourceMappingURL=store-module-rename.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"store-module-rename.d.ts","sourceRoot":"","sources":["../../../src/common/store-module-rename.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAiC,MAAM,kBAAkB,CAAC;AAUhF,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAI3D,8BAAsB,iBAAkB,SAAQ,gBAAgB;IAC/D;;;;;;;;;OASG;IACG,WAAW,CAChB,EAAE,EAAE,QAAQ,EACZ,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,MAAM,EACf,GAAG,CAAC,EAAE,MAAM,GACV,OAAO,CAAC,IAAI,CAAC;IAgPhB;;;;;;;;;;;;;;;;;;;;;OAqBG;IACG,cAAc,CACnB,GAAG,EAAE,QAAQ,EACb,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,MAAM,GACd,OAAO,CAAC,IAAI,CAAC;CAIhB"}
|