document-dataply 0.0.4 → 0.0.5-alpha.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.
Files changed (2) hide show
  1. package/dist/cjs/index.js +104 -107
  2. package/package.json +3 -3
package/dist/cjs/index.js CHANGED
@@ -1877,6 +1877,25 @@ var require_cjs = __commonJS({
1877
1877
  this._cachedRegexp.clear();
1878
1878
  this.nodes.clear();
1879
1879
  }
1880
+ _binarySearchValues(values, target, usePrimary = false, upperBound = false) {
1881
+ let low = 0;
1882
+ let high = values.length;
1883
+ let found = false;
1884
+ while (low < high) {
1885
+ const mid = low + high >>> 1;
1886
+ const cmp = usePrimary ? this.comparator.primaryAsc(target, values[mid]) : this.comparator.asc(target, values[mid]);
1887
+ if (cmp === 0) {
1888
+ found = true;
1889
+ if (upperBound) low = mid + 1;
1890
+ else high = mid;
1891
+ } else if (cmp < 0) {
1892
+ high = mid;
1893
+ } else {
1894
+ low = mid + 1;
1895
+ }
1896
+ }
1897
+ return { index: low, found };
1898
+ }
1880
1899
  };
1881
1900
  var BPTreeSyncTransaction = class extends BPTreeTransaction {
1882
1901
  constructor(rootTx, mvccRoot, mvcc, strategy, comparator, option) {
@@ -2036,58 +2055,24 @@ var require_cjs = __commonJS({
2036
2055
  insertableNode(value) {
2037
2056
  let node = this.getNode(this.rootId);
2038
2057
  while (!node.leaf) {
2039
- for (let i = 0, len = node.values.length; i < len; i++) {
2040
- const nValue = node.values[i];
2041
- const k = node.keys;
2042
- if (this.comparator.isSame(value, nValue)) {
2043
- node = this.getNode(k[i + 1]);
2044
- break;
2045
- } else if (this.comparator.isLower(value, nValue)) {
2046
- node = this.getNode(k[i]);
2047
- break;
2048
- } else if (i + 1 === node.values.length) {
2049
- node = this.getNode(k[i + 1]);
2050
- break;
2051
- }
2052
- }
2058
+ const { index } = this._binarySearchValues(node.values, value, false, true);
2059
+ node = this.getNode(node.keys[index]);
2053
2060
  }
2054
2061
  return node;
2055
2062
  }
2056
2063
  insertableNodeByPrimary(value) {
2057
2064
  let node = this.getNode(this.rootId);
2058
2065
  while (!node.leaf) {
2059
- for (let i = 0, len = node.values.length; i < len; i++) {
2060
- const nValue = node.values[i];
2061
- const k = node.keys;
2062
- if (this.comparator.isPrimarySame(value, nValue)) {
2063
- node = this.getNode(k[i]);
2064
- break;
2065
- } else if (this.comparator.isPrimaryLower(value, nValue)) {
2066
- node = this.getNode(k[i]);
2067
- break;
2068
- } else if (i + 1 === node.values.length) {
2069
- node = this.getNode(k[i + 1]);
2070
- break;
2071
- }
2072
- }
2066
+ const { index } = this._binarySearchValues(node.values, value, true, false);
2067
+ node = this.getNode(node.keys[index]);
2073
2068
  }
2074
2069
  return node;
2075
2070
  }
2076
2071
  insertableRightestNodeByPrimary(value) {
2077
2072
  let node = this.getNode(this.rootId);
2078
2073
  while (!node.leaf) {
2079
- for (let i = 0, len = node.values.length; i < len; i++) {
2080
- const nValue = node.values[i];
2081
- const k = node.keys;
2082
- if (this.comparator.isPrimaryLower(value, nValue)) {
2083
- node = this.getNode(k[i]);
2084
- break;
2085
- }
2086
- if (i + 1 === node.values.length) {
2087
- node = this.getNode(k[i + 1]);
2088
- break;
2089
- }
2090
- }
2074
+ const { index } = this._binarySearchValues(node.values, value, true, true);
2075
+ node = this.getNode(node.keys[index]);
2091
2076
  }
2092
2077
  return node;
2093
2078
  }
@@ -2220,12 +2205,11 @@ var require_cjs = __commonJS({
2220
2205
  }
2221
2206
  exists(key, value) {
2222
2207
  const node = this.insertableNode(value);
2223
- for (let i = 0, len = node.values.length; i < len; i++) {
2224
- if (this.comparator.isSame(value, node.values[i])) {
2225
- const keys = node.keys[i];
2226
- if (keys.includes(key)) {
2227
- return true;
2228
- }
2208
+ const { index, found } = this._binarySearchValues(node.values, value);
2209
+ if (found) {
2210
+ const keys = node.keys[index];
2211
+ if (keys.includes(key)) {
2212
+ return true;
2229
2213
  }
2230
2214
  }
2231
2215
  return false;
@@ -2855,58 +2839,24 @@ var require_cjs = __commonJS({
2855
2839
  async insertableNode(value) {
2856
2840
  let node = await this.getNode(this.rootId);
2857
2841
  while (!node.leaf) {
2858
- for (let i = 0, len = node.values.length; i < len; i++) {
2859
- const nValue = node.values[i];
2860
- const k = node.keys;
2861
- if (this.comparator.isSame(value, nValue)) {
2862
- node = await this.getNode(k[i + 1]);
2863
- break;
2864
- } else if (this.comparator.isLower(value, nValue)) {
2865
- node = await this.getNode(k[i]);
2866
- break;
2867
- } else if (i + 1 === node.values.length) {
2868
- node = await this.getNode(k[i + 1]);
2869
- break;
2870
- }
2871
- }
2842
+ const { index } = this._binarySearchValues(node.values, value, false, true);
2843
+ node = await this.getNode(node.keys[index]);
2872
2844
  }
2873
2845
  return node;
2874
2846
  }
2875
2847
  async insertableNodeByPrimary(value) {
2876
2848
  let node = await this.getNode(this.rootId);
2877
2849
  while (!node.leaf) {
2878
- for (let i = 0, len = node.values.length; i < len; i++) {
2879
- const nValue = node.values[i];
2880
- const k = node.keys;
2881
- if (this.comparator.isPrimarySame(value, nValue)) {
2882
- node = await this.getNode(k[i]);
2883
- break;
2884
- } else if (this.comparator.isPrimaryLower(value, nValue)) {
2885
- node = await this.getNode(k[i]);
2886
- break;
2887
- } else if (i + 1 === node.values.length) {
2888
- node = await this.getNode(k[i + 1]);
2889
- break;
2890
- }
2891
- }
2850
+ const { index } = this._binarySearchValues(node.values, value, true, false);
2851
+ node = await this.getNode(node.keys[index]);
2892
2852
  }
2893
2853
  return node;
2894
2854
  }
2895
2855
  async insertableRightestNodeByPrimary(value) {
2896
2856
  let node = await this.getNode(this.rootId);
2897
2857
  while (!node.leaf) {
2898
- for (let i = 0, len = node.values.length; i < len; i++) {
2899
- const nValue = node.values[i];
2900
- const k = node.keys;
2901
- if (this.comparator.isPrimaryLower(value, nValue)) {
2902
- node = await this.getNode(k[i]);
2903
- break;
2904
- }
2905
- if (i + 1 === node.values.length) {
2906
- node = await this.getNode(k[i + 1]);
2907
- break;
2908
- }
2909
- }
2858
+ const { index } = this._binarySearchValues(node.values, value, true, true);
2859
+ node = await this.getNode(node.keys[index]);
2910
2860
  }
2911
2861
  return node;
2912
2862
  }
@@ -2959,11 +2909,21 @@ var require_cjs = __commonJS({
2959
2909
  let node = startNode;
2960
2910
  let done = false;
2961
2911
  let hasMatched = false;
2912
+ let nextNodePromise = null;
2962
2913
  while (!done) {
2963
2914
  if (endNode && node.id === endNode.id) {
2964
2915
  done = true;
2965
2916
  break;
2966
2917
  }
2918
+ if (direction === 1) {
2919
+ if (node.next && !done) {
2920
+ nextNodePromise = this.getNode(node.next);
2921
+ }
2922
+ } else {
2923
+ if (node.prev && !done) {
2924
+ nextNodePromise = this.getNode(node.prev);
2925
+ }
2926
+ }
2967
2927
  const len = node.values.length;
2968
2928
  if (direction === 1) {
2969
2929
  for (let i = 0; i < len; i++) {
@@ -2996,19 +2956,15 @@ var require_cjs = __commonJS({
2996
2956
  }
2997
2957
  }
2998
2958
  }
2999
- if (done) break;
3000
- if (direction === 1) {
3001
- if (!node.next) {
3002
- done = true;
3003
- break;
3004
- }
3005
- node = await this.getNode(node.next);
2959
+ if (done) {
2960
+ if (nextNodePromise) await nextNodePromise;
2961
+ break;
2962
+ }
2963
+ if (nextNodePromise) {
2964
+ node = await nextNodePromise;
2965
+ nextNodePromise = null;
3006
2966
  } else {
3007
- if (!node.prev) {
3008
- done = true;
3009
- break;
3010
- }
3011
- node = await this.getNode(node.prev);
2967
+ done = true;
3012
2968
  }
3013
2969
  }
3014
2970
  }
@@ -3039,12 +2995,11 @@ var require_cjs = __commonJS({
3039
2995
  }
3040
2996
  async exists(key, value) {
3041
2997
  const node = await this.insertableNode(value);
3042
- for (let i = 0, len = node.values.length; i < len; i++) {
3043
- if (this.comparator.isSame(value, node.values[i])) {
3044
- const keys = node.keys[i];
3045
- if (keys.includes(key)) {
3046
- return true;
3047
- }
2998
+ const { index, found } = this._binarySearchValues(node.values, value);
2999
+ if (found) {
3000
+ const keys = node.keys[index];
3001
+ if (keys.includes(key)) {
3002
+ return true;
3048
3003
  }
3049
3004
  }
3050
3005
  return false;
@@ -8715,6 +8670,7 @@ var require_cjs = __commonJS({
8715
8670
  }
8716
8671
  /**
8717
8672
  * Selects multiple rows by their PKs in a single B+ Tree traversal.
8673
+ * Results are returned in no guaranteed order, and PKs not found are excluded from the result.
8718
8674
  * @param pks Array of PKs to look up
8719
8675
  * @param tx Transaction
8720
8676
  * @returns Array of raw data of the rows in the same order as input PKs
@@ -8726,17 +8682,58 @@ var require_cjs = __commonJS({
8726
8682
  const minPk = Math.min(...pks);
8727
8683
  const maxPk = Math.max(...pks);
8728
8684
  const pkSet = new Set(pks);
8729
- const resultMap = /* @__PURE__ */ new Map();
8685
+ const pkRidPairs = [];
8730
8686
  const btx = await this.getBPTreeTransaction(tx);
8731
8687
  const stream = btx.whereStream({ gte: minPk, lte: maxPk });
8732
8688
  for await (const [rid, pk] of stream) {
8733
8689
  if (pkSet.has(pk)) {
8734
- const rowData = await this.fetchRowByRid(pk, rid, tx);
8735
- resultMap.set(pk, rowData);
8690
+ pkRidPairs.push({ pk, rid });
8736
8691
  }
8737
8692
  }
8693
+ const resultMap = await this.fetchRowsByRids(pkRidPairs, tx);
8738
8694
  return pks.map((pk) => resultMap.get(pk) ?? null);
8739
8695
  }
8696
+ /**
8697
+ * Fetches multiple rows by their RID and PK combinations, grouping by page ID to minimize I/O.
8698
+ * @param pkRidPairs Array of {pk, rid} pairs
8699
+ * @param tx Transaction
8700
+ * @returns Map of PK to row data
8701
+ */
8702
+ async fetchRowsByRids(pkRidPairs, tx) {
8703
+ const resultMap = /* @__PURE__ */ new Map();
8704
+ if (pkRidPairs.length === 0) return resultMap;
8705
+ const pageGroupMap = /* @__PURE__ */ new Map();
8706
+ for (const pair of pkRidPairs) {
8707
+ const rid = pair.rid;
8708
+ const slotIndex = rid % 65536;
8709
+ const pageId = Math.floor(rid / 65536);
8710
+ if (!pageGroupMap.has(pageId)) {
8711
+ pageGroupMap.set(pageId, []);
8712
+ }
8713
+ pageGroupMap.get(pageId).push({ pk: pair.pk, slotIndex });
8714
+ }
8715
+ const sortedPageEntries = Array.from(pageGroupMap.entries()).sort((a, b) => a[0] - b[0]);
8716
+ await Promise.all(sortedPageEntries.map(async ([pageId, items]) => {
8717
+ const page = await this.pfs.get(pageId, tx);
8718
+ if (!this.factory.isDataPage(page)) {
8719
+ throw new Error(`Page ${pageId} is not a data page`);
8720
+ }
8721
+ const manager = this.factory.getManager(page);
8722
+ for (const item of items) {
8723
+ const row = manager.getRow(page, item.slotIndex);
8724
+ if (this.rowManager.getDeletedFlag(row)) {
8725
+ resultMap.set(item.pk, null);
8726
+ } else if (this.rowManager.getOverflowFlag(row)) {
8727
+ const overflowPageId = bytesToNumber(this.rowManager.getBody(row));
8728
+ const body = await this.pfs.getBody(overflowPageId, true, tx);
8729
+ resultMap.set(item.pk, body);
8730
+ } else {
8731
+ resultMap.set(item.pk, this.rowManager.getBody(row));
8732
+ }
8733
+ }
8734
+ }));
8735
+ return resultMap;
8736
+ }
8740
8737
  async fetchRowByRid(pk, rid, tx) {
8741
8738
  this.keyManager.setBufferFromKey(rid, this.ridBuffer);
8742
8739
  const pageId = this.keyManager.getPageId(this.ridBuffer);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "document-dataply",
3
- "version": "0.0.4",
3
+ "version": "0.0.5-alpha.0",
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.20"
45
+ "dataply": "^0.0.21-alpha.0"
46
46
  },
47
47
  "devDependencies": {
48
48
  "@types/jest": "^30.0.0",
@@ -51,4 +51,4 @@
51
51
  "ts-jest": "^29.4.6",
52
52
  "typescript": "^5.9.3"
53
53
  }
54
- }
54
+ }