serializable-bptree 8.3.1 → 8.3.3

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.
@@ -1519,83 +1519,217 @@ var BPTreeTransaction = class _BPTreeTransaction {
1519
1519
  return regexp.test(nodeValue);
1520
1520
  }
1521
1521
  };
1522
- verifierStartNode = {
1523
- gt: (v) => this.insertableNodeByPrimary(v),
1524
- gte: (v) => this.insertableNodeByPrimary(v),
1525
- lt: (v) => this.insertableNodeByPrimary(v),
1526
- lte: (v) => this.insertableRightestNodeByPrimary(v),
1527
- equal: (v) => this.insertableNodeByPrimary(v),
1528
- notEqual: (v) => this.leftestNode(),
1529
- or: (v) => this.insertableNodeByPrimary(this.lowestPrimaryValue(this.ensureValues(v))),
1530
- primaryGt: (v) => this.insertableNodeByPrimary(v),
1531
- primaryGte: (v) => this.insertableNodeByPrimary(v),
1532
- primaryLt: (v) => this.insertableNodeByPrimary(v),
1533
- primaryLte: (v) => this.insertableRightestNodeByPrimary(v),
1534
- primaryEqual: (v) => this.insertableNodeByPrimary(v),
1535
- primaryNotEqual: (v) => this.leftestNode(),
1536
- primaryOr: (v) => this.insertableNodeByPrimary(this.lowestPrimaryValue(this.ensureValues(v))),
1537
- like: (v) => this.leftestNode()
1538
- };
1539
- verifierEndNode = {
1540
- gt: (v) => null,
1541
- gte: (v) => null,
1542
- lt: (v) => null,
1543
- lte: (v) => null,
1544
- equal: (v) => this.insertableEndNode(v, this.verifierDirection.equal),
1545
- notEqual: (v) => null,
1546
- or: (v) => this.insertableEndNode(
1547
- this.highestValue(this.ensureValues(v)),
1548
- this.verifierDirection.or
1549
- ),
1550
- primaryGt: (v) => null,
1551
- primaryGte: (v) => null,
1552
- primaryLt: (v) => null,
1553
- primaryLte: (v) => null,
1554
- primaryEqual: (v) => this.insertableRightestEndNodeByPrimary(v),
1555
- primaryNotEqual: (v) => null,
1556
- primaryOr: (v) => this.insertableRightestEndNodeByPrimary(
1557
- this.highestPrimaryValue(this.ensureValues(v))
1558
- ),
1559
- like: (v) => null
1560
- };
1561
- verifierDirection = {
1562
- gt: 1,
1563
- gte: 1,
1564
- lt: -1,
1565
- lte: -1,
1566
- equal: 1,
1567
- notEqual: 1,
1568
- or: 1,
1569
- primaryGt: 1,
1570
- primaryGte: 1,
1571
- primaryLt: -1,
1572
- primaryLte: -1,
1573
- primaryEqual: 1,
1574
- primaryNotEqual: 1,
1575
- primaryOr: 1,
1576
- like: 1
1577
- };
1578
- /**
1579
- * Determines whether early termination is allowed for each condition.
1580
- * When true, the search will stop once a match is found and then a non-match is encountered.
1581
- * Only applicable for conditions that guarantee contiguous matches in a sorted B+Tree.
1582
- */
1583
- verifierEarlyTerminate = {
1584
- gt: false,
1585
- gte: false,
1586
- lt: false,
1587
- lte: false,
1588
- equal: true,
1589
- notEqual: false,
1590
- or: false,
1591
- primaryGt: false,
1592
- primaryGte: false,
1593
- primaryLt: false,
1594
- primaryLte: false,
1595
- primaryEqual: true,
1596
- primaryNotEqual: false,
1597
- primaryOr: false,
1598
- like: false
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.insertableRightestEndNodeByPrimary(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.
@@ -2027,7 +2161,7 @@ var BPTreeSyncTransaction = class extends BPTreeTransaction {
2027
2161
  return this.getNode(node.next);
2028
2162
  }
2029
2163
  insertableEndNode(value, direction) {
2030
- const insertableNode = this.insertableNode(value);
2164
+ const insertableNode = direction === -1 ? this.insertableNodeByPrimary(value) : this.insertableRightestNodeByPrimary(value);
2031
2165
  let key;
2032
2166
  switch (direction) {
2033
2167
  case -1:
@@ -2208,16 +2342,20 @@ var BPTreeSyncTransaction = class extends BPTreeTransaction {
2208
2342
  const driverKey = this.getDriverKey(condition);
2209
2343
  if (!driverKey) return;
2210
2344
  const value = condition[driverKey];
2211
- let startNode = this.verifierStartNode[driverKey](value);
2212
- let endNode = this.verifierEndNode[driverKey](value);
2213
- let direction = this.verifierDirection[driverKey];
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;
2214
2358
  const comparator = this.verifierMap[driverKey];
2215
- const earlyTerminate = this.verifierEarlyTerminate[driverKey];
2216
- if (order === "desc") {
2217
- startNode = endNode ?? this.rightestNode();
2218
- endNode = null;
2219
- direction *= -1;
2220
- }
2221
2359
  const generator = this.getPairsGenerator(
2222
2360
  value,
2223
2361
  startNode,
@@ -2229,7 +2367,7 @@ var BPTreeSyncTransaction = class extends BPTreeTransaction {
2229
2367
  let count = 0;
2230
2368
  const intersection = filterValues && filterValues.size > 0 ? filterValues : null;
2231
2369
  for (const pair of generator) {
2232
- const [k, v] = pair;
2370
+ const [k, v2] = pair;
2233
2371
  if (intersection && !intersection.has(k)) {
2234
2372
  continue;
2235
2373
  }
@@ -2238,7 +2376,7 @@ var BPTreeSyncTransaction = class extends BPTreeTransaction {
2238
2376
  if (key === driverKey) continue;
2239
2377
  const verify = this.verifierMap[key];
2240
2378
  const condValue = condition[key];
2241
- if (!verify(v, condValue)) {
2379
+ if (!verify(v2, condValue)) {
2242
2380
  isMatch = false;
2243
2381
  break;
2244
2382
  }
@@ -3159,7 +3297,7 @@ var BPTreeAsyncTransaction = class extends BPTreeTransaction {
3159
3297
  return await this.getNode(node.next);
3160
3298
  }
3161
3299
  async insertableEndNode(value, direction) {
3162
- const insertableNode = await this.insertableNode(value);
3300
+ const insertableNode = direction === -1 ? await this.insertableNodeByPrimary(value) : await this.insertableRightestNodeByPrimary(value);
3163
3301
  let key;
3164
3302
  switch (direction) {
3165
3303
  case -1:
@@ -3346,16 +3484,20 @@ var BPTreeAsyncTransaction = class extends BPTreeTransaction {
3346
3484
  const driverKey = this.getDriverKey(condition);
3347
3485
  if (!driverKey) return;
3348
3486
  const value = condition[driverKey];
3349
- let startNode = await this.verifierStartNode[driverKey](value);
3350
- let endNode = await this.verifierEndNode[driverKey](value);
3351
- let direction = this.verifierDirection[driverKey];
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;
3352
3500
  const comparator = this.verifierMap[driverKey];
3353
- const earlyTerminate = this.verifierEarlyTerminate[driverKey];
3354
- if (order === "desc") {
3355
- startNode = endNode ?? await this.rightestNode();
3356
- endNode = null;
3357
- direction *= -1;
3358
- }
3359
3501
  const generator = this.getPairsGenerator(
3360
3502
  value,
3361
3503
  startNode,
@@ -3367,7 +3509,7 @@ var BPTreeAsyncTransaction = class extends BPTreeTransaction {
3367
3509
  let count = 0;
3368
3510
  const intersection = filterValues && filterValues.size > 0 ? filterValues : null;
3369
3511
  for await (const pair of generator) {
3370
- const [k, v] = pair;
3512
+ const [k, v2] = pair;
3371
3513
  if (intersection && !intersection.has(k)) {
3372
3514
  continue;
3373
3515
  }
@@ -3376,7 +3518,7 @@ var BPTreeAsyncTransaction = class extends BPTreeTransaction {
3376
3518
  if (key === driverKey) continue;
3377
3519
  const verify = this.verifierMap[key];
3378
3520
  const condValue = condition[key];
3379
- if (!verify(v, condValue)) {
3521
+ if (!verify(v2, condValue)) {
3380
3522
  isMatch = false;
3381
3523
  break;
3382
3524
  }
@@ -1483,83 +1483,217 @@ var BPTreeTransaction = class _BPTreeTransaction {
1483
1483
  return regexp.test(nodeValue);
1484
1484
  }
1485
1485
  };
1486
- verifierStartNode = {
1487
- gt: (v) => this.insertableNodeByPrimary(v),
1488
- gte: (v) => this.insertableNodeByPrimary(v),
1489
- lt: (v) => this.insertableNodeByPrimary(v),
1490
- lte: (v) => this.insertableRightestNodeByPrimary(v),
1491
- equal: (v) => this.insertableNodeByPrimary(v),
1492
- notEqual: (v) => this.leftestNode(),
1493
- or: (v) => this.insertableNodeByPrimary(this.lowestPrimaryValue(this.ensureValues(v))),
1494
- primaryGt: (v) => this.insertableNodeByPrimary(v),
1495
- primaryGte: (v) => this.insertableNodeByPrimary(v),
1496
- primaryLt: (v) => this.insertableNodeByPrimary(v),
1497
- primaryLte: (v) => this.insertableRightestNodeByPrimary(v),
1498
- primaryEqual: (v) => this.insertableNodeByPrimary(v),
1499
- primaryNotEqual: (v) => this.leftestNode(),
1500
- primaryOr: (v) => this.insertableNodeByPrimary(this.lowestPrimaryValue(this.ensureValues(v))),
1501
- like: (v) => this.leftestNode()
1502
- };
1503
- verifierEndNode = {
1504
- gt: (v) => null,
1505
- gte: (v) => null,
1506
- lt: (v) => null,
1507
- lte: (v) => null,
1508
- equal: (v) => this.insertableEndNode(v, this.verifierDirection.equal),
1509
- notEqual: (v) => null,
1510
- or: (v) => this.insertableEndNode(
1511
- this.highestValue(this.ensureValues(v)),
1512
- this.verifierDirection.or
1513
- ),
1514
- primaryGt: (v) => null,
1515
- primaryGte: (v) => null,
1516
- primaryLt: (v) => null,
1517
- primaryLte: (v) => null,
1518
- primaryEqual: (v) => this.insertableRightestEndNodeByPrimary(v),
1519
- primaryNotEqual: (v) => null,
1520
- primaryOr: (v) => this.insertableRightestEndNodeByPrimary(
1521
- this.highestPrimaryValue(this.ensureValues(v))
1522
- ),
1523
- like: (v) => null
1524
- };
1525
- verifierDirection = {
1526
- gt: 1,
1527
- gte: 1,
1528
- lt: -1,
1529
- lte: -1,
1530
- equal: 1,
1531
- notEqual: 1,
1532
- or: 1,
1533
- primaryGt: 1,
1534
- primaryGte: 1,
1535
- primaryLt: -1,
1536
- primaryLte: -1,
1537
- primaryEqual: 1,
1538
- primaryNotEqual: 1,
1539
- primaryOr: 1,
1540
- like: 1
1541
- };
1542
- /**
1543
- * Determines whether early termination is allowed for each condition.
1544
- * When true, the search will stop once a match is found and then a non-match is encountered.
1545
- * Only applicable for conditions that guarantee contiguous matches in a sorted B+Tree.
1546
- */
1547
- verifierEarlyTerminate = {
1548
- gt: false,
1549
- gte: false,
1550
- lt: false,
1551
- lte: false,
1552
- equal: true,
1553
- notEqual: false,
1554
- or: false,
1555
- primaryGt: false,
1556
- primaryGte: false,
1557
- primaryLt: false,
1558
- primaryLte: false,
1559
- primaryEqual: true,
1560
- primaryNotEqual: false,
1561
- primaryOr: false,
1562
- like: false
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.insertableRightestEndNodeByPrimary(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.
@@ -1991,7 +2125,7 @@ var BPTreeSyncTransaction = class extends BPTreeTransaction {
1991
2125
  return this.getNode(node.next);
1992
2126
  }
1993
2127
  insertableEndNode(value, direction) {
1994
- const insertableNode = this.insertableNode(value);
2128
+ const insertableNode = direction === -1 ? this.insertableNodeByPrimary(value) : this.insertableRightestNodeByPrimary(value);
1995
2129
  let key;
1996
2130
  switch (direction) {
1997
2131
  case -1:
@@ -2172,16 +2306,20 @@ var BPTreeSyncTransaction = class extends BPTreeTransaction {
2172
2306
  const driverKey = this.getDriverKey(condition);
2173
2307
  if (!driverKey) return;
2174
2308
  const value = condition[driverKey];
2175
- let startNode = this.verifierStartNode[driverKey](value);
2176
- let endNode = this.verifierEndNode[driverKey](value);
2177
- let direction = this.verifierDirection[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();
2320
+ }
2321
+ if (!startNode) return;
2178
2322
  const comparator = this.verifierMap[driverKey];
2179
- const earlyTerminate = this.verifierEarlyTerminate[driverKey];
2180
- if (order === "desc") {
2181
- startNode = endNode ?? this.rightestNode();
2182
- endNode = null;
2183
- direction *= -1;
2184
- }
2185
2323
  const generator = this.getPairsGenerator(
2186
2324
  value,
2187
2325
  startNode,
@@ -2193,7 +2331,7 @@ var BPTreeSyncTransaction = class extends BPTreeTransaction {
2193
2331
  let count = 0;
2194
2332
  const intersection = filterValues && filterValues.size > 0 ? filterValues : null;
2195
2333
  for (const pair of generator) {
2196
- const [k, v] = pair;
2334
+ const [k, v2] = pair;
2197
2335
  if (intersection && !intersection.has(k)) {
2198
2336
  continue;
2199
2337
  }
@@ -2202,7 +2340,7 @@ var BPTreeSyncTransaction = class extends BPTreeTransaction {
2202
2340
  if (key === driverKey) continue;
2203
2341
  const verify = this.verifierMap[key];
2204
2342
  const condValue = condition[key];
2205
- if (!verify(v, condValue)) {
2343
+ if (!verify(v2, condValue)) {
2206
2344
  isMatch = false;
2207
2345
  break;
2208
2346
  }
@@ -3123,7 +3261,7 @@ var BPTreeAsyncTransaction = class extends BPTreeTransaction {
3123
3261
  return await this.getNode(node.next);
3124
3262
  }
3125
3263
  async insertableEndNode(value, direction) {
3126
- const insertableNode = await this.insertableNode(value);
3264
+ const insertableNode = direction === -1 ? await this.insertableNodeByPrimary(value) : await this.insertableRightestNodeByPrimary(value);
3127
3265
  let key;
3128
3266
  switch (direction) {
3129
3267
  case -1:
@@ -3310,16 +3448,20 @@ var BPTreeAsyncTransaction = class extends BPTreeTransaction {
3310
3448
  const driverKey = this.getDriverKey(condition);
3311
3449
  if (!driverKey) return;
3312
3450
  const value = condition[driverKey];
3313
- let startNode = await this.verifierStartNode[driverKey](value);
3314
- let endNode = await this.verifierEndNode[driverKey](value);
3315
- let direction = this.verifierDirection[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();
3462
+ }
3463
+ if (!startNode) return;
3316
3464
  const comparator = this.verifierMap[driverKey];
3317
- const earlyTerminate = this.verifierEarlyTerminate[driverKey];
3318
- if (order === "desc") {
3319
- startNode = endNode ?? await this.rightestNode();
3320
- endNode = null;
3321
- direction *= -1;
3322
- }
3323
3465
  const generator = this.getPairsGenerator(
3324
3466
  value,
3325
3467
  startNode,
@@ -3331,7 +3473,7 @@ var BPTreeAsyncTransaction = class extends BPTreeTransaction {
3331
3473
  let count = 0;
3332
3474
  const intersection = filterValues && filterValues.size > 0 ? filterValues : null;
3333
3475
  for await (const pair of generator) {
3334
- const [k, v] = pair;
3476
+ const [k, v2] = pair;
3335
3477
  if (intersection && !intersection.has(k)) {
3336
3478
  continue;
3337
3479
  }
@@ -3340,7 +3482,7 @@ var BPTreeAsyncTransaction = class extends BPTreeTransaction {
3340
3482
  if (key === driverKey) continue;
3341
3483
  const verify = this.verifierMap[key];
3342
3484
  const condValue = condition[key];
3343
- if (!verify(v, condValue)) {
3485
+ if (!verify(v2, condValue)) {
3344
3486
  isMatch = false;
3345
3487
  break;
3346
3488
  }
@@ -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 verifierStartNode: Record<keyof BPTreeCondition<V>, (value: V) => Deferred<BPTreeLeafNode<K, V>>>;
21
- protected readonly verifierEndNode: Record<keyof BPTreeCondition<V>, (value: V) => Deferred<BPTreeLeafNode<K, V> | null>>;
22
- protected readonly verifierDirection: Record<keyof BPTreeCondition<V>, -1 | 1>;
23
- /**
24
- * Determines whether early termination is allowed for each condition.
25
- * When true, the search will stop once a match is found and then a non-match is encountered.
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).
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "serializable-bptree",
3
- "version": "8.3.1",
3
+ "version": "8.3.3",
4
4
  "description": "Store the B+tree flexibly, not only in-memory.",
5
5
  "types": "./dist/types/index.d.ts",
6
6
  "main": "./dist/cjs/index.cjs",