dataply 0.0.11 → 0.0.13

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/cjs/index.js +443 -207
  2. package/package.json +2 -2
package/dist/cjs/index.js CHANGED
@@ -490,7 +490,7 @@ var CacheEntanglementAsync = class extends CacheEntanglement {
490
490
  return this.caches.get(key);
491
491
  }
492
492
  };
493
- var BPTree = class {
493
+ var BPTree = class _BPTree {
494
494
  _cachedRegexp;
495
495
  strategy;
496
496
  comparator;
@@ -507,9 +507,15 @@ var BPTree = class {
507
507
  lt: (nv, v) => this.comparator.isLower(nv, v),
508
508
  lte: (nv, v) => this.comparator.isLower(nv, v) || this.comparator.isSame(nv, v),
509
509
  equal: (nv, v) => this.comparator.isSame(nv, v),
510
- primaryEqual: (nv, v) => this.comparator.isPrimarySame(nv, v),
511
510
  notEqual: (nv, v) => this.comparator.isSame(nv, v) === false,
512
511
  or: (nv, v) => this.ensureValues(v).some((v2) => this.comparator.isSame(nv, v2)),
512
+ primaryGt: (nv, v) => this.comparator.isPrimaryHigher(nv, v),
513
+ primaryGte: (nv, v) => this.comparator.isPrimaryHigher(nv, v) || this.comparator.isPrimarySame(nv, v),
514
+ primaryLt: (nv, v) => this.comparator.isPrimaryLower(nv, v),
515
+ primaryLte: (nv, v) => this.comparator.isPrimaryLower(nv, v) || this.comparator.isPrimarySame(nv, v),
516
+ primaryEqual: (nv, v) => this.comparator.isPrimarySame(nv, v),
517
+ primaryNotEqual: (nv, v) => this.comparator.isPrimarySame(nv, v) === false,
518
+ primaryOr: (nv, v) => this.ensureValues(v).some((v2) => this.comparator.isPrimarySame(nv, v2)),
513
519
  like: (nv, v) => {
514
520
  const nodeValue = this.comparator.match(nv);
515
521
  const value = this.comparator.match(v);
@@ -524,9 +530,15 @@ var BPTree = class {
524
530
  lt: (v) => this.insertableNode(v),
525
531
  lte: (v) => this.insertableNode(v),
526
532
  equal: (v) => this.insertableNode(v),
527
- primaryEqual: (v) => this.insertableNodeByPrimary(v),
528
533
  notEqual: (v) => this.leftestNode(),
529
534
  or: (v) => this.insertableNode(this.lowestValue(this.ensureValues(v))),
535
+ primaryGt: (v) => this.insertableNodeByPrimary(v),
536
+ primaryGte: (v) => this.insertableNodeByPrimary(v),
537
+ primaryLt: (v) => this.insertableNodeByPrimary(v),
538
+ primaryLte: (v) => this.insertableRightestNodeByPrimary(v),
539
+ primaryEqual: (v) => this.insertableNodeByPrimary(v),
540
+ primaryNotEqual: (v) => this.leftestNode(),
541
+ primaryOr: (v) => this.insertableNodeByPrimary(this.lowestPrimaryValue(this.ensureValues(v))),
530
542
  like: (v) => this.leftestNode()
531
543
  };
532
544
  verifierEndNode = {
@@ -535,12 +547,20 @@ var BPTree = class {
535
547
  lt: (v) => null,
536
548
  lte: (v) => null,
537
549
  equal: (v) => this.insertableEndNode(v, this.verifierDirection.equal),
538
- primaryEqual: (v) => null,
539
550
  notEqual: (v) => null,
540
551
  or: (v) => this.insertableEndNode(
541
552
  this.highestValue(this.ensureValues(v)),
542
553
  this.verifierDirection.or
543
554
  ),
555
+ primaryGt: (v) => null,
556
+ primaryGte: (v) => null,
557
+ primaryLt: (v) => null,
558
+ primaryLte: (v) => null,
559
+ primaryEqual: (v) => null,
560
+ primaryNotEqual: (v) => null,
561
+ primaryOr: (v) => this.insertableRightestEndNodeByPrimary(
562
+ this.highestPrimaryValue(this.ensureValues(v))
563
+ ),
544
564
  like: (v) => null
545
565
  };
546
566
  verifierDirection = {
@@ -549,9 +569,15 @@ var BPTree = class {
549
569
  lt: -1,
550
570
  lte: -1,
551
571
  equal: 1,
552
- primaryEqual: 1,
553
572
  notEqual: 1,
554
573
  or: 1,
574
+ primaryGt: 1,
575
+ primaryGte: 1,
576
+ primaryLt: -1,
577
+ primaryLte: -1,
578
+ primaryEqual: 1,
579
+ primaryNotEqual: 1,
580
+ primaryOr: 1,
555
581
  like: 1
556
582
  };
557
583
  /**
@@ -565,11 +591,93 @@ var BPTree = class {
565
591
  lt: false,
566
592
  lte: false,
567
593
  equal: true,
568
- primaryEqual: true,
569
594
  notEqual: false,
570
595
  or: false,
596
+ primaryGt: false,
597
+ primaryGte: false,
598
+ primaryLt: false,
599
+ primaryLte: false,
600
+ primaryEqual: true,
601
+ primaryNotEqual: false,
602
+ primaryOr: false,
571
603
  like: false
572
604
  };
605
+ /**
606
+ * Priority map for condition types.
607
+ * Higher value = higher selectivity (fewer expected results).
608
+ * Used by `chooseDriver` to select the most selective index.
609
+ */
610
+ static conditionPriority = {
611
+ equal: 100,
612
+ primaryEqual: 100,
613
+ or: 80,
614
+ primaryOr: 80,
615
+ gt: 50,
616
+ gte: 50,
617
+ lt: 50,
618
+ lte: 50,
619
+ primaryGt: 50,
620
+ primaryGte: 50,
621
+ primaryLt: 50,
622
+ primaryLte: 50,
623
+ like: 30,
624
+ notEqual: 10,
625
+ primaryNotEqual: 10
626
+ };
627
+ /**
628
+ * Selects the best driver tree from multiple tree/condition pairs.
629
+ * Uses rule-based optimization to choose the tree with highest estimated selectivity.
630
+ *
631
+ * @param candidates Array of { tree, condition } pairs to evaluate
632
+ * @returns The candidate with highest priority condition, or null if empty
633
+ *
634
+ * @example
635
+ * ```typescript
636
+ * const driver = BPTreeSync.chooseDriver([
637
+ * { tree: idxId, condition: { equal: 100 } },
638
+ * { tree: idxAge, condition: { gt: 20 } }
639
+ * ])
640
+ * // Returns { tree: idxId, condition: { equal: 100 } } because 'equal' has higher priority
641
+ * ```
642
+ */
643
+ static ChooseDriver(candidates) {
644
+ if (candidates.length === 0) return null;
645
+ if (candidates.length === 1) return candidates[0];
646
+ let best = candidates[0];
647
+ let bestScore = 0;
648
+ for (const candidate of candidates) {
649
+ let score = 0;
650
+ for (const key in candidate.condition) {
651
+ const condKey = key;
652
+ const priority = _BPTree.conditionPriority[condKey] ?? 0;
653
+ if (priority > score) {
654
+ score = priority;
655
+ }
656
+ }
657
+ if (score > bestScore) {
658
+ bestScore = score;
659
+ best = candidate;
660
+ }
661
+ }
662
+ return best;
663
+ }
664
+ /**
665
+ * Verified if the value satisfies the condition.
666
+ *
667
+ * @param nodeValue The value to verify.
668
+ * @param condition The condition to verify against.
669
+ * @returns Returns true if the value satisfies the condition.
670
+ */
671
+ verify(nodeValue, condition) {
672
+ for (const key in condition) {
673
+ const verify = this.verifierMap[key];
674
+ const condValue = condition[key];
675
+ if (!verify(nodeValue, condValue)) {
676
+ return false;
677
+ }
678
+ }
679
+ return true;
680
+ }
573
681
  constructor(strategy, comparator, option) {
574
682
  this.strategy = strategy;
575
683
  this.comparator = comparator;
@@ -603,6 +711,14 @@ var BPTree = class {
603
711
  const i = v.length - 1;
604
712
  return [...v].sort((a, b) => this.comparator.asc(a, b))[i];
605
713
  }
714
+ lowestPrimaryValue(v) {
715
+ const i = 0;
716
+ return [...v].sort((a, b) => this.comparator.primaryAsc(a, b))[i];
717
+ }
718
+ highestPrimaryValue(v) {
719
+ const i = v.length - 1;
720
+ return [...v].sort((a, b) => this.comparator.primaryAsc(a, b))[i];
721
+ }
606
722
  _insertAtLeaf(node, key, value) {
607
723
  if (node.values.length) {
608
724
  for (let i = 0, len = node.values.length; i < len; i++) {
@@ -680,8 +796,7 @@ var BPTreeSync = class extends BPTree {
680
796
  capacity: this.option.capacity ?? 1e3
681
797
  });
682
798
  }
683
- getPairsRightToLeft(value, startNode, endNode, comparator, earlyTerminate) {
684
- const pairs = [];
799
+ *getPairsGenerator(value, startNode, endNode, comparator, direction, earlyTerminate) {
685
800
  let node = startNode;
686
801
  let done = false;
687
802
  let hasMatched = false;
@@ -690,71 +805,52 @@ var BPTreeSync = class extends BPTree {
690
805
  done = true;
691
806
  break;
692
807
  }
693
- let i = node.values.length;
694
- while (i--) {
695
- const nValue = node.values[i];
696
- const keys = node.keys[i];
697
- if (comparator(nValue, value)) {
698
- hasMatched = true;
699
- let j = keys.length;
700
- while (j--) {
701
- pairs.push([keys[j], nValue]);
808
+ const len = node.values.length;
809
+ if (direction === 1) {
810
+ for (let i = 0; i < len; i++) {
811
+ const nValue = node.values[i];
812
+ const keys = node.keys[i];
813
+ if (comparator(nValue, value)) {
814
+ hasMatched = true;
815
+ for (let j = 0; j < keys.length; j++) {
816
+ yield [keys[j], nValue];
817
+ }
818
+ } else if (earlyTerminate && hasMatched) {
819
+ done = true;
820
+ break;
821
+ }
822
+ }
823
+ } else {
824
+ let i = len;
825
+ while (i--) {
826
+ const nValue = node.values[i];
827
+ const keys = node.keys[i];
828
+ if (comparator(nValue, value)) {
829
+ hasMatched = true;
830
+ let j = keys.length;
831
+ while (j--) {
832
+ yield [keys[j], nValue];
833
+ }
834
+ } else if (earlyTerminate && hasMatched) {
835
+ done = true;
836
+ break;
702
837
  }
703
- } else if (earlyTerminate && hasMatched) {
704
- done = true;
705
- break;
706
838
  }
707
839
  }
708
840
  if (done) break;
709
- if (!node.prev) {
710
- done = true;
711
- break;
712
- }
713
- node = this.getNode(node.prev);
714
- }
715
- return new Map(pairs.reverse());
716
- }
717
- getPairsLeftToRight(value, startNode, endNode, comparator, earlyTerminate) {
718
- const pairs = [];
719
- let node = startNode;
720
- let done = false;
721
- let hasMatched = false;
722
- while (!done) {
723
- if (endNode && node.id === endNode.id) {
724
- done = true;
725
- break;
726
- }
727
- for (let i = 0, len = node.values.length; i < len; i++) {
728
- const nValue = node.values[i];
729
- const keys = node.keys[i];
730
- if (comparator(nValue, value)) {
731
- hasMatched = true;
732
- for (let j = 0, len2 = keys.length; j < len2; j++) {
733
- const key = keys[j];
734
- pairs.push([key, nValue]);
735
- }
736
- } else if (earlyTerminate && hasMatched) {
841
+ if (direction === 1) {
842
+ if (!node.next) {
737
843
  done = true;
738
844
  break;
739
845
  }
846
+ node = this.getNode(node.next);
847
+ } else {
848
+ if (!node.prev) {
849
+ done = true;
850
+ break;
851
+ }
852
+ node = this.getNode(node.prev);
740
853
  }
741
- if (done) break;
742
- if (!node.next) {
743
- done = true;
744
- break;
745
- }
746
- node = this.getNode(node.next);
747
- }
748
- return new Map(pairs);
749
- }
750
- getPairs(value, startNode, endNode, comparator, direction, earlyTerminate) {
751
- switch (direction) {
752
- case -1:
753
- return this.getPairsRightToLeft(value, startNode, endNode, comparator, earlyTerminate);
754
- case 1:
755
- return this.getPairsLeftToRight(value, startNode, endNode, comparator, earlyTerminate);
756
- default:
757
- throw new Error(`Direction must be -1 or 1. but got a ${direction}`);
758
854
  }
759
855
  }
760
856
  _createNodeId(isLeaf) {
@@ -1125,6 +1221,31 @@ var BPTreeSync = class extends BPTree {
1125
1221
  }
1126
1222
  return node;
1127
1223
  }
1224
+ insertableRightestNodeByPrimary(value) {
1225
+ let node = this.getNode(this.root.id);
1226
+ while (!node.leaf) {
1227
+ for (let i = 0, len = node.values.length; i < len; i++) {
1228
+ const nValue = node.values[i];
1229
+ const k = node.keys;
1230
+ if (this.comparator.isPrimaryLower(value, nValue)) {
1231
+ node = this.getNode(k[i]);
1232
+ break;
1233
+ }
1234
+ if (i + 1 === node.values.length) {
1235
+ node = this.getNode(k[i + 1]);
1236
+ break;
1237
+ }
1238
+ }
1239
+ }
1240
+ return node;
1241
+ }
1242
+ insertableRightestEndNodeByPrimary(value) {
1243
+ const node = this.insertableRightestNodeByPrimary(value);
1244
+ if (!node.next) {
1245
+ return null;
1246
+ }
1247
+ return this.getNode(node.next);
1248
+ }
1128
1249
  insertableEndNode(value, direction) {
1129
1250
  const insertableNode = this.insertableNode(value);
1130
1251
  let key;
@@ -1185,55 +1306,109 @@ var BPTreeSync = class extends BPTree {
1185
1306
  }
1186
1307
  this._nodeDeleteBuffer.clear();
1187
1308
  }
1188
- keys(condition, filterValues) {
1189
- for (const k in condition) {
1190
- const key = k;
1191
- const value = condition[key];
1192
- const startNode = this.verifierStartNode[key](value);
1193
- const endNode = this.verifierEndNode[key](value);
1194
- const direction = this.verifierDirection[key];
1195
- const comparator = this.verifierMap[key];
1196
- const earlyTerminate = this.verifierEarlyTerminate[key];
1197
- const pairs = this.getPairs(value, startNode, endNode, comparator, direction, earlyTerminate);
1198
- if (!filterValues) {
1199
- filterValues = new Set(pairs.keys());
1200
- } else {
1201
- const intersections = /* @__PURE__ */ new Set();
1202
- for (const key2 of filterValues) {
1203
- const has = pairs.has(key2);
1204
- if (has) {
1205
- intersections.add(key2);
1309
+ /**
1310
+ * Retrieves the value associated with the given key (PK).
1311
+ * Note: This method performs a full scan of leaf nodes as the tree is ordered by Value, not Key.
1312
+ *
1313
+ * @param key The key to search for.
1314
+ * @returns The value associated with the key, or undefined if not found.
1315
+ */
1316
+ get(key) {
1317
+ let node = this.leftestNode();
1318
+ while (true) {
1319
+ if (node.values) {
1320
+ const len = node.values.length;
1321
+ for (let i = 0; i < len; i++) {
1322
+ const keys = node.keys[i];
1323
+ for (let j = 0; j < keys.length; j++) {
1324
+ if (keys[j] === key) {
1325
+ return node.values[i];
1326
+ }
1206
1327
  }
1207
1328
  }
1208
- filterValues = intersections;
1209
1329
  }
1330
+ if (!node.next) break;
1331
+ node = this.getNode(node.next);
1210
1332
  }
1211
- return filterValues ?? /* @__PURE__ */ new Set([]);
1333
+ return void 0;
1212
1334
  }
1213
- where(condition) {
1214
- let result = null;
1215
- for (const k in condition) {
1216
- const key = k;
1217
- const value = condition[key];
1218
- const startNode = this.verifierStartNode[key](value);
1219
- const endNode = this.verifierEndNode[key](value);
1220
- const direction = this.verifierDirection[key];
1221
- const comparator = this.verifierMap[key];
1222
- const earlyTerminate = this.verifierEarlyTerminate[key];
1223
- const pairs = this.getPairs(value, startNode, endNode, comparator, direction, earlyTerminate);
1224
- if (result === null) {
1225
- result = pairs;
1226
- } else {
1227
- const intersection = /* @__PURE__ */ new Map();
1228
- for (const [k2, v] of pairs) {
1229
- if (result.has(k2)) {
1230
- intersection.set(k2, v);
1231
- }
1335
+ *keysStream(condition, filterValues, limit) {
1336
+ const stream = this.whereStream(condition, limit);
1337
+ const intersection = filterValues && filterValues.size > 0 ? filterValues : null;
1338
+ for (const [key] of stream) {
1339
+ if (intersection && !intersection.has(key)) {
1340
+ continue;
1341
+ }
1342
+ yield key;
1343
+ }
1344
+ }
1345
+ *whereStream(condition, limit) {
1346
+ let driverKey = null;
1347
+ if ("primaryEqual" in condition) driverKey = "primaryEqual";
1348
+ else if ("equal" in condition) driverKey = "equal";
1349
+ else if ("gt" in condition) driverKey = "gt";
1350
+ else if ("gte" in condition) driverKey = "gte";
1351
+ else if ("lt" in condition) driverKey = "lt";
1352
+ else if ("lte" in condition) driverKey = "lte";
1353
+ else if ("primaryGt" in condition) driverKey = "primaryGt";
1354
+ else if ("primaryGte" in condition) driverKey = "primaryGte";
1355
+ else if ("primaryLt" in condition) driverKey = "primaryLt";
1356
+ else if ("primaryLte" in condition) driverKey = "primaryLte";
1357
+ else if ("like" in condition) driverKey = "like";
1358
+ else if ("notEqual" in condition) driverKey = "notEqual";
1359
+ else if ("primaryNotEqual" in condition) driverKey = "primaryNotEqual";
1360
+ else if ("or" in condition) driverKey = "or";
1361
+ else if ("primaryOr" in condition) driverKey = "primaryOr";
1362
+ if (!driverKey) return;
1363
+ const value = condition[driverKey];
1364
+ const startNode = this.verifierStartNode[driverKey](value);
1365
+ const endNode = this.verifierEndNode[driverKey](value);
1366
+ const direction = this.verifierDirection[driverKey];
1367
+ const comparator = this.verifierMap[driverKey];
1368
+ const earlyTerminate = this.verifierEarlyTerminate[driverKey];
1369
+ const generator = this.getPairsGenerator(
1370
+ value,
1371
+ startNode,
1372
+ endNode,
1373
+ comparator,
1374
+ direction,
1375
+ earlyTerminate
1376
+ );
1377
+ let count = 0;
1378
+ for (const pair of generator) {
1379
+ const [k, v] = pair;
1380
+ let isMatch = true;
1381
+ for (const key in condition) {
1382
+ if (key === driverKey) continue;
1383
+ const verify = this.verifierMap[key];
1384
+ const condValue = condition[key];
1385
+ if (!verify(v, condValue)) {
1386
+ isMatch = false;
1387
+ break;
1388
+ }
1389
+ }
1390
+ if (isMatch) {
1391
+ yield pair;
1392
+ count++;
1393
+ if (limit !== void 0 && count >= limit) {
1394
+ break;
1232
1395
  }
1233
- result = intersection;
1234
1396
  }
1235
1397
  }
1236
- return result ?? /* @__PURE__ */ new Map();
1398
+ }
1399
+ keys(condition, filterValues) {
1400
+ const set = /* @__PURE__ */ new Set();
1401
+ for (const key of this.keysStream(condition, filterValues)) {
1402
+ set.add(key);
1403
+ }
1404
+ return set;
1405
+ }
1406
+ where(condition) {
1407
+ const map = /* @__PURE__ */ new Map();
1408
+ for (const [key, value] of this.whereStream(condition)) {
1409
+ map.set(key, value);
1410
+ }
1411
+ return map;
1237
1412
  }
1238
1413
  insert(key, value) {
1239
1414
  const before = this.insertableNode(value);
@@ -1604,8 +1779,7 @@ var BPTreeAsync = class extends BPTree {
1604
1779
  this.lock.writeUnlock(lockId);
1605
1780
  });
1606
1781
  }
1607
- async getPairsRightToLeft(value, startNode, endNode, comparator, earlyTerminate) {
1608
- const pairs = [];
1782
+ async *getPairsGenerator(value, startNode, endNode, comparator, direction, earlyTerminate) {
1609
1783
  let node = startNode;
1610
1784
  let done = false;
1611
1785
  let hasMatched = false;
@@ -1614,71 +1788,52 @@ var BPTreeAsync = class extends BPTree {
1614
1788
  done = true;
1615
1789
  break;
1616
1790
  }
1617
- let i = node.values.length;
1618
- while (i--) {
1619
- const nValue = node.values[i];
1620
- const keys = node.keys[i];
1621
- if (comparator(nValue, value)) {
1622
- hasMatched = true;
1623
- let j = keys.length;
1624
- while (j--) {
1625
- pairs.push([keys[j], nValue]);
1791
+ const len = node.values.length;
1792
+ if (direction === 1) {
1793
+ for (let i = 0; i < len; i++) {
1794
+ const nValue = node.values[i];
1795
+ const keys = node.keys[i];
1796
+ if (comparator(nValue, value)) {
1797
+ hasMatched = true;
1798
+ for (let j = 0; j < keys.length; j++) {
1799
+ yield [keys[j], nValue];
1800
+ }
1801
+ } else if (earlyTerminate && hasMatched) {
1802
+ done = true;
1803
+ break;
1804
+ }
1805
+ }
1806
+ } else {
1807
+ let i = len;
1808
+ while (i--) {
1809
+ const nValue = node.values[i];
1810
+ const keys = node.keys[i];
1811
+ if (comparator(nValue, value)) {
1812
+ hasMatched = true;
1813
+ let j = keys.length;
1814
+ while (j--) {
1815
+ yield [keys[j], nValue];
1816
+ }
1817
+ } else if (earlyTerminate && hasMatched) {
1818
+ done = true;
1819
+ break;
1626
1820
  }
1627
- } else if (earlyTerminate && hasMatched) {
1628
- done = true;
1629
- break;
1630
1821
  }
1631
1822
  }
1632
1823
  if (done) break;
1633
- if (!node.prev) {
1634
- done = true;
1635
- break;
1636
- }
1637
- node = await this.getNode(node.prev);
1638
- }
1639
- return new Map(pairs.reverse());
1640
- }
1641
- async getPairsLeftToRight(value, startNode, endNode, comparator, earlyTerminate) {
1642
- const pairs = [];
1643
- let node = startNode;
1644
- let done = false;
1645
- let hasMatched = false;
1646
- while (!done) {
1647
- if (endNode && node.id === endNode.id) {
1648
- done = true;
1649
- break;
1650
- }
1651
- for (let i = 0, len = node.values.length; i < len; i++) {
1652
- const nValue = node.values[i];
1653
- const keys = node.keys[i];
1654
- if (comparator(nValue, value)) {
1655
- hasMatched = true;
1656
- for (let j = 0, len2 = keys.length; j < len2; j++) {
1657
- const key = keys[j];
1658
- pairs.push([key, nValue]);
1659
- }
1660
- } else if (earlyTerminate && hasMatched) {
1824
+ if (direction === 1) {
1825
+ if (!node.next) {
1661
1826
  done = true;
1662
1827
  break;
1663
1828
  }
1829
+ node = await this.getNode(node.next);
1830
+ } else {
1831
+ if (!node.prev) {
1832
+ done = true;
1833
+ break;
1834
+ }
1835
+ node = await this.getNode(node.prev);
1664
1836
  }
1665
- if (done) break;
1666
- if (!node.next) {
1667
- done = true;
1668
- break;
1669
- }
1670
- node = await this.getNode(node.next);
1671
- }
1672
- return new Map(pairs);
1673
- }
1674
- async getPairs(value, startNode, endNode, comparator, direction, earlyTerminate) {
1675
- switch (direction) {
1676
- case -1:
1677
- return await this.getPairsRightToLeft(value, startNode, endNode, comparator, earlyTerminate);
1678
- case 1:
1679
- return await this.getPairsLeftToRight(value, startNode, endNode, comparator, earlyTerminate);
1680
- default:
1681
- throw new Error(`Direction must be -1 or 1. but got a ${direction}`);
1682
1837
  }
1683
1838
  }
1684
1839
  async _createNodeId(isLeaf) {
@@ -2049,6 +2204,31 @@ var BPTreeAsync = class extends BPTree {
2049
2204
  }
2050
2205
  return node;
2051
2206
  }
2207
+ async insertableRightestNodeByPrimary(value) {
2208
+ let node = await this.getNode(this.root.id);
2209
+ while (!node.leaf) {
2210
+ for (let i = 0, len = node.values.length; i < len; i++) {
2211
+ const nValue = node.values[i];
2212
+ const k = node.keys;
2213
+ if (this.comparator.isPrimaryLower(value, nValue)) {
2214
+ node = await this.getNode(k[i]);
2215
+ break;
2216
+ }
2217
+ if (i + 1 === node.values.length) {
2218
+ node = await this.getNode(k[i + 1]);
2219
+ break;
2220
+ }
2221
+ }
2222
+ }
2223
+ return node;
2224
+ }
2225
+ async insertableRightestEndNodeByPrimary(value) {
2226
+ const node = await this.insertableRightestNodeByPrimary(value);
2227
+ if (!node.next) {
2228
+ return null;
2229
+ }
2230
+ return await this.getNode(node.next);
2231
+ }
2052
2232
  async insertableEndNode(value, direction) {
2053
2233
  const insertableNode = await this.insertableNode(value);
2054
2234
  let key;
@@ -2109,58 +2289,114 @@ var BPTreeAsync = class extends BPTree {
2109
2289
  }
2110
2290
  this._nodeDeleteBuffer.clear();
2111
2291
  }
2112
- async keys(condition, filterValues) {
2292
+ /**
2293
+ * Retrieves the value associated with the given key (PK).
2294
+ * Note: This method performs a full scan of leaf nodes as the tree is ordered by Value, not Key.
2295
+ *
2296
+ * @param key The key to search for.
2297
+ * @returns The value associated with the key, or undefined if not found.
2298
+ */
2299
+ async get(key) {
2113
2300
  return this.readLock(async () => {
2114
- for (const k in condition) {
2115
- const key = k;
2116
- const value = condition[key];
2117
- const startNode = await this.verifierStartNode[key](value);
2118
- const endNode = await this.verifierEndNode[key](value);
2119
- const direction = this.verifierDirection[key];
2120
- const comparator = this.verifierMap[key];
2121
- const earlyTerminate = this.verifierEarlyTerminate[key];
2122
- const pairs = await this.getPairs(value, startNode, endNode, comparator, direction, earlyTerminate);
2123
- if (!filterValues) {
2124
- filterValues = new Set(pairs.keys());
2125
- } else {
2126
- const intersections = /* @__PURE__ */ new Set();
2127
- for (const key2 of filterValues) {
2128
- const has = pairs.has(key2);
2129
- if (has) {
2130
- intersections.add(key2);
2301
+ let node = await this.leftestNode();
2302
+ while (true) {
2303
+ if (node.values) {
2304
+ const len = node.values.length;
2305
+ for (let i = 0; i < len; i++) {
2306
+ const keys = node.keys[i];
2307
+ for (let j = 0; j < keys.length; j++) {
2308
+ if (keys[j] === key) {
2309
+ return node.values[i];
2310
+ }
2131
2311
  }
2132
2312
  }
2133
- filterValues = intersections;
2134
2313
  }
2314
+ if (!node.next) break;
2315
+ node = await this.getNode(node.next);
2135
2316
  }
2136
- return filterValues ?? /* @__PURE__ */ new Set([]);
2317
+ return void 0;
2318
+ });
2319
+ }
2320
+ async *keysStream(condition, filterValues, limit) {
2321
+ const stream = this.whereStream(condition, limit);
2322
+ const intersection = filterValues && filterValues.size > 0 ? filterValues : null;
2323
+ for await (const [key] of stream) {
2324
+ if (intersection && !intersection.has(key)) {
2325
+ continue;
2326
+ }
2327
+ yield key;
2328
+ }
2329
+ }
2330
+ async *whereStream(condition, limit) {
2331
+ let driverKey = null;
2332
+ if ("primaryEqual" in condition) driverKey = "primaryEqual";
2333
+ else if ("equal" in condition) driverKey = "equal";
2334
+ else if ("gt" in condition) driverKey = "gt";
2335
+ else if ("gte" in condition) driverKey = "gte";
2336
+ else if ("lt" in condition) driverKey = "lt";
2337
+ else if ("lte" in condition) driverKey = "lte";
2338
+ else if ("primaryGt" in condition) driverKey = "primaryGt";
2339
+ else if ("primaryGte" in condition) driverKey = "primaryGte";
2340
+ else if ("primaryLt" in condition) driverKey = "primaryLt";
2341
+ else if ("primaryLte" in condition) driverKey = "primaryLte";
2342
+ else if ("like" in condition) driverKey = "like";
2343
+ else if ("notEqual" in condition) driverKey = "notEqual";
2344
+ else if ("primaryNotEqual" in condition) driverKey = "primaryNotEqual";
2345
+ else if ("or" in condition) driverKey = "or";
2346
+ else if ("primaryOr" in condition) driverKey = "primaryOr";
2347
+ if (!driverKey) return;
2348
+ const value = condition[driverKey];
2349
+ const startNode = await this.verifierStartNode[driverKey](value);
2350
+ const endNode = await this.verifierEndNode[driverKey](value);
2351
+ const direction = this.verifierDirection[driverKey];
2352
+ const comparator = this.verifierMap[driverKey];
2353
+ const earlyTerminate = this.verifierEarlyTerminate[driverKey];
2354
+ const generator = this.getPairsGenerator(
2355
+ value,
2356
+ startNode,
2357
+ endNode,
2358
+ comparator,
2359
+ direction,
2360
+ earlyTerminate
2361
+ );
2362
+ let count = 0;
2363
+ for await (const pair of generator) {
2364
+ const [k, v] = pair;
2365
+ let isMatch = true;
2366
+ for (const key in condition) {
2367
+ if (key === driverKey) continue;
2368
+ const verify = this.verifierMap[key];
2369
+ const condValue = condition[key];
2370
+ if (!verify(v, condValue)) {
2371
+ isMatch = false;
2372
+ break;
2373
+ }
2374
+ }
2375
+ if (isMatch) {
2376
+ yield pair;
2377
+ count++;
2378
+ if (limit !== void 0 && count >= limit) {
2379
+ break;
2380
+ }
2381
+ }
2382
+ }
2383
+ }
2384
+ async keys(condition, filterValues) {
2385
+ return this.readLock(async () => {
2386
+ const set = /* @__PURE__ */ new Set();
2387
+ for await (const key of this.keysStream(condition, filterValues)) {
2388
+ set.add(key);
2389
+ }
2390
+ return set;
2137
2391
  });
2138
2392
  }
2139
2393
  async where(condition) {
2140
2394
  return this.readLock(async () => {
2141
- let result = null;
2142
- for (const k in condition) {
2143
- const key = k;
2144
- const value = condition[key];
2145
- const startNode = await this.verifierStartNode[key](value);
2146
- const endNode = await this.verifierEndNode[key](value);
2147
- const direction = this.verifierDirection[key];
2148
- const comparator = this.verifierMap[key];
2149
- const earlyTerminate = this.verifierEarlyTerminate[key];
2150
- const pairs = await this.getPairs(value, startNode, endNode, comparator, direction, earlyTerminate);
2151
- if (result === null) {
2152
- result = pairs;
2153
- } else {
2154
- const intersection = /* @__PURE__ */ new Map();
2155
- for (const [k2, v] of pairs) {
2156
- if (result.has(k2)) {
2157
- intersection.set(k2, v);
2158
- }
2159
- }
2160
- result = intersection;
2161
- }
2395
+ const map = /* @__PURE__ */ new Map();
2396
+ for await (const [key, value] of this.whereStream(condition)) {
2397
+ map.set(key, value);
2162
2398
  }
2163
- return result ?? /* @__PURE__ */ new Map();
2399
+ return map;
2164
2400
  });
2165
2401
  }
2166
2402
  async insert(key, value) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dataply",
3
- "version": "0.0.11",
3
+ "version": "0.0.13",
4
4
  "description": "A lightweight storage engine for Node.js with support for MVCC, WAL.",
5
5
  "license": "MIT",
6
6
  "author": "izure <admin@izure.org>",
@@ -47,6 +47,6 @@
47
47
  "cache-entanglement": "^1.7.1",
48
48
  "hookall": "^2.2.0",
49
49
  "ryoiki": "^1.2.0",
50
- "serializable-bptree": "^6.1.0"
50
+ "serializable-bptree": "^6.2.0"
51
51
  }
52
52
  }