@naturalcycles/db-lib 9.20.0 → 9.22.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.
- package/dist/adapter/cachedb/cache.db.d.ts +2 -2
- package/dist/adapter/cachedb/cache.db.js +4 -3
- package/dist/adapter/file/file.db.js +2 -1
- package/dist/adapter/inmemory/inMemory.db.d.ts +7 -6
- package/dist/adapter/inmemory/inMemory.db.js +15 -13
- package/dist/adapter/inmemory/inMemoryKeyValueDB.d.ts +5 -0
- package/dist/adapter/inmemory/inMemoryKeyValueDB.js +17 -0
- package/dist/base.common.db.d.ts +4 -3
- package/dist/base.common.db.js +5 -2
- package/dist/common.db.d.ts +23 -29
- package/dist/common.db.js +2 -2
- package/dist/commondao/common.dao.d.ts +16 -5
- package/dist/commondao/common.dao.js +37 -8
- package/dist/db.model.d.ts +0 -13
- package/dist/db.model.js +1 -17
- package/dist/kv/commonKeyValueDB.d.ts +36 -10
- package/dist/kv/commonKeyValueDB.js +5 -0
- package/dist/kv/commonKeyValueDao.d.ts +8 -5
- package/dist/kv/commonKeyValueDao.js +9 -0
- package/dist/query/dbQuery.d.ts +2 -2
- package/dist/query/dbQuery.js +2 -2
- package/dist/testing/daoTest.js +26 -0
- package/dist/testing/dbTest.js +21 -23
- package/dist/testing/keyValueDBTest.js +32 -15
- package/dist/testing/keyValueDaoTest.js +15 -12
- package/package.json +1 -1
- package/src/adapter/cachedb/cache.db.ts +6 -5
- package/src/adapter/file/file.db.ts +2 -1
- package/src/adapter/inmemory/inMemory.db.ts +29 -18
- package/src/adapter/inmemory/inMemoryKeyValueDB.ts +26 -2
- package/src/base.common.db.ts +18 -5
- package/src/common.db.ts +36 -34
- package/src/commondao/common.dao.ts +46 -11
- package/src/db.model.ts +0 -19
- package/src/kv/commonKeyValueDB.ts +45 -12
- package/src/kv/commonKeyValueDao.ts +22 -8
- package/src/query/dbQuery.ts +2 -3
- package/src/testing/daoTest.ts +28 -0
- package/src/testing/dbTest.ts +22 -28
- package/src/testing/keyValueDBTest.ts +37 -17
- package/src/testing/keyValueDaoTest.ts +16 -12
package/dist/testing/daoTest.js
CHANGED
|
@@ -99,6 +99,32 @@ function runCommonDaoTest(db, quirks = {}) {
|
|
|
99
99
|
expect(items[0]).toMatchObject(clone);
|
|
100
100
|
(0, dbTest_1.expectMatch)(expectedItems, itemsSaved, quirks);
|
|
101
101
|
});
|
|
102
|
+
if (support.increment) {
|
|
103
|
+
test('increment', async () => {
|
|
104
|
+
await dao.incrementBatch('k3', { id1: 1, id2: 2 });
|
|
105
|
+
let rows = await dao.query().runQuery();
|
|
106
|
+
rows = (0, js_lib_1._sortBy)(rows, r => r.id);
|
|
107
|
+
const expected = expectedItems.map(r => {
|
|
108
|
+
if (r.id === 'id1') {
|
|
109
|
+
return {
|
|
110
|
+
...r,
|
|
111
|
+
k3: r.k3 + 1,
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
if (r.id === 'id2') {
|
|
115
|
+
return {
|
|
116
|
+
...r,
|
|
117
|
+
k3: r.k3 + 2,
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
return r;
|
|
121
|
+
});
|
|
122
|
+
(0, dbTest_1.expectMatch)(expected, rows, quirks);
|
|
123
|
+
// reset the changes
|
|
124
|
+
await dao.increment('k3', 'id1', -1);
|
|
125
|
+
await dao.increment('k3', 'id2', -2);
|
|
126
|
+
});
|
|
127
|
+
}
|
|
102
128
|
// GET not empty
|
|
103
129
|
test('getByIds all items', async () => {
|
|
104
130
|
const rows = await dao.getByIds(items.map(i => i.id).concat('abcd'));
|
package/dist/testing/dbTest.js
CHANGED
|
@@ -4,7 +4,6 @@ exports.runCommonDBTest = runCommonDBTest;
|
|
|
4
4
|
exports.expectMatch = expectMatch;
|
|
5
5
|
const js_lib_1 = require("@naturalcycles/js-lib");
|
|
6
6
|
const common_db_1 = require("../common.db");
|
|
7
|
-
const db_model_1 = require("../db.model");
|
|
8
7
|
const dbQuery_1 = require("../query/dbQuery");
|
|
9
8
|
const test_model_1 = require("./test.model");
|
|
10
9
|
function runCommonDBTest(db, quirks = {}) {
|
|
@@ -236,8 +235,8 @@ function runCommonDBTest(db, quirks = {}) {
|
|
|
236
235
|
expectMatch(expected, rows, quirks);
|
|
237
236
|
});
|
|
238
237
|
}
|
|
239
|
-
if (support.
|
|
240
|
-
test('
|
|
238
|
+
if (support.patchByQuery) {
|
|
239
|
+
test('patchByQuery', async () => {
|
|
241
240
|
// cleanup, reset initial data
|
|
242
241
|
await db.deleteByQuery(queryAll());
|
|
243
242
|
await db.saveBatch(test_model_1.TEST_TABLE, items);
|
|
@@ -245,7 +244,7 @@ function runCommonDBTest(db, quirks = {}) {
|
|
|
245
244
|
k3: 5,
|
|
246
245
|
k2: 'abc',
|
|
247
246
|
};
|
|
248
|
-
await db.
|
|
247
|
+
await db.patchByQuery(dbQuery_1.DBQuery.create(test_model_1.TEST_TABLE).filterEq('even', true), patch);
|
|
249
248
|
const { rows } = await db.runQuery(queryAll());
|
|
250
249
|
const expected = items.map(r => {
|
|
251
250
|
if (r.even) {
|
|
@@ -255,26 +254,25 @@ function runCommonDBTest(db, quirks = {}) {
|
|
|
255
254
|
});
|
|
256
255
|
expectMatch(expected, rows, quirks);
|
|
257
256
|
});
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
});
|
|
275
|
-
expectMatch(expected, rows, quirks);
|
|
257
|
+
}
|
|
258
|
+
if (support.increment) {
|
|
259
|
+
test('incrementBatch', async () => {
|
|
260
|
+
// cleanup, reset initial data
|
|
261
|
+
await db.deleteByQuery(queryAll());
|
|
262
|
+
await db.saveBatch(test_model_1.TEST_TABLE, items);
|
|
263
|
+
await db.incrementBatch(test_model_1.TEST_TABLE, 'k3', { id1: 1, id2: 2 });
|
|
264
|
+
const { rows } = await db.runQuery(queryAll());
|
|
265
|
+
const expected = items.map(r => {
|
|
266
|
+
if (r.id === 'id1') {
|
|
267
|
+
return { ...r, k3: 2 };
|
|
268
|
+
}
|
|
269
|
+
if (r.id === 'id2') {
|
|
270
|
+
return { ...r, k3: 4 };
|
|
271
|
+
}
|
|
272
|
+
return r;
|
|
276
273
|
});
|
|
277
|
-
|
|
274
|
+
expectMatch(expected, rows, quirks);
|
|
275
|
+
});
|
|
278
276
|
}
|
|
279
277
|
if (support.queries) {
|
|
280
278
|
test('cleanup', async () => {
|
|
@@ -18,6 +18,7 @@ function runCommonKeyValueDBTest(db) {
|
|
|
18
18
|
const ids = await db.streamIds(test_model_1.TEST_TABLE).toArray();
|
|
19
19
|
await db.deleteByIds(test_model_1.TEST_TABLE, ids);
|
|
20
20
|
});
|
|
21
|
+
const { support } = db;
|
|
21
22
|
test('ping', async () => {
|
|
22
23
|
await db.ping();
|
|
23
24
|
});
|
|
@@ -40,9 +41,11 @@ function runCommonKeyValueDBTest(db) {
|
|
|
40
41
|
(0, js_lib_1._sortBy)(entries, e => e[0], true);
|
|
41
42
|
expect(entries).toEqual(testEntries);
|
|
42
43
|
});
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
44
|
+
if (support.count) {
|
|
45
|
+
test('count should be 3', async () => {
|
|
46
|
+
expect(await db.count(test_model_1.TEST_TABLE)).toBe(3);
|
|
47
|
+
});
|
|
48
|
+
}
|
|
46
49
|
test('streamIds', async () => {
|
|
47
50
|
const ids = await db.streamIds(test_model_1.TEST_TABLE).toArray();
|
|
48
51
|
ids.sort();
|
|
@@ -82,16 +85,30 @@ function runCommonKeyValueDBTest(db) {
|
|
|
82
85
|
const results = await db.getByIds(test_model_1.TEST_TABLE, testIds);
|
|
83
86
|
expect(results).toEqual([]);
|
|
84
87
|
});
|
|
85
|
-
|
|
86
|
-
const
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
88
|
+
if (support.increment) {
|
|
89
|
+
const id = 'nonExistingField';
|
|
90
|
+
const id2 = 'nonExistingField2';
|
|
91
|
+
test('increment on a non-existing field should set the value to 1', async () => {
|
|
92
|
+
const result = await db.increment(test_model_1.TEST_TABLE, id);
|
|
93
|
+
expect(result).toBe(1);
|
|
94
|
+
});
|
|
95
|
+
test('increment on a existing field should increase the value by one', async () => {
|
|
96
|
+
const result = await db.increment(test_model_1.TEST_TABLE, id);
|
|
97
|
+
expect(result).toBe(2);
|
|
98
|
+
});
|
|
99
|
+
test('increment should increase the value by the specified amount', async () => {
|
|
100
|
+
const result = await db.increment(test_model_1.TEST_TABLE, id, 2);
|
|
101
|
+
expect(result).toBe(4);
|
|
102
|
+
});
|
|
103
|
+
test('increment 2 ids at the same time', async () => {
|
|
104
|
+
const result = await db.incrementBatch(test_model_1.TEST_TABLE, {
|
|
105
|
+
[id]: 1,
|
|
106
|
+
[id2]: 2,
|
|
107
|
+
});
|
|
108
|
+
expect(result).toEqual({
|
|
109
|
+
[id]: 5,
|
|
110
|
+
[id2]: 2,
|
|
111
|
+
});
|
|
112
|
+
});
|
|
113
|
+
}
|
|
97
114
|
}
|
|
@@ -17,6 +17,7 @@ function runCommonKeyValueDaoTest(dao) {
|
|
|
17
17
|
const ids = await dao.streamIds().toArray();
|
|
18
18
|
await dao.deleteByIds(ids);
|
|
19
19
|
});
|
|
20
|
+
const { support } = dao.cfg.db;
|
|
20
21
|
test('ping', async () => {
|
|
21
22
|
await dao.ping();
|
|
22
23
|
});
|
|
@@ -75,16 +76,18 @@ function runCommonKeyValueDaoTest(dao) {
|
|
|
75
76
|
const results = await dao.getByIds(testIds);
|
|
76
77
|
expect(results).toEqual([]);
|
|
77
78
|
});
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
79
|
+
if (support.increment) {
|
|
80
|
+
test('increment on a non-existing field should set the value to 1', async () => {
|
|
81
|
+
const result = await dao.increment('nonExistingField');
|
|
82
|
+
expect(result).toBe(1);
|
|
83
|
+
});
|
|
84
|
+
test('increment on a existing field should increase the value by one', async () => {
|
|
85
|
+
const result = await dao.increment('nonExistingField');
|
|
86
|
+
expect(result).toBe(2);
|
|
87
|
+
});
|
|
88
|
+
test('increment should increase the value by the specified amount', async () => {
|
|
89
|
+
const result = await dao.increment('nonExistingField', 2);
|
|
90
|
+
expect(result).toBe(4);
|
|
91
|
+
});
|
|
92
|
+
}
|
|
90
93
|
}
|
package/package.json
CHANGED
|
@@ -9,7 +9,7 @@ import {
|
|
|
9
9
|
import { ReadableTyped } from '@naturalcycles/nodejs-lib'
|
|
10
10
|
import { BaseCommonDB } from '../../base.common.db'
|
|
11
11
|
import { CommonDB, commonDBFullSupport, CommonDBSupport } from '../../common.db'
|
|
12
|
-
import {
|
|
12
|
+
import { RunQueryResult } from '../../db.model'
|
|
13
13
|
import { DBQuery } from '../../query/dbQuery'
|
|
14
14
|
import {
|
|
15
15
|
CacheDBCfg,
|
|
@@ -29,6 +29,7 @@ export class CacheDB extends BaseCommonDB implements CommonDB {
|
|
|
29
29
|
override support: CommonDBSupport = {
|
|
30
30
|
...commonDBFullSupport,
|
|
31
31
|
transactions: false,
|
|
32
|
+
increment: false,
|
|
32
33
|
}
|
|
33
34
|
|
|
34
35
|
constructor(cfg: CacheDBCfg) {
|
|
@@ -271,19 +272,19 @@ export class CacheDB extends BaseCommonDB implements CommonDB {
|
|
|
271
272
|
return deletedIds
|
|
272
273
|
}
|
|
273
274
|
|
|
274
|
-
override async
|
|
275
|
+
override async patchByQuery<ROW extends ObjectWithId>(
|
|
275
276
|
q: DBQuery<ROW>,
|
|
276
|
-
patch:
|
|
277
|
+
patch: Partial<ROW>,
|
|
277
278
|
opt: CacheDBOptions = {},
|
|
278
279
|
): Promise<number> {
|
|
279
280
|
let updated: number | undefined
|
|
280
281
|
|
|
281
282
|
if (!opt.onlyCache && !this.cfg.onlyCache) {
|
|
282
|
-
updated = await this.cfg.downstreamDB.
|
|
283
|
+
updated = await this.cfg.downstreamDB.patchByQuery(q, patch, opt)
|
|
283
284
|
}
|
|
284
285
|
|
|
285
286
|
if (!opt.skipCache && !this.cfg.skipCache) {
|
|
286
|
-
const cacheResult = this.cfg.cacheDB.
|
|
287
|
+
const cacheResult = this.cfg.cacheDB.patchByQuery(q, patch, opt)
|
|
287
288
|
if (this.cfg.awaitCache) updated ??= await cacheResult
|
|
288
289
|
}
|
|
289
290
|
|
|
@@ -45,9 +45,10 @@ export class FileDB extends BaseCommonDB implements CommonDB {
|
|
|
45
45
|
bufferValues: false, // todo: implement
|
|
46
46
|
insertSaveMethod: false,
|
|
47
47
|
updateSaveMethod: false,
|
|
48
|
-
|
|
48
|
+
patchByQuery: false,
|
|
49
49
|
createTable: false,
|
|
50
50
|
transactions: false, // todo
|
|
51
|
+
increment: false,
|
|
51
52
|
}
|
|
52
53
|
|
|
53
54
|
constructor(cfg: FileDBCfg) {
|
|
@@ -3,9 +3,12 @@ import {
|
|
|
3
3
|
_assert,
|
|
4
4
|
_by,
|
|
5
5
|
_deepCopy,
|
|
6
|
+
_isEmptyObject,
|
|
6
7
|
_since,
|
|
7
8
|
_sortObjectDeep,
|
|
9
|
+
_stringMapEntries,
|
|
8
10
|
_stringMapValues,
|
|
11
|
+
AnyObjectWithId,
|
|
9
12
|
CommonLogger,
|
|
10
13
|
generateJsonSchemaFromData,
|
|
11
14
|
JsonSchemaObject,
|
|
@@ -27,9 +30,7 @@ import {
|
|
|
27
30
|
commonDBFullSupport,
|
|
28
31
|
CommonDBTransactionOptions,
|
|
29
32
|
CommonDBType,
|
|
30
|
-
DBIncrement,
|
|
31
33
|
DBOperation,
|
|
32
|
-
DBPatch,
|
|
33
34
|
DBTransactionFn,
|
|
34
35
|
queryInMemory,
|
|
35
36
|
} from '../..'
|
|
@@ -113,7 +114,7 @@ export class InMemoryDB implements CommonDB {
|
|
|
113
114
|
cfg: InMemoryDBCfg
|
|
114
115
|
|
|
115
116
|
// data[table][id] > {id: 'a', created: ... }
|
|
116
|
-
data: StringMap<StringMap<
|
|
117
|
+
data: StringMap<StringMap<AnyObjectWithId>> = {}
|
|
117
118
|
|
|
118
119
|
/**
|
|
119
120
|
* Returns internal "Data snapshot".
|
|
@@ -233,25 +234,14 @@ export class InMemoryDB implements CommonDB {
|
|
|
233
234
|
return count
|
|
234
235
|
}
|
|
235
236
|
|
|
236
|
-
async
|
|
237
|
+
async patchByQuery<ROW extends ObjectWithId>(
|
|
237
238
|
q: DBQuery<ROW>,
|
|
238
|
-
patch:
|
|
239
|
+
patch: Partial<ROW>,
|
|
239
240
|
): Promise<number> {
|
|
240
|
-
|
|
241
|
-
if (!patchEntries.length) return 0
|
|
242
|
-
|
|
241
|
+
if (_isEmptyObject(patch)) return 0
|
|
243
242
|
const table = this.cfg.tablesPrefix + q.table
|
|
244
243
|
const rows = queryInMemory(q, Object.values(this.data[table] || {}) as ROW[])
|
|
245
|
-
rows.forEach((row
|
|
246
|
-
patchEntries.forEach(([k, v]) => {
|
|
247
|
-
if (v instanceof DBIncrement) {
|
|
248
|
-
row[k] = (row[k] || 0) + v.amount
|
|
249
|
-
} else {
|
|
250
|
-
row[k] = v
|
|
251
|
-
}
|
|
252
|
-
})
|
|
253
|
-
})
|
|
254
|
-
|
|
244
|
+
rows.forEach(row => Object.assign(row, patch))
|
|
255
245
|
return rows.length
|
|
256
246
|
}
|
|
257
247
|
|
|
@@ -294,6 +284,27 @@ export class InMemoryDB implements CommonDB {
|
|
|
294
284
|
}
|
|
295
285
|
}
|
|
296
286
|
|
|
287
|
+
async incrementBatch(
|
|
288
|
+
table: string,
|
|
289
|
+
prop: string,
|
|
290
|
+
incrementMap: StringMap<number>,
|
|
291
|
+
_opt?: CommonDBOptions,
|
|
292
|
+
): Promise<StringMap<number>> {
|
|
293
|
+
const tbl = this.cfg.tablesPrefix + table
|
|
294
|
+
this.data[tbl] ||= {}
|
|
295
|
+
|
|
296
|
+
const result: StringMap<number> = {}
|
|
297
|
+
|
|
298
|
+
for (const [id, by] of _stringMapEntries(incrementMap)) {
|
|
299
|
+
this.data[tbl][id] ||= { id }
|
|
300
|
+
const newValue = ((this.data[tbl][id][prop] as number) || 0) + by
|
|
301
|
+
this.data[tbl][id][prop] = newValue
|
|
302
|
+
result[id] = newValue
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
return result
|
|
306
|
+
}
|
|
307
|
+
|
|
297
308
|
/**
|
|
298
309
|
* Flushes all tables (all namespaces) at once.
|
|
299
310
|
*/
|
|
@@ -1,14 +1,22 @@
|
|
|
1
1
|
import { Readable } from 'node:stream'
|
|
2
|
-
import { StringMap } from '@naturalcycles/js-lib'
|
|
2
|
+
import { _stringMapEntries, StringMap } from '@naturalcycles/js-lib'
|
|
3
3
|
import { ReadableTyped } from '@naturalcycles/nodejs-lib'
|
|
4
4
|
import { CommonDBCreateOptions } from '../../db.model'
|
|
5
|
-
import {
|
|
5
|
+
import {
|
|
6
|
+
CommonKeyValueDB,
|
|
7
|
+
commonKeyValueDBFullSupport,
|
|
8
|
+
KeyValueDBTuple,
|
|
9
|
+
} from '../../kv/commonKeyValueDB'
|
|
6
10
|
|
|
7
11
|
export interface InMemoryKeyValueDBCfg {}
|
|
8
12
|
|
|
9
13
|
export class InMemoryKeyValueDB implements CommonKeyValueDB {
|
|
10
14
|
constructor(public cfg: InMemoryKeyValueDBCfg = {}) {}
|
|
11
15
|
|
|
16
|
+
support = {
|
|
17
|
+
...commonKeyValueDBFullSupport,
|
|
18
|
+
}
|
|
19
|
+
|
|
12
20
|
// data[table][id] > Buffer
|
|
13
21
|
data: StringMap<StringMap<Buffer>> = {}
|
|
14
22
|
|
|
@@ -21,6 +29,7 @@ export class InMemoryKeyValueDB implements CommonKeyValueDB {
|
|
|
21
29
|
ids.forEach(id => delete this.data[table]![id])
|
|
22
30
|
}
|
|
23
31
|
|
|
32
|
+
// todo: but should we work with Tuples or Objects?
|
|
24
33
|
async getByIds(table: string, ids: string[]): Promise<KeyValueDBTuple[]> {
|
|
25
34
|
this.data[table] ||= {}
|
|
26
35
|
return ids.map(id => [id, this.data[table]![id]!] as KeyValueDBTuple).filter(e => e[1])
|
|
@@ -57,4 +66,19 @@ export class InMemoryKeyValueDB implements CommonKeyValueDB {
|
|
|
57
66
|
|
|
58
67
|
return newValue
|
|
59
68
|
}
|
|
69
|
+
|
|
70
|
+
async incrementBatch(table: string, incrementMap: StringMap<number>): Promise<StringMap<number>> {
|
|
71
|
+
this.data[table] ||= {}
|
|
72
|
+
|
|
73
|
+
const result: StringMap<number> = {}
|
|
74
|
+
|
|
75
|
+
for (const [id, by] of _stringMapEntries(incrementMap)) {
|
|
76
|
+
const newValue = parseInt(this.data[table][id]?.toString() || '0') + by
|
|
77
|
+
// todo: but should this.data store Buffer or number for incremented values?
|
|
78
|
+
this.data[table][id] = Buffer.from(String(newValue))
|
|
79
|
+
result[id] = newValue
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
return result
|
|
83
|
+
}
|
|
60
84
|
}
|
package/src/base.common.db.ts
CHANGED
|
@@ -1,11 +1,15 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
JsonSchemaObject,
|
|
3
|
+
JsonSchemaRootObject,
|
|
4
|
+
ObjectWithId,
|
|
5
|
+
StringMap,
|
|
6
|
+
} from '@naturalcycles/js-lib'
|
|
2
7
|
import { ReadableTyped } from '@naturalcycles/nodejs-lib'
|
|
3
8
|
import { CommonDB, CommonDBSupport, CommonDBType } from './common.db'
|
|
4
9
|
import {
|
|
5
10
|
CommonDBOptions,
|
|
6
11
|
CommonDBSaveOptions,
|
|
7
12
|
CommonDBTransactionOptions,
|
|
8
|
-
DBPatch,
|
|
9
13
|
DBTransactionFn,
|
|
10
14
|
RunQueryResult,
|
|
11
15
|
} from './db.model'
|
|
@@ -50,12 +54,12 @@ export class BaseCommonDB implements CommonDB {
|
|
|
50
54
|
throw new Error('deleteByQuery is not implemented')
|
|
51
55
|
}
|
|
52
56
|
|
|
53
|
-
async
|
|
57
|
+
async patchByQuery<ROW extends ObjectWithId>(
|
|
54
58
|
_q: DBQuery<ROW>,
|
|
55
|
-
_patch:
|
|
59
|
+
_patch: Partial<ROW>,
|
|
56
60
|
_opt?: CommonDBOptions,
|
|
57
61
|
): Promise<number> {
|
|
58
|
-
throw new Error('
|
|
62
|
+
throw new Error('patchByQuery is not implemented')
|
|
59
63
|
}
|
|
60
64
|
|
|
61
65
|
async runQuery<ROW extends ObjectWithId>(_q: DBQuery<ROW>): Promise<RunQueryResult<ROW>> {
|
|
@@ -87,4 +91,13 @@ export class BaseCommonDB implements CommonDB {
|
|
|
87
91
|
await fn(tx)
|
|
88
92
|
// there's no try/catch and rollback, as there's nothing to rollback
|
|
89
93
|
}
|
|
94
|
+
|
|
95
|
+
async incrementBatch(
|
|
96
|
+
_table: string,
|
|
97
|
+
_prop: string,
|
|
98
|
+
_incrementMap: StringMap<number>,
|
|
99
|
+
_opt?: CommonDBOptions,
|
|
100
|
+
): Promise<StringMap<number>> {
|
|
101
|
+
throw new Error('incrementBatch is not implemented')
|
|
102
|
+
}
|
|
90
103
|
}
|
package/src/common.db.ts
CHANGED
|
@@ -1,4 +1,9 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
JsonSchemaObject,
|
|
3
|
+
JsonSchemaRootObject,
|
|
4
|
+
ObjectWithId,
|
|
5
|
+
StringMap,
|
|
6
|
+
} from '@naturalcycles/js-lib'
|
|
2
7
|
import type { ReadableTyped } from '@naturalcycles/nodejs-lib'
|
|
3
8
|
import {
|
|
4
9
|
CommonDBCreateOptions,
|
|
@@ -6,7 +11,6 @@ import {
|
|
|
6
11
|
CommonDBSaveOptions,
|
|
7
12
|
CommonDBStreamOptions,
|
|
8
13
|
CommonDBTransactionOptions,
|
|
9
|
-
DBPatch,
|
|
10
14
|
DBTransactionFn,
|
|
11
15
|
RunQueryResult,
|
|
12
16
|
} from './db.model'
|
|
@@ -28,23 +32,6 @@ export interface CommonDB {
|
|
|
28
32
|
*/
|
|
29
33
|
support: CommonDBSupport
|
|
30
34
|
|
|
31
|
-
// Support flags indicate which of the CommonDB features are supported by this implementation.
|
|
32
|
-
supportsQueries?: boolean
|
|
33
|
-
supportsDBQueryFilter?: boolean
|
|
34
|
-
supportsDBQueryFilterIn?: boolean
|
|
35
|
-
supportsDBQueryOrder?: boolean
|
|
36
|
-
supportsDBQuerySelectFields?: boolean
|
|
37
|
-
supportsInsertSaveMethod?: boolean
|
|
38
|
-
supportsUpdateSaveMethod?: boolean
|
|
39
|
-
supportsUpdateByQuery?: boolean
|
|
40
|
-
supportsDBIncrement?: boolean
|
|
41
|
-
supportsCreateTable?: boolean
|
|
42
|
-
supportsTableSchemas?: boolean
|
|
43
|
-
supportsStreaming?: boolean
|
|
44
|
-
supportsBufferValues?: boolean
|
|
45
|
-
supportsNullValues?: boolean
|
|
46
|
-
supportsTransactions?: boolean
|
|
47
|
-
|
|
48
35
|
/**
|
|
49
36
|
* Checks that connection/credentials/etc is ok.
|
|
50
37
|
* Also acts as a "warmup request" for a DB.
|
|
@@ -133,7 +120,7 @@ export interface CommonDB {
|
|
|
133
120
|
) => Promise<number>
|
|
134
121
|
|
|
135
122
|
/**
|
|
136
|
-
* Applies patch to the rows
|
|
123
|
+
* Applies patch to all the rows that are matched by the query.
|
|
137
124
|
*
|
|
138
125
|
* Example:
|
|
139
126
|
*
|
|
@@ -141,18 +128,11 @@ export interface CommonDB {
|
|
|
141
128
|
*
|
|
142
129
|
* patch would be { A: 'B' } for that query.
|
|
143
130
|
*
|
|
144
|
-
*
|
|
145
|
-
*
|
|
146
|
-
* UPDATE table SET A = A + 1
|
|
147
|
-
*
|
|
148
|
-
* In that case patch would look like:
|
|
149
|
-
* { A: DBIncrement(1) }
|
|
150
|
-
*
|
|
151
|
-
* Returns number of rows affected.
|
|
131
|
+
* Returns the number of rows affected.
|
|
152
132
|
*/
|
|
153
|
-
|
|
133
|
+
patchByQuery: <ROW extends ObjectWithId>(
|
|
154
134
|
q: DBQuery<ROW>,
|
|
155
|
-
patch:
|
|
135
|
+
patch: Partial<ROW>,
|
|
156
136
|
opt?: CommonDBOptions,
|
|
157
137
|
) => Promise<number>
|
|
158
138
|
|
|
@@ -169,6 +149,28 @@ export interface CommonDB {
|
|
|
169
149
|
* unless specified as readOnly in CommonDBTransactionOptions.
|
|
170
150
|
*/
|
|
171
151
|
runInTransaction: (fn: DBTransactionFn, opt?: CommonDBTransactionOptions) => Promise<void>
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* Increments a value of a property by a given amount.
|
|
155
|
+
* This is a batch operation, so it allows to increment multiple rows at once.
|
|
156
|
+
*
|
|
157
|
+
* - table - the table to apply operations on
|
|
158
|
+
* - prop - name of the property to increment (in each of the rows passed)
|
|
159
|
+
* - incrementMap - map from id to increment value
|
|
160
|
+
*
|
|
161
|
+
* Example of incrementMap:
|
|
162
|
+
* { rowId1: 2, rowId2: 3 }
|
|
163
|
+
*
|
|
164
|
+
* Returns the incrementMap with the same keys and updated values.
|
|
165
|
+
*
|
|
166
|
+
* @experimental
|
|
167
|
+
*/
|
|
168
|
+
incrementBatch: (
|
|
169
|
+
table: string,
|
|
170
|
+
prop: string,
|
|
171
|
+
incrementMap: StringMap<number>,
|
|
172
|
+
opt?: CommonDBOptions,
|
|
173
|
+
) => Promise<StringMap<number>>
|
|
172
174
|
}
|
|
173
175
|
|
|
174
176
|
/**
|
|
@@ -182,8 +184,8 @@ export interface CommonDBSupport {
|
|
|
182
184
|
dbQuerySelectFields?: boolean
|
|
183
185
|
insertSaveMethod?: boolean
|
|
184
186
|
updateSaveMethod?: boolean
|
|
185
|
-
|
|
186
|
-
|
|
187
|
+
patchByQuery?: boolean
|
|
188
|
+
increment?: boolean
|
|
187
189
|
createTable?: boolean
|
|
188
190
|
tableSchemas?: boolean
|
|
189
191
|
streaming?: boolean
|
|
@@ -200,8 +202,8 @@ export const commonDBFullSupport: CommonDBSupport = {
|
|
|
200
202
|
dbQuerySelectFields: true,
|
|
201
203
|
insertSaveMethod: true,
|
|
202
204
|
updateSaveMethod: true,
|
|
203
|
-
|
|
204
|
-
|
|
205
|
+
patchByQuery: true,
|
|
206
|
+
increment: true,
|
|
205
207
|
createTable: true,
|
|
206
208
|
tableSchemas: true,
|
|
207
209
|
streaming: true,
|