@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.
Files changed (107) hide show
  1. package/README.md +34 -6
  2. package/dist/src/common/encoding.d.ts +4 -3
  3. package/dist/src/common/encoding.d.ts.map +1 -1
  4. package/dist/src/common/encoding.js +17 -13
  5. package/dist/src/common/encoding.js.map +1 -1
  6. package/dist/src/common/events.d.ts +31 -25
  7. package/dist/src/common/events.d.ts.map +1 -1
  8. package/dist/src/common/events.js +38 -39
  9. package/dist/src/common/events.js.map +1 -1
  10. package/dist/src/common/implicit-unique-index.d.ts +80 -0
  11. package/dist/src/common/implicit-unique-index.d.ts.map +1 -0
  12. package/dist/src/common/implicit-unique-index.js +148 -0
  13. package/dist/src/common/implicit-unique-index.js.map +1 -0
  14. package/dist/src/common/index.d.ts +7 -3
  15. package/dist/src/common/index.d.ts.map +1 -1
  16. package/dist/src/common/index.js +5 -2
  17. package/dist/src/common/index.js.map +1 -1
  18. package/dist/src/common/json-key.d.ts +30 -2
  19. package/dist/src/common/json-key.d.ts.map +1 -1
  20. package/dist/src/common/json-key.js +49 -2
  21. package/dist/src/common/json-key.js.map +1 -1
  22. package/dist/src/common/key-builder.d.ts +40 -20
  23. package/dist/src/common/key-builder.d.ts.map +1 -1
  24. package/dist/src/common/key-builder.js +31 -23
  25. package/dist/src/common/key-builder.js.map +1 -1
  26. package/dist/src/common/kv-store.d.ts +10 -0
  27. package/dist/src/common/kv-store.d.ts.map +1 -1
  28. package/dist/src/common/pk-key-resolution.d.ts +348 -0
  29. package/dist/src/common/pk-key-resolution.d.ts.map +1 -0
  30. package/dist/src/common/pk-key-resolution.js +481 -0
  31. package/dist/src/common/pk-key-resolution.js.map +1 -0
  32. package/dist/src/common/store-module-access-plan.d.ts +32 -0
  33. package/dist/src/common/store-module-access-plan.d.ts.map +1 -0
  34. package/dist/src/common/store-module-access-plan.js +428 -0
  35. package/dist/src/common/store-module-access-plan.js.map +1 -0
  36. package/dist/src/common/store-module-alter-column.d.ts +23 -0
  37. package/dist/src/common/store-module-alter-column.d.ts.map +1 -0
  38. package/dist/src/common/store-module-alter-column.js +389 -0
  39. package/dist/src/common/store-module-alter-column.js.map +1 -0
  40. package/dist/src/common/store-module-alter.d.ts +55 -0
  41. package/dist/src/common/store-module-alter.d.ts.map +1 -0
  42. package/dist/src/common/store-module-alter.js +504 -0
  43. package/dist/src/common/store-module-alter.js.map +1 -0
  44. package/dist/src/common/store-module-base.d.ts +268 -0
  45. package/dist/src/common/store-module-base.d.ts.map +1 -0
  46. package/dist/src/common/store-module-base.js +362 -0
  47. package/dist/src/common/store-module-base.js.map +1 -0
  48. package/dist/src/common/store-module-catalog.d.ts +269 -0
  49. package/dist/src/common/store-module-catalog.d.ts.map +1 -0
  50. package/dist/src/common/store-module-catalog.js +462 -0
  51. package/dist/src/common/store-module-catalog.js.map +1 -0
  52. package/dist/src/common/store-module-index-build.d.ts +88 -0
  53. package/dist/src/common/store-module-index-build.d.ts.map +1 -0
  54. package/dist/src/common/store-module-index-build.js +280 -0
  55. package/dist/src/common/store-module-index-build.js.map +1 -0
  56. package/dist/src/common/store-module-index.d.ts +116 -0
  57. package/dist/src/common/store-module-index.d.ts.map +1 -0
  58. package/dist/src/common/store-module-index.js +373 -0
  59. package/dist/src/common/store-module-index.js.map +1 -0
  60. package/dist/src/common/store-module-rename.d.ts +49 -0
  61. package/dist/src/common/store-module-rename.d.ts.map +1 -0
  62. package/dist/src/common/store-module-rename.js +268 -0
  63. package/dist/src/common/store-module-rename.js.map +1 -0
  64. package/dist/src/common/store-module-schema-rewrite.d.ts +57 -0
  65. package/dist/src/common/store-module-schema-rewrite.d.ts.map +1 -0
  66. package/dist/src/common/store-module-schema-rewrite.js +140 -0
  67. package/dist/src/common/store-module-schema-rewrite.js.map +1 -0
  68. package/dist/src/common/store-module-schema-sync.d.ts +232 -0
  69. package/dist/src/common/store-module-schema-sync.d.ts.map +1 -0
  70. package/dist/src/common/store-module-schema-sync.js +529 -0
  71. package/dist/src/common/store-module-schema-sync.js.map +1 -0
  72. package/dist/src/common/store-module.d.ts +43 -909
  73. package/dist/src/common/store-module.d.ts.map +1 -1
  74. package/dist/src/common/store-module.js +184 -3276
  75. package/dist/src/common/store-module.js.map +1 -1
  76. package/dist/src/common/store-table-base.d.ts +539 -0
  77. package/dist/src/common/store-table-base.d.ts.map +1 -0
  78. package/dist/src/common/store-table-base.js +900 -0
  79. package/dist/src/common/store-table-base.js.map +1 -0
  80. package/dist/src/common/store-table-constraints.d.ts +237 -0
  81. package/dist/src/common/store-table-constraints.d.ts.map +1 -0
  82. package/dist/src/common/store-table-constraints.js +624 -0
  83. package/dist/src/common/store-table-constraints.js.map +1 -0
  84. package/dist/src/common/store-table-scan.d.ts +452 -0
  85. package/dist/src/common/store-table-scan.d.ts.map +1 -0
  86. package/dist/src/common/store-table-scan.js +901 -0
  87. package/dist/src/common/store-table-scan.js.map +1 -0
  88. package/dist/src/common/store-table.d.ts +71 -1144
  89. package/dist/src/common/store-table.d.ts.map +1 -1
  90. package/dist/src/common/store-table.js +168 -2385
  91. package/dist/src/common/store-table.js.map +1 -1
  92. package/dist/src/testing/index.d.ts +12 -0
  93. package/dist/src/testing/index.d.ts.map +1 -0
  94. package/dist/src/testing/index.js +12 -0
  95. package/dist/src/testing/index.js.map +1 -0
  96. package/dist/src/testing/kv-assert.d.ts +19 -0
  97. package/dist/src/testing/kv-assert.d.ts.map +1 -0
  98. package/dist/src/testing/kv-assert.js +25 -0
  99. package/dist/src/testing/kv-assert.js.map +1 -0
  100. package/dist/src/testing/kv-conformance.d.ts.map +1 -1
  101. package/dist/src/testing/kv-conformance.js +1 -15
  102. package/dist/src/testing/kv-conformance.js.map +1 -1
  103. package/dist/src/testing/kv-provider-conformance.d.ts +54 -0
  104. package/dist/src/testing/kv-provider-conformance.d.ts.map +1 -0
  105. package/dist/src/testing/kv-provider-conformance.js +183 -0
  106. package/dist/src/testing/kv-provider-conformance.js.map +1 -0
  107. 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"}