@naturalcycles/mysql-lib 3.11.0 → 3.12.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.
@@ -4,7 +4,7 @@ import { ReadableTyped } from '@naturalcycles/nodejs-lib';
4
4
  import { Connection, Pool, PoolConfig, PoolConnection, QueryOptions } from 'mysql';
5
5
  export interface MysqlDBOptions extends CommonDBOptions {
6
6
  }
7
- export interface MysqlDBSaveOptions<ROW extends ObjectWithId = AnyObjectWithId> extends CommonDBSaveOptions<ROW> {
7
+ export interface MysqlDBSaveOptions<ROW extends Partial<ObjectWithId> = AnyObjectWithId> extends CommonDBSaveOptions<ROW> {
8
8
  }
9
9
  /**
10
10
  * @default false / undefined
@@ -40,7 +40,7 @@ export declare class MysqlDB extends BaseCommonDB implements CommonDB {
40
40
  * Be careful to manage this connection yourself (open, release, etc).
41
41
  */
42
42
  createSingleConnection(): Promise<Connection>;
43
- getByIds<ROW extends ObjectWithId>(table: string, ids: string[], opt?: MysqlDBOptions): Promise<ROW[]>;
43
+ getByIds<ROW extends ObjectWithId>(table: string, ids: ROW['id'][], opt?: MysqlDBOptions): Promise<ROW[]>;
44
44
  runQuery<ROW extends ObjectWithId, OUT = ROW>(q: DBQuery<ROW>, _opt?: MysqlDBOptions): Promise<RunQueryResult<OUT>>;
45
45
  runSQL<RESULT>(q: QueryOptions): Promise<RESULT>;
46
46
  /**
@@ -50,11 +50,11 @@ export declare class MysqlDB extends BaseCommonDB implements CommonDB {
50
50
  runSQLString(s: string): Promise<void>;
51
51
  runQueryCount<ROW extends ObjectWithId>(q: DBQuery<ROW>, _opt?: CommonDBOptions): Promise<number>;
52
52
  streamQuery<ROW extends ObjectWithId, OUT = ROW>(q: DBQuery<ROW>, _opt?: MysqlDBOptions): ReadableTyped<OUT>;
53
- saveBatch<ROW extends ObjectWithId>(table: string, _rows: ROW[], _opt?: MysqlDBSaveOptions<ROW>): Promise<void>;
53
+ saveBatch<ROW extends Partial<ObjectWithId>>(table: string, rowsInput: ROW[], opt?: MysqlDBSaveOptions<ROW>): Promise<void>;
54
54
  /**
55
55
  * Limitation: always returns [], regardless of which rows are actually deleted
56
56
  */
57
- deleteByIds(table: string, ids: string[], _opt?: MysqlDBOptions): Promise<number>;
57
+ deleteByIds<ROW extends ObjectWithId>(table: string, ids: ROW['id'][], _opt?: MysqlDBOptions): Promise<number>;
58
58
  deleteByQuery<ROW extends ObjectWithId>(q: DBQuery<ROW>, _opt?: CommonDBOptions): Promise<number>;
59
59
  /**
60
60
  * Use with caution!
package/dist/mysql.db.js CHANGED
@@ -171,15 +171,28 @@ class MysqlDB extends db_lib_1.BaseCommonDB {
171
171
  }));
172
172
  }
173
173
  // SAVE
174
- async saveBatch(table, _rows, _opt) {
175
- if (!_rows.length)
174
+ async saveBatch(table, rowsInput, opt = {}) {
175
+ if (!rowsInput.length)
176
176
  return;
177
177
  // Stringify object values
178
- const rows = _rows.map(row => (0, js_lib_1._mapValues)(row, (_k, v) => {
178
+ const rows = rowsInput.map(row => (0, js_lib_1._mapValues)(row, (_k, v) => {
179
179
  return v && typeof v === 'object' && !Buffer.isBuffer(v) ? JSON.stringify(v) : v;
180
180
  }));
181
+ const verb = opt.saveMethod === 'insert' ? 'INSERT' : 'REPLACE';
182
+ if (opt.assignGeneratedIds) {
183
+ // Insert rows one-by-one, to get their auto-generated id
184
+ let i = -1;
185
+ for await (const row of rows) {
186
+ i++;
187
+ const sql = (0, query_util_1.insertSQL)(table, [row], verb, this.cfg.logger)[0];
188
+ const { insertId } = await this.runSQL({ sql });
189
+ // Mutate the input row with insertIt
190
+ rowsInput[i].id = insertId;
191
+ }
192
+ return;
193
+ }
181
194
  // inserts are split into multiple sentenses to respect the max_packet_size (1Mb usually)
182
- const sqls = (0, query_util_1.insertSQL)(table, rows, 'REPLACE', this.cfg.logger);
195
+ const sqls = (0, query_util_1.insertSQL)(table, rows, verb, this.cfg.logger);
183
196
  for await (const sql of sqls) {
184
197
  await this.runSQL({ sql });
185
198
  }
@@ -227,7 +240,7 @@ class MysqlDB extends db_lib_1.BaseCommonDB {
227
240
  return (0, mysql_schema_util_1.mysqlTableStatsToJsonSchemaField)(table, stats, this.cfg.logger);
228
241
  }
229
242
  }
230
- (0, tslib_1.__decorate)([
243
+ tslib_1.__decorate([
231
244
  (0, js_lib_1._Memo)()
232
245
  ], MysqlDB.prototype, "pool", null);
233
246
  exports.MysqlDB = MysqlDB;
package/package.json CHANGED
@@ -13,8 +13,8 @@
13
13
  "devDependencies": {
14
14
  "@naturalcycles/dev-lib": "^12.7.5",
15
15
  "@types/node": "^17.0.5",
16
- "dotenv": "^14.1.0",
17
- "jest": "^27.2.4"
16
+ "dotenv": "^16.0.0",
17
+ "jest": "^28.1.0"
18
18
  },
19
19
  "files": [
20
20
  "dist",
@@ -36,7 +36,7 @@
36
36
  "engines": {
37
37
  "node": ">=14.15.0"
38
38
  },
39
- "version": "3.11.0",
39
+ "version": "3.12.0",
40
40
  "description": "MySQL client implementing CommonDB interface",
41
41
  "keywords": [
42
42
  "mysql",
package/src/mysql.db.ts CHANGED
@@ -23,7 +23,15 @@ import {
23
23
  } from '@naturalcycles/js-lib'
24
24
  import { ReadableTyped } from '@naturalcycles/nodejs-lib'
25
25
  import { white } from '@naturalcycles/nodejs-lib/dist/colors'
26
- import { Connection, Pool, PoolConfig, PoolConnection, QueryOptions, TypeCast } from 'mysql'
26
+ import {
27
+ Connection,
28
+ OkPacket,
29
+ Pool,
30
+ PoolConfig,
31
+ PoolConnection,
32
+ QueryOptions,
33
+ TypeCast,
34
+ } from 'mysql'
27
35
  import * as mysql from 'mysql'
28
36
  import { dbQueryToSQLDelete, dbQueryToSQLSelect, insertSQL } from './query.util'
29
37
  import {
@@ -34,7 +42,7 @@ import {
34
42
  } from './schema/mysql.schema.util'
35
43
 
36
44
  export interface MysqlDBOptions extends CommonDBOptions {}
37
- export interface MysqlDBSaveOptions<ROW extends ObjectWithId = AnyObjectWithId>
45
+ export interface MysqlDBSaveOptions<ROW extends Partial<ObjectWithId> = AnyObjectWithId>
38
46
  extends CommonDBSaveOptions<ROW> {}
39
47
 
40
48
  /**
@@ -176,7 +184,7 @@ export class MysqlDB extends BaseCommonDB implements CommonDB {
176
184
  // GET
177
185
  override async getByIds<ROW extends ObjectWithId>(
178
186
  table: string,
179
- ids: string[],
187
+ ids: ROW['id'][],
180
188
  opt: MysqlDBOptions = {},
181
189
  ): Promise<ROW[]> {
182
190
  if (!ids.length) return []
@@ -264,22 +272,40 @@ export class MysqlDB extends BaseCommonDB implements CommonDB {
264
272
  }
265
273
 
266
274
  // SAVE
267
- override async saveBatch<ROW extends ObjectWithId>(
275
+ override async saveBatch<ROW extends Partial<ObjectWithId>>(
268
276
  table: string,
269
- _rows: ROW[],
270
- _opt?: MysqlDBSaveOptions<ROW>,
277
+ rowsInput: ROW[],
278
+ opt: MysqlDBSaveOptions<ROW> = {},
271
279
  ): Promise<void> {
272
- if (!_rows.length) return
280
+ if (!rowsInput.length) return
273
281
 
274
282
  // Stringify object values
275
- const rows = _rows.map(row =>
283
+ const rows = rowsInput.map(row =>
276
284
  _mapValues(row, (_k, v) => {
277
285
  return v && typeof v === 'object' && !Buffer.isBuffer(v) ? JSON.stringify(v) : v
278
286
  }),
279
287
  )
280
288
 
289
+ const verb = opt.saveMethod === 'insert' ? 'INSERT' : 'REPLACE'
290
+
291
+ if (opt.assignGeneratedIds) {
292
+ // Insert rows one-by-one, to get their auto-generated id
293
+
294
+ let i = -1
295
+ for await (const row of rows) {
296
+ i++
297
+ const sql = insertSQL(table, [row], verb, this.cfg.logger)[0]!
298
+ const { insertId } = await this.runSQL<OkPacket>({ sql })
299
+
300
+ // Mutate the input row with insertIt
301
+ rowsInput[i]!.id = insertId
302
+ }
303
+
304
+ return
305
+ }
306
+
281
307
  // inserts are split into multiple sentenses to respect the max_packet_size (1Mb usually)
282
- const sqls = insertSQL(table, rows, 'REPLACE', this.cfg.logger)
308
+ const sqls = insertSQL(table, rows, verb, this.cfg.logger)
283
309
 
284
310
  for await (const sql of sqls) {
285
311
  await this.runSQL({ sql })
@@ -290,7 +316,11 @@ export class MysqlDB extends BaseCommonDB implements CommonDB {
290
316
  /**
291
317
  * Limitation: always returns [], regardless of which rows are actually deleted
292
318
  */
293
- override async deleteByIds(table: string, ids: string[], _opt?: MysqlDBOptions): Promise<number> {
319
+ override async deleteByIds<ROW extends ObjectWithId>(
320
+ table: string,
321
+ ids: ROW['id'][],
322
+ _opt?: MysqlDBOptions,
323
+ ): Promise<number> {
294
324
  if (!ids.length) return 0
295
325
  const sql = dbQueryToSQLDelete(new DBQuery(table).filterEq('id', ids))
296
326
  const res = await this.runSQL<any>({ sql })