@naturalcycles/db-lib 8.47.0 → 8.48.1
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 +0 -2
- package/dist/adapter/cachedb/cache.db.js +0 -51
- package/dist/adapter/file/file.db.d.ts +0 -2
- package/dist/adapter/file/file.db.js +0 -20
- package/dist/adapter/inmemory/inMemory.db.d.ts +0 -2
- package/dist/adapter/inmemory/inMemory.db.js +10 -17
- package/dist/adapter/inmemory/queryInMemory.js +0 -4
- package/dist/base.common.db.d.ts +0 -2
- package/dist/base.common.db.js +1 -7
- package/dist/common.db.d.ts +0 -6
- package/dist/commondao/common.dao.js +18 -15
- package/dist/query/dbQuery.d.ts +1 -15
- package/dist/query/dbQuery.js +4 -29
- package/dist/testing/daoTest.js +3 -4
- package/dist/testing/dbTest.js +11 -12
- package/dist/transaction/dbTransaction.util.js +5 -1
- package/package.json +1 -1
- package/src/adapter/cachedb/cache.db.ts +1 -81
- package/src/adapter/file/file.db.ts +0 -32
- package/src/adapter/inmemory/inMemory.db.ts +10 -28
- package/src/adapter/inmemory/queryInMemory.ts +0 -5
- package/src/base.common.db.ts +1 -9
- package/src/common.db.ts +0 -17
- package/src/commondao/common.dao.ts +24 -17
- package/src/query/dbQuery.ts +5 -32
- package/src/testing/daoTest.ts +13 -10
- package/src/testing/dbTest.ts +20 -18
- package/src/transaction/dbTransaction.util.ts +5 -1
|
@@ -23,8 +23,6 @@ export declare class CacheDB extends BaseCommonDB implements CommonDB {
|
|
|
23
23
|
getTables(): Promise<string[]>;
|
|
24
24
|
getTableSchema<ROW extends ObjectWithId>(table: string): Promise<JsonSchemaRootObject<ROW>>;
|
|
25
25
|
createTable<ROW extends ObjectWithId>(table: string, schema: JsonSchemaObject<ROW>, opt?: CacheDBCreateOptions): Promise<void>;
|
|
26
|
-
getByIds<ROW extends ObjectWithId>(table: string, ids: ROW['id'][], opt?: CacheDBSaveOptions<ROW>): Promise<ROW[]>;
|
|
27
|
-
deleteByIds<ROW extends ObjectWithId>(table: string, ids: ROW['id'][], opt?: CacheDBOptions): Promise<number>;
|
|
28
26
|
saveBatch<ROW extends Partial<ObjectWithId>>(table: string, rows: ROW[], opt?: CacheDBSaveOptions<ROW>): Promise<void>;
|
|
29
27
|
runQuery<ROW extends ObjectWithId>(q: DBQuery<ROW>, opt?: CacheDBSaveOptions<ROW>): Promise<RunQueryResult<ROW>>;
|
|
30
28
|
runQueryCount<ROW extends ObjectWithId>(q: DBQuery<ROW>, opt?: CacheDBOptions): Promise<number>;
|
|
@@ -42,57 +42,6 @@ class CacheDB extends base_common_db_1.BaseCommonDB {
|
|
|
42
42
|
await this.cfg.cacheDB.createTable(table, schema, opt);
|
|
43
43
|
}
|
|
44
44
|
}
|
|
45
|
-
async getByIds(table, ids, opt = {}) {
|
|
46
|
-
const resultMap = {};
|
|
47
|
-
const missingIds = [];
|
|
48
|
-
if (!opt.skipCache && !this.cfg.skipCache) {
|
|
49
|
-
const results = await this.cfg.cacheDB.getByIds(table, ids, opt);
|
|
50
|
-
results.forEach(r => (resultMap[r.id] = r));
|
|
51
|
-
missingIds.push(...ids.filter(id => !resultMap[id]));
|
|
52
|
-
if (this.cfg.logCached) {
|
|
53
|
-
this.cfg.logger?.log(`${table}.getByIds ${results.length} rows from cache: [${results
|
|
54
|
-
.map(r => r.id)
|
|
55
|
-
.join(', ')}]`);
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
if (missingIds.length && !opt.onlyCache && !this.cfg.onlyCache) {
|
|
59
|
-
const results = await this.cfg.downstreamDB.getByIds(table, missingIds, opt);
|
|
60
|
-
results.forEach(r => (resultMap[r.id] = r));
|
|
61
|
-
if (this.cfg.logDownstream) {
|
|
62
|
-
this.cfg.logger?.log(`${table}.getByIds ${results.length} rows from downstream: [${results
|
|
63
|
-
.map(r => r.id)
|
|
64
|
-
.join(', ')}]`);
|
|
65
|
-
}
|
|
66
|
-
if (!opt.skipCache) {
|
|
67
|
-
const cacheResult = this.cfg.cacheDB.saveBatch(table, results, opt);
|
|
68
|
-
if (this.cfg.awaitCache)
|
|
69
|
-
await cacheResult;
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
// return in right order
|
|
73
|
-
return ids.map(id => resultMap[id]).filter(Boolean);
|
|
74
|
-
}
|
|
75
|
-
async deleteByIds(table, ids, opt = {}) {
|
|
76
|
-
let deletedIds = 0;
|
|
77
|
-
if (!opt.onlyCache && !this.cfg.onlyCache) {
|
|
78
|
-
deletedIds = await this.cfg.downstreamDB.deleteByIds(table, ids, opt);
|
|
79
|
-
if (this.cfg.logDownstream) {
|
|
80
|
-
this.cfg.logger?.log(`${table}.deleteByIds ${deletedIds} rows from downstream`);
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
if (!opt.skipCache && !this.cfg.skipCache) {
|
|
84
|
-
const cacheResult = this.cfg.cacheDB
|
|
85
|
-
.deleteByIds(table, ids, opt)
|
|
86
|
-
.then(deletedFromCache => {
|
|
87
|
-
if (this.cfg.logCached) {
|
|
88
|
-
this.cfg.logger?.log(`${table}.deleteByIds ${deletedFromCache} rows from cache`);
|
|
89
|
-
}
|
|
90
|
-
});
|
|
91
|
-
if (this.cfg.awaitCache)
|
|
92
|
-
await cacheResult;
|
|
93
|
-
}
|
|
94
|
-
return deletedIds;
|
|
95
|
-
}
|
|
96
45
|
async saveBatch(table, rows, opt = {}) {
|
|
97
46
|
if (!opt.onlyCache && !this.cfg.onlyCache) {
|
|
98
47
|
await this.cfg.downstreamDB.saveBatch(table, rows, opt);
|
|
@@ -21,7 +21,6 @@ export declare class FileDB extends BaseCommonDB implements CommonDB {
|
|
|
21
21
|
cfg: FileDBCfg;
|
|
22
22
|
ping(): Promise<void>;
|
|
23
23
|
getTables(): Promise<string[]>;
|
|
24
|
-
getByIds<ROW extends ObjectWithId>(table: string, ids: ROW['id'][], _opt?: CommonDBOptions): Promise<ROW[]>;
|
|
25
24
|
saveBatch<ROW extends Partial<ObjectWithId>>(table: string, rows: ROW[], _opt?: CommonDBSaveOptions<ROW>): Promise<void>;
|
|
26
25
|
/**
|
|
27
26
|
* Implementation is optimized for loading/saving _whole files_.
|
|
@@ -30,7 +29,6 @@ export declare class FileDB extends BaseCommonDB implements CommonDB {
|
|
|
30
29
|
runQuery<ROW extends ObjectWithId>(q: DBQuery<ROW>, _opt?: CommonDBOptions): Promise<RunQueryResult<ROW>>;
|
|
31
30
|
runQueryCount<ROW extends ObjectWithId>(q: DBQuery<ROW>, _opt?: CommonDBOptions): Promise<number>;
|
|
32
31
|
streamQuery<ROW extends ObjectWithId>(q: DBQuery<ROW>, opt?: CommonDBStreamOptions): ReadableTyped<ROW>;
|
|
33
|
-
deleteByIds<ROW extends ObjectWithId>(table: string, ids: ROW['id'][], _opt?: CommonDBOptions): Promise<number>;
|
|
34
32
|
deleteByQuery<ROW extends ObjectWithId>(q: DBQuery<ROW>, _opt?: CommonDBOptions): Promise<number>;
|
|
35
33
|
getTableSchema<ROW extends ObjectWithId>(table: string): Promise<JsonSchemaRootObject<ROW>>;
|
|
36
34
|
loadFile<ROW extends ObjectWithId>(table: string): Promise<ROW[]>;
|
|
@@ -34,10 +34,6 @@ class FileDB extends __1.BaseCommonDB {
|
|
|
34
34
|
this.logFinished(started, `getTables() ${tables.length} tables`);
|
|
35
35
|
return tables;
|
|
36
36
|
}
|
|
37
|
-
async getByIds(table, ids, _opt) {
|
|
38
|
-
const byId = (0, js_lib_1._by)(await this.loadFile(table), r => r.id);
|
|
39
|
-
return ids.map(id => byId[id]).filter(Boolean);
|
|
40
|
-
}
|
|
41
37
|
async saveBatch(table, rows, _opt) {
|
|
42
38
|
if (!rows.length)
|
|
43
39
|
return; // save some api calls
|
|
@@ -130,22 +126,6 @@ class FileDB extends __1.BaseCommonDB {
|
|
|
130
126
|
});
|
|
131
127
|
return readable;
|
|
132
128
|
}
|
|
133
|
-
async deleteByIds(table, ids, _opt) {
|
|
134
|
-
if (!ids.length)
|
|
135
|
-
return 0;
|
|
136
|
-
let deleted = 0;
|
|
137
|
-
const rows = (await this.loadFile(table)).filter(r => {
|
|
138
|
-
if (ids.includes(r.id)) {
|
|
139
|
-
deleted++;
|
|
140
|
-
return false;
|
|
141
|
-
}
|
|
142
|
-
return true;
|
|
143
|
-
});
|
|
144
|
-
if (deleted > 0) {
|
|
145
|
-
await this.saveFile(table, rows);
|
|
146
|
-
}
|
|
147
|
-
return deleted;
|
|
148
|
-
}
|
|
149
129
|
async deleteByQuery(q, _opt) {
|
|
150
130
|
const byId = (0, js_lib_1._by)(await this.loadFile(q.table), r => r.id);
|
|
151
131
|
let deleted = 0;
|
|
@@ -52,9 +52,7 @@ export declare class InMemoryDB implements CommonDB {
|
|
|
52
52
|
getTables(): Promise<string[]>;
|
|
53
53
|
getTableSchema<ROW extends ObjectWithId>(_table: string): Promise<JsonSchemaRootObject<ROW>>;
|
|
54
54
|
createTable<ROW extends ObjectWithId>(_table: string, _schema: JsonSchemaObject<ROW>, opt?: CommonDBCreateOptions): Promise<void>;
|
|
55
|
-
getByIds<ROW extends ObjectWithId>(_table: string, ids: ROW['id'][], _opt?: CommonDBOptions): Promise<ROW[]>;
|
|
56
55
|
saveBatch<ROW extends Partial<ObjectWithId>>(_table: string, rows: ROW[], opt?: CommonDBSaveOptions<ROW>): Promise<void>;
|
|
57
|
-
deleteByIds<ROW extends ObjectWithId>(_table: string, ids: ROW['id'][], _opt?: CommonDBOptions): Promise<number>;
|
|
58
56
|
deleteByQuery<ROW extends ObjectWithId>(q: DBQuery<ROW>, _opt?: CommonDBOptions): Promise<number>;
|
|
59
57
|
updateByQuery<ROW extends ObjectWithId>(q: DBQuery<ROW>, patch: DBPatch<ROW>): Promise<number>;
|
|
60
58
|
runQuery<ROW extends ObjectWithId>(q: DBQuery<ROW>, _opt?: CommonDBOptions): Promise<RunQueryResult<ROW>>;
|
|
@@ -8,6 +8,7 @@ const nodejs_lib_1 = require("@naturalcycles/nodejs-lib");
|
|
|
8
8
|
const colors_1 = require("@naturalcycles/nodejs-lib/dist/colors");
|
|
9
9
|
const fs = require("fs-extra");
|
|
10
10
|
const __1 = require("../..");
|
|
11
|
+
const dbQuery_1 = require("../../query/dbQuery");
|
|
11
12
|
class InMemoryDB {
|
|
12
13
|
constructor(cfg) {
|
|
13
14
|
// data[table][id] > {id: 'a', created: ... }
|
|
@@ -66,11 +67,6 @@ class InMemoryDB {
|
|
|
66
67
|
this.data[table] ||= {};
|
|
67
68
|
}
|
|
68
69
|
}
|
|
69
|
-
async getByIds(_table, ids, _opt) {
|
|
70
|
-
const table = this.cfg.tablesPrefix + _table;
|
|
71
|
-
this.data[table] ||= {};
|
|
72
|
-
return ids.map(id => this.data[table][id]).filter(Boolean);
|
|
73
|
-
}
|
|
74
70
|
async saveBatch(_table, rows, opt = {}) {
|
|
75
71
|
const table = this.cfg.tablesPrefix + _table;
|
|
76
72
|
this.data[table] ||= {};
|
|
@@ -91,24 +87,18 @@ class InMemoryDB {
|
|
|
91
87
|
this.data[table][r.id] = JSON.parse(JSON.stringify(r), nodejs_lib_1.bufferReviver);
|
|
92
88
|
});
|
|
93
89
|
}
|
|
94
|
-
async
|
|
95
|
-
const table = this.cfg.tablesPrefix +
|
|
90
|
+
async deleteByQuery(q, _opt) {
|
|
91
|
+
const table = this.cfg.tablesPrefix + q.table;
|
|
96
92
|
this.data[table] ||= {};
|
|
97
93
|
let count = 0;
|
|
98
|
-
|
|
99
|
-
if (!this.data[table][id])
|
|
94
|
+
(0, __1.queryInMemory)(q, Object.values(this.data[table] || {})).forEach(r => {
|
|
95
|
+
if (!this.data[table][r.id])
|
|
100
96
|
return;
|
|
101
|
-
delete this.data[table][id];
|
|
97
|
+
delete this.data[table][r.id];
|
|
102
98
|
count++;
|
|
103
99
|
});
|
|
104
100
|
return count;
|
|
105
101
|
}
|
|
106
|
-
async deleteByQuery(q, _opt) {
|
|
107
|
-
const table = this.cfg.tablesPrefix + q.table;
|
|
108
|
-
const rows = (0, __1.queryInMemory)(q, Object.values(this.data[table] || {}));
|
|
109
|
-
const ids = rows.map(r => r.id);
|
|
110
|
-
return await this.deleteByIds(q.table, ids);
|
|
111
|
-
}
|
|
112
102
|
async updateByQuery(q, patch) {
|
|
113
103
|
const patchEntries = Object.entries(patch);
|
|
114
104
|
if (!patchEntries.length)
|
|
@@ -147,7 +137,10 @@ class InMemoryDB {
|
|
|
147
137
|
await this.saveBatch(op.table, op.rows, { ...op.opt, ...opt });
|
|
148
138
|
}
|
|
149
139
|
else if (op.type === 'deleteByIds') {
|
|
150
|
-
await this.
|
|
140
|
+
await this.deleteByQuery(dbQuery_1.DBQuery.create(op.table).filter('id', 'in', op.ids), {
|
|
141
|
+
...op.opt,
|
|
142
|
+
...opt,
|
|
143
|
+
});
|
|
151
144
|
}
|
|
152
145
|
else {
|
|
153
146
|
throw new Error(`DBOperation not supported: ${op.type}`);
|
|
@@ -17,10 +17,6 @@ const FILTER_FNS = {
|
|
|
17
17
|
// Important: q.table is not used in this function, so tablesPrefix is not needed.
|
|
18
18
|
// But should be careful here..
|
|
19
19
|
function queryInMemory(q, rows = []) {
|
|
20
|
-
// .ids
|
|
21
|
-
if (q._ids?.length) {
|
|
22
|
-
rows = rows.filter(r => q._ids.includes(r.id));
|
|
23
|
-
}
|
|
24
20
|
// .filter
|
|
25
21
|
// eslint-disable-next-line unicorn/no-array-reduce
|
|
26
22
|
rows = q._filters.reduce((rows, filter) => {
|
package/dist/base.common.db.d.ts
CHANGED
|
@@ -13,10 +13,8 @@ export declare class BaseCommonDB implements CommonDB {
|
|
|
13
13
|
getTables(): Promise<string[]>;
|
|
14
14
|
getTableSchema<ROW extends ObjectWithId>(table: string): Promise<JsonSchemaRootObject<ROW>>;
|
|
15
15
|
createTable<ROW extends ObjectWithId>(table: string, schema: JsonSchemaObject<ROW>): Promise<void>;
|
|
16
|
-
deleteByIds<ROW extends ObjectWithId>(table: string, ids: ROW['id'][]): Promise<number>;
|
|
17
16
|
deleteByQuery<ROW extends ObjectWithId>(q: DBQuery<ROW>): Promise<number>;
|
|
18
17
|
updateByQuery<ROW extends ObjectWithId>(q: DBQuery<ROW>, patch: DBPatch<ROW>, opt?: CommonDBOptions): Promise<number>;
|
|
19
|
-
getByIds<ROW extends ObjectWithId>(table: string, ids: ROW['id'][]): Promise<ROW[]>;
|
|
20
18
|
runQuery<ROW extends ObjectWithId>(q: DBQuery<ROW>): Promise<RunQueryResult<ROW>>;
|
|
21
19
|
runQueryCount<ROW extends ObjectWithId>(q: DBQuery<ROW>): Promise<number>;
|
|
22
20
|
saveBatch<ROW extends Partial<ObjectWithId>>(table: string, rows: ROW[], opt?: CommonDBSaveOptions<ROW>): Promise<void>;
|
package/dist/base.common.db.js
CHANGED
|
@@ -17,10 +17,7 @@ class BaseCommonDB {
|
|
|
17
17
|
throw new Error('getTableSchema is not implemented');
|
|
18
18
|
}
|
|
19
19
|
async createTable(table, schema) {
|
|
20
|
-
|
|
21
|
-
}
|
|
22
|
-
async deleteByIds(table, ids) {
|
|
23
|
-
throw new Error('deleteByIds is not implemented');
|
|
20
|
+
// no-op
|
|
24
21
|
}
|
|
25
22
|
async deleteByQuery(q) {
|
|
26
23
|
throw new Error('deleteByQuery is not implemented');
|
|
@@ -28,9 +25,6 @@ class BaseCommonDB {
|
|
|
28
25
|
async updateByQuery(q, patch, opt) {
|
|
29
26
|
throw new Error('updateByQuery is not implemented');
|
|
30
27
|
}
|
|
31
|
-
async getByIds(table, ids) {
|
|
32
|
-
throw new Error('getByIds is not implemented');
|
|
33
|
-
}
|
|
34
28
|
async runQuery(q) {
|
|
35
29
|
throw new Error('runQuery is not implemented');
|
|
36
30
|
}
|
package/dist/common.db.d.ts
CHANGED
|
@@ -27,11 +27,6 @@ export interface CommonDB {
|
|
|
27
27
|
* Caution! dropIfExists defaults to false. If set to true - will actually DROP the table!
|
|
28
28
|
*/
|
|
29
29
|
createTable<ROW extends ObjectWithId>(table: string, schema: JsonSchemaObject<ROW>, opt?: CommonDBCreateOptions): Promise<void>;
|
|
30
|
-
/**
|
|
31
|
-
* Order of items returned is not guaranteed to match order of ids.
|
|
32
|
-
* (Such limitation exists because Datastore doesn't support it).
|
|
33
|
-
*/
|
|
34
|
-
getByIds<ROW extends ObjectWithId>(table: string, ids: ROW['id'][], opt?: CommonDBOptions): Promise<ROW[]>;
|
|
35
30
|
/**
|
|
36
31
|
* Order by 'id' is not supported by all implementations (for example, Datastore doesn't support it).
|
|
37
32
|
*/
|
|
@@ -46,7 +41,6 @@ export interface CommonDB {
|
|
|
46
41
|
* Returns number of deleted items.
|
|
47
42
|
* Not supported by all implementations (e.g Datastore will always return same number as number of ids).
|
|
48
43
|
*/
|
|
49
|
-
deleteByIds<ROW extends ObjectWithId>(table: string, ids: ROW['id'][], opt?: CommonDBOptions): Promise<number>;
|
|
50
44
|
deleteByQuery<ROW extends ObjectWithId>(q: DBQuery<ROW>, opt?: CommonDBOptions): Promise<number>;
|
|
51
45
|
/**
|
|
52
46
|
* Applies patch to the rows returned by the query.
|
|
@@ -112,13 +112,15 @@ class CommonDao {
|
|
|
112
112
|
let dbm;
|
|
113
113
|
if (opt.timeout) {
|
|
114
114
|
// todo: possibly remove it after debugging is done
|
|
115
|
-
dbm =
|
|
115
|
+
dbm = await (0, js_lib_1.pTimeout)(async () => {
|
|
116
|
+
return (await this.cfg.db.runQuery(dbQuery_1.DBQuery.create(table).filterEq('id', id))).rows[0];
|
|
117
|
+
}, {
|
|
116
118
|
timeout: opt.timeout,
|
|
117
119
|
name: `getById(${table})`,
|
|
118
|
-
})
|
|
120
|
+
});
|
|
119
121
|
}
|
|
120
122
|
else {
|
|
121
|
-
dbm = (await this.cfg.db.
|
|
123
|
+
dbm = (await this.cfg.db.runQuery(dbQuery_1.DBQuery.create(table).filterEq('id', id))).rows[0];
|
|
122
124
|
}
|
|
123
125
|
const bm = opt.raw ? dbm : await this.dbmToBM(dbm, opt);
|
|
124
126
|
this.logResult(started, op, bm, table);
|
|
@@ -143,7 +145,7 @@ class CommonDao {
|
|
|
143
145
|
const op = `getByIdAsDBM(${id})`;
|
|
144
146
|
const table = opt.table || this.cfg.table;
|
|
145
147
|
const started = this.logStarted(op, table);
|
|
146
|
-
let [dbm] = await this.cfg.db.
|
|
148
|
+
let [dbm] = (await this.cfg.db.runQuery(dbQuery_1.DBQuery.create(table).filterEq('id', id))).rows;
|
|
147
149
|
if (!opt.raw) {
|
|
148
150
|
dbm = this.anyToDBM(dbm, opt);
|
|
149
151
|
}
|
|
@@ -156,7 +158,7 @@ class CommonDao {
|
|
|
156
158
|
const op = `getByIdAsTM(${id})`;
|
|
157
159
|
const table = opt.table || this.cfg.table;
|
|
158
160
|
const started = this.logStarted(op, table);
|
|
159
|
-
const [dbm] = await this.cfg.db.
|
|
161
|
+
const [dbm] = (await this.cfg.db.runQuery(dbQuery_1.DBQuery.create(table).filterEq('id', id))).rows;
|
|
160
162
|
if (opt.raw) {
|
|
161
163
|
this.logResult(started, op, dbm, table);
|
|
162
164
|
return dbm || null;
|
|
@@ -170,7 +172,7 @@ class CommonDao {
|
|
|
170
172
|
const op = `getByIds ${ids.length} id(s) (${(0, js_lib_1._truncate)(ids.slice(0, 10).join(', '), 50)})`;
|
|
171
173
|
const table = opt.table || this.cfg.table;
|
|
172
174
|
const started = this.logStarted(op, table);
|
|
173
|
-
const dbms = await this.cfg.db.
|
|
175
|
+
const dbms = (await this.cfg.db.runQuery(dbQuery_1.DBQuery.create(table).filterIn('id', ids))).rows;
|
|
174
176
|
const bms = opt.raw ? dbms : await this.dbmsToBM(dbms, opt);
|
|
175
177
|
this.logResult(started, op, bms, table);
|
|
176
178
|
return bms;
|
|
@@ -179,7 +181,7 @@ class CommonDao {
|
|
|
179
181
|
const op = `getByIdsAsDBM ${ids.length} id(s) (${(0, js_lib_1._truncate)(ids.slice(0, 10).join(', '), 50)})`;
|
|
180
182
|
const table = opt.table || this.cfg.table;
|
|
181
183
|
const started = this.logStarted(op, table);
|
|
182
|
-
const dbms = await this.cfg.db.
|
|
184
|
+
const dbms = (await this.cfg.db.runQuery(dbQuery_1.DBQuery.create(table).filterIn('id', ids))).rows;
|
|
183
185
|
this.logResult(started, op, dbms, table);
|
|
184
186
|
return dbms;
|
|
185
187
|
}
|
|
@@ -229,7 +231,8 @@ class CommonDao {
|
|
|
229
231
|
}
|
|
230
232
|
async ensureUniqueId(table, dbm) {
|
|
231
233
|
// todo: retry N times
|
|
232
|
-
const existing = await this.cfg.db.
|
|
234
|
+
const existing = (await this.cfg.db.runQuery(dbQuery_1.DBQuery.create(table).filterEq('id', dbm.id)))
|
|
235
|
+
.rows;
|
|
233
236
|
if (existing.length) {
|
|
234
237
|
throw new js_lib_1.AppError(cnst_1.DBLibError.NON_UNIQUE_ID, {
|
|
235
238
|
table,
|
|
@@ -656,9 +659,9 @@ class CommonDao {
|
|
|
656
659
|
const op = `deleteById(${id})`;
|
|
657
660
|
const table = opt.table || this.cfg.table;
|
|
658
661
|
const started = this.logStarted(op, table);
|
|
659
|
-
const
|
|
662
|
+
const count = await this.cfg.db.deleteByQuery(dbQuery_1.DBQuery.create(table).filterEq('id', id));
|
|
660
663
|
this.logSaveResult(started, op, table);
|
|
661
|
-
return
|
|
664
|
+
return count;
|
|
662
665
|
}
|
|
663
666
|
async deleteByIds(ids, opt = {}) {
|
|
664
667
|
this.requireWriteAccess();
|
|
@@ -666,9 +669,9 @@ class CommonDao {
|
|
|
666
669
|
const op = `deleteByIds(${ids.join(', ')})`;
|
|
667
670
|
const table = opt.table || this.cfg.table;
|
|
668
671
|
const started = this.logStarted(op, table);
|
|
669
|
-
const
|
|
672
|
+
const count = await this.cfg.db.deleteByQuery(dbQuery_1.DBQuery.create(table).filterIn('id', ids));
|
|
670
673
|
this.logSaveResult(started, op, table);
|
|
671
|
-
return
|
|
674
|
+
return count;
|
|
672
675
|
}
|
|
673
676
|
/**
|
|
674
677
|
* Pass `stream: true` option to use Streaming: it will Stream the query, batch by 500, and execute
|
|
@@ -691,7 +694,7 @@ class CommonDao {
|
|
|
691
694
|
}),
|
|
692
695
|
(0, nodejs_lib_1.transformBuffer)({ batchSize }),
|
|
693
696
|
(0, nodejs_lib_1.transformMap)(async (ids) => {
|
|
694
|
-
deleted += await this.cfg.db.
|
|
697
|
+
deleted += await this.cfg.db.deleteByQuery(dbQuery_1.DBQuery.create(q.table).filterIn('id', ids), opt);
|
|
695
698
|
}, {
|
|
696
699
|
predicate: js_lib_1._passthroughPredicate,
|
|
697
700
|
}),
|
|
@@ -712,10 +715,10 @@ class CommonDao {
|
|
|
712
715
|
return deleted;
|
|
713
716
|
}
|
|
714
717
|
async updateById(id, patch, opt = {}) {
|
|
715
|
-
return await this.updateByQuery(this.query().
|
|
718
|
+
return await this.updateByQuery(this.query().filterEq('id', id), patch, opt);
|
|
716
719
|
}
|
|
717
720
|
async updateByIds(ids, patch, opt = {}) {
|
|
718
|
-
return await this.updateByQuery(this.query().
|
|
721
|
+
return await this.updateByQuery(this.query().filterIn('id', ids), patch, opt);
|
|
719
722
|
}
|
|
720
723
|
async updateByQuery(q, patch, opt = {}) {
|
|
721
724
|
this.requireWriteAccess();
|
package/dist/query/dbQuery.d.ts
CHANGED
|
@@ -66,9 +66,9 @@ export declare class DBQuery<ROW extends ObjectWithId = AnyObjectWithId> {
|
|
|
66
66
|
_selectedFieldNames?: (keyof ROW)[];
|
|
67
67
|
_groupByFieldNames?: (keyof ROW)[];
|
|
68
68
|
_distinct: boolean;
|
|
69
|
-
_ids?: ROW['id'][];
|
|
70
69
|
filter(name: keyof ROW, op: DBQueryFilterOperator, val: any): this;
|
|
71
70
|
filterEq(name: keyof ROW, val: any): this;
|
|
71
|
+
filterIn(name: keyof ROW, val: any[]): this;
|
|
72
72
|
limit(limit: number): this;
|
|
73
73
|
offset(offset: number): this;
|
|
74
74
|
order(name: keyof ROW, descending?: boolean): this;
|
|
@@ -77,20 +77,6 @@ export declare class DBQuery<ROW extends ObjectWithId = AnyObjectWithId> {
|
|
|
77
77
|
distinct(distinct?: boolean): this;
|
|
78
78
|
startCursor(startCursor?: string): this;
|
|
79
79
|
endCursor(endCursor?: string): this;
|
|
80
|
-
/**
|
|
81
|
-
* Allows to query by ids (one or many).
|
|
82
|
-
* Similar to:
|
|
83
|
-
* SELECT * FROM table where id in (a, b, c)
|
|
84
|
-
* or (if only 1 id is passed)
|
|
85
|
-
* SELECT * FROM table where id = a
|
|
86
|
-
*/
|
|
87
|
-
byIds(ids: ROW['id'][]): this;
|
|
88
|
-
/**
|
|
89
|
-
* Allows to query by id.
|
|
90
|
-
* Similar to:
|
|
91
|
-
* SELECT * FROM table where id = a
|
|
92
|
-
*/
|
|
93
|
-
byId(id: ROW['id']): this;
|
|
94
80
|
clone(): DBQuery<ROW>;
|
|
95
81
|
pretty(): string;
|
|
96
82
|
prettyConditions(): string[];
|
package/dist/query/dbQuery.js
CHANGED
|
@@ -50,6 +50,10 @@ class DBQuery {
|
|
|
50
50
|
this._filters.push({ name, op: '==', val });
|
|
51
51
|
return this;
|
|
52
52
|
}
|
|
53
|
+
filterIn(name, val) {
|
|
54
|
+
this._filters.push({ name, op: 'in', val });
|
|
55
|
+
return this;
|
|
56
|
+
}
|
|
53
57
|
limit(limit) {
|
|
54
58
|
this._limitValue = limit;
|
|
55
59
|
return this;
|
|
@@ -85,26 +89,6 @@ class DBQuery {
|
|
|
85
89
|
this._endCursor = endCursor;
|
|
86
90
|
return this;
|
|
87
91
|
}
|
|
88
|
-
/**
|
|
89
|
-
* Allows to query by ids (one or many).
|
|
90
|
-
* Similar to:
|
|
91
|
-
* SELECT * FROM table where id in (a, b, c)
|
|
92
|
-
* or (if only 1 id is passed)
|
|
93
|
-
* SELECT * FROM table where id = a
|
|
94
|
-
*/
|
|
95
|
-
byIds(ids) {
|
|
96
|
-
this._ids = ids;
|
|
97
|
-
return this;
|
|
98
|
-
}
|
|
99
|
-
/**
|
|
100
|
-
* Allows to query by id.
|
|
101
|
-
* Similar to:
|
|
102
|
-
* SELECT * FROM table where id = a
|
|
103
|
-
*/
|
|
104
|
-
byId(id) {
|
|
105
|
-
this._ids = [id];
|
|
106
|
-
return this;
|
|
107
|
-
}
|
|
108
92
|
clone() {
|
|
109
93
|
return (0, js_lib_1._objectAssign)(new DBQuery(this.table), {
|
|
110
94
|
_filters: [...this._filters],
|
|
@@ -116,7 +100,6 @@ class DBQuery {
|
|
|
116
100
|
_distinct: this._distinct,
|
|
117
101
|
_startCursor: this._startCursor,
|
|
118
102
|
_endCursor: this._endCursor,
|
|
119
|
-
_ids: this._ids,
|
|
120
103
|
});
|
|
121
104
|
}
|
|
122
105
|
pretty() {
|
|
@@ -130,14 +113,6 @@ class DBQuery {
|
|
|
130
113
|
if (this._selectedFieldNames) {
|
|
131
114
|
tokens.push(`select${this._distinct ? ' distinct' : ''}(${this._selectedFieldNames.join(',')})`);
|
|
132
115
|
}
|
|
133
|
-
if (this._ids?.length) {
|
|
134
|
-
if (this._ids.length === 1) {
|
|
135
|
-
tokens.push(`id=${this._ids[0]}`);
|
|
136
|
-
}
|
|
137
|
-
else {
|
|
138
|
-
tokens.push(`ids in (${this._ids.join(',')})`);
|
|
139
|
-
}
|
|
140
|
-
}
|
|
141
116
|
tokens.push(...this._filters.map(f => `${f.name}${f.op}${f.val}`), ...this._orders.map(o => `order by ${o.name}${o.descending ? ' desc' : ''}`));
|
|
142
117
|
if (this._groupByFieldNames) {
|
|
143
118
|
tokens.push(`groupBy(${this._groupByFieldNames.join(',')})`);
|
package/dist/testing/daoTest.js
CHANGED
|
@@ -48,7 +48,7 @@ function runCommonDaoTest(db, features = {}, quirks = {}) {
|
|
|
48
48
|
// DELETE ALL initially
|
|
49
49
|
test('deleteByIds test items', async () => {
|
|
50
50
|
const rows = await dao.query().select(['id']).runQuery();
|
|
51
|
-
await db.
|
|
51
|
+
await db.deleteByQuery(__1.DBQuery.create(test_model_1.TEST_TABLE).filter('id', 'in', rows.map(r => r.id)));
|
|
52
52
|
});
|
|
53
53
|
// QUERY empty
|
|
54
54
|
test('runQuery(all), runQueryCount should return empty', async () => {
|
|
@@ -114,7 +114,7 @@ function runCommonDaoTest(db, features = {}, quirks = {}) {
|
|
|
114
114
|
// GET not empty
|
|
115
115
|
test('getByIds all items', async () => {
|
|
116
116
|
const rows = await dao.getByIds(items.map(i => i.id).concat('abcd'));
|
|
117
|
-
(0, dbTest_1.expectMatch)(expectedItems, rows, quirks);
|
|
117
|
+
(0, dbTest_1.expectMatch)(expectedItems, (0, js_lib_1._sortBy)(rows, r => r.id), quirks);
|
|
118
118
|
});
|
|
119
119
|
// QUERY
|
|
120
120
|
if (querying) {
|
|
@@ -187,8 +187,7 @@ function runCommonDaoTest(db, features = {}, quirks = {}) {
|
|
|
187
187
|
});
|
|
188
188
|
test('cleanup', async () => {
|
|
189
189
|
// CLEAN UP
|
|
190
|
-
|
|
191
|
-
await db.deleteByIds(test_model_1.TEST_TABLE, rows.map(i => i.id));
|
|
190
|
+
await dao.query().deleteByQuery();
|
|
192
191
|
});
|
|
193
192
|
}
|
|
194
193
|
if (transactions) {
|
package/dist/testing/dbTest.js
CHANGED
|
@@ -37,7 +37,7 @@ function runCommonDBTest(db, features = {}, quirks = {}) {
|
|
|
37
37
|
// DELETE ALL initially
|
|
38
38
|
test('deleteByIds test items', async () => {
|
|
39
39
|
const { rows } = await db.runQuery(queryAll().select(['id']));
|
|
40
|
-
await db.
|
|
40
|
+
await db.deleteByQuery(queryAll().filterIn('id', rows.map(i => i.id)));
|
|
41
41
|
});
|
|
42
42
|
// QUERY empty
|
|
43
43
|
test('runQuery(all), runQueryCount should return empty', async () => {
|
|
@@ -49,15 +49,15 @@ function runCommonDBTest(db, features = {}, quirks = {}) {
|
|
|
49
49
|
}
|
|
50
50
|
// GET empty
|
|
51
51
|
test('getByIds(item1.id) should return empty', async () => {
|
|
52
|
-
const [item1Loaded] = await db.
|
|
52
|
+
const [item1Loaded] = (await db.runQuery(queryAll().filterEq('id', item1.id))).rows;
|
|
53
53
|
// console.log(a)
|
|
54
54
|
expect(item1Loaded).toBeUndefined();
|
|
55
55
|
});
|
|
56
56
|
test('getByIds([]) should return []', async () => {
|
|
57
|
-
expect(await db.
|
|
57
|
+
expect((await db.runQuery(queryAll().filterIn('id', []))).rows).toEqual([]);
|
|
58
58
|
});
|
|
59
59
|
test('getByIds(...) should return empty', async () => {
|
|
60
|
-
expect(await db.
|
|
60
|
+
expect((await db.runQuery(queryAll().filterIn('id', ['abc', 'abcd']))).rows).toEqual([]);
|
|
61
61
|
});
|
|
62
62
|
// SAVE
|
|
63
63
|
if (nullValues) {
|
|
@@ -68,7 +68,7 @@ function runCommonDBTest(db, features = {}, quirks = {}) {
|
|
|
68
68
|
};
|
|
69
69
|
(0, test_util_1.deepFreeze)(item3);
|
|
70
70
|
await db.saveBatch(test_model_1.TEST_TABLE, [item3]);
|
|
71
|
-
const item3Loaded = (await db.
|
|
71
|
+
const item3Loaded = (await db.runQuery(queryAll().filterEq('id', item3.id))).rows[0];
|
|
72
72
|
expectMatch([item3], [item3Loaded], quirks);
|
|
73
73
|
expect(item3Loaded.k2).toBeNull();
|
|
74
74
|
});
|
|
@@ -83,7 +83,7 @@ function runCommonDBTest(db, features = {}, quirks = {}) {
|
|
|
83
83
|
const expected = { ...item3 };
|
|
84
84
|
delete expected.k2;
|
|
85
85
|
await db.saveBatch(test_model_1.TEST_TABLE, [item3]);
|
|
86
|
-
const item3Loaded = (await db.
|
|
86
|
+
const item3Loaded = (await db.runQuery(queryAll().filterEq('id', item3.id))).rows[0];
|
|
87
87
|
expectMatch([expected], [item3Loaded], quirks);
|
|
88
88
|
expect(item3Loaded.k2).toBeUndefined();
|
|
89
89
|
expect(Object.keys(item3Loaded)).not.toContain('k2');
|
|
@@ -112,8 +112,9 @@ function runCommonDBTest(db, features = {}, quirks = {}) {
|
|
|
112
112
|
}
|
|
113
113
|
// GET not empty
|
|
114
114
|
test('getByIds all items', async () => {
|
|
115
|
-
const rows = await db.
|
|
116
|
-
|
|
115
|
+
const rows = (await db.runQuery(queryAll().filterIn('id', items.map(i => i.id).concat('abcd'))))
|
|
116
|
+
.rows;
|
|
117
|
+
expectMatch(items, (0, js_lib_1._sortBy)(rows, r => r.id), quirks);
|
|
117
118
|
});
|
|
118
119
|
// QUERY
|
|
119
120
|
if (querying) {
|
|
@@ -204,7 +205,7 @@ function runCommonDBTest(db, features = {}, quirks = {}) {
|
|
|
204
205
|
b1,
|
|
205
206
|
};
|
|
206
207
|
await db.saveBatch(test_model_1.TEST_TABLE, [item]);
|
|
207
|
-
const
|
|
208
|
+
const loaded = (await db.runQuery(queryAll().filterEq('id', item.id))).rows[0];
|
|
208
209
|
const b1Loaded = loaded.b1;
|
|
209
210
|
// console.log({
|
|
210
211
|
// b11: typeof b1,
|
|
@@ -247,7 +248,6 @@ function runCommonDBTest(db, features = {}, quirks = {}) {
|
|
|
247
248
|
});
|
|
248
249
|
}
|
|
249
250
|
if (updateByQuery) {
|
|
250
|
-
// todo: query by ids (same as getByIds)
|
|
251
251
|
test('updateByQuery simple', async () => {
|
|
252
252
|
// cleanup, reset initial data
|
|
253
253
|
await db.deleteByQuery(queryAll());
|
|
@@ -290,8 +290,7 @@ function runCommonDBTest(db, features = {}, quirks = {}) {
|
|
|
290
290
|
if (querying) {
|
|
291
291
|
test('cleanup', async () => {
|
|
292
292
|
// CLEAN UP
|
|
293
|
-
|
|
294
|
-
await db.deleteByIds(test_model_1.TEST_TABLE, rows.map(i => i.id));
|
|
293
|
+
await db.deleteByQuery(queryAll());
|
|
295
294
|
});
|
|
296
295
|
}
|
|
297
296
|
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.commitDBTransactionSimple = exports.mergeDBOperations = void 0;
|
|
4
|
+
const dbQuery_1 = require("../query/dbQuery");
|
|
4
5
|
/**
|
|
5
6
|
* Optimizes the Transaction (list of DBOperations) to do less operations.
|
|
6
7
|
* E.g if you save id1 first and then delete it - this function will turn it into a no-op (self-eliminate).
|
|
@@ -74,7 +75,10 @@ async function commitDBTransactionSimple(db, tx, opt) {
|
|
|
74
75
|
await db.saveBatch(op.table, op.rows, { ...op.opt, ...opt });
|
|
75
76
|
}
|
|
76
77
|
else if (op.type === 'deleteByIds') {
|
|
77
|
-
await db.
|
|
78
|
+
await db.deleteByQuery(dbQuery_1.DBQuery.create(op.table).filter('id', 'in', op.ids), {
|
|
79
|
+
...op.opt,
|
|
80
|
+
...opt,
|
|
81
|
+
});
|
|
78
82
|
}
|
|
79
83
|
else {
|
|
80
84
|
throw new Error(`DBOperation not supported: ${op.type}`);
|
package/package.json
CHANGED
|
@@ -1,10 +1,5 @@
|
|
|
1
1
|
import { Readable } from 'node:stream'
|
|
2
|
-
import {
|
|
3
|
-
JsonSchemaObject,
|
|
4
|
-
JsonSchemaRootObject,
|
|
5
|
-
ObjectWithId,
|
|
6
|
-
StringMap,
|
|
7
|
-
} from '@naturalcycles/js-lib'
|
|
2
|
+
import { JsonSchemaObject, JsonSchemaRootObject, ObjectWithId } from '@naturalcycles/js-lib'
|
|
8
3
|
import { BaseCommonDB } from '../../base.common.db'
|
|
9
4
|
import { CommonDB } from '../../common.db'
|
|
10
5
|
import { CommonDBOptions, DBPatch, RunQueryResult } from '../../db.model'
|
|
@@ -72,81 +67,6 @@ export class CacheDB extends BaseCommonDB implements CommonDB {
|
|
|
72
67
|
}
|
|
73
68
|
}
|
|
74
69
|
|
|
75
|
-
override async getByIds<ROW extends ObjectWithId>(
|
|
76
|
-
table: string,
|
|
77
|
-
ids: ROW['id'][],
|
|
78
|
-
opt: CacheDBSaveOptions<ROW> = {},
|
|
79
|
-
): Promise<ROW[]> {
|
|
80
|
-
const resultMap: StringMap<ROW> = {}
|
|
81
|
-
const missingIds: ROW['id'][] = []
|
|
82
|
-
|
|
83
|
-
if (!opt.skipCache && !this.cfg.skipCache) {
|
|
84
|
-
const results = await this.cfg.cacheDB.getByIds<ROW>(table, ids, opt)
|
|
85
|
-
|
|
86
|
-
results.forEach(r => (resultMap[r.id] = r))
|
|
87
|
-
|
|
88
|
-
missingIds.push(...ids.filter(id => !resultMap[id]))
|
|
89
|
-
|
|
90
|
-
if (this.cfg.logCached) {
|
|
91
|
-
this.cfg.logger?.log(
|
|
92
|
-
`${table}.getByIds ${results.length} rows from cache: [${results
|
|
93
|
-
.map(r => r.id)
|
|
94
|
-
.join(', ')}]`,
|
|
95
|
-
)
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
if (missingIds.length && !opt.onlyCache && !this.cfg.onlyCache) {
|
|
100
|
-
const results = await this.cfg.downstreamDB.getByIds<ROW>(table, missingIds, opt)
|
|
101
|
-
results.forEach(r => (resultMap[r.id] = r))
|
|
102
|
-
|
|
103
|
-
if (this.cfg.logDownstream) {
|
|
104
|
-
this.cfg.logger?.log(
|
|
105
|
-
`${table}.getByIds ${results.length} rows from downstream: [${results
|
|
106
|
-
.map(r => r.id)
|
|
107
|
-
.join(', ')}]`,
|
|
108
|
-
)
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
if (!opt.skipCache) {
|
|
112
|
-
const cacheResult = this.cfg.cacheDB.saveBatch(table, results, opt)
|
|
113
|
-
if (this.cfg.awaitCache) await cacheResult
|
|
114
|
-
}
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
// return in right order
|
|
118
|
-
return ids.map(id => resultMap[id]!).filter(Boolean)
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
override async deleteByIds<ROW extends ObjectWithId>(
|
|
122
|
-
table: string,
|
|
123
|
-
ids: ROW['id'][],
|
|
124
|
-
opt: CacheDBOptions = {},
|
|
125
|
-
): Promise<number> {
|
|
126
|
-
let deletedIds = 0
|
|
127
|
-
|
|
128
|
-
if (!opt.onlyCache && !this.cfg.onlyCache) {
|
|
129
|
-
deletedIds = await this.cfg.downstreamDB.deleteByIds<ROW>(table, ids, opt)
|
|
130
|
-
|
|
131
|
-
if (this.cfg.logDownstream) {
|
|
132
|
-
this.cfg.logger?.log(`${table}.deleteByIds ${deletedIds} rows from downstream`)
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
if (!opt.skipCache && !this.cfg.skipCache) {
|
|
137
|
-
const cacheResult = this.cfg.cacheDB
|
|
138
|
-
.deleteByIds<ROW>(table, ids, opt)
|
|
139
|
-
.then(deletedFromCache => {
|
|
140
|
-
if (this.cfg.logCached) {
|
|
141
|
-
this.cfg.logger?.log(`${table}.deleteByIds ${deletedFromCache} rows from cache`)
|
|
142
|
-
}
|
|
143
|
-
})
|
|
144
|
-
if (this.cfg.awaitCache) await cacheResult
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
return deletedIds
|
|
148
|
-
}
|
|
149
|
-
|
|
150
70
|
override async saveBatch<ROW extends Partial<ObjectWithId>>(
|
|
151
71
|
table: string,
|
|
152
72
|
rows: ROW[],
|
|
@@ -65,15 +65,6 @@ export class FileDB extends BaseCommonDB implements CommonDB {
|
|
|
65
65
|
return tables
|
|
66
66
|
}
|
|
67
67
|
|
|
68
|
-
override async getByIds<ROW extends ObjectWithId>(
|
|
69
|
-
table: string,
|
|
70
|
-
ids: ROW['id'][],
|
|
71
|
-
_opt?: CommonDBOptions,
|
|
72
|
-
): Promise<ROW[]> {
|
|
73
|
-
const byId = _by(await this.loadFile<ROW>(table), r => r.id)
|
|
74
|
-
return ids.map(id => byId[id]!).filter(Boolean)
|
|
75
|
-
}
|
|
76
|
-
|
|
77
68
|
override async saveBatch<ROW extends Partial<ObjectWithId>>(
|
|
78
69
|
table: string,
|
|
79
70
|
rows: ROW[],
|
|
@@ -198,29 +189,6 @@ export class FileDB extends BaseCommonDB implements CommonDB {
|
|
|
198
189
|
return readable
|
|
199
190
|
}
|
|
200
191
|
|
|
201
|
-
override async deleteByIds<ROW extends ObjectWithId>(
|
|
202
|
-
table: string,
|
|
203
|
-
ids: ROW['id'][],
|
|
204
|
-
_opt?: CommonDBOptions,
|
|
205
|
-
): Promise<number> {
|
|
206
|
-
if (!ids.length) return 0
|
|
207
|
-
|
|
208
|
-
let deleted = 0
|
|
209
|
-
const rows = (await this.loadFile<ROW>(table)).filter(r => {
|
|
210
|
-
if (ids.includes(r.id)) {
|
|
211
|
-
deleted++
|
|
212
|
-
return false
|
|
213
|
-
}
|
|
214
|
-
return true
|
|
215
|
-
})
|
|
216
|
-
|
|
217
|
-
if (deleted > 0) {
|
|
218
|
-
await this.saveFile(table, rows)
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
return deleted
|
|
222
|
-
}
|
|
223
|
-
|
|
224
192
|
override async deleteByQuery<ROW extends ObjectWithId>(
|
|
225
193
|
q: DBQuery<ROW>,
|
|
226
194
|
_opt?: CommonDBOptions,
|
|
@@ -143,16 +143,6 @@ export class InMemoryDB implements CommonDB {
|
|
|
143
143
|
}
|
|
144
144
|
}
|
|
145
145
|
|
|
146
|
-
async getByIds<ROW extends ObjectWithId>(
|
|
147
|
-
_table: string,
|
|
148
|
-
ids: ROW['id'][],
|
|
149
|
-
_opt?: CommonDBOptions,
|
|
150
|
-
): Promise<ROW[]> {
|
|
151
|
-
const table = this.cfg.tablesPrefix + _table
|
|
152
|
-
this.data[table] ||= {}
|
|
153
|
-
return ids.map(id => this.data[table]![id] as ROW).filter(Boolean)
|
|
154
|
-
}
|
|
155
|
-
|
|
156
146
|
async saveBatch<ROW extends Partial<ObjectWithId>>(
|
|
157
147
|
_table: string,
|
|
158
148
|
rows: ROW[],
|
|
@@ -184,32 +174,21 @@ export class InMemoryDB implements CommonDB {
|
|
|
184
174
|
})
|
|
185
175
|
}
|
|
186
176
|
|
|
187
|
-
async
|
|
188
|
-
|
|
189
|
-
ids: ROW['id'][],
|
|
177
|
+
async deleteByQuery<ROW extends ObjectWithId>(
|
|
178
|
+
q: DBQuery<ROW>,
|
|
190
179
|
_opt?: CommonDBOptions,
|
|
191
180
|
): Promise<number> {
|
|
192
|
-
const table = this.cfg.tablesPrefix +
|
|
181
|
+
const table = this.cfg.tablesPrefix + q.table
|
|
193
182
|
this.data[table] ||= {}
|
|
194
183
|
let count = 0
|
|
195
|
-
|
|
196
|
-
if (!this.data[table]![id]) return
|
|
197
|
-
delete this.data[table]![id]
|
|
184
|
+
queryInMemory(q, Object.values(this.data[table] || {}) as ROW[]).forEach(r => {
|
|
185
|
+
if (!this.data[table]![r.id]) return
|
|
186
|
+
delete this.data[table]![r.id]
|
|
198
187
|
count++
|
|
199
188
|
})
|
|
200
189
|
return count
|
|
201
190
|
}
|
|
202
191
|
|
|
203
|
-
async deleteByQuery<ROW extends ObjectWithId>(
|
|
204
|
-
q: DBQuery<ROW>,
|
|
205
|
-
_opt?: CommonDBOptions,
|
|
206
|
-
): Promise<number> {
|
|
207
|
-
const table = this.cfg.tablesPrefix + q.table
|
|
208
|
-
const rows = queryInMemory(q, Object.values(this.data[table] || {}) as ROW[])
|
|
209
|
-
const ids = rows.map(r => r.id)
|
|
210
|
-
return await this.deleteByIds(q.table, ids)
|
|
211
|
-
}
|
|
212
|
-
|
|
213
192
|
async updateByQuery<ROW extends ObjectWithId>(
|
|
214
193
|
q: DBQuery<ROW>,
|
|
215
194
|
patch: DBPatch<ROW>,
|
|
@@ -264,7 +243,10 @@ export class InMemoryDB implements CommonDB {
|
|
|
264
243
|
if (op.type === 'saveBatch') {
|
|
265
244
|
await this.saveBatch(op.table, op.rows, { ...op.opt, ...opt })
|
|
266
245
|
} else if (op.type === 'deleteByIds') {
|
|
267
|
-
await this.
|
|
246
|
+
await this.deleteByQuery(DBQuery.create(op.table).filter('id', 'in', op.ids), {
|
|
247
|
+
...op.opt,
|
|
248
|
+
...opt,
|
|
249
|
+
})
|
|
268
250
|
} else {
|
|
269
251
|
throw new Error(`DBOperation not supported: ${(op as any).type}`)
|
|
270
252
|
}
|
|
@@ -19,11 +19,6 @@ const FILTER_FNS: Record<DBQueryFilterOperator, FilterFn> = {
|
|
|
19
19
|
// Important: q.table is not used in this function, so tablesPrefix is not needed.
|
|
20
20
|
// But should be careful here..
|
|
21
21
|
export function queryInMemory<ROW extends ObjectWithId>(q: DBQuery<ROW>, rows: ROW[] = []): ROW[] {
|
|
22
|
-
// .ids
|
|
23
|
-
if (q._ids?.length) {
|
|
24
|
-
rows = rows.filter(r => q._ids!.includes(r.id))
|
|
25
|
-
}
|
|
26
|
-
|
|
27
22
|
// .filter
|
|
28
23
|
// eslint-disable-next-line unicorn/no-array-reduce
|
|
29
24
|
rows = q._filters.reduce((rows, filter) => {
|
package/src/base.common.db.ts
CHANGED
|
@@ -30,11 +30,7 @@ export class BaseCommonDB implements CommonDB {
|
|
|
30
30
|
table: string,
|
|
31
31
|
schema: JsonSchemaObject<ROW>,
|
|
32
32
|
): Promise<void> {
|
|
33
|
-
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
async deleteByIds<ROW extends ObjectWithId>(table: string, ids: ROW['id'][]): Promise<number> {
|
|
37
|
-
throw new Error('deleteByIds is not implemented')
|
|
33
|
+
// no-op
|
|
38
34
|
}
|
|
39
35
|
|
|
40
36
|
async deleteByQuery<ROW extends ObjectWithId>(q: DBQuery<ROW>): Promise<number> {
|
|
@@ -49,10 +45,6 @@ export class BaseCommonDB implements CommonDB {
|
|
|
49
45
|
throw new Error('updateByQuery is not implemented')
|
|
50
46
|
}
|
|
51
47
|
|
|
52
|
-
async getByIds<ROW extends ObjectWithId>(table: string, ids: ROW['id'][]): Promise<ROW[]> {
|
|
53
|
-
throw new Error('getByIds is not implemented')
|
|
54
|
-
}
|
|
55
|
-
|
|
56
48
|
async runQuery<ROW extends ObjectWithId>(q: DBQuery<ROW>): Promise<RunQueryResult<ROW>> {
|
|
57
49
|
throw new Error('runQuery is not implemented')
|
|
58
50
|
}
|
package/src/common.db.ts
CHANGED
|
@@ -43,17 +43,6 @@ export interface CommonDB {
|
|
|
43
43
|
opt?: CommonDBCreateOptions,
|
|
44
44
|
): Promise<void>
|
|
45
45
|
|
|
46
|
-
// GET
|
|
47
|
-
/**
|
|
48
|
-
* Order of items returned is not guaranteed to match order of ids.
|
|
49
|
-
* (Such limitation exists because Datastore doesn't support it).
|
|
50
|
-
*/
|
|
51
|
-
getByIds<ROW extends ObjectWithId>(
|
|
52
|
-
table: string,
|
|
53
|
-
ids: ROW['id'][],
|
|
54
|
-
opt?: CommonDBOptions,
|
|
55
|
-
): Promise<ROW[]>
|
|
56
|
-
|
|
57
46
|
// QUERY
|
|
58
47
|
/**
|
|
59
48
|
* Order by 'id' is not supported by all implementations (for example, Datastore doesn't support it).
|
|
@@ -85,12 +74,6 @@ export interface CommonDB {
|
|
|
85
74
|
* Returns number of deleted items.
|
|
86
75
|
* Not supported by all implementations (e.g Datastore will always return same number as number of ids).
|
|
87
76
|
*/
|
|
88
|
-
deleteByIds<ROW extends ObjectWithId>(
|
|
89
|
-
table: string,
|
|
90
|
-
ids: ROW['id'][],
|
|
91
|
-
opt?: CommonDBOptions,
|
|
92
|
-
): Promise<number>
|
|
93
|
-
|
|
94
77
|
deleteByQuery<ROW extends ObjectWithId>(q: DBQuery<ROW>, opt?: CommonDBOptions): Promise<number>
|
|
95
78
|
|
|
96
79
|
/**
|
|
@@ -134,14 +134,17 @@ export class CommonDao<
|
|
|
134
134
|
|
|
135
135
|
if (opt.timeout) {
|
|
136
136
|
// todo: possibly remove it after debugging is done
|
|
137
|
-
dbm = (
|
|
138
|
-
|
|
137
|
+
dbm = await pTimeout(
|
|
138
|
+
async () => {
|
|
139
|
+
return (await this.cfg.db.runQuery(DBQuery.create<DBM>(table).filterEq('id', id))).rows[0]
|
|
140
|
+
},
|
|
141
|
+
{
|
|
139
142
|
timeout: opt.timeout,
|
|
140
143
|
name: `getById(${table})`,
|
|
141
|
-
}
|
|
142
|
-
)
|
|
144
|
+
},
|
|
145
|
+
)
|
|
143
146
|
} else {
|
|
144
|
-
dbm = (await this.cfg.db.
|
|
147
|
+
dbm = (await this.cfg.db.runQuery(DBQuery.create<DBM>(table).filterEq('id', id))).rows[0]
|
|
145
148
|
}
|
|
146
149
|
|
|
147
150
|
const bm = opt.raw ? (dbm as any) : await this.dbmToBM(dbm, opt)
|
|
@@ -171,7 +174,7 @@ export class CommonDao<
|
|
|
171
174
|
const op = `getByIdAsDBM(${id})`
|
|
172
175
|
const table = opt.table || this.cfg.table
|
|
173
176
|
const started = this.logStarted(op, table)
|
|
174
|
-
let [dbm] = await this.cfg.db.
|
|
177
|
+
let [dbm] = (await this.cfg.db.runQuery(DBQuery.create<DBM>(table).filterEq('id', id))).rows
|
|
175
178
|
if (!opt.raw) {
|
|
176
179
|
dbm = this.anyToDBM(dbm!, opt)
|
|
177
180
|
}
|
|
@@ -186,7 +189,7 @@ export class CommonDao<
|
|
|
186
189
|
const op = `getByIdAsTM(${id})`
|
|
187
190
|
const table = opt.table || this.cfg.table
|
|
188
191
|
const started = this.logStarted(op, table)
|
|
189
|
-
const [dbm] = await this.cfg.db.
|
|
192
|
+
const [dbm] = (await this.cfg.db.runQuery(DBQuery.create<DBM>(table).filterEq('id', id))).rows
|
|
190
193
|
if (opt.raw) {
|
|
191
194
|
this.logResult(started, op, dbm, table)
|
|
192
195
|
return (dbm as any) || null
|
|
@@ -201,7 +204,7 @@ export class CommonDao<
|
|
|
201
204
|
const op = `getByIds ${ids.length} id(s) (${_truncate(ids.slice(0, 10).join(', '), 50)})`
|
|
202
205
|
const table = opt.table || this.cfg.table
|
|
203
206
|
const started = this.logStarted(op, table)
|
|
204
|
-
const dbms = await this.cfg.db.
|
|
207
|
+
const dbms = (await this.cfg.db.runQuery(DBQuery.create<DBM>(table).filterIn('id', ids))).rows
|
|
205
208
|
const bms = opt.raw ? (dbms as any) : await this.dbmsToBM(dbms, opt)
|
|
206
209
|
this.logResult(started, op, bms, table)
|
|
207
210
|
return bms
|
|
@@ -211,7 +214,7 @@ export class CommonDao<
|
|
|
211
214
|
const op = `getByIdsAsDBM ${ids.length} id(s) (${_truncate(ids.slice(0, 10).join(', '), 50)})`
|
|
212
215
|
const table = opt.table || this.cfg.table
|
|
213
216
|
const started = this.logStarted(op, table)
|
|
214
|
-
const dbms = await this.cfg.db.
|
|
217
|
+
const dbms = (await this.cfg.db.runQuery(DBQuery.create<DBM>(table).filterIn('id', ids))).rows
|
|
215
218
|
this.logResult(started, op, dbms, table)
|
|
216
219
|
return dbms
|
|
217
220
|
}
|
|
@@ -267,7 +270,8 @@ export class CommonDao<
|
|
|
267
270
|
|
|
268
271
|
private async ensureUniqueId(table: string, dbm: DBM): Promise<void> {
|
|
269
272
|
// todo: retry N times
|
|
270
|
-
const existing = await this.cfg.db.
|
|
273
|
+
const existing = (await this.cfg.db.runQuery(DBQuery.create<DBM>(table).filterEq('id', dbm.id)))
|
|
274
|
+
.rows
|
|
271
275
|
if (existing.length) {
|
|
272
276
|
throw new AppError(DBLibError.NON_UNIQUE_ID, {
|
|
273
277
|
table,
|
|
@@ -869,9 +873,9 @@ export class CommonDao<
|
|
|
869
873
|
const op = `deleteById(${id})`
|
|
870
874
|
const table = opt.table || this.cfg.table
|
|
871
875
|
const started = this.logStarted(op, table)
|
|
872
|
-
const
|
|
876
|
+
const count = await this.cfg.db.deleteByQuery(DBQuery.create(table).filterEq('id', id))
|
|
873
877
|
this.logSaveResult(started, op, table)
|
|
874
|
-
return
|
|
878
|
+
return count
|
|
875
879
|
}
|
|
876
880
|
|
|
877
881
|
async deleteByIds(ids: ID[], opt: CommonDaoOptions = {}): Promise<number> {
|
|
@@ -880,9 +884,9 @@ export class CommonDao<
|
|
|
880
884
|
const op = `deleteByIds(${ids.join(', ')})`
|
|
881
885
|
const table = opt.table || this.cfg.table
|
|
882
886
|
const started = this.logStarted(op, table)
|
|
883
|
-
const
|
|
887
|
+
const count = await this.cfg.db.deleteByQuery(DBQuery.create(table).filterIn('id', ids))
|
|
884
888
|
this.logSaveResult(started, op, table)
|
|
885
|
-
return
|
|
889
|
+
return count
|
|
886
890
|
}
|
|
887
891
|
|
|
888
892
|
/**
|
|
@@ -912,7 +916,10 @@ export class CommonDao<
|
|
|
912
916
|
transformBuffer<string>({ batchSize }),
|
|
913
917
|
transformMap<string[], void>(
|
|
914
918
|
async ids => {
|
|
915
|
-
deleted += await this.cfg.db.
|
|
919
|
+
deleted += await this.cfg.db.deleteByQuery(
|
|
920
|
+
DBQuery.create(q.table).filterIn('id', ids),
|
|
921
|
+
opt,
|
|
922
|
+
)
|
|
916
923
|
},
|
|
917
924
|
{
|
|
918
925
|
predicate: _passthroughPredicate,
|
|
@@ -936,11 +943,11 @@ export class CommonDao<
|
|
|
936
943
|
}
|
|
937
944
|
|
|
938
945
|
async updateById(id: ID, patch: DBPatch<DBM>, opt: CommonDaoOptions = {}): Promise<number> {
|
|
939
|
-
return await this.updateByQuery(this.query().
|
|
946
|
+
return await this.updateByQuery(this.query().filterEq('id', id), patch, opt)
|
|
940
947
|
}
|
|
941
948
|
|
|
942
949
|
async updateByIds(ids: ID[], patch: DBPatch<DBM>, opt: CommonDaoOptions = {}): Promise<number> {
|
|
943
|
-
return await this.updateByQuery(this.query().
|
|
950
|
+
return await this.updateByQuery(this.query().filterIn('id', ids), patch, opt)
|
|
944
951
|
}
|
|
945
952
|
|
|
946
953
|
async updateByQuery(
|
package/src/query/dbQuery.ts
CHANGED
|
@@ -113,7 +113,6 @@ export class DBQuery<ROW extends ObjectWithId = AnyObjectWithId> {
|
|
|
113
113
|
_selectedFieldNames?: (keyof ROW)[]
|
|
114
114
|
_groupByFieldNames?: (keyof ROW)[]
|
|
115
115
|
_distinct = false
|
|
116
|
-
_ids?: ROW['id'][]
|
|
117
116
|
|
|
118
117
|
filter(name: keyof ROW, op: DBQueryFilterOperator, val: any): this {
|
|
119
118
|
this._filters.push({ name, op, val })
|
|
@@ -125,6 +124,11 @@ export class DBQuery<ROW extends ObjectWithId = AnyObjectWithId> {
|
|
|
125
124
|
return this
|
|
126
125
|
}
|
|
127
126
|
|
|
127
|
+
filterIn(name: keyof ROW, val: any[]): this {
|
|
128
|
+
this._filters.push({ name, op: 'in', val })
|
|
129
|
+
return this
|
|
130
|
+
}
|
|
131
|
+
|
|
128
132
|
limit(limit: number): this {
|
|
129
133
|
this._limitValue = limit
|
|
130
134
|
return this
|
|
@@ -168,28 +172,6 @@ export class DBQuery<ROW extends ObjectWithId = AnyObjectWithId> {
|
|
|
168
172
|
return this
|
|
169
173
|
}
|
|
170
174
|
|
|
171
|
-
/**
|
|
172
|
-
* Allows to query by ids (one or many).
|
|
173
|
-
* Similar to:
|
|
174
|
-
* SELECT * FROM table where id in (a, b, c)
|
|
175
|
-
* or (if only 1 id is passed)
|
|
176
|
-
* SELECT * FROM table where id = a
|
|
177
|
-
*/
|
|
178
|
-
byIds(ids: ROW['id'][]): this {
|
|
179
|
-
this._ids = ids
|
|
180
|
-
return this
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
/**
|
|
184
|
-
* Allows to query by id.
|
|
185
|
-
* Similar to:
|
|
186
|
-
* SELECT * FROM table where id = a
|
|
187
|
-
*/
|
|
188
|
-
byId(id: ROW['id']): this {
|
|
189
|
-
this._ids = [id]
|
|
190
|
-
return this
|
|
191
|
-
}
|
|
192
|
-
|
|
193
175
|
clone(): DBQuery<ROW> {
|
|
194
176
|
return _objectAssign(new DBQuery<ROW>(this.table), {
|
|
195
177
|
_filters: [...this._filters],
|
|
@@ -201,7 +183,6 @@ export class DBQuery<ROW extends ObjectWithId = AnyObjectWithId> {
|
|
|
201
183
|
_distinct: this._distinct,
|
|
202
184
|
_startCursor: this._startCursor,
|
|
203
185
|
_endCursor: this._endCursor,
|
|
204
|
-
_ids: this._ids,
|
|
205
186
|
})
|
|
206
187
|
}
|
|
207
188
|
|
|
@@ -222,14 +203,6 @@ export class DBQuery<ROW extends ObjectWithId = AnyObjectWithId> {
|
|
|
222
203
|
)
|
|
223
204
|
}
|
|
224
205
|
|
|
225
|
-
if (this._ids?.length) {
|
|
226
|
-
if (this._ids.length === 1) {
|
|
227
|
-
tokens.push(`id=${this._ids[0]}`)
|
|
228
|
-
} else {
|
|
229
|
-
tokens.push(`ids in (${this._ids.join(',')})`)
|
|
230
|
-
}
|
|
231
|
-
}
|
|
232
|
-
|
|
233
206
|
tokens.push(
|
|
234
207
|
...this._filters.map(f => `${f.name as string}${f.op}${f.val}`),
|
|
235
208
|
...this._orders.map(o => `order by ${o.name as string}${o.descending ? ' desc' : ''}`),
|
package/src/testing/daoTest.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { pDelay, _deepCopy, _pick, _sortBy, _omit, localTime } from '@naturalcycles/js-lib'
|
|
2
2
|
import { readableToArray, transformNoOp } from '@naturalcycles/nodejs-lib'
|
|
3
|
-
import { CommonDaoLogLevel } from '..'
|
|
3
|
+
import { CommonDaoLogLevel, DBQuery } from '..'
|
|
4
4
|
import { CommonDB } from '../common.db'
|
|
5
5
|
import { CommonDao } from '../commondao/common.dao'
|
|
6
6
|
import { CommonDBImplementationFeatures, CommonDBImplementationQuirks, expectMatch } from './dbTest'
|
|
@@ -75,9 +75,12 @@ export function runCommonDaoTest(
|
|
|
75
75
|
// DELETE ALL initially
|
|
76
76
|
test('deleteByIds test items', async () => {
|
|
77
77
|
const rows = await dao.query().select(['id']).runQuery()
|
|
78
|
-
await db.
|
|
79
|
-
TEST_TABLE
|
|
80
|
-
|
|
78
|
+
await db.deleteByQuery(
|
|
79
|
+
DBQuery.create(TEST_TABLE).filter(
|
|
80
|
+
'id',
|
|
81
|
+
'in',
|
|
82
|
+
rows.map(r => r.id),
|
|
83
|
+
),
|
|
81
84
|
)
|
|
82
85
|
})
|
|
83
86
|
|
|
@@ -156,7 +159,11 @@ export function runCommonDaoTest(
|
|
|
156
159
|
// GET not empty
|
|
157
160
|
test('getByIds all items', async () => {
|
|
158
161
|
const rows = await dao.getByIds(items.map(i => i.id).concat('abcd'))
|
|
159
|
-
expectMatch(
|
|
162
|
+
expectMatch(
|
|
163
|
+
expectedItems,
|
|
164
|
+
_sortBy(rows, r => r.id),
|
|
165
|
+
quirks,
|
|
166
|
+
)
|
|
160
167
|
})
|
|
161
168
|
|
|
162
169
|
// QUERY
|
|
@@ -258,11 +265,7 @@ export function runCommonDaoTest(
|
|
|
258
265
|
|
|
259
266
|
test('cleanup', async () => {
|
|
260
267
|
// CLEAN UP
|
|
261
|
-
|
|
262
|
-
await db.deleteByIds(
|
|
263
|
-
TEST_TABLE,
|
|
264
|
-
rows.map(i => i.id),
|
|
265
|
-
)
|
|
268
|
+
await dao.query().deleteByQuery()
|
|
266
269
|
})
|
|
267
270
|
}
|
|
268
271
|
|
package/src/testing/dbTest.ts
CHANGED
|
@@ -129,9 +129,11 @@ export function runCommonDBTest(
|
|
|
129
129
|
// DELETE ALL initially
|
|
130
130
|
test('deleteByIds test items', async () => {
|
|
131
131
|
const { rows } = await db.runQuery(queryAll().select(['id']))
|
|
132
|
-
await db.
|
|
133
|
-
|
|
134
|
-
|
|
132
|
+
await db.deleteByQuery(
|
|
133
|
+
queryAll().filterIn(
|
|
134
|
+
'id',
|
|
135
|
+
rows.map(i => i.id),
|
|
136
|
+
),
|
|
135
137
|
)
|
|
136
138
|
})
|
|
137
139
|
|
|
@@ -145,17 +147,17 @@ export function runCommonDBTest(
|
|
|
145
147
|
|
|
146
148
|
// GET empty
|
|
147
149
|
test('getByIds(item1.id) should return empty', async () => {
|
|
148
|
-
const [item1Loaded] = await db.
|
|
150
|
+
const [item1Loaded] = (await db.runQuery(queryAll().filterEq('id', item1.id))).rows
|
|
149
151
|
// console.log(a)
|
|
150
152
|
expect(item1Loaded).toBeUndefined()
|
|
151
153
|
})
|
|
152
154
|
|
|
153
155
|
test('getByIds([]) should return []', async () => {
|
|
154
|
-
expect(await db.
|
|
156
|
+
expect((await db.runQuery(queryAll().filterIn('id', []))).rows).toEqual([])
|
|
155
157
|
})
|
|
156
158
|
|
|
157
159
|
test('getByIds(...) should return empty', async () => {
|
|
158
|
-
expect(await db.
|
|
160
|
+
expect((await db.runQuery(queryAll().filterIn('id', ['abc', 'abcd']))).rows).toEqual([])
|
|
159
161
|
})
|
|
160
162
|
|
|
161
163
|
// SAVE
|
|
@@ -167,7 +169,7 @@ export function runCommonDBTest(
|
|
|
167
169
|
}
|
|
168
170
|
deepFreeze(item3)
|
|
169
171
|
await db.saveBatch(TEST_TABLE, [item3])
|
|
170
|
-
const item3Loaded = (await db.
|
|
172
|
+
const item3Loaded = (await db.runQuery(queryAll().filterEq('id', item3.id))).rows[0]!
|
|
171
173
|
expectMatch([item3], [item3Loaded], quirks)
|
|
172
174
|
expect(item3Loaded.k2).toBeNull()
|
|
173
175
|
})
|
|
@@ -184,7 +186,7 @@ export function runCommonDBTest(
|
|
|
184
186
|
delete expected.k2
|
|
185
187
|
|
|
186
188
|
await db.saveBatch(TEST_TABLE, [item3])
|
|
187
|
-
const item3Loaded = (await db.
|
|
189
|
+
const item3Loaded = (await db.runQuery(queryAll().filterEq('id', item3.id))).rows[0]!
|
|
188
190
|
expectMatch([expected], [item3Loaded], quirks)
|
|
189
191
|
expect(item3Loaded.k2).toBeUndefined()
|
|
190
192
|
expect(Object.keys(item3Loaded)).not.toContain('k2')
|
|
@@ -219,8 +221,13 @@ export function runCommonDBTest(
|
|
|
219
221
|
|
|
220
222
|
// GET not empty
|
|
221
223
|
test('getByIds all items', async () => {
|
|
222
|
-
const rows = await db.
|
|
223
|
-
|
|
224
|
+
const rows = (await db.runQuery(queryAll().filterIn('id', items.map(i => i.id).concat('abcd'))))
|
|
225
|
+
.rows
|
|
226
|
+
expectMatch(
|
|
227
|
+
items,
|
|
228
|
+
_sortBy(rows, r => r.id),
|
|
229
|
+
quirks,
|
|
230
|
+
)
|
|
224
231
|
})
|
|
225
232
|
|
|
226
233
|
// QUERY
|
|
@@ -340,8 +347,8 @@ export function runCommonDBTest(
|
|
|
340
347
|
b1,
|
|
341
348
|
}
|
|
342
349
|
await db.saveBatch(TEST_TABLE, [item])
|
|
343
|
-
const
|
|
344
|
-
const b1Loaded = loaded
|
|
350
|
+
const loaded = (await db.runQuery(queryAll().filterEq('id', item.id))).rows[0]!
|
|
351
|
+
const b1Loaded = loaded.b1!
|
|
345
352
|
// console.log({
|
|
346
353
|
// b11: typeof b1,
|
|
347
354
|
// b12: typeof b1Loaded,
|
|
@@ -391,7 +398,6 @@ export function runCommonDBTest(
|
|
|
391
398
|
}
|
|
392
399
|
|
|
393
400
|
if (updateByQuery) {
|
|
394
|
-
// todo: query by ids (same as getByIds)
|
|
395
401
|
test('updateByQuery simple', async () => {
|
|
396
402
|
// cleanup, reset initial data
|
|
397
403
|
await db.deleteByQuery(queryAll())
|
|
@@ -445,11 +451,7 @@ export function runCommonDBTest(
|
|
|
445
451
|
if (querying) {
|
|
446
452
|
test('cleanup', async () => {
|
|
447
453
|
// CLEAN UP
|
|
448
|
-
|
|
449
|
-
await db.deleteByIds(
|
|
450
|
-
TEST_TABLE,
|
|
451
|
-
rows.map(i => i.id),
|
|
452
|
-
)
|
|
454
|
+
await db.deleteByQuery(queryAll())
|
|
453
455
|
})
|
|
454
456
|
}
|
|
455
457
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { CommonDB } from '../common.db'
|
|
2
2
|
import { CommonDBSaveOptions, DBOperation } from '../db.model'
|
|
3
|
+
import { DBQuery } from '../query/dbQuery'
|
|
3
4
|
import { DBTransaction } from './dbTransaction'
|
|
4
5
|
|
|
5
6
|
/**
|
|
@@ -80,7 +81,10 @@ export async function commitDBTransactionSimple(
|
|
|
80
81
|
if (op.type === 'saveBatch') {
|
|
81
82
|
await db.saveBatch(op.table, op.rows, { ...op.opt, ...opt })
|
|
82
83
|
} else if (op.type === 'deleteByIds') {
|
|
83
|
-
await db.
|
|
84
|
+
await db.deleteByQuery(DBQuery.create(op.table).filter('id', 'in', op.ids), {
|
|
85
|
+
...op.opt,
|
|
86
|
+
...opt,
|
|
87
|
+
})
|
|
84
88
|
} else {
|
|
85
89
|
throw new Error(`DBOperation not supported: ${(op as any).type}`)
|
|
86
90
|
}
|