@naturalcycles/db-lib 9.21.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.
Files changed (35) hide show
  1. package/dist/adapter/cachedb/cache.db.d.ts +2 -2
  2. package/dist/adapter/cachedb/cache.db.js +4 -3
  3. package/dist/adapter/file/file.db.js +2 -1
  4. package/dist/adapter/inmemory/inMemory.db.d.ts +7 -6
  5. package/dist/adapter/inmemory/inMemory.db.js +15 -13
  6. package/dist/adapter/inmemory/inMemoryKeyValueDB.d.ts +1 -0
  7. package/dist/adapter/inmemory/inMemoryKeyValueDB.js +13 -0
  8. package/dist/base.common.db.d.ts +4 -3
  9. package/dist/base.common.db.js +5 -2
  10. package/dist/common.db.d.ts +23 -14
  11. package/dist/common.db.js +2 -2
  12. package/dist/commondao/common.dao.d.ts +16 -5
  13. package/dist/commondao/common.dao.js +37 -8
  14. package/dist/db.model.d.ts +0 -13
  15. package/dist/db.model.js +1 -17
  16. package/dist/kv/commonKeyValueDB.d.ts +16 -2
  17. package/dist/query/dbQuery.d.ts +2 -2
  18. package/dist/query/dbQuery.js +2 -2
  19. package/dist/testing/daoTest.js +26 -0
  20. package/dist/testing/dbTest.js +21 -23
  21. package/dist/testing/keyValueDBTest.js +15 -3
  22. package/package.json +1 -1
  23. package/src/adapter/cachedb/cache.db.ts +6 -5
  24. package/src/adapter/file/file.db.ts +2 -1
  25. package/src/adapter/inmemory/inMemory.db.ts +29 -18
  26. package/src/adapter/inmemory/inMemoryKeyValueDB.ts +17 -1
  27. package/src/base.common.db.ts +18 -5
  28. package/src/common.db.ts +36 -17
  29. package/src/commondao/common.dao.ts +46 -11
  30. package/src/db.model.ts +0 -19
  31. package/src/kv/commonKeyValueDB.ts +17 -2
  32. package/src/query/dbQuery.ts +2 -3
  33. package/src/testing/daoTest.ts +28 -0
  34. package/src/testing/dbTest.ts +22 -28
  35. package/src/testing/keyValueDBTest.ts +17 -3
@@ -86,17 +86,29 @@ function runCommonKeyValueDBTest(db) {
86
86
  expect(results).toEqual([]);
87
87
  });
88
88
  if (support.increment) {
89
+ const id = 'nonExistingField';
90
+ const id2 = 'nonExistingField2';
89
91
  test('increment on a non-existing field should set the value to 1', async () => {
90
- const result = await db.increment(test_model_1.TEST_TABLE, 'nonExistingField');
92
+ const result = await db.increment(test_model_1.TEST_TABLE, id);
91
93
  expect(result).toBe(1);
92
94
  });
93
95
  test('increment on a existing field should increase the value by one', async () => {
94
- const result = await db.increment(test_model_1.TEST_TABLE, 'nonExistingField');
96
+ const result = await db.increment(test_model_1.TEST_TABLE, id);
95
97
  expect(result).toBe(2);
96
98
  });
97
99
  test('increment should increase the value by the specified amount', async () => {
98
- const result = await db.increment(test_model_1.TEST_TABLE, 'nonExistingField', 2);
100
+ const result = await db.increment(test_model_1.TEST_TABLE, id, 2);
99
101
  expect(result).toBe(4);
100
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
+ });
101
113
  }
102
114
  }
package/package.json CHANGED
@@ -45,7 +45,7 @@
45
45
  "engines": {
46
46
  "node": ">=20.13"
47
47
  },
48
- "version": "9.21.0",
48
+ "version": "9.22.0",
49
49
  "description": "Lowest Common Denominator API to supported Databases",
50
50
  "keywords": [
51
51
  "db",
@@ -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 { DBPatch, RunQueryResult } from '../../db.model'
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 updateByQuery<ROW extends ObjectWithId>(
275
+ override async patchByQuery<ROW extends ObjectWithId>(
275
276
  q: DBQuery<ROW>,
276
- patch: DBPatch<ROW>,
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.updateByQuery(q, patch, opt)
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.updateByQuery(q, patch, opt)
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
- updateByQuery: false,
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<ObjectWithId>> = {}
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 updateByQuery<ROW extends ObjectWithId>(
237
+ async patchByQuery<ROW extends ObjectWithId>(
237
238
  q: DBQuery<ROW>,
238
- patch: DBPatch<ROW>,
239
+ patch: Partial<ROW>,
239
240
  ): Promise<number> {
240
- const patchEntries = Object.entries(patch)
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: any) => {
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,5 +1,5 @@
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
5
  import {
@@ -29,6 +29,7 @@ export class InMemoryKeyValueDB implements CommonKeyValueDB {
29
29
  ids.forEach(id => delete this.data[table]![id])
30
30
  }
31
31
 
32
+ // todo: but should we work with Tuples or Objects?
32
33
  async getByIds(table: string, ids: string[]): Promise<KeyValueDBTuple[]> {
33
34
  this.data[table] ||= {}
34
35
  return ids.map(id => [id, this.data[table]![id]!] as KeyValueDBTuple).filter(e => e[1])
@@ -65,4 +66,19 @@ export class InMemoryKeyValueDB implements CommonKeyValueDB {
65
66
 
66
67
  return newValue
67
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
+ }
68
84
  }
@@ -1,11 +1,15 @@
1
- import { JsonSchemaObject, JsonSchemaRootObject, ObjectWithId } from '@naturalcycles/js-lib'
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 updateByQuery<ROW extends ObjectWithId>(
57
+ async patchByQuery<ROW extends ObjectWithId>(
54
58
  _q: DBQuery<ROW>,
55
- _patch: DBPatch<ROW>,
59
+ _patch: Partial<ROW>,
56
60
  _opt?: CommonDBOptions,
57
61
  ): Promise<number> {
58
- throw new Error('updateByQuery is not implemented')
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 { JsonSchemaObject, JsonSchemaRootObject, ObjectWithId } from '@naturalcycles/js-lib'
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'
@@ -116,7 +120,7 @@ export interface CommonDB {
116
120
  ) => Promise<number>
117
121
 
118
122
  /**
119
- * Applies patch to the rows returned by the query.
123
+ * Applies patch to all the rows that are matched by the query.
120
124
  *
121
125
  * Example:
122
126
  *
@@ -124,18 +128,11 @@ export interface CommonDB {
124
128
  *
125
129
  * patch would be { A: 'B' } for that query.
126
130
  *
127
- * Supports "increment query", example:
128
- *
129
- * UPDATE table SET A = A + 1
130
- *
131
- * In that case patch would look like:
132
- * { A: DBIncrement(1) }
133
- *
134
- * Returns number of rows affected.
131
+ * Returns the number of rows affected.
135
132
  */
136
- updateByQuery: <ROW extends ObjectWithId>(
133
+ patchByQuery: <ROW extends ObjectWithId>(
137
134
  q: DBQuery<ROW>,
138
- patch: DBPatch<ROW>,
135
+ patch: Partial<ROW>,
139
136
  opt?: CommonDBOptions,
140
137
  ) => Promise<number>
141
138
 
@@ -152,6 +149,28 @@ export interface CommonDB {
152
149
  * unless specified as readOnly in CommonDBTransactionOptions.
153
150
  */
154
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>>
155
174
  }
156
175
 
157
176
  /**
@@ -165,8 +184,8 @@ export interface CommonDBSupport {
165
184
  dbQuerySelectFields?: boolean
166
185
  insertSaveMethod?: boolean
167
186
  updateSaveMethod?: boolean
168
- updateByQuery?: boolean
169
- dbIncrement?: boolean
187
+ patchByQuery?: boolean
188
+ increment?: boolean
170
189
  createTable?: boolean
171
190
  tableSchemas?: boolean
172
191
  streaming?: boolean
@@ -183,8 +202,8 @@ export const commonDBFullSupport: CommonDBSupport = {
183
202
  dbQuerySelectFields: true,
184
203
  insertSaveMethod: true,
185
204
  updateSaveMethod: true,
186
- updateByQuery: true,
187
- dbIncrement: true,
205
+ patchByQuery: true,
206
+ increment: true,
188
207
  createTable: true,
189
208
  tableSchemas: true,
190
209
  streaming: true,
@@ -22,6 +22,7 @@ import {
22
22
  ObjectWithId,
23
23
  pMap,
24
24
  SKIP,
25
+ StringMap,
25
26
  UnixTimestampMillisNumber,
26
27
  Unsaved,
27
28
  ZodSchema,
@@ -44,7 +45,7 @@ import {
44
45
  writableVoid,
45
46
  } from '@naturalcycles/nodejs-lib'
46
47
  import { DBLibError } from '../cnst'
47
- import { CommonDBTransactionOptions, DBPatch, DBTransaction, RunQueryResult } from '../db.model'
48
+ import { CommonDBTransactionOptions, DBTransaction, RunQueryResult } from '../db.model'
48
49
  import { DBQuery, RunnableDBQuery } from '../query/dbQuery'
49
50
  import {
50
51
  CommonDaoCfg,
@@ -1068,31 +1069,65 @@ export class CommonDao<BM extends BaseDBEntity, DBM extends BaseDBEntity = BM, I
1068
1069
  return deleted
1069
1070
  }
1070
1071
 
1071
- async updateById(id: ID, patch: DBPatch<DBM>, opt: CommonDaoOptions = {}): Promise<number> {
1072
- return await this.updateByQuery(this.query().filterEq('id', id), patch, opt)
1073
- }
1074
-
1075
- async updateByIds(ids: ID[], patch: DBPatch<DBM>, opt: CommonDaoOptions = {}): Promise<number> {
1072
+ async patchByIds(ids: ID[], patch: Partial<DBM>, opt: CommonDaoOptions = {}): Promise<number> {
1076
1073
  if (!ids.length) return 0
1077
- return await this.updateByQuery(this.query().filterIn('id', ids), patch, opt)
1074
+ return await this.patchByQuery(this.query().filterIn('id', ids), patch, opt)
1078
1075
  }
1079
1076
 
1080
- async updateByQuery(
1077
+ async patchByQuery(
1081
1078
  q: DBQuery<DBM>,
1082
- patch: DBPatch<DBM>,
1079
+ patch: Partial<DBM>,
1083
1080
  opt: CommonDaoOptions = {},
1084
1081
  ): Promise<number> {
1085
1082
  this.validateQueryIndexes(q) // throws if query uses `excludeFromIndexes` property
1086
1083
  this.requireWriteAccess()
1087
1084
  this.requireObjectMutability(opt)
1088
1085
  q.table = opt.table || q.table
1089
- const op = `updateByQuery(${q.pretty()})`
1086
+ const op = `patchByQuery(${q.pretty()})`
1090
1087
  const started = this.logStarted(op, q.table)
1091
- const updated = await this.cfg.db.updateByQuery(q, patch, opt)
1088
+ const updated = await this.cfg.db.patchByQuery(q, patch, opt)
1092
1089
  this.logSaveResult(started, op, q.table)
1093
1090
  return updated
1094
1091
  }
1095
1092
 
1093
+ /**
1094
+ * Caveat: it doesn't update created/updated props.
1095
+ *
1096
+ * @experimental
1097
+ */
1098
+ async increment(prop: keyof DBM, id: ID, by = 1, opt: CommonDaoOptions = {}): Promise<number> {
1099
+ this.requireWriteAccess()
1100
+ this.requireObjectMutability(opt)
1101
+ const { table } = this.cfg
1102
+ const op = `increment`
1103
+ const started = this.logStarted(op, table)
1104
+ const result = await this.cfg.db.incrementBatch(table, prop as string, {
1105
+ [id as string]: by,
1106
+ })
1107
+ this.logSaveResult(started, op, table)
1108
+ return result[id as string]!
1109
+ }
1110
+
1111
+ /**
1112
+ * Caveat: it doesn't update created/updated props.
1113
+ *
1114
+ * @experimental
1115
+ */
1116
+ async incrementBatch(
1117
+ prop: keyof DBM,
1118
+ incrementMap: StringMap<number>,
1119
+ opt: CommonDaoOptions = {},
1120
+ ): Promise<StringMap<number>> {
1121
+ this.requireWriteAccess()
1122
+ this.requireObjectMutability(opt)
1123
+ const { table } = this.cfg
1124
+ const op = `incrementBatch`
1125
+ const started = this.logStarted(op, table)
1126
+ const result = await this.cfg.db.incrementBatch(table, prop as string, incrementMap)
1127
+ this.logSaveResult(started, op, table)
1128
+ return result
1129
+ }
1130
+
1096
1131
  // CONVERSIONS
1097
1132
 
1098
1133
  async dbmToBM(_dbm: undefined, opt?: CommonDaoOptions): Promise<undefined>
package/src/db.model.ts CHANGED
@@ -113,22 +113,3 @@ export enum DBModelType {
113
113
  DBM = 'DBM',
114
114
  BM = 'BM',
115
115
  }
116
-
117
- /**
118
- * Allows to construct a query similar to:
119
- *
120
- * UPDATE table SET A = A + 1
121
- *
122
- * In this case DBIncement.of(1) will be needed.
123
- */
124
- export class DBIncrement {
125
- private constructor(public amount: number) {}
126
-
127
- static of(amount: number): DBIncrement {
128
- return new DBIncrement(amount)
129
- }
130
- }
131
-
132
- export type DBPatch<ROW extends ObjectWithId> = Partial<
133
- Record<keyof ROW, ROW[keyof ROW] | DBIncrement>
134
- >
@@ -1,4 +1,4 @@
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
4
 
@@ -46,13 +46,28 @@ export interface CommonKeyValueDB {
46
46
  count: (table: string) => Promise<number>
47
47
 
48
48
  /**
49
- *
50
49
  * Increments the value of a key in a table by a given amount.
51
50
  * Default increment is 1 when `by` is not provided.
52
51
  *
53
52
  * Returns the new value.
53
+ *
54
+ * @experimental
54
55
  */
55
56
  increment: (table: string, id: string, by?: number) => Promise<number>
57
+
58
+ /**
59
+ * Perform a batch of Increment operations.
60
+ * Given incrementMap, increment each key of it by the given amount (value of the map).
61
+ *
62
+ * Example:
63
+ * { key1: 2, key2: 3 }
64
+ * would increment `key1` by 2, and `key2` by 3.
65
+ *
66
+ * Returns the incrementMap with the same keys and updated values.
67
+ *
68
+ * @experimental
69
+ */
70
+ incrementBatch: (table: string, incrementMap: StringMap<number>) => Promise<StringMap<number>>
56
71
  }
57
72
 
58
73
  export type KeyValueDBTuple = [key: string, value: Buffer]
@@ -11,7 +11,6 @@ import {
11
11
  CommonDaoStreamDeleteOptions,
12
12
  CommonDaoStreamForEachOptions,
13
13
  CommonDaoStreamOptions,
14
- DBPatch,
15
14
  } from '..'
16
15
  import { CommonDao } from '../commondao/common.dao'
17
16
  import { RunQueryResult } from '../db.model'
@@ -276,8 +275,8 @@ export class RunnableDBQuery<
276
275
  return await this.dao.runQueryCount(this, opt)
277
276
  }
278
277
 
279
- async updateByQuery(patch: DBPatch<DBM>, opt?: CommonDaoOptions): Promise<number> {
280
- return await this.dao.updateByQuery(this, patch, opt)
278
+ async patchByQuery(patch: Partial<DBM>, opt?: CommonDaoOptions): Promise<number> {
279
+ return await this.dao.patchByQuery(this, patch, opt)
281
280
  }
282
281
 
283
282
  async streamQueryForEach(
@@ -129,6 +129,34 @@ export function runCommonDaoTest(db: CommonDB, quirks: CommonDBImplementationQui
129
129
  expectMatch(expectedItems, itemsSaved, quirks)
130
130
  })
131
131
 
132
+ if (support.increment) {
133
+ test('increment', async () => {
134
+ await dao.incrementBatch('k3', { id1: 1, id2: 2 })
135
+ let rows = await dao.query().runQuery()
136
+ rows = _sortBy(rows, r => r.id)
137
+ const expected = expectedItems.map(r => {
138
+ if (r.id === 'id1') {
139
+ return {
140
+ ...r,
141
+ k3: r.k3! + 1,
142
+ }
143
+ }
144
+ if (r.id === 'id2') {
145
+ return {
146
+ ...r,
147
+ k3: r.k3! + 2,
148
+ }
149
+ }
150
+ return r
151
+ })
152
+ expectMatch(expected, rows, quirks)
153
+
154
+ // reset the changes
155
+ await dao.increment('k3', 'id1', -1)
156
+ await dao.increment('k3', 'id2', -2)
157
+ })
158
+ }
159
+
132
160
  // GET not empty
133
161
  test('getByIds all items', async () => {
134
162
  const rows = await dao.getByIds(items.map(i => i.id).concat('abcd'))
@@ -1,6 +1,5 @@
1
1
  import { _deepFreeze, _filterObject, _pick, _sortBy, pMap } from '@naturalcycles/js-lib'
2
2
  import { CommonDB, CommonDBType } from '../common.db'
3
- import { DBIncrement, DBPatch } from '../db.model'
4
3
  import { DBQuery } from '../query/dbQuery'
5
4
  import {
6
5
  createTestItemDBM,
@@ -317,18 +316,18 @@ export function runCommonDBTest(db: CommonDB, quirks: CommonDBImplementationQuir
317
316
  })
318
317
  }
319
318
 
320
- if (support.updateByQuery) {
321
- test('updateByQuery simple', async () => {
319
+ if (support.patchByQuery) {
320
+ test('patchByQuery', async () => {
322
321
  // cleanup, reset initial data
323
322
  await db.deleteByQuery(queryAll())
324
323
  await db.saveBatch(TEST_TABLE, items)
325
324
 
326
- const patch: DBPatch<TestItemDBM> = {
325
+ const patch: Partial<TestItemDBM> = {
327
326
  k3: 5,
328
327
  k2: 'abc',
329
328
  }
330
329
 
331
- await db.updateByQuery(DBQuery.create<TestItemDBM>(TEST_TABLE).filterEq('even', true), patch)
330
+ await db.patchByQuery(DBQuery.create<TestItemDBM>(TEST_TABLE).filterEq('even', true), patch)
332
331
 
333
332
  const { rows } = await db.runQuery(queryAll())
334
333
  const expected = items.map(r => {
@@ -339,33 +338,28 @@ export function runCommonDBTest(db: CommonDB, quirks: CommonDBImplementationQuir
339
338
  })
340
339
  expectMatch(expected, rows, quirks)
341
340
  })
341
+ }
342
342
 
343
- if (support.dbIncrement) {
344
- test('updateByQuery DBIncrement', async () => {
345
- // cleanup, reset initial data
346
- await db.deleteByQuery(queryAll())
347
- await db.saveBatch(TEST_TABLE, items)
348
-
349
- const patch: DBPatch<TestItemDBM> = {
350
- k3: DBIncrement.of(1),
351
- k2: 'abcd',
352
- }
343
+ if (support.increment) {
344
+ test('incrementBatch', async () => {
345
+ // cleanup, reset initial data
346
+ await db.deleteByQuery(queryAll())
347
+ await db.saveBatch(TEST_TABLE, items)
353
348
 
354
- await db.updateByQuery(
355
- DBQuery.create<TestItemDBM>(TEST_TABLE).filterEq('even', true),
356
- patch,
357
- )
349
+ await db.incrementBatch(TEST_TABLE, 'k3', { id1: 1, id2: 2 })
358
350
 
359
- const { rows } = await db.runQuery(queryAll())
360
- const expected = items.map(r => {
361
- if (r.even) {
362
- return { ...r, ...patch, k3: (r.k3 || 0) + 1 }
363
- }
364
- return r
365
- })
366
- expectMatch(expected, rows, quirks)
351
+ const { rows } = await db.runQuery(queryAll())
352
+ const expected = items.map(r => {
353
+ if (r.id === 'id1') {
354
+ return { ...r, k3: 2 }
355
+ }
356
+ if (r.id === 'id2') {
357
+ return { ...r, k3: 4 }
358
+ }
359
+ return r
367
360
  })
368
- }
361
+ expectMatch(expected, rows, quirks)
362
+ })
369
363
  }
370
364
 
371
365
  if (support.queries) {