serializable-bptree 8.3.2 → 8.3.4
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/dist/cjs/index.cjs
CHANGED
|
@@ -94,39 +94,125 @@ var StringComparator = class extends ValueComparator {
|
|
|
94
94
|
var MVCCStrategy = class {
|
|
95
95
|
};
|
|
96
96
|
var LRUMap = class {
|
|
97
|
-
cache = /* @__PURE__ */ new Map();
|
|
98
97
|
capacity;
|
|
98
|
+
map;
|
|
99
|
+
head = null;
|
|
100
|
+
tail = null;
|
|
101
|
+
/**
|
|
102
|
+
* Creates an instance of LRUMap.
|
|
103
|
+
* @param capacity The maximum number of items the cache can hold.
|
|
104
|
+
*/
|
|
99
105
|
constructor(capacity) {
|
|
100
106
|
this.capacity = capacity;
|
|
107
|
+
this.map = /* @__PURE__ */ new Map();
|
|
101
108
|
}
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
109
|
+
/**
|
|
110
|
+
* Promotes a node to the head of the linked list (marks as most recently used).
|
|
111
|
+
* @param node The node to promote.
|
|
112
|
+
*/
|
|
113
|
+
promote(node) {
|
|
114
|
+
this.extract(node);
|
|
115
|
+
this.prepend(node);
|
|
108
116
|
}
|
|
117
|
+
/**
|
|
118
|
+
* Disconnects a node from the doubly linked list.
|
|
119
|
+
* @param node The node to extract.
|
|
120
|
+
*/
|
|
121
|
+
extract(node) {
|
|
122
|
+
if (node.prev) node.prev.next = node.next;
|
|
123
|
+
else this.head = node.next;
|
|
124
|
+
if (node.next) node.next.prev = node.prev;
|
|
125
|
+
else this.tail = node.prev;
|
|
126
|
+
node.prev = null;
|
|
127
|
+
node.next = null;
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Inserts a node at the head of the doubly linked list.
|
|
131
|
+
* @param node The node to prepend.
|
|
132
|
+
*/
|
|
133
|
+
prepend(node) {
|
|
134
|
+
node.next = this.head;
|
|
135
|
+
if (this.head) this.head.prev = node;
|
|
136
|
+
this.head = node;
|
|
137
|
+
if (!this.tail) this.tail = node;
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* Stores or updates a value by key.
|
|
141
|
+
* If the capacity is exceeded, the least recently used item (tail) is removed.
|
|
142
|
+
* @param key The key to store.
|
|
143
|
+
* @param value The value to store.
|
|
144
|
+
*/
|
|
109
145
|
set(key, value) {
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
146
|
+
const existing = this.map.get(key);
|
|
147
|
+
if (existing) {
|
|
148
|
+
existing.value = value;
|
|
149
|
+
this.promote(existing);
|
|
150
|
+
return;
|
|
115
151
|
}
|
|
116
|
-
|
|
117
|
-
|
|
152
|
+
const newNode = { key, value, prev: null, next: null };
|
|
153
|
+
this.map.set(key, newNode);
|
|
154
|
+
this.prepend(newNode);
|
|
155
|
+
if (this.map.size > this.capacity && this.tail) {
|
|
156
|
+
this.map.delete(this.tail.key);
|
|
157
|
+
this.extract(this.tail);
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
* Retrieves a value by key.
|
|
162
|
+
* Accessing the item moves it to the "most recently used" position.
|
|
163
|
+
* @param key The key to look for.
|
|
164
|
+
* @returns The value associated with the key, or undefined if not found.
|
|
165
|
+
*/
|
|
166
|
+
get(key) {
|
|
167
|
+
const node = this.map.get(key);
|
|
168
|
+
if (!node) return void 0;
|
|
169
|
+
this.promote(node);
|
|
170
|
+
return node.value;
|
|
118
171
|
}
|
|
172
|
+
/**
|
|
173
|
+
* Checks if a key exists in the cache without changing its access order.
|
|
174
|
+
* @param key The key to check.
|
|
175
|
+
* @returns True if the key exists, false otherwise.
|
|
176
|
+
*/
|
|
119
177
|
has(key) {
|
|
120
|
-
return this.
|
|
178
|
+
return this.map.has(key);
|
|
121
179
|
}
|
|
180
|
+
/**
|
|
181
|
+
* Removes a key and its associated value from the cache.
|
|
182
|
+
* @param key The key to remove.
|
|
183
|
+
* @returns True if the key was found and removed, false otherwise.
|
|
184
|
+
*/
|
|
122
185
|
delete(key) {
|
|
123
|
-
|
|
186
|
+
const node = this.map.get(key);
|
|
187
|
+
if (!node) return false;
|
|
188
|
+
this.extract(node);
|
|
189
|
+
this.map.delete(key);
|
|
190
|
+
return true;
|
|
124
191
|
}
|
|
125
|
-
|
|
126
|
-
|
|
192
|
+
/**
|
|
193
|
+
* Returns an iterator of keys in the order of most recently used to least recently used.
|
|
194
|
+
* @returns An iterable iterator of keys.
|
|
195
|
+
*/
|
|
196
|
+
*keys() {
|
|
197
|
+
let current = this.head;
|
|
198
|
+
while (current) {
|
|
199
|
+
yield current.key;
|
|
200
|
+
current = current.next;
|
|
201
|
+
}
|
|
127
202
|
}
|
|
203
|
+
/**
|
|
204
|
+
* Returns the current number of items in the cache.
|
|
205
|
+
*/
|
|
128
206
|
get size() {
|
|
129
|
-
return this.
|
|
207
|
+
return this.map.size;
|
|
208
|
+
}
|
|
209
|
+
/**
|
|
210
|
+
* Clears all items from the cache.
|
|
211
|
+
*/
|
|
212
|
+
clear() {
|
|
213
|
+
this.map.clear();
|
|
214
|
+
this.head = null;
|
|
215
|
+
this.tail = null;
|
|
130
216
|
}
|
|
131
217
|
};
|
|
132
218
|
var MVCCTransaction = class {
|
|
@@ -1522,7 +1608,7 @@ var BPTreeTransaction = class _BPTreeTransaction {
|
|
|
1522
1608
|
searchConfigs = {
|
|
1523
1609
|
gt: {
|
|
1524
1610
|
asc: {
|
|
1525
|
-
start: (tx, v) => tx.
|
|
1611
|
+
start: (tx, v) => tx.insertableRightestNodeByPrimary(v[0]),
|
|
1526
1612
|
end: () => null,
|
|
1527
1613
|
direction: 1,
|
|
1528
1614
|
earlyTerminate: false
|
|
@@ -1620,7 +1706,7 @@ var BPTreeTransaction = class _BPTreeTransaction {
|
|
|
1620
1706
|
},
|
|
1621
1707
|
primaryGt: {
|
|
1622
1708
|
asc: {
|
|
1623
|
-
start: (tx, v) => tx.
|
|
1709
|
+
start: (tx, v) => tx.insertableRightestNodeByPrimary(v[0]),
|
|
1624
1710
|
end: () => null,
|
|
1625
1711
|
direction: 1,
|
|
1626
1712
|
earlyTerminate: false
|
|
@@ -1682,7 +1768,7 @@ var BPTreeTransaction = class _BPTreeTransaction {
|
|
|
1682
1768
|
earlyTerminate: true
|
|
1683
1769
|
},
|
|
1684
1770
|
desc: {
|
|
1685
|
-
start: (tx, v) => tx.
|
|
1771
|
+
start: (tx, v) => tx.insertableRightestNodeByPrimary(v[0]),
|
|
1686
1772
|
end: (tx, v) => tx.insertableEndNode(v[0], -1),
|
|
1687
1773
|
direction: -1,
|
|
1688
1774
|
earlyTerminate: true
|
|
@@ -1710,7 +1796,7 @@ var BPTreeTransaction = class _BPTreeTransaction {
|
|
|
1710
1796
|
earlyTerminate: false
|
|
1711
1797
|
},
|
|
1712
1798
|
desc: {
|
|
1713
|
-
start: (tx, v) => tx.
|
|
1799
|
+
start: (tx, v) => tx.insertableRightestNodeByPrimary(tx.highestPrimaryValue(v)),
|
|
1714
1800
|
end: (tx, v) => tx.insertableEndNode(tx.lowestPrimaryValue(v), -1),
|
|
1715
1801
|
direction: -1,
|
|
1716
1802
|
earlyTerminate: false
|
|
@@ -1867,30 +1953,62 @@ var BPTreeTransaction = class _BPTreeTransaction {
|
|
|
1867
1953
|
return JSON.parse(JSON.stringify(node));
|
|
1868
1954
|
}
|
|
1869
1955
|
/**
|
|
1870
|
-
*
|
|
1871
|
-
*
|
|
1872
|
-
*
|
|
1956
|
+
* Resolves the best start/end configuration by independently examining
|
|
1957
|
+
* all conditions. Selects the tightest lower bound for start and the
|
|
1958
|
+
* tightest upper bound for end (in asc; reversed for desc).
|
|
1959
|
+
*
|
|
1873
1960
|
* @param condition The condition to analyze.
|
|
1874
|
-
* @
|
|
1961
|
+
* @param order The sort order ('asc' or 'desc').
|
|
1962
|
+
* @returns The resolved start/end keys, values, and traversal direction.
|
|
1875
1963
|
*/
|
|
1876
|
-
|
|
1877
|
-
|
|
1878
|
-
|
|
1879
|
-
|
|
1880
|
-
|
|
1881
|
-
|
|
1882
|
-
|
|
1883
|
-
|
|
1884
|
-
|
|
1885
|
-
|
|
1886
|
-
|
|
1887
|
-
|
|
1888
|
-
|
|
1889
|
-
|
|
1890
|
-
|
|
1891
|
-
|
|
1892
|
-
|
|
1893
|
-
|
|
1964
|
+
resolveStartEndConfigs(condition, order) {
|
|
1965
|
+
const direction = order === "asc" ? 1 : -1;
|
|
1966
|
+
const startCandidates = order === "asc" ? _BPTreeTransaction._lowerBoundKeys : _BPTreeTransaction._upperBoundKeys;
|
|
1967
|
+
const endCandidates = order === "asc" ? _BPTreeTransaction._upperBoundKeys : _BPTreeTransaction._lowerBoundKeys;
|
|
1968
|
+
let startKey = null;
|
|
1969
|
+
let endKey = null;
|
|
1970
|
+
let startValues = [];
|
|
1971
|
+
let endValues = [];
|
|
1972
|
+
for (const key of startCandidates) {
|
|
1973
|
+
if (key in condition) {
|
|
1974
|
+
startKey = key;
|
|
1975
|
+
startValues = this.ensureValues(condition[key]);
|
|
1976
|
+
break;
|
|
1977
|
+
}
|
|
1978
|
+
}
|
|
1979
|
+
for (const key of endCandidates) {
|
|
1980
|
+
if (key in condition) {
|
|
1981
|
+
endKey = key;
|
|
1982
|
+
endValues = this.ensureValues(condition[key]);
|
|
1983
|
+
break;
|
|
1984
|
+
}
|
|
1985
|
+
}
|
|
1986
|
+
return { startKey, endKey, startValues, endValues, direction };
|
|
1987
|
+
}
|
|
1988
|
+
// Lower bound providers, ordered by selectivity (tightest first)
|
|
1989
|
+
// Used for asc start / desc end
|
|
1990
|
+
static _lowerBoundKeys = [
|
|
1991
|
+
"primaryEqual",
|
|
1992
|
+
"equal",
|
|
1993
|
+
"primaryGt",
|
|
1994
|
+
"gt",
|
|
1995
|
+
"primaryGte",
|
|
1996
|
+
"gte",
|
|
1997
|
+
"primaryOr",
|
|
1998
|
+
"or"
|
|
1999
|
+
];
|
|
2000
|
+
// Upper bound providers, ordered by selectivity (tightest first)
|
|
2001
|
+
// Used for asc end / desc start
|
|
2002
|
+
static _upperBoundKeys = [
|
|
2003
|
+
"primaryEqual",
|
|
2004
|
+
"equal",
|
|
2005
|
+
"primaryLt",
|
|
2006
|
+
"lt",
|
|
2007
|
+
"primaryLte",
|
|
2008
|
+
"lte",
|
|
2009
|
+
"primaryOr",
|
|
2010
|
+
"or"
|
|
2011
|
+
];
|
|
1894
2012
|
constructor(rootTx, mvccRoot, mvcc, strategy, comparator, option) {
|
|
1895
2013
|
this.rootTx = rootTx === null ? this : rootTx;
|
|
1896
2014
|
this.mvccRoot = mvccRoot;
|
|
@@ -2161,7 +2279,7 @@ var BPTreeSyncTransaction = class extends BPTreeTransaction {
|
|
|
2161
2279
|
return this.getNode(node.next);
|
|
2162
2280
|
}
|
|
2163
2281
|
insertableEndNode(value, direction) {
|
|
2164
|
-
const insertableNode = this.
|
|
2282
|
+
const insertableNode = direction === -1 ? this.insertableNodeByPrimary(value) : this.insertableRightestNodeByPrimary(value);
|
|
2165
2283
|
let key;
|
|
2166
2284
|
switch (direction) {
|
|
2167
2285
|
case -1:
|
|
@@ -2198,13 +2316,10 @@ var BPTreeSyncTransaction = class extends BPTreeTransaction {
|
|
|
2198
2316
|
}
|
|
2199
2317
|
return node;
|
|
2200
2318
|
}
|
|
2201
|
-
*getPairsGenerator(
|
|
2319
|
+
*getPairsGenerator(startNode, endNode, direction) {
|
|
2202
2320
|
let node = startNode;
|
|
2203
|
-
|
|
2204
|
-
let hasMatched = false;
|
|
2205
|
-
while (!done) {
|
|
2321
|
+
while (true) {
|
|
2206
2322
|
if (endNode && node.id === endNode.id) {
|
|
2207
|
-
done = true;
|
|
2208
2323
|
break;
|
|
2209
2324
|
}
|
|
2210
2325
|
const len = node.values.length;
|
|
@@ -2212,14 +2327,8 @@ var BPTreeSyncTransaction = class extends BPTreeTransaction {
|
|
|
2212
2327
|
for (let i = 0; i < len; i++) {
|
|
2213
2328
|
const nValue = node.values[i];
|
|
2214
2329
|
const keys = node.keys[i];
|
|
2215
|
-
|
|
2216
|
-
|
|
2217
|
-
for (let j = 0; j < keys.length; j++) {
|
|
2218
|
-
yield [keys[j], nValue];
|
|
2219
|
-
}
|
|
2220
|
-
} else if (earlyTerminate && hasMatched) {
|
|
2221
|
-
done = true;
|
|
2222
|
-
break;
|
|
2330
|
+
for (let j = 0, kLen = keys.length; j < kLen; j++) {
|
|
2331
|
+
yield [keys[j], nValue];
|
|
2223
2332
|
}
|
|
2224
2333
|
}
|
|
2225
2334
|
} else {
|
|
@@ -2227,30 +2336,17 @@ var BPTreeSyncTransaction = class extends BPTreeTransaction {
|
|
|
2227
2336
|
while (i--) {
|
|
2228
2337
|
const nValue = node.values[i];
|
|
2229
2338
|
const keys = node.keys[i];
|
|
2230
|
-
|
|
2231
|
-
|
|
2232
|
-
|
|
2233
|
-
while (j--) {
|
|
2234
|
-
yield [keys[j], nValue];
|
|
2235
|
-
}
|
|
2236
|
-
} else if (earlyTerminate && hasMatched) {
|
|
2237
|
-
done = true;
|
|
2238
|
-
break;
|
|
2339
|
+
let j = keys.length;
|
|
2340
|
+
while (j--) {
|
|
2341
|
+
yield [keys[j], nValue];
|
|
2239
2342
|
}
|
|
2240
2343
|
}
|
|
2241
2344
|
}
|
|
2242
|
-
if (done) break;
|
|
2243
2345
|
if (direction === 1) {
|
|
2244
|
-
if (!node.next)
|
|
2245
|
-
done = true;
|
|
2246
|
-
break;
|
|
2247
|
-
}
|
|
2346
|
+
if (!node.next) break;
|
|
2248
2347
|
node = this.getNode(node.next);
|
|
2249
2348
|
} else {
|
|
2250
|
-
if (!node.prev)
|
|
2251
|
-
done = true;
|
|
2252
|
-
break;
|
|
2253
|
-
}
|
|
2349
|
+
if (!node.prev) break;
|
|
2254
2350
|
node = this.getNode(node.prev);
|
|
2255
2351
|
}
|
|
2256
2352
|
}
|
|
@@ -2339,49 +2435,36 @@ var BPTreeSyncTransaction = class extends BPTreeTransaction {
|
|
|
2339
2435
|
}
|
|
2340
2436
|
*whereStream(condition, options) {
|
|
2341
2437
|
const { filterValues, limit, order = "asc" } = options ?? {};
|
|
2342
|
-
const
|
|
2343
|
-
if (
|
|
2344
|
-
const
|
|
2345
|
-
const
|
|
2346
|
-
|
|
2347
|
-
|
|
2348
|
-
|
|
2349
|
-
|
|
2350
|
-
|
|
2351
|
-
|
|
2352
|
-
|
|
2353
|
-
|
|
2354
|
-
if (
|
|
2355
|
-
|
|
2438
|
+
const conditionKeys = Object.keys(condition);
|
|
2439
|
+
if (conditionKeys.length === 0) return;
|
|
2440
|
+
const resolved = this.resolveStartEndConfigs(condition, order);
|
|
2441
|
+
const direction = resolved.direction;
|
|
2442
|
+
let startNode;
|
|
2443
|
+
if (resolved.startKey) {
|
|
2444
|
+
const startConfig = this.searchConfigs[resolved.startKey][order];
|
|
2445
|
+
startNode = startConfig.start(this, resolved.startValues);
|
|
2446
|
+
} else {
|
|
2447
|
+
startNode = order === "asc" ? this.leftestNode() : this.rightestNode();
|
|
2448
|
+
}
|
|
2449
|
+
let endNode = null;
|
|
2450
|
+
if (resolved.endKey) {
|
|
2451
|
+
const endConfig = this.searchConfigs[resolved.endKey][order];
|
|
2452
|
+
endNode = endConfig.end(this, resolved.endValues);
|
|
2356
2453
|
}
|
|
2357
2454
|
if (!startNode) return;
|
|
2358
|
-
const comparator = this.verifierMap[driverKey];
|
|
2359
2455
|
const generator = this.getPairsGenerator(
|
|
2360
|
-
value,
|
|
2361
2456
|
startNode,
|
|
2362
2457
|
endNode,
|
|
2363
|
-
|
|
2364
|
-
direction,
|
|
2365
|
-
earlyTerminate
|
|
2458
|
+
direction
|
|
2366
2459
|
);
|
|
2367
2460
|
let count = 0;
|
|
2368
2461
|
const intersection = filterValues && filterValues.size > 0 ? filterValues : null;
|
|
2369
2462
|
for (const pair of generator) {
|
|
2370
|
-
const [k,
|
|
2463
|
+
const [k, v] = pair;
|
|
2371
2464
|
if (intersection && !intersection.has(k)) {
|
|
2372
2465
|
continue;
|
|
2373
2466
|
}
|
|
2374
|
-
|
|
2375
|
-
for (const key in condition) {
|
|
2376
|
-
if (key === driverKey) continue;
|
|
2377
|
-
const verify = this.verifierMap[key];
|
|
2378
|
-
const condValue = condition[key];
|
|
2379
|
-
if (!verify(v2, condValue)) {
|
|
2380
|
-
isMatch = false;
|
|
2381
|
-
break;
|
|
2382
|
-
}
|
|
2383
|
-
}
|
|
2384
|
-
if (isMatch) {
|
|
2467
|
+
if (this.verify(v, condition)) {
|
|
2385
2468
|
yield pair;
|
|
2386
2469
|
count++;
|
|
2387
2470
|
if (limit !== void 0 && count >= limit) {
|
|
@@ -3297,7 +3380,7 @@ var BPTreeAsyncTransaction = class extends BPTreeTransaction {
|
|
|
3297
3380
|
return await this.getNode(node.next);
|
|
3298
3381
|
}
|
|
3299
3382
|
async insertableEndNode(value, direction) {
|
|
3300
|
-
const insertableNode = await this.
|
|
3383
|
+
const insertableNode = direction === -1 ? await this.insertableNodeByPrimary(value) : await this.insertableRightestNodeByPrimary(value);
|
|
3301
3384
|
let key;
|
|
3302
3385
|
switch (direction) {
|
|
3303
3386
|
case -1:
|
|
@@ -3334,22 +3417,19 @@ var BPTreeAsyncTransaction = class extends BPTreeTransaction {
|
|
|
3334
3417
|
}
|
|
3335
3418
|
return node;
|
|
3336
3419
|
}
|
|
3337
|
-
async *getPairsGenerator(
|
|
3420
|
+
async *getPairsGenerator(startNode, endNode, direction) {
|
|
3338
3421
|
let node = startNode;
|
|
3339
|
-
let done = false;
|
|
3340
|
-
let hasMatched = false;
|
|
3341
3422
|
let nextNodePromise = null;
|
|
3342
|
-
while (
|
|
3423
|
+
while (true) {
|
|
3343
3424
|
if (endNode && node.id === endNode.id) {
|
|
3344
|
-
done = true;
|
|
3345
3425
|
break;
|
|
3346
3426
|
}
|
|
3347
3427
|
if (direction === 1) {
|
|
3348
|
-
if (node.next
|
|
3428
|
+
if (node.next) {
|
|
3349
3429
|
nextNodePromise = this.getNode(node.next);
|
|
3350
3430
|
}
|
|
3351
3431
|
} else {
|
|
3352
|
-
if (node.prev
|
|
3432
|
+
if (node.prev) {
|
|
3353
3433
|
nextNodePromise = this.getNode(node.prev);
|
|
3354
3434
|
}
|
|
3355
3435
|
}
|
|
@@ -3358,14 +3438,8 @@ var BPTreeAsyncTransaction = class extends BPTreeTransaction {
|
|
|
3358
3438
|
for (let i = 0; i < len; i++) {
|
|
3359
3439
|
const nValue = node.values[i];
|
|
3360
3440
|
const keys = node.keys[i];
|
|
3361
|
-
|
|
3362
|
-
|
|
3363
|
-
for (let j = 0; j < keys.length; j++) {
|
|
3364
|
-
yield [keys[j], nValue];
|
|
3365
|
-
}
|
|
3366
|
-
} else if (earlyTerminate && hasMatched) {
|
|
3367
|
-
done = true;
|
|
3368
|
-
break;
|
|
3441
|
+
for (let j = 0, kLen = keys.length; j < kLen; j++) {
|
|
3442
|
+
yield [keys[j], nValue];
|
|
3369
3443
|
}
|
|
3370
3444
|
}
|
|
3371
3445
|
} else {
|
|
@@ -3373,27 +3447,17 @@ var BPTreeAsyncTransaction = class extends BPTreeTransaction {
|
|
|
3373
3447
|
while (i--) {
|
|
3374
3448
|
const nValue = node.values[i];
|
|
3375
3449
|
const keys = node.keys[i];
|
|
3376
|
-
|
|
3377
|
-
|
|
3378
|
-
|
|
3379
|
-
while (j--) {
|
|
3380
|
-
yield [keys[j], nValue];
|
|
3381
|
-
}
|
|
3382
|
-
} else if (earlyTerminate && hasMatched) {
|
|
3383
|
-
done = true;
|
|
3384
|
-
break;
|
|
3450
|
+
let j = keys.length;
|
|
3451
|
+
while (j--) {
|
|
3452
|
+
yield [keys[j], nValue];
|
|
3385
3453
|
}
|
|
3386
3454
|
}
|
|
3387
3455
|
}
|
|
3388
|
-
if (done) {
|
|
3389
|
-
if (nextNodePromise) await nextNodePromise;
|
|
3390
|
-
break;
|
|
3391
|
-
}
|
|
3392
3456
|
if (nextNodePromise) {
|
|
3393
3457
|
node = await nextNodePromise;
|
|
3394
3458
|
nextNodePromise = null;
|
|
3395
3459
|
} else {
|
|
3396
|
-
|
|
3460
|
+
break;
|
|
3397
3461
|
}
|
|
3398
3462
|
}
|
|
3399
3463
|
}
|
|
@@ -3481,49 +3545,36 @@ var BPTreeAsyncTransaction = class extends BPTreeTransaction {
|
|
|
3481
3545
|
}
|
|
3482
3546
|
async *whereStream(condition, options) {
|
|
3483
3547
|
const { filterValues, limit, order = "asc" } = options ?? {};
|
|
3484
|
-
const
|
|
3485
|
-
if (
|
|
3486
|
-
const
|
|
3487
|
-
const
|
|
3488
|
-
|
|
3489
|
-
|
|
3490
|
-
|
|
3491
|
-
|
|
3492
|
-
|
|
3493
|
-
|
|
3494
|
-
|
|
3495
|
-
|
|
3496
|
-
if (
|
|
3497
|
-
|
|
3548
|
+
const conditionKeys = Object.keys(condition);
|
|
3549
|
+
if (conditionKeys.length === 0) return;
|
|
3550
|
+
const resolved = this.resolveStartEndConfigs(condition, order);
|
|
3551
|
+
const direction = resolved.direction;
|
|
3552
|
+
let startNode;
|
|
3553
|
+
if (resolved.startKey) {
|
|
3554
|
+
const startConfig = this.searchConfigs[resolved.startKey][order];
|
|
3555
|
+
startNode = await startConfig.start(this, resolved.startValues);
|
|
3556
|
+
} else {
|
|
3557
|
+
startNode = order === "asc" ? await this.leftestNode() : await this.rightestNode();
|
|
3558
|
+
}
|
|
3559
|
+
let endNode = null;
|
|
3560
|
+
if (resolved.endKey) {
|
|
3561
|
+
const endConfig = this.searchConfigs[resolved.endKey][order];
|
|
3562
|
+
endNode = await endConfig.end(this, resolved.endValues);
|
|
3498
3563
|
}
|
|
3499
3564
|
if (!startNode) return;
|
|
3500
|
-
const comparator = this.verifierMap[driverKey];
|
|
3501
3565
|
const generator = this.getPairsGenerator(
|
|
3502
|
-
value,
|
|
3503
3566
|
startNode,
|
|
3504
3567
|
endNode,
|
|
3505
|
-
|
|
3506
|
-
direction,
|
|
3507
|
-
earlyTerminate
|
|
3568
|
+
direction
|
|
3508
3569
|
);
|
|
3509
3570
|
let count = 0;
|
|
3510
3571
|
const intersection = filterValues && filterValues.size > 0 ? filterValues : null;
|
|
3511
3572
|
for await (const pair of generator) {
|
|
3512
|
-
const [k,
|
|
3573
|
+
const [k, v] = pair;
|
|
3513
3574
|
if (intersection && !intersection.has(k)) {
|
|
3514
3575
|
continue;
|
|
3515
3576
|
}
|
|
3516
|
-
|
|
3517
|
-
for (const key in condition) {
|
|
3518
|
-
if (key === driverKey) continue;
|
|
3519
|
-
const verify = this.verifierMap[key];
|
|
3520
|
-
const condValue = condition[key];
|
|
3521
|
-
if (!verify(v2, condValue)) {
|
|
3522
|
-
isMatch = false;
|
|
3523
|
-
break;
|
|
3524
|
-
}
|
|
3525
|
-
}
|
|
3526
|
-
if (isMatch) {
|
|
3577
|
+
if (this.verify(v, condition)) {
|
|
3527
3578
|
yield pair;
|
|
3528
3579
|
count++;
|
|
3529
3580
|
if (limit !== void 0 && count >= limit) {
|
package/dist/esm/index.mjs
CHANGED
|
@@ -58,39 +58,125 @@ var StringComparator = class extends ValueComparator {
|
|
|
58
58
|
var MVCCStrategy = class {
|
|
59
59
|
};
|
|
60
60
|
var LRUMap = class {
|
|
61
|
-
cache = /* @__PURE__ */ new Map();
|
|
62
61
|
capacity;
|
|
62
|
+
map;
|
|
63
|
+
head = null;
|
|
64
|
+
tail = null;
|
|
65
|
+
/**
|
|
66
|
+
* Creates an instance of LRUMap.
|
|
67
|
+
* @param capacity The maximum number of items the cache can hold.
|
|
68
|
+
*/
|
|
63
69
|
constructor(capacity) {
|
|
64
70
|
this.capacity = capacity;
|
|
71
|
+
this.map = /* @__PURE__ */ new Map();
|
|
65
72
|
}
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
73
|
+
/**
|
|
74
|
+
* Promotes a node to the head of the linked list (marks as most recently used).
|
|
75
|
+
* @param node The node to promote.
|
|
76
|
+
*/
|
|
77
|
+
promote(node) {
|
|
78
|
+
this.extract(node);
|
|
79
|
+
this.prepend(node);
|
|
72
80
|
}
|
|
81
|
+
/**
|
|
82
|
+
* Disconnects a node from the doubly linked list.
|
|
83
|
+
* @param node The node to extract.
|
|
84
|
+
*/
|
|
85
|
+
extract(node) {
|
|
86
|
+
if (node.prev) node.prev.next = node.next;
|
|
87
|
+
else this.head = node.next;
|
|
88
|
+
if (node.next) node.next.prev = node.prev;
|
|
89
|
+
else this.tail = node.prev;
|
|
90
|
+
node.prev = null;
|
|
91
|
+
node.next = null;
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Inserts a node at the head of the doubly linked list.
|
|
95
|
+
* @param node The node to prepend.
|
|
96
|
+
*/
|
|
97
|
+
prepend(node) {
|
|
98
|
+
node.next = this.head;
|
|
99
|
+
if (this.head) this.head.prev = node;
|
|
100
|
+
this.head = node;
|
|
101
|
+
if (!this.tail) this.tail = node;
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Stores or updates a value by key.
|
|
105
|
+
* If the capacity is exceeded, the least recently used item (tail) is removed.
|
|
106
|
+
* @param key The key to store.
|
|
107
|
+
* @param value The value to store.
|
|
108
|
+
*/
|
|
73
109
|
set(key, value) {
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
110
|
+
const existing = this.map.get(key);
|
|
111
|
+
if (existing) {
|
|
112
|
+
existing.value = value;
|
|
113
|
+
this.promote(existing);
|
|
114
|
+
return;
|
|
79
115
|
}
|
|
80
|
-
|
|
81
|
-
|
|
116
|
+
const newNode = { key, value, prev: null, next: null };
|
|
117
|
+
this.map.set(key, newNode);
|
|
118
|
+
this.prepend(newNode);
|
|
119
|
+
if (this.map.size > this.capacity && this.tail) {
|
|
120
|
+
this.map.delete(this.tail.key);
|
|
121
|
+
this.extract(this.tail);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Retrieves a value by key.
|
|
126
|
+
* Accessing the item moves it to the "most recently used" position.
|
|
127
|
+
* @param key The key to look for.
|
|
128
|
+
* @returns The value associated with the key, or undefined if not found.
|
|
129
|
+
*/
|
|
130
|
+
get(key) {
|
|
131
|
+
const node = this.map.get(key);
|
|
132
|
+
if (!node) return void 0;
|
|
133
|
+
this.promote(node);
|
|
134
|
+
return node.value;
|
|
82
135
|
}
|
|
136
|
+
/**
|
|
137
|
+
* Checks if a key exists in the cache without changing its access order.
|
|
138
|
+
* @param key The key to check.
|
|
139
|
+
* @returns True if the key exists, false otherwise.
|
|
140
|
+
*/
|
|
83
141
|
has(key) {
|
|
84
|
-
return this.
|
|
142
|
+
return this.map.has(key);
|
|
85
143
|
}
|
|
144
|
+
/**
|
|
145
|
+
* Removes a key and its associated value from the cache.
|
|
146
|
+
* @param key The key to remove.
|
|
147
|
+
* @returns True if the key was found and removed, false otherwise.
|
|
148
|
+
*/
|
|
86
149
|
delete(key) {
|
|
87
|
-
|
|
150
|
+
const node = this.map.get(key);
|
|
151
|
+
if (!node) return false;
|
|
152
|
+
this.extract(node);
|
|
153
|
+
this.map.delete(key);
|
|
154
|
+
return true;
|
|
88
155
|
}
|
|
89
|
-
|
|
90
|
-
|
|
156
|
+
/**
|
|
157
|
+
* Returns an iterator of keys in the order of most recently used to least recently used.
|
|
158
|
+
* @returns An iterable iterator of keys.
|
|
159
|
+
*/
|
|
160
|
+
*keys() {
|
|
161
|
+
let current = this.head;
|
|
162
|
+
while (current) {
|
|
163
|
+
yield current.key;
|
|
164
|
+
current = current.next;
|
|
165
|
+
}
|
|
91
166
|
}
|
|
167
|
+
/**
|
|
168
|
+
* Returns the current number of items in the cache.
|
|
169
|
+
*/
|
|
92
170
|
get size() {
|
|
93
|
-
return this.
|
|
171
|
+
return this.map.size;
|
|
172
|
+
}
|
|
173
|
+
/**
|
|
174
|
+
* Clears all items from the cache.
|
|
175
|
+
*/
|
|
176
|
+
clear() {
|
|
177
|
+
this.map.clear();
|
|
178
|
+
this.head = null;
|
|
179
|
+
this.tail = null;
|
|
94
180
|
}
|
|
95
181
|
};
|
|
96
182
|
var MVCCTransaction = class {
|
|
@@ -1486,7 +1572,7 @@ var BPTreeTransaction = class _BPTreeTransaction {
|
|
|
1486
1572
|
searchConfigs = {
|
|
1487
1573
|
gt: {
|
|
1488
1574
|
asc: {
|
|
1489
|
-
start: (tx, v) => tx.
|
|
1575
|
+
start: (tx, v) => tx.insertableRightestNodeByPrimary(v[0]),
|
|
1490
1576
|
end: () => null,
|
|
1491
1577
|
direction: 1,
|
|
1492
1578
|
earlyTerminate: false
|
|
@@ -1584,7 +1670,7 @@ var BPTreeTransaction = class _BPTreeTransaction {
|
|
|
1584
1670
|
},
|
|
1585
1671
|
primaryGt: {
|
|
1586
1672
|
asc: {
|
|
1587
|
-
start: (tx, v) => tx.
|
|
1673
|
+
start: (tx, v) => tx.insertableRightestNodeByPrimary(v[0]),
|
|
1588
1674
|
end: () => null,
|
|
1589
1675
|
direction: 1,
|
|
1590
1676
|
earlyTerminate: false
|
|
@@ -1646,7 +1732,7 @@ var BPTreeTransaction = class _BPTreeTransaction {
|
|
|
1646
1732
|
earlyTerminate: true
|
|
1647
1733
|
},
|
|
1648
1734
|
desc: {
|
|
1649
|
-
start: (tx, v) => tx.
|
|
1735
|
+
start: (tx, v) => tx.insertableRightestNodeByPrimary(v[0]),
|
|
1650
1736
|
end: (tx, v) => tx.insertableEndNode(v[0], -1),
|
|
1651
1737
|
direction: -1,
|
|
1652
1738
|
earlyTerminate: true
|
|
@@ -1674,7 +1760,7 @@ var BPTreeTransaction = class _BPTreeTransaction {
|
|
|
1674
1760
|
earlyTerminate: false
|
|
1675
1761
|
},
|
|
1676
1762
|
desc: {
|
|
1677
|
-
start: (tx, v) => tx.
|
|
1763
|
+
start: (tx, v) => tx.insertableRightestNodeByPrimary(tx.highestPrimaryValue(v)),
|
|
1678
1764
|
end: (tx, v) => tx.insertableEndNode(tx.lowestPrimaryValue(v), -1),
|
|
1679
1765
|
direction: -1,
|
|
1680
1766
|
earlyTerminate: false
|
|
@@ -1831,30 +1917,62 @@ var BPTreeTransaction = class _BPTreeTransaction {
|
|
|
1831
1917
|
return JSON.parse(JSON.stringify(node));
|
|
1832
1918
|
}
|
|
1833
1919
|
/**
|
|
1834
|
-
*
|
|
1835
|
-
*
|
|
1836
|
-
*
|
|
1920
|
+
* Resolves the best start/end configuration by independently examining
|
|
1921
|
+
* all conditions. Selects the tightest lower bound for start and the
|
|
1922
|
+
* tightest upper bound for end (in asc; reversed for desc).
|
|
1923
|
+
*
|
|
1837
1924
|
* @param condition The condition to analyze.
|
|
1838
|
-
* @
|
|
1925
|
+
* @param order The sort order ('asc' or 'desc').
|
|
1926
|
+
* @returns The resolved start/end keys, values, and traversal direction.
|
|
1839
1927
|
*/
|
|
1840
|
-
|
|
1841
|
-
|
|
1842
|
-
|
|
1843
|
-
|
|
1844
|
-
|
|
1845
|
-
|
|
1846
|
-
|
|
1847
|
-
|
|
1848
|
-
|
|
1849
|
-
|
|
1850
|
-
|
|
1851
|
-
|
|
1852
|
-
|
|
1853
|
-
|
|
1854
|
-
|
|
1855
|
-
|
|
1856
|
-
|
|
1857
|
-
|
|
1928
|
+
resolveStartEndConfigs(condition, order) {
|
|
1929
|
+
const direction = order === "asc" ? 1 : -1;
|
|
1930
|
+
const startCandidates = order === "asc" ? _BPTreeTransaction._lowerBoundKeys : _BPTreeTransaction._upperBoundKeys;
|
|
1931
|
+
const endCandidates = order === "asc" ? _BPTreeTransaction._upperBoundKeys : _BPTreeTransaction._lowerBoundKeys;
|
|
1932
|
+
let startKey = null;
|
|
1933
|
+
let endKey = null;
|
|
1934
|
+
let startValues = [];
|
|
1935
|
+
let endValues = [];
|
|
1936
|
+
for (const key of startCandidates) {
|
|
1937
|
+
if (key in condition) {
|
|
1938
|
+
startKey = key;
|
|
1939
|
+
startValues = this.ensureValues(condition[key]);
|
|
1940
|
+
break;
|
|
1941
|
+
}
|
|
1942
|
+
}
|
|
1943
|
+
for (const key of endCandidates) {
|
|
1944
|
+
if (key in condition) {
|
|
1945
|
+
endKey = key;
|
|
1946
|
+
endValues = this.ensureValues(condition[key]);
|
|
1947
|
+
break;
|
|
1948
|
+
}
|
|
1949
|
+
}
|
|
1950
|
+
return { startKey, endKey, startValues, endValues, direction };
|
|
1951
|
+
}
|
|
1952
|
+
// Lower bound providers, ordered by selectivity (tightest first)
|
|
1953
|
+
// Used for asc start / desc end
|
|
1954
|
+
static _lowerBoundKeys = [
|
|
1955
|
+
"primaryEqual",
|
|
1956
|
+
"equal",
|
|
1957
|
+
"primaryGt",
|
|
1958
|
+
"gt",
|
|
1959
|
+
"primaryGte",
|
|
1960
|
+
"gte",
|
|
1961
|
+
"primaryOr",
|
|
1962
|
+
"or"
|
|
1963
|
+
];
|
|
1964
|
+
// Upper bound providers, ordered by selectivity (tightest first)
|
|
1965
|
+
// Used for asc end / desc start
|
|
1966
|
+
static _upperBoundKeys = [
|
|
1967
|
+
"primaryEqual",
|
|
1968
|
+
"equal",
|
|
1969
|
+
"primaryLt",
|
|
1970
|
+
"lt",
|
|
1971
|
+
"primaryLte",
|
|
1972
|
+
"lte",
|
|
1973
|
+
"primaryOr",
|
|
1974
|
+
"or"
|
|
1975
|
+
];
|
|
1858
1976
|
constructor(rootTx, mvccRoot, mvcc, strategy, comparator, option) {
|
|
1859
1977
|
this.rootTx = rootTx === null ? this : rootTx;
|
|
1860
1978
|
this.mvccRoot = mvccRoot;
|
|
@@ -2125,7 +2243,7 @@ var BPTreeSyncTransaction = class extends BPTreeTransaction {
|
|
|
2125
2243
|
return this.getNode(node.next);
|
|
2126
2244
|
}
|
|
2127
2245
|
insertableEndNode(value, direction) {
|
|
2128
|
-
const insertableNode = this.
|
|
2246
|
+
const insertableNode = direction === -1 ? this.insertableNodeByPrimary(value) : this.insertableRightestNodeByPrimary(value);
|
|
2129
2247
|
let key;
|
|
2130
2248
|
switch (direction) {
|
|
2131
2249
|
case -1:
|
|
@@ -2162,13 +2280,10 @@ var BPTreeSyncTransaction = class extends BPTreeTransaction {
|
|
|
2162
2280
|
}
|
|
2163
2281
|
return node;
|
|
2164
2282
|
}
|
|
2165
|
-
*getPairsGenerator(
|
|
2283
|
+
*getPairsGenerator(startNode, endNode, direction) {
|
|
2166
2284
|
let node = startNode;
|
|
2167
|
-
|
|
2168
|
-
let hasMatched = false;
|
|
2169
|
-
while (!done) {
|
|
2285
|
+
while (true) {
|
|
2170
2286
|
if (endNode && node.id === endNode.id) {
|
|
2171
|
-
done = true;
|
|
2172
2287
|
break;
|
|
2173
2288
|
}
|
|
2174
2289
|
const len = node.values.length;
|
|
@@ -2176,14 +2291,8 @@ var BPTreeSyncTransaction = class extends BPTreeTransaction {
|
|
|
2176
2291
|
for (let i = 0; i < len; i++) {
|
|
2177
2292
|
const nValue = node.values[i];
|
|
2178
2293
|
const keys = node.keys[i];
|
|
2179
|
-
|
|
2180
|
-
|
|
2181
|
-
for (let j = 0; j < keys.length; j++) {
|
|
2182
|
-
yield [keys[j], nValue];
|
|
2183
|
-
}
|
|
2184
|
-
} else if (earlyTerminate && hasMatched) {
|
|
2185
|
-
done = true;
|
|
2186
|
-
break;
|
|
2294
|
+
for (let j = 0, kLen = keys.length; j < kLen; j++) {
|
|
2295
|
+
yield [keys[j], nValue];
|
|
2187
2296
|
}
|
|
2188
2297
|
}
|
|
2189
2298
|
} else {
|
|
@@ -2191,30 +2300,17 @@ var BPTreeSyncTransaction = class extends BPTreeTransaction {
|
|
|
2191
2300
|
while (i--) {
|
|
2192
2301
|
const nValue = node.values[i];
|
|
2193
2302
|
const keys = node.keys[i];
|
|
2194
|
-
|
|
2195
|
-
|
|
2196
|
-
|
|
2197
|
-
while (j--) {
|
|
2198
|
-
yield [keys[j], nValue];
|
|
2199
|
-
}
|
|
2200
|
-
} else if (earlyTerminate && hasMatched) {
|
|
2201
|
-
done = true;
|
|
2202
|
-
break;
|
|
2303
|
+
let j = keys.length;
|
|
2304
|
+
while (j--) {
|
|
2305
|
+
yield [keys[j], nValue];
|
|
2203
2306
|
}
|
|
2204
2307
|
}
|
|
2205
2308
|
}
|
|
2206
|
-
if (done) break;
|
|
2207
2309
|
if (direction === 1) {
|
|
2208
|
-
if (!node.next)
|
|
2209
|
-
done = true;
|
|
2210
|
-
break;
|
|
2211
|
-
}
|
|
2310
|
+
if (!node.next) break;
|
|
2212
2311
|
node = this.getNode(node.next);
|
|
2213
2312
|
} else {
|
|
2214
|
-
if (!node.prev)
|
|
2215
|
-
done = true;
|
|
2216
|
-
break;
|
|
2217
|
-
}
|
|
2313
|
+
if (!node.prev) break;
|
|
2218
2314
|
node = this.getNode(node.prev);
|
|
2219
2315
|
}
|
|
2220
2316
|
}
|
|
@@ -2303,49 +2399,36 @@ var BPTreeSyncTransaction = class extends BPTreeTransaction {
|
|
|
2303
2399
|
}
|
|
2304
2400
|
*whereStream(condition, options) {
|
|
2305
2401
|
const { filterValues, limit, order = "asc" } = options ?? {};
|
|
2306
|
-
const
|
|
2307
|
-
if (
|
|
2308
|
-
const
|
|
2309
|
-
const
|
|
2310
|
-
|
|
2311
|
-
|
|
2312
|
-
|
|
2313
|
-
|
|
2314
|
-
|
|
2315
|
-
|
|
2316
|
-
|
|
2317
|
-
|
|
2318
|
-
if (
|
|
2319
|
-
|
|
2402
|
+
const conditionKeys = Object.keys(condition);
|
|
2403
|
+
if (conditionKeys.length === 0) return;
|
|
2404
|
+
const resolved = this.resolveStartEndConfigs(condition, order);
|
|
2405
|
+
const direction = resolved.direction;
|
|
2406
|
+
let startNode;
|
|
2407
|
+
if (resolved.startKey) {
|
|
2408
|
+
const startConfig = this.searchConfigs[resolved.startKey][order];
|
|
2409
|
+
startNode = startConfig.start(this, resolved.startValues);
|
|
2410
|
+
} else {
|
|
2411
|
+
startNode = order === "asc" ? this.leftestNode() : this.rightestNode();
|
|
2412
|
+
}
|
|
2413
|
+
let endNode = null;
|
|
2414
|
+
if (resolved.endKey) {
|
|
2415
|
+
const endConfig = this.searchConfigs[resolved.endKey][order];
|
|
2416
|
+
endNode = endConfig.end(this, resolved.endValues);
|
|
2320
2417
|
}
|
|
2321
2418
|
if (!startNode) return;
|
|
2322
|
-
const comparator = this.verifierMap[driverKey];
|
|
2323
2419
|
const generator = this.getPairsGenerator(
|
|
2324
|
-
value,
|
|
2325
2420
|
startNode,
|
|
2326
2421
|
endNode,
|
|
2327
|
-
|
|
2328
|
-
direction,
|
|
2329
|
-
earlyTerminate
|
|
2422
|
+
direction
|
|
2330
2423
|
);
|
|
2331
2424
|
let count = 0;
|
|
2332
2425
|
const intersection = filterValues && filterValues.size > 0 ? filterValues : null;
|
|
2333
2426
|
for (const pair of generator) {
|
|
2334
|
-
const [k,
|
|
2427
|
+
const [k, v] = pair;
|
|
2335
2428
|
if (intersection && !intersection.has(k)) {
|
|
2336
2429
|
continue;
|
|
2337
2430
|
}
|
|
2338
|
-
|
|
2339
|
-
for (const key in condition) {
|
|
2340
|
-
if (key === driverKey) continue;
|
|
2341
|
-
const verify = this.verifierMap[key];
|
|
2342
|
-
const condValue = condition[key];
|
|
2343
|
-
if (!verify(v2, condValue)) {
|
|
2344
|
-
isMatch = false;
|
|
2345
|
-
break;
|
|
2346
|
-
}
|
|
2347
|
-
}
|
|
2348
|
-
if (isMatch) {
|
|
2431
|
+
if (this.verify(v, condition)) {
|
|
2349
2432
|
yield pair;
|
|
2350
2433
|
count++;
|
|
2351
2434
|
if (limit !== void 0 && count >= limit) {
|
|
@@ -3261,7 +3344,7 @@ var BPTreeAsyncTransaction = class extends BPTreeTransaction {
|
|
|
3261
3344
|
return await this.getNode(node.next);
|
|
3262
3345
|
}
|
|
3263
3346
|
async insertableEndNode(value, direction) {
|
|
3264
|
-
const insertableNode = await this.
|
|
3347
|
+
const insertableNode = direction === -1 ? await this.insertableNodeByPrimary(value) : await this.insertableRightestNodeByPrimary(value);
|
|
3265
3348
|
let key;
|
|
3266
3349
|
switch (direction) {
|
|
3267
3350
|
case -1:
|
|
@@ -3298,22 +3381,19 @@ var BPTreeAsyncTransaction = class extends BPTreeTransaction {
|
|
|
3298
3381
|
}
|
|
3299
3382
|
return node;
|
|
3300
3383
|
}
|
|
3301
|
-
async *getPairsGenerator(
|
|
3384
|
+
async *getPairsGenerator(startNode, endNode, direction) {
|
|
3302
3385
|
let node = startNode;
|
|
3303
|
-
let done = false;
|
|
3304
|
-
let hasMatched = false;
|
|
3305
3386
|
let nextNodePromise = null;
|
|
3306
|
-
while (
|
|
3387
|
+
while (true) {
|
|
3307
3388
|
if (endNode && node.id === endNode.id) {
|
|
3308
|
-
done = true;
|
|
3309
3389
|
break;
|
|
3310
3390
|
}
|
|
3311
3391
|
if (direction === 1) {
|
|
3312
|
-
if (node.next
|
|
3392
|
+
if (node.next) {
|
|
3313
3393
|
nextNodePromise = this.getNode(node.next);
|
|
3314
3394
|
}
|
|
3315
3395
|
} else {
|
|
3316
|
-
if (node.prev
|
|
3396
|
+
if (node.prev) {
|
|
3317
3397
|
nextNodePromise = this.getNode(node.prev);
|
|
3318
3398
|
}
|
|
3319
3399
|
}
|
|
@@ -3322,14 +3402,8 @@ var BPTreeAsyncTransaction = class extends BPTreeTransaction {
|
|
|
3322
3402
|
for (let i = 0; i < len; i++) {
|
|
3323
3403
|
const nValue = node.values[i];
|
|
3324
3404
|
const keys = node.keys[i];
|
|
3325
|
-
|
|
3326
|
-
|
|
3327
|
-
for (let j = 0; j < keys.length; j++) {
|
|
3328
|
-
yield [keys[j], nValue];
|
|
3329
|
-
}
|
|
3330
|
-
} else if (earlyTerminate && hasMatched) {
|
|
3331
|
-
done = true;
|
|
3332
|
-
break;
|
|
3405
|
+
for (let j = 0, kLen = keys.length; j < kLen; j++) {
|
|
3406
|
+
yield [keys[j], nValue];
|
|
3333
3407
|
}
|
|
3334
3408
|
}
|
|
3335
3409
|
} else {
|
|
@@ -3337,27 +3411,17 @@ var BPTreeAsyncTransaction = class extends BPTreeTransaction {
|
|
|
3337
3411
|
while (i--) {
|
|
3338
3412
|
const nValue = node.values[i];
|
|
3339
3413
|
const keys = node.keys[i];
|
|
3340
|
-
|
|
3341
|
-
|
|
3342
|
-
|
|
3343
|
-
while (j--) {
|
|
3344
|
-
yield [keys[j], nValue];
|
|
3345
|
-
}
|
|
3346
|
-
} else if (earlyTerminate && hasMatched) {
|
|
3347
|
-
done = true;
|
|
3348
|
-
break;
|
|
3414
|
+
let j = keys.length;
|
|
3415
|
+
while (j--) {
|
|
3416
|
+
yield [keys[j], nValue];
|
|
3349
3417
|
}
|
|
3350
3418
|
}
|
|
3351
3419
|
}
|
|
3352
|
-
if (done) {
|
|
3353
|
-
if (nextNodePromise) await nextNodePromise;
|
|
3354
|
-
break;
|
|
3355
|
-
}
|
|
3356
3420
|
if (nextNodePromise) {
|
|
3357
3421
|
node = await nextNodePromise;
|
|
3358
3422
|
nextNodePromise = null;
|
|
3359
3423
|
} else {
|
|
3360
|
-
|
|
3424
|
+
break;
|
|
3361
3425
|
}
|
|
3362
3426
|
}
|
|
3363
3427
|
}
|
|
@@ -3445,49 +3509,36 @@ var BPTreeAsyncTransaction = class extends BPTreeTransaction {
|
|
|
3445
3509
|
}
|
|
3446
3510
|
async *whereStream(condition, options) {
|
|
3447
3511
|
const { filterValues, limit, order = "asc" } = options ?? {};
|
|
3448
|
-
const
|
|
3449
|
-
if (
|
|
3450
|
-
const
|
|
3451
|
-
const
|
|
3452
|
-
|
|
3453
|
-
|
|
3454
|
-
|
|
3455
|
-
|
|
3456
|
-
|
|
3457
|
-
|
|
3458
|
-
|
|
3459
|
-
|
|
3460
|
-
if (
|
|
3461
|
-
|
|
3512
|
+
const conditionKeys = Object.keys(condition);
|
|
3513
|
+
if (conditionKeys.length === 0) return;
|
|
3514
|
+
const resolved = this.resolveStartEndConfigs(condition, order);
|
|
3515
|
+
const direction = resolved.direction;
|
|
3516
|
+
let startNode;
|
|
3517
|
+
if (resolved.startKey) {
|
|
3518
|
+
const startConfig = this.searchConfigs[resolved.startKey][order];
|
|
3519
|
+
startNode = await startConfig.start(this, resolved.startValues);
|
|
3520
|
+
} else {
|
|
3521
|
+
startNode = order === "asc" ? await this.leftestNode() : await this.rightestNode();
|
|
3522
|
+
}
|
|
3523
|
+
let endNode = null;
|
|
3524
|
+
if (resolved.endKey) {
|
|
3525
|
+
const endConfig = this.searchConfigs[resolved.endKey][order];
|
|
3526
|
+
endNode = await endConfig.end(this, resolved.endValues);
|
|
3462
3527
|
}
|
|
3463
3528
|
if (!startNode) return;
|
|
3464
|
-
const comparator = this.verifierMap[driverKey];
|
|
3465
3529
|
const generator = this.getPairsGenerator(
|
|
3466
|
-
value,
|
|
3467
3530
|
startNode,
|
|
3468
3531
|
endNode,
|
|
3469
|
-
|
|
3470
|
-
direction,
|
|
3471
|
-
earlyTerminate
|
|
3532
|
+
direction
|
|
3472
3533
|
);
|
|
3473
3534
|
let count = 0;
|
|
3474
3535
|
const intersection = filterValues && filterValues.size > 0 ? filterValues : null;
|
|
3475
3536
|
for await (const pair of generator) {
|
|
3476
|
-
const [k,
|
|
3537
|
+
const [k, v] = pair;
|
|
3477
3538
|
if (intersection && !intersection.has(k)) {
|
|
3478
3539
|
continue;
|
|
3479
3540
|
}
|
|
3480
|
-
|
|
3481
|
-
for (const key in condition) {
|
|
3482
|
-
if (key === driverKey) continue;
|
|
3483
|
-
const verify = this.verifierMap[key];
|
|
3484
|
-
const condValue = condition[key];
|
|
3485
|
-
if (!verify(v2, condValue)) {
|
|
3486
|
-
isMatch = false;
|
|
3487
|
-
break;
|
|
3488
|
-
}
|
|
3489
|
-
}
|
|
3490
|
-
if (isMatch) {
|
|
3541
|
+
if (this.verify(v, condition)) {
|
|
3491
3542
|
yield pair;
|
|
3492
3543
|
count++;
|
|
3493
3544
|
if (limit !== void 0 && count >= limit) {
|
|
@@ -86,13 +86,23 @@ export declare abstract class BPTreeTransaction<K, V> {
|
|
|
86
86
|
protected _insertValueIntoLeaf(leaf: BPTreeLeafNode<K, V>, key: K, value: V): boolean;
|
|
87
87
|
protected _cloneNode<T extends BPTreeUnknownNode<K, V>>(node: T): T;
|
|
88
88
|
/**
|
|
89
|
-
*
|
|
90
|
-
*
|
|
89
|
+
* Resolves the best start/end configuration by independently examining
|
|
90
|
+
* all conditions. Selects the tightest lower bound for start and the
|
|
91
|
+
* tightest upper bound for end (in asc; reversed for desc).
|
|
91
92
|
*
|
|
92
93
|
* @param condition The condition to analyze.
|
|
93
|
-
* @
|
|
94
|
-
|
|
95
|
-
|
|
94
|
+
* @param order The sort order ('asc' or 'desc').
|
|
95
|
+
* @returns The resolved start/end keys, values, and traversal direction.
|
|
96
|
+
*/
|
|
97
|
+
resolveStartEndConfigs(condition: BPTreeCondition<V>, order: 'asc' | 'desc'): {
|
|
98
|
+
startKey: keyof BPTreeCondition<V> | null;
|
|
99
|
+
endKey: keyof BPTreeCondition<V> | null;
|
|
100
|
+
startValues: V[];
|
|
101
|
+
endValues: V[];
|
|
102
|
+
direction: 1 | -1;
|
|
103
|
+
};
|
|
104
|
+
private static readonly _lowerBoundKeys;
|
|
105
|
+
private static readonly _upperBoundKeys;
|
|
96
106
|
protected constructor(rootTx: BPTreeTransaction<K, V> | null, mvccRoot: BPTreeMVCC<K, V>, mvcc: BPTreeMVCC<K, V>, strategy: SerializeStrategy<K, V>, comparator: ValueComparator<V>, option?: BPTreeConstructorOption);
|
|
97
107
|
protected abstract _createNode(leaf: boolean, keys: string[] | K[][], values: V[], parent?: string | null, next?: string | null, prev?: string | null): Deferred<BPTreeUnknownNode<K, V>>;
|
|
98
108
|
protected abstract _deleteEntry(node: BPTreeUnknownNode<K, V>, key: BPTreeNodeKey<K>): Deferred<BPTreeUnknownNode<K, V>>;
|
|
@@ -32,7 +32,7 @@ export declare class BPTreeAsyncTransaction<K, V> extends BPTreeTransaction<K, V
|
|
|
32
32
|
protected insertableEndNode(value: V, direction: 1 | -1): Promise<BPTreeLeafNode<K, V> | null>;
|
|
33
33
|
protected leftestNode(): Promise<BPTreeLeafNode<K, V>>;
|
|
34
34
|
protected rightestNode(): Promise<BPTreeLeafNode<K, V>>;
|
|
35
|
-
protected getPairsGenerator(
|
|
35
|
+
protected getPairsGenerator(startNode: BPTreeLeafNode<K, V>, endNode: BPTreeLeafNode<K, V> | null, direction: 1 | -1): AsyncGenerator<[K, V]>;
|
|
36
36
|
init(): Promise<void>;
|
|
37
37
|
protected _initInternal(): Promise<void>;
|
|
38
38
|
exists(key: K, value: V): Promise<boolean>;
|
|
@@ -29,7 +29,7 @@ export declare class BPTreeSyncTransaction<K, V> extends BPTreeTransaction<K, V>
|
|
|
29
29
|
protected insertableEndNode(value: V, direction: 1 | -1): BPTreeLeafNode<K, V> | null;
|
|
30
30
|
protected leftestNode(): BPTreeLeafNode<K, V>;
|
|
31
31
|
protected rightestNode(): BPTreeLeafNode<K, V>;
|
|
32
|
-
protected getPairsGenerator(
|
|
32
|
+
protected getPairsGenerator(startNode: BPTreeLeafNode<K, V>, endNode: BPTreeLeafNode<K, V> | null, direction: 1 | -1): Generator<[K, V]>;
|
|
33
33
|
init(): void;
|
|
34
34
|
protected _initInternal(): void;
|
|
35
35
|
exists(key: K, value: V): boolean;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "serializable-bptree",
|
|
3
|
-
"version": "8.3.
|
|
3
|
+
"version": "8.3.4",
|
|
4
4
|
"description": "Store the B+tree flexibly, not only in-memory.",
|
|
5
5
|
"types": "./dist/types/index.d.ts",
|
|
6
6
|
"main": "./dist/cjs/index.cjs",
|
|
@@ -44,7 +44,7 @@
|
|
|
44
44
|
"typescript": "^5.9.3"
|
|
45
45
|
},
|
|
46
46
|
"dependencies": {
|
|
47
|
-
"mvcc-api": "^1.3.
|
|
47
|
+
"mvcc-api": "^1.3.5",
|
|
48
48
|
"ryoiki": "^1.2.0"
|
|
49
49
|
}
|
|
50
|
-
}
|
|
50
|
+
}
|