serializable-bptree 6.1.1 → 6.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +34 -2
- package/dist/cjs/index.cjs +348 -202
- package/dist/esm/index.mjs +348 -202
- package/dist/types/BPTreeAsync.d.ts +11 -3
- package/dist/types/BPTreeSync.d.ts +11 -3
- package/dist/types/base/BPTree.d.ts +37 -3
- package/package.json +1 -1
package/dist/cjs/index.cjs
CHANGED
|
@@ -466,7 +466,7 @@ var CacheEntanglementAsync = class extends CacheEntanglement {
|
|
|
466
466
|
};
|
|
467
467
|
|
|
468
468
|
// src/base/BPTree.ts
|
|
469
|
-
var BPTree = class {
|
|
469
|
+
var BPTree = class _BPTree {
|
|
470
470
|
_cachedRegexp;
|
|
471
471
|
strategy;
|
|
472
472
|
comparator;
|
|
@@ -578,6 +578,82 @@ var BPTree = class {
|
|
|
578
578
|
primaryOr: false,
|
|
579
579
|
like: false
|
|
580
580
|
};
|
|
581
|
+
/**
|
|
582
|
+
* Priority map for condition types.
|
|
583
|
+
* Higher value = higher selectivity (fewer expected results).
|
|
584
|
+
* Used by `chooseDriver` to select the most selective index.
|
|
585
|
+
*/
|
|
586
|
+
static conditionPriority = {
|
|
587
|
+
equal: 100,
|
|
588
|
+
primaryEqual: 100,
|
|
589
|
+
or: 80,
|
|
590
|
+
primaryOr: 80,
|
|
591
|
+
gt: 50,
|
|
592
|
+
gte: 50,
|
|
593
|
+
lt: 50,
|
|
594
|
+
lte: 50,
|
|
595
|
+
primaryGt: 50,
|
|
596
|
+
primaryGte: 50,
|
|
597
|
+
primaryLt: 50,
|
|
598
|
+
primaryLte: 50,
|
|
599
|
+
like: 30,
|
|
600
|
+
notEqual: 10,
|
|
601
|
+
primaryNotEqual: 10
|
|
602
|
+
};
|
|
603
|
+
/**
|
|
604
|
+
* Selects the best driver tree from multiple tree/condition pairs.
|
|
605
|
+
* Uses rule-based optimization to choose the tree with highest estimated selectivity.
|
|
606
|
+
*
|
|
607
|
+
* @param candidates Array of { tree, condition } pairs to evaluate
|
|
608
|
+
* @returns The candidate with highest priority condition, or null if empty
|
|
609
|
+
*
|
|
610
|
+
* @example
|
|
611
|
+
* ```typescript
|
|
612
|
+
* const driver = BPTreeSync.chooseDriver([
|
|
613
|
+
* { tree: idxId, condition: { equal: 100 } },
|
|
614
|
+
* { tree: idxAge, condition: { gt: 20 } }
|
|
615
|
+
* ])
|
|
616
|
+
* // Returns { tree: idxId, condition: { equal: 100 } } because 'equal' has higher priority
|
|
617
|
+
* ```
|
|
618
|
+
*/
|
|
619
|
+
static ChooseDriver(candidates) {
|
|
620
|
+
if (candidates.length === 0) return null;
|
|
621
|
+
if (candidates.length === 1) return candidates[0];
|
|
622
|
+
let best = candidates[0];
|
|
623
|
+
let bestScore = 0;
|
|
624
|
+
for (const candidate of candidates) {
|
|
625
|
+
let score = 0;
|
|
626
|
+
for (const key in candidate.condition) {
|
|
627
|
+
const condKey = key;
|
|
628
|
+
const priority = _BPTree.conditionPriority[condKey] ?? 0;
|
|
629
|
+
if (priority > score) {
|
|
630
|
+
score = priority;
|
|
631
|
+
}
|
|
632
|
+
}
|
|
633
|
+
if (score > bestScore) {
|
|
634
|
+
bestScore = score;
|
|
635
|
+
best = candidate;
|
|
636
|
+
}
|
|
637
|
+
}
|
|
638
|
+
return best;
|
|
639
|
+
}
|
|
640
|
+
/**
|
|
641
|
+
* Verified if the value satisfies the condition.
|
|
642
|
+
*
|
|
643
|
+
* @param nodeValue The value to verify.
|
|
644
|
+
* @param condition The condition to verify against.
|
|
645
|
+
* @returns Returns true if the value satisfies the condition.
|
|
646
|
+
*/
|
|
647
|
+
verify(nodeValue, condition) {
|
|
648
|
+
for (const key in condition) {
|
|
649
|
+
const verify = this.verifierMap[key];
|
|
650
|
+
const condValue = condition[key];
|
|
651
|
+
if (!verify(nodeValue, condValue)) {
|
|
652
|
+
return false;
|
|
653
|
+
}
|
|
654
|
+
}
|
|
655
|
+
return true;
|
|
656
|
+
}
|
|
581
657
|
constructor(strategy, comparator, option) {
|
|
582
658
|
this.strategy = strategy;
|
|
583
659
|
this.comparator = comparator;
|
|
@@ -698,8 +774,7 @@ var BPTreeSync = class extends BPTree {
|
|
|
698
774
|
capacity: this.option.capacity ?? 1e3
|
|
699
775
|
});
|
|
700
776
|
}
|
|
701
|
-
|
|
702
|
-
const pairs = [];
|
|
777
|
+
*getPairsGenerator(value, startNode, endNode, comparator, direction, earlyTerminate) {
|
|
703
778
|
let node = startNode;
|
|
704
779
|
let done = false;
|
|
705
780
|
let hasMatched = false;
|
|
@@ -708,71 +783,52 @@ var BPTreeSync = class extends BPTree {
|
|
|
708
783
|
done = true;
|
|
709
784
|
break;
|
|
710
785
|
}
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
786
|
+
const len = node.values.length;
|
|
787
|
+
if (direction === 1) {
|
|
788
|
+
for (let i = 0; i < len; i++) {
|
|
789
|
+
const nValue = node.values[i];
|
|
790
|
+
const keys = node.keys[i];
|
|
791
|
+
if (comparator(nValue, value)) {
|
|
792
|
+
hasMatched = true;
|
|
793
|
+
for (let j = 0; j < keys.length; j++) {
|
|
794
|
+
yield [keys[j], nValue];
|
|
795
|
+
}
|
|
796
|
+
} else if (earlyTerminate && hasMatched) {
|
|
797
|
+
done = true;
|
|
798
|
+
break;
|
|
799
|
+
}
|
|
800
|
+
}
|
|
801
|
+
} else {
|
|
802
|
+
let i = len;
|
|
803
|
+
while (i--) {
|
|
804
|
+
const nValue = node.values[i];
|
|
805
|
+
const keys = node.keys[i];
|
|
806
|
+
if (comparator(nValue, value)) {
|
|
807
|
+
hasMatched = true;
|
|
808
|
+
let j = keys.length;
|
|
809
|
+
while (j--) {
|
|
810
|
+
yield [keys[j], nValue];
|
|
811
|
+
}
|
|
812
|
+
} else if (earlyTerminate && hasMatched) {
|
|
813
|
+
done = true;
|
|
814
|
+
break;
|
|
720
815
|
}
|
|
721
|
-
} else if (earlyTerminate && hasMatched) {
|
|
722
|
-
done = true;
|
|
723
|
-
break;
|
|
724
816
|
}
|
|
725
817
|
}
|
|
726
818
|
if (done) break;
|
|
727
|
-
if (
|
|
728
|
-
|
|
729
|
-
break;
|
|
730
|
-
}
|
|
731
|
-
node = this.getNode(node.prev);
|
|
732
|
-
}
|
|
733
|
-
return new Map(pairs.reverse());
|
|
734
|
-
}
|
|
735
|
-
getPairsLeftToRight(value, startNode, endNode, comparator, earlyTerminate) {
|
|
736
|
-
const pairs = [];
|
|
737
|
-
let node = startNode;
|
|
738
|
-
let done = false;
|
|
739
|
-
let hasMatched = false;
|
|
740
|
-
while (!done) {
|
|
741
|
-
if (endNode && node.id === endNode.id) {
|
|
742
|
-
done = true;
|
|
743
|
-
break;
|
|
744
|
-
}
|
|
745
|
-
for (let i = 0, len = node.values.length; i < len; i++) {
|
|
746
|
-
const nValue = node.values[i];
|
|
747
|
-
const keys = node.keys[i];
|
|
748
|
-
if (comparator(nValue, value)) {
|
|
749
|
-
hasMatched = true;
|
|
750
|
-
for (let j = 0, len2 = keys.length; j < len2; j++) {
|
|
751
|
-
const key = keys[j];
|
|
752
|
-
pairs.push([key, nValue]);
|
|
753
|
-
}
|
|
754
|
-
} else if (earlyTerminate && hasMatched) {
|
|
819
|
+
if (direction === 1) {
|
|
820
|
+
if (!node.next) {
|
|
755
821
|
done = true;
|
|
756
822
|
break;
|
|
757
823
|
}
|
|
824
|
+
node = this.getNode(node.next);
|
|
825
|
+
} else {
|
|
826
|
+
if (!node.prev) {
|
|
827
|
+
done = true;
|
|
828
|
+
break;
|
|
829
|
+
}
|
|
830
|
+
node = this.getNode(node.prev);
|
|
758
831
|
}
|
|
759
|
-
if (done) break;
|
|
760
|
-
if (!node.next) {
|
|
761
|
-
done = true;
|
|
762
|
-
break;
|
|
763
|
-
}
|
|
764
|
-
node = this.getNode(node.next);
|
|
765
|
-
}
|
|
766
|
-
return new Map(pairs);
|
|
767
|
-
}
|
|
768
|
-
getPairs(value, startNode, endNode, comparator, direction, earlyTerminate) {
|
|
769
|
-
switch (direction) {
|
|
770
|
-
case -1:
|
|
771
|
-
return this.getPairsRightToLeft(value, startNode, endNode, comparator, earlyTerminate);
|
|
772
|
-
case 1:
|
|
773
|
-
return this.getPairsLeftToRight(value, startNode, endNode, comparator, earlyTerminate);
|
|
774
|
-
default:
|
|
775
|
-
throw new Error(`Direction must be -1 or 1. but got a ${direction}`);
|
|
776
832
|
}
|
|
777
833
|
}
|
|
778
834
|
_createNodeId(isLeaf) {
|
|
@@ -1228,55 +1284,109 @@ var BPTreeSync = class extends BPTree {
|
|
|
1228
1284
|
}
|
|
1229
1285
|
this._nodeDeleteBuffer.clear();
|
|
1230
1286
|
}
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
if (
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
|
|
1287
|
+
/**
|
|
1288
|
+
* Retrieves the value associated with the given key (PK).
|
|
1289
|
+
* Note: This method performs a full scan of leaf nodes as the tree is ordered by Value, not Key.
|
|
1290
|
+
*
|
|
1291
|
+
* @param key The key to search for.
|
|
1292
|
+
* @returns The value associated with the key, or undefined if not found.
|
|
1293
|
+
*/
|
|
1294
|
+
get(key) {
|
|
1295
|
+
let node = this.leftestNode();
|
|
1296
|
+
while (true) {
|
|
1297
|
+
if (node.values) {
|
|
1298
|
+
const len = node.values.length;
|
|
1299
|
+
for (let i = 0; i < len; i++) {
|
|
1300
|
+
const keys = node.keys[i];
|
|
1301
|
+
for (let j = 0; j < keys.length; j++) {
|
|
1302
|
+
if (keys[j] === key) {
|
|
1303
|
+
return node.values[i];
|
|
1304
|
+
}
|
|
1249
1305
|
}
|
|
1250
1306
|
}
|
|
1251
|
-
filterValues = intersections;
|
|
1252
1307
|
}
|
|
1308
|
+
if (!node.next) break;
|
|
1309
|
+
node = this.getNode(node.next);
|
|
1253
1310
|
}
|
|
1254
|
-
return
|
|
1311
|
+
return void 0;
|
|
1255
1312
|
}
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
|
|
1313
|
+
*keysStream(condition, filterValues, limit) {
|
|
1314
|
+
const stream = this.whereStream(condition, limit);
|
|
1315
|
+
const intersection = filterValues && filterValues.size > 0 ? filterValues : null;
|
|
1316
|
+
for (const [key] of stream) {
|
|
1317
|
+
if (intersection && !intersection.has(key)) {
|
|
1318
|
+
continue;
|
|
1319
|
+
}
|
|
1320
|
+
yield key;
|
|
1321
|
+
}
|
|
1322
|
+
}
|
|
1323
|
+
*whereStream(condition, limit) {
|
|
1324
|
+
let driverKey = null;
|
|
1325
|
+
if ("primaryEqual" in condition) driverKey = "primaryEqual";
|
|
1326
|
+
else if ("equal" in condition) driverKey = "equal";
|
|
1327
|
+
else if ("gt" in condition) driverKey = "gt";
|
|
1328
|
+
else if ("gte" in condition) driverKey = "gte";
|
|
1329
|
+
else if ("lt" in condition) driverKey = "lt";
|
|
1330
|
+
else if ("lte" in condition) driverKey = "lte";
|
|
1331
|
+
else if ("primaryGt" in condition) driverKey = "primaryGt";
|
|
1332
|
+
else if ("primaryGte" in condition) driverKey = "primaryGte";
|
|
1333
|
+
else if ("primaryLt" in condition) driverKey = "primaryLt";
|
|
1334
|
+
else if ("primaryLte" in condition) driverKey = "primaryLte";
|
|
1335
|
+
else if ("like" in condition) driverKey = "like";
|
|
1336
|
+
else if ("notEqual" in condition) driverKey = "notEqual";
|
|
1337
|
+
else if ("primaryNotEqual" in condition) driverKey = "primaryNotEqual";
|
|
1338
|
+
else if ("or" in condition) driverKey = "or";
|
|
1339
|
+
else if ("primaryOr" in condition) driverKey = "primaryOr";
|
|
1340
|
+
if (!driverKey) return;
|
|
1341
|
+
const value = condition[driverKey];
|
|
1342
|
+
const startNode = this.verifierStartNode[driverKey](value);
|
|
1343
|
+
const endNode = this.verifierEndNode[driverKey](value);
|
|
1344
|
+
const direction = this.verifierDirection[driverKey];
|
|
1345
|
+
const comparator = this.verifierMap[driverKey];
|
|
1346
|
+
const earlyTerminate = this.verifierEarlyTerminate[driverKey];
|
|
1347
|
+
const generator = this.getPairsGenerator(
|
|
1348
|
+
value,
|
|
1349
|
+
startNode,
|
|
1350
|
+
endNode,
|
|
1351
|
+
comparator,
|
|
1352
|
+
direction,
|
|
1353
|
+
earlyTerminate
|
|
1354
|
+
);
|
|
1355
|
+
let count = 0;
|
|
1356
|
+
for (const pair of generator) {
|
|
1357
|
+
const [k, v] = pair;
|
|
1358
|
+
let isMatch = true;
|
|
1359
|
+
for (const key in condition) {
|
|
1360
|
+
if (key === driverKey) continue;
|
|
1361
|
+
const verify = this.verifierMap[key];
|
|
1362
|
+
const condValue = condition[key];
|
|
1363
|
+
if (!verify(v, condValue)) {
|
|
1364
|
+
isMatch = false;
|
|
1365
|
+
break;
|
|
1275
1366
|
}
|
|
1276
|
-
result = intersection;
|
|
1277
1367
|
}
|
|
1368
|
+
if (isMatch) {
|
|
1369
|
+
yield pair;
|
|
1370
|
+
count++;
|
|
1371
|
+
if (limit !== void 0 && count >= limit) {
|
|
1372
|
+
break;
|
|
1373
|
+
}
|
|
1374
|
+
}
|
|
1375
|
+
}
|
|
1376
|
+
}
|
|
1377
|
+
keys(condition, filterValues) {
|
|
1378
|
+
const set = /* @__PURE__ */ new Set();
|
|
1379
|
+
for (const key of this.keysStream(condition, filterValues)) {
|
|
1380
|
+
set.add(key);
|
|
1278
1381
|
}
|
|
1279
|
-
return
|
|
1382
|
+
return set;
|
|
1383
|
+
}
|
|
1384
|
+
where(condition) {
|
|
1385
|
+
const map = /* @__PURE__ */ new Map();
|
|
1386
|
+
for (const [key, value] of this.whereStream(condition)) {
|
|
1387
|
+
map.set(key, value);
|
|
1388
|
+
}
|
|
1389
|
+
return map;
|
|
1280
1390
|
}
|
|
1281
1391
|
insert(key, value) {
|
|
1282
1392
|
const before = this.insertableNode(value);
|
|
@@ -1651,8 +1761,7 @@ var BPTreeAsync = class extends BPTree {
|
|
|
1651
1761
|
this.lock.writeUnlock(lockId);
|
|
1652
1762
|
});
|
|
1653
1763
|
}
|
|
1654
|
-
async
|
|
1655
|
-
const pairs = [];
|
|
1764
|
+
async *getPairsGenerator(value, startNode, endNode, comparator, direction, earlyTerminate) {
|
|
1656
1765
|
let node = startNode;
|
|
1657
1766
|
let done = false;
|
|
1658
1767
|
let hasMatched = false;
|
|
@@ -1661,71 +1770,52 @@ var BPTreeAsync = class extends BPTree {
|
|
|
1661
1770
|
done = true;
|
|
1662
1771
|
break;
|
|
1663
1772
|
}
|
|
1664
|
-
|
|
1665
|
-
|
|
1666
|
-
|
|
1667
|
-
|
|
1668
|
-
|
|
1669
|
-
|
|
1670
|
-
|
|
1671
|
-
|
|
1672
|
-
|
|
1773
|
+
const len = node.values.length;
|
|
1774
|
+
if (direction === 1) {
|
|
1775
|
+
for (let i = 0; i < len; i++) {
|
|
1776
|
+
const nValue = node.values[i];
|
|
1777
|
+
const keys = node.keys[i];
|
|
1778
|
+
if (comparator(nValue, value)) {
|
|
1779
|
+
hasMatched = true;
|
|
1780
|
+
for (let j = 0; j < keys.length; j++) {
|
|
1781
|
+
yield [keys[j], nValue];
|
|
1782
|
+
}
|
|
1783
|
+
} else if (earlyTerminate && hasMatched) {
|
|
1784
|
+
done = true;
|
|
1785
|
+
break;
|
|
1786
|
+
}
|
|
1787
|
+
}
|
|
1788
|
+
} else {
|
|
1789
|
+
let i = len;
|
|
1790
|
+
while (i--) {
|
|
1791
|
+
const nValue = node.values[i];
|
|
1792
|
+
const keys = node.keys[i];
|
|
1793
|
+
if (comparator(nValue, value)) {
|
|
1794
|
+
hasMatched = true;
|
|
1795
|
+
let j = keys.length;
|
|
1796
|
+
while (j--) {
|
|
1797
|
+
yield [keys[j], nValue];
|
|
1798
|
+
}
|
|
1799
|
+
} else if (earlyTerminate && hasMatched) {
|
|
1800
|
+
done = true;
|
|
1801
|
+
break;
|
|
1673
1802
|
}
|
|
1674
|
-
} else if (earlyTerminate && hasMatched) {
|
|
1675
|
-
done = true;
|
|
1676
|
-
break;
|
|
1677
1803
|
}
|
|
1678
1804
|
}
|
|
1679
1805
|
if (done) break;
|
|
1680
|
-
if (
|
|
1681
|
-
|
|
1682
|
-
break;
|
|
1683
|
-
}
|
|
1684
|
-
node = await this.getNode(node.prev);
|
|
1685
|
-
}
|
|
1686
|
-
return new Map(pairs.reverse());
|
|
1687
|
-
}
|
|
1688
|
-
async getPairsLeftToRight(value, startNode, endNode, comparator, earlyTerminate) {
|
|
1689
|
-
const pairs = [];
|
|
1690
|
-
let node = startNode;
|
|
1691
|
-
let done = false;
|
|
1692
|
-
let hasMatched = false;
|
|
1693
|
-
while (!done) {
|
|
1694
|
-
if (endNode && node.id === endNode.id) {
|
|
1695
|
-
done = true;
|
|
1696
|
-
break;
|
|
1697
|
-
}
|
|
1698
|
-
for (let i = 0, len = node.values.length; i < len; i++) {
|
|
1699
|
-
const nValue = node.values[i];
|
|
1700
|
-
const keys = node.keys[i];
|
|
1701
|
-
if (comparator(nValue, value)) {
|
|
1702
|
-
hasMatched = true;
|
|
1703
|
-
for (let j = 0, len2 = keys.length; j < len2; j++) {
|
|
1704
|
-
const key = keys[j];
|
|
1705
|
-
pairs.push([key, nValue]);
|
|
1706
|
-
}
|
|
1707
|
-
} else if (earlyTerminate && hasMatched) {
|
|
1806
|
+
if (direction === 1) {
|
|
1807
|
+
if (!node.next) {
|
|
1708
1808
|
done = true;
|
|
1709
1809
|
break;
|
|
1710
1810
|
}
|
|
1811
|
+
node = await this.getNode(node.next);
|
|
1812
|
+
} else {
|
|
1813
|
+
if (!node.prev) {
|
|
1814
|
+
done = true;
|
|
1815
|
+
break;
|
|
1816
|
+
}
|
|
1817
|
+
node = await this.getNode(node.prev);
|
|
1711
1818
|
}
|
|
1712
|
-
if (done) break;
|
|
1713
|
-
if (!node.next) {
|
|
1714
|
-
done = true;
|
|
1715
|
-
break;
|
|
1716
|
-
}
|
|
1717
|
-
node = await this.getNode(node.next);
|
|
1718
|
-
}
|
|
1719
|
-
return new Map(pairs);
|
|
1720
|
-
}
|
|
1721
|
-
async getPairs(value, startNode, endNode, comparator, direction, earlyTerminate) {
|
|
1722
|
-
switch (direction) {
|
|
1723
|
-
case -1:
|
|
1724
|
-
return await this.getPairsRightToLeft(value, startNode, endNode, comparator, earlyTerminate);
|
|
1725
|
-
case 1:
|
|
1726
|
-
return await this.getPairsLeftToRight(value, startNode, endNode, comparator, earlyTerminate);
|
|
1727
|
-
default:
|
|
1728
|
-
throw new Error(`Direction must be -1 or 1. but got a ${direction}`);
|
|
1729
1819
|
}
|
|
1730
1820
|
}
|
|
1731
1821
|
async _createNodeId(isLeaf) {
|
|
@@ -2181,58 +2271,114 @@ var BPTreeAsync = class extends BPTree {
|
|
|
2181
2271
|
}
|
|
2182
2272
|
this._nodeDeleteBuffer.clear();
|
|
2183
2273
|
}
|
|
2184
|
-
|
|
2274
|
+
/**
|
|
2275
|
+
* Retrieves the value associated with the given key (PK).
|
|
2276
|
+
* Note: This method performs a full scan of leaf nodes as the tree is ordered by Value, not Key.
|
|
2277
|
+
*
|
|
2278
|
+
* @param key The key to search for.
|
|
2279
|
+
* @returns The value associated with the key, or undefined if not found.
|
|
2280
|
+
*/
|
|
2281
|
+
async get(key) {
|
|
2185
2282
|
return this.readLock(async () => {
|
|
2186
|
-
|
|
2187
|
-
|
|
2188
|
-
|
|
2189
|
-
|
|
2190
|
-
|
|
2191
|
-
|
|
2192
|
-
|
|
2193
|
-
|
|
2194
|
-
|
|
2195
|
-
|
|
2196
|
-
filterValues = new Set(pairs.keys());
|
|
2197
|
-
} else {
|
|
2198
|
-
const intersections = /* @__PURE__ */ new Set();
|
|
2199
|
-
for (const key2 of filterValues) {
|
|
2200
|
-
const has = pairs.has(key2);
|
|
2201
|
-
if (has) {
|
|
2202
|
-
intersections.add(key2);
|
|
2283
|
+
let node = await this.leftestNode();
|
|
2284
|
+
while (true) {
|
|
2285
|
+
if (node.values) {
|
|
2286
|
+
const len = node.values.length;
|
|
2287
|
+
for (let i = 0; i < len; i++) {
|
|
2288
|
+
const keys = node.keys[i];
|
|
2289
|
+
for (let j = 0; j < keys.length; j++) {
|
|
2290
|
+
if (keys[j] === key) {
|
|
2291
|
+
return node.values[i];
|
|
2292
|
+
}
|
|
2203
2293
|
}
|
|
2204
2294
|
}
|
|
2205
|
-
filterValues = intersections;
|
|
2206
2295
|
}
|
|
2296
|
+
if (!node.next) break;
|
|
2297
|
+
node = await this.getNode(node.next);
|
|
2207
2298
|
}
|
|
2208
|
-
return
|
|
2299
|
+
return void 0;
|
|
2300
|
+
});
|
|
2301
|
+
}
|
|
2302
|
+
async *keysStream(condition, filterValues, limit) {
|
|
2303
|
+
const stream = this.whereStream(condition, limit);
|
|
2304
|
+
const intersection = filterValues && filterValues.size > 0 ? filterValues : null;
|
|
2305
|
+
for await (const [key] of stream) {
|
|
2306
|
+
if (intersection && !intersection.has(key)) {
|
|
2307
|
+
continue;
|
|
2308
|
+
}
|
|
2309
|
+
yield key;
|
|
2310
|
+
}
|
|
2311
|
+
}
|
|
2312
|
+
async *whereStream(condition, limit) {
|
|
2313
|
+
let driverKey = null;
|
|
2314
|
+
if ("primaryEqual" in condition) driverKey = "primaryEqual";
|
|
2315
|
+
else if ("equal" in condition) driverKey = "equal";
|
|
2316
|
+
else if ("gt" in condition) driverKey = "gt";
|
|
2317
|
+
else if ("gte" in condition) driverKey = "gte";
|
|
2318
|
+
else if ("lt" in condition) driverKey = "lt";
|
|
2319
|
+
else if ("lte" in condition) driverKey = "lte";
|
|
2320
|
+
else if ("primaryGt" in condition) driverKey = "primaryGt";
|
|
2321
|
+
else if ("primaryGte" in condition) driverKey = "primaryGte";
|
|
2322
|
+
else if ("primaryLt" in condition) driverKey = "primaryLt";
|
|
2323
|
+
else if ("primaryLte" in condition) driverKey = "primaryLte";
|
|
2324
|
+
else if ("like" in condition) driverKey = "like";
|
|
2325
|
+
else if ("notEqual" in condition) driverKey = "notEqual";
|
|
2326
|
+
else if ("primaryNotEqual" in condition) driverKey = "primaryNotEqual";
|
|
2327
|
+
else if ("or" in condition) driverKey = "or";
|
|
2328
|
+
else if ("primaryOr" in condition) driverKey = "primaryOr";
|
|
2329
|
+
if (!driverKey) return;
|
|
2330
|
+
const value = condition[driverKey];
|
|
2331
|
+
const startNode = await this.verifierStartNode[driverKey](value);
|
|
2332
|
+
const endNode = await this.verifierEndNode[driverKey](value);
|
|
2333
|
+
const direction = this.verifierDirection[driverKey];
|
|
2334
|
+
const comparator = this.verifierMap[driverKey];
|
|
2335
|
+
const earlyTerminate = this.verifierEarlyTerminate[driverKey];
|
|
2336
|
+
const generator = this.getPairsGenerator(
|
|
2337
|
+
value,
|
|
2338
|
+
startNode,
|
|
2339
|
+
endNode,
|
|
2340
|
+
comparator,
|
|
2341
|
+
direction,
|
|
2342
|
+
earlyTerminate
|
|
2343
|
+
);
|
|
2344
|
+
let count = 0;
|
|
2345
|
+
for await (const pair of generator) {
|
|
2346
|
+
const [k, v] = pair;
|
|
2347
|
+
let isMatch = true;
|
|
2348
|
+
for (const key in condition) {
|
|
2349
|
+
if (key === driverKey) continue;
|
|
2350
|
+
const verify = this.verifierMap[key];
|
|
2351
|
+
const condValue = condition[key];
|
|
2352
|
+
if (!verify(v, condValue)) {
|
|
2353
|
+
isMatch = false;
|
|
2354
|
+
break;
|
|
2355
|
+
}
|
|
2356
|
+
}
|
|
2357
|
+
if (isMatch) {
|
|
2358
|
+
yield pair;
|
|
2359
|
+
count++;
|
|
2360
|
+
if (limit !== void 0 && count >= limit) {
|
|
2361
|
+
break;
|
|
2362
|
+
}
|
|
2363
|
+
}
|
|
2364
|
+
}
|
|
2365
|
+
}
|
|
2366
|
+
async keys(condition, filterValues) {
|
|
2367
|
+
return this.readLock(async () => {
|
|
2368
|
+
const set = /* @__PURE__ */ new Set();
|
|
2369
|
+
for await (const key of this.keysStream(condition, filterValues)) {
|
|
2370
|
+
set.add(key);
|
|
2371
|
+
}
|
|
2372
|
+
return set;
|
|
2209
2373
|
});
|
|
2210
2374
|
}
|
|
2211
2375
|
async where(condition) {
|
|
2212
2376
|
return this.readLock(async () => {
|
|
2213
|
-
|
|
2214
|
-
for (const
|
|
2215
|
-
|
|
2216
|
-
const value = condition[key];
|
|
2217
|
-
const startNode = await this.verifierStartNode[key](value);
|
|
2218
|
-
const endNode = await this.verifierEndNode[key](value);
|
|
2219
|
-
const direction = this.verifierDirection[key];
|
|
2220
|
-
const comparator = this.verifierMap[key];
|
|
2221
|
-
const earlyTerminate = this.verifierEarlyTerminate[key];
|
|
2222
|
-
const pairs = await this.getPairs(value, startNode, endNode, comparator, direction, earlyTerminate);
|
|
2223
|
-
if (result === null) {
|
|
2224
|
-
result = pairs;
|
|
2225
|
-
} else {
|
|
2226
|
-
const intersection = /* @__PURE__ */ new Map();
|
|
2227
|
-
for (const [k2, v] of pairs) {
|
|
2228
|
-
if (result.has(k2)) {
|
|
2229
|
-
intersection.set(k2, v);
|
|
2230
|
-
}
|
|
2231
|
-
}
|
|
2232
|
-
result = intersection;
|
|
2233
|
-
}
|
|
2377
|
+
const map = /* @__PURE__ */ new Map();
|
|
2378
|
+
for await (const [key, value] of this.whereStream(condition)) {
|
|
2379
|
+
map.set(key, value);
|
|
2234
2380
|
}
|
|
2235
|
-
return
|
|
2381
|
+
return map;
|
|
2236
2382
|
});
|
|
2237
2383
|
}
|
|
2238
2384
|
async insert(key, value) {
|