jsql-neo 2.1.4 → 2.2.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/lib/table.js +46 -1
  2. package/package.json +1 -1
package/lib/table.js CHANGED
@@ -29,6 +29,7 @@ class Table {
29
29
  this._btreesDirty = false;
30
30
 
31
31
  this._primaryKey = null;
32
+ this._pkIndex = null;
32
33
  this._autoIncrementField = null;
33
34
  this._foreignKeys = [];
34
35
  this._checkConstraints = [];
@@ -69,6 +70,7 @@ class Table {
69
70
  this._softDelete = true;
70
71
  }
71
72
 
73
+ this._pkIndex = this._primaryKey ? new Map() : null;
72
74
  this._cachedSchemaFields = Object.keys(schema).filter(f => f !== '_softDelete');
73
75
  this._cachedDateFields = Object.keys(this._dateFields);
74
76
  this._cachedUniqueFields = this._cachedSchemaFields.filter(f => schema[f].unique);
@@ -179,7 +181,12 @@ class Table {
179
181
  } else if (autoIncField && data[autoIncField] > this._autoIncrement) {
180
182
  this._autoIncrement = data[autoIncField];
181
183
  }
184
+ const rowIdx = this._rows.length;
182
185
  this._rows.push(Object.assign({}, data));
186
+ if (this._pkIndex && this._primaryKey) {
187
+ const pkVal = data[this._primaryKey];
188
+ if (pkVal !== undefined && pkVal !== null) this._pkIndex.set(pkVal, rowIdx);
189
+ }
183
190
  items[i] = data;
184
191
  }
185
192
  this._btreesDirty = true;
@@ -222,6 +229,15 @@ class Table {
222
229
 
223
230
  findById(id) {
224
231
  if (!this._primaryKey) throw createError('ER_PARSE_ERROR', 'Table has no primary key');
232
+ // Hash 索引 O(1)
233
+ if (this._pkIndex) {
234
+ const rowIndex = this._pkIndex.get(id);
235
+ if (rowIndex !== undefined) {
236
+ const row = this._rows[rowIndex];
237
+ if (row && !row._deleted) return { ...row };
238
+ }
239
+ return null;
240
+ }
225
241
  this._ensureBTrees();
226
242
  if (this._btrees[this._primaryKey]) {
227
243
  const indices = this._btrees[this._primaryKey].search(id);
@@ -345,6 +361,17 @@ class Table {
345
361
  return this.remove(query);
346
362
  }
347
363
 
364
+ _findRowIndex(id) {
365
+ if (this._pkIndex && this._primaryKey) {
366
+ const idx = this._pkIndex.get(id);
367
+ if (idx !== undefined) return idx;
368
+ }
369
+ for (let i = 0; i < this._rows.length; i++) {
370
+ if (this._rows[i][this._primaryKey] === id) return i;
371
+ }
372
+ return -1;
373
+ }
374
+
348
375
  restore(query = {}) {
349
376
  if (!this._softDelete) throw createError('ER_NOT_SUPPORTED', 'Soft delete is not enabled');
350
377
  const matched = this._applyFilter(this._rows, { ...query, _deleted: true });
@@ -365,6 +392,7 @@ class Table {
365
392
  _truncate() {
366
393
  const count = this._rows.length;
367
394
  this._rows = [];
395
+ if (this._pkIndex) this._pkIndex.clear();
368
396
  for (const key of Object.keys(this._btrees)) {
369
397
  this._btrees[key].clear();
370
398
  }
@@ -902,6 +930,10 @@ class Table {
902
930
 
903
931
  _addToIndexes(rowIndex, data) {
904
932
  this._ensureBTrees();
933
+ if (this._pkIndex && this._primaryKey) {
934
+ const pkVal = data[this._primaryKey];
935
+ if (pkVal !== undefined && pkVal !== null) this._pkIndex.set(pkVal, rowIndex);
936
+ }
905
937
  for (const field of Object.keys(this._indexes)) {
906
938
  const value = data[field];
907
939
  if (value !== undefined) {
@@ -921,6 +953,9 @@ class Table {
921
953
 
922
954
  _removeFromIndexes(rowIndex, data) {
923
955
  this._ensureBTrees();
956
+ if (this._pkIndex && this._primaryKey) {
957
+ this._pkIndex.delete(data[this._primaryKey]);
958
+ }
924
959
  for (const field of Object.keys(this._indexes)) {
925
960
  const value = data[field];
926
961
  if (value !== undefined && this._indexes[field].has(value)) {
@@ -940,8 +975,17 @@ class Table {
940
975
  }
941
976
  }
942
977
 
978
+ _rebuildPKIndex() {
979
+ if (!this._pkIndex || !this._primaryKey) return;
980
+ this._pkIndex.clear();
981
+ for (let i = 0; i < this._rows.length; i++) {
982
+ const pkVal = this._rows[i][this._primaryKey];
983
+ if (pkVal !== undefined && pkVal !== null) this._pkIndex.set(pkVal, i);
984
+ }
985
+ }
986
+
943
987
  _adjustBTreeAfterRemove(removedIndex) {
944
- // 重建受影响的 B-Tree
988
+ this._rebuildPKIndex();
945
989
  for (const field of Object.keys(this._btrees)) {
946
990
  this._rebuildBTree(field);
947
991
  }
@@ -957,6 +1001,7 @@ class Table {
957
1001
  }
958
1002
  }
959
1003
  }
1004
+ this._rebuildPKIndex();
960
1005
  this._rebuildAllBTrees();
961
1006
  for (const field of Object.keys(this._indexes)) {
962
1007
  this.createIndex(field);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "jsql-neo",
3
- "version": "2.1.4",
3
+ "version": "2.2.0",
4
4
  "description": "JSQL-NEO — Pure JavaScript embedded database with B-Tree indexes, WAL, hash JOIN, Redis-compatible Cache, and MySQL-style error codes",
5
5
  "main": "index.js",
6
6
  "files": [