serializable-bptree 8.3.3 → 8.3.5

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.
@@ -58,39 +58,125 @@ var StringComparator = class extends ValueComparator {
58
58
  var MVCCStrategy = class {
59
59
  };
60
60
  var LRUMap = class {
61
- cache = /* @__PURE__ */ new Map();
62
61
  capacity;
62
+ map;
63
+ head = null;
64
+ tail = null;
65
+ /**
66
+ * Creates an instance of LRUMap.
67
+ * @param capacity The maximum number of items the cache can hold.
68
+ */
63
69
  constructor(capacity) {
64
70
  this.capacity = capacity;
71
+ this.map = /* @__PURE__ */ new Map();
65
72
  }
66
- get(key) {
67
- if (!this.cache.has(key)) return void 0;
68
- const value = this.cache.get(key);
69
- this.cache.delete(key);
70
- this.cache.set(key, value);
71
- return value;
73
+ /**
74
+ * Promotes a node to the head of the linked list (marks as most recently used).
75
+ * @param node The node to promote.
76
+ */
77
+ promote(node) {
78
+ this.extract(node);
79
+ this.prepend(node);
72
80
  }
81
+ /**
82
+ * Disconnects a node from the doubly linked list.
83
+ * @param node The node to extract.
84
+ */
85
+ extract(node) {
86
+ if (node.prev) node.prev.next = node.next;
87
+ else this.head = node.next;
88
+ if (node.next) node.next.prev = node.prev;
89
+ else this.tail = node.prev;
90
+ node.prev = null;
91
+ node.next = null;
92
+ }
93
+ /**
94
+ * Inserts a node at the head of the doubly linked list.
95
+ * @param node The node to prepend.
96
+ */
97
+ prepend(node) {
98
+ node.next = this.head;
99
+ if (this.head) this.head.prev = node;
100
+ this.head = node;
101
+ if (!this.tail) this.tail = node;
102
+ }
103
+ /**
104
+ * Stores or updates a value by key.
105
+ * If the capacity is exceeded, the least recently used item (tail) is removed.
106
+ * @param key The key to store.
107
+ * @param value The value to store.
108
+ */
73
109
  set(key, value) {
74
- if (this.cache.has(key)) {
75
- this.cache.delete(key);
76
- } else if (this.cache.size >= this.capacity) {
77
- const oldestKey = this.cache.keys().next().value;
78
- if (oldestKey !== void 0) this.cache.delete(oldestKey);
110
+ const existing = this.map.get(key);
111
+ if (existing) {
112
+ existing.value = value;
113
+ this.promote(existing);
114
+ return;
79
115
  }
80
- this.cache.set(key, value);
81
- return this;
116
+ const newNode = { key, value, prev: null, next: null };
117
+ this.map.set(key, newNode);
118
+ this.prepend(newNode);
119
+ if (this.map.size > this.capacity && this.tail) {
120
+ this.map.delete(this.tail.key);
121
+ this.extract(this.tail);
122
+ }
123
+ }
124
+ /**
125
+ * Retrieves a value by key.
126
+ * Accessing the item moves it to the "most recently used" position.
127
+ * @param key The key to look for.
128
+ * @returns The value associated with the key, or undefined if not found.
129
+ */
130
+ get(key) {
131
+ const node = this.map.get(key);
132
+ if (!node) return void 0;
133
+ this.promote(node);
134
+ return node.value;
82
135
  }
136
+ /**
137
+ * Checks if a key exists in the cache without changing its access order.
138
+ * @param key The key to check.
139
+ * @returns True if the key exists, false otherwise.
140
+ */
83
141
  has(key) {
84
- return this.cache.has(key);
142
+ return this.map.has(key);
85
143
  }
144
+ /**
145
+ * Removes a key and its associated value from the cache.
146
+ * @param key The key to remove.
147
+ * @returns True if the key was found and removed, false otherwise.
148
+ */
86
149
  delete(key) {
87
- return this.cache.delete(key);
150
+ const node = this.map.get(key);
151
+ if (!node) return false;
152
+ this.extract(node);
153
+ this.map.delete(key);
154
+ return true;
88
155
  }
89
- clear() {
90
- this.cache.clear();
156
+ /**
157
+ * Returns an iterator of keys in the order of most recently used to least recently used.
158
+ * @returns An iterable iterator of keys.
159
+ */
160
+ *keys() {
161
+ let current = this.head;
162
+ while (current) {
163
+ yield current.key;
164
+ current = current.next;
165
+ }
91
166
  }
167
+ /**
168
+ * Returns the current number of items in the cache.
169
+ */
92
170
  get size() {
93
- return this.cache.size;
171
+ return this.map.size;
172
+ }
173
+ /**
174
+ * Clears all items from the cache.
175
+ */
176
+ clear() {
177
+ this.map.clear();
178
+ this.head = null;
179
+ this.tail = null;
94
180
  }
95
181
  };
96
182
  var MVCCTransaction = class {
@@ -1486,28 +1572,28 @@ var BPTreeTransaction = class _BPTreeTransaction {
1486
1572
  searchConfigs = {
1487
1573
  gt: {
1488
1574
  asc: {
1489
- start: (tx, v) => tx.insertableNodeByPrimary(v[0]),
1575
+ start: (tx, v) => tx.findUpperBoundLeaf(v[0]),
1490
1576
  end: () => null,
1491
1577
  direction: 1,
1492
1578
  earlyTerminate: false
1493
1579
  },
1494
1580
  desc: {
1495
1581
  start: (tx) => tx.rightestNode(),
1496
- end: (tx, v) => tx.insertableEndNode(v[0], -1),
1582
+ end: (tx, v) => tx.findOuterBoundaryLeaf(v[0], -1),
1497
1583
  direction: -1,
1498
1584
  earlyTerminate: true
1499
1585
  }
1500
1586
  },
1501
1587
  gte: {
1502
1588
  asc: {
1503
- start: (tx, v) => tx.insertableNodeByPrimary(v[0]),
1589
+ start: (tx, v) => tx.findLowerBoundLeaf(v[0]),
1504
1590
  end: () => null,
1505
1591
  direction: 1,
1506
1592
  earlyTerminate: false
1507
1593
  },
1508
1594
  desc: {
1509
1595
  start: (tx) => tx.rightestNode(),
1510
- end: (tx, v) => tx.insertableEndNode(v[0], -1),
1596
+ end: (tx, v) => tx.findOuterBoundaryLeaf(v[0], -1),
1511
1597
  direction: -1,
1512
1598
  earlyTerminate: true
1513
1599
  }
@@ -1515,12 +1601,12 @@ var BPTreeTransaction = class _BPTreeTransaction {
1515
1601
  lt: {
1516
1602
  asc: {
1517
1603
  start: (tx) => tx.leftestNode(),
1518
- end: (tx, v) => tx.insertableEndNode(v[0], 1),
1604
+ end: (tx, v) => tx.findOuterBoundaryLeaf(v[0], 1),
1519
1605
  direction: 1,
1520
1606
  earlyTerminate: true
1521
1607
  },
1522
1608
  desc: {
1523
- start: (tx, v) => tx.insertableNodeByPrimary(v[0]),
1609
+ start: (tx, v) => tx.findLowerBoundLeaf(v[0]),
1524
1610
  end: () => null,
1525
1611
  direction: -1,
1526
1612
  earlyTerminate: false
@@ -1529,12 +1615,12 @@ var BPTreeTransaction = class _BPTreeTransaction {
1529
1615
  lte: {
1530
1616
  asc: {
1531
1617
  start: (tx) => tx.leftestNode(),
1532
- end: (tx, v) => tx.insertableEndNode(v[0], 1),
1618
+ end: (tx, v) => tx.findOuterBoundaryLeaf(v[0], 1),
1533
1619
  direction: 1,
1534
1620
  earlyTerminate: true
1535
1621
  },
1536
1622
  desc: {
1537
- start: (tx, v) => tx.insertableRightestNodeByPrimary(v[0]),
1623
+ start: (tx, v) => tx.findUpperBoundLeaf(v[0]),
1538
1624
  end: () => null,
1539
1625
  direction: -1,
1540
1626
  earlyTerminate: false
@@ -1542,14 +1628,14 @@ var BPTreeTransaction = class _BPTreeTransaction {
1542
1628
  },
1543
1629
  equal: {
1544
1630
  asc: {
1545
- start: (tx, v) => tx.insertableNodeByPrimary(v[0]),
1546
- end: (tx, v) => tx.insertableEndNode(v[0], 1),
1631
+ start: (tx, v) => tx.findLowerBoundLeaf(v[0]),
1632
+ end: (tx, v) => tx.findOuterBoundaryLeaf(v[0], 1),
1547
1633
  direction: 1,
1548
1634
  earlyTerminate: true
1549
1635
  },
1550
1636
  desc: {
1551
- start: (tx, v) => tx.insertableEndNode(v[0], 1),
1552
- end: (tx, v) => tx.insertableEndNode(v[0], -1),
1637
+ start: (tx, v) => tx.findOuterBoundaryLeaf(v[0], 1),
1638
+ end: (tx, v) => tx.findOuterBoundaryLeaf(v[0], -1),
1553
1639
  direction: -1,
1554
1640
  earlyTerminate: true
1555
1641
  }
@@ -1570,42 +1656,42 @@ var BPTreeTransaction = class _BPTreeTransaction {
1570
1656
  },
1571
1657
  or: {
1572
1658
  asc: {
1573
- start: (tx, v) => tx.insertableNodeByPrimary(tx.lowestValue(v)),
1574
- end: (tx, v) => tx.insertableEndNode(tx.highestValue(v), 1),
1659
+ start: (tx, v) => tx.findLowerBoundLeaf(tx.lowestValue(v)),
1660
+ end: (tx, v) => tx.findOuterBoundaryLeaf(tx.highestValue(v), 1),
1575
1661
  direction: 1,
1576
1662
  earlyTerminate: false
1577
1663
  },
1578
1664
  desc: {
1579
- start: (tx, v) => tx.insertableEndNode(tx.highestValue(v), 1),
1580
- end: (tx, v) => tx.insertableEndNode(tx.lowestValue(v), -1),
1665
+ start: (tx, v) => tx.findOuterBoundaryLeaf(tx.highestValue(v), 1),
1666
+ end: (tx, v) => tx.findOuterBoundaryLeaf(tx.lowestValue(v), -1),
1581
1667
  direction: -1,
1582
1668
  earlyTerminate: false
1583
1669
  }
1584
1670
  },
1585
1671
  primaryGt: {
1586
1672
  asc: {
1587
- start: (tx, v) => tx.insertableRightestEndNodeByPrimary(v[0]),
1673
+ start: (tx, v) => tx.findUpperBoundLeaf(v[0]),
1588
1674
  end: () => null,
1589
1675
  direction: 1,
1590
1676
  earlyTerminate: false
1591
1677
  },
1592
1678
  desc: {
1593
1679
  start: (tx) => tx.rightestNode(),
1594
- end: (tx, v) => tx.insertableEndNode(v[0], -1),
1680
+ end: (tx, v) => tx.findOuterBoundaryLeaf(v[0], -1),
1595
1681
  direction: -1,
1596
1682
  earlyTerminate: true
1597
1683
  }
1598
1684
  },
1599
1685
  primaryGte: {
1600
1686
  asc: {
1601
- start: (tx, v) => tx.insertableNodeByPrimary(v[0]),
1687
+ start: (tx, v) => tx.findLowerBoundLeaf(v[0]),
1602
1688
  end: () => null,
1603
1689
  direction: 1,
1604
1690
  earlyTerminate: false
1605
1691
  },
1606
1692
  desc: {
1607
1693
  start: (tx) => tx.rightestNode(),
1608
- end: (tx, v) => tx.insertableEndNode(v[0], -1),
1694
+ end: (tx, v) => tx.findOuterBoundaryLeaf(v[0], -1),
1609
1695
  direction: -1,
1610
1696
  earlyTerminate: true
1611
1697
  }
@@ -1613,12 +1699,12 @@ var BPTreeTransaction = class _BPTreeTransaction {
1613
1699
  primaryLt: {
1614
1700
  asc: {
1615
1701
  start: (tx) => tx.leftestNode(),
1616
- end: (tx, v) => tx.insertableEndNode(v[0], 1),
1702
+ end: (tx, v) => tx.findOuterBoundaryLeaf(v[0], 1),
1617
1703
  direction: 1,
1618
1704
  earlyTerminate: true
1619
1705
  },
1620
1706
  desc: {
1621
- start: (tx, v) => tx.insertableNodeByPrimary(v[0]),
1707
+ start: (tx, v) => tx.findLowerBoundLeaf(v[0]),
1622
1708
  end: () => null,
1623
1709
  direction: -1,
1624
1710
  earlyTerminate: false
@@ -1627,12 +1713,12 @@ var BPTreeTransaction = class _BPTreeTransaction {
1627
1713
  primaryLte: {
1628
1714
  asc: {
1629
1715
  start: (tx) => tx.leftestNode(),
1630
- end: (tx, v) => tx.insertableEndNode(v[0], 1),
1716
+ end: (tx, v) => tx.findOuterBoundaryLeaf(v[0], 1),
1631
1717
  direction: 1,
1632
1718
  earlyTerminate: true
1633
1719
  },
1634
1720
  desc: {
1635
- start: (tx, v) => tx.insertableRightestNodeByPrimary(v[0]),
1721
+ start: (tx, v) => tx.findUpperBoundLeaf(v[0]),
1636
1722
  end: () => null,
1637
1723
  direction: -1,
1638
1724
  earlyTerminate: false
@@ -1640,14 +1726,14 @@ var BPTreeTransaction = class _BPTreeTransaction {
1640
1726
  },
1641
1727
  primaryEqual: {
1642
1728
  asc: {
1643
- start: (tx, v) => tx.insertableNodeByPrimary(v[0]),
1644
- end: (tx, v) => tx.insertableRightestEndNodeByPrimary(v[0]),
1729
+ start: (tx, v) => tx.findLowerBoundLeaf(v[0]),
1730
+ end: (tx, v) => tx.findOuterBoundaryLeaf(v[0], 1),
1645
1731
  direction: 1,
1646
1732
  earlyTerminate: true
1647
1733
  },
1648
1734
  desc: {
1649
- start: (tx, v) => tx.insertableRightestEndNodeByPrimary(v[0]),
1650
- end: (tx, v) => tx.insertableEndNode(v[0], -1),
1735
+ start: (tx, v) => tx.findUpperBoundLeaf(v[0]),
1736
+ end: (tx, v) => tx.findOuterBoundaryLeaf(v[0], -1),
1651
1737
  direction: -1,
1652
1738
  earlyTerminate: true
1653
1739
  }
@@ -1668,14 +1754,14 @@ var BPTreeTransaction = class _BPTreeTransaction {
1668
1754
  },
1669
1755
  primaryOr: {
1670
1756
  asc: {
1671
- start: (tx, v) => tx.insertableNodeByPrimary(tx.lowestPrimaryValue(v)),
1672
- end: (tx, v) => tx.insertableRightestEndNodeByPrimary(tx.highestPrimaryValue(v)),
1757
+ start: (tx, v) => tx.findLowerBoundLeaf(tx.lowestPrimaryValue(v)),
1758
+ end: (tx, v) => tx.findOuterBoundaryLeaf(tx.highestPrimaryValue(v), 1),
1673
1759
  direction: 1,
1674
1760
  earlyTerminate: false
1675
1761
  },
1676
1762
  desc: {
1677
- start: (tx, v) => tx.insertableRightestEndNodeByPrimary(tx.highestPrimaryValue(v)),
1678
- end: (tx, v) => tx.insertableEndNode(tx.lowestPrimaryValue(v), -1),
1763
+ start: (tx, v) => tx.findUpperBoundLeaf(tx.highestPrimaryValue(v)),
1764
+ end: (tx, v) => tx.findOuterBoundaryLeaf(tx.lowestPrimaryValue(v), -1),
1679
1765
  direction: -1,
1680
1766
  earlyTerminate: false
1681
1767
  }
@@ -1831,30 +1917,69 @@ var BPTreeTransaction = class _BPTreeTransaction {
1831
1917
  return JSON.parse(JSON.stringify(node));
1832
1918
  }
1833
1919
  /**
1834
- * Selects the best driver key from a condition object.
1835
- * The driver key determines the starting point and traversal direction for queries.
1836
- *
1920
+ * Resolves the best start/end configuration by independently examining
1921
+ * all conditions. Selects the tightest lower bound for start and the
1922
+ * tightest upper bound for end (in asc; reversed for desc).
1923
+ *
1837
1924
  * @param condition The condition to analyze.
1838
- * @returns The best driver key or null if no valid key found.
1925
+ * @param order The sort order ('asc' or 'desc').
1926
+ * @returns The resolved start/end keys, values, and traversal direction.
1839
1927
  */
1840
- getDriverKey(condition) {
1841
- if ("primaryEqual" in condition) return "primaryEqual";
1842
- if ("equal" in condition) return "equal";
1843
- if ("gt" in condition) return "gt";
1844
- if ("gte" in condition) return "gte";
1845
- if ("lt" in condition) return "lt";
1846
- if ("lte" in condition) return "lte";
1847
- if ("primaryGt" in condition) return "primaryGt";
1848
- if ("primaryGte" in condition) return "primaryGte";
1849
- if ("primaryLt" in condition) return "primaryLt";
1850
- if ("primaryLte" in condition) return "primaryLte";
1851
- if ("like" in condition) return "like";
1852
- if ("notEqual" in condition) return "notEqual";
1853
- if ("primaryNotEqual" in condition) return "primaryNotEqual";
1854
- if ("or" in condition) return "or";
1855
- if ("primaryOr" in condition) return "primaryOr";
1856
- return null;
1857
- }
1928
+ resolveStartEndConfigs(condition, order) {
1929
+ const direction = order === "asc" ? 1 : -1;
1930
+ const startCandidates = order === "asc" ? _BPTreeTransaction._lowerBoundKeys : _BPTreeTransaction._upperBoundKeys;
1931
+ const endCandidates = order === "asc" ? _BPTreeTransaction._upperBoundKeys : _BPTreeTransaction._lowerBoundKeys;
1932
+ let startKey = null;
1933
+ let endKey = null;
1934
+ let startValues = [];
1935
+ let endValues = [];
1936
+ for (let i = 0, len = startCandidates.length; i < len; i++) {
1937
+ const key = startCandidates[i];
1938
+ if (key in condition) {
1939
+ startKey = key;
1940
+ startValues = _BPTreeTransaction._multiValueKeys.includes(key) ? this.ensureValues(condition[key]) : [condition[key]];
1941
+ break;
1942
+ }
1943
+ }
1944
+ for (let i = 0, len = endCandidates.length; i < len; i++) {
1945
+ const key = endCandidates[i];
1946
+ if (key in condition) {
1947
+ endKey = key;
1948
+ endValues = _BPTreeTransaction._multiValueKeys.includes(key) ? this.ensureValues(condition[key]) : [condition[key]];
1949
+ break;
1950
+ }
1951
+ }
1952
+ return { startKey, endKey, startValues, endValues, direction };
1953
+ }
1954
+ // Lower bound providers, ordered by selectivity (tightest first)
1955
+ // Used for asc start / desc end
1956
+ static _lowerBoundKeys = [
1957
+ "primaryEqual",
1958
+ "equal",
1959
+ "primaryGt",
1960
+ "gt",
1961
+ "primaryGte",
1962
+ "gte",
1963
+ "primaryOr",
1964
+ "or"
1965
+ ];
1966
+ // Upper bound providers, ordered by selectivity (tightest first)
1967
+ // Used for asc end / desc start
1968
+ static _upperBoundKeys = [
1969
+ "primaryEqual",
1970
+ "equal",
1971
+ "primaryLt",
1972
+ "lt",
1973
+ "primaryLte",
1974
+ "lte",
1975
+ "primaryOr",
1976
+ "or"
1977
+ ];
1978
+ // Condition keys that accept multiple values (V[]) rather than a single value (V)
1979
+ static _multiValueKeys = [
1980
+ "or",
1981
+ "primaryOr"
1982
+ ];
1858
1983
  constructor(rootTx, mvccRoot, mvcc, strategy, comparator, option) {
1859
1984
  this.rootTx = rootTx === null ? this : rootTx;
1860
1985
  this.mvccRoot = mvccRoot;
@@ -2093,7 +2218,7 @@ var BPTreeSyncTransaction = class extends BPTreeTransaction {
2093
2218
  this._insertInParent(parentNode, midValue, newSiblingNodeRecursive);
2094
2219
  }
2095
2220
  }
2096
- insertableNode(value) {
2221
+ locateLeaf(value) {
2097
2222
  let node = this.getNode(this.rootId);
2098
2223
  while (!node.leaf) {
2099
2224
  const { index } = this._binarySearchValues(node.values, value, false, true);
@@ -2101,7 +2226,7 @@ var BPTreeSyncTransaction = class extends BPTreeTransaction {
2101
2226
  }
2102
2227
  return node;
2103
2228
  }
2104
- insertableNodeByPrimary(value) {
2229
+ findLowerBoundLeaf(value) {
2105
2230
  let node = this.getNode(this.rootId);
2106
2231
  while (!node.leaf) {
2107
2232
  const { index } = this._binarySearchValues(node.values, value, true, false);
@@ -2109,7 +2234,7 @@ var BPTreeSyncTransaction = class extends BPTreeTransaction {
2109
2234
  }
2110
2235
  return node;
2111
2236
  }
2112
- insertableRightestNodeByPrimary(value) {
2237
+ findUpperBoundLeaf(value) {
2113
2238
  let node = this.getNode(this.rootId);
2114
2239
  while (!node.leaf) {
2115
2240
  const { index } = this._binarySearchValues(node.values, value, true, true);
@@ -2117,15 +2242,8 @@ var BPTreeSyncTransaction = class extends BPTreeTransaction {
2117
2242
  }
2118
2243
  return node;
2119
2244
  }
2120
- insertableRightestEndNodeByPrimary(value) {
2121
- const node = this.insertableRightestNodeByPrimary(value);
2122
- if (!node.next) {
2123
- return null;
2124
- }
2125
- return this.getNode(node.next);
2126
- }
2127
- insertableEndNode(value, direction) {
2128
- const insertableNode = direction === -1 ? this.insertableNodeByPrimary(value) : this.insertableRightestNodeByPrimary(value);
2245
+ findOuterBoundaryLeaf(value, direction) {
2246
+ const insertableNode = direction === -1 ? this.findLowerBoundLeaf(value) : this.findUpperBoundLeaf(value);
2129
2247
  let key;
2130
2248
  switch (direction) {
2131
2249
  case -1:
@@ -2162,13 +2280,10 @@ var BPTreeSyncTransaction = class extends BPTreeTransaction {
2162
2280
  }
2163
2281
  return node;
2164
2282
  }
2165
- *getPairsGenerator(value, startNode, endNode, comparator, direction, earlyTerminate) {
2283
+ *getPairsGenerator(startNode, endNode, direction) {
2166
2284
  let node = startNode;
2167
- let done = false;
2168
- let hasMatched = false;
2169
- while (!done) {
2285
+ while (true) {
2170
2286
  if (endNode && node.id === endNode.id) {
2171
- done = true;
2172
2287
  break;
2173
2288
  }
2174
2289
  const len = node.values.length;
@@ -2176,14 +2291,8 @@ var BPTreeSyncTransaction = class extends BPTreeTransaction {
2176
2291
  for (let i = 0; i < len; i++) {
2177
2292
  const nValue = node.values[i];
2178
2293
  const keys = node.keys[i];
2179
- if (comparator(nValue, value)) {
2180
- hasMatched = true;
2181
- for (let j = 0; j < keys.length; j++) {
2182
- yield [keys[j], nValue];
2183
- }
2184
- } else if (earlyTerminate && hasMatched) {
2185
- done = true;
2186
- break;
2294
+ for (let j = 0, kLen = keys.length; j < kLen; j++) {
2295
+ yield [keys[j], nValue];
2187
2296
  }
2188
2297
  }
2189
2298
  } else {
@@ -2191,30 +2300,17 @@ var BPTreeSyncTransaction = class extends BPTreeTransaction {
2191
2300
  while (i--) {
2192
2301
  const nValue = node.values[i];
2193
2302
  const keys = node.keys[i];
2194
- if (comparator(nValue, value)) {
2195
- hasMatched = true;
2196
- let j = keys.length;
2197
- while (j--) {
2198
- yield [keys[j], nValue];
2199
- }
2200
- } else if (earlyTerminate && hasMatched) {
2201
- done = true;
2202
- break;
2303
+ let j = keys.length;
2304
+ while (j--) {
2305
+ yield [keys[j], nValue];
2203
2306
  }
2204
2307
  }
2205
2308
  }
2206
- if (done) break;
2207
2309
  if (direction === 1) {
2208
- if (!node.next) {
2209
- done = true;
2210
- break;
2211
- }
2310
+ if (!node.next) break;
2212
2311
  node = this.getNode(node.next);
2213
2312
  } else {
2214
- if (!node.prev) {
2215
- done = true;
2216
- break;
2217
- }
2313
+ if (!node.prev) break;
2218
2314
  node = this.getNode(node.prev);
2219
2315
  }
2220
2316
  }
@@ -2259,7 +2355,7 @@ var BPTreeSyncTransaction = class extends BPTreeTransaction {
2259
2355
  }
2260
2356
  }
2261
2357
  exists(key, value) {
2262
- const node = this.insertableNode(value);
2358
+ const node = this.locateLeaf(value);
2263
2359
  const { index, found } = this._binarySearchValues(node.values, value);
2264
2360
  if (found) {
2265
2361
  const keys = node.keys[index];
@@ -2303,49 +2399,36 @@ var BPTreeSyncTransaction = class extends BPTreeTransaction {
2303
2399
  }
2304
2400
  *whereStream(condition, options) {
2305
2401
  const { filterValues, limit, order = "asc" } = options ?? {};
2306
- const driverKey = this.getDriverKey(condition);
2307
- if (!driverKey) return;
2308
- const value = condition[driverKey];
2309
- const v = this.ensureValues(value);
2310
- const config = this.searchConfigs[driverKey][order];
2311
- let startNode = config.start(this, v);
2312
- let endNode = config.end(this, v);
2313
- const direction = config.direction;
2314
- const earlyTerminate = config.earlyTerminate;
2315
- if (order === "desc" && !startNode) {
2316
- startNode = this.rightestNode();
2317
- }
2318
- if (order === "asc" && !startNode) {
2319
- startNode = this.leftestNode();
2402
+ const conditionKeys = Object.keys(condition);
2403
+ if (conditionKeys.length === 0) return;
2404
+ const resolved = this.resolveStartEndConfigs(condition, order);
2405
+ const direction = resolved.direction;
2406
+ let startNode;
2407
+ if (resolved.startKey) {
2408
+ const startConfig = this.searchConfigs[resolved.startKey][order];
2409
+ startNode = startConfig.start(this, resolved.startValues);
2410
+ } else {
2411
+ startNode = order === "asc" ? this.leftestNode() : this.rightestNode();
2412
+ }
2413
+ let endNode = null;
2414
+ if (resolved.endKey) {
2415
+ const endConfig = this.searchConfigs[resolved.endKey][order];
2416
+ endNode = endConfig.end(this, resolved.endValues);
2320
2417
  }
2321
2418
  if (!startNode) return;
2322
- const comparator = this.verifierMap[driverKey];
2323
2419
  const generator = this.getPairsGenerator(
2324
- value,
2325
2420
  startNode,
2326
2421
  endNode,
2327
- comparator,
2328
- direction,
2329
- earlyTerminate
2422
+ direction
2330
2423
  );
2331
2424
  let count = 0;
2332
2425
  const intersection = filterValues && filterValues.size > 0 ? filterValues : null;
2333
2426
  for (const pair of generator) {
2334
- const [k, v2] = pair;
2427
+ const [k, v] = pair;
2335
2428
  if (intersection && !intersection.has(k)) {
2336
2429
  continue;
2337
2430
  }
2338
- let isMatch = true;
2339
- for (const key in condition) {
2340
- if (key === driverKey) continue;
2341
- const verify = this.verifierMap[key];
2342
- const condValue = condition[key];
2343
- if (!verify(v2, condValue)) {
2344
- isMatch = false;
2345
- break;
2346
- }
2347
- }
2348
- if (isMatch) {
2431
+ if (this.verify(v, condition)) {
2349
2432
  yield pair;
2350
2433
  count++;
2351
2434
  if (limit !== void 0 && count >= limit) {
@@ -2369,7 +2452,7 @@ var BPTreeSyncTransaction = class extends BPTreeTransaction {
2369
2452
  return map;
2370
2453
  }
2371
2454
  insert(key, value) {
2372
- let before = this.insertableNode(value);
2455
+ let before = this.locateLeaf(value);
2373
2456
  before = this._insertAtLeaf(before, key, value);
2374
2457
  if (before.values.length === this.order) {
2375
2458
  let after = this._createNode(
@@ -2397,7 +2480,7 @@ var BPTreeSyncTransaction = class extends BPTreeTransaction {
2397
2480
  let currentLeaf = null;
2398
2481
  let modified = false;
2399
2482
  for (const [key, value] of sorted) {
2400
- const targetLeaf = this.insertableNode(value);
2483
+ const targetLeaf = this.locateLeaf(value);
2401
2484
  if (currentLeaf !== null && currentLeaf.id === targetLeaf.id) {
2402
2485
  } else {
2403
2486
  if (currentLeaf !== null && modified) {
@@ -2639,7 +2722,7 @@ var BPTreeSyncTransaction = class extends BPTreeTransaction {
2639
2722
  if (value === void 0) {
2640
2723
  return;
2641
2724
  }
2642
- let node = this.insertableNodeByPrimary(value);
2725
+ let node = this.findLowerBoundLeaf(value);
2643
2726
  let found = false;
2644
2727
  while (true) {
2645
2728
  let i = node.values.length;
@@ -3229,7 +3312,7 @@ var BPTreeAsyncTransaction = class extends BPTreeTransaction {
3229
3312
  await this._insertInParent(parentNode, midValue, newSiblingNodeRecursive);
3230
3313
  }
3231
3314
  }
3232
- async insertableNode(value) {
3315
+ async locateLeaf(value) {
3233
3316
  let node = await this.getNode(this.rootId);
3234
3317
  while (!node.leaf) {
3235
3318
  const { index } = this._binarySearchValues(node.values, value, false, true);
@@ -3237,7 +3320,7 @@ var BPTreeAsyncTransaction = class extends BPTreeTransaction {
3237
3320
  }
3238
3321
  return node;
3239
3322
  }
3240
- async insertableNodeByPrimary(value) {
3323
+ async findLowerBoundLeaf(value) {
3241
3324
  let node = await this.getNode(this.rootId);
3242
3325
  while (!node.leaf) {
3243
3326
  const { index } = this._binarySearchValues(node.values, value, true, false);
@@ -3245,7 +3328,7 @@ var BPTreeAsyncTransaction = class extends BPTreeTransaction {
3245
3328
  }
3246
3329
  return node;
3247
3330
  }
3248
- async insertableRightestNodeByPrimary(value) {
3331
+ async findUpperBoundLeaf(value) {
3249
3332
  let node = await this.getNode(this.rootId);
3250
3333
  while (!node.leaf) {
3251
3334
  const { index } = this._binarySearchValues(node.values, value, true, true);
@@ -3253,15 +3336,8 @@ var BPTreeAsyncTransaction = class extends BPTreeTransaction {
3253
3336
  }
3254
3337
  return node;
3255
3338
  }
3256
- async insertableRightestEndNodeByPrimary(value) {
3257
- const node = await this.insertableRightestNodeByPrimary(value);
3258
- if (!node.next) {
3259
- return null;
3260
- }
3261
- return await this.getNode(node.next);
3262
- }
3263
- async insertableEndNode(value, direction) {
3264
- const insertableNode = direction === -1 ? await this.insertableNodeByPrimary(value) : await this.insertableRightestNodeByPrimary(value);
3339
+ async findOuterBoundaryLeaf(value, direction) {
3340
+ const insertableNode = direction === -1 ? await this.findLowerBoundLeaf(value) : await this.findUpperBoundLeaf(value);
3265
3341
  let key;
3266
3342
  switch (direction) {
3267
3343
  case -1:
@@ -3298,22 +3374,19 @@ var BPTreeAsyncTransaction = class extends BPTreeTransaction {
3298
3374
  }
3299
3375
  return node;
3300
3376
  }
3301
- async *getPairsGenerator(value, startNode, endNode, comparator, direction, earlyTerminate) {
3377
+ async *getPairsGenerator(startNode, endNode, direction) {
3302
3378
  let node = startNode;
3303
- let done = false;
3304
- let hasMatched = false;
3305
3379
  let nextNodePromise = null;
3306
- while (!done) {
3380
+ while (true) {
3307
3381
  if (endNode && node.id === endNode.id) {
3308
- done = true;
3309
3382
  break;
3310
3383
  }
3311
3384
  if (direction === 1) {
3312
- if (node.next && !done) {
3385
+ if (node.next) {
3313
3386
  nextNodePromise = this.getNode(node.next);
3314
3387
  }
3315
3388
  } else {
3316
- if (node.prev && !done) {
3389
+ if (node.prev) {
3317
3390
  nextNodePromise = this.getNode(node.prev);
3318
3391
  }
3319
3392
  }
@@ -3322,14 +3395,8 @@ var BPTreeAsyncTransaction = class extends BPTreeTransaction {
3322
3395
  for (let i = 0; i < len; i++) {
3323
3396
  const nValue = node.values[i];
3324
3397
  const keys = node.keys[i];
3325
- if (comparator(nValue, value)) {
3326
- hasMatched = true;
3327
- for (let j = 0; j < keys.length; j++) {
3328
- yield [keys[j], nValue];
3329
- }
3330
- } else if (earlyTerminate && hasMatched) {
3331
- done = true;
3332
- break;
3398
+ for (let j = 0, kLen = keys.length; j < kLen; j++) {
3399
+ yield [keys[j], nValue];
3333
3400
  }
3334
3401
  }
3335
3402
  } else {
@@ -3337,27 +3404,17 @@ var BPTreeAsyncTransaction = class extends BPTreeTransaction {
3337
3404
  while (i--) {
3338
3405
  const nValue = node.values[i];
3339
3406
  const keys = node.keys[i];
3340
- if (comparator(nValue, value)) {
3341
- hasMatched = true;
3342
- let j = keys.length;
3343
- while (j--) {
3344
- yield [keys[j], nValue];
3345
- }
3346
- } else if (earlyTerminate && hasMatched) {
3347
- done = true;
3348
- break;
3407
+ let j = keys.length;
3408
+ while (j--) {
3409
+ yield [keys[j], nValue];
3349
3410
  }
3350
3411
  }
3351
3412
  }
3352
- if (done) {
3353
- if (nextNodePromise) await nextNodePromise;
3354
- break;
3355
- }
3356
3413
  if (nextNodePromise) {
3357
3414
  node = await nextNodePromise;
3358
3415
  nextNodePromise = null;
3359
3416
  } else {
3360
- done = true;
3417
+ break;
3361
3418
  }
3362
3419
  }
3363
3420
  }
@@ -3401,7 +3458,7 @@ var BPTreeAsyncTransaction = class extends BPTreeTransaction {
3401
3458
  }
3402
3459
  }
3403
3460
  async exists(key, value) {
3404
- const node = await this.insertableNode(value);
3461
+ const node = await this.locateLeaf(value);
3405
3462
  const { index, found } = this._binarySearchValues(node.values, value);
3406
3463
  if (found) {
3407
3464
  const keys = node.keys[index];
@@ -3445,49 +3502,36 @@ var BPTreeAsyncTransaction = class extends BPTreeTransaction {
3445
3502
  }
3446
3503
  async *whereStream(condition, options) {
3447
3504
  const { filterValues, limit, order = "asc" } = options ?? {};
3448
- const driverKey = this.getDriverKey(condition);
3449
- if (!driverKey) return;
3450
- const value = condition[driverKey];
3451
- const v = this.ensureValues(value);
3452
- const config = this.searchConfigs[driverKey][order];
3453
- let startNode = await config.start(this, v);
3454
- let endNode = await config.end(this, v);
3455
- const direction = config.direction;
3456
- const earlyTerminate = config.earlyTerminate;
3457
- if (order === "desc" && !startNode) {
3458
- startNode = await this.rightestNode();
3459
- }
3460
- if (order === "asc" && !startNode) {
3461
- startNode = await this.leftestNode();
3505
+ const conditionKeys = Object.keys(condition);
3506
+ if (conditionKeys.length === 0) return;
3507
+ const resolved = this.resolveStartEndConfigs(condition, order);
3508
+ const direction = resolved.direction;
3509
+ let startNode;
3510
+ if (resolved.startKey) {
3511
+ const startConfig = this.searchConfigs[resolved.startKey][order];
3512
+ startNode = await startConfig.start(this, resolved.startValues);
3513
+ } else {
3514
+ startNode = order === "asc" ? await this.leftestNode() : await this.rightestNode();
3515
+ }
3516
+ let endNode = null;
3517
+ if (resolved.endKey) {
3518
+ const endConfig = this.searchConfigs[resolved.endKey][order];
3519
+ endNode = await endConfig.end(this, resolved.endValues);
3462
3520
  }
3463
3521
  if (!startNode) return;
3464
- const comparator = this.verifierMap[driverKey];
3465
3522
  const generator = this.getPairsGenerator(
3466
- value,
3467
3523
  startNode,
3468
3524
  endNode,
3469
- comparator,
3470
- direction,
3471
- earlyTerminate
3525
+ direction
3472
3526
  );
3473
3527
  let count = 0;
3474
3528
  const intersection = filterValues && filterValues.size > 0 ? filterValues : null;
3475
3529
  for await (const pair of generator) {
3476
- const [k, v2] = pair;
3530
+ const [k, v] = pair;
3477
3531
  if (intersection && !intersection.has(k)) {
3478
3532
  continue;
3479
3533
  }
3480
- let isMatch = true;
3481
- for (const key in condition) {
3482
- if (key === driverKey) continue;
3483
- const verify = this.verifierMap[key];
3484
- const condValue = condition[key];
3485
- if (!verify(v2, condValue)) {
3486
- isMatch = false;
3487
- break;
3488
- }
3489
- }
3490
- if (isMatch) {
3534
+ if (this.verify(v, condition)) {
3491
3535
  yield pair;
3492
3536
  count++;
3493
3537
  if (limit !== void 0 && count >= limit) {
@@ -3512,7 +3556,7 @@ var BPTreeAsyncTransaction = class extends BPTreeTransaction {
3512
3556
  }
3513
3557
  async insert(key, value) {
3514
3558
  return this.writeLock(0, async () => {
3515
- let before = await this.insertableNode(value);
3559
+ let before = await this.locateLeaf(value);
3516
3560
  before = await this._insertAtLeaf(before, key, value);
3517
3561
  if (before.values.length === this.order) {
3518
3562
  let after = await this._createNode(
@@ -3542,7 +3586,7 @@ var BPTreeAsyncTransaction = class extends BPTreeTransaction {
3542
3586
  let currentLeaf = null;
3543
3587
  let modified = false;
3544
3588
  for (const [key, value] of sorted) {
3545
- const targetLeaf = await this.insertableNode(value);
3589
+ const targetLeaf = await this.locateLeaf(value);
3546
3590
  if (currentLeaf !== null && currentLeaf.id === targetLeaf.id) {
3547
3591
  } else {
3548
3592
  if (currentLeaf !== null && modified) {
@@ -3786,7 +3830,7 @@ var BPTreeAsyncTransaction = class extends BPTreeTransaction {
3786
3830
  if (value === void 0) {
3787
3831
  return;
3788
3832
  }
3789
- let node = await this.insertableNodeByPrimary(value);
3833
+ let node = await this.findLowerBoundLeaf(value);
3790
3834
  let found = false;
3791
3835
  while (true) {
3792
3836
  let i = node.values.length;