serializable-bptree 8.3.0 → 8.3.2
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.
- package/dist/cjs/index.cjs +328 -119
- package/dist/esm/index.mjs +328 -119
- package/dist/types/base/BPTreeTransaction.d.ts +13 -9
- package/package.json +1 -1
package/dist/cjs/index.cjs
CHANGED
|
@@ -1519,83 +1519,217 @@ var BPTreeTransaction = class _BPTreeTransaction {
|
|
|
1519
1519
|
return regexp.test(nodeValue);
|
|
1520
1520
|
}
|
|
1521
1521
|
};
|
|
1522
|
-
|
|
1523
|
-
gt:
|
|
1524
|
-
|
|
1525
|
-
|
|
1526
|
-
|
|
1527
|
-
|
|
1528
|
-
|
|
1529
|
-
|
|
1530
|
-
|
|
1531
|
-
|
|
1532
|
-
|
|
1533
|
-
|
|
1534
|
-
|
|
1535
|
-
|
|
1536
|
-
|
|
1537
|
-
|
|
1538
|
-
|
|
1539
|
-
|
|
1540
|
-
|
|
1541
|
-
|
|
1542
|
-
|
|
1543
|
-
|
|
1544
|
-
|
|
1545
|
-
|
|
1546
|
-
|
|
1547
|
-
|
|
1548
|
-
|
|
1549
|
-
|
|
1550
|
-
|
|
1551
|
-
|
|
1552
|
-
|
|
1553
|
-
|
|
1554
|
-
|
|
1555
|
-
|
|
1556
|
-
|
|
1557
|
-
|
|
1558
|
-
|
|
1559
|
-
|
|
1560
|
-
|
|
1561
|
-
|
|
1562
|
-
|
|
1563
|
-
|
|
1564
|
-
|
|
1565
|
-
lte:
|
|
1566
|
-
|
|
1567
|
-
|
|
1568
|
-
|
|
1569
|
-
|
|
1570
|
-
|
|
1571
|
-
|
|
1572
|
-
|
|
1573
|
-
|
|
1574
|
-
|
|
1575
|
-
|
|
1576
|
-
|
|
1577
|
-
|
|
1578
|
-
|
|
1579
|
-
|
|
1580
|
-
|
|
1581
|
-
|
|
1582
|
-
|
|
1583
|
-
|
|
1584
|
-
|
|
1585
|
-
|
|
1586
|
-
|
|
1587
|
-
|
|
1588
|
-
|
|
1589
|
-
|
|
1590
|
-
|
|
1591
|
-
|
|
1592
|
-
|
|
1593
|
-
|
|
1594
|
-
|
|
1595
|
-
|
|
1596
|
-
|
|
1597
|
-
|
|
1598
|
-
|
|
1522
|
+
searchConfigs = {
|
|
1523
|
+
gt: {
|
|
1524
|
+
asc: {
|
|
1525
|
+
start: (tx, v) => tx.insertableNodeByPrimary(v[0]),
|
|
1526
|
+
end: () => null,
|
|
1527
|
+
direction: 1,
|
|
1528
|
+
earlyTerminate: false
|
|
1529
|
+
},
|
|
1530
|
+
desc: {
|
|
1531
|
+
start: (tx) => tx.rightestNode(),
|
|
1532
|
+
end: (tx, v) => tx.insertableEndNode(v[0], -1),
|
|
1533
|
+
direction: -1,
|
|
1534
|
+
earlyTerminate: true
|
|
1535
|
+
}
|
|
1536
|
+
},
|
|
1537
|
+
gte: {
|
|
1538
|
+
asc: {
|
|
1539
|
+
start: (tx, v) => tx.insertableNodeByPrimary(v[0]),
|
|
1540
|
+
end: () => null,
|
|
1541
|
+
direction: 1,
|
|
1542
|
+
earlyTerminate: false
|
|
1543
|
+
},
|
|
1544
|
+
desc: {
|
|
1545
|
+
start: (tx) => tx.rightestNode(),
|
|
1546
|
+
end: (tx, v) => tx.insertableEndNode(v[0], -1),
|
|
1547
|
+
direction: -1,
|
|
1548
|
+
earlyTerminate: true
|
|
1549
|
+
}
|
|
1550
|
+
},
|
|
1551
|
+
lt: {
|
|
1552
|
+
asc: {
|
|
1553
|
+
start: (tx) => tx.leftestNode(),
|
|
1554
|
+
end: (tx, v) => tx.insertableEndNode(v[0], 1),
|
|
1555
|
+
direction: 1,
|
|
1556
|
+
earlyTerminate: true
|
|
1557
|
+
},
|
|
1558
|
+
desc: {
|
|
1559
|
+
start: (tx, v) => tx.insertableNodeByPrimary(v[0]),
|
|
1560
|
+
end: () => null,
|
|
1561
|
+
direction: -1,
|
|
1562
|
+
earlyTerminate: false
|
|
1563
|
+
}
|
|
1564
|
+
},
|
|
1565
|
+
lte: {
|
|
1566
|
+
asc: {
|
|
1567
|
+
start: (tx) => tx.leftestNode(),
|
|
1568
|
+
end: (tx, v) => tx.insertableEndNode(v[0], 1),
|
|
1569
|
+
direction: 1,
|
|
1570
|
+
earlyTerminate: true
|
|
1571
|
+
},
|
|
1572
|
+
desc: {
|
|
1573
|
+
start: (tx, v) => tx.insertableRightestNodeByPrimary(v[0]),
|
|
1574
|
+
end: () => null,
|
|
1575
|
+
direction: -1,
|
|
1576
|
+
earlyTerminate: false
|
|
1577
|
+
}
|
|
1578
|
+
},
|
|
1579
|
+
equal: {
|
|
1580
|
+
asc: {
|
|
1581
|
+
start: (tx, v) => tx.insertableNodeByPrimary(v[0]),
|
|
1582
|
+
end: (tx, v) => tx.insertableEndNode(v[0], 1),
|
|
1583
|
+
direction: 1,
|
|
1584
|
+
earlyTerminate: true
|
|
1585
|
+
},
|
|
1586
|
+
desc: {
|
|
1587
|
+
start: (tx, v) => tx.insertableEndNode(v[0], 1),
|
|
1588
|
+
end: (tx, v) => tx.insertableEndNode(v[0], -1),
|
|
1589
|
+
direction: -1,
|
|
1590
|
+
earlyTerminate: true
|
|
1591
|
+
}
|
|
1592
|
+
},
|
|
1593
|
+
notEqual: {
|
|
1594
|
+
asc: {
|
|
1595
|
+
start: (tx) => tx.leftestNode(),
|
|
1596
|
+
end: () => null,
|
|
1597
|
+
direction: 1,
|
|
1598
|
+
earlyTerminate: false
|
|
1599
|
+
},
|
|
1600
|
+
desc: {
|
|
1601
|
+
start: (tx) => tx.rightestNode(),
|
|
1602
|
+
end: () => null,
|
|
1603
|
+
direction: -1,
|
|
1604
|
+
earlyTerminate: false
|
|
1605
|
+
}
|
|
1606
|
+
},
|
|
1607
|
+
or: {
|
|
1608
|
+
asc: {
|
|
1609
|
+
start: (tx, v) => tx.insertableNodeByPrimary(tx.lowestValue(v)),
|
|
1610
|
+
end: (tx, v) => tx.insertableEndNode(tx.highestValue(v), 1),
|
|
1611
|
+
direction: 1,
|
|
1612
|
+
earlyTerminate: false
|
|
1613
|
+
},
|
|
1614
|
+
desc: {
|
|
1615
|
+
start: (tx, v) => tx.insertableEndNode(tx.highestValue(v), 1),
|
|
1616
|
+
end: (tx, v) => tx.insertableEndNode(tx.lowestValue(v), -1),
|
|
1617
|
+
direction: -1,
|
|
1618
|
+
earlyTerminate: false
|
|
1619
|
+
}
|
|
1620
|
+
},
|
|
1621
|
+
primaryGt: {
|
|
1622
|
+
asc: {
|
|
1623
|
+
start: (tx, v) => tx.insertableNodeByPrimary(v[0]),
|
|
1624
|
+
end: () => null,
|
|
1625
|
+
direction: 1,
|
|
1626
|
+
earlyTerminate: false
|
|
1627
|
+
},
|
|
1628
|
+
desc: {
|
|
1629
|
+
start: (tx) => tx.rightestNode(),
|
|
1630
|
+
end: (tx, v) => tx.insertableEndNode(v[0], -1),
|
|
1631
|
+
direction: -1,
|
|
1632
|
+
earlyTerminate: true
|
|
1633
|
+
}
|
|
1634
|
+
},
|
|
1635
|
+
primaryGte: {
|
|
1636
|
+
asc: {
|
|
1637
|
+
start: (tx, v) => tx.insertableNodeByPrimary(v[0]),
|
|
1638
|
+
end: () => null,
|
|
1639
|
+
direction: 1,
|
|
1640
|
+
earlyTerminate: false
|
|
1641
|
+
},
|
|
1642
|
+
desc: {
|
|
1643
|
+
start: (tx) => tx.rightestNode(),
|
|
1644
|
+
end: (tx, v) => tx.insertableEndNode(v[0], -1),
|
|
1645
|
+
direction: -1,
|
|
1646
|
+
earlyTerminate: true
|
|
1647
|
+
}
|
|
1648
|
+
},
|
|
1649
|
+
primaryLt: {
|
|
1650
|
+
asc: {
|
|
1651
|
+
start: (tx) => tx.leftestNode(),
|
|
1652
|
+
end: (tx, v) => tx.insertableEndNode(v[0], 1),
|
|
1653
|
+
direction: 1,
|
|
1654
|
+
earlyTerminate: true
|
|
1655
|
+
},
|
|
1656
|
+
desc: {
|
|
1657
|
+
start: (tx, v) => tx.insertableNodeByPrimary(v[0]),
|
|
1658
|
+
end: () => null,
|
|
1659
|
+
direction: -1,
|
|
1660
|
+
earlyTerminate: false
|
|
1661
|
+
}
|
|
1662
|
+
},
|
|
1663
|
+
primaryLte: {
|
|
1664
|
+
asc: {
|
|
1665
|
+
start: (tx) => tx.leftestNode(),
|
|
1666
|
+
end: (tx, v) => tx.insertableEndNode(v[0], 1),
|
|
1667
|
+
direction: 1,
|
|
1668
|
+
earlyTerminate: true
|
|
1669
|
+
},
|
|
1670
|
+
desc: {
|
|
1671
|
+
start: (tx, v) => tx.insertableRightestNodeByPrimary(v[0]),
|
|
1672
|
+
end: () => null,
|
|
1673
|
+
direction: -1,
|
|
1674
|
+
earlyTerminate: false
|
|
1675
|
+
}
|
|
1676
|
+
},
|
|
1677
|
+
primaryEqual: {
|
|
1678
|
+
asc: {
|
|
1679
|
+
start: (tx, v) => tx.insertableNodeByPrimary(v[0]),
|
|
1680
|
+
end: (tx, v) => tx.insertableRightestEndNodeByPrimary(v[0]),
|
|
1681
|
+
direction: 1,
|
|
1682
|
+
earlyTerminate: true
|
|
1683
|
+
},
|
|
1684
|
+
desc: {
|
|
1685
|
+
start: (tx, v) => tx.insertableRightestEndNodeByPrimary(v[0]),
|
|
1686
|
+
end: (tx, v) => tx.insertableEndNode(v[0], -1),
|
|
1687
|
+
direction: -1,
|
|
1688
|
+
earlyTerminate: true
|
|
1689
|
+
}
|
|
1690
|
+
},
|
|
1691
|
+
primaryNotEqual: {
|
|
1692
|
+
asc: {
|
|
1693
|
+
start: (tx) => tx.leftestNode(),
|
|
1694
|
+
end: () => null,
|
|
1695
|
+
direction: 1,
|
|
1696
|
+
earlyTerminate: false
|
|
1697
|
+
},
|
|
1698
|
+
desc: {
|
|
1699
|
+
start: (tx) => tx.rightestNode(),
|
|
1700
|
+
end: () => null,
|
|
1701
|
+
direction: -1,
|
|
1702
|
+
earlyTerminate: false
|
|
1703
|
+
}
|
|
1704
|
+
},
|
|
1705
|
+
primaryOr: {
|
|
1706
|
+
asc: {
|
|
1707
|
+
start: (tx, v) => tx.insertableNodeByPrimary(tx.lowestPrimaryValue(v)),
|
|
1708
|
+
end: (tx, v) => tx.insertableRightestEndNodeByPrimary(tx.highestPrimaryValue(v)),
|
|
1709
|
+
direction: 1,
|
|
1710
|
+
earlyTerminate: false
|
|
1711
|
+
},
|
|
1712
|
+
desc: {
|
|
1713
|
+
start: (tx, v) => tx.insertableRightestEndNodeByPrimary(tx.highestPrimaryValue(v)),
|
|
1714
|
+
end: (tx, v) => tx.insertableEndNode(tx.lowestPrimaryValue(v), -1),
|
|
1715
|
+
direction: -1,
|
|
1716
|
+
earlyTerminate: false
|
|
1717
|
+
}
|
|
1718
|
+
},
|
|
1719
|
+
like: {
|
|
1720
|
+
asc: {
|
|
1721
|
+
start: (tx) => tx.leftestNode(),
|
|
1722
|
+
end: () => null,
|
|
1723
|
+
direction: 1,
|
|
1724
|
+
earlyTerminate: false
|
|
1725
|
+
},
|
|
1726
|
+
desc: {
|
|
1727
|
+
start: (tx) => tx.rightestNode(),
|
|
1728
|
+
end: () => null,
|
|
1729
|
+
direction: -1,
|
|
1730
|
+
earlyTerminate: false
|
|
1731
|
+
}
|
|
1732
|
+
}
|
|
1599
1733
|
};
|
|
1600
1734
|
/**
|
|
1601
1735
|
* Priority map for condition types.
|
|
@@ -1696,6 +1830,39 @@ var BPTreeTransaction = class _BPTreeTransaction {
|
|
|
1696
1830
|
}
|
|
1697
1831
|
return true;
|
|
1698
1832
|
}
|
|
1833
|
+
/**
|
|
1834
|
+
* Inserts a key-value pair into an already-cloned leaf node in-place.
|
|
1835
|
+
* Unlike _insertAtLeaf, this does NOT clone or update the node via MVCC.
|
|
1836
|
+
* Used by batchInsert to batch multiple insertions with a single clone/update.
|
|
1837
|
+
* @returns true if the leaf was modified, false if the key already exists.
|
|
1838
|
+
*/
|
|
1839
|
+
_insertValueIntoLeaf(leaf, key, value) {
|
|
1840
|
+
if (leaf.values.length) {
|
|
1841
|
+
for (let i = 0, len = leaf.values.length; i < len; i++) {
|
|
1842
|
+
const nValue = leaf.values[i];
|
|
1843
|
+
if (this.comparator.isSame(value, nValue)) {
|
|
1844
|
+
if (leaf.keys[i].includes(key)) {
|
|
1845
|
+
return false;
|
|
1846
|
+
}
|
|
1847
|
+
leaf.keys[i].push(key);
|
|
1848
|
+
return true;
|
|
1849
|
+
} else if (this.comparator.isLower(value, nValue)) {
|
|
1850
|
+
leaf.values.splice(i, 0, value);
|
|
1851
|
+
leaf.keys.splice(i, 0, [key]);
|
|
1852
|
+
return true;
|
|
1853
|
+
} else if (i + 1 === leaf.values.length) {
|
|
1854
|
+
leaf.values.push(value);
|
|
1855
|
+
leaf.keys.push([key]);
|
|
1856
|
+
return true;
|
|
1857
|
+
}
|
|
1858
|
+
}
|
|
1859
|
+
} else {
|
|
1860
|
+
leaf.values = [value];
|
|
1861
|
+
leaf.keys = [[key]];
|
|
1862
|
+
return true;
|
|
1863
|
+
}
|
|
1864
|
+
return false;
|
|
1865
|
+
}
|
|
1699
1866
|
_cloneNode(node) {
|
|
1700
1867
|
return JSON.parse(JSON.stringify(node));
|
|
1701
1868
|
}
|
|
@@ -2175,16 +2342,20 @@ var BPTreeSyncTransaction = class extends BPTreeTransaction {
|
|
|
2175
2342
|
const driverKey = this.getDriverKey(condition);
|
|
2176
2343
|
if (!driverKey) return;
|
|
2177
2344
|
const value = condition[driverKey];
|
|
2178
|
-
|
|
2179
|
-
|
|
2180
|
-
let
|
|
2345
|
+
const v = this.ensureValues(value);
|
|
2346
|
+
const config = this.searchConfigs[driverKey][order];
|
|
2347
|
+
let startNode = config.start(this, v);
|
|
2348
|
+
let endNode = config.end(this, v);
|
|
2349
|
+
const direction = config.direction;
|
|
2350
|
+
const earlyTerminate = config.earlyTerminate;
|
|
2351
|
+
if (order === "desc" && !startNode) {
|
|
2352
|
+
startNode = this.rightestNode();
|
|
2353
|
+
}
|
|
2354
|
+
if (order === "asc" && !startNode) {
|
|
2355
|
+
startNode = this.leftestNode();
|
|
2356
|
+
}
|
|
2357
|
+
if (!startNode) return;
|
|
2181
2358
|
const comparator = this.verifierMap[driverKey];
|
|
2182
|
-
const earlyTerminate = this.verifierEarlyTerminate[driverKey];
|
|
2183
|
-
if (order === "desc") {
|
|
2184
|
-
startNode = endNode ?? this.rightestNode();
|
|
2185
|
-
endNode = null;
|
|
2186
|
-
direction *= -1;
|
|
2187
|
-
}
|
|
2188
2359
|
const generator = this.getPairsGenerator(
|
|
2189
2360
|
value,
|
|
2190
2361
|
startNode,
|
|
@@ -2196,7 +2367,7 @@ var BPTreeSyncTransaction = class extends BPTreeTransaction {
|
|
|
2196
2367
|
let count = 0;
|
|
2197
2368
|
const intersection = filterValues && filterValues.size > 0 ? filterValues : null;
|
|
2198
2369
|
for (const pair of generator) {
|
|
2199
|
-
const [k,
|
|
2370
|
+
const [k, v2] = pair;
|
|
2200
2371
|
if (intersection && !intersection.has(k)) {
|
|
2201
2372
|
continue;
|
|
2202
2373
|
}
|
|
@@ -2205,7 +2376,7 @@ var BPTreeSyncTransaction = class extends BPTreeTransaction {
|
|
|
2205
2376
|
if (key === driverKey) continue;
|
|
2206
2377
|
const verify = this.verifierMap[key];
|
|
2207
2378
|
const condValue = condition[key];
|
|
2208
|
-
if (!verify(
|
|
2379
|
+
if (!verify(v2, condValue)) {
|
|
2209
2380
|
isMatch = false;
|
|
2210
2381
|
break;
|
|
2211
2382
|
}
|
|
@@ -2259,29 +2430,46 @@ var BPTreeSyncTransaction = class extends BPTreeTransaction {
|
|
|
2259
2430
|
batchInsert(entries) {
|
|
2260
2431
|
if (entries.length === 0) return;
|
|
2261
2432
|
const sorted = [...entries].sort((a, b) => this.comparator.asc(a[1], b[1]));
|
|
2433
|
+
let currentLeaf = null;
|
|
2434
|
+
let modified = false;
|
|
2262
2435
|
for (const [key, value] of sorted) {
|
|
2263
|
-
|
|
2264
|
-
|
|
2265
|
-
|
|
2436
|
+
const targetLeaf = this.insertableNode(value);
|
|
2437
|
+
if (currentLeaf !== null && currentLeaf.id === targetLeaf.id) {
|
|
2438
|
+
} else {
|
|
2439
|
+
if (currentLeaf !== null && modified) {
|
|
2440
|
+
this._updateNode(currentLeaf);
|
|
2441
|
+
}
|
|
2442
|
+
currentLeaf = this._cloneNode(targetLeaf);
|
|
2443
|
+
modified = false;
|
|
2444
|
+
}
|
|
2445
|
+
const changed = this._insertValueIntoLeaf(currentLeaf, key, value);
|
|
2446
|
+
modified = modified || changed;
|
|
2447
|
+
if (currentLeaf.values.length === this.order) {
|
|
2448
|
+
this._updateNode(currentLeaf);
|
|
2266
2449
|
let after = this._createNode(
|
|
2267
2450
|
true,
|
|
2268
2451
|
[],
|
|
2269
2452
|
[],
|
|
2270
|
-
|
|
2453
|
+
currentLeaf.parent,
|
|
2271
2454
|
null,
|
|
2272
2455
|
null
|
|
2273
2456
|
);
|
|
2274
2457
|
const mid = Math.ceil(this.order / 2) - 1;
|
|
2275
2458
|
after = this._cloneNode(after);
|
|
2276
|
-
after.values =
|
|
2277
|
-
after.keys =
|
|
2278
|
-
|
|
2279
|
-
|
|
2280
|
-
this._updateNode(
|
|
2459
|
+
after.values = currentLeaf.values.slice(mid + 1);
|
|
2460
|
+
after.keys = currentLeaf.keys.slice(mid + 1);
|
|
2461
|
+
currentLeaf.values = currentLeaf.values.slice(0, mid + 1);
|
|
2462
|
+
currentLeaf.keys = currentLeaf.keys.slice(0, mid + 1);
|
|
2463
|
+
this._updateNode(currentLeaf);
|
|
2281
2464
|
this._updateNode(after);
|
|
2282
|
-
this._insertInParent(
|
|
2465
|
+
this._insertInParent(currentLeaf, after.values[0], after);
|
|
2466
|
+
currentLeaf = null;
|
|
2467
|
+
modified = false;
|
|
2283
2468
|
}
|
|
2284
2469
|
}
|
|
2470
|
+
if (currentLeaf !== null && modified) {
|
|
2471
|
+
this._updateNode(currentLeaf);
|
|
2472
|
+
}
|
|
2285
2473
|
}
|
|
2286
2474
|
_deleteEntry(node, key) {
|
|
2287
2475
|
if (!node.leaf) {
|
|
@@ -3296,16 +3484,20 @@ var BPTreeAsyncTransaction = class extends BPTreeTransaction {
|
|
|
3296
3484
|
const driverKey = this.getDriverKey(condition);
|
|
3297
3485
|
if (!driverKey) return;
|
|
3298
3486
|
const value = condition[driverKey];
|
|
3299
|
-
|
|
3300
|
-
|
|
3301
|
-
let
|
|
3487
|
+
const v = this.ensureValues(value);
|
|
3488
|
+
const config = this.searchConfigs[driverKey][order];
|
|
3489
|
+
let startNode = await config.start(this, v);
|
|
3490
|
+
let endNode = await config.end(this, v);
|
|
3491
|
+
const direction = config.direction;
|
|
3492
|
+
const earlyTerminate = config.earlyTerminate;
|
|
3493
|
+
if (order === "desc" && !startNode) {
|
|
3494
|
+
startNode = await this.rightestNode();
|
|
3495
|
+
}
|
|
3496
|
+
if (order === "asc" && !startNode) {
|
|
3497
|
+
startNode = await this.leftestNode();
|
|
3498
|
+
}
|
|
3499
|
+
if (!startNode) return;
|
|
3302
3500
|
const comparator = this.verifierMap[driverKey];
|
|
3303
|
-
const earlyTerminate = this.verifierEarlyTerminate[driverKey];
|
|
3304
|
-
if (order === "desc") {
|
|
3305
|
-
startNode = endNode ?? await this.rightestNode();
|
|
3306
|
-
endNode = null;
|
|
3307
|
-
direction *= -1;
|
|
3308
|
-
}
|
|
3309
3501
|
const generator = this.getPairsGenerator(
|
|
3310
3502
|
value,
|
|
3311
3503
|
startNode,
|
|
@@ -3317,7 +3509,7 @@ var BPTreeAsyncTransaction = class extends BPTreeTransaction {
|
|
|
3317
3509
|
let count = 0;
|
|
3318
3510
|
const intersection = filterValues && filterValues.size > 0 ? filterValues : null;
|
|
3319
3511
|
for await (const pair of generator) {
|
|
3320
|
-
const [k,
|
|
3512
|
+
const [k, v2] = pair;
|
|
3321
3513
|
if (intersection && !intersection.has(k)) {
|
|
3322
3514
|
continue;
|
|
3323
3515
|
}
|
|
@@ -3326,7 +3518,7 @@ var BPTreeAsyncTransaction = class extends BPTreeTransaction {
|
|
|
3326
3518
|
if (key === driverKey) continue;
|
|
3327
3519
|
const verify = this.verifierMap[key];
|
|
3328
3520
|
const condValue = condition[key];
|
|
3329
|
-
if (!verify(
|
|
3521
|
+
if (!verify(v2, condValue)) {
|
|
3330
3522
|
isMatch = false;
|
|
3331
3523
|
break;
|
|
3332
3524
|
}
|
|
@@ -3383,29 +3575,46 @@ var BPTreeAsyncTransaction = class extends BPTreeTransaction {
|
|
|
3383
3575
|
if (entries.length === 0) return;
|
|
3384
3576
|
return this.writeLock(0, async () => {
|
|
3385
3577
|
const sorted = [...entries].sort((a, b) => this.comparator.asc(a[1], b[1]));
|
|
3578
|
+
let currentLeaf = null;
|
|
3579
|
+
let modified = false;
|
|
3386
3580
|
for (const [key, value] of sorted) {
|
|
3387
|
-
|
|
3388
|
-
|
|
3389
|
-
|
|
3581
|
+
const targetLeaf = await this.insertableNode(value);
|
|
3582
|
+
if (currentLeaf !== null && currentLeaf.id === targetLeaf.id) {
|
|
3583
|
+
} else {
|
|
3584
|
+
if (currentLeaf !== null && modified) {
|
|
3585
|
+
await this._updateNode(currentLeaf);
|
|
3586
|
+
}
|
|
3587
|
+
currentLeaf = this._cloneNode(targetLeaf);
|
|
3588
|
+
modified = false;
|
|
3589
|
+
}
|
|
3590
|
+
const changed = this._insertValueIntoLeaf(currentLeaf, key, value);
|
|
3591
|
+
modified = modified || changed;
|
|
3592
|
+
if (currentLeaf.values.length === this.order) {
|
|
3593
|
+
await this._updateNode(currentLeaf);
|
|
3390
3594
|
let after = await this._createNode(
|
|
3391
3595
|
true,
|
|
3392
3596
|
[],
|
|
3393
3597
|
[],
|
|
3394
|
-
|
|
3598
|
+
currentLeaf.parent,
|
|
3395
3599
|
null,
|
|
3396
3600
|
null
|
|
3397
3601
|
);
|
|
3398
3602
|
const mid = Math.ceil(this.order / 2) - 1;
|
|
3399
3603
|
after = this._cloneNode(after);
|
|
3400
|
-
after.values =
|
|
3401
|
-
after.keys =
|
|
3402
|
-
|
|
3403
|
-
|
|
3404
|
-
await this._updateNode(
|
|
3604
|
+
after.values = currentLeaf.values.slice(mid + 1);
|
|
3605
|
+
after.keys = currentLeaf.keys.slice(mid + 1);
|
|
3606
|
+
currentLeaf.values = currentLeaf.values.slice(0, mid + 1);
|
|
3607
|
+
currentLeaf.keys = currentLeaf.keys.slice(0, mid + 1);
|
|
3608
|
+
await this._updateNode(currentLeaf);
|
|
3405
3609
|
await this._updateNode(after);
|
|
3406
|
-
await this._insertInParent(
|
|
3610
|
+
await this._insertInParent(currentLeaf, after.values[0], after);
|
|
3611
|
+
currentLeaf = null;
|
|
3612
|
+
modified = false;
|
|
3407
3613
|
}
|
|
3408
3614
|
}
|
|
3615
|
+
if (currentLeaf !== null && modified) {
|
|
3616
|
+
await this._updateNode(currentLeaf);
|
|
3617
|
+
}
|
|
3409
3618
|
});
|
|
3410
3619
|
}
|
|
3411
3620
|
async _deleteEntry(node, key) {
|
package/dist/esm/index.mjs
CHANGED
|
@@ -1483,83 +1483,217 @@ var BPTreeTransaction = class _BPTreeTransaction {
|
|
|
1483
1483
|
return regexp.test(nodeValue);
|
|
1484
1484
|
}
|
|
1485
1485
|
};
|
|
1486
|
-
|
|
1487
|
-
gt:
|
|
1488
|
-
|
|
1489
|
-
|
|
1490
|
-
|
|
1491
|
-
|
|
1492
|
-
|
|
1493
|
-
|
|
1494
|
-
|
|
1495
|
-
|
|
1496
|
-
|
|
1497
|
-
|
|
1498
|
-
|
|
1499
|
-
|
|
1500
|
-
|
|
1501
|
-
|
|
1502
|
-
|
|
1503
|
-
|
|
1504
|
-
|
|
1505
|
-
|
|
1506
|
-
|
|
1507
|
-
|
|
1508
|
-
|
|
1509
|
-
|
|
1510
|
-
|
|
1511
|
-
|
|
1512
|
-
|
|
1513
|
-
|
|
1514
|
-
|
|
1515
|
-
|
|
1516
|
-
|
|
1517
|
-
|
|
1518
|
-
|
|
1519
|
-
|
|
1520
|
-
|
|
1521
|
-
|
|
1522
|
-
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
|
|
1526
|
-
|
|
1527
|
-
|
|
1528
|
-
|
|
1529
|
-
lte:
|
|
1530
|
-
|
|
1531
|
-
|
|
1532
|
-
|
|
1533
|
-
|
|
1534
|
-
|
|
1535
|
-
|
|
1536
|
-
|
|
1537
|
-
|
|
1538
|
-
|
|
1539
|
-
|
|
1540
|
-
|
|
1541
|
-
|
|
1542
|
-
|
|
1543
|
-
|
|
1544
|
-
|
|
1545
|
-
|
|
1546
|
-
|
|
1547
|
-
|
|
1548
|
-
|
|
1549
|
-
|
|
1550
|
-
|
|
1551
|
-
|
|
1552
|
-
|
|
1553
|
-
|
|
1554
|
-
|
|
1555
|
-
|
|
1556
|
-
|
|
1557
|
-
|
|
1558
|
-
|
|
1559
|
-
|
|
1560
|
-
|
|
1561
|
-
|
|
1562
|
-
|
|
1486
|
+
searchConfigs = {
|
|
1487
|
+
gt: {
|
|
1488
|
+
asc: {
|
|
1489
|
+
start: (tx, v) => tx.insertableNodeByPrimary(v[0]),
|
|
1490
|
+
end: () => null,
|
|
1491
|
+
direction: 1,
|
|
1492
|
+
earlyTerminate: false
|
|
1493
|
+
},
|
|
1494
|
+
desc: {
|
|
1495
|
+
start: (tx) => tx.rightestNode(),
|
|
1496
|
+
end: (tx, v) => tx.insertableEndNode(v[0], -1),
|
|
1497
|
+
direction: -1,
|
|
1498
|
+
earlyTerminate: true
|
|
1499
|
+
}
|
|
1500
|
+
},
|
|
1501
|
+
gte: {
|
|
1502
|
+
asc: {
|
|
1503
|
+
start: (tx, v) => tx.insertableNodeByPrimary(v[0]),
|
|
1504
|
+
end: () => null,
|
|
1505
|
+
direction: 1,
|
|
1506
|
+
earlyTerminate: false
|
|
1507
|
+
},
|
|
1508
|
+
desc: {
|
|
1509
|
+
start: (tx) => tx.rightestNode(),
|
|
1510
|
+
end: (tx, v) => tx.insertableEndNode(v[0], -1),
|
|
1511
|
+
direction: -1,
|
|
1512
|
+
earlyTerminate: true
|
|
1513
|
+
}
|
|
1514
|
+
},
|
|
1515
|
+
lt: {
|
|
1516
|
+
asc: {
|
|
1517
|
+
start: (tx) => tx.leftestNode(),
|
|
1518
|
+
end: (tx, v) => tx.insertableEndNode(v[0], 1),
|
|
1519
|
+
direction: 1,
|
|
1520
|
+
earlyTerminate: true
|
|
1521
|
+
},
|
|
1522
|
+
desc: {
|
|
1523
|
+
start: (tx, v) => tx.insertableNodeByPrimary(v[0]),
|
|
1524
|
+
end: () => null,
|
|
1525
|
+
direction: -1,
|
|
1526
|
+
earlyTerminate: false
|
|
1527
|
+
}
|
|
1528
|
+
},
|
|
1529
|
+
lte: {
|
|
1530
|
+
asc: {
|
|
1531
|
+
start: (tx) => tx.leftestNode(),
|
|
1532
|
+
end: (tx, v) => tx.insertableEndNode(v[0], 1),
|
|
1533
|
+
direction: 1,
|
|
1534
|
+
earlyTerminate: true
|
|
1535
|
+
},
|
|
1536
|
+
desc: {
|
|
1537
|
+
start: (tx, v) => tx.insertableRightestNodeByPrimary(v[0]),
|
|
1538
|
+
end: () => null,
|
|
1539
|
+
direction: -1,
|
|
1540
|
+
earlyTerminate: false
|
|
1541
|
+
}
|
|
1542
|
+
},
|
|
1543
|
+
equal: {
|
|
1544
|
+
asc: {
|
|
1545
|
+
start: (tx, v) => tx.insertableNodeByPrimary(v[0]),
|
|
1546
|
+
end: (tx, v) => tx.insertableEndNode(v[0], 1),
|
|
1547
|
+
direction: 1,
|
|
1548
|
+
earlyTerminate: true
|
|
1549
|
+
},
|
|
1550
|
+
desc: {
|
|
1551
|
+
start: (tx, v) => tx.insertableEndNode(v[0], 1),
|
|
1552
|
+
end: (tx, v) => tx.insertableEndNode(v[0], -1),
|
|
1553
|
+
direction: -1,
|
|
1554
|
+
earlyTerminate: true
|
|
1555
|
+
}
|
|
1556
|
+
},
|
|
1557
|
+
notEqual: {
|
|
1558
|
+
asc: {
|
|
1559
|
+
start: (tx) => tx.leftestNode(),
|
|
1560
|
+
end: () => null,
|
|
1561
|
+
direction: 1,
|
|
1562
|
+
earlyTerminate: false
|
|
1563
|
+
},
|
|
1564
|
+
desc: {
|
|
1565
|
+
start: (tx) => tx.rightestNode(),
|
|
1566
|
+
end: () => null,
|
|
1567
|
+
direction: -1,
|
|
1568
|
+
earlyTerminate: false
|
|
1569
|
+
}
|
|
1570
|
+
},
|
|
1571
|
+
or: {
|
|
1572
|
+
asc: {
|
|
1573
|
+
start: (tx, v) => tx.insertableNodeByPrimary(tx.lowestValue(v)),
|
|
1574
|
+
end: (tx, v) => tx.insertableEndNode(tx.highestValue(v), 1),
|
|
1575
|
+
direction: 1,
|
|
1576
|
+
earlyTerminate: false
|
|
1577
|
+
},
|
|
1578
|
+
desc: {
|
|
1579
|
+
start: (tx, v) => tx.insertableEndNode(tx.highestValue(v), 1),
|
|
1580
|
+
end: (tx, v) => tx.insertableEndNode(tx.lowestValue(v), -1),
|
|
1581
|
+
direction: -1,
|
|
1582
|
+
earlyTerminate: false
|
|
1583
|
+
}
|
|
1584
|
+
},
|
|
1585
|
+
primaryGt: {
|
|
1586
|
+
asc: {
|
|
1587
|
+
start: (tx, v) => tx.insertableNodeByPrimary(v[0]),
|
|
1588
|
+
end: () => null,
|
|
1589
|
+
direction: 1,
|
|
1590
|
+
earlyTerminate: false
|
|
1591
|
+
},
|
|
1592
|
+
desc: {
|
|
1593
|
+
start: (tx) => tx.rightestNode(),
|
|
1594
|
+
end: (tx, v) => tx.insertableEndNode(v[0], -1),
|
|
1595
|
+
direction: -1,
|
|
1596
|
+
earlyTerminate: true
|
|
1597
|
+
}
|
|
1598
|
+
},
|
|
1599
|
+
primaryGte: {
|
|
1600
|
+
asc: {
|
|
1601
|
+
start: (tx, v) => tx.insertableNodeByPrimary(v[0]),
|
|
1602
|
+
end: () => null,
|
|
1603
|
+
direction: 1,
|
|
1604
|
+
earlyTerminate: false
|
|
1605
|
+
},
|
|
1606
|
+
desc: {
|
|
1607
|
+
start: (tx) => tx.rightestNode(),
|
|
1608
|
+
end: (tx, v) => tx.insertableEndNode(v[0], -1),
|
|
1609
|
+
direction: -1,
|
|
1610
|
+
earlyTerminate: true
|
|
1611
|
+
}
|
|
1612
|
+
},
|
|
1613
|
+
primaryLt: {
|
|
1614
|
+
asc: {
|
|
1615
|
+
start: (tx) => tx.leftestNode(),
|
|
1616
|
+
end: (tx, v) => tx.insertableEndNode(v[0], 1),
|
|
1617
|
+
direction: 1,
|
|
1618
|
+
earlyTerminate: true
|
|
1619
|
+
},
|
|
1620
|
+
desc: {
|
|
1621
|
+
start: (tx, v) => tx.insertableNodeByPrimary(v[0]),
|
|
1622
|
+
end: () => null,
|
|
1623
|
+
direction: -1,
|
|
1624
|
+
earlyTerminate: false
|
|
1625
|
+
}
|
|
1626
|
+
},
|
|
1627
|
+
primaryLte: {
|
|
1628
|
+
asc: {
|
|
1629
|
+
start: (tx) => tx.leftestNode(),
|
|
1630
|
+
end: (tx, v) => tx.insertableEndNode(v[0], 1),
|
|
1631
|
+
direction: 1,
|
|
1632
|
+
earlyTerminate: true
|
|
1633
|
+
},
|
|
1634
|
+
desc: {
|
|
1635
|
+
start: (tx, v) => tx.insertableRightestNodeByPrimary(v[0]),
|
|
1636
|
+
end: () => null,
|
|
1637
|
+
direction: -1,
|
|
1638
|
+
earlyTerminate: false
|
|
1639
|
+
}
|
|
1640
|
+
},
|
|
1641
|
+
primaryEqual: {
|
|
1642
|
+
asc: {
|
|
1643
|
+
start: (tx, v) => tx.insertableNodeByPrimary(v[0]),
|
|
1644
|
+
end: (tx, v) => tx.insertableRightestEndNodeByPrimary(v[0]),
|
|
1645
|
+
direction: 1,
|
|
1646
|
+
earlyTerminate: true
|
|
1647
|
+
},
|
|
1648
|
+
desc: {
|
|
1649
|
+
start: (tx, v) => tx.insertableRightestEndNodeByPrimary(v[0]),
|
|
1650
|
+
end: (tx, v) => tx.insertableEndNode(v[0], -1),
|
|
1651
|
+
direction: -1,
|
|
1652
|
+
earlyTerminate: true
|
|
1653
|
+
}
|
|
1654
|
+
},
|
|
1655
|
+
primaryNotEqual: {
|
|
1656
|
+
asc: {
|
|
1657
|
+
start: (tx) => tx.leftestNode(),
|
|
1658
|
+
end: () => null,
|
|
1659
|
+
direction: 1,
|
|
1660
|
+
earlyTerminate: false
|
|
1661
|
+
},
|
|
1662
|
+
desc: {
|
|
1663
|
+
start: (tx) => tx.rightestNode(),
|
|
1664
|
+
end: () => null,
|
|
1665
|
+
direction: -1,
|
|
1666
|
+
earlyTerminate: false
|
|
1667
|
+
}
|
|
1668
|
+
},
|
|
1669
|
+
primaryOr: {
|
|
1670
|
+
asc: {
|
|
1671
|
+
start: (tx, v) => tx.insertableNodeByPrimary(tx.lowestPrimaryValue(v)),
|
|
1672
|
+
end: (tx, v) => tx.insertableRightestEndNodeByPrimary(tx.highestPrimaryValue(v)),
|
|
1673
|
+
direction: 1,
|
|
1674
|
+
earlyTerminate: false
|
|
1675
|
+
},
|
|
1676
|
+
desc: {
|
|
1677
|
+
start: (tx, v) => tx.insertableRightestEndNodeByPrimary(tx.highestPrimaryValue(v)),
|
|
1678
|
+
end: (tx, v) => tx.insertableEndNode(tx.lowestPrimaryValue(v), -1),
|
|
1679
|
+
direction: -1,
|
|
1680
|
+
earlyTerminate: false
|
|
1681
|
+
}
|
|
1682
|
+
},
|
|
1683
|
+
like: {
|
|
1684
|
+
asc: {
|
|
1685
|
+
start: (tx) => tx.leftestNode(),
|
|
1686
|
+
end: () => null,
|
|
1687
|
+
direction: 1,
|
|
1688
|
+
earlyTerminate: false
|
|
1689
|
+
},
|
|
1690
|
+
desc: {
|
|
1691
|
+
start: (tx) => tx.rightestNode(),
|
|
1692
|
+
end: () => null,
|
|
1693
|
+
direction: -1,
|
|
1694
|
+
earlyTerminate: false
|
|
1695
|
+
}
|
|
1696
|
+
}
|
|
1563
1697
|
};
|
|
1564
1698
|
/**
|
|
1565
1699
|
* Priority map for condition types.
|
|
@@ -1660,6 +1794,39 @@ var BPTreeTransaction = class _BPTreeTransaction {
|
|
|
1660
1794
|
}
|
|
1661
1795
|
return true;
|
|
1662
1796
|
}
|
|
1797
|
+
/**
|
|
1798
|
+
* Inserts a key-value pair into an already-cloned leaf node in-place.
|
|
1799
|
+
* Unlike _insertAtLeaf, this does NOT clone or update the node via MVCC.
|
|
1800
|
+
* Used by batchInsert to batch multiple insertions with a single clone/update.
|
|
1801
|
+
* @returns true if the leaf was modified, false if the key already exists.
|
|
1802
|
+
*/
|
|
1803
|
+
_insertValueIntoLeaf(leaf, key, value) {
|
|
1804
|
+
if (leaf.values.length) {
|
|
1805
|
+
for (let i = 0, len = leaf.values.length; i < len; i++) {
|
|
1806
|
+
const nValue = leaf.values[i];
|
|
1807
|
+
if (this.comparator.isSame(value, nValue)) {
|
|
1808
|
+
if (leaf.keys[i].includes(key)) {
|
|
1809
|
+
return false;
|
|
1810
|
+
}
|
|
1811
|
+
leaf.keys[i].push(key);
|
|
1812
|
+
return true;
|
|
1813
|
+
} else if (this.comparator.isLower(value, nValue)) {
|
|
1814
|
+
leaf.values.splice(i, 0, value);
|
|
1815
|
+
leaf.keys.splice(i, 0, [key]);
|
|
1816
|
+
return true;
|
|
1817
|
+
} else if (i + 1 === leaf.values.length) {
|
|
1818
|
+
leaf.values.push(value);
|
|
1819
|
+
leaf.keys.push([key]);
|
|
1820
|
+
return true;
|
|
1821
|
+
}
|
|
1822
|
+
}
|
|
1823
|
+
} else {
|
|
1824
|
+
leaf.values = [value];
|
|
1825
|
+
leaf.keys = [[key]];
|
|
1826
|
+
return true;
|
|
1827
|
+
}
|
|
1828
|
+
return false;
|
|
1829
|
+
}
|
|
1663
1830
|
_cloneNode(node) {
|
|
1664
1831
|
return JSON.parse(JSON.stringify(node));
|
|
1665
1832
|
}
|
|
@@ -2139,16 +2306,20 @@ var BPTreeSyncTransaction = class extends BPTreeTransaction {
|
|
|
2139
2306
|
const driverKey = this.getDriverKey(condition);
|
|
2140
2307
|
if (!driverKey) return;
|
|
2141
2308
|
const value = condition[driverKey];
|
|
2142
|
-
|
|
2143
|
-
|
|
2144
|
-
let
|
|
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();
|
|
2320
|
+
}
|
|
2321
|
+
if (!startNode) return;
|
|
2145
2322
|
const comparator = this.verifierMap[driverKey];
|
|
2146
|
-
const earlyTerminate = this.verifierEarlyTerminate[driverKey];
|
|
2147
|
-
if (order === "desc") {
|
|
2148
|
-
startNode = endNode ?? this.rightestNode();
|
|
2149
|
-
endNode = null;
|
|
2150
|
-
direction *= -1;
|
|
2151
|
-
}
|
|
2152
2323
|
const generator = this.getPairsGenerator(
|
|
2153
2324
|
value,
|
|
2154
2325
|
startNode,
|
|
@@ -2160,7 +2331,7 @@ var BPTreeSyncTransaction = class extends BPTreeTransaction {
|
|
|
2160
2331
|
let count = 0;
|
|
2161
2332
|
const intersection = filterValues && filterValues.size > 0 ? filterValues : null;
|
|
2162
2333
|
for (const pair of generator) {
|
|
2163
|
-
const [k,
|
|
2334
|
+
const [k, v2] = pair;
|
|
2164
2335
|
if (intersection && !intersection.has(k)) {
|
|
2165
2336
|
continue;
|
|
2166
2337
|
}
|
|
@@ -2169,7 +2340,7 @@ var BPTreeSyncTransaction = class extends BPTreeTransaction {
|
|
|
2169
2340
|
if (key === driverKey) continue;
|
|
2170
2341
|
const verify = this.verifierMap[key];
|
|
2171
2342
|
const condValue = condition[key];
|
|
2172
|
-
if (!verify(
|
|
2343
|
+
if (!verify(v2, condValue)) {
|
|
2173
2344
|
isMatch = false;
|
|
2174
2345
|
break;
|
|
2175
2346
|
}
|
|
@@ -2223,29 +2394,46 @@ var BPTreeSyncTransaction = class extends BPTreeTransaction {
|
|
|
2223
2394
|
batchInsert(entries) {
|
|
2224
2395
|
if (entries.length === 0) return;
|
|
2225
2396
|
const sorted = [...entries].sort((a, b) => this.comparator.asc(a[1], b[1]));
|
|
2397
|
+
let currentLeaf = null;
|
|
2398
|
+
let modified = false;
|
|
2226
2399
|
for (const [key, value] of sorted) {
|
|
2227
|
-
|
|
2228
|
-
|
|
2229
|
-
|
|
2400
|
+
const targetLeaf = this.insertableNode(value);
|
|
2401
|
+
if (currentLeaf !== null && currentLeaf.id === targetLeaf.id) {
|
|
2402
|
+
} else {
|
|
2403
|
+
if (currentLeaf !== null && modified) {
|
|
2404
|
+
this._updateNode(currentLeaf);
|
|
2405
|
+
}
|
|
2406
|
+
currentLeaf = this._cloneNode(targetLeaf);
|
|
2407
|
+
modified = false;
|
|
2408
|
+
}
|
|
2409
|
+
const changed = this._insertValueIntoLeaf(currentLeaf, key, value);
|
|
2410
|
+
modified = modified || changed;
|
|
2411
|
+
if (currentLeaf.values.length === this.order) {
|
|
2412
|
+
this._updateNode(currentLeaf);
|
|
2230
2413
|
let after = this._createNode(
|
|
2231
2414
|
true,
|
|
2232
2415
|
[],
|
|
2233
2416
|
[],
|
|
2234
|
-
|
|
2417
|
+
currentLeaf.parent,
|
|
2235
2418
|
null,
|
|
2236
2419
|
null
|
|
2237
2420
|
);
|
|
2238
2421
|
const mid = Math.ceil(this.order / 2) - 1;
|
|
2239
2422
|
after = this._cloneNode(after);
|
|
2240
|
-
after.values =
|
|
2241
|
-
after.keys =
|
|
2242
|
-
|
|
2243
|
-
|
|
2244
|
-
this._updateNode(
|
|
2423
|
+
after.values = currentLeaf.values.slice(mid + 1);
|
|
2424
|
+
after.keys = currentLeaf.keys.slice(mid + 1);
|
|
2425
|
+
currentLeaf.values = currentLeaf.values.slice(0, mid + 1);
|
|
2426
|
+
currentLeaf.keys = currentLeaf.keys.slice(0, mid + 1);
|
|
2427
|
+
this._updateNode(currentLeaf);
|
|
2245
2428
|
this._updateNode(after);
|
|
2246
|
-
this._insertInParent(
|
|
2429
|
+
this._insertInParent(currentLeaf, after.values[0], after);
|
|
2430
|
+
currentLeaf = null;
|
|
2431
|
+
modified = false;
|
|
2247
2432
|
}
|
|
2248
2433
|
}
|
|
2434
|
+
if (currentLeaf !== null && modified) {
|
|
2435
|
+
this._updateNode(currentLeaf);
|
|
2436
|
+
}
|
|
2249
2437
|
}
|
|
2250
2438
|
_deleteEntry(node, key) {
|
|
2251
2439
|
if (!node.leaf) {
|
|
@@ -3260,16 +3448,20 @@ var BPTreeAsyncTransaction = class extends BPTreeTransaction {
|
|
|
3260
3448
|
const driverKey = this.getDriverKey(condition);
|
|
3261
3449
|
if (!driverKey) return;
|
|
3262
3450
|
const value = condition[driverKey];
|
|
3263
|
-
|
|
3264
|
-
|
|
3265
|
-
let
|
|
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();
|
|
3462
|
+
}
|
|
3463
|
+
if (!startNode) return;
|
|
3266
3464
|
const comparator = this.verifierMap[driverKey];
|
|
3267
|
-
const earlyTerminate = this.verifierEarlyTerminate[driverKey];
|
|
3268
|
-
if (order === "desc") {
|
|
3269
|
-
startNode = endNode ?? await this.rightestNode();
|
|
3270
|
-
endNode = null;
|
|
3271
|
-
direction *= -1;
|
|
3272
|
-
}
|
|
3273
3465
|
const generator = this.getPairsGenerator(
|
|
3274
3466
|
value,
|
|
3275
3467
|
startNode,
|
|
@@ -3281,7 +3473,7 @@ var BPTreeAsyncTransaction = class extends BPTreeTransaction {
|
|
|
3281
3473
|
let count = 0;
|
|
3282
3474
|
const intersection = filterValues && filterValues.size > 0 ? filterValues : null;
|
|
3283
3475
|
for await (const pair of generator) {
|
|
3284
|
-
const [k,
|
|
3476
|
+
const [k, v2] = pair;
|
|
3285
3477
|
if (intersection && !intersection.has(k)) {
|
|
3286
3478
|
continue;
|
|
3287
3479
|
}
|
|
@@ -3290,7 +3482,7 @@ var BPTreeAsyncTransaction = class extends BPTreeTransaction {
|
|
|
3290
3482
|
if (key === driverKey) continue;
|
|
3291
3483
|
const verify = this.verifierMap[key];
|
|
3292
3484
|
const condValue = condition[key];
|
|
3293
|
-
if (!verify(
|
|
3485
|
+
if (!verify(v2, condValue)) {
|
|
3294
3486
|
isMatch = false;
|
|
3295
3487
|
break;
|
|
3296
3488
|
}
|
|
@@ -3347,29 +3539,46 @@ var BPTreeAsyncTransaction = class extends BPTreeTransaction {
|
|
|
3347
3539
|
if (entries.length === 0) return;
|
|
3348
3540
|
return this.writeLock(0, async () => {
|
|
3349
3541
|
const sorted = [...entries].sort((a, b) => this.comparator.asc(a[1], b[1]));
|
|
3542
|
+
let currentLeaf = null;
|
|
3543
|
+
let modified = false;
|
|
3350
3544
|
for (const [key, value] of sorted) {
|
|
3351
|
-
|
|
3352
|
-
|
|
3353
|
-
|
|
3545
|
+
const targetLeaf = await this.insertableNode(value);
|
|
3546
|
+
if (currentLeaf !== null && currentLeaf.id === targetLeaf.id) {
|
|
3547
|
+
} else {
|
|
3548
|
+
if (currentLeaf !== null && modified) {
|
|
3549
|
+
await this._updateNode(currentLeaf);
|
|
3550
|
+
}
|
|
3551
|
+
currentLeaf = this._cloneNode(targetLeaf);
|
|
3552
|
+
modified = false;
|
|
3553
|
+
}
|
|
3554
|
+
const changed = this._insertValueIntoLeaf(currentLeaf, key, value);
|
|
3555
|
+
modified = modified || changed;
|
|
3556
|
+
if (currentLeaf.values.length === this.order) {
|
|
3557
|
+
await this._updateNode(currentLeaf);
|
|
3354
3558
|
let after = await this._createNode(
|
|
3355
3559
|
true,
|
|
3356
3560
|
[],
|
|
3357
3561
|
[],
|
|
3358
|
-
|
|
3562
|
+
currentLeaf.parent,
|
|
3359
3563
|
null,
|
|
3360
3564
|
null
|
|
3361
3565
|
);
|
|
3362
3566
|
const mid = Math.ceil(this.order / 2) - 1;
|
|
3363
3567
|
after = this._cloneNode(after);
|
|
3364
|
-
after.values =
|
|
3365
|
-
after.keys =
|
|
3366
|
-
|
|
3367
|
-
|
|
3368
|
-
await this._updateNode(
|
|
3568
|
+
after.values = currentLeaf.values.slice(mid + 1);
|
|
3569
|
+
after.keys = currentLeaf.keys.slice(mid + 1);
|
|
3570
|
+
currentLeaf.values = currentLeaf.values.slice(0, mid + 1);
|
|
3571
|
+
currentLeaf.keys = currentLeaf.keys.slice(0, mid + 1);
|
|
3572
|
+
await this._updateNode(currentLeaf);
|
|
3369
3573
|
await this._updateNode(after);
|
|
3370
|
-
await this._insertInParent(
|
|
3574
|
+
await this._insertInParent(currentLeaf, after.values[0], after);
|
|
3575
|
+
currentLeaf = null;
|
|
3576
|
+
modified = false;
|
|
3371
3577
|
}
|
|
3372
3578
|
}
|
|
3579
|
+
if (currentLeaf !== null && modified) {
|
|
3580
|
+
await this._updateNode(currentLeaf);
|
|
3581
|
+
}
|
|
3373
3582
|
});
|
|
3374
3583
|
}
|
|
3375
3584
|
async _deleteEntry(node, key) {
|
|
@@ -17,15 +17,12 @@ export declare abstract class BPTreeTransaction<K, V> {
|
|
|
17
17
|
protected isInitialized: boolean;
|
|
18
18
|
protected isDestroyed: boolean;
|
|
19
19
|
protected readonly verifierMap: Record<keyof BPTreeCondition<V>, (nodeValue: V, value: V | V[]) => boolean>;
|
|
20
|
-
protected readonly
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
* Only applicable for conditions that guarantee contiguous matches in a sorted B+Tree.
|
|
27
|
-
*/
|
|
28
|
-
protected readonly verifierEarlyTerminate: Record<keyof BPTreeCondition<V>, boolean>;
|
|
20
|
+
protected readonly searchConfigs: Record<keyof BPTreeCondition<V>, Record<'asc' | 'desc', {
|
|
21
|
+
start: (tx: BPTreeTransaction<K, V>, v: V[]) => Deferred<BPTreeLeafNode<K, V> | null>;
|
|
22
|
+
end: (tx: BPTreeTransaction<K, V>, v: V[]) => Deferred<BPTreeLeafNode<K, V> | null>;
|
|
23
|
+
direction: 1 | -1;
|
|
24
|
+
earlyTerminate: boolean;
|
|
25
|
+
}>>;
|
|
29
26
|
/**
|
|
30
27
|
* Priority map for condition types.
|
|
31
28
|
* Higher value = higher selectivity (fewer expected results).
|
|
@@ -80,6 +77,13 @@ export declare abstract class BPTreeTransaction<K, V> {
|
|
|
80
77
|
* @returns Returns true if the value satisfies the condition.
|
|
81
78
|
*/
|
|
82
79
|
verify(nodeValue: V, condition: BPTreeCondition<V>): boolean;
|
|
80
|
+
/**
|
|
81
|
+
* Inserts a key-value pair into an already-cloned leaf node in-place.
|
|
82
|
+
* Unlike _insertAtLeaf, this does NOT clone or update the node via MVCC.
|
|
83
|
+
* Used by batchInsert to batch multiple insertions with a single clone/update.
|
|
84
|
+
* @returns true if the leaf was modified, false if the key already exists.
|
|
85
|
+
*/
|
|
86
|
+
protected _insertValueIntoLeaf(leaf: BPTreeLeafNode<K, V>, key: K, value: V): boolean;
|
|
83
87
|
protected _cloneNode<T extends BPTreeUnknownNode<K, V>>(node: T): T;
|
|
84
88
|
/**
|
|
85
89
|
* Selects the best driver key from a condition object.
|