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.
@@ -432,7 +432,7 @@ var CacheEntanglementAsync = class extends CacheEntanglement {
432
432
  };
433
433
 
434
434
  // src/base/BPTree.ts
435
- var BPTree = class {
435
+ var BPTree = class _BPTree {
436
436
  _cachedRegexp;
437
437
  strategy;
438
438
  comparator;
@@ -449,9 +449,15 @@ var BPTree = class {
449
449
  lt: (nv, v) => this.comparator.isLower(nv, v),
450
450
  lte: (nv, v) => this.comparator.isLower(nv, v) || this.comparator.isSame(nv, v),
451
451
  equal: (nv, v) => this.comparator.isSame(nv, v),
452
- primaryEqual: (nv, v) => this.comparator.isPrimarySame(nv, v),
453
452
  notEqual: (nv, v) => this.comparator.isSame(nv, v) === false,
454
453
  or: (nv, v) => this.ensureValues(v).some((v2) => this.comparator.isSame(nv, v2)),
454
+ primaryGt: (nv, v) => this.comparator.isPrimaryHigher(nv, v),
455
+ primaryGte: (nv, v) => this.comparator.isPrimaryHigher(nv, v) || this.comparator.isPrimarySame(nv, v),
456
+ primaryLt: (nv, v) => this.comparator.isPrimaryLower(nv, v),
457
+ primaryLte: (nv, v) => this.comparator.isPrimaryLower(nv, v) || this.comparator.isPrimarySame(nv, v),
458
+ primaryEqual: (nv, v) => this.comparator.isPrimarySame(nv, v),
459
+ primaryNotEqual: (nv, v) => this.comparator.isPrimarySame(nv, v) === false,
460
+ primaryOr: (nv, v) => this.ensureValues(v).some((v2) => this.comparator.isPrimarySame(nv, v2)),
455
461
  like: (nv, v) => {
456
462
  const nodeValue = this.comparator.match(nv);
457
463
  const value = this.comparator.match(v);
@@ -466,9 +472,15 @@ var BPTree = class {
466
472
  lt: (v) => this.insertableNode(v),
467
473
  lte: (v) => this.insertableNode(v),
468
474
  equal: (v) => this.insertableNode(v),
469
- primaryEqual: (v) => this.insertableNodeByPrimary(v),
470
475
  notEqual: (v) => this.leftestNode(),
471
476
  or: (v) => this.insertableNode(this.lowestValue(this.ensureValues(v))),
477
+ primaryGt: (v) => this.insertableNodeByPrimary(v),
478
+ primaryGte: (v) => this.insertableNodeByPrimary(v),
479
+ primaryLt: (v) => this.insertableNodeByPrimary(v),
480
+ primaryLte: (v) => this.insertableRightestNodeByPrimary(v),
481
+ primaryEqual: (v) => this.insertableNodeByPrimary(v),
482
+ primaryNotEqual: (v) => this.leftestNode(),
483
+ primaryOr: (v) => this.insertableNodeByPrimary(this.lowestPrimaryValue(this.ensureValues(v))),
472
484
  like: (v) => this.leftestNode()
473
485
  };
474
486
  verifierEndNode = {
@@ -477,12 +489,20 @@ var BPTree = class {
477
489
  lt: (v) => null,
478
490
  lte: (v) => null,
479
491
  equal: (v) => this.insertableEndNode(v, this.verifierDirection.equal),
480
- primaryEqual: (v) => null,
481
492
  notEqual: (v) => null,
482
493
  or: (v) => this.insertableEndNode(
483
494
  this.highestValue(this.ensureValues(v)),
484
495
  this.verifierDirection.or
485
496
  ),
497
+ primaryGt: (v) => null,
498
+ primaryGte: (v) => null,
499
+ primaryLt: (v) => null,
500
+ primaryLte: (v) => null,
501
+ primaryEqual: (v) => null,
502
+ primaryNotEqual: (v) => null,
503
+ primaryOr: (v) => this.insertableRightestEndNodeByPrimary(
504
+ this.highestPrimaryValue(this.ensureValues(v))
505
+ ),
486
506
  like: (v) => null
487
507
  };
488
508
  verifierDirection = {
@@ -491,9 +511,15 @@ var BPTree = class {
491
511
  lt: -1,
492
512
  lte: -1,
493
513
  equal: 1,
494
- primaryEqual: 1,
495
514
  notEqual: 1,
496
515
  or: 1,
516
+ primaryGt: 1,
517
+ primaryGte: 1,
518
+ primaryLt: -1,
519
+ primaryLte: -1,
520
+ primaryEqual: 1,
521
+ primaryNotEqual: 1,
522
+ primaryOr: 1,
497
523
  like: 1
498
524
  };
499
525
  /**
@@ -507,11 +533,93 @@ var BPTree = class {
507
533
  lt: false,
508
534
  lte: false,
509
535
  equal: true,
510
- primaryEqual: true,
511
536
  notEqual: false,
512
537
  or: false,
538
+ primaryGt: false,
539
+ primaryGte: false,
540
+ primaryLt: false,
541
+ primaryLte: false,
542
+ primaryEqual: true,
543
+ primaryNotEqual: false,
544
+ primaryOr: false,
513
545
  like: false
514
546
  };
547
+ /**
548
+ * Priority map for condition types.
549
+ * Higher value = higher selectivity (fewer expected results).
550
+ * Used by `chooseDriver` to select the most selective index.
551
+ */
552
+ static conditionPriority = {
553
+ equal: 100,
554
+ primaryEqual: 100,
555
+ or: 80,
556
+ primaryOr: 80,
557
+ gt: 50,
558
+ gte: 50,
559
+ lt: 50,
560
+ lte: 50,
561
+ primaryGt: 50,
562
+ primaryGte: 50,
563
+ primaryLt: 50,
564
+ primaryLte: 50,
565
+ like: 30,
566
+ notEqual: 10,
567
+ primaryNotEqual: 10
568
+ };
569
+ /**
570
+ * Selects the best driver tree from multiple tree/condition pairs.
571
+ * Uses rule-based optimization to choose the tree with highest estimated selectivity.
572
+ *
573
+ * @param candidates Array of { tree, condition } pairs to evaluate
574
+ * @returns The candidate with highest priority condition, or null if empty
575
+ *
576
+ * @example
577
+ * ```typescript
578
+ * const driver = BPTreeSync.chooseDriver([
579
+ * { tree: idxId, condition: { equal: 100 } },
580
+ * { tree: idxAge, condition: { gt: 20 } }
581
+ * ])
582
+ * // Returns { tree: idxId, condition: { equal: 100 } } because 'equal' has higher priority
583
+ * ```
584
+ */
585
+ static ChooseDriver(candidates) {
586
+ if (candidates.length === 0) return null;
587
+ if (candidates.length === 1) return candidates[0];
588
+ let best = candidates[0];
589
+ let bestScore = 0;
590
+ for (const candidate of candidates) {
591
+ let score = 0;
592
+ for (const key in candidate.condition) {
593
+ const condKey = key;
594
+ const priority = _BPTree.conditionPriority[condKey] ?? 0;
595
+ if (priority > score) {
596
+ score = priority;
597
+ }
598
+ }
599
+ if (score > bestScore) {
600
+ bestScore = score;
601
+ best = candidate;
602
+ }
603
+ }
604
+ return best;
605
+ }
606
+ /**
607
+ * Verified if the value satisfies the condition.
608
+ *
609
+ * @param nodeValue The value to verify.
610
+ * @param condition The condition to verify against.
611
+ * @returns Returns true if the value satisfies the condition.
612
+ */
613
+ verify(nodeValue, condition) {
614
+ for (const key in condition) {
615
+ const verify = this.verifierMap[key];
616
+ const condValue = condition[key];
617
+ if (!verify(nodeValue, condValue)) {
618
+ return false;
619
+ }
620
+ }
621
+ return true;
622
+ }
515
623
  constructor(strategy, comparator, option) {
516
624
  this.strategy = strategy;
517
625
  this.comparator = comparator;
@@ -545,6 +653,14 @@ var BPTree = class {
545
653
  const i = v.length - 1;
546
654
  return [...v].sort((a, b) => this.comparator.asc(a, b))[i];
547
655
  }
656
+ lowestPrimaryValue(v) {
657
+ const i = 0;
658
+ return [...v].sort((a, b) => this.comparator.primaryAsc(a, b))[i];
659
+ }
660
+ highestPrimaryValue(v) {
661
+ const i = v.length - 1;
662
+ return [...v].sort((a, b) => this.comparator.primaryAsc(a, b))[i];
663
+ }
548
664
  _insertAtLeaf(node, key, value) {
549
665
  if (node.values.length) {
550
666
  for (let i = 0, len = node.values.length; i < len; i++) {
@@ -624,8 +740,7 @@ var BPTreeSync = class extends BPTree {
624
740
  capacity: this.option.capacity ?? 1e3
625
741
  });
626
742
  }
627
- getPairsRightToLeft(value, startNode, endNode, comparator, earlyTerminate) {
628
- const pairs = [];
743
+ *getPairsGenerator(value, startNode, endNode, comparator, direction, earlyTerminate) {
629
744
  let node = startNode;
630
745
  let done = false;
631
746
  let hasMatched = false;
@@ -634,71 +749,52 @@ var BPTreeSync = class extends BPTree {
634
749
  done = true;
635
750
  break;
636
751
  }
637
- let i = node.values.length;
638
- while (i--) {
639
- const nValue = node.values[i];
640
- const keys = node.keys[i];
641
- if (comparator(nValue, value)) {
642
- hasMatched = true;
643
- let j = keys.length;
644
- while (j--) {
645
- pairs.push([keys[j], nValue]);
752
+ const len = node.values.length;
753
+ if (direction === 1) {
754
+ for (let i = 0; i < len; i++) {
755
+ const nValue = node.values[i];
756
+ const keys = node.keys[i];
757
+ if (comparator(nValue, value)) {
758
+ hasMatched = true;
759
+ for (let j = 0; j < keys.length; j++) {
760
+ yield [keys[j], nValue];
761
+ }
762
+ } else if (earlyTerminate && hasMatched) {
763
+ done = true;
764
+ break;
765
+ }
766
+ }
767
+ } else {
768
+ let i = len;
769
+ while (i--) {
770
+ const nValue = node.values[i];
771
+ const keys = node.keys[i];
772
+ if (comparator(nValue, value)) {
773
+ hasMatched = true;
774
+ let j = keys.length;
775
+ while (j--) {
776
+ yield [keys[j], nValue];
777
+ }
778
+ } else if (earlyTerminate && hasMatched) {
779
+ done = true;
780
+ break;
646
781
  }
647
- } else if (earlyTerminate && hasMatched) {
648
- done = true;
649
- break;
650
782
  }
651
783
  }
652
784
  if (done) break;
653
- if (!node.prev) {
654
- done = true;
655
- break;
656
- }
657
- node = this.getNode(node.prev);
658
- }
659
- return new Map(pairs.reverse());
660
- }
661
- getPairsLeftToRight(value, startNode, endNode, comparator, earlyTerminate) {
662
- const pairs = [];
663
- let node = startNode;
664
- let done = false;
665
- let hasMatched = false;
666
- while (!done) {
667
- if (endNode && node.id === endNode.id) {
668
- done = true;
669
- break;
670
- }
671
- for (let i = 0, len = node.values.length; i < len; i++) {
672
- const nValue = node.values[i];
673
- const keys = node.keys[i];
674
- if (comparator(nValue, value)) {
675
- hasMatched = true;
676
- for (let j = 0, len2 = keys.length; j < len2; j++) {
677
- const key = keys[j];
678
- pairs.push([key, nValue]);
679
- }
680
- } else if (earlyTerminate && hasMatched) {
785
+ if (direction === 1) {
786
+ if (!node.next) {
681
787
  done = true;
682
788
  break;
683
789
  }
790
+ node = this.getNode(node.next);
791
+ } else {
792
+ if (!node.prev) {
793
+ done = true;
794
+ break;
795
+ }
796
+ node = this.getNode(node.prev);
684
797
  }
685
- if (done) break;
686
- if (!node.next) {
687
- done = true;
688
- break;
689
- }
690
- node = this.getNode(node.next);
691
- }
692
- return new Map(pairs);
693
- }
694
- getPairs(value, startNode, endNode, comparator, direction, earlyTerminate) {
695
- switch (direction) {
696
- case -1:
697
- return this.getPairsRightToLeft(value, startNode, endNode, comparator, earlyTerminate);
698
- case 1:
699
- return this.getPairsLeftToRight(value, startNode, endNode, comparator, earlyTerminate);
700
- default:
701
- throw new Error(`Direction must be -1 or 1. but got a ${direction}`);
702
798
  }
703
799
  }
704
800
  _createNodeId(isLeaf) {
@@ -1069,6 +1165,31 @@ var BPTreeSync = class extends BPTree {
1069
1165
  }
1070
1166
  return node;
1071
1167
  }
1168
+ insertableRightestNodeByPrimary(value) {
1169
+ let node = this.getNode(this.root.id);
1170
+ while (!node.leaf) {
1171
+ for (let i = 0, len = node.values.length; i < len; i++) {
1172
+ const nValue = node.values[i];
1173
+ const k = node.keys;
1174
+ if (this.comparator.isPrimaryLower(value, nValue)) {
1175
+ node = this.getNode(k[i]);
1176
+ break;
1177
+ }
1178
+ if (i + 1 === node.values.length) {
1179
+ node = this.getNode(k[i + 1]);
1180
+ break;
1181
+ }
1182
+ }
1183
+ }
1184
+ return node;
1185
+ }
1186
+ insertableRightestEndNodeByPrimary(value) {
1187
+ const node = this.insertableRightestNodeByPrimary(value);
1188
+ if (!node.next) {
1189
+ return null;
1190
+ }
1191
+ return this.getNode(node.next);
1192
+ }
1072
1193
  insertableEndNode(value, direction) {
1073
1194
  const insertableNode = this.insertableNode(value);
1074
1195
  let key;
@@ -1129,55 +1250,109 @@ var BPTreeSync = class extends BPTree {
1129
1250
  }
1130
1251
  this._nodeDeleteBuffer.clear();
1131
1252
  }
1132
- keys(condition, filterValues) {
1133
- for (const k in condition) {
1134
- const key = k;
1135
- const value = condition[key];
1136
- const startNode = this.verifierStartNode[key](value);
1137
- const endNode = this.verifierEndNode[key](value);
1138
- const direction = this.verifierDirection[key];
1139
- const comparator = this.verifierMap[key];
1140
- const earlyTerminate = this.verifierEarlyTerminate[key];
1141
- const pairs = this.getPairs(value, startNode, endNode, comparator, direction, earlyTerminate);
1142
- if (!filterValues) {
1143
- filterValues = new Set(pairs.keys());
1144
- } else {
1145
- const intersections = /* @__PURE__ */ new Set();
1146
- for (const key2 of filterValues) {
1147
- const has = pairs.has(key2);
1148
- if (has) {
1149
- intersections.add(key2);
1253
+ /**
1254
+ * Retrieves the value associated with the given key (PK).
1255
+ * Note: This method performs a full scan of leaf nodes as the tree is ordered by Value, not Key.
1256
+ *
1257
+ * @param key The key to search for.
1258
+ * @returns The value associated with the key, or undefined if not found.
1259
+ */
1260
+ get(key) {
1261
+ let node = this.leftestNode();
1262
+ while (true) {
1263
+ if (node.values) {
1264
+ const len = node.values.length;
1265
+ for (let i = 0; i < len; i++) {
1266
+ const keys = node.keys[i];
1267
+ for (let j = 0; j < keys.length; j++) {
1268
+ if (keys[j] === key) {
1269
+ return node.values[i];
1270
+ }
1150
1271
  }
1151
1272
  }
1152
- filterValues = intersections;
1153
1273
  }
1274
+ if (!node.next) break;
1275
+ node = this.getNode(node.next);
1154
1276
  }
1155
- return filterValues ?? /* @__PURE__ */ new Set([]);
1277
+ return void 0;
1156
1278
  }
1157
- where(condition) {
1158
- let result = null;
1159
- for (const k in condition) {
1160
- const key = k;
1161
- const value = condition[key];
1162
- const startNode = this.verifierStartNode[key](value);
1163
- const endNode = this.verifierEndNode[key](value);
1164
- const direction = this.verifierDirection[key];
1165
- const comparator = this.verifierMap[key];
1166
- const earlyTerminate = this.verifierEarlyTerminate[key];
1167
- const pairs = this.getPairs(value, startNode, endNode, comparator, direction, earlyTerminate);
1168
- if (result === null) {
1169
- result = pairs;
1170
- } else {
1171
- const intersection = /* @__PURE__ */ new Map();
1172
- for (const [k2, v] of pairs) {
1173
- if (result.has(k2)) {
1174
- intersection.set(k2, v);
1175
- }
1279
+ *keysStream(condition, filterValues, limit) {
1280
+ const stream = this.whereStream(condition, limit);
1281
+ const intersection = filterValues && filterValues.size > 0 ? filterValues : null;
1282
+ for (const [key] of stream) {
1283
+ if (intersection && !intersection.has(key)) {
1284
+ continue;
1285
+ }
1286
+ yield key;
1287
+ }
1288
+ }
1289
+ *whereStream(condition, limit) {
1290
+ let driverKey = null;
1291
+ if ("primaryEqual" in condition) driverKey = "primaryEqual";
1292
+ else if ("equal" in condition) driverKey = "equal";
1293
+ else if ("gt" in condition) driverKey = "gt";
1294
+ else if ("gte" in condition) driverKey = "gte";
1295
+ else if ("lt" in condition) driverKey = "lt";
1296
+ else if ("lte" in condition) driverKey = "lte";
1297
+ else if ("primaryGt" in condition) driverKey = "primaryGt";
1298
+ else if ("primaryGte" in condition) driverKey = "primaryGte";
1299
+ else if ("primaryLt" in condition) driverKey = "primaryLt";
1300
+ else if ("primaryLte" in condition) driverKey = "primaryLte";
1301
+ else if ("like" in condition) driverKey = "like";
1302
+ else if ("notEqual" in condition) driverKey = "notEqual";
1303
+ else if ("primaryNotEqual" in condition) driverKey = "primaryNotEqual";
1304
+ else if ("or" in condition) driverKey = "or";
1305
+ else if ("primaryOr" in condition) driverKey = "primaryOr";
1306
+ if (!driverKey) return;
1307
+ const value = condition[driverKey];
1308
+ const startNode = this.verifierStartNode[driverKey](value);
1309
+ const endNode = this.verifierEndNode[driverKey](value);
1310
+ const direction = this.verifierDirection[driverKey];
1311
+ const comparator = this.verifierMap[driverKey];
1312
+ const earlyTerminate = this.verifierEarlyTerminate[driverKey];
1313
+ const generator = this.getPairsGenerator(
1314
+ value,
1315
+ startNode,
1316
+ endNode,
1317
+ comparator,
1318
+ direction,
1319
+ earlyTerminate
1320
+ );
1321
+ let count = 0;
1322
+ for (const pair of generator) {
1323
+ const [k, v] = pair;
1324
+ let isMatch = true;
1325
+ for (const key in condition) {
1326
+ if (key === driverKey) continue;
1327
+ const verify = this.verifierMap[key];
1328
+ const condValue = condition[key];
1329
+ if (!verify(v, condValue)) {
1330
+ isMatch = false;
1331
+ break;
1176
1332
  }
1177
- result = intersection;
1178
1333
  }
1334
+ if (isMatch) {
1335
+ yield pair;
1336
+ count++;
1337
+ if (limit !== void 0 && count >= limit) {
1338
+ break;
1339
+ }
1340
+ }
1341
+ }
1342
+ }
1343
+ keys(condition, filterValues) {
1344
+ const set = /* @__PURE__ */ new Set();
1345
+ for (const key of this.keysStream(condition, filterValues)) {
1346
+ set.add(key);
1347
+ }
1348
+ return set;
1349
+ }
1350
+ where(condition) {
1351
+ const map = /* @__PURE__ */ new Map();
1352
+ for (const [key, value] of this.whereStream(condition)) {
1353
+ map.set(key, value);
1179
1354
  }
1180
- return result ?? /* @__PURE__ */ new Map();
1355
+ return map;
1181
1356
  }
1182
1357
  insert(key, value) {
1183
1358
  const before = this.insertableNode(value);
@@ -1552,8 +1727,7 @@ var BPTreeAsync = class extends BPTree {
1552
1727
  this.lock.writeUnlock(lockId);
1553
1728
  });
1554
1729
  }
1555
- async getPairsRightToLeft(value, startNode, endNode, comparator, earlyTerminate) {
1556
- const pairs = [];
1730
+ async *getPairsGenerator(value, startNode, endNode, comparator, direction, earlyTerminate) {
1557
1731
  let node = startNode;
1558
1732
  let done = false;
1559
1733
  let hasMatched = false;
@@ -1562,71 +1736,52 @@ var BPTreeAsync = class extends BPTree {
1562
1736
  done = true;
1563
1737
  break;
1564
1738
  }
1565
- let i = node.values.length;
1566
- while (i--) {
1567
- const nValue = node.values[i];
1568
- const keys = node.keys[i];
1569
- if (comparator(nValue, value)) {
1570
- hasMatched = true;
1571
- let j = keys.length;
1572
- while (j--) {
1573
- pairs.push([keys[j], nValue]);
1739
+ const len = node.values.length;
1740
+ if (direction === 1) {
1741
+ for (let i = 0; i < len; i++) {
1742
+ const nValue = node.values[i];
1743
+ const keys = node.keys[i];
1744
+ if (comparator(nValue, value)) {
1745
+ hasMatched = true;
1746
+ for (let j = 0; j < keys.length; j++) {
1747
+ yield [keys[j], nValue];
1748
+ }
1749
+ } else if (earlyTerminate && hasMatched) {
1750
+ done = true;
1751
+ break;
1752
+ }
1753
+ }
1754
+ } else {
1755
+ let i = len;
1756
+ while (i--) {
1757
+ const nValue = node.values[i];
1758
+ const keys = node.keys[i];
1759
+ if (comparator(nValue, value)) {
1760
+ hasMatched = true;
1761
+ let j = keys.length;
1762
+ while (j--) {
1763
+ yield [keys[j], nValue];
1764
+ }
1765
+ } else if (earlyTerminate && hasMatched) {
1766
+ done = true;
1767
+ break;
1574
1768
  }
1575
- } else if (earlyTerminate && hasMatched) {
1576
- done = true;
1577
- break;
1578
1769
  }
1579
1770
  }
1580
1771
  if (done) break;
1581
- if (!node.prev) {
1582
- done = true;
1583
- break;
1584
- }
1585
- node = await this.getNode(node.prev);
1586
- }
1587
- return new Map(pairs.reverse());
1588
- }
1589
- async getPairsLeftToRight(value, startNode, endNode, comparator, earlyTerminate) {
1590
- const pairs = [];
1591
- let node = startNode;
1592
- let done = false;
1593
- let hasMatched = false;
1594
- while (!done) {
1595
- if (endNode && node.id === endNode.id) {
1596
- done = true;
1597
- break;
1598
- }
1599
- for (let i = 0, len = node.values.length; i < len; i++) {
1600
- const nValue = node.values[i];
1601
- const keys = node.keys[i];
1602
- if (comparator(nValue, value)) {
1603
- hasMatched = true;
1604
- for (let j = 0, len2 = keys.length; j < len2; j++) {
1605
- const key = keys[j];
1606
- pairs.push([key, nValue]);
1607
- }
1608
- } else if (earlyTerminate && hasMatched) {
1772
+ if (direction === 1) {
1773
+ if (!node.next) {
1609
1774
  done = true;
1610
1775
  break;
1611
1776
  }
1777
+ node = await this.getNode(node.next);
1778
+ } else {
1779
+ if (!node.prev) {
1780
+ done = true;
1781
+ break;
1782
+ }
1783
+ node = await this.getNode(node.prev);
1612
1784
  }
1613
- if (done) break;
1614
- if (!node.next) {
1615
- done = true;
1616
- break;
1617
- }
1618
- node = await this.getNode(node.next);
1619
- }
1620
- return new Map(pairs);
1621
- }
1622
- async getPairs(value, startNode, endNode, comparator, direction, earlyTerminate) {
1623
- switch (direction) {
1624
- case -1:
1625
- return await this.getPairsRightToLeft(value, startNode, endNode, comparator, earlyTerminate);
1626
- case 1:
1627
- return await this.getPairsLeftToRight(value, startNode, endNode, comparator, earlyTerminate);
1628
- default:
1629
- throw new Error(`Direction must be -1 or 1. but got a ${direction}`);
1630
1785
  }
1631
1786
  }
1632
1787
  async _createNodeId(isLeaf) {
@@ -1997,6 +2152,31 @@ var BPTreeAsync = class extends BPTree {
1997
2152
  }
1998
2153
  return node;
1999
2154
  }
2155
+ async insertableRightestNodeByPrimary(value) {
2156
+ let node = await this.getNode(this.root.id);
2157
+ while (!node.leaf) {
2158
+ for (let i = 0, len = node.values.length; i < len; i++) {
2159
+ const nValue = node.values[i];
2160
+ const k = node.keys;
2161
+ if (this.comparator.isPrimaryLower(value, nValue)) {
2162
+ node = await this.getNode(k[i]);
2163
+ break;
2164
+ }
2165
+ if (i + 1 === node.values.length) {
2166
+ node = await this.getNode(k[i + 1]);
2167
+ break;
2168
+ }
2169
+ }
2170
+ }
2171
+ return node;
2172
+ }
2173
+ async insertableRightestEndNodeByPrimary(value) {
2174
+ const node = await this.insertableRightestNodeByPrimary(value);
2175
+ if (!node.next) {
2176
+ return null;
2177
+ }
2178
+ return await this.getNode(node.next);
2179
+ }
2000
2180
  async insertableEndNode(value, direction) {
2001
2181
  const insertableNode = await this.insertableNode(value);
2002
2182
  let key;
@@ -2057,58 +2237,114 @@ var BPTreeAsync = class extends BPTree {
2057
2237
  }
2058
2238
  this._nodeDeleteBuffer.clear();
2059
2239
  }
2060
- async keys(condition, filterValues) {
2240
+ /**
2241
+ * Retrieves the value associated with the given key (PK).
2242
+ * Note: This method performs a full scan of leaf nodes as the tree is ordered by Value, not Key.
2243
+ *
2244
+ * @param key The key to search for.
2245
+ * @returns The value associated with the key, or undefined if not found.
2246
+ */
2247
+ async get(key) {
2061
2248
  return this.readLock(async () => {
2062
- for (const k in condition) {
2063
- const key = k;
2064
- const value = condition[key];
2065
- const startNode = await this.verifierStartNode[key](value);
2066
- const endNode = await this.verifierEndNode[key](value);
2067
- const direction = this.verifierDirection[key];
2068
- const comparator = this.verifierMap[key];
2069
- const earlyTerminate = this.verifierEarlyTerminate[key];
2070
- const pairs = await this.getPairs(value, startNode, endNode, comparator, direction, earlyTerminate);
2071
- if (!filterValues) {
2072
- filterValues = new Set(pairs.keys());
2073
- } else {
2074
- const intersections = /* @__PURE__ */ new Set();
2075
- for (const key2 of filterValues) {
2076
- const has = pairs.has(key2);
2077
- if (has) {
2078
- intersections.add(key2);
2249
+ let node = await this.leftestNode();
2250
+ while (true) {
2251
+ if (node.values) {
2252
+ const len = node.values.length;
2253
+ for (let i = 0; i < len; i++) {
2254
+ const keys = node.keys[i];
2255
+ for (let j = 0; j < keys.length; j++) {
2256
+ if (keys[j] === key) {
2257
+ return node.values[i];
2258
+ }
2079
2259
  }
2080
2260
  }
2081
- filterValues = intersections;
2082
2261
  }
2262
+ if (!node.next) break;
2263
+ node = await this.getNode(node.next);
2083
2264
  }
2084
- return filterValues ?? /* @__PURE__ */ new Set([]);
2265
+ return void 0;
2266
+ });
2267
+ }
2268
+ async *keysStream(condition, filterValues, limit) {
2269
+ const stream = this.whereStream(condition, limit);
2270
+ const intersection = filterValues && filterValues.size > 0 ? filterValues : null;
2271
+ for await (const [key] of stream) {
2272
+ if (intersection && !intersection.has(key)) {
2273
+ continue;
2274
+ }
2275
+ yield key;
2276
+ }
2277
+ }
2278
+ async *whereStream(condition, limit) {
2279
+ let driverKey = null;
2280
+ if ("primaryEqual" in condition) driverKey = "primaryEqual";
2281
+ else if ("equal" in condition) driverKey = "equal";
2282
+ else if ("gt" in condition) driverKey = "gt";
2283
+ else if ("gte" in condition) driverKey = "gte";
2284
+ else if ("lt" in condition) driverKey = "lt";
2285
+ else if ("lte" in condition) driverKey = "lte";
2286
+ else if ("primaryGt" in condition) driverKey = "primaryGt";
2287
+ else if ("primaryGte" in condition) driverKey = "primaryGte";
2288
+ else if ("primaryLt" in condition) driverKey = "primaryLt";
2289
+ else if ("primaryLte" in condition) driverKey = "primaryLte";
2290
+ else if ("like" in condition) driverKey = "like";
2291
+ else if ("notEqual" in condition) driverKey = "notEqual";
2292
+ else if ("primaryNotEqual" in condition) driverKey = "primaryNotEqual";
2293
+ else if ("or" in condition) driverKey = "or";
2294
+ else if ("primaryOr" in condition) driverKey = "primaryOr";
2295
+ if (!driverKey) return;
2296
+ const value = condition[driverKey];
2297
+ const startNode = await this.verifierStartNode[driverKey](value);
2298
+ const endNode = await this.verifierEndNode[driverKey](value);
2299
+ const direction = this.verifierDirection[driverKey];
2300
+ const comparator = this.verifierMap[driverKey];
2301
+ const earlyTerminate = this.verifierEarlyTerminate[driverKey];
2302
+ const generator = this.getPairsGenerator(
2303
+ value,
2304
+ startNode,
2305
+ endNode,
2306
+ comparator,
2307
+ direction,
2308
+ earlyTerminate
2309
+ );
2310
+ let count = 0;
2311
+ for await (const pair of generator) {
2312
+ const [k, v] = pair;
2313
+ let isMatch = true;
2314
+ for (const key in condition) {
2315
+ if (key === driverKey) continue;
2316
+ const verify = this.verifierMap[key];
2317
+ const condValue = condition[key];
2318
+ if (!verify(v, condValue)) {
2319
+ isMatch = false;
2320
+ break;
2321
+ }
2322
+ }
2323
+ if (isMatch) {
2324
+ yield pair;
2325
+ count++;
2326
+ if (limit !== void 0 && count >= limit) {
2327
+ break;
2328
+ }
2329
+ }
2330
+ }
2331
+ }
2332
+ async keys(condition, filterValues) {
2333
+ return this.readLock(async () => {
2334
+ const set = /* @__PURE__ */ new Set();
2335
+ for await (const key of this.keysStream(condition, filterValues)) {
2336
+ set.add(key);
2337
+ }
2338
+ return set;
2085
2339
  });
2086
2340
  }
2087
2341
  async where(condition) {
2088
2342
  return this.readLock(async () => {
2089
- let result = null;
2090
- for (const k in condition) {
2091
- const key = k;
2092
- const value = condition[key];
2093
- const startNode = await this.verifierStartNode[key](value);
2094
- const endNode = await this.verifierEndNode[key](value);
2095
- const direction = this.verifierDirection[key];
2096
- const comparator = this.verifierMap[key];
2097
- const earlyTerminate = this.verifierEarlyTerminate[key];
2098
- const pairs = await this.getPairs(value, startNode, endNode, comparator, direction, earlyTerminate);
2099
- if (result === null) {
2100
- result = pairs;
2101
- } else {
2102
- const intersection = /* @__PURE__ */ new Map();
2103
- for (const [k2, v] of pairs) {
2104
- if (result.has(k2)) {
2105
- intersection.set(k2, v);
2106
- }
2107
- }
2108
- result = intersection;
2109
- }
2343
+ const map = /* @__PURE__ */ new Map();
2344
+ for await (const [key, value] of this.whereStream(condition)) {
2345
+ map.set(key, value);
2110
2346
  }
2111
- return result ?? /* @__PURE__ */ new Map();
2347
+ return map;
2112
2348
  });
2113
2349
  }
2114
2350
  async insert(key, value) {