serializable-bptree 6.1.0 → 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.
@@ -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;
@@ -483,9 +483,15 @@ var BPTree = class {
483
483
  lt: (nv, v) => this.comparator.isLower(nv, v),
484
484
  lte: (nv, v) => this.comparator.isLower(nv, v) || this.comparator.isSame(nv, v),
485
485
  equal: (nv, v) => this.comparator.isSame(nv, v),
486
- primaryEqual: (nv, v) => this.comparator.isPrimarySame(nv, v),
487
486
  notEqual: (nv, v) => this.comparator.isSame(nv, v) === false,
488
487
  or: (nv, v) => this.ensureValues(v).some((v2) => this.comparator.isSame(nv, v2)),
488
+ primaryGt: (nv, v) => this.comparator.isPrimaryHigher(nv, v),
489
+ primaryGte: (nv, v) => this.comparator.isPrimaryHigher(nv, v) || this.comparator.isPrimarySame(nv, v),
490
+ primaryLt: (nv, v) => this.comparator.isPrimaryLower(nv, v),
491
+ primaryLte: (nv, v) => this.comparator.isPrimaryLower(nv, v) || this.comparator.isPrimarySame(nv, v),
492
+ primaryEqual: (nv, v) => this.comparator.isPrimarySame(nv, v),
493
+ primaryNotEqual: (nv, v) => this.comparator.isPrimarySame(nv, v) === false,
494
+ primaryOr: (nv, v) => this.ensureValues(v).some((v2) => this.comparator.isPrimarySame(nv, v2)),
489
495
  like: (nv, v) => {
490
496
  const nodeValue = this.comparator.match(nv);
491
497
  const value = this.comparator.match(v);
@@ -500,9 +506,15 @@ var BPTree = class {
500
506
  lt: (v) => this.insertableNode(v),
501
507
  lte: (v) => this.insertableNode(v),
502
508
  equal: (v) => this.insertableNode(v),
503
- primaryEqual: (v) => this.insertableNodeByPrimary(v),
504
509
  notEqual: (v) => this.leftestNode(),
505
510
  or: (v) => this.insertableNode(this.lowestValue(this.ensureValues(v))),
511
+ primaryGt: (v) => this.insertableNodeByPrimary(v),
512
+ primaryGte: (v) => this.insertableNodeByPrimary(v),
513
+ primaryLt: (v) => this.insertableNodeByPrimary(v),
514
+ primaryLte: (v) => this.insertableRightestNodeByPrimary(v),
515
+ primaryEqual: (v) => this.insertableNodeByPrimary(v),
516
+ primaryNotEqual: (v) => this.leftestNode(),
517
+ primaryOr: (v) => this.insertableNodeByPrimary(this.lowestPrimaryValue(this.ensureValues(v))),
506
518
  like: (v) => this.leftestNode()
507
519
  };
508
520
  verifierEndNode = {
@@ -511,12 +523,20 @@ var BPTree = class {
511
523
  lt: (v) => null,
512
524
  lte: (v) => null,
513
525
  equal: (v) => this.insertableEndNode(v, this.verifierDirection.equal),
514
- primaryEqual: (v) => null,
515
526
  notEqual: (v) => null,
516
527
  or: (v) => this.insertableEndNode(
517
528
  this.highestValue(this.ensureValues(v)),
518
529
  this.verifierDirection.or
519
530
  ),
531
+ primaryGt: (v) => null,
532
+ primaryGte: (v) => null,
533
+ primaryLt: (v) => null,
534
+ primaryLte: (v) => null,
535
+ primaryEqual: (v) => null,
536
+ primaryNotEqual: (v) => null,
537
+ primaryOr: (v) => this.insertableRightestEndNodeByPrimary(
538
+ this.highestPrimaryValue(this.ensureValues(v))
539
+ ),
520
540
  like: (v) => null
521
541
  };
522
542
  verifierDirection = {
@@ -525,9 +545,15 @@ var BPTree = class {
525
545
  lt: -1,
526
546
  lte: -1,
527
547
  equal: 1,
528
- primaryEqual: 1,
529
548
  notEqual: 1,
530
549
  or: 1,
550
+ primaryGt: 1,
551
+ primaryGte: 1,
552
+ primaryLt: -1,
553
+ primaryLte: -1,
554
+ primaryEqual: 1,
555
+ primaryNotEqual: 1,
556
+ primaryOr: 1,
531
557
  like: 1
532
558
  };
533
559
  /**
@@ -541,11 +567,93 @@ var BPTree = class {
541
567
  lt: false,
542
568
  lte: false,
543
569
  equal: true,
544
- primaryEqual: true,
545
570
  notEqual: false,
546
571
  or: false,
572
+ primaryGt: false,
573
+ primaryGte: false,
574
+ primaryLt: false,
575
+ primaryLte: false,
576
+ primaryEqual: true,
577
+ primaryNotEqual: false,
578
+ primaryOr: false,
547
579
  like: false
548
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
+ }
549
657
  constructor(strategy, comparator, option) {
550
658
  this.strategy = strategy;
551
659
  this.comparator = comparator;
@@ -579,6 +687,14 @@ var BPTree = class {
579
687
  const i = v.length - 1;
580
688
  return [...v].sort((a, b) => this.comparator.asc(a, b))[i];
581
689
  }
690
+ lowestPrimaryValue(v) {
691
+ const i = 0;
692
+ return [...v].sort((a, b) => this.comparator.primaryAsc(a, b))[i];
693
+ }
694
+ highestPrimaryValue(v) {
695
+ const i = v.length - 1;
696
+ return [...v].sort((a, b) => this.comparator.primaryAsc(a, b))[i];
697
+ }
582
698
  _insertAtLeaf(node, key, value) {
583
699
  if (node.values.length) {
584
700
  for (let i = 0, len = node.values.length; i < len; i++) {
@@ -658,8 +774,7 @@ var BPTreeSync = class extends BPTree {
658
774
  capacity: this.option.capacity ?? 1e3
659
775
  });
660
776
  }
661
- getPairsRightToLeft(value, startNode, endNode, comparator, earlyTerminate) {
662
- const pairs = [];
777
+ *getPairsGenerator(value, startNode, endNode, comparator, direction, earlyTerminate) {
663
778
  let node = startNode;
664
779
  let done = false;
665
780
  let hasMatched = false;
@@ -668,71 +783,52 @@ var BPTreeSync = class extends BPTree {
668
783
  done = true;
669
784
  break;
670
785
  }
671
- let i = node.values.length;
672
- while (i--) {
673
- const nValue = node.values[i];
674
- const keys = node.keys[i];
675
- if (comparator(nValue, value)) {
676
- hasMatched = true;
677
- let j = keys.length;
678
- while (j--) {
679
- pairs.push([keys[j], nValue]);
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;
680
815
  }
681
- } else if (earlyTerminate && hasMatched) {
682
- done = true;
683
- break;
684
816
  }
685
817
  }
686
818
  if (done) break;
687
- if (!node.prev) {
688
- done = true;
689
- break;
690
- }
691
- node = this.getNode(node.prev);
692
- }
693
- return new Map(pairs.reverse());
694
- }
695
- getPairsLeftToRight(value, startNode, endNode, comparator, earlyTerminate) {
696
- const pairs = [];
697
- let node = startNode;
698
- let done = false;
699
- let hasMatched = false;
700
- while (!done) {
701
- if (endNode && node.id === endNode.id) {
702
- done = true;
703
- break;
704
- }
705
- for (let i = 0, len = node.values.length; i < len; i++) {
706
- const nValue = node.values[i];
707
- const keys = node.keys[i];
708
- if (comparator(nValue, value)) {
709
- hasMatched = true;
710
- for (let j = 0, len2 = keys.length; j < len2; j++) {
711
- const key = keys[j];
712
- pairs.push([key, nValue]);
713
- }
714
- } else if (earlyTerminate && hasMatched) {
819
+ if (direction === 1) {
820
+ if (!node.next) {
715
821
  done = true;
716
822
  break;
717
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);
718
831
  }
719
- if (done) break;
720
- if (!node.next) {
721
- done = true;
722
- break;
723
- }
724
- node = this.getNode(node.next);
725
- }
726
- return new Map(pairs);
727
- }
728
- getPairs(value, startNode, endNode, comparator, direction, earlyTerminate) {
729
- switch (direction) {
730
- case -1:
731
- return this.getPairsRightToLeft(value, startNode, endNode, comparator, earlyTerminate);
732
- case 1:
733
- return this.getPairsLeftToRight(value, startNode, endNode, comparator, earlyTerminate);
734
- default:
735
- throw new Error(`Direction must be -1 or 1. but got a ${direction}`);
736
832
  }
737
833
  }
738
834
  _createNodeId(isLeaf) {
@@ -1103,6 +1199,31 @@ var BPTreeSync = class extends BPTree {
1103
1199
  }
1104
1200
  return node;
1105
1201
  }
1202
+ insertableRightestNodeByPrimary(value) {
1203
+ let node = this.getNode(this.root.id);
1204
+ while (!node.leaf) {
1205
+ for (let i = 0, len = node.values.length; i < len; i++) {
1206
+ const nValue = node.values[i];
1207
+ const k = node.keys;
1208
+ if (this.comparator.isPrimaryLower(value, nValue)) {
1209
+ node = this.getNode(k[i]);
1210
+ break;
1211
+ }
1212
+ if (i + 1 === node.values.length) {
1213
+ node = this.getNode(k[i + 1]);
1214
+ break;
1215
+ }
1216
+ }
1217
+ }
1218
+ return node;
1219
+ }
1220
+ insertableRightestEndNodeByPrimary(value) {
1221
+ const node = this.insertableRightestNodeByPrimary(value);
1222
+ if (!node.next) {
1223
+ return null;
1224
+ }
1225
+ return this.getNode(node.next);
1226
+ }
1106
1227
  insertableEndNode(value, direction) {
1107
1228
  const insertableNode = this.insertableNode(value);
1108
1229
  let key;
@@ -1163,55 +1284,109 @@ var BPTreeSync = class extends BPTree {
1163
1284
  }
1164
1285
  this._nodeDeleteBuffer.clear();
1165
1286
  }
1166
- keys(condition, filterValues) {
1167
- for (const k in condition) {
1168
- const key = k;
1169
- const value = condition[key];
1170
- const startNode = this.verifierStartNode[key](value);
1171
- const endNode = this.verifierEndNode[key](value);
1172
- const direction = this.verifierDirection[key];
1173
- const comparator = this.verifierMap[key];
1174
- const earlyTerminate = this.verifierEarlyTerminate[key];
1175
- const pairs = this.getPairs(value, startNode, endNode, comparator, direction, earlyTerminate);
1176
- if (!filterValues) {
1177
- filterValues = new Set(pairs.keys());
1178
- } else {
1179
- const intersections = /* @__PURE__ */ new Set();
1180
- for (const key2 of filterValues) {
1181
- const has = pairs.has(key2);
1182
- if (has) {
1183
- intersections.add(key2);
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
+ }
1184
1305
  }
1185
1306
  }
1186
- filterValues = intersections;
1187
1307
  }
1308
+ if (!node.next) break;
1309
+ node = this.getNode(node.next);
1188
1310
  }
1189
- return filterValues ?? /* @__PURE__ */ new Set([]);
1311
+ return void 0;
1190
1312
  }
1191
- where(condition) {
1192
- let result = null;
1193
- for (const k in condition) {
1194
- const key = k;
1195
- const value = condition[key];
1196
- const startNode = this.verifierStartNode[key](value);
1197
- const endNode = this.verifierEndNode[key](value);
1198
- const direction = this.verifierDirection[key];
1199
- const comparator = this.verifierMap[key];
1200
- const earlyTerminate = this.verifierEarlyTerminate[key];
1201
- const pairs = this.getPairs(value, startNode, endNode, comparator, direction, earlyTerminate);
1202
- if (result === null) {
1203
- result = pairs;
1204
- } else {
1205
- const intersection = /* @__PURE__ */ new Map();
1206
- for (const [k2, v] of pairs) {
1207
- if (result.has(k2)) {
1208
- intersection.set(k2, v);
1209
- }
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;
1210
1366
  }
1211
- result = intersection;
1212
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);
1381
+ }
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);
1213
1388
  }
1214
- return result ?? /* @__PURE__ */ new Map();
1389
+ return map;
1215
1390
  }
1216
1391
  insert(key, value) {
1217
1392
  const before = this.insertableNode(value);
@@ -1586,8 +1761,7 @@ var BPTreeAsync = class extends BPTree {
1586
1761
  this.lock.writeUnlock(lockId);
1587
1762
  });
1588
1763
  }
1589
- async getPairsRightToLeft(value, startNode, endNode, comparator, earlyTerminate) {
1590
- const pairs = [];
1764
+ async *getPairsGenerator(value, startNode, endNode, comparator, direction, earlyTerminate) {
1591
1765
  let node = startNode;
1592
1766
  let done = false;
1593
1767
  let hasMatched = false;
@@ -1596,71 +1770,52 @@ var BPTreeAsync = class extends BPTree {
1596
1770
  done = true;
1597
1771
  break;
1598
1772
  }
1599
- let i = node.values.length;
1600
- while (i--) {
1601
- const nValue = node.values[i];
1602
- const keys = node.keys[i];
1603
- if (comparator(nValue, value)) {
1604
- hasMatched = true;
1605
- let j = keys.length;
1606
- while (j--) {
1607
- pairs.push([keys[j], nValue]);
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;
1608
1802
  }
1609
- } else if (earlyTerminate && hasMatched) {
1610
- done = true;
1611
- break;
1612
1803
  }
1613
1804
  }
1614
1805
  if (done) break;
1615
- if (!node.prev) {
1616
- done = true;
1617
- break;
1618
- }
1619
- node = await this.getNode(node.prev);
1620
- }
1621
- return new Map(pairs.reverse());
1622
- }
1623
- async getPairsLeftToRight(value, startNode, endNode, comparator, earlyTerminate) {
1624
- const pairs = [];
1625
- let node = startNode;
1626
- let done = false;
1627
- let hasMatched = false;
1628
- while (!done) {
1629
- if (endNode && node.id === endNode.id) {
1630
- done = true;
1631
- break;
1632
- }
1633
- for (let i = 0, len = node.values.length; i < len; i++) {
1634
- const nValue = node.values[i];
1635
- const keys = node.keys[i];
1636
- if (comparator(nValue, value)) {
1637
- hasMatched = true;
1638
- for (let j = 0, len2 = keys.length; j < len2; j++) {
1639
- const key = keys[j];
1640
- pairs.push([key, nValue]);
1641
- }
1642
- } else if (earlyTerminate && hasMatched) {
1806
+ if (direction === 1) {
1807
+ if (!node.next) {
1643
1808
  done = true;
1644
1809
  break;
1645
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);
1646
1818
  }
1647
- if (done) break;
1648
- if (!node.next) {
1649
- done = true;
1650
- break;
1651
- }
1652
- node = await this.getNode(node.next);
1653
- }
1654
- return new Map(pairs);
1655
- }
1656
- async getPairs(value, startNode, endNode, comparator, direction, earlyTerminate) {
1657
- switch (direction) {
1658
- case -1:
1659
- return await this.getPairsRightToLeft(value, startNode, endNode, comparator, earlyTerminate);
1660
- case 1:
1661
- return await this.getPairsLeftToRight(value, startNode, endNode, comparator, earlyTerminate);
1662
- default:
1663
- throw new Error(`Direction must be -1 or 1. but got a ${direction}`);
1664
1819
  }
1665
1820
  }
1666
1821
  async _createNodeId(isLeaf) {
@@ -2031,6 +2186,31 @@ var BPTreeAsync = class extends BPTree {
2031
2186
  }
2032
2187
  return node;
2033
2188
  }
2189
+ async insertableRightestNodeByPrimary(value) {
2190
+ let node = await this.getNode(this.root.id);
2191
+ while (!node.leaf) {
2192
+ for (let i = 0, len = node.values.length; i < len; i++) {
2193
+ const nValue = node.values[i];
2194
+ const k = node.keys;
2195
+ if (this.comparator.isPrimaryLower(value, nValue)) {
2196
+ node = await this.getNode(k[i]);
2197
+ break;
2198
+ }
2199
+ if (i + 1 === node.values.length) {
2200
+ node = await this.getNode(k[i + 1]);
2201
+ break;
2202
+ }
2203
+ }
2204
+ }
2205
+ return node;
2206
+ }
2207
+ async insertableRightestEndNodeByPrimary(value) {
2208
+ const node = await this.insertableRightestNodeByPrimary(value);
2209
+ if (!node.next) {
2210
+ return null;
2211
+ }
2212
+ return await this.getNode(node.next);
2213
+ }
2034
2214
  async insertableEndNode(value, direction) {
2035
2215
  const insertableNode = await this.insertableNode(value);
2036
2216
  let key;
@@ -2091,58 +2271,114 @@ var BPTreeAsync = class extends BPTree {
2091
2271
  }
2092
2272
  this._nodeDeleteBuffer.clear();
2093
2273
  }
2094
- async keys(condition, filterValues) {
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) {
2095
2282
  return this.readLock(async () => {
2096
- for (const k in condition) {
2097
- const key = k;
2098
- const value = condition[key];
2099
- const startNode = await this.verifierStartNode[key](value);
2100
- const endNode = await this.verifierEndNode[key](value);
2101
- const direction = this.verifierDirection[key];
2102
- const comparator = this.verifierMap[key];
2103
- const earlyTerminate = this.verifierEarlyTerminate[key];
2104
- const pairs = await this.getPairs(value, startNode, endNode, comparator, direction, earlyTerminate);
2105
- if (!filterValues) {
2106
- filterValues = new Set(pairs.keys());
2107
- } else {
2108
- const intersections = /* @__PURE__ */ new Set();
2109
- for (const key2 of filterValues) {
2110
- const has = pairs.has(key2);
2111
- if (has) {
2112
- 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
+ }
2113
2293
  }
2114
2294
  }
2115
- filterValues = intersections;
2116
2295
  }
2296
+ if (!node.next) break;
2297
+ node = await this.getNode(node.next);
2117
2298
  }
2118
- return filterValues ?? /* @__PURE__ */ new Set([]);
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;
2119
2373
  });
2120
2374
  }
2121
2375
  async where(condition) {
2122
2376
  return this.readLock(async () => {
2123
- let result = null;
2124
- for (const k in condition) {
2125
- const key = k;
2126
- const value = condition[key];
2127
- const startNode = await this.verifierStartNode[key](value);
2128
- const endNode = await this.verifierEndNode[key](value);
2129
- const direction = this.verifierDirection[key];
2130
- const comparator = this.verifierMap[key];
2131
- const earlyTerminate = this.verifierEarlyTerminate[key];
2132
- const pairs = await this.getPairs(value, startNode, endNode, comparator, direction, earlyTerminate);
2133
- if (result === null) {
2134
- result = pairs;
2135
- } else {
2136
- const intersection = /* @__PURE__ */ new Map();
2137
- for (const [k2, v] of pairs) {
2138
- if (result.has(k2)) {
2139
- intersection.set(k2, v);
2140
- }
2141
- }
2142
- result = intersection;
2143
- }
2377
+ const map = /* @__PURE__ */ new Map();
2378
+ for await (const [key, value] of this.whereStream(condition)) {
2379
+ map.set(key, value);
2144
2380
  }
2145
- return result ?? /* @__PURE__ */ new Map();
2381
+ return map;
2146
2382
  });
2147
2383
  }
2148
2384
  async insert(key, value) {