serializable-bptree 8.3.4 → 8.4.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.
@@ -1608,28 +1608,28 @@ var BPTreeTransaction = class _BPTreeTransaction {
1608
1608
  searchConfigs = {
1609
1609
  gt: {
1610
1610
  asc: {
1611
- start: (tx, v) => tx.insertableRightestNodeByPrimary(v[0]),
1611
+ start: (tx, v) => tx.findUpperBoundLeaf(v[0]),
1612
1612
  end: () => null,
1613
1613
  direction: 1,
1614
1614
  earlyTerminate: false
1615
1615
  },
1616
1616
  desc: {
1617
1617
  start: (tx) => tx.rightestNode(),
1618
- end: (tx, v) => tx.insertableEndNode(v[0], -1),
1618
+ end: (tx, v) => tx.findOuterBoundaryLeaf(v[0], -1),
1619
1619
  direction: -1,
1620
1620
  earlyTerminate: true
1621
1621
  }
1622
1622
  },
1623
1623
  gte: {
1624
1624
  asc: {
1625
- start: (tx, v) => tx.insertableNodeByPrimary(v[0]),
1625
+ start: (tx, v) => tx.findLowerBoundLeaf(v[0]),
1626
1626
  end: () => null,
1627
1627
  direction: 1,
1628
1628
  earlyTerminate: false
1629
1629
  },
1630
1630
  desc: {
1631
1631
  start: (tx) => tx.rightestNode(),
1632
- end: (tx, v) => tx.insertableEndNode(v[0], -1),
1632
+ end: (tx, v) => tx.findOuterBoundaryLeaf(v[0], -1),
1633
1633
  direction: -1,
1634
1634
  earlyTerminate: true
1635
1635
  }
@@ -1637,12 +1637,12 @@ var BPTreeTransaction = class _BPTreeTransaction {
1637
1637
  lt: {
1638
1638
  asc: {
1639
1639
  start: (tx) => tx.leftestNode(),
1640
- end: (tx, v) => tx.insertableEndNode(v[0], 1),
1640
+ end: (tx, v) => tx.findOuterBoundaryLeaf(v[0], 1),
1641
1641
  direction: 1,
1642
1642
  earlyTerminate: true
1643
1643
  },
1644
1644
  desc: {
1645
- start: (tx, v) => tx.insertableNodeByPrimary(v[0]),
1645
+ start: (tx, v) => tx.findLowerBoundLeaf(v[0]),
1646
1646
  end: () => null,
1647
1647
  direction: -1,
1648
1648
  earlyTerminate: false
@@ -1651,12 +1651,12 @@ var BPTreeTransaction = class _BPTreeTransaction {
1651
1651
  lte: {
1652
1652
  asc: {
1653
1653
  start: (tx) => tx.leftestNode(),
1654
- end: (tx, v) => tx.insertableEndNode(v[0], 1),
1654
+ end: (tx, v) => tx.findOuterBoundaryLeaf(v[0], 1),
1655
1655
  direction: 1,
1656
1656
  earlyTerminate: true
1657
1657
  },
1658
1658
  desc: {
1659
- start: (tx, v) => tx.insertableRightestNodeByPrimary(v[0]),
1659
+ start: (tx, v) => tx.findUpperBoundLeaf(v[0]),
1660
1660
  end: () => null,
1661
1661
  direction: -1,
1662
1662
  earlyTerminate: false
@@ -1664,14 +1664,14 @@ var BPTreeTransaction = class _BPTreeTransaction {
1664
1664
  },
1665
1665
  equal: {
1666
1666
  asc: {
1667
- start: (tx, v) => tx.insertableNodeByPrimary(v[0]),
1668
- end: (tx, v) => tx.insertableEndNode(v[0], 1),
1667
+ start: (tx, v) => tx.findLowerBoundLeaf(v[0]),
1668
+ end: (tx, v) => tx.findOuterBoundaryLeaf(v[0], 1),
1669
1669
  direction: 1,
1670
1670
  earlyTerminate: true
1671
1671
  },
1672
1672
  desc: {
1673
- start: (tx, v) => tx.insertableEndNode(v[0], 1),
1674
- end: (tx, v) => tx.insertableEndNode(v[0], -1),
1673
+ start: (tx, v) => tx.findOuterBoundaryLeaf(v[0], 1),
1674
+ end: (tx, v) => tx.findOuterBoundaryLeaf(v[0], -1),
1675
1675
  direction: -1,
1676
1676
  earlyTerminate: true
1677
1677
  }
@@ -1692,42 +1692,42 @@ var BPTreeTransaction = class _BPTreeTransaction {
1692
1692
  },
1693
1693
  or: {
1694
1694
  asc: {
1695
- start: (tx, v) => tx.insertableNodeByPrimary(tx.lowestValue(v)),
1696
- end: (tx, v) => tx.insertableEndNode(tx.highestValue(v), 1),
1695
+ start: (tx, v) => tx.findLowerBoundLeaf(tx.lowestValue(v)),
1696
+ end: (tx, v) => tx.findOuterBoundaryLeaf(tx.highestValue(v), 1),
1697
1697
  direction: 1,
1698
1698
  earlyTerminate: false
1699
1699
  },
1700
1700
  desc: {
1701
- start: (tx, v) => tx.insertableEndNode(tx.highestValue(v), 1),
1702
- end: (tx, v) => tx.insertableEndNode(tx.lowestValue(v), -1),
1701
+ start: (tx, v) => tx.findOuterBoundaryLeaf(tx.highestValue(v), 1),
1702
+ end: (tx, v) => tx.findOuterBoundaryLeaf(tx.lowestValue(v), -1),
1703
1703
  direction: -1,
1704
1704
  earlyTerminate: false
1705
1705
  }
1706
1706
  },
1707
1707
  primaryGt: {
1708
1708
  asc: {
1709
- start: (tx, v) => tx.insertableRightestNodeByPrimary(v[0]),
1709
+ start: (tx, v) => tx.findUpperBoundLeaf(v[0]),
1710
1710
  end: () => null,
1711
1711
  direction: 1,
1712
1712
  earlyTerminate: false
1713
1713
  },
1714
1714
  desc: {
1715
1715
  start: (tx) => tx.rightestNode(),
1716
- end: (tx, v) => tx.insertableEndNode(v[0], -1),
1716
+ end: (tx, v) => tx.findOuterBoundaryLeaf(v[0], -1),
1717
1717
  direction: -1,
1718
1718
  earlyTerminate: true
1719
1719
  }
1720
1720
  },
1721
1721
  primaryGte: {
1722
1722
  asc: {
1723
- start: (tx, v) => tx.insertableNodeByPrimary(v[0]),
1723
+ start: (tx, v) => tx.findLowerBoundLeaf(v[0]),
1724
1724
  end: () => null,
1725
1725
  direction: 1,
1726
1726
  earlyTerminate: false
1727
1727
  },
1728
1728
  desc: {
1729
1729
  start: (tx) => tx.rightestNode(),
1730
- end: (tx, v) => tx.insertableEndNode(v[0], -1),
1730
+ end: (tx, v) => tx.findOuterBoundaryLeaf(v[0], -1),
1731
1731
  direction: -1,
1732
1732
  earlyTerminate: true
1733
1733
  }
@@ -1735,12 +1735,12 @@ var BPTreeTransaction = class _BPTreeTransaction {
1735
1735
  primaryLt: {
1736
1736
  asc: {
1737
1737
  start: (tx) => tx.leftestNode(),
1738
- end: (tx, v) => tx.insertableEndNode(v[0], 1),
1738
+ end: (tx, v) => tx.findOuterBoundaryLeaf(v[0], 1),
1739
1739
  direction: 1,
1740
1740
  earlyTerminate: true
1741
1741
  },
1742
1742
  desc: {
1743
- start: (tx, v) => tx.insertableNodeByPrimary(v[0]),
1743
+ start: (tx, v) => tx.findLowerBoundLeaf(v[0]),
1744
1744
  end: () => null,
1745
1745
  direction: -1,
1746
1746
  earlyTerminate: false
@@ -1749,12 +1749,12 @@ var BPTreeTransaction = class _BPTreeTransaction {
1749
1749
  primaryLte: {
1750
1750
  asc: {
1751
1751
  start: (tx) => tx.leftestNode(),
1752
- end: (tx, v) => tx.insertableEndNode(v[0], 1),
1752
+ end: (tx, v) => tx.findOuterBoundaryLeaf(v[0], 1),
1753
1753
  direction: 1,
1754
1754
  earlyTerminate: true
1755
1755
  },
1756
1756
  desc: {
1757
- start: (tx, v) => tx.insertableRightestNodeByPrimary(v[0]),
1757
+ start: (tx, v) => tx.findUpperBoundLeaf(v[0]),
1758
1758
  end: () => null,
1759
1759
  direction: -1,
1760
1760
  earlyTerminate: false
@@ -1762,14 +1762,14 @@ var BPTreeTransaction = class _BPTreeTransaction {
1762
1762
  },
1763
1763
  primaryEqual: {
1764
1764
  asc: {
1765
- start: (tx, v) => tx.insertableNodeByPrimary(v[0]),
1766
- end: (tx, v) => tx.insertableRightestEndNodeByPrimary(v[0]),
1765
+ start: (tx, v) => tx.findLowerBoundLeaf(v[0]),
1766
+ end: (tx, v) => tx.findOuterBoundaryLeaf(v[0], 1),
1767
1767
  direction: 1,
1768
1768
  earlyTerminate: true
1769
1769
  },
1770
1770
  desc: {
1771
- start: (tx, v) => tx.insertableRightestNodeByPrimary(v[0]),
1772
- end: (tx, v) => tx.insertableEndNode(v[0], -1),
1771
+ start: (tx, v) => tx.findUpperBoundLeaf(v[0]),
1772
+ end: (tx, v) => tx.findOuterBoundaryLeaf(v[0], -1),
1773
1773
  direction: -1,
1774
1774
  earlyTerminate: true
1775
1775
  }
@@ -1790,14 +1790,14 @@ var BPTreeTransaction = class _BPTreeTransaction {
1790
1790
  },
1791
1791
  primaryOr: {
1792
1792
  asc: {
1793
- start: (tx, v) => tx.insertableNodeByPrimary(tx.lowestPrimaryValue(v)),
1794
- end: (tx, v) => tx.insertableRightestEndNodeByPrimary(tx.highestPrimaryValue(v)),
1793
+ start: (tx, v) => tx.findLowerBoundLeaf(tx.lowestPrimaryValue(v)),
1794
+ end: (tx, v) => tx.findOuterBoundaryLeaf(tx.highestPrimaryValue(v), 1),
1795
1795
  direction: 1,
1796
1796
  earlyTerminate: false
1797
1797
  },
1798
1798
  desc: {
1799
- start: (tx, v) => tx.insertableRightestNodeByPrimary(tx.highestPrimaryValue(v)),
1800
- end: (tx, v) => tx.insertableEndNode(tx.lowestPrimaryValue(v), -1),
1799
+ start: (tx, v) => tx.findUpperBoundLeaf(tx.highestPrimaryValue(v)),
1800
+ end: (tx, v) => tx.findOuterBoundaryLeaf(tx.lowestPrimaryValue(v), -1),
1801
1801
  direction: -1,
1802
1802
  earlyTerminate: false
1803
1803
  }
@@ -1924,30 +1924,22 @@ var BPTreeTransaction = class _BPTreeTransaction {
1924
1924
  */
1925
1925
  _insertValueIntoLeaf(leaf, key, value) {
1926
1926
  if (leaf.values.length) {
1927
- for (let i = 0, len = leaf.values.length; i < len; i++) {
1928
- const nValue = leaf.values[i];
1929
- if (this.comparator.isSame(value, nValue)) {
1930
- if (leaf.keys[i].includes(key)) {
1931
- return false;
1932
- }
1933
- leaf.keys[i].push(key);
1934
- return true;
1935
- } else if (this.comparator.isLower(value, nValue)) {
1936
- leaf.values.splice(i, 0, value);
1937
- leaf.keys.splice(i, 0, [key]);
1938
- return true;
1939
- } else if (i + 1 === leaf.values.length) {
1940
- leaf.values.push(value);
1941
- leaf.keys.push([key]);
1942
- return true;
1927
+ const { index, found } = this._binarySearchValues(leaf.values, value);
1928
+ if (found) {
1929
+ if (leaf.keys[index].includes(key)) {
1930
+ return false;
1943
1931
  }
1932
+ leaf.keys[index].push(key);
1933
+ return true;
1944
1934
  }
1935
+ leaf.values.splice(index, 0, value);
1936
+ leaf.keys.splice(index, 0, [key]);
1937
+ return true;
1945
1938
  } else {
1946
1939
  leaf.values = [value];
1947
1940
  leaf.keys = [[key]];
1948
1941
  return true;
1949
1942
  }
1950
- return false;
1951
1943
  }
1952
1944
  _cloneNode(node) {
1953
1945
  return JSON.parse(JSON.stringify(node));
@@ -1969,17 +1961,19 @@ var BPTreeTransaction = class _BPTreeTransaction {
1969
1961
  let endKey = null;
1970
1962
  let startValues = [];
1971
1963
  let endValues = [];
1972
- for (const key of startCandidates) {
1964
+ for (let i = 0, len = startCandidates.length; i < len; i++) {
1965
+ const key = startCandidates[i];
1973
1966
  if (key in condition) {
1974
1967
  startKey = key;
1975
- startValues = this.ensureValues(condition[key]);
1968
+ startValues = _BPTreeTransaction._multiValueKeys.includes(key) ? this.ensureValues(condition[key]) : [condition[key]];
1976
1969
  break;
1977
1970
  }
1978
1971
  }
1979
- for (const key of endCandidates) {
1972
+ for (let i = 0, len = endCandidates.length; i < len; i++) {
1973
+ const key = endCandidates[i];
1980
1974
  if (key in condition) {
1981
1975
  endKey = key;
1982
- endValues = this.ensureValues(condition[key]);
1976
+ endValues = _BPTreeTransaction._multiValueKeys.includes(key) ? this.ensureValues(condition[key]) : [condition[key]];
1983
1977
  break;
1984
1978
  }
1985
1979
  }
@@ -2009,6 +2003,11 @@ var BPTreeTransaction = class _BPTreeTransaction {
2009
2003
  "primaryOr",
2010
2004
  "or"
2011
2005
  ];
2006
+ // Condition keys that accept multiple values (V[]) rather than a single value (V)
2007
+ static _multiValueKeys = [
2008
+ "or",
2009
+ "primaryOr"
2010
+ ];
2012
2011
  constructor(rootTx, mvccRoot, mvcc, strategy, comparator, option) {
2013
2012
  this.rootTx = rootTx === null ? this : rootTx;
2014
2013
  this.mvccRoot = mvccRoot;
@@ -2233,12 +2232,8 @@ var BPTreeSyncTransaction = class extends BPTreeTransaction {
2233
2232
  const midValue = parentNode.values[mid];
2234
2233
  parentNode.values = parentNode.values.slice(0, mid);
2235
2234
  parentNode.keys = parentNode.keys.slice(0, mid + 1);
2236
- for (const k of parentNode.keys) {
2237
- const n = this._cloneNode(this.getNode(k));
2238
- n.parent = parentNode.id;
2239
- this._updateNode(n);
2240
- }
2241
- for (const k of newSiblingNodeRecursive.keys) {
2235
+ for (let i = 0, len = newSiblingNodeRecursive.keys.length; i < len; i++) {
2236
+ const k = newSiblingNodeRecursive.keys[i];
2242
2237
  const n = this._cloneNode(this.getNode(k));
2243
2238
  n.parent = newSiblingNodeRecursive.id;
2244
2239
  this._updateNode(n);
@@ -2247,7 +2242,7 @@ var BPTreeSyncTransaction = class extends BPTreeTransaction {
2247
2242
  this._insertInParent(parentNode, midValue, newSiblingNodeRecursive);
2248
2243
  }
2249
2244
  }
2250
- insertableNode(value) {
2245
+ locateLeaf(value) {
2251
2246
  let node = this.getNode(this.rootId);
2252
2247
  while (!node.leaf) {
2253
2248
  const { index } = this._binarySearchValues(node.values, value, false, true);
@@ -2255,7 +2250,7 @@ var BPTreeSyncTransaction = class extends BPTreeTransaction {
2255
2250
  }
2256
2251
  return node;
2257
2252
  }
2258
- insertableNodeByPrimary(value) {
2253
+ findLowerBoundLeaf(value) {
2259
2254
  let node = this.getNode(this.rootId);
2260
2255
  while (!node.leaf) {
2261
2256
  const { index } = this._binarySearchValues(node.values, value, true, false);
@@ -2263,7 +2258,7 @@ var BPTreeSyncTransaction = class extends BPTreeTransaction {
2263
2258
  }
2264
2259
  return node;
2265
2260
  }
2266
- insertableRightestNodeByPrimary(value) {
2261
+ findUpperBoundLeaf(value) {
2267
2262
  let node = this.getNode(this.rootId);
2268
2263
  while (!node.leaf) {
2269
2264
  const { index } = this._binarySearchValues(node.values, value, true, true);
@@ -2271,15 +2266,8 @@ var BPTreeSyncTransaction = class extends BPTreeTransaction {
2271
2266
  }
2272
2267
  return node;
2273
2268
  }
2274
- insertableRightestEndNodeByPrimary(value) {
2275
- const node = this.insertableRightestNodeByPrimary(value);
2276
- if (!node.next) {
2277
- return null;
2278
- }
2279
- return this.getNode(node.next);
2280
- }
2281
- insertableEndNode(value, direction) {
2282
- const insertableNode = direction === -1 ? this.insertableNodeByPrimary(value) : this.insertableRightestNodeByPrimary(value);
2269
+ findOuterBoundaryLeaf(value, direction) {
2270
+ const insertableNode = direction === -1 ? this.findLowerBoundLeaf(value) : this.findUpperBoundLeaf(value);
2283
2271
  let key;
2284
2272
  switch (direction) {
2285
2273
  case -1:
@@ -2327,7 +2315,7 @@ var BPTreeSyncTransaction = class extends BPTreeTransaction {
2327
2315
  for (let i = 0; i < len; i++) {
2328
2316
  const nValue = node.values[i];
2329
2317
  const keys = node.keys[i];
2330
- for (let j = 0, kLen = keys.length; j < kLen; j++) {
2318
+ for (let j = 0, len2 = keys.length; j < len2; j++) {
2331
2319
  yield [keys[j], nValue];
2332
2320
  }
2333
2321
  }
@@ -2391,7 +2379,7 @@ var BPTreeSyncTransaction = class extends BPTreeTransaction {
2391
2379
  }
2392
2380
  }
2393
2381
  exists(key, value) {
2394
- const node = this.insertableNode(value);
2382
+ const node = this.locateLeaf(value);
2395
2383
  const { index, found } = this._binarySearchValues(node.values, value);
2396
2384
  if (found) {
2397
2385
  const keys = node.keys[index];
@@ -2406,7 +2394,7 @@ var BPTreeSyncTransaction = class extends BPTreeTransaction {
2406
2394
  while (true) {
2407
2395
  for (let i = 0, len = node.values.length; i < len; i++) {
2408
2396
  const keys = node.keys[i];
2409
- for (let j = 0, kLen = keys.length; j < kLen; j++) {
2397
+ for (let j = 0, len2 = keys.length; j < len2; j++) {
2410
2398
  if (keys[j] === key) {
2411
2399
  return node.values[i];
2412
2400
  }
@@ -2488,7 +2476,7 @@ var BPTreeSyncTransaction = class extends BPTreeTransaction {
2488
2476
  return map;
2489
2477
  }
2490
2478
  insert(key, value) {
2491
- let before = this.insertableNode(value);
2479
+ let before = this.locateLeaf(value);
2492
2480
  before = this._insertAtLeaf(before, key, value);
2493
2481
  if (before.values.length === this.order) {
2494
2482
  let after = this._createNode(
@@ -2515,8 +2503,16 @@ var BPTreeSyncTransaction = class extends BPTreeTransaction {
2515
2503
  const sorted = [...entries].sort((a, b) => this.comparator.asc(a[1], b[1]));
2516
2504
  let currentLeaf = null;
2517
2505
  let modified = false;
2518
- for (const [key, value] of sorted) {
2519
- const targetLeaf = this.insertableNode(value);
2506
+ let cachedLeafId = null;
2507
+ let cachedLeafMaxValue = null;
2508
+ for (let i = 0, len = sorted.length; i < len; i++) {
2509
+ const [key, value] = sorted[i];
2510
+ let targetLeaf;
2511
+ if (cachedLeafId !== null && cachedLeafMaxValue !== null && currentLeaf !== null && (this.comparator.isLower(value, cachedLeafMaxValue) || this.comparator.isSame(value, cachedLeafMaxValue))) {
2512
+ targetLeaf = currentLeaf;
2513
+ } else {
2514
+ targetLeaf = this.locateLeaf(value);
2515
+ }
2520
2516
  if (currentLeaf !== null && currentLeaf.id === targetLeaf.id) {
2521
2517
  } else {
2522
2518
  if (currentLeaf !== null && modified) {
@@ -2525,8 +2521,10 @@ var BPTreeSyncTransaction = class extends BPTreeTransaction {
2525
2521
  currentLeaf = this._cloneNode(targetLeaf);
2526
2522
  modified = false;
2527
2523
  }
2524
+ cachedLeafId = currentLeaf.id;
2528
2525
  const changed = this._insertValueIntoLeaf(currentLeaf, key, value);
2529
2526
  modified = modified || changed;
2527
+ cachedLeafMaxValue = currentLeaf.values[currentLeaf.values.length - 1];
2530
2528
  if (currentLeaf.values.length === this.order) {
2531
2529
  this._updateNode(currentLeaf);
2532
2530
  let after = this._createNode(
@@ -2547,6 +2545,8 @@ var BPTreeSyncTransaction = class extends BPTreeTransaction {
2547
2545
  this._updateNode(after);
2548
2546
  this._insertInParent(currentLeaf, after.values[0], after);
2549
2547
  currentLeaf = null;
2548
+ cachedLeafId = null;
2549
+ cachedLeafMaxValue = null;
2550
2550
  modified = false;
2551
2551
  }
2552
2552
  }
@@ -2554,6 +2554,85 @@ var BPTreeSyncTransaction = class extends BPTreeTransaction {
2554
2554
  this._updateNode(currentLeaf);
2555
2555
  }
2556
2556
  }
2557
+ bulkLoad(entries) {
2558
+ if (entries.length === 0) return;
2559
+ const root = this.getNode(this.rootId);
2560
+ if (!root.leaf || root.values.length > 0) {
2561
+ throw new Error("bulkLoad can only be called on an empty tree. Use batchInsert for non-empty trees.");
2562
+ }
2563
+ const sorted = [...entries].sort((a, b) => this.comparator.asc(a[1], b[1]));
2564
+ const grouped = [];
2565
+ for (let i = 0, len = sorted.length; i < len; i++) {
2566
+ const [key, value] = sorted[i];
2567
+ const last = grouped[grouped.length - 1];
2568
+ if (last && this.comparator.isSame(last.value, value)) {
2569
+ if (!last.keys.includes(key)) {
2570
+ last.keys.push(key);
2571
+ }
2572
+ } else {
2573
+ grouped.push({ keys: [key], value });
2574
+ }
2575
+ }
2576
+ this._deleteNode(root);
2577
+ const maxLeafSize = this.order - 1;
2578
+ const leaves = [];
2579
+ for (let i = 0, len = grouped.length; i < len; i += maxLeafSize) {
2580
+ const chunk = grouped.slice(i, i + maxLeafSize);
2581
+ const leafKeys = chunk.map((g) => g.keys);
2582
+ const leafValues = chunk.map((g) => g.value);
2583
+ const leaf = this._createNode(
2584
+ true,
2585
+ leafKeys,
2586
+ leafValues,
2587
+ null,
2588
+ null,
2589
+ null
2590
+ );
2591
+ leaves.push(leaf);
2592
+ }
2593
+ for (let i = 0, len = leaves.length; i < len; i++) {
2594
+ if (i > 0) {
2595
+ leaves[i].prev = leaves[i - 1].id;
2596
+ }
2597
+ if (i < len - 1) {
2598
+ leaves[i].next = leaves[i + 1].id;
2599
+ }
2600
+ this._updateNode(leaves[i]);
2601
+ }
2602
+ let currentLevel = leaves;
2603
+ while (currentLevel.length > 1) {
2604
+ const nextLevel = [];
2605
+ for (let i = 0, len = currentLevel.length; i < len; i += this.order) {
2606
+ const children = currentLevel.slice(i, i + this.order);
2607
+ const childIds = children.map((c) => c.id);
2608
+ const separators = [];
2609
+ for (let j = 1, len2 = children.length; j < len2; j++) {
2610
+ separators.push(children[j].values[0]);
2611
+ }
2612
+ const internalNode = this._createNode(
2613
+ false,
2614
+ childIds,
2615
+ separators,
2616
+ null,
2617
+ null,
2618
+ null
2619
+ );
2620
+ for (let j = 0, len2 = children.length; j < len2; j++) {
2621
+ const child = children[j];
2622
+ child.parent = internalNode.id;
2623
+ this._updateNode(child);
2624
+ }
2625
+ nextLevel.push(internalNode);
2626
+ }
2627
+ currentLevel = nextLevel;
2628
+ }
2629
+ const newRoot = currentLevel[0];
2630
+ this._writeHead({
2631
+ root: newRoot.id,
2632
+ order: this.order,
2633
+ data: this.strategy.head.data
2634
+ });
2635
+ }
2557
2636
  _deleteEntry(node, key) {
2558
2637
  if (!node.leaf) {
2559
2638
  let keyIndex = -1;
@@ -2657,7 +2736,8 @@ var BPTreeSyncTransaction = class extends BPTreeTransaction {
2657
2736
  siblingNode.values.push(...node.values);
2658
2737
  if (!siblingNode.leaf) {
2659
2738
  const keys = siblingNode.keys;
2660
- for (const key2 of keys) {
2739
+ for (let i = 0, len = keys.length; i < len; i++) {
2740
+ const key2 = keys[i];
2661
2741
  const node2 = this._cloneNode(this.getNode(key2));
2662
2742
  node2.parent = siblingNode.id;
2663
2743
  this._updateNode(node2);
@@ -2725,21 +2805,24 @@ var BPTreeSyncTransaction = class extends BPTreeTransaction {
2725
2805
  this._updateNode(siblingNode);
2726
2806
  }
2727
2807
  if (!siblingNode.leaf) {
2728
- for (const key2 of siblingNode.keys) {
2808
+ for (let i = 0, len = siblingNode.keys.length; i < len; i++) {
2809
+ const key2 = siblingNode.keys[i];
2729
2810
  const n = this._cloneNode(this.getNode(key2));
2730
2811
  n.parent = siblingNode.id;
2731
2812
  this._updateNode(n);
2732
2813
  }
2733
2814
  }
2734
2815
  if (!node.leaf) {
2735
- for (const key2 of node.keys) {
2816
+ for (let i = 0, len = node.keys.length; i < len; i++) {
2817
+ const key2 = node.keys[i];
2736
2818
  const n = this._cloneNode(this.getNode(key2));
2737
2819
  n.parent = node.id;
2738
2820
  this._updateNode(n);
2739
2821
  }
2740
2822
  }
2741
2823
  if (!parentNode.leaf) {
2742
- for (const key2 of parentNode.keys) {
2824
+ for (let i = 0, len = parentNode.keys.length; i < len; i++) {
2825
+ const key2 = parentNode.keys[i];
2743
2826
  const n = this._cloneNode(this.getNode(key2));
2744
2827
  n.parent = parentNode.id;
2745
2828
  this._updateNode(n);
@@ -2758,7 +2841,7 @@ var BPTreeSyncTransaction = class extends BPTreeTransaction {
2758
2841
  if (value === void 0) {
2759
2842
  return;
2760
2843
  }
2761
- let node = this.insertableNodeByPrimary(value);
2844
+ let node = this.findLowerBoundLeaf(value);
2762
2845
  let found = false;
2763
2846
  while (true) {
2764
2847
  let i = node.values.length;
@@ -2917,6 +3000,14 @@ var BPTreeSync = class extends BPTreeSyncTransaction {
2917
3000
  throw new Error(`Transaction failed: ${result.error || "Commit failed due to conflict"}`);
2918
3001
  }
2919
3002
  }
3003
+ bulkLoad(entries) {
3004
+ const tx = this.createTransaction();
3005
+ tx.bulkLoad(entries);
3006
+ const result = tx.commit();
3007
+ if (!result.success) {
3008
+ throw new Error(`Transaction failed: ${result.error || "Commit failed due to conflict"}`);
3009
+ }
3010
+ }
2920
3011
  };
2921
3012
 
2922
3013
  // node_modules/ryoiki/dist/esm/index.mjs
@@ -3334,12 +3425,8 @@ var BPTreeAsyncTransaction = class extends BPTreeTransaction {
3334
3425
  const midValue = parentNode.values[mid];
3335
3426
  parentNode.values = parentNode.values.slice(0, mid);
3336
3427
  parentNode.keys = parentNode.keys.slice(0, mid + 1);
3337
- for (const k of parentNode.keys) {
3338
- const n = this._cloneNode(await this.getNode(k));
3339
- n.parent = parentNode.id;
3340
- await this._updateNode(n);
3341
- }
3342
- for (const k of newSiblingNodeRecursive.keys) {
3428
+ for (let i = 0, len = newSiblingNodeRecursive.keys.length; i < len; i++) {
3429
+ const k = newSiblingNodeRecursive.keys[i];
3343
3430
  const n = this._cloneNode(await this.getNode(k));
3344
3431
  n.parent = newSiblingNodeRecursive.id;
3345
3432
  await this._updateNode(n);
@@ -3348,7 +3435,7 @@ var BPTreeAsyncTransaction = class extends BPTreeTransaction {
3348
3435
  await this._insertInParent(parentNode, midValue, newSiblingNodeRecursive);
3349
3436
  }
3350
3437
  }
3351
- async insertableNode(value) {
3438
+ async locateLeaf(value) {
3352
3439
  let node = await this.getNode(this.rootId);
3353
3440
  while (!node.leaf) {
3354
3441
  const { index } = this._binarySearchValues(node.values, value, false, true);
@@ -3356,7 +3443,7 @@ var BPTreeAsyncTransaction = class extends BPTreeTransaction {
3356
3443
  }
3357
3444
  return node;
3358
3445
  }
3359
- async insertableNodeByPrimary(value) {
3446
+ async findLowerBoundLeaf(value) {
3360
3447
  let node = await this.getNode(this.rootId);
3361
3448
  while (!node.leaf) {
3362
3449
  const { index } = this._binarySearchValues(node.values, value, true, false);
@@ -3364,7 +3451,7 @@ var BPTreeAsyncTransaction = class extends BPTreeTransaction {
3364
3451
  }
3365
3452
  return node;
3366
3453
  }
3367
- async insertableRightestNodeByPrimary(value) {
3454
+ async findUpperBoundLeaf(value) {
3368
3455
  let node = await this.getNode(this.rootId);
3369
3456
  while (!node.leaf) {
3370
3457
  const { index } = this._binarySearchValues(node.values, value, true, true);
@@ -3372,15 +3459,8 @@ var BPTreeAsyncTransaction = class extends BPTreeTransaction {
3372
3459
  }
3373
3460
  return node;
3374
3461
  }
3375
- async insertableRightestEndNodeByPrimary(value) {
3376
- const node = await this.insertableRightestNodeByPrimary(value);
3377
- if (!node.next) {
3378
- return null;
3379
- }
3380
- return await this.getNode(node.next);
3381
- }
3382
- async insertableEndNode(value, direction) {
3383
- const insertableNode = direction === -1 ? await this.insertableNodeByPrimary(value) : await this.insertableRightestNodeByPrimary(value);
3462
+ async findOuterBoundaryLeaf(value, direction) {
3463
+ const insertableNode = direction === -1 ? await this.findLowerBoundLeaf(value) : await this.findUpperBoundLeaf(value);
3384
3464
  let key;
3385
3465
  switch (direction) {
3386
3466
  case -1:
@@ -3438,7 +3518,7 @@ var BPTreeAsyncTransaction = class extends BPTreeTransaction {
3438
3518
  for (let i = 0; i < len; i++) {
3439
3519
  const nValue = node.values[i];
3440
3520
  const keys = node.keys[i];
3441
- for (let j = 0, kLen = keys.length; j < kLen; j++) {
3521
+ for (let j = 0, len2 = keys.length; j < len2; j++) {
3442
3522
  yield [keys[j], nValue];
3443
3523
  }
3444
3524
  }
@@ -3501,7 +3581,7 @@ var BPTreeAsyncTransaction = class extends BPTreeTransaction {
3501
3581
  }
3502
3582
  }
3503
3583
  async exists(key, value) {
3504
- const node = await this.insertableNode(value);
3584
+ const node = await this.locateLeaf(value);
3505
3585
  const { index, found } = this._binarySearchValues(node.values, value);
3506
3586
  if (found) {
3507
3587
  const keys = node.keys[index];
@@ -3516,7 +3596,7 @@ var BPTreeAsyncTransaction = class extends BPTreeTransaction {
3516
3596
  while (true) {
3517
3597
  for (let i = 0, len = node.values.length; i < len; i++) {
3518
3598
  const keys = node.keys[i];
3519
- for (let j = 0, kLen = keys.length; j < kLen; j++) {
3599
+ for (let j = 0, len2 = keys.length; j < len2; j++) {
3520
3600
  if (keys[j] === key) {
3521
3601
  return node.values[i];
3522
3602
  }
@@ -3599,7 +3679,7 @@ var BPTreeAsyncTransaction = class extends BPTreeTransaction {
3599
3679
  }
3600
3680
  async insert(key, value) {
3601
3681
  return this.writeLock(0, async () => {
3602
- let before = await this.insertableNode(value);
3682
+ let before = await this.locateLeaf(value);
3603
3683
  before = await this._insertAtLeaf(before, key, value);
3604
3684
  if (before.values.length === this.order) {
3605
3685
  let after = await this._createNode(
@@ -3628,8 +3708,16 @@ var BPTreeAsyncTransaction = class extends BPTreeTransaction {
3628
3708
  const sorted = [...entries].sort((a, b) => this.comparator.asc(a[1], b[1]));
3629
3709
  let currentLeaf = null;
3630
3710
  let modified = false;
3631
- for (const [key, value] of sorted) {
3632
- const targetLeaf = await this.insertableNode(value);
3711
+ let cachedLeafId = null;
3712
+ let cachedLeafMaxValue = null;
3713
+ for (let i = 0, len = sorted.length; i < len; i++) {
3714
+ const [key, value] = sorted[i];
3715
+ let targetLeaf;
3716
+ if (cachedLeafId !== null && cachedLeafMaxValue !== null && currentLeaf !== null && (this.comparator.isLower(value, cachedLeafMaxValue) || this.comparator.isSame(value, cachedLeafMaxValue))) {
3717
+ targetLeaf = currentLeaf;
3718
+ } else {
3719
+ targetLeaf = await this.locateLeaf(value);
3720
+ }
3633
3721
  if (currentLeaf !== null && currentLeaf.id === targetLeaf.id) {
3634
3722
  } else {
3635
3723
  if (currentLeaf !== null && modified) {
@@ -3638,8 +3726,10 @@ var BPTreeAsyncTransaction = class extends BPTreeTransaction {
3638
3726
  currentLeaf = this._cloneNode(targetLeaf);
3639
3727
  modified = false;
3640
3728
  }
3729
+ cachedLeafId = currentLeaf.id;
3641
3730
  const changed = this._insertValueIntoLeaf(currentLeaf, key, value);
3642
3731
  modified = modified || changed;
3732
+ cachedLeafMaxValue = currentLeaf.values[currentLeaf.values.length - 1];
3643
3733
  if (currentLeaf.values.length === this.order) {
3644
3734
  await this._updateNode(currentLeaf);
3645
3735
  let after = await this._createNode(
@@ -3660,6 +3750,8 @@ var BPTreeAsyncTransaction = class extends BPTreeTransaction {
3660
3750
  await this._updateNode(after);
3661
3751
  await this._insertInParent(currentLeaf, after.values[0], after);
3662
3752
  currentLeaf = null;
3753
+ cachedLeafId = null;
3754
+ cachedLeafMaxValue = null;
3663
3755
  modified = false;
3664
3756
  }
3665
3757
  }
@@ -3668,6 +3760,87 @@ var BPTreeAsyncTransaction = class extends BPTreeTransaction {
3668
3760
  }
3669
3761
  });
3670
3762
  }
3763
+ async bulkLoad(entries) {
3764
+ if (entries.length === 0) return;
3765
+ return this.writeLock(0, async () => {
3766
+ const root = await this.getNode(this.rootId);
3767
+ if (!root.leaf || root.values.length > 0) {
3768
+ throw new Error("bulkLoad can only be called on an empty tree. Use batchInsert for non-empty trees.");
3769
+ }
3770
+ const sorted = [...entries].sort((a, b) => this.comparator.asc(a[1], b[1]));
3771
+ const grouped = [];
3772
+ for (let i = 0, len = sorted.length; i < len; i++) {
3773
+ const [key, value] = sorted[i];
3774
+ const last = grouped[grouped.length - 1];
3775
+ if (last && this.comparator.isSame(last.value, value)) {
3776
+ if (!last.keys.includes(key)) {
3777
+ last.keys.push(key);
3778
+ }
3779
+ } else {
3780
+ grouped.push({ keys: [key], value });
3781
+ }
3782
+ }
3783
+ await this._deleteNode(root);
3784
+ const maxLeafSize = this.order - 1;
3785
+ const leaves = [];
3786
+ for (let i = 0, len = grouped.length; i < len; i += maxLeafSize) {
3787
+ const chunk = grouped.slice(i, i + maxLeafSize);
3788
+ const leafKeys = chunk.map((g) => g.keys);
3789
+ const leafValues = chunk.map((g) => g.value);
3790
+ const leaf = await this._createNode(
3791
+ true,
3792
+ leafKeys,
3793
+ leafValues,
3794
+ null,
3795
+ null,
3796
+ null
3797
+ );
3798
+ leaves.push(leaf);
3799
+ }
3800
+ for (let i = 0, len = leaves.length; i < len; i++) {
3801
+ if (i > 0) {
3802
+ leaves[i].prev = leaves[i - 1].id;
3803
+ }
3804
+ if (i < len - 1) {
3805
+ leaves[i].next = leaves[i + 1].id;
3806
+ }
3807
+ await this._updateNode(leaves[i]);
3808
+ }
3809
+ let currentLevel = leaves;
3810
+ while (currentLevel.length > 1) {
3811
+ const nextLevel = [];
3812
+ for (let i = 0, len = currentLevel.length; i < len; i += this.order) {
3813
+ const children = currentLevel.slice(i, i + this.order);
3814
+ const childIds = children.map((c) => c.id);
3815
+ const separators = [];
3816
+ for (let j = 1, len2 = children.length; j < len2; j++) {
3817
+ separators.push(children[j].values[0]);
3818
+ }
3819
+ const internalNode = await this._createNode(
3820
+ false,
3821
+ childIds,
3822
+ separators,
3823
+ null,
3824
+ null,
3825
+ null
3826
+ );
3827
+ for (let j = 0, len2 = children.length; j < len2; j++) {
3828
+ const child = children[j];
3829
+ child.parent = internalNode.id;
3830
+ await this._updateNode(child);
3831
+ }
3832
+ nextLevel.push(internalNode);
3833
+ }
3834
+ currentLevel = nextLevel;
3835
+ }
3836
+ const newRoot = currentLevel[0];
3837
+ await this._writeHead({
3838
+ root: newRoot.id,
3839
+ order: this.order,
3840
+ data: this.strategy.head.data
3841
+ });
3842
+ });
3843
+ }
3671
3844
  async _deleteEntry(node, key) {
3672
3845
  if (!node.leaf) {
3673
3846
  let keyIndex = -1;
@@ -3771,7 +3944,8 @@ var BPTreeAsyncTransaction = class extends BPTreeTransaction {
3771
3944
  siblingNode.values.push(...node.values);
3772
3945
  if (!siblingNode.leaf) {
3773
3946
  const keys = siblingNode.keys;
3774
- for (const key2 of keys) {
3947
+ for (let i = 0, len = keys.length; i < len; i++) {
3948
+ const key2 = keys[i];
3775
3949
  const node2 = this._cloneNode(await this.getNode(key2));
3776
3950
  node2.parent = siblingNode.id;
3777
3951
  await this._updateNode(node2);
@@ -3839,21 +4013,24 @@ var BPTreeAsyncTransaction = class extends BPTreeTransaction {
3839
4013
  await this._updateNode(siblingNode);
3840
4014
  }
3841
4015
  if (!siblingNode.leaf) {
3842
- for (const key2 of siblingNode.keys) {
4016
+ for (let i = 0, len = siblingNode.keys.length; i < len; i++) {
4017
+ const key2 = siblingNode.keys[i];
3843
4018
  const n = this._cloneNode(await this.getNode(key2));
3844
4019
  n.parent = siblingNode.id;
3845
4020
  await this._updateNode(n);
3846
4021
  }
3847
4022
  }
3848
4023
  if (!node.leaf) {
3849
- for (const key2 of node.keys) {
4024
+ for (let i = 0, len = node.keys.length; i < len; i++) {
4025
+ const key2 = node.keys[i];
3850
4026
  const n = this._cloneNode(await this.getNode(key2));
3851
4027
  n.parent = node.id;
3852
4028
  await this._updateNode(n);
3853
4029
  }
3854
4030
  }
3855
4031
  if (!parentNode.leaf) {
3856
- for (const key2 of parentNode.keys) {
4032
+ for (let i = 0, len = parentNode.keys.length; i < len; i++) {
4033
+ const key2 = parentNode.keys[i];
3857
4034
  const n = this._cloneNode(await this.getNode(key2));
3858
4035
  n.parent = parentNode.id;
3859
4036
  await this._updateNode(n);
@@ -3873,7 +4050,7 @@ var BPTreeAsyncTransaction = class extends BPTreeTransaction {
3873
4050
  if (value === void 0) {
3874
4051
  return;
3875
4052
  }
3876
- let node = await this.insertableNodeByPrimary(value);
4053
+ let node = await this.findLowerBoundLeaf(value);
3877
4054
  let found = false;
3878
4055
  while (true) {
3879
4056
  let i = node.values.length;
@@ -4039,6 +4216,16 @@ var BPTreeAsync = class extends BPTreeAsyncTransaction {
4039
4216
  }
4040
4217
  });
4041
4218
  }
4219
+ async bulkLoad(entries) {
4220
+ return this.writeLock(1, async () => {
4221
+ const tx = await this.createTransaction();
4222
+ await tx.bulkLoad(entries);
4223
+ const result = await tx.commit();
4224
+ if (!result.success) {
4225
+ throw new Error(`Transaction failed: ${result.error || "Commit failed due to conflict"}`);
4226
+ }
4227
+ });
4228
+ }
4042
4229
  };
4043
4230
 
4044
4231
  // src/base/SerializeStrategy.ts