document-dataply 0.0.9-alpha.5 → 0.0.9-alpha.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/cjs/index.js +261 -102
  2. package/package.json +2 -2
package/dist/cjs/index.js CHANGED
@@ -1580,83 +1580,217 @@ var require_cjs = __commonJS({
1580
1580
  return regexp.test(nodeValue);
1581
1581
  }
1582
1582
  };
1583
- verifierStartNode = {
1584
- gt: (v) => this.insertableNodeByPrimary(v),
1585
- gte: (v) => this.insertableNodeByPrimary(v),
1586
- lt: (v) => this.insertableNodeByPrimary(v),
1587
- lte: (v) => this.insertableRightestNodeByPrimary(v),
1588
- equal: (v) => this.insertableNodeByPrimary(v),
1589
- notEqual: (v) => this.leftestNode(),
1590
- or: (v) => this.insertableNodeByPrimary(this.lowestPrimaryValue(this.ensureValues(v))),
1591
- primaryGt: (v) => this.insertableNodeByPrimary(v),
1592
- primaryGte: (v) => this.insertableNodeByPrimary(v),
1593
- primaryLt: (v) => this.insertableNodeByPrimary(v),
1594
- primaryLte: (v) => this.insertableRightestNodeByPrimary(v),
1595
- primaryEqual: (v) => this.insertableNodeByPrimary(v),
1596
- primaryNotEqual: (v) => this.leftestNode(),
1597
- primaryOr: (v) => this.insertableNodeByPrimary(this.lowestPrimaryValue(this.ensureValues(v))),
1598
- like: (v) => this.leftestNode()
1599
- };
1600
- verifierEndNode = {
1601
- gt: (v) => null,
1602
- gte: (v) => null,
1603
- lt: (v) => null,
1604
- lte: (v) => null,
1605
- equal: (v) => this.insertableEndNode(v, this.verifierDirection.equal),
1606
- notEqual: (v) => null,
1607
- or: (v) => this.insertableEndNode(
1608
- this.highestValue(this.ensureValues(v)),
1609
- this.verifierDirection.or
1610
- ),
1611
- primaryGt: (v) => null,
1612
- primaryGte: (v) => null,
1613
- primaryLt: (v) => null,
1614
- primaryLte: (v) => null,
1615
- primaryEqual: (v) => this.insertableRightestEndNodeByPrimary(v),
1616
- primaryNotEqual: (v) => null,
1617
- primaryOr: (v) => this.insertableRightestEndNodeByPrimary(
1618
- this.highestPrimaryValue(this.ensureValues(v))
1619
- ),
1620
- like: (v) => null
1621
- };
1622
- verifierDirection = {
1623
- gt: 1,
1624
- gte: 1,
1625
- lt: -1,
1626
- lte: -1,
1627
- equal: 1,
1628
- notEqual: 1,
1629
- or: 1,
1630
- primaryGt: 1,
1631
- primaryGte: 1,
1632
- primaryLt: -1,
1633
- primaryLte: -1,
1634
- primaryEqual: 1,
1635
- primaryNotEqual: 1,
1636
- primaryOr: 1,
1637
- like: 1
1638
- };
1639
- /**
1640
- * Determines whether early termination is allowed for each condition.
1641
- * When true, the search will stop once a match is found and then a non-match is encountered.
1642
- * Only applicable for conditions that guarantee contiguous matches in a sorted B+Tree.
1643
- */
1644
- verifierEarlyTerminate = {
1645
- gt: false,
1646
- gte: false,
1647
- lt: false,
1648
- lte: false,
1649
- equal: true,
1650
- notEqual: false,
1651
- or: false,
1652
- primaryGt: false,
1653
- primaryGte: false,
1654
- primaryLt: false,
1655
- primaryLte: false,
1656
- primaryEqual: true,
1657
- primaryNotEqual: false,
1658
- primaryOr: false,
1659
- like: false
1583
+ searchConfigs = {
1584
+ gt: {
1585
+ asc: {
1586
+ start: (tx, v) => tx.insertableNodeByPrimary(v[0]),
1587
+ end: () => null,
1588
+ direction: 1,
1589
+ earlyTerminate: false
1590
+ },
1591
+ desc: {
1592
+ start: (tx) => tx.rightestNode(),
1593
+ end: (tx, v) => tx.insertableEndNode(v[0], -1),
1594
+ direction: -1,
1595
+ earlyTerminate: true
1596
+ }
1597
+ },
1598
+ gte: {
1599
+ asc: {
1600
+ start: (tx, v) => tx.insertableNodeByPrimary(v[0]),
1601
+ end: () => null,
1602
+ direction: 1,
1603
+ earlyTerminate: false
1604
+ },
1605
+ desc: {
1606
+ start: (tx) => tx.rightestNode(),
1607
+ end: (tx, v) => tx.insertableEndNode(v[0], -1),
1608
+ direction: -1,
1609
+ earlyTerminate: true
1610
+ }
1611
+ },
1612
+ lt: {
1613
+ asc: {
1614
+ start: (tx) => tx.leftestNode(),
1615
+ end: (tx, v) => tx.insertableEndNode(v[0], 1),
1616
+ direction: 1,
1617
+ earlyTerminate: true
1618
+ },
1619
+ desc: {
1620
+ start: (tx, v) => tx.insertableNodeByPrimary(v[0]),
1621
+ end: () => null,
1622
+ direction: -1,
1623
+ earlyTerminate: false
1624
+ }
1625
+ },
1626
+ lte: {
1627
+ asc: {
1628
+ start: (tx) => tx.leftestNode(),
1629
+ end: (tx, v) => tx.insertableEndNode(v[0], 1),
1630
+ direction: 1,
1631
+ earlyTerminate: true
1632
+ },
1633
+ desc: {
1634
+ start: (tx, v) => tx.insertableRightestNodeByPrimary(v[0]),
1635
+ end: () => null,
1636
+ direction: -1,
1637
+ earlyTerminate: false
1638
+ }
1639
+ },
1640
+ equal: {
1641
+ asc: {
1642
+ start: (tx, v) => tx.insertableNodeByPrimary(v[0]),
1643
+ end: (tx, v) => tx.insertableEndNode(v[0], 1),
1644
+ direction: 1,
1645
+ earlyTerminate: true
1646
+ },
1647
+ desc: {
1648
+ start: (tx, v) => tx.insertableEndNode(v[0], 1),
1649
+ end: (tx, v) => tx.insertableEndNode(v[0], -1),
1650
+ direction: -1,
1651
+ earlyTerminate: true
1652
+ }
1653
+ },
1654
+ notEqual: {
1655
+ asc: {
1656
+ start: (tx) => tx.leftestNode(),
1657
+ end: () => null,
1658
+ direction: 1,
1659
+ earlyTerminate: false
1660
+ },
1661
+ desc: {
1662
+ start: (tx) => tx.rightestNode(),
1663
+ end: () => null,
1664
+ direction: -1,
1665
+ earlyTerminate: false
1666
+ }
1667
+ },
1668
+ or: {
1669
+ asc: {
1670
+ start: (tx, v) => tx.insertableNodeByPrimary(tx.lowestValue(v)),
1671
+ end: (tx, v) => tx.insertableEndNode(tx.highestValue(v), 1),
1672
+ direction: 1,
1673
+ earlyTerminate: false
1674
+ },
1675
+ desc: {
1676
+ start: (tx, v) => tx.insertableEndNode(tx.highestValue(v), 1),
1677
+ end: (tx, v) => tx.insertableEndNode(tx.lowestValue(v), -1),
1678
+ direction: -1,
1679
+ earlyTerminate: false
1680
+ }
1681
+ },
1682
+ primaryGt: {
1683
+ asc: {
1684
+ start: (tx, v) => tx.insertableNodeByPrimary(v[0]),
1685
+ end: () => null,
1686
+ direction: 1,
1687
+ earlyTerminate: false
1688
+ },
1689
+ desc: {
1690
+ start: (tx) => tx.rightestNode(),
1691
+ end: (tx, v) => tx.insertableEndNode(v[0], -1),
1692
+ direction: -1,
1693
+ earlyTerminate: true
1694
+ }
1695
+ },
1696
+ primaryGte: {
1697
+ asc: {
1698
+ start: (tx, v) => tx.insertableNodeByPrimary(v[0]),
1699
+ end: () => null,
1700
+ direction: 1,
1701
+ earlyTerminate: false
1702
+ },
1703
+ desc: {
1704
+ start: (tx) => tx.rightestNode(),
1705
+ end: (tx, v) => tx.insertableEndNode(v[0], -1),
1706
+ direction: -1,
1707
+ earlyTerminate: true
1708
+ }
1709
+ },
1710
+ primaryLt: {
1711
+ asc: {
1712
+ start: (tx) => tx.leftestNode(),
1713
+ end: (tx, v) => tx.insertableEndNode(v[0], 1),
1714
+ direction: 1,
1715
+ earlyTerminate: true
1716
+ },
1717
+ desc: {
1718
+ start: (tx, v) => tx.insertableNodeByPrimary(v[0]),
1719
+ end: () => null,
1720
+ direction: -1,
1721
+ earlyTerminate: false
1722
+ }
1723
+ },
1724
+ primaryLte: {
1725
+ asc: {
1726
+ start: (tx) => tx.leftestNode(),
1727
+ end: (tx, v) => tx.insertableEndNode(v[0], 1),
1728
+ direction: 1,
1729
+ earlyTerminate: true
1730
+ },
1731
+ desc: {
1732
+ start: (tx, v) => tx.insertableRightestNodeByPrimary(v[0]),
1733
+ end: () => null,
1734
+ direction: -1,
1735
+ earlyTerminate: false
1736
+ }
1737
+ },
1738
+ primaryEqual: {
1739
+ asc: {
1740
+ start: (tx, v) => tx.insertableNodeByPrimary(v[0]),
1741
+ end: (tx, v) => tx.insertableRightestEndNodeByPrimary(v[0]),
1742
+ direction: 1,
1743
+ earlyTerminate: true
1744
+ },
1745
+ desc: {
1746
+ start: (tx, v) => tx.insertableRightestEndNodeByPrimary(v[0]),
1747
+ end: (tx, v) => tx.insertableEndNode(v[0], -1),
1748
+ direction: -1,
1749
+ earlyTerminate: true
1750
+ }
1751
+ },
1752
+ primaryNotEqual: {
1753
+ asc: {
1754
+ start: (tx) => tx.leftestNode(),
1755
+ end: () => null,
1756
+ direction: 1,
1757
+ earlyTerminate: false
1758
+ },
1759
+ desc: {
1760
+ start: (tx) => tx.rightestNode(),
1761
+ end: () => null,
1762
+ direction: -1,
1763
+ earlyTerminate: false
1764
+ }
1765
+ },
1766
+ primaryOr: {
1767
+ asc: {
1768
+ start: (tx, v) => tx.insertableNodeByPrimary(tx.lowestPrimaryValue(v)),
1769
+ end: (tx, v) => tx.insertableRightestEndNodeByPrimary(tx.highestPrimaryValue(v)),
1770
+ direction: 1,
1771
+ earlyTerminate: false
1772
+ },
1773
+ desc: {
1774
+ start: (tx, v) => tx.insertableRightestEndNodeByPrimary(tx.highestPrimaryValue(v)),
1775
+ end: (tx, v) => tx.insertableEndNode(tx.lowestPrimaryValue(v), -1),
1776
+ direction: -1,
1777
+ earlyTerminate: false
1778
+ }
1779
+ },
1780
+ like: {
1781
+ asc: {
1782
+ start: (tx) => tx.leftestNode(),
1783
+ end: () => null,
1784
+ direction: 1,
1785
+ earlyTerminate: false
1786
+ },
1787
+ desc: {
1788
+ start: (tx) => tx.rightestNode(),
1789
+ end: () => null,
1790
+ direction: -1,
1791
+ earlyTerminate: false
1792
+ }
1793
+ }
1660
1794
  };
1661
1795
  /**
1662
1796
  * Priority map for condition types.
@@ -2267,16 +2401,20 @@ var require_cjs = __commonJS({
2267
2401
  const driverKey = this.getDriverKey(condition);
2268
2402
  if (!driverKey) return;
2269
2403
  const value = condition[driverKey];
2270
- let startNode = this.verifierStartNode[driverKey](value);
2271
- let endNode = this.verifierEndNode[driverKey](value);
2272
- let direction = this.verifierDirection[driverKey];
2404
+ const v = this.ensureValues(value);
2405
+ const config = this.searchConfigs[driverKey][order];
2406
+ let startNode = config.start(this, v);
2407
+ let endNode = config.end(this, v);
2408
+ const direction = config.direction;
2409
+ const earlyTerminate = config.earlyTerminate;
2410
+ if (order === "desc" && !startNode) {
2411
+ startNode = this.rightestNode();
2412
+ }
2413
+ if (order === "asc" && !startNode) {
2414
+ startNode = this.leftestNode();
2415
+ }
2416
+ if (!startNode) return;
2273
2417
  const comparator = this.verifierMap[driverKey];
2274
- const earlyTerminate = this.verifierEarlyTerminate[driverKey];
2275
- if (order === "desc") {
2276
- startNode = endNode ?? this.rightestNode();
2277
- endNode = null;
2278
- direction *= -1;
2279
- }
2280
2418
  const generator = this.getPairsGenerator(
2281
2419
  value,
2282
2420
  startNode,
@@ -2288,7 +2426,7 @@ var require_cjs = __commonJS({
2288
2426
  let count = 0;
2289
2427
  const intersection = filterValues && filterValues.size > 0 ? filterValues : null;
2290
2428
  for (const pair of generator) {
2291
- const [k, v] = pair;
2429
+ const [k, v2] = pair;
2292
2430
  if (intersection && !intersection.has(k)) {
2293
2431
  continue;
2294
2432
  }
@@ -2297,7 +2435,7 @@ var require_cjs = __commonJS({
2297
2435
  if (key === driverKey) continue;
2298
2436
  const verify = this.verifierMap[key];
2299
2437
  const condValue = condition[key];
2300
- if (!verify(v, condValue)) {
2438
+ if (!verify(v2, condValue)) {
2301
2439
  isMatch = false;
2302
2440
  break;
2303
2441
  }
@@ -3397,16 +3535,20 @@ var require_cjs = __commonJS({
3397
3535
  const driverKey = this.getDriverKey(condition);
3398
3536
  if (!driverKey) return;
3399
3537
  const value = condition[driverKey];
3400
- let startNode = await this.verifierStartNode[driverKey](value);
3401
- let endNode = await this.verifierEndNode[driverKey](value);
3402
- let direction = this.verifierDirection[driverKey];
3538
+ const v = this.ensureValues(value);
3539
+ const config = this.searchConfigs[driverKey][order];
3540
+ let startNode = await config.start(this, v);
3541
+ let endNode = await config.end(this, v);
3542
+ const direction = config.direction;
3543
+ const earlyTerminate = config.earlyTerminate;
3544
+ if (order === "desc" && !startNode) {
3545
+ startNode = await this.rightestNode();
3546
+ }
3547
+ if (order === "asc" && !startNode) {
3548
+ startNode = await this.leftestNode();
3549
+ }
3550
+ if (!startNode) return;
3403
3551
  const comparator = this.verifierMap[driverKey];
3404
- const earlyTerminate = this.verifierEarlyTerminate[driverKey];
3405
- if (order === "desc") {
3406
- startNode = endNode ?? await this.rightestNode();
3407
- endNode = null;
3408
- direction *= -1;
3409
- }
3410
3552
  const generator = this.getPairsGenerator(
3411
3553
  value,
3412
3554
  startNode,
@@ -3418,7 +3560,7 @@ var require_cjs = __commonJS({
3418
3560
  let count = 0;
3419
3561
  const intersection = filterValues && filterValues.size > 0 ? filterValues : null;
3420
3562
  for await (const pair of generator) {
3421
- const [k, v] = pair;
3563
+ const [k, v2] = pair;
3422
3564
  if (intersection && !intersection.has(k)) {
3423
3565
  continue;
3424
3566
  }
@@ -3427,7 +3569,7 @@ var require_cjs = __commonJS({
3427
3569
  if (key === driverKey) continue;
3428
3570
  const verify = this.verifierMap[key];
3429
3571
  const condValue = condition[key];
3430
- if (!verify(v, condValue)) {
3572
+ if (!verify(v2, condValue)) {
3431
3573
  isMatch = false;
3432
3574
  break;
3433
3575
  }
@@ -8342,7 +8484,7 @@ var require_cjs = __commonJS({
8342
8484
  /**
8343
8485
  * Appends and inserts a new page.
8344
8486
  * If a free page is available in the free list, it reuses it.
8345
- * Otherwise, it appends a new page to the end of the file.
8487
+ * Otherwise, it preallocates `pagePreallocationCount` pages to support sequential reads.
8346
8488
  * @returns Created or reused page ID
8347
8489
  */
8348
8490
  async appendNewPage(pageType = PageManager.CONSTANT.PAGE_TYPE_EMPTY, tx) {
@@ -8363,12 +8505,26 @@ var require_cjs = __commonJS({
8363
8505
  await this.setPage(reusedPageId, newPage2, tx);
8364
8506
  return reusedPageId;
8365
8507
  }
8508
+ const preallocationCount = this.options.pagePreallocationCount;
8366
8509
  const pageCount = metadataManager.getPageCount(metadata);
8367
8510
  const newPageIndex = pageCount;
8368
- const newTotalCount = pageCount + 1;
8511
+ const newTotalCount = pageCount + preallocationCount;
8369
8512
  const manager = this.pageFactory.getManagerFromType(pageType);
8370
8513
  const newPage = manager.create(this.pageSize, newPageIndex);
8371
8514
  await this.setPage(newPageIndex, newPage, tx);
8515
+ const emptyManager = this.pageFactory.getManagerFromType(PageManager.CONSTANT.PAGE_TYPE_EMPTY);
8516
+ const firstFreeIndex = newPageIndex + 1;
8517
+ const lastFreeIndex = newPageIndex + preallocationCount - 1;
8518
+ for (let i = firstFreeIndex; i <= lastFreeIndex; i++) {
8519
+ const emptyPage = emptyManager.create(this.pageSize, i);
8520
+ const nextId = i < lastFreeIndex ? i + 1 : -1;
8521
+ emptyManager.setNextPageId(emptyPage, nextId);
8522
+ await this.setPage(i, emptyPage, tx);
8523
+ await this.updateBitmap(i, true, tx);
8524
+ }
8525
+ if (preallocationCount > 1) {
8526
+ metadataManager.setFreePageId(metadata, firstFreeIndex);
8527
+ }
8372
8528
  metadataManager.setPageCount(metadata, newTotalCount);
8373
8529
  await this.setPage(0, metadata, tx);
8374
8530
  return newPageIndex;
@@ -9168,7 +9324,9 @@ var require_cjs = __commonJS({
9168
9324
  }
9169
9325
  pageGroupMap.get(pageId).push({ pk: pair.pk, slotIndex, index: pair.index });
9170
9326
  }
9171
- await Promise.all(Array.from(pageGroupMap).map(async ([pageId, items]) => {
9327
+ const sortedPageIds = Array.from(pageGroupMap.keys()).sort((a, b) => a - b);
9328
+ await Promise.all(sortedPageIds.map(async (pageId) => {
9329
+ const items = pageGroupMap.get(pageId);
9172
9330
  const page = await this.pfs.get(pageId, tx);
9173
9331
  if (!this.factory.isDataPage(page)) {
9174
9332
  throw new Error(`Page ${pageId} is not a data page`);
@@ -9519,6 +9677,7 @@ var require_cjs = __commonJS({
9519
9677
  return Object.assign({
9520
9678
  pageSize: 8192,
9521
9679
  pageCacheCapacity: 1e4,
9680
+ pagePreallocationCount: 1e3,
9522
9681
  wal: null,
9523
9682
  walCheckpointThreshold: 1e3
9524
9683
  }, options);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "document-dataply",
3
- "version": "0.0.9-alpha.5",
3
+ "version": "0.0.9-alpha.7",
4
4
  "description": "Simple and powerful JSON document database supporting complex queries and flexible indexing policies.",
5
5
  "license": "MIT",
6
6
  "author": "izure <admin@izure.org>",
@@ -42,7 +42,7 @@
42
42
  "dataply"
43
43
  ],
44
44
  "dependencies": {
45
- "dataply": "^0.0.24-alpha.1"
45
+ "dataply": "^0.0.24-alpha.3"
46
46
  },
47
47
  "devDependencies": {
48
48
  "@types/jest": "^30.0.0",