@push.rocks/smartdb 1.0.1 → 2.1.1

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 (126) hide show
  1. package/.smartconfig.json +18 -4
  2. package/dist_rust/rustdb_linux_amd64 +0 -0
  3. package/dist_rust/rustdb_linux_arm64 +0 -0
  4. package/dist_ts/00_commitinfo_data.js +3 -3
  5. package/dist_ts/index.d.ts +1 -0
  6. package/dist_ts/ts_local/classes.localsmartdb.d.ts +5 -5
  7. package/dist_ts/ts_local/classes.localsmartdb.js +7 -9
  8. package/dist_ts/ts_local/plugins.d.ts +1 -2
  9. package/dist_ts/ts_local/plugins.js +3 -3
  10. package/dist_ts/ts_smartdb/index.d.ts +2 -24
  11. package/dist_ts/ts_smartdb/index.js +4 -29
  12. package/dist_ts/ts_smartdb/plugins.d.ts +2 -10
  13. package/dist_ts/ts_smartdb/plugins.js +3 -13
  14. package/dist_ts/ts_smartdb/rust-db-bridge.d.ts +122 -0
  15. package/dist_ts/ts_smartdb/rust-db-bridge.js +113 -0
  16. package/dist_ts/ts_smartdb/server/SmartdbServer.d.ts +39 -37
  17. package/dist_ts/ts_smartdb/server/SmartdbServer.js +87 -206
  18. package/dist_ts/ts_smartdb/server/index.d.ts +0 -4
  19. package/dist_ts/ts_smartdb/server/index.js +1 -5
  20. package/dist_ts_debugserver/bundled.d.ts +4 -0
  21. package/dist_ts_debugserver/bundled.js +12 -0
  22. package/dist_ts_debugserver/classes.debugserver.d.ts +36 -0
  23. package/dist_ts_debugserver/classes.debugserver.js +95 -0
  24. package/dist_ts_debugserver/index.d.ts +2 -0
  25. package/dist_ts_debugserver/index.js +2 -0
  26. package/dist_ts_debugserver/plugins.d.ts +2 -0
  27. package/dist_ts_debugserver/plugins.js +3 -0
  28. package/dist_ts_debugui/index.d.ts +2 -0
  29. package/dist_ts_debugui/index.js +2 -0
  30. package/dist_ts_debugui/plugins.d.ts +1 -0
  31. package/dist_ts_debugui/plugins.js +2 -0
  32. package/dist_ts_debugui/smartdb-debugui.d.ts +62 -0
  33. package/dist_ts_debugui/smartdb-debugui.js +1132 -0
  34. package/license +3 -1
  35. package/package.json +14 -13
  36. package/readme.md +209 -177
  37. package/ts/00_commitinfo_data.ts +2 -2
  38. package/ts/index.ts +11 -0
  39. package/ts/ts_local/classes.localsmartdb.ts +5 -6
  40. package/ts/ts_local/plugins.ts +1 -3
  41. package/ts/ts_smartdb/index.ts +14 -41
  42. package/ts/ts_smartdb/plugins.ts +2 -15
  43. package/ts/ts_smartdb/rust-db-bridge.ts +262 -0
  44. package/ts/ts_smartdb/server/SmartdbServer.ts +115 -246
  45. package/ts/ts_smartdb/server/index.ts +0 -7
  46. package/dist_ts/ts_smartdb/engine/AggregationEngine.d.ts +0 -66
  47. package/dist_ts/ts_smartdb/engine/AggregationEngine.js +0 -189
  48. package/dist_ts/ts_smartdb/engine/IndexEngine.d.ts +0 -97
  49. package/dist_ts/ts_smartdb/engine/IndexEngine.js +0 -678
  50. package/dist_ts/ts_smartdb/engine/QueryEngine.d.ts +0 -54
  51. package/dist_ts/ts_smartdb/engine/QueryEngine.js +0 -271
  52. package/dist_ts/ts_smartdb/engine/QueryPlanner.d.ts +0 -64
  53. package/dist_ts/ts_smartdb/engine/QueryPlanner.js +0 -308
  54. package/dist_ts/ts_smartdb/engine/SessionEngine.d.ts +0 -117
  55. package/dist_ts/ts_smartdb/engine/SessionEngine.js +0 -232
  56. package/dist_ts/ts_smartdb/engine/TransactionEngine.d.ts +0 -85
  57. package/dist_ts/ts_smartdb/engine/TransactionEngine.js +0 -287
  58. package/dist_ts/ts_smartdb/engine/UpdateEngine.d.ts +0 -47
  59. package/dist_ts/ts_smartdb/engine/UpdateEngine.js +0 -461
  60. package/dist_ts/ts_smartdb/errors/SmartdbErrors.d.ts +0 -100
  61. package/dist_ts/ts_smartdb/errors/SmartdbErrors.js +0 -155
  62. package/dist_ts/ts_smartdb/server/CommandRouter.d.ts +0 -87
  63. package/dist_ts/ts_smartdb/server/CommandRouter.js +0 -222
  64. package/dist_ts/ts_smartdb/server/WireProtocol.d.ts +0 -117
  65. package/dist_ts/ts_smartdb/server/WireProtocol.js +0 -298
  66. package/dist_ts/ts_smartdb/server/handlers/AdminHandler.d.ts +0 -100
  67. package/dist_ts/ts_smartdb/server/handlers/AdminHandler.js +0 -668
  68. package/dist_ts/ts_smartdb/server/handlers/AggregateHandler.d.ts +0 -31
  69. package/dist_ts/ts_smartdb/server/handlers/AggregateHandler.js +0 -277
  70. package/dist_ts/ts_smartdb/server/handlers/DeleteHandler.d.ts +0 -8
  71. package/dist_ts/ts_smartdb/server/handlers/DeleteHandler.js +0 -95
  72. package/dist_ts/ts_smartdb/server/handlers/FindHandler.d.ts +0 -31
  73. package/dist_ts/ts_smartdb/server/handlers/FindHandler.js +0 -291
  74. package/dist_ts/ts_smartdb/server/handlers/HelloHandler.d.ts +0 -11
  75. package/dist_ts/ts_smartdb/server/handlers/HelloHandler.js +0 -62
  76. package/dist_ts/ts_smartdb/server/handlers/IndexHandler.d.ts +0 -20
  77. package/dist_ts/ts_smartdb/server/handlers/IndexHandler.js +0 -183
  78. package/dist_ts/ts_smartdb/server/handlers/InsertHandler.d.ts +0 -8
  79. package/dist_ts/ts_smartdb/server/handlers/InsertHandler.js +0 -79
  80. package/dist_ts/ts_smartdb/server/handlers/UpdateHandler.d.ts +0 -24
  81. package/dist_ts/ts_smartdb/server/handlers/UpdateHandler.js +0 -296
  82. package/dist_ts/ts_smartdb/server/handlers/index.d.ts +0 -8
  83. package/dist_ts/ts_smartdb/server/handlers/index.js +0 -10
  84. package/dist_ts/ts_smartdb/storage/FileStorageAdapter.d.ts +0 -85
  85. package/dist_ts/ts_smartdb/storage/FileStorageAdapter.js +0 -465
  86. package/dist_ts/ts_smartdb/storage/IStorageAdapter.d.ts +0 -145
  87. package/dist_ts/ts_smartdb/storage/IStorageAdapter.js +0 -2
  88. package/dist_ts/ts_smartdb/storage/MemoryStorageAdapter.d.ts +0 -67
  89. package/dist_ts/ts_smartdb/storage/MemoryStorageAdapter.js +0 -378
  90. package/dist_ts/ts_smartdb/storage/OpLog.d.ts +0 -93
  91. package/dist_ts/ts_smartdb/storage/OpLog.js +0 -221
  92. package/dist_ts/ts_smartdb/storage/WAL.d.ts +0 -117
  93. package/dist_ts/ts_smartdb/storage/WAL.js +0 -286
  94. package/dist_ts/ts_smartdb/types/interfaces.d.ts +0 -363
  95. package/dist_ts/ts_smartdb/types/interfaces.js +0 -2
  96. package/dist_ts/ts_smartdb/utils/checksum.d.ts +0 -30
  97. package/dist_ts/ts_smartdb/utils/checksum.js +0 -77
  98. package/dist_ts/ts_smartdb/utils/index.d.ts +0 -1
  99. package/dist_ts/ts_smartdb/utils/index.js +0 -2
  100. package/ts/ts_smartdb/engine/AggregationEngine.ts +0 -283
  101. package/ts/ts_smartdb/engine/IndexEngine.ts +0 -798
  102. package/ts/ts_smartdb/engine/QueryEngine.ts +0 -301
  103. package/ts/ts_smartdb/engine/QueryPlanner.ts +0 -393
  104. package/ts/ts_smartdb/engine/SessionEngine.ts +0 -292
  105. package/ts/ts_smartdb/engine/TransactionEngine.ts +0 -351
  106. package/ts/ts_smartdb/engine/UpdateEngine.ts +0 -506
  107. package/ts/ts_smartdb/errors/SmartdbErrors.ts +0 -181
  108. package/ts/ts_smartdb/server/CommandRouter.ts +0 -289
  109. package/ts/ts_smartdb/server/WireProtocol.ts +0 -416
  110. package/ts/ts_smartdb/server/handlers/AdminHandler.ts +0 -719
  111. package/ts/ts_smartdb/server/handlers/AggregateHandler.ts +0 -342
  112. package/ts/ts_smartdb/server/handlers/DeleteHandler.ts +0 -115
  113. package/ts/ts_smartdb/server/handlers/FindHandler.ts +0 -330
  114. package/ts/ts_smartdb/server/handlers/HelloHandler.ts +0 -78
  115. package/ts/ts_smartdb/server/handlers/IndexHandler.ts +0 -207
  116. package/ts/ts_smartdb/server/handlers/InsertHandler.ts +0 -97
  117. package/ts/ts_smartdb/server/handlers/UpdateHandler.ts +0 -344
  118. package/ts/ts_smartdb/server/handlers/index.ts +0 -10
  119. package/ts/ts_smartdb/storage/FileStorageAdapter.ts +0 -562
  120. package/ts/ts_smartdb/storage/IStorageAdapter.ts +0 -208
  121. package/ts/ts_smartdb/storage/MemoryStorageAdapter.ts +0 -455
  122. package/ts/ts_smartdb/storage/OpLog.ts +0 -282
  123. package/ts/ts_smartdb/storage/WAL.ts +0 -375
  124. package/ts/ts_smartdb/types/interfaces.ts +0 -433
  125. package/ts/ts_smartdb/utils/checksum.ts +0 -88
  126. package/ts/ts_smartdb/utils/index.ts +0 -1
@@ -1,678 +0,0 @@
1
- import * as plugins from '../plugins.js';
2
- // Simple B-Tree implementation for range queries
3
- // Since sorted-btree has ESM/CJS interop issues, we use a simple custom implementation
4
- class SimpleBTree {
5
- entries = new Map();
6
- sortedKeys = [];
7
- comparator;
8
- constructor(_unused, comparator) {
9
- this.comparator = comparator || ((a, b) => {
10
- if (a < b)
11
- return -1;
12
- if (a > b)
13
- return 1;
14
- return 0;
15
- });
16
- }
17
- keyToString(key) {
18
- return JSON.stringify(key);
19
- }
20
- set(key, value) {
21
- const keyStr = this.keyToString(key);
22
- const existed = this.entries.has(keyStr);
23
- this.entries.set(keyStr, { key, value });
24
- if (!existed) {
25
- // Insert in sorted order
26
- const idx = this.sortedKeys.findIndex(k => this.comparator(k, key) > 0);
27
- if (idx === -1) {
28
- this.sortedKeys.push(key);
29
- }
30
- else {
31
- this.sortedKeys.splice(idx, 0, key);
32
- }
33
- }
34
- return !existed;
35
- }
36
- get(key) {
37
- const entry = this.entries.get(this.keyToString(key));
38
- return entry?.value;
39
- }
40
- delete(key) {
41
- const keyStr = this.keyToString(key);
42
- if (this.entries.has(keyStr)) {
43
- this.entries.delete(keyStr);
44
- const idx = this.sortedKeys.findIndex(k => this.comparator(k, key) === 0);
45
- if (idx !== -1) {
46
- this.sortedKeys.splice(idx, 1);
47
- }
48
- return true;
49
- }
50
- return false;
51
- }
52
- forRange(lowKey, highKey, lowInclusive, highInclusive, callback) {
53
- for (const key of this.sortedKeys) {
54
- // Check low bound
55
- if (lowKey !== undefined) {
56
- const cmp = this.comparator(key, lowKey);
57
- if (cmp < 0)
58
- continue;
59
- if (cmp === 0 && !lowInclusive)
60
- continue;
61
- }
62
- // Check high bound
63
- if (highKey !== undefined) {
64
- const cmp = this.comparator(key, highKey);
65
- if (cmp > 0)
66
- break;
67
- if (cmp === 0 && !highInclusive)
68
- break;
69
- }
70
- const entry = this.entries.get(this.keyToString(key));
71
- if (entry) {
72
- callback(entry.value, key);
73
- }
74
- }
75
- }
76
- }
77
- import { SmartdbDuplicateKeyError, SmartdbIndexError } from '../errors/SmartdbErrors.js';
78
- import { QueryEngine } from './QueryEngine.js';
79
- /**
80
- * Comparator for B-Tree that handles mixed types consistently
81
- */
82
- function indexKeyComparator(a, b) {
83
- // Handle null/undefined
84
- if (a === null || a === undefined) {
85
- if (b === null || b === undefined)
86
- return 0;
87
- return -1;
88
- }
89
- if (b === null || b === undefined)
90
- return 1;
91
- // Handle arrays (compound keys)
92
- if (Array.isArray(a) && Array.isArray(b)) {
93
- for (let i = 0; i < Math.max(a.length, b.length); i++) {
94
- const cmp = indexKeyComparator(a[i], b[i]);
95
- if (cmp !== 0)
96
- return cmp;
97
- }
98
- return 0;
99
- }
100
- // Handle ObjectId
101
- if (a instanceof plugins.bson.ObjectId && b instanceof plugins.bson.ObjectId) {
102
- return a.toHexString().localeCompare(b.toHexString());
103
- }
104
- // Handle Date
105
- if (a instanceof Date && b instanceof Date) {
106
- return a.getTime() - b.getTime();
107
- }
108
- // Handle different types - use type ordering (null < number < string < object)
109
- const typeOrder = (v) => {
110
- if (v === null || v === undefined)
111
- return 0;
112
- if (typeof v === 'number')
113
- return 1;
114
- if (typeof v === 'string')
115
- return 2;
116
- if (typeof v === 'boolean')
117
- return 3;
118
- if (v instanceof Date)
119
- return 4;
120
- if (v instanceof plugins.bson.ObjectId)
121
- return 5;
122
- return 6;
123
- };
124
- const typeA = typeOrder(a);
125
- const typeB = typeOrder(b);
126
- if (typeA !== typeB)
127
- return typeA - typeB;
128
- // Same type comparison
129
- if (typeof a === 'number')
130
- return a - b;
131
- if (typeof a === 'string')
132
- return a.localeCompare(b);
133
- if (typeof a === 'boolean')
134
- return (a ? 1 : 0) - (b ? 1 : 0);
135
- // Fallback to string comparison
136
- return String(a).localeCompare(String(b));
137
- }
138
- /**
139
- * Index engine for managing indexes and query optimization
140
- */
141
- export class IndexEngine {
142
- dbName;
143
- collName;
144
- storage;
145
- indexes = new Map();
146
- initialized = false;
147
- constructor(dbName, collName, storage) {
148
- this.dbName = dbName;
149
- this.collName = collName;
150
- this.storage = storage;
151
- }
152
- /**
153
- * Initialize indexes from storage
154
- */
155
- async initialize() {
156
- if (this.initialized)
157
- return;
158
- const storedIndexes = await this.storage.getIndexes(this.dbName, this.collName);
159
- const documents = await this.storage.findAll(this.dbName, this.collName);
160
- for (const indexSpec of storedIndexes) {
161
- const indexData = {
162
- name: indexSpec.name,
163
- key: indexSpec.key,
164
- unique: indexSpec.unique || false,
165
- sparse: indexSpec.sparse || false,
166
- expireAfterSeconds: indexSpec.expireAfterSeconds,
167
- btree: new SimpleBTree(undefined, indexKeyComparator),
168
- hashMap: new Map(),
169
- };
170
- // Build index entries
171
- for (const doc of documents) {
172
- const keyValue = this.extractKeyValue(doc, indexSpec.key);
173
- if (keyValue !== null || !indexData.sparse) {
174
- const keyStr = JSON.stringify(keyValue);
175
- // Add to hash map
176
- if (!indexData.hashMap.has(keyStr)) {
177
- indexData.hashMap.set(keyStr, new Set());
178
- }
179
- indexData.hashMap.get(keyStr).add(doc._id.toHexString());
180
- // Add to B-tree
181
- const existing = indexData.btree.get(keyValue);
182
- if (existing) {
183
- existing.add(doc._id.toHexString());
184
- }
185
- else {
186
- indexData.btree.set(keyValue, new Set([doc._id.toHexString()]));
187
- }
188
- }
189
- }
190
- this.indexes.set(indexSpec.name, indexData);
191
- }
192
- this.initialized = true;
193
- }
194
- /**
195
- * Create a new index
196
- */
197
- async createIndex(key, options) {
198
- await this.initialize();
199
- // Generate index name if not provided
200
- const name = options?.name || this.generateIndexName(key);
201
- // Check if index already exists
202
- if (this.indexes.has(name)) {
203
- return name;
204
- }
205
- // Create index data structure
206
- const indexData = {
207
- name,
208
- key: key,
209
- unique: options?.unique || false,
210
- sparse: options?.sparse || false,
211
- expireAfterSeconds: options?.expireAfterSeconds,
212
- btree: new SimpleBTree(undefined, indexKeyComparator),
213
- hashMap: new Map(),
214
- };
215
- // Build index from existing documents
216
- const documents = await this.storage.findAll(this.dbName, this.collName);
217
- for (const doc of documents) {
218
- const keyValue = this.extractKeyValue(doc, key);
219
- if (keyValue === null && indexData.sparse) {
220
- continue;
221
- }
222
- const keyStr = JSON.stringify(keyValue);
223
- if (indexData.unique && indexData.hashMap.has(keyStr)) {
224
- throw new SmartdbDuplicateKeyError(`E11000 duplicate key error index: ${this.dbName}.${this.collName}.$${name}`, key, keyValue);
225
- }
226
- // Add to hash map
227
- if (!indexData.hashMap.has(keyStr)) {
228
- indexData.hashMap.set(keyStr, new Set());
229
- }
230
- indexData.hashMap.get(keyStr).add(doc._id.toHexString());
231
- // Add to B-tree
232
- const existing = indexData.btree.get(keyValue);
233
- if (existing) {
234
- existing.add(doc._id.toHexString());
235
- }
236
- else {
237
- indexData.btree.set(keyValue, new Set([doc._id.toHexString()]));
238
- }
239
- }
240
- // Store index
241
- this.indexes.set(name, indexData);
242
- await this.storage.saveIndex(this.dbName, this.collName, name, {
243
- key,
244
- unique: options?.unique,
245
- sparse: options?.sparse,
246
- expireAfterSeconds: options?.expireAfterSeconds,
247
- });
248
- return name;
249
- }
250
- /**
251
- * Drop an index
252
- */
253
- async dropIndex(name) {
254
- await this.initialize();
255
- if (name === '_id_') {
256
- throw new SmartdbIndexError('cannot drop _id index');
257
- }
258
- if (!this.indexes.has(name)) {
259
- throw new SmartdbIndexError(`index not found: ${name}`);
260
- }
261
- this.indexes.delete(name);
262
- await this.storage.dropIndex(this.dbName, this.collName, name);
263
- }
264
- /**
265
- * Drop all indexes except _id
266
- */
267
- async dropAllIndexes() {
268
- await this.initialize();
269
- const names = Array.from(this.indexes.keys()).filter(n => n !== '_id_');
270
- for (const name of names) {
271
- this.indexes.delete(name);
272
- await this.storage.dropIndex(this.dbName, this.collName, name);
273
- }
274
- }
275
- /**
276
- * List all indexes
277
- */
278
- async listIndexes() {
279
- await this.initialize();
280
- return Array.from(this.indexes.values()).map(idx => ({
281
- v: 2,
282
- key: idx.key,
283
- name: idx.name,
284
- unique: idx.unique || undefined,
285
- sparse: idx.sparse || undefined,
286
- expireAfterSeconds: idx.expireAfterSeconds,
287
- }));
288
- }
289
- /**
290
- * Check if an index exists
291
- */
292
- async indexExists(name) {
293
- await this.initialize();
294
- return this.indexes.has(name);
295
- }
296
- /**
297
- * Update index entries after document insert
298
- */
299
- async onInsert(doc) {
300
- await this.initialize();
301
- for (const [name, indexData] of this.indexes) {
302
- const keyValue = this.extractKeyValue(doc, indexData.key);
303
- if (keyValue === null && indexData.sparse) {
304
- continue;
305
- }
306
- const keyStr = JSON.stringify(keyValue);
307
- // Check unique constraint
308
- if (indexData.unique) {
309
- const existing = indexData.hashMap.get(keyStr);
310
- if (existing && existing.size > 0) {
311
- throw new SmartdbDuplicateKeyError(`E11000 duplicate key error collection: ${this.dbName}.${this.collName} index: ${name}`, indexData.key, keyValue);
312
- }
313
- }
314
- // Add to hash map
315
- if (!indexData.hashMap.has(keyStr)) {
316
- indexData.hashMap.set(keyStr, new Set());
317
- }
318
- indexData.hashMap.get(keyStr).add(doc._id.toHexString());
319
- // Add to B-tree
320
- const btreeSet = indexData.btree.get(keyValue);
321
- if (btreeSet) {
322
- btreeSet.add(doc._id.toHexString());
323
- }
324
- else {
325
- indexData.btree.set(keyValue, new Set([doc._id.toHexString()]));
326
- }
327
- }
328
- }
329
- /**
330
- * Update index entries after document update
331
- */
332
- async onUpdate(oldDoc, newDoc) {
333
- await this.initialize();
334
- for (const [name, indexData] of this.indexes) {
335
- const oldKeyValue = this.extractKeyValue(oldDoc, indexData.key);
336
- const newKeyValue = this.extractKeyValue(newDoc, indexData.key);
337
- const oldKeyStr = JSON.stringify(oldKeyValue);
338
- const newKeyStr = JSON.stringify(newKeyValue);
339
- // Remove old entry if key changed
340
- if (oldKeyStr !== newKeyStr) {
341
- if (oldKeyValue !== null || !indexData.sparse) {
342
- // Remove from hash map
343
- const oldHashSet = indexData.hashMap.get(oldKeyStr);
344
- if (oldHashSet) {
345
- oldHashSet.delete(oldDoc._id.toHexString());
346
- if (oldHashSet.size === 0) {
347
- indexData.hashMap.delete(oldKeyStr);
348
- }
349
- }
350
- // Remove from B-tree
351
- const oldBtreeSet = indexData.btree.get(oldKeyValue);
352
- if (oldBtreeSet) {
353
- oldBtreeSet.delete(oldDoc._id.toHexString());
354
- if (oldBtreeSet.size === 0) {
355
- indexData.btree.delete(oldKeyValue);
356
- }
357
- }
358
- }
359
- // Add new entry
360
- if (newKeyValue !== null || !indexData.sparse) {
361
- // Check unique constraint
362
- if (indexData.unique) {
363
- const existing = indexData.hashMap.get(newKeyStr);
364
- if (existing && existing.size > 0) {
365
- throw new SmartdbDuplicateKeyError(`E11000 duplicate key error collection: ${this.dbName}.${this.collName} index: ${name}`, indexData.key, newKeyValue);
366
- }
367
- }
368
- // Add to hash map
369
- if (!indexData.hashMap.has(newKeyStr)) {
370
- indexData.hashMap.set(newKeyStr, new Set());
371
- }
372
- indexData.hashMap.get(newKeyStr).add(newDoc._id.toHexString());
373
- // Add to B-tree
374
- const newBtreeSet = indexData.btree.get(newKeyValue);
375
- if (newBtreeSet) {
376
- newBtreeSet.add(newDoc._id.toHexString());
377
- }
378
- else {
379
- indexData.btree.set(newKeyValue, new Set([newDoc._id.toHexString()]));
380
- }
381
- }
382
- }
383
- }
384
- }
385
- /**
386
- * Update index entries after document delete
387
- */
388
- async onDelete(doc) {
389
- await this.initialize();
390
- for (const indexData of this.indexes.values()) {
391
- const keyValue = this.extractKeyValue(doc, indexData.key);
392
- if (keyValue === null && indexData.sparse) {
393
- continue;
394
- }
395
- const keyStr = JSON.stringify(keyValue);
396
- // Remove from hash map
397
- const hashSet = indexData.hashMap.get(keyStr);
398
- if (hashSet) {
399
- hashSet.delete(doc._id.toHexString());
400
- if (hashSet.size === 0) {
401
- indexData.hashMap.delete(keyStr);
402
- }
403
- }
404
- // Remove from B-tree
405
- const btreeSet = indexData.btree.get(keyValue);
406
- if (btreeSet) {
407
- btreeSet.delete(doc._id.toHexString());
408
- if (btreeSet.size === 0) {
409
- indexData.btree.delete(keyValue);
410
- }
411
- }
412
- }
413
- }
414
- /**
415
- * Find the best index for a query
416
- */
417
- selectIndex(filter) {
418
- if (!filter || Object.keys(filter).length === 0) {
419
- return null;
420
- }
421
- // Get filter fields and operators
422
- const filterInfo = this.analyzeFilter(filter);
423
- // Score each index
424
- let bestIndex = null;
425
- let bestScore = 0;
426
- for (const [name, indexData] of this.indexes) {
427
- const indexFields = Object.keys(indexData.key);
428
- let score = 0;
429
- // Count how many index fields can be used
430
- for (const field of indexFields) {
431
- const info = filterInfo.get(field);
432
- if (!info)
433
- break;
434
- // Equality is best
435
- if (info.equality) {
436
- score += 2;
437
- }
438
- else if (info.range) {
439
- // Range queries can use B-tree
440
- score += 1;
441
- }
442
- else if (info.in) {
443
- score += 1.5;
444
- }
445
- else {
446
- break;
447
- }
448
- }
449
- // Prefer unique indexes
450
- if (indexData.unique && score > 0) {
451
- score += 0.5;
452
- }
453
- if (score > bestScore) {
454
- bestScore = score;
455
- bestIndex = { name, data: indexData };
456
- }
457
- }
458
- return bestIndex;
459
- }
460
- /**
461
- * Analyze filter to extract field operators
462
- */
463
- analyzeFilter(filter) {
464
- const result = new Map();
465
- for (const [key, value] of Object.entries(filter)) {
466
- if (key.startsWith('$'))
467
- continue;
468
- const info = { equality: false, range: false, in: false, ops: {} };
469
- if (typeof value !== 'object' || value === null || value instanceof plugins.bson.ObjectId || value instanceof Date) {
470
- info.equality = true;
471
- info.ops['$eq'] = value;
472
- }
473
- else {
474
- const ops = value;
475
- if (ops.$eq !== undefined) {
476
- info.equality = true;
477
- info.ops['$eq'] = ops.$eq;
478
- }
479
- if (ops.$in !== undefined) {
480
- info.in = true;
481
- info.ops['$in'] = ops.$in;
482
- }
483
- if (ops.$gt !== undefined || ops.$gte !== undefined || ops.$lt !== undefined || ops.$lte !== undefined) {
484
- info.range = true;
485
- if (ops.$gt !== undefined)
486
- info.ops['$gt'] = ops.$gt;
487
- if (ops.$gte !== undefined)
488
- info.ops['$gte'] = ops.$gte;
489
- if (ops.$lt !== undefined)
490
- info.ops['$lt'] = ops.$lt;
491
- if (ops.$lte !== undefined)
492
- info.ops['$lte'] = ops.$lte;
493
- }
494
- }
495
- result.set(key, info);
496
- }
497
- return result;
498
- }
499
- /**
500
- * Use index to find candidate document IDs (supports range queries with B-tree)
501
- */
502
- async findCandidateIds(filter) {
503
- await this.initialize();
504
- const index = this.selectIndex(filter);
505
- if (!index)
506
- return null;
507
- const filterInfo = this.analyzeFilter(filter);
508
- const indexFields = Object.keys(index.data.key);
509
- // For single-field indexes with range queries, use B-tree
510
- if (indexFields.length === 1) {
511
- const field = indexFields[0];
512
- const info = filterInfo.get(field);
513
- if (info) {
514
- // Handle equality using hash map (faster)
515
- if (info.equality) {
516
- const keyStr = JSON.stringify(info.ops['$eq']);
517
- return index.data.hashMap.get(keyStr) || new Set();
518
- }
519
- // Handle $in using hash map
520
- if (info.in) {
521
- const results = new Set();
522
- for (const val of info.ops['$in']) {
523
- const keyStr = JSON.stringify(val);
524
- const ids = index.data.hashMap.get(keyStr);
525
- if (ids) {
526
- for (const id of ids) {
527
- results.add(id);
528
- }
529
- }
530
- }
531
- return results;
532
- }
533
- // Handle range queries using B-tree
534
- if (info.range) {
535
- return this.findRangeCandidates(index.data, info.ops);
536
- }
537
- }
538
- }
539
- else {
540
- // For compound indexes, use hash map with partial key matching
541
- const equalityValues = {};
542
- for (const field of indexFields) {
543
- const info = filterInfo.get(field);
544
- if (!info)
545
- break;
546
- if (info.equality) {
547
- equalityValues[field] = info.ops['$eq'];
548
- }
549
- else if (info.in) {
550
- // Handle $in with multiple lookups
551
- const results = new Set();
552
- for (const val of info.ops['$in']) {
553
- equalityValues[field] = val;
554
- const keyStr = JSON.stringify(this.buildKeyValue(equalityValues, index.data.key));
555
- const ids = index.data.hashMap.get(keyStr);
556
- if (ids) {
557
- for (const id of ids) {
558
- results.add(id);
559
- }
560
- }
561
- }
562
- return results;
563
- }
564
- else {
565
- break; // Non-equality/in operator, stop here
566
- }
567
- }
568
- if (Object.keys(equalityValues).length > 0) {
569
- const keyStr = JSON.stringify(this.buildKeyValue(equalityValues, index.data.key));
570
- return index.data.hashMap.get(keyStr) || new Set();
571
- }
572
- }
573
- return null;
574
- }
575
- /**
576
- * Find candidates using B-tree range scan
577
- */
578
- findRangeCandidates(indexData, ops) {
579
- const results = new Set();
580
- let lowKey = undefined;
581
- let highKey = undefined;
582
- let lowInclusive = true;
583
- let highInclusive = true;
584
- if (ops['$gt'] !== undefined) {
585
- lowKey = ops['$gt'];
586
- lowInclusive = false;
587
- }
588
- if (ops['$gte'] !== undefined) {
589
- lowKey = ops['$gte'];
590
- lowInclusive = true;
591
- }
592
- if (ops['$lt'] !== undefined) {
593
- highKey = ops['$lt'];
594
- highInclusive = false;
595
- }
596
- if (ops['$lte'] !== undefined) {
597
- highKey = ops['$lte'];
598
- highInclusive = true;
599
- }
600
- // Use B-tree range iteration
601
- indexData.btree.forRange(lowKey, highKey, lowInclusive, highInclusive, (value, key) => {
602
- if (value) {
603
- for (const id of value) {
604
- results.add(id);
605
- }
606
- }
607
- });
608
- return results;
609
- }
610
- // ============================================================================
611
- // Helper Methods
612
- // ============================================================================
613
- generateIndexName(key) {
614
- return Object.entries(key)
615
- .map(([field, dir]) => `${field}_${dir}`)
616
- .join('_');
617
- }
618
- extractKeyValue(doc, key) {
619
- const values = [];
620
- for (const field of Object.keys(key)) {
621
- const value = QueryEngine.getNestedValue(doc, field);
622
- values.push(value === undefined ? null : value);
623
- }
624
- // For single-field index, return the value directly
625
- if (values.length === 1) {
626
- return values[0];
627
- }
628
- return values;
629
- }
630
- buildKeyValue(values, key) {
631
- const result = [];
632
- for (const field of Object.keys(key)) {
633
- result.push(values[field] !== undefined ? values[field] : null);
634
- }
635
- if (result.length === 1) {
636
- return result[0];
637
- }
638
- return result;
639
- }
640
- getFilterFields(filter, prefix = '') {
641
- const fields = [];
642
- for (const [key, value] of Object.entries(filter)) {
643
- if (key.startsWith('$')) {
644
- // Logical operator
645
- if (key === '$and' || key === '$or' || key === '$nor') {
646
- for (const subFilter of value) {
647
- fields.push(...this.getFilterFields(subFilter, prefix));
648
- }
649
- }
650
- }
651
- else {
652
- const fullKey = prefix ? `${prefix}.${key}` : key;
653
- fields.push(fullKey);
654
- // Check for nested filters
655
- if (typeof value === 'object' && value !== null && !Array.isArray(value)) {
656
- const subKeys = Object.keys(value);
657
- if (subKeys.length > 0 && !subKeys[0].startsWith('$')) {
658
- fields.push(...this.getFilterFields(value, fullKey));
659
- }
660
- }
661
- }
662
- }
663
- return fields;
664
- }
665
- getFilterValue(filter, field) {
666
- // Handle dot notation
667
- const parts = field.split('.');
668
- let current = filter;
669
- for (const part of parts) {
670
- if (current === null || current === undefined) {
671
- return undefined;
672
- }
673
- current = current[part];
674
- }
675
- return current;
676
- }
677
- }
678
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiSW5kZXhFbmdpbmUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi90cy90c19zbWFydGRiL2VuZ2luZS9JbmRleEVuZ2luZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEtBQUssT0FBTyxNQUFNLGVBQWUsQ0FBQztBQUd6QyxpREFBaUQ7QUFDakQsdUZBQXVGO0FBQ3ZGLE1BQU0sV0FBVztJQUNQLE9BQU8sR0FBc0MsSUFBSSxHQUFHLEVBQUUsQ0FBQztJQUN2RCxVQUFVLEdBQVEsRUFBRSxDQUFDO0lBQ3JCLFVBQVUsQ0FBeUI7SUFFM0MsWUFBWSxPQUFtQixFQUFFLFVBQW1DO1FBQ2xFLElBQUksQ0FBQyxVQUFVLEdBQUcsVUFBVSxJQUFJLENBQUMsQ0FBQyxDQUFJLEVBQUUsQ0FBSSxFQUFFLEVBQUU7WUFDOUMsSUFBSSxDQUFDLEdBQUcsQ0FBQztnQkFBRSxPQUFPLENBQUMsQ0FBQyxDQUFDO1lBQ3JCLElBQUksQ0FBQyxHQUFHLENBQUM7Z0JBQUUsT0FBTyxDQUFDLENBQUM7WUFDcEIsT0FBTyxDQUFDLENBQUM7UUFDWCxDQUFDLENBQUMsQ0FBQztJQUNMLENBQUM7SUFFTyxXQUFXLENBQUMsR0FBTTtRQUN4QixPQUFPLElBQUksQ0FBQyxTQUFTLENBQUMsR0FBRyxDQUFDLENBQUM7SUFDN0IsQ0FBQztJQUVELEdBQUcsQ0FBQyxHQUFNLEVBQUUsS0FBUTtRQUNsQixNQUFNLE1BQU0sR0FBRyxJQUFJLENBQUMsV0FBVyxDQUFDLEdBQUcsQ0FBQyxDQUFDO1FBQ3JDLE1BQU0sT0FBTyxHQUFHLElBQUksQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLE1BQU0sQ0FBQyxDQUFDO1FBQ3pDLElBQUksQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLE1BQU0sRUFBRSxFQUFFLEdBQUcsRUFBRSxLQUFLLEVBQUUsQ0FBQyxDQUFDO1FBRXpDLElBQUksQ0FBQyxPQUFPLEVBQUUsQ0FBQztZQUNiLHlCQUF5QjtZQUN6QixN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