deepbase-sqlite 3.6.4 → 3.6.6
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/README.md +1 -1
- package/package.json +2 -2
- package/src/SqliteDriver.js +47 -1
- package/test/test.js +13 -0
package/README.md
CHANGED
|
@@ -82,7 +82,7 @@ Efficiently stores nested objects using a key-value schema:
|
|
|
82
82
|
- Values are stored as JSON
|
|
83
83
|
- Fast lookups for both exact keys and partial paths
|
|
84
84
|
|
|
85
|
-
Each row also stores a monotonic `seq` so reads that rebuild objects use `ORDER BY seq, key`. That matches JavaScript insertion order for sibling keys and keeps `shift()` / `pop()` (
|
|
85
|
+
Each row also stores a monotonic `seq` so reads that rebuild objects use `ORDER BY seq, key`. That matches JavaScript insertion order for sibling keys and keeps `shift()` / `pop()` aligned with `JsonDriver`. The driver now exposes `first()` / `last()` using SQL boundary queries in the same order semantics as `keys()`. Existing databases pick up `seq` via `ALTER TABLE` on connect (legacy rows default to `0`, then tie-break by `key`).
|
|
86
86
|
|
|
87
87
|
### ACID Compliance
|
|
88
88
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "deepbase-sqlite",
|
|
3
|
-
"version": "3.6.
|
|
3
|
+
"version": "3.6.6",
|
|
4
4
|
"description": "⚡ DeepBase SQLite - SQLite database driver",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "src/index.cjs",
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
"better-sqlite3": "^11.8.1"
|
|
18
18
|
},
|
|
19
19
|
"peerDependencies": {
|
|
20
|
-
"deepbase": "^3.6.
|
|
20
|
+
"deepbase": "^3.6.6"
|
|
21
21
|
},
|
|
22
22
|
"scripts": {
|
|
23
23
|
"test": "mocha test/test.js"
|
package/src/SqliteDriver.js
CHANGED
|
@@ -38,7 +38,7 @@ export class SqliteDriver extends DeepBaseDriver {
|
|
|
38
38
|
super(opts);
|
|
39
39
|
|
|
40
40
|
this.name = name || 'default';
|
|
41
|
-
this.path = path ||
|
|
41
|
+
this.path = path || pathModule.join(process.cwd(), 'db');
|
|
42
42
|
this.pragma = pragma || 'balanced';
|
|
43
43
|
|
|
44
44
|
this.path = pathModule.resolve(this.path);
|
|
@@ -112,6 +112,12 @@ export class SqliteDriver extends DeepBaseDriver {
|
|
|
112
112
|
this.getKeysLikeStmt = this.db.prepare(
|
|
113
113
|
"SELECT key, value FROM deepbase WHERE key LIKE ? ESCAPE '!' ORDER BY seq, key",
|
|
114
114
|
);
|
|
115
|
+
this.getFirstChildKeyStmt = this.db.prepare(
|
|
116
|
+
"SELECT key FROM deepbase WHERE key LIKE ? ESCAPE '!' ORDER BY seq, key LIMIT 1",
|
|
117
|
+
);
|
|
118
|
+
this.getLastChildKeyStmt = this.db.prepare(
|
|
119
|
+
"SELECT key FROM deepbase WHERE key LIKE ? ESCAPE '!' ORDER BY seq DESC, key DESC LIMIT 1",
|
|
120
|
+
);
|
|
115
121
|
this.delChildrenStmt = this.db.prepare("DELETE FROM deepbase WHERE key LIKE ? ESCAPE '!'");
|
|
116
122
|
this.hasChildrenStmt = this.db.prepare("SELECT 1 FROM deepbase WHERE key LIKE ? ESCAPE '!' LIMIT 1");
|
|
117
123
|
|
|
@@ -242,6 +248,46 @@ export class SqliteDriver extends DeepBaseDriver {
|
|
|
242
248
|
return this._updTxn(keys, func);
|
|
243
249
|
}
|
|
244
250
|
|
|
251
|
+
async first(...args) {
|
|
252
|
+
return this._firstOrLastKey(args, false);
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
async last(...args) {
|
|
256
|
+
return this._firstOrLastKey(args, true);
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
_firstOrLastKey(path, fromEnd) {
|
|
260
|
+
const nestedKey = this._findBoundaryNestedKey(path, fromEnd);
|
|
261
|
+
if (nestedKey !== undefined) {
|
|
262
|
+
return nestedKey;
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
const value = this._getSync(path);
|
|
266
|
+
if (value === null || typeof value !== 'object') {
|
|
267
|
+
return undefined;
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
let keyResult;
|
|
271
|
+
for (const key in value) {
|
|
272
|
+
if (Object.prototype.hasOwnProperty.call(value, key)) {
|
|
273
|
+
if (!fromEnd) return key;
|
|
274
|
+
keyResult = key;
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
return keyResult;
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
_findBoundaryNestedKey(path, fromEnd) {
|
|
281
|
+
const likePattern = path.length === 0 ? '%' : this._likePrefix(this._pathToKey(path));
|
|
282
|
+
const row = (fromEnd ? this.getLastChildKeyStmt : this.getFirstChildKeyStmt).get(likePattern);
|
|
283
|
+
if (!row) return undefined;
|
|
284
|
+
|
|
285
|
+
const fullPath = this._keyToPath(row.key);
|
|
286
|
+
if (fullPath.length <= path.length) return undefined;
|
|
287
|
+
|
|
288
|
+
return fullPath[path.length];
|
|
289
|
+
}
|
|
290
|
+
|
|
245
291
|
_getRootObject() {
|
|
246
292
|
const rows = this.getAllStmt.all();
|
|
247
293
|
const result = {};
|
package/test/test.js
CHANGED
|
@@ -278,6 +278,19 @@ for (const pragma of PRAGMA_MODES) {
|
|
|
278
278
|
assert.deepStrictEqual(await db.values('simple'), []);
|
|
279
279
|
assert.deepStrictEqual(await db.entries('simple'), []);
|
|
280
280
|
});
|
|
281
|
+
|
|
282
|
+
it('first/last should match keys() boundaries', async function () {
|
|
283
|
+
const keys = await db.keys('users');
|
|
284
|
+
const driver = db.getDriver(0);
|
|
285
|
+
assert.strictEqual(await driver.first('users'), keys[0]);
|
|
286
|
+
assert.strictEqual(await driver.last('users'), keys[keys.length - 1]);
|
|
287
|
+
});
|
|
288
|
+
|
|
289
|
+
it('first/last should return undefined for missing path', async function () {
|
|
290
|
+
const driver = db.getDriver(0);
|
|
291
|
+
assert.strictEqual(await driver.first('missing'), undefined);
|
|
292
|
+
assert.strictEqual(await driver.last('missing'), undefined);
|
|
293
|
+
});
|
|
281
294
|
});
|
|
282
295
|
|
|
283
296
|
describe('Persistence', function () {
|