@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
|
@@ -2,7 +2,7 @@ import { JsonSchemaObject, JsonSchemaRootObject, ObjectWithId } from '@naturalcy
|
|
|
2
2
|
import { ReadableTyped } from '@naturalcycles/nodejs-lib';
|
|
3
3
|
import { BaseCommonDB } from '../../base.common.db';
|
|
4
4
|
import { CommonDB, CommonDBSupport } from '../../common.db';
|
|
5
|
-
import {
|
|
5
|
+
import { RunQueryResult } from '../../db.model';
|
|
6
6
|
import { DBQuery } from '../../query/dbQuery';
|
|
7
7
|
import { CacheDBCfg, CacheDBCreateOptions, CacheDBOptions, CacheDBSaveOptions, CacheDBStreamOptions } from './cache.db.model';
|
|
8
8
|
/**
|
|
@@ -28,5 +28,5 @@ export declare class CacheDB extends BaseCommonDB implements CommonDB {
|
|
|
28
28
|
runQueryCount<ROW extends ObjectWithId>(q: DBQuery<ROW>, opt?: CacheDBOptions): Promise<number>;
|
|
29
29
|
streamQuery<ROW extends ObjectWithId>(q: DBQuery<ROW>, opt?: CacheDBStreamOptions): ReadableTyped<ROW>;
|
|
30
30
|
deleteByQuery<ROW extends ObjectWithId>(q: DBQuery<ROW>, opt?: CacheDBOptions): Promise<number>;
|
|
31
|
-
|
|
31
|
+
patchByQuery<ROW extends ObjectWithId>(q: DBQuery<ROW>, patch: Partial<ROW>, opt?: CacheDBOptions): Promise<number>;
|
|
32
32
|
}
|
|
@@ -17,6 +17,7 @@ class CacheDB extends base_common_db_1.BaseCommonDB {
|
|
|
17
17
|
this.support = {
|
|
18
18
|
...common_db_1.commonDBFullSupport,
|
|
19
19
|
transactions: false,
|
|
20
|
+
increment: false,
|
|
20
21
|
};
|
|
21
22
|
this.cfg = {
|
|
22
23
|
logger: console,
|
|
@@ -180,13 +181,13 @@ class CacheDB extends base_common_db_1.BaseCommonDB {
|
|
|
180
181
|
}
|
|
181
182
|
return deletedIds;
|
|
182
183
|
}
|
|
183
|
-
async
|
|
184
|
+
async patchByQuery(q, patch, opt = {}) {
|
|
184
185
|
let updated;
|
|
185
186
|
if (!opt.onlyCache && !this.cfg.onlyCache) {
|
|
186
|
-
updated = await this.cfg.downstreamDB.
|
|
187
|
+
updated = await this.cfg.downstreamDB.patchByQuery(q, patch, opt);
|
|
187
188
|
}
|
|
188
189
|
if (!opt.skipCache && !this.cfg.skipCache) {
|
|
189
|
-
const cacheResult = this.cfg.cacheDB.
|
|
190
|
+
const cacheResult = this.cfg.cacheDB.patchByQuery(q, patch, opt);
|
|
190
191
|
if (this.cfg.awaitCache)
|
|
191
192
|
updated ??= await cacheResult;
|
|
192
193
|
}
|
|
@@ -22,9 +22,10 @@ class FileDB extends __1.BaseCommonDB {
|
|
|
22
22
|
bufferValues: false, // todo: implement
|
|
23
23
|
insertSaveMethod: false,
|
|
24
24
|
updateSaveMethod: false,
|
|
25
|
-
|
|
25
|
+
patchByQuery: false,
|
|
26
26
|
createTable: false,
|
|
27
27
|
transactions: false, // todo
|
|
28
|
+
increment: false,
|
|
28
29
|
};
|
|
29
30
|
this.cfg = {
|
|
30
31
|
sortObjects: true,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { CommonLogger, JsonSchemaObject, JsonSchemaRootObject, ObjectWithId, StringMap } from '@naturalcycles/js-lib';
|
|
1
|
+
import { AnyObjectWithId, CommonLogger, JsonSchemaObject, JsonSchemaRootObject, ObjectWithId, StringMap } from '@naturalcycles/js-lib';
|
|
2
2
|
import { ReadableTyped } from '@naturalcycles/nodejs-lib';
|
|
3
|
-
import { CommonDB, CommonDBTransactionOptions, CommonDBType, DBOperation,
|
|
3
|
+
import { CommonDB, CommonDBTransactionOptions, CommonDBType, DBOperation, DBTransactionFn } from '../..';
|
|
4
4
|
import { CommonDBCreateOptions, CommonDBOptions, CommonDBSaveOptions, DBTransaction, RunQueryResult } from '../../db.model';
|
|
5
5
|
import { DBQuery } from '../../query/dbQuery';
|
|
6
6
|
export interface InMemoryDBCfg {
|
|
@@ -55,8 +55,8 @@ export declare class InMemoryDB implements CommonDB {
|
|
|
55
55
|
dbQuerySelectFields?: boolean;
|
|
56
56
|
insertSaveMethod?: boolean;
|
|
57
57
|
updateSaveMethod?: boolean;
|
|
58
|
-
|
|
59
|
-
|
|
58
|
+
patchByQuery?: boolean;
|
|
59
|
+
increment?: boolean;
|
|
60
60
|
createTable?: boolean;
|
|
61
61
|
tableSchemas?: boolean;
|
|
62
62
|
streaming?: boolean;
|
|
@@ -66,7 +66,7 @@ export declare class InMemoryDB implements CommonDB {
|
|
|
66
66
|
};
|
|
67
67
|
constructor(cfg?: Partial<InMemoryDBCfg>);
|
|
68
68
|
cfg: InMemoryDBCfg;
|
|
69
|
-
data: StringMap<StringMap<
|
|
69
|
+
data: StringMap<StringMap<AnyObjectWithId>>;
|
|
70
70
|
/**
|
|
71
71
|
* Returns internal "Data snapshot".
|
|
72
72
|
* Deterministic - jsonSorted.
|
|
@@ -84,11 +84,12 @@ export declare class InMemoryDB implements CommonDB {
|
|
|
84
84
|
saveBatch<ROW extends ObjectWithId>(_table: string, rows: ROW[], opt?: CommonDBSaveOptions<ROW>): Promise<void>;
|
|
85
85
|
deleteByQuery<ROW extends ObjectWithId>(q: DBQuery<ROW>, _opt?: CommonDBOptions): Promise<number>;
|
|
86
86
|
deleteByIds(_table: string, ids: string[], _opt?: CommonDBOptions): Promise<number>;
|
|
87
|
-
|
|
87
|
+
patchByQuery<ROW extends ObjectWithId>(q: DBQuery<ROW>, patch: Partial<ROW>): Promise<number>;
|
|
88
88
|
runQuery<ROW extends ObjectWithId>(q: DBQuery<ROW>, _opt?: CommonDBOptions): Promise<RunQueryResult<ROW>>;
|
|
89
89
|
runQueryCount<ROW extends ObjectWithId>(q: DBQuery<ROW>, _opt?: CommonDBOptions): Promise<number>;
|
|
90
90
|
streamQuery<ROW extends ObjectWithId>(q: DBQuery<ROW>, _opt?: CommonDBOptions): ReadableTyped<ROW>;
|
|
91
91
|
runInTransaction(fn: DBTransactionFn, opt?: CommonDBTransactionOptions): Promise<void>;
|
|
92
|
+
incrementBatch(table: string, prop: string, incrementMap: StringMap<number>, _opt?: CommonDBOptions): Promise<StringMap<number>>;
|
|
92
93
|
/**
|
|
93
94
|
* Flushes all tables (all namespaces) at once.
|
|
94
95
|
*/
|
|
@@ -113,22 +113,12 @@ class InMemoryDB {
|
|
|
113
113
|
});
|
|
114
114
|
return count;
|
|
115
115
|
}
|
|
116
|
-
async
|
|
117
|
-
|
|
118
|
-
if (!patchEntries.length)
|
|
116
|
+
async patchByQuery(q, patch) {
|
|
117
|
+
if ((0, js_lib_1._isEmptyObject)(patch))
|
|
119
118
|
return 0;
|
|
120
119
|
const table = this.cfg.tablesPrefix + q.table;
|
|
121
120
|
const rows = (0, __1.queryInMemory)(q, Object.values(this.data[table] || {}));
|
|
122
|
-
rows.forEach(
|
|
123
|
-
patchEntries.forEach(([k, v]) => {
|
|
124
|
-
if (v instanceof __1.DBIncrement) {
|
|
125
|
-
row[k] = (row[k] || 0) + v.amount;
|
|
126
|
-
}
|
|
127
|
-
else {
|
|
128
|
-
row[k] = v;
|
|
129
|
-
}
|
|
130
|
-
});
|
|
131
|
-
});
|
|
121
|
+
rows.forEach(row => Object.assign(row, patch));
|
|
132
122
|
return rows.length;
|
|
133
123
|
}
|
|
134
124
|
async runQuery(q, _opt) {
|
|
@@ -157,6 +147,18 @@ class InMemoryDB {
|
|
|
157
147
|
throw err;
|
|
158
148
|
}
|
|
159
149
|
}
|
|
150
|
+
async incrementBatch(table, prop, incrementMap, _opt) {
|
|
151
|
+
const tbl = this.cfg.tablesPrefix + table;
|
|
152
|
+
this.data[tbl] ||= {};
|
|
153
|
+
const result = {};
|
|
154
|
+
for (const [id, by] of (0, js_lib_1._stringMapEntries)(incrementMap)) {
|
|
155
|
+
this.data[tbl][id] ||= { id };
|
|
156
|
+
const newValue = (this.data[tbl][id][prop] || 0) + by;
|
|
157
|
+
this.data[tbl][id][prop] = newValue;
|
|
158
|
+
result[id] = newValue;
|
|
159
|
+
}
|
|
160
|
+
return result;
|
|
161
|
+
}
|
|
160
162
|
/**
|
|
161
163
|
* Flushes all tables (all namespaces) at once.
|
|
162
164
|
*/
|
|
@@ -7,6 +7,10 @@ export interface InMemoryKeyValueDBCfg {
|
|
|
7
7
|
export declare class InMemoryKeyValueDB implements CommonKeyValueDB {
|
|
8
8
|
cfg: InMemoryKeyValueDBCfg;
|
|
9
9
|
constructor(cfg?: InMemoryKeyValueDBCfg);
|
|
10
|
+
support: {
|
|
11
|
+
count?: boolean;
|
|
12
|
+
increment?: boolean;
|
|
13
|
+
};
|
|
10
14
|
data: StringMap<StringMap<Buffer>>;
|
|
11
15
|
ping(): Promise<void>;
|
|
12
16
|
createTable(_table: string, _opt?: CommonDBCreateOptions): Promise<void>;
|
|
@@ -18,4 +22,5 @@ export declare class InMemoryKeyValueDB implements CommonKeyValueDB {
|
|
|
18
22
|
streamEntries(table: string, limit?: number): ReadableTyped<KeyValueDBTuple>;
|
|
19
23
|
count(table: string): Promise<number>;
|
|
20
24
|
increment(table: string, id: string, by?: number): Promise<number>;
|
|
25
|
+
incrementBatch(table: string, incrementMap: StringMap<number>): Promise<StringMap<number>>;
|
|
21
26
|
}
|
|
@@ -2,9 +2,14 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.InMemoryKeyValueDB = void 0;
|
|
4
4
|
const node_stream_1 = require("node:stream");
|
|
5
|
+
const js_lib_1 = require("@naturalcycles/js-lib");
|
|
6
|
+
const commonKeyValueDB_1 = require("../../kv/commonKeyValueDB");
|
|
5
7
|
class InMemoryKeyValueDB {
|
|
6
8
|
constructor(cfg = {}) {
|
|
7
9
|
this.cfg = cfg;
|
|
10
|
+
this.support = {
|
|
11
|
+
...commonKeyValueDB_1.commonKeyValueDBFullSupport,
|
|
12
|
+
};
|
|
8
13
|
// data[table][id] > Buffer
|
|
9
14
|
this.data = {};
|
|
10
15
|
}
|
|
@@ -14,6 +19,7 @@ class InMemoryKeyValueDB {
|
|
|
14
19
|
this.data[table] ||= {};
|
|
15
20
|
ids.forEach(id => delete this.data[table][id]);
|
|
16
21
|
}
|
|
22
|
+
// todo: but should we work with Tuples or Objects?
|
|
17
23
|
async getByIds(table, ids) {
|
|
18
24
|
this.data[table] ||= {};
|
|
19
25
|
return ids.map(id => [id, this.data[table][id]]).filter(e => e[1]);
|
|
@@ -42,5 +48,16 @@ class InMemoryKeyValueDB {
|
|
|
42
48
|
this.data[table][id] = Buffer.from(String(newValue));
|
|
43
49
|
return newValue;
|
|
44
50
|
}
|
|
51
|
+
async incrementBatch(table, incrementMap) {
|
|
52
|
+
this.data[table] ||= {};
|
|
53
|
+
const result = {};
|
|
54
|
+
for (const [id, by] of (0, js_lib_1._stringMapEntries)(incrementMap)) {
|
|
55
|
+
const newValue = parseInt(this.data[table][id]?.toString() || '0') + by;
|
|
56
|
+
// todo: but should this.data store Buffer or number for incremented values?
|
|
57
|
+
this.data[table][id] = Buffer.from(String(newValue));
|
|
58
|
+
result[id] = newValue;
|
|
59
|
+
}
|
|
60
|
+
return result;
|
|
61
|
+
}
|
|
45
62
|
}
|
|
46
63
|
exports.InMemoryKeyValueDB = InMemoryKeyValueDB;
|
package/dist/base.common.db.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { JsonSchemaObject, JsonSchemaRootObject, ObjectWithId } from '@naturalcycles/js-lib';
|
|
1
|
+
import { JsonSchemaObject, JsonSchemaRootObject, ObjectWithId, StringMap } from '@naturalcycles/js-lib';
|
|
2
2
|
import { ReadableTyped } from '@naturalcycles/nodejs-lib';
|
|
3
3
|
import { CommonDB, CommonDBSupport, CommonDBType } from './common.db';
|
|
4
|
-
import { CommonDBOptions, CommonDBSaveOptions, CommonDBTransactionOptions,
|
|
4
|
+
import { CommonDBOptions, CommonDBSaveOptions, CommonDBTransactionOptions, DBTransactionFn, RunQueryResult } from './db.model';
|
|
5
5
|
import { DBQuery } from './query/dbQuery';
|
|
6
6
|
/**
|
|
7
7
|
* No-op implementation of CommonDB interface.
|
|
@@ -16,11 +16,12 @@ export declare class BaseCommonDB implements CommonDB {
|
|
|
16
16
|
createTable<ROW extends ObjectWithId>(_table: string, _schema: JsonSchemaObject<ROW>): Promise<void>;
|
|
17
17
|
getByIds<ROW extends ObjectWithId>(_table: string, _ids: string[]): Promise<ROW[]>;
|
|
18
18
|
deleteByQuery<ROW extends ObjectWithId>(_q: DBQuery<ROW>): Promise<number>;
|
|
19
|
-
|
|
19
|
+
patchByQuery<ROW extends ObjectWithId>(_q: DBQuery<ROW>, _patch: Partial<ROW>, _opt?: CommonDBOptions): Promise<number>;
|
|
20
20
|
runQuery<ROW extends ObjectWithId>(_q: DBQuery<ROW>): Promise<RunQueryResult<ROW>>;
|
|
21
21
|
runQueryCount<ROW extends ObjectWithId>(_q: DBQuery<ROW>): Promise<number>;
|
|
22
22
|
saveBatch<ROW extends ObjectWithId>(_table: string, _rows: ROW[], _opt?: CommonDBSaveOptions<ROW>): Promise<void>;
|
|
23
23
|
streamQuery<ROW extends ObjectWithId>(_q: DBQuery<ROW>): ReadableTyped<ROW>;
|
|
24
24
|
deleteByIds(_table: string, _ids: string[], _opt?: CommonDBOptions): Promise<number>;
|
|
25
25
|
runInTransaction(fn: DBTransactionFn, _opt?: CommonDBTransactionOptions): Promise<void>;
|
|
26
|
+
incrementBatch(_table: string, _prop: string, _incrementMap: StringMap<number>, _opt?: CommonDBOptions): Promise<StringMap<number>>;
|
|
26
27
|
}
|
package/dist/base.common.db.js
CHANGED
|
@@ -30,8 +30,8 @@ class BaseCommonDB {
|
|
|
30
30
|
async deleteByQuery(_q) {
|
|
31
31
|
throw new Error('deleteByQuery is not implemented');
|
|
32
32
|
}
|
|
33
|
-
async
|
|
34
|
-
throw new Error('
|
|
33
|
+
async patchByQuery(_q, _patch, _opt) {
|
|
34
|
+
throw new Error('patchByQuery is not implemented');
|
|
35
35
|
}
|
|
36
36
|
async runQuery(_q) {
|
|
37
37
|
throw new Error('runQuery is not implemented');
|
|
@@ -53,5 +53,8 @@ class BaseCommonDB {
|
|
|
53
53
|
await fn(tx);
|
|
54
54
|
// there's no try/catch and rollback, as there's nothing to rollback
|
|
55
55
|
}
|
|
56
|
+
async incrementBatch(_table, _prop, _incrementMap, _opt) {
|
|
57
|
+
throw new Error('incrementBatch is not implemented');
|
|
58
|
+
}
|
|
56
59
|
}
|
|
57
60
|
exports.BaseCommonDB = BaseCommonDB;
|
package/dist/common.db.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { JsonSchemaObject, JsonSchemaRootObject, ObjectWithId } from '@naturalcycles/js-lib';
|
|
1
|
+
import { JsonSchemaObject, JsonSchemaRootObject, ObjectWithId, StringMap } from '@naturalcycles/js-lib';
|
|
2
2
|
import type { ReadableTyped } from '@naturalcycles/nodejs-lib';
|
|
3
|
-
import { CommonDBCreateOptions, CommonDBOptions, CommonDBSaveOptions, CommonDBStreamOptions, CommonDBTransactionOptions,
|
|
3
|
+
import { CommonDBCreateOptions, CommonDBOptions, CommonDBSaveOptions, CommonDBStreamOptions, CommonDBTransactionOptions, DBTransactionFn, RunQueryResult } from './db.model';
|
|
4
4
|
import { DBQuery } from './query/dbQuery';
|
|
5
5
|
export declare enum CommonDBType {
|
|
6
6
|
'document' = "document",
|
|
@@ -15,21 +15,6 @@ export interface CommonDB {
|
|
|
15
15
|
* Manifest of supported features.
|
|
16
16
|
*/
|
|
17
17
|
support: CommonDBSupport;
|
|
18
|
-
supportsQueries?: boolean;
|
|
19
|
-
supportsDBQueryFilter?: boolean;
|
|
20
|
-
supportsDBQueryFilterIn?: boolean;
|
|
21
|
-
supportsDBQueryOrder?: boolean;
|
|
22
|
-
supportsDBQuerySelectFields?: boolean;
|
|
23
|
-
supportsInsertSaveMethod?: boolean;
|
|
24
|
-
supportsUpdateSaveMethod?: boolean;
|
|
25
|
-
supportsUpdateByQuery?: boolean;
|
|
26
|
-
supportsDBIncrement?: boolean;
|
|
27
|
-
supportsCreateTable?: boolean;
|
|
28
|
-
supportsTableSchemas?: boolean;
|
|
29
|
-
supportsStreaming?: boolean;
|
|
30
|
-
supportsBufferValues?: boolean;
|
|
31
|
-
supportsNullValues?: boolean;
|
|
32
|
-
supportsTransactions?: boolean;
|
|
33
18
|
/**
|
|
34
19
|
* Checks that connection/credentials/etc is ok.
|
|
35
20
|
* Also acts as a "warmup request" for a DB.
|
|
@@ -79,7 +64,7 @@ export interface CommonDB {
|
|
|
79
64
|
*/
|
|
80
65
|
deleteByQuery: <ROW extends ObjectWithId>(q: DBQuery<ROW>, opt?: CommonDBOptions) => Promise<number>;
|
|
81
66
|
/**
|
|
82
|
-
* Applies patch to the rows
|
|
67
|
+
* Applies patch to all the rows that are matched by the query.
|
|
83
68
|
*
|
|
84
69
|
* Example:
|
|
85
70
|
*
|
|
@@ -87,16 +72,9 @@ export interface CommonDB {
|
|
|
87
72
|
*
|
|
88
73
|
* patch would be { A: 'B' } for that query.
|
|
89
74
|
*
|
|
90
|
-
*
|
|
91
|
-
*
|
|
92
|
-
* UPDATE table SET A = A + 1
|
|
93
|
-
*
|
|
94
|
-
* In that case patch would look like:
|
|
95
|
-
* { A: DBIncrement(1) }
|
|
96
|
-
*
|
|
97
|
-
* Returns number of rows affected.
|
|
75
|
+
* Returns the number of rows affected.
|
|
98
76
|
*/
|
|
99
|
-
|
|
77
|
+
patchByQuery: <ROW extends ObjectWithId>(q: DBQuery<ROW>, patch: Partial<ROW>, opt?: CommonDBOptions) => Promise<number>;
|
|
100
78
|
/**
|
|
101
79
|
* Should be implemented as a Transaction (best effort), which means that
|
|
102
80
|
* either ALL or NONE of the operations should be applied.
|
|
@@ -109,6 +87,22 @@ export interface CommonDB {
|
|
|
109
87
|
* unless specified as readOnly in CommonDBTransactionOptions.
|
|
110
88
|
*/
|
|
111
89
|
runInTransaction: (fn: DBTransactionFn, opt?: CommonDBTransactionOptions) => Promise<void>;
|
|
90
|
+
/**
|
|
91
|
+
* Increments a value of a property by a given amount.
|
|
92
|
+
* This is a batch operation, so it allows to increment multiple rows at once.
|
|
93
|
+
*
|
|
94
|
+
* - table - the table to apply operations on
|
|
95
|
+
* - prop - name of the property to increment (in each of the rows passed)
|
|
96
|
+
* - incrementMap - map from id to increment value
|
|
97
|
+
*
|
|
98
|
+
* Example of incrementMap:
|
|
99
|
+
* { rowId1: 2, rowId2: 3 }
|
|
100
|
+
*
|
|
101
|
+
* Returns the incrementMap with the same keys and updated values.
|
|
102
|
+
*
|
|
103
|
+
* @experimental
|
|
104
|
+
*/
|
|
105
|
+
incrementBatch: (table: string, prop: string, incrementMap: StringMap<number>, opt?: CommonDBOptions) => Promise<StringMap<number>>;
|
|
112
106
|
}
|
|
113
107
|
/**
|
|
114
108
|
* Manifest of supported features.
|
|
@@ -121,8 +115,8 @@ export interface CommonDBSupport {
|
|
|
121
115
|
dbQuerySelectFields?: boolean;
|
|
122
116
|
insertSaveMethod?: boolean;
|
|
123
117
|
updateSaveMethod?: boolean;
|
|
124
|
-
|
|
125
|
-
|
|
118
|
+
patchByQuery?: boolean;
|
|
119
|
+
increment?: boolean;
|
|
126
120
|
createTable?: boolean;
|
|
127
121
|
tableSchemas?: boolean;
|
|
128
122
|
streaming?: boolean;
|
package/dist/common.db.js
CHANGED
|
@@ -14,8 +14,8 @@ exports.commonDBFullSupport = {
|
|
|
14
14
|
dbQuerySelectFields: true,
|
|
15
15
|
insertSaveMethod: true,
|
|
16
16
|
updateSaveMethod: true,
|
|
17
|
-
|
|
18
|
-
|
|
17
|
+
patchByQuery: true,
|
|
18
|
+
increment: true,
|
|
19
19
|
createTable: true,
|
|
20
20
|
tableSchemas: true,
|
|
21
21
|
streaming: true,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Transform } from 'node:stream';
|
|
2
|
-
import { AsyncMapper, BaseDBEntity, CommonLogger, JsonSchemaObject, JsonSchemaRootObject, UnixTimestampMillisNumber, Unsaved, ZodSchema } from '@naturalcycles/js-lib';
|
|
2
|
+
import { AsyncMapper, BaseDBEntity, CommonLogger, JsonSchemaObject, JsonSchemaRootObject, StringMap, UnixTimestampMillisNumber, Unsaved, ZodSchema } from '@naturalcycles/js-lib';
|
|
3
3
|
import { AjvSchema, ObjectSchema, ReadableTyped } from '@naturalcycles/nodejs-lib';
|
|
4
|
-
import { CommonDBTransactionOptions,
|
|
4
|
+
import { CommonDBTransactionOptions, DBTransaction, RunQueryResult } from '../db.model';
|
|
5
5
|
import { DBQuery, RunnableDBQuery } from '../query/dbQuery';
|
|
6
6
|
import { CommonDaoCfg, CommonDaoCreateOptions, CommonDaoOptions, CommonDaoPatchByIdOptions, CommonDaoPatchOptions, CommonDaoSaveBatchOptions, CommonDaoSaveOptions, CommonDaoStreamDeleteOptions, CommonDaoStreamForEachOptions, CommonDaoStreamOptions, CommonDaoStreamSaveOptions } from './common.dao.model';
|
|
7
7
|
/**
|
|
@@ -125,9 +125,20 @@ export declare class CommonDao<BM extends BaseDBEntity, DBM extends BaseDBEntity
|
|
|
125
125
|
* This is expected to be more memory-efficient way of deleting large number of rows.
|
|
126
126
|
*/
|
|
127
127
|
deleteByQuery(q: DBQuery<DBM>, opt?: CommonDaoStreamDeleteOptions<DBM>): Promise<number>;
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
128
|
+
patchByIds(ids: ID[], patch: Partial<DBM>, opt?: CommonDaoOptions): Promise<number>;
|
|
129
|
+
patchByQuery(q: DBQuery<DBM>, patch: Partial<DBM>, opt?: CommonDaoOptions): Promise<number>;
|
|
130
|
+
/**
|
|
131
|
+
* Caveat: it doesn't update created/updated props.
|
|
132
|
+
*
|
|
133
|
+
* @experimental
|
|
134
|
+
*/
|
|
135
|
+
increment(prop: keyof DBM, id: ID, by?: number, opt?: CommonDaoOptions): Promise<number>;
|
|
136
|
+
/**
|
|
137
|
+
* Caveat: it doesn't update created/updated props.
|
|
138
|
+
*
|
|
139
|
+
* @experimental
|
|
140
|
+
*/
|
|
141
|
+
incrementBatch(prop: keyof DBM, incrementMap: StringMap<number>, opt?: CommonDaoOptions): Promise<StringMap<number>>;
|
|
131
142
|
dbmToBM(_dbm: undefined, opt?: CommonDaoOptions): Promise<undefined>;
|
|
132
143
|
dbmToBM(_dbm?: DBM, opt?: CommonDaoOptions): Promise<BM>;
|
|
133
144
|
dbmsToBM(dbms: DBM[], opt?: CommonDaoOptions): Promise<BM[]>;
|
|
@@ -829,25 +829,54 @@ class CommonDao {
|
|
|
829
829
|
this.logSaveResult(started, op, q.table);
|
|
830
830
|
return deleted;
|
|
831
831
|
}
|
|
832
|
-
async
|
|
833
|
-
return await this.updateByQuery(this.query().filterEq('id', id), patch, opt);
|
|
834
|
-
}
|
|
835
|
-
async updateByIds(ids, patch, opt = {}) {
|
|
832
|
+
async patchByIds(ids, patch, opt = {}) {
|
|
836
833
|
if (!ids.length)
|
|
837
834
|
return 0;
|
|
838
|
-
return await this.
|
|
835
|
+
return await this.patchByQuery(this.query().filterIn('id', ids), patch, opt);
|
|
839
836
|
}
|
|
840
|
-
async
|
|
837
|
+
async patchByQuery(q, patch, opt = {}) {
|
|
841
838
|
this.validateQueryIndexes(q); // throws if query uses `excludeFromIndexes` property
|
|
842
839
|
this.requireWriteAccess();
|
|
843
840
|
this.requireObjectMutability(opt);
|
|
844
841
|
q.table = opt.table || q.table;
|
|
845
|
-
const op = `
|
|
842
|
+
const op = `patchByQuery(${q.pretty()})`;
|
|
846
843
|
const started = this.logStarted(op, q.table);
|
|
847
|
-
const updated = await this.cfg.db.
|
|
844
|
+
const updated = await this.cfg.db.patchByQuery(q, patch, opt);
|
|
848
845
|
this.logSaveResult(started, op, q.table);
|
|
849
846
|
return updated;
|
|
850
847
|
}
|
|
848
|
+
/**
|
|
849
|
+
* Caveat: it doesn't update created/updated props.
|
|
850
|
+
*
|
|
851
|
+
* @experimental
|
|
852
|
+
*/
|
|
853
|
+
async increment(prop, id, by = 1, opt = {}) {
|
|
854
|
+
this.requireWriteAccess();
|
|
855
|
+
this.requireObjectMutability(opt);
|
|
856
|
+
const { table } = this.cfg;
|
|
857
|
+
const op = `increment`;
|
|
858
|
+
const started = this.logStarted(op, table);
|
|
859
|
+
const result = await this.cfg.db.incrementBatch(table, prop, {
|
|
860
|
+
[id]: by,
|
|
861
|
+
});
|
|
862
|
+
this.logSaveResult(started, op, table);
|
|
863
|
+
return result[id];
|
|
864
|
+
}
|
|
865
|
+
/**
|
|
866
|
+
* Caveat: it doesn't update created/updated props.
|
|
867
|
+
*
|
|
868
|
+
* @experimental
|
|
869
|
+
*/
|
|
870
|
+
async incrementBatch(prop, incrementMap, opt = {}) {
|
|
871
|
+
this.requireWriteAccess();
|
|
872
|
+
this.requireObjectMutability(opt);
|
|
873
|
+
const { table } = this.cfg;
|
|
874
|
+
const op = `incrementBatch`;
|
|
875
|
+
const started = this.logStarted(op, table);
|
|
876
|
+
const result = await this.cfg.db.incrementBatch(table, prop, incrementMap);
|
|
877
|
+
this.logSaveResult(started, op, table);
|
|
878
|
+
return result;
|
|
879
|
+
}
|
|
851
880
|
async dbmToBM(_dbm, opt = {}) {
|
|
852
881
|
if (!_dbm)
|
|
853
882
|
return;
|
package/dist/db.model.d.ts
CHANGED
|
@@ -96,16 +96,3 @@ export declare enum DBModelType {
|
|
|
96
96
|
DBM = "DBM",
|
|
97
97
|
BM = "BM"
|
|
98
98
|
}
|
|
99
|
-
/**
|
|
100
|
-
* Allows to construct a query similar to:
|
|
101
|
-
*
|
|
102
|
-
* UPDATE table SET A = A + 1
|
|
103
|
-
*
|
|
104
|
-
* In this case DBIncement.of(1) will be needed.
|
|
105
|
-
*/
|
|
106
|
-
export declare class DBIncrement {
|
|
107
|
-
amount: number;
|
|
108
|
-
private constructor();
|
|
109
|
-
static of(amount: number): DBIncrement;
|
|
110
|
-
}
|
|
111
|
-
export type DBPatch<ROW extends ObjectWithId> = Partial<Record<keyof ROW, ROW[keyof ROW] | DBIncrement>>;
|
package/dist/db.model.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.DBModelType = exports.DBRelation = void 0;
|
|
4
4
|
var DBRelation;
|
|
5
5
|
(function (DBRelation) {
|
|
6
6
|
DBRelation["ONE_TO_ONE"] = "ONE_TO_ONE";
|
|
@@ -11,19 +11,3 @@ var DBModelType;
|
|
|
11
11
|
DBModelType["DBM"] = "DBM";
|
|
12
12
|
DBModelType["BM"] = "BM";
|
|
13
13
|
})(DBModelType || (exports.DBModelType = DBModelType = {}));
|
|
14
|
-
/**
|
|
15
|
-
* Allows to construct a query similar to:
|
|
16
|
-
*
|
|
17
|
-
* UPDATE table SET A = A + 1
|
|
18
|
-
*
|
|
19
|
-
* In this case DBIncement.of(1) will be needed.
|
|
20
|
-
*/
|
|
21
|
-
class DBIncrement {
|
|
22
|
-
constructor(amount) {
|
|
23
|
-
this.amount = amount;
|
|
24
|
-
}
|
|
25
|
-
static of(amount) {
|
|
26
|
-
return new DBIncrement(amount);
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
exports.DBIncrement = DBIncrement;
|
|
@@ -1,20 +1,16 @@
|
|
|
1
|
-
import { UnixTimestampNumber } from '@naturalcycles/js-lib';
|
|
1
|
+
import { StringMap, UnixTimestampNumber } from '@naturalcycles/js-lib';
|
|
2
2
|
import { ReadableTyped } from '@naturalcycles/nodejs-lib';
|
|
3
3
|
import { CommonDBCreateOptions } from '../db.model';
|
|
4
|
-
export type KeyValueDBTuple = [key: string, value: Buffer];
|
|
5
|
-
export interface CommonKeyValueDBSaveBatchOptions {
|
|
6
|
-
/**
|
|
7
|
-
* If set (and if it's implemented by the driver) - will set expiry TTL for each key of the batch.
|
|
8
|
-
* E.g EXAT in Redis.
|
|
9
|
-
*/
|
|
10
|
-
expireAt?: UnixTimestampNumber;
|
|
11
|
-
}
|
|
12
4
|
/**
|
|
13
5
|
* Common interface for Key-Value database implementations.
|
|
14
6
|
*
|
|
15
7
|
* @experimental
|
|
16
8
|
*/
|
|
17
9
|
export interface CommonKeyValueDB {
|
|
10
|
+
/**
|
|
11
|
+
* Manifest of supported features.
|
|
12
|
+
*/
|
|
13
|
+
support: CommonKeyValueDBSupport;
|
|
18
14
|
/**
|
|
19
15
|
* Check that DB connection is working properly.
|
|
20
16
|
*/
|
|
@@ -37,11 +33,41 @@ export interface CommonKeyValueDB {
|
|
|
37
33
|
streamEntries: (table: string, limit?: number) => ReadableTyped<KeyValueDBTuple>;
|
|
38
34
|
count: (table: string) => Promise<number>;
|
|
39
35
|
/**
|
|
40
|
-
*
|
|
41
36
|
* Increments the value of a key in a table by a given amount.
|
|
42
37
|
* Default increment is 1 when `by` is not provided.
|
|
43
38
|
*
|
|
44
39
|
* Returns the new value.
|
|
40
|
+
*
|
|
41
|
+
* @experimental
|
|
45
42
|
*/
|
|
46
43
|
increment: (table: string, id: string, by?: number) => Promise<number>;
|
|
44
|
+
/**
|
|
45
|
+
* Perform a batch of Increment operations.
|
|
46
|
+
* Given incrementMap, increment each key of it by the given amount (value of the map).
|
|
47
|
+
*
|
|
48
|
+
* Example:
|
|
49
|
+
* { key1: 2, key2: 3 }
|
|
50
|
+
* would increment `key1` by 2, and `key2` by 3.
|
|
51
|
+
*
|
|
52
|
+
* Returns the incrementMap with the same keys and updated values.
|
|
53
|
+
*
|
|
54
|
+
* @experimental
|
|
55
|
+
*/
|
|
56
|
+
incrementBatch: (table: string, incrementMap: StringMap<number>) => Promise<StringMap<number>>;
|
|
57
|
+
}
|
|
58
|
+
export type KeyValueDBTuple = [key: string, value: Buffer];
|
|
59
|
+
export interface CommonKeyValueDBSaveBatchOptions {
|
|
60
|
+
/**
|
|
61
|
+
* If set (and if it's implemented by the driver) - will set expiry TTL for each key of the batch.
|
|
62
|
+
* E.g EXAT in Redis.
|
|
63
|
+
*/
|
|
64
|
+
expireAt?: UnixTimestampNumber;
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Manifest of supported features.
|
|
68
|
+
*/
|
|
69
|
+
export interface CommonKeyValueDBSupport {
|
|
70
|
+
count?: boolean;
|
|
71
|
+
increment?: boolean;
|
|
47
72
|
}
|
|
73
|
+
export declare const commonKeyValueDBFullSupport: CommonKeyValueDBSupport;
|
|
@@ -3,7 +3,7 @@ import { ReadableTyped } from '@naturalcycles/nodejs-lib';
|
|
|
3
3
|
import { CommonDaoLogLevel } from '../commondao/common.dao.model';
|
|
4
4
|
import { CommonDBCreateOptions } from '../db.model';
|
|
5
5
|
import { CommonKeyValueDB, CommonKeyValueDBSaveBatchOptions, KeyValueDBTuple } from './commonKeyValueDB';
|
|
6
|
-
export interface CommonKeyValueDaoCfg<
|
|
6
|
+
export interface CommonKeyValueDaoCfg<V> {
|
|
7
7
|
db: CommonKeyValueDB;
|
|
8
8
|
table: string;
|
|
9
9
|
/**
|
|
@@ -24,9 +24,9 @@ export interface CommonKeyValueDaoCfg<T> {
|
|
|
24
24
|
*/
|
|
25
25
|
logStarted?: boolean;
|
|
26
26
|
hooks?: {
|
|
27
|
-
mapValueToBuffer?: (v:
|
|
28
|
-
mapBufferToValue?: (b: Buffer) => Promise<
|
|
29
|
-
beforeCreate?: (v: Partial<
|
|
27
|
+
mapValueToBuffer?: (v: V) => Promise<Buffer>;
|
|
28
|
+
mapBufferToValue?: (b: Buffer) => Promise<V>;
|
|
29
|
+
beforeCreate?: (v: Partial<V>) => Partial<V>;
|
|
30
30
|
};
|
|
31
31
|
/**
|
|
32
32
|
* Set to `true` to conveniently enable zipping+JSON.stringify
|
|
@@ -59,9 +59,12 @@ export declare class CommonKeyValueDao<V, K extends string = string> {
|
|
|
59
59
|
saveBatchAsBuffer(entries: KeyValueDBTuple[], opt?: CommonKeyValueDaoSaveOptions): Promise<void>;
|
|
60
60
|
deleteByIds(ids: K[]): Promise<void>;
|
|
61
61
|
deleteById(id: K): Promise<void>;
|
|
62
|
-
streamIds(limit?: number): ReadableTyped<
|
|
62
|
+
streamIds(limit?: number): ReadableTyped<K>;
|
|
63
63
|
streamValues(limit?: number): ReadableTyped<V>;
|
|
64
64
|
streamEntries(limit?: number): ReadableTyped<KeyValueTuple<K, V>>;
|
|
65
|
+
getAllKeys(limit?: number): Promise<K[]>;
|
|
66
|
+
getAllValues(limit?: number): Promise<V[]>;
|
|
67
|
+
getAllEntries(limit?: number): Promise<KeyValueTuple<K, V>[]>;
|
|
65
68
|
/**
|
|
66
69
|
* Increments the `id` field by the amount specified in `by`,
|
|
67
70
|
* or by 1 if `by` is not specified.
|
|
@@ -157,6 +157,15 @@ class CommonKeyValueDao {
|
|
|
157
157
|
concurrency: 32,
|
|
158
158
|
});
|
|
159
159
|
}
|
|
160
|
+
async getAllKeys(limit) {
|
|
161
|
+
return await this.streamIds(limit).toArray();
|
|
162
|
+
}
|
|
163
|
+
async getAllValues(limit) {
|
|
164
|
+
return await this.streamValues(limit).toArray();
|
|
165
|
+
}
|
|
166
|
+
async getAllEntries(limit) {
|
|
167
|
+
return await this.streamEntries(limit).toArray();
|
|
168
|
+
}
|
|
160
169
|
/**
|
|
161
170
|
* Increments the `id` field by the amount specified in `by`,
|
|
162
171
|
* or by 1 if `by` is not specified.
|
package/dist/query/dbQuery.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { AsyncMapper, BaseDBEntity, ObjectWithId } from '@naturalcycles/js-lib';
|
|
2
2
|
import { ReadableTyped } from '@naturalcycles/nodejs-lib';
|
|
3
|
-
import { CommonDaoOptions, CommonDaoStreamDeleteOptions, CommonDaoStreamForEachOptions, CommonDaoStreamOptions
|
|
3
|
+
import { CommonDaoOptions, CommonDaoStreamDeleteOptions, CommonDaoStreamForEachOptions, CommonDaoStreamOptions } from '..';
|
|
4
4
|
import { CommonDao } from '../commondao/common.dao';
|
|
5
5
|
import { RunQueryResult } from '../db.model';
|
|
6
6
|
/**
|
|
@@ -99,7 +99,7 @@ export declare class RunnableDBQuery<BM extends BaseDBEntity, DBM extends BaseDB
|
|
|
99
99
|
runQueryExtended(opt?: CommonDaoOptions): Promise<RunQueryResult<BM>>;
|
|
100
100
|
runQueryExtendedAsDBM(opt?: CommonDaoOptions): Promise<RunQueryResult<DBM>>;
|
|
101
101
|
runQueryCount(opt?: CommonDaoOptions): Promise<number>;
|
|
102
|
-
|
|
102
|
+
patchByQuery(patch: Partial<DBM>, opt?: CommonDaoOptions): Promise<number>;
|
|
103
103
|
streamQueryForEach(mapper: AsyncMapper<BM, void>, opt?: CommonDaoStreamForEachOptions<BM>): Promise<void>;
|
|
104
104
|
streamQueryAsDBMForEach(mapper: AsyncMapper<DBM, void>, opt?: CommonDaoStreamForEachOptions<DBM>): Promise<void>;
|
|
105
105
|
streamQuery(opt?: CommonDaoStreamOptions<BM>): ReadableTyped<BM>;
|
package/dist/query/dbQuery.js
CHANGED
|
@@ -165,8 +165,8 @@ class RunnableDBQuery extends DBQuery {
|
|
|
165
165
|
async runQueryCount(opt) {
|
|
166
166
|
return await this.dao.runQueryCount(this, opt);
|
|
167
167
|
}
|
|
168
|
-
async
|
|
169
|
-
return await this.dao.
|
|
168
|
+
async patchByQuery(patch, opt) {
|
|
169
|
+
return await this.dao.patchByQuery(this, patch, opt);
|
|
170
170
|
}
|
|
171
171
|
async streamQueryForEach(mapper, opt) {
|
|
172
172
|
await this.dao.streamQueryForEach(this, mapper, opt);
|