mysql2-core 0.3.7 → 0.3.9

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/src/index.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  import { Connection, createPool as createPool2, FieldPacket, Pool, PoolConnection, ResultSetHeader } from "mysql2"
2
- import { buildToSave, buildToSaveBatch } from "./build"
2
+ import { Pool as PromisePool } from "mysql2/promise"
3
+ import { buildToSave, buildToSaveBatch, param } from "./build"
3
4
  import { Attribute, Attributes, DB, Statement, StringMap, Transaction } from "./metadata"
4
5
 
5
6
  export * from "./build"
@@ -27,8 +28,7 @@ export function createPool(conf: Config): Pool {
27
28
  if (conf.max && conf.max > 0 && !conf.connectionLimit) {
28
29
  conf.connectionLimit = conf.max
29
30
  }
30
- const pool = createPool2({ ...conf, rowsAsArray: true })
31
- return pool
31
+ return createPool2({ ...conf, rowsAsArray: true })
32
32
  }
33
33
  export function getConnection(pool: Pool): Promise<PoolConnection> {
34
34
  return new Promise<PoolConnection>((resolve, reject) => {
@@ -47,7 +47,7 @@ export function beginTransaction(connection: PoolConnection, rollbackIfError?: b
47
47
  if (!rollbackIfError) {
48
48
  return reject(err)
49
49
  }
50
- connection.rollback(() => {
50
+ return connection.rollback(() => {
51
51
  return reject(err)
52
52
  })
53
53
  }
@@ -62,11 +62,11 @@ export function commit(connection: PoolConnection, rollbackIfError?: boolean): P
62
62
  if (!rollbackIfError) {
63
63
  return reject(err)
64
64
  }
65
- connection.rollback(() => {
65
+ return connection.rollback(() => {
66
66
  return reject(err)
67
67
  })
68
68
  }
69
- resolve()
69
+ return resolve()
70
70
  })
71
71
  })
72
72
  }
@@ -76,7 +76,7 @@ export function rollback(connection: PoolConnection): Promise<void> {
76
76
  if (err) {
77
77
  return reject(err)
78
78
  }
79
- resolve()
79
+ return resolve()
80
80
  })
81
81
  })
82
82
  }
@@ -97,18 +97,18 @@ export class PoolManager implements DB {
97
97
  }
98
98
  beginTransaction(): Promise<Transaction> {
99
99
  return new Promise<Transaction>((resolve, reject) => {
100
- this.pool.getConnection((er0, connection) => {
101
- if (er0) {
102
- return reject(er0)
100
+ this.pool.getConnection((err, connection) => {
101
+ if (err) {
102
+ return reject(err)
103
103
  }
104
- connection.beginTransaction((er1) => {
105
- if (er1) {
106
- connection.rollback(() => {
107
- return reject(er1)
104
+ connection.beginTransaction((beginError) => {
105
+ if (beginError) {
106
+ return connection.rollback(() => {
107
+ connection.release()
108
+ return reject(beginError)
108
109
  })
109
110
  }
110
- const tx = new PoolConnectionManager(connection)
111
- return resolve(tx)
111
+ return resolve(new PoolConnectionManager(connection))
112
112
  })
113
113
  })
114
114
  })
@@ -129,7 +129,7 @@ export class PoolManager implements DB {
129
129
  const p = ctx ? ctx : this.pool
130
130
  return queryOne(p, sql, args, m, bools)
131
131
  }
132
- executeScalar<T>(sql: string, args?: any[], ctx?: any): Promise<T> {
132
+ executeScalar<T>(sql: string, args?: any[], ctx?: any): Promise<T | null> {
133
133
  const p = ctx ? ctx : this.pool
134
134
  return executeScalar<T>(p, sql, args)
135
135
  }
@@ -140,6 +140,7 @@ export class PoolManager implements DB {
140
140
  }
141
141
  // tslint:disable-next-line:max-classes-per-file
142
142
  export class PoolConnectionManager implements Transaction {
143
+ protected released = false
143
144
  constructor(protected connection: PoolConnection) {
144
145
  this.param = this.param.bind(this)
145
146
  this.execute = this.execute.bind(this)
@@ -155,24 +156,36 @@ export class PoolConnectionManager implements Transaction {
155
156
  }
156
157
  commit(): Promise<void> {
157
158
  return new Promise<void>((resolve, reject) => {
158
- this.connection.commit((er3) => {
159
- if (er3) {
160
- return reject(er3)
159
+ this.connection.commit((err) => {
160
+ if (err) {
161
+ return this.connection.rollback(() => {
162
+ this.release()
163
+ return reject(err)
164
+ })
161
165
  }
166
+ this.release()
162
167
  return resolve()
163
168
  })
164
169
  })
165
170
  }
166
171
  rollback(): Promise<void> {
167
172
  return new Promise<void>((resolve, reject) => {
168
- this.connection.rollback((er3) => {
169
- if (er3) {
170
- return reject(er3)
173
+ this.connection.rollback((err) => {
174
+ this.release()
175
+ if (err) {
176
+ return reject(err)
171
177
  }
172
178
  return resolve()
173
179
  })
174
180
  })
175
181
  }
182
+ protected release(): void {
183
+ if (this.released) {
184
+ return
185
+ }
186
+ this.released = true
187
+ this.connection.release()
188
+ }
176
189
  execute(sql: string, args?: any[], ctx?: any): Promise<number> {
177
190
  const p = ctx ? ctx : this.connection
178
191
  return execute(p, sql, args)
@@ -189,7 +202,7 @@ export class PoolConnectionManager implements Transaction {
189
202
  const p = ctx ? ctx : this.connection
190
203
  return queryOne(p, sql, args, m, bools)
191
204
  }
192
- executeScalar<T>(sql: string, args?: any[], ctx?: any): Promise<T> {
205
+ executeScalar<T>(sql: string, args?: any[], ctx?: any): Promise<T | null> {
193
206
  const p = ctx ? ctx : this.connection
194
207
  return executeScalar<T>(p, sql, args)
195
208
  }
@@ -200,290 +213,169 @@ export class PoolConnectionManager implements Transaction {
200
213
  }
201
214
  export async function executeBatch(pool: Pool, statements: Statement[], firstSuccess?: boolean): Promise<number> {
202
215
  if (!statements || statements.length === 0) {
203
- return Promise.resolve(0)
204
- } else if (statements.length === 1) {
216
+ return 0
217
+ }
218
+ if (statements.length === 1) {
205
219
  return execute(pool, statements[0].query, statements[0].params)
206
220
  }
207
- return new Promise<number>((resolve, reject) => {
208
- pool.getConnection((er0, connection) => {
209
- if (er0) {
210
- return reject(er0)
211
- }
212
- return executeBatchConnectionTx(connection, statements, firstSuccess)
213
- })
214
- })
221
+ const connection = await getConnection(pool)
222
+ try {
223
+ return await executeBatchConnectionTx(connection, statements, firstSuccess)
224
+ } finally {
225
+ connection.release()
226
+ }
215
227
  }
216
228
  export async function executeBatchConnectionTx(connection: PoolConnection, statements: Statement[], firstSuccess?: boolean): Promise<number> {
217
229
  if (!statements || statements.length === 0) {
218
- return Promise.resolve(0)
219
- } else if (statements.length === 1) {
230
+ return 0
231
+ }
232
+ if (statements.length === 1) {
220
233
  return execute(connection, statements[0].query, statements[0].params)
221
234
  }
222
- if (resource.multipleStatements) {
223
- if (firstSuccess) {
224
- return new Promise<number>((resolve, reject) => {
225
- connection.beginTransaction((er1) => {
226
- if (er1) {
227
- connection.rollback(() => {
228
- return reject(er1)
229
- })
230
- } else {
231
- connection.execute<ResultSetHeader>(statements[0].query, toArray(statements[0].params), (er2a, results0) => {
232
- if (er2a) {
233
- connection.rollback(() => {
234
- return reject(er2a)
235
- })
236
- } else {
237
- if (results0 && results0.affectedRows === 0) {
238
- connection.commit((er3) => {
239
- if (er3) {
240
- connection.rollback(() => {
241
- return reject(er3)
242
- })
243
- }
244
- })
245
- return 0
246
- } else {
247
- const queries: string[] = []
248
- const params: any[] = []
249
- const l = statements.length
250
- for (let j = 1; j < l; j++) {
251
- const item = statements[j]
252
- if (item.query.endsWith(";")) {
253
- queries.push(item.query)
254
- } else {
255
- queries.push(item.query + ";")
256
- }
257
- if (item.params && item.params.length > 0) {
258
- for (const p of item.params) {
259
- params.push(p)
260
- }
261
- }
262
- }
263
- connection.query<ResultSetHeader>(queries.join(""), toArray(params), (er2, results) => {
264
- if (er2) {
265
- connection.rollback(() => {
266
- return reject(er2)
267
- })
268
- } else {
269
- connection.commit((er3) => {
270
- if (er3) {
271
- connection.rollback(() => {
272
- return reject(er3)
273
- })
274
- }
275
- })
276
- let c = 0
277
- c += results0.affectedRows + results.affectedRows
278
- return resolve(c)
279
- }
280
- })
281
- }
282
- }
283
- })
284
- }
285
- })
286
- })
287
- } else {
288
- return new Promise<number>((resolve, reject) => {
289
- connection.beginTransaction((er1) => {
290
- if (er1) {
291
- connection.rollback(() => {
292
- return reject(er1)
293
- })
294
- } else {
295
- const queries: string[] = []
296
- const params: any[] = []
297
- statements.forEach((item) => {
298
- if (item.query.endsWith(";")) {
299
- queries.push(item.query)
300
- } else {
301
- queries.push(item.query + ";")
302
- }
303
- if (item.params && item.params.length > 0) {
304
- for (const p of item.params) {
305
- params.push(p)
306
- }
307
- }
308
- })
309
- connection.query<ResultSetHeader>(queries.join(""), toArray(params), (er2, results) => {
310
- if (er2) {
311
- connection.rollback(() => {
312
- buildError(er2)
313
- return reject(er2)
314
- })
315
- } else {
316
- connection.commit((er3) => {
317
- if (er3) {
318
- connection.rollback(() => {
319
- return reject(er3)
320
- })
321
- }
322
- })
323
- return resolve(results.affectedRows)
324
- }
325
- })
326
- }
327
- })
328
- })
329
- }
330
- } else {
331
- if (firstSuccess) {
332
- try {
333
- await beginTransaction(connection, true)
334
- let count = await execute(connection, statements[0].query, toArray(statements[0].params))
335
- if (count === 0) {
336
- commit(connection, true)
337
- return 0
338
- }
339
- const l = statements.length
235
+ await beginTransaction(connection, true)
236
+ try {
237
+ let count = 0
340
238
 
341
- for (let j = 1; j < l; j++) {
342
- const item = statements[j]
343
- const c = await execute(connection, item.query, toArray(item.params))
344
- count = count + c
239
+ if (resource.multipleStatements) {
240
+ if (firstSuccess) {
241
+ const firstCount = await execute(connection, statements[0].query, statements[0].params)
242
+
243
+ count = firstCount
244
+
245
+ if (firstCount === 0) {
246
+ await commit(connection, true)
247
+ return 0
345
248
  }
346
- commit(connection, true)
347
- return count
348
- } catch (err) {
349
- rollback(connection)
350
- throw err
249
+ const remaining = statements.slice(1)
250
+ count += await executeMultipleStatements(connection, remaining)
251
+ } else {
252
+ count = await executeMultipleStatements(connection, statements)
351
253
  }
352
254
  } else {
353
- try {
354
- await beginTransaction(connection, true)
355
- let count = 0
356
- const l = statements.length
357
- for (let j = 0; j < l; j++) {
358
- const item = statements[j]
359
- const c = await execute(connection, item.query, toArray(item.params))
360
- count = count + c
255
+ const start = firstSuccess ? 1 : 0
256
+ if (firstSuccess) {
257
+ const firstCount = await execute(connection, statements[0].query, statements[0].params)
258
+ count = firstCount
259
+ if (firstCount === 0) {
260
+ await commit(connection, true)
261
+ return 0
361
262
  }
362
- commit(connection, true)
363
- return count
364
- } catch (err) {
365
- rollback(connection)
366
- throw err
367
263
  }
264
+ for (let i = start; i < statements.length; i++) {
265
+ const item = statements[i]
266
+ count += await execute(connection, item.query, item.params)
267
+ }
268
+ }
269
+
270
+ await commit(connection, true)
271
+
272
+ return count
273
+ } catch (err) {
274
+ try {
275
+ await rollback(connection)
276
+ } catch {
277
+ // Preserve the original error.
368
278
  }
279
+
280
+ throw buildError(err)
369
281
  }
370
282
  }
283
+
371
284
  export async function executeBatchConnection(connection: PoolConnection, statements: Statement[], firstSuccess?: boolean): Promise<number> {
372
285
  if (!statements || statements.length === 0) {
373
- return Promise.resolve(0)
374
- } else if (statements.length === 1) {
286
+ return 0
287
+ }
288
+
289
+ if (statements.length === 1) {
375
290
  return execute(connection, statements[0].query, statements[0].params)
376
291
  }
292
+
377
293
  if (resource.multipleStatements) {
378
294
  if (firstSuccess) {
379
- return new Promise<number>((resolve, reject) => {
380
- connection.execute<ResultSetHeader>(statements[0].query, toArray(statements[0].params), (er2a, results0) => {
381
- if (er2a) {
382
- return reject(er2a)
383
- } else {
384
- if (results0 && results0.affectedRows === 0) {
385
- return 0
386
- } else {
387
- const queries: string[] = []
388
- const params: any[] = []
389
- const l = statements.length
390
- for (let j = 1; j < l; j++) {
391
- const item = statements[j]
392
- if (item.query.endsWith(";")) {
393
- queries.push(item.query)
394
- } else {
395
- queries.push(item.query + ";")
396
- }
397
- if (item.params && item.params.length > 0) {
398
- for (const p of item.params) {
399
- params.push(p)
400
- }
401
- }
402
- }
403
- connection.query<ResultSetHeader>(queries.join(""), toArray(params), (er2, results) => {
404
- if (er2) {
405
- return reject(er2)
406
- } else {
407
- let c = 0
408
- c += results0.affectedRows + results.affectedRows
409
- return resolve(c)
410
- }
411
- })
412
- }
413
- }
414
- })
415
- })
416
- } else {
417
- return new Promise<number>((resolve, reject) => {
418
- const queries: string[] = []
419
- const params: any[] = []
420
- statements.forEach((item) => {
421
- if (item.query.endsWith(";")) {
422
- queries.push(item.query)
423
- } else {
424
- queries.push(item.query + ";")
425
- }
426
- if (item.params && item.params.length > 0) {
427
- for (const p of item.params) {
428
- params.push(p)
429
- }
430
- }
431
- })
432
- connection.query<ResultSetHeader>(queries.join(""), toArray(params), (er2, results) => {
433
- if (er2) {
434
- connection.rollback(() => {
435
- buildError(er2)
436
- return reject(er2)
437
- })
438
- } else {
439
- connection.commit((er3) => {
440
- if (er3) {
441
- connection.rollback(() => {
442
- return reject(er3)
443
- })
444
- }
445
- })
446
- return resolve(results.affectedRows)
447
- }
448
- })
449
- })
295
+ const firstCount = await execute(connection, statements[0].query, statements[0].params)
296
+
297
+ if (firstCount === 0) {
298
+ return 0
299
+ }
300
+
301
+ return firstCount + (await executeMultipleStatements(connection, statements.slice(1)))
450
302
  }
451
- } else {
452
- if (firstSuccess) {
453
- try {
454
- let count = await execute(connection, statements[0].query, toArray(statements[0].params))
455
- if (count === 0) {
456
- return 0
457
- }
458
- const l = statements.length
459
- try {
460
- for (let j = 1; j < l; j++) {
461
- const item = statements[j]
462
- const c = await execute(connection, item.query, toArray(item.params))
463
- count = count + c
464
- }
465
- return count
466
- } catch (er1) {
467
- throw er1
468
- }
469
- } catch (er0) {
470
- throw er0
303
+
304
+ return executeMultipleStatements(connection, statements)
305
+ }
306
+
307
+ let count = 0
308
+ const start = firstSuccess ? 1 : 0
309
+
310
+ if (firstSuccess) {
311
+ const firstCount = await execute(connection, statements[0].query, statements[0].params)
312
+
313
+ count = firstCount
314
+
315
+ if (firstCount === 0) {
316
+ return 0
317
+ }
318
+ }
319
+
320
+ for (let i = start; i < statements.length; i++) {
321
+ const item = statements[i]
322
+
323
+ count += await execute(connection, item.query, item.params)
324
+ }
325
+
326
+ return count
327
+ }
328
+
329
+ async function executeMultipleStatements(connection: PoolConnection, statements: Statement[]): Promise<number> {
330
+ if (!statements || statements.length === 0) {
331
+ return 0
332
+ }
333
+
334
+ const queries: string[] = []
335
+ const params: any[] = []
336
+
337
+ for (const item of statements) {
338
+ queries.push(ensureSemicolon(item.query))
339
+
340
+ if (item.params && item.params.length > 0) {
341
+ params.push(...item.params)
342
+ }
343
+ }
344
+
345
+ return new Promise<number>((resolve, reject) => {
346
+ connection.query<any>(queries.join(""), toArray(params), (err, results) => {
347
+ if (err) {
348
+ buildError(err)
349
+ return reject(err)
471
350
  }
472
- } else {
473
- let count = 0
474
- const l = statements.length
475
- try {
476
- for (let j = 0; j < l; j++) {
477
- const item = statements[j]
478
- const c = await execute(connection, item.query, toArray(item.params))
479
- count = count + c
480
- }
481
- return count
482
- } catch (err) {
483
- throw err
351
+
352
+ return resolve(getAffectedRows(results))
353
+ })
354
+ })
355
+ }
356
+ function ensureSemicolon(sql: string): string {
357
+ return sql.endsWith(";") ? sql : `${sql};`
358
+ }
359
+ function getAffectedRows(results: any): number {
360
+ if (!results) {
361
+ return 0
362
+ }
363
+
364
+ if (Array.isArray(results)) {
365
+ let count = 0
366
+
367
+ for (const result of results) {
368
+ if (result && typeof result.affectedRows === "number") {
369
+ count += result.affectedRows
484
370
  }
485
371
  }
372
+
373
+ return count
374
+ }
375
+ if (typeof results.affectedRows === "number") {
376
+ return results.affectedRows
486
377
  }
378
+ return 0
487
379
  }
488
380
  function buildError(err: any): any {
489
381
  if (err.errno === 1062 && err.code === "ER_DUP_ENTRY") {
@@ -495,36 +387,33 @@ function buildError(err: any): any {
495
387
  export async function execute(pool: Pool | PoolConnection, sql: string, args?: any[]): Promise<number> {
496
388
  const p = toArray(args)
497
389
  return new Promise<number>((resolve, reject) => {
498
- return pool.execute<ResultSetHeader>(sql, p, (err, res) => {
390
+ pool.execute<ResultSetHeader>(sql, p, (err, res) => {
499
391
  if (err) {
500
392
  buildError(err)
501
393
  return reject(err)
502
- } else {
503
- return resolve(res.affectedRows)
504
394
  }
395
+ return resolve(res.affectedRows)
505
396
  })
506
397
  })
507
398
  }
508
399
  export async function query<T>(pool: Pool | PoolConnection, sql: string, args?: any[], m?: StringMap, bools?: Attribute[]): Promise<T[]> {
509
400
  const p = toArray(args)
510
- return new Promise((resolve, reject) => {
511
- return pool.query<T[] & ResultSetHeader>(sql, p, (err, results, fields) => {
401
+ return new Promise<T[]>((resolve, reject) => {
402
+ pool.query<T[] & ResultSetHeader>(sql, p, (err, results, fields) => {
512
403
  if (err) {
513
404
  return reject(err)
514
- } else {
515
- if (results.length > 0) {
516
- const arrayResult = results.map((item) => {
517
- if (Array.isArray(item)) {
518
- return formatData<T>(fields, item)
519
- } else {
520
- return item
521
- }
522
- })
523
- return resolve(handleResults(arrayResult, m, bools))
524
- } else {
525
- resolve([])
526
- }
527
405
  }
406
+ if (results.length === 0) {
407
+ return resolve([])
408
+ }
409
+ const arrayResult = results.map((item) => {
410
+ if (Array.isArray(item)) {
411
+ return formatData<T>(fields, item)
412
+ }
413
+
414
+ return item
415
+ })
416
+ return resolve(handleResults(arrayResult, m, bools))
528
417
  })
529
418
  })
530
419
  }
@@ -534,29 +423,21 @@ export function queryOne<T>(pool: Pool | PoolConnection, sql: string, args?: any
534
423
  return r && r.length > 0 ? r[0] : null
535
424
  })
536
425
  }
537
- export function executeScalar<T>(pool: Pool | PoolConnection, sql: string, args?: any[]): Promise<T> {
426
+ export function executeScalar<T>(pool: Pool | PoolConnection, sql: string, args?: any[]): Promise<T | null> {
538
427
  return queryOne<T>(pool, sql, args).then((r) => {
539
428
  if (!r) {
540
429
  return null
541
- } else {
542
- const keys = Object.keys(r)
543
- return (r as any)[keys[0]]
544
430
  }
431
+ const keys = Object.keys(r)
432
+ return (r as any)[keys[0]]
545
433
  })
546
434
  }
547
435
 
548
436
  export function count(pool: Pool | PoolConnection, sql: string, args?: any[]): Promise<number> {
549
- return executeScalar<number>(pool, sql, args)
437
+ return executeScalar<number>(pool, sql, args).then((res) => (res !== null ? res : 0))
550
438
  }
551
439
 
552
- export function save<T>(
553
- pool: Pool | PoolConnection | ((sql: string, args?: any[]) => Promise<number>),
554
- obj: T,
555
- table: string,
556
- attrs: Attributes,
557
- ver?: string,
558
- buildParam?: (i: number) => string,
559
- ): Promise<number> {
440
+ export function save<T>(pool: Pool | PoolConnection | ((sql: string, args?: any[]) => Promise<number>), obj: T, table: string, attrs: Attributes, ver?: string, buildParam?: (i: number) => string): Promise<number> {
560
441
  const s = buildToSave(obj, table, attrs, ver, buildParam)
561
442
  if (!s.query) {
562
443
  return Promise.resolve(-1)
@@ -567,14 +448,7 @@ export function save<T>(
567
448
  return execute(pool, s.query, s.params)
568
449
  }
569
450
  }
570
- export function saveBatch<T>(
571
- pool: Pool | ((statements: Statement[]) => Promise<number>),
572
- objs: T[],
573
- table: string,
574
- attrs: Attributes,
575
- ver?: string,
576
- buildParam?: (i: number) => string,
577
- ): Promise<number> {
451
+ export function saveBatch<T>(pool: Pool | ((statements: Statement[]) => Promise<number>), objs: T[], table: string, attrs: Attributes, ver?: string, buildParam?: (i: number) => string): Promise<number> {
578
452
  const s = buildToSaveBatch(objs, table, attrs, ver, buildParam)
579
453
  if (typeof pool === "function") {
580
454
  return pool(s)
@@ -587,64 +461,61 @@ export function toArray(arr?: any[]): any[] {
587
461
  return []
588
462
  }
589
463
  const p: any[] = []
590
- const l = arr.length
591
- for (let i = 0; i < l; i++) {
592
- if (arr[i] === undefined || arr[i] == null) {
464
+ for (const value of arr) {
465
+ if (value === undefined || value === null) {
593
466
  p.push(null)
594
- } else {
595
- if (typeof arr[i] === "object") {
596
- if (arr[i] instanceof Date) {
597
- p.push(arr[i])
598
- } else {
599
- if (resource.string) {
600
- const s: string = JSON.stringify(arr[i])
601
- p.push(s)
602
- } else {
603
- p.push(arr[i])
604
- }
605
- }
467
+ continue
468
+ }
469
+ if (typeof value === "object") {
470
+ if (value instanceof Date) {
471
+ p.push(value)
472
+ continue
473
+ }
474
+ if (resource.string) {
475
+ p.push(JSON.stringify(value))
606
476
  } else {
607
- p.push(arr[i])
477
+ p.push(value)
608
478
  }
479
+ continue
609
480
  }
481
+ p.push(value)
610
482
  }
611
483
  return p
612
484
  }
613
- export function handleResults<T>(r: T[], m?: StringMap, bools?: Attribute[]) {
485
+ export function handleResults<T>(r: T[], m?: StringMap, bools?: Attribute[]): T[] {
614
486
  if (m) {
615
487
  const res = mapArray(r, m)
616
488
  if (bools && bools.length > 0) {
617
489
  return handleBool(res, bools)
618
- } else {
619
- return res
620
- }
621
- } else {
622
- if (bools && bools.length > 0) {
623
- return handleBool(r, bools)
624
- } else {
625
- return r
626
490
  }
491
+ return res
492
+ }
493
+ if (bools && bools.length > 0) {
494
+ return handleBool(r, bools)
627
495
  }
496
+ return r
628
497
  }
629
- export function handleBool<T>(objs: T[], bools: Attribute[]) {
498
+ export function handleBool<T>(objs: T[], bools: Attribute[]): T[] {
630
499
  if (!bools || bools.length === 0 || !objs) {
631
500
  return objs
632
501
  }
633
502
  for (const obj of objs) {
634
503
  const o: any = obj
635
504
  for (const field of bools) {
636
- if (field.name) {
637
- const v = o[field.name]
638
- if (typeof v !== "boolean" && v != null && v !== undefined) {
639
- const b = field.true
640
- if (b == null || b === undefined) {
641
- // tslint:disable-next-line:triple-equals
642
- o[field.name] = "1" == v || "T" == v || "Y" == v || "true" == v || "on" == v
643
- } else {
644
- // tslint:disable-next-line:triple-equals
645
- o[field.name] = v == b ? true : false
646
- }
647
- }
505
+ if (!field.name) {
506
+ continue
507
+ }
508
+ const v = o[field.name]
509
+ if (typeof v === "boolean" || v == null) {
510
+ continue
511
+ }
512
+ const b = field.true
513
+ if (b == null) {
514
+ // tslint:disable-next-line:triple-equals
515
+ o[field.name] = "1" == v || "T" == v || "Y" == v || "true" == v || "on" == v
516
+ } else {
517
+ // tslint:disable-next-line:triple-equals
518
+ o[field.name] = v == b
648
519
  }
649
520
  }
650
521
  }
@@ -654,7 +525,7 @@ export function formatData<T>(nameColumn: FieldPacket[], data: any, m?: StringMa
654
525
  const result: any = {}
655
526
  nameColumn.forEach((item, index) => {
656
527
  let key = item.name
657
- if (m) {
528
+ if (m && m[item.name]) {
658
529
  key = m[item.name]
659
530
  }
660
531
  result[key] = data[index]
@@ -688,10 +559,8 @@ export function mapArray<T>(results: T[], m?: StringMap): T[] {
688
559
  if (mkeys.length === 0) {
689
560
  return results
690
561
  }
691
- const objs = []
692
- const length = results.length
693
- for (let i = 0; i < length; i++) {
694
- const obj = results[i]
562
+ const objs: T[] = []
563
+ for (const obj of results) {
695
564
  const obj2: any = {}
696
565
  const keys = Object.keys(obj as any)
697
566
  for (const key of keys) {
@@ -750,11 +619,11 @@ export function isEmpty(s: string): boolean {
750
619
  return !(s && s.length > 0)
751
620
  }
752
621
  // tslint:disable-next-line:max-classes-per-file
753
- export class StringService {
622
+ export class StringAdapter {
754
623
  constructor(
755
624
  protected pool: Pool | PoolConnection,
756
- public table: string,
757
- public column: string,
625
+ protected table: string,
626
+ protected column: string,
758
627
  ) {
759
628
  this.load = this.load.bind(this)
760
629
  this.save = this.save.bind(this)
@@ -791,27 +660,18 @@ export function version(attrs: Attributes): Attribute | undefined {
791
660
  }
792
661
  // tslint:disable-next-line:max-classes-per-file
793
662
  export class MySQLWriter<T> {
794
- pool?: Pool | PoolConnection
795
- version?: string
796
- execute?: (sql: string, args?: any[]) => Promise<number>
797
- map?: (v: T) => T
798
- param?: (i: number) => string
663
+ protected version?: string
664
+ protected param?: (i: number) => string
799
665
  constructor(
800
- pool: Pool | PoolConnection | ((sql: string, args?: any[]) => Promise<number>),
801
- public table: string,
802
- public attributes: Attributes,
803
- public oneIfSuccess?: boolean,
804
- toDB?: (v: T) => T,
666
+ protected pool: Pool | PoolConnection,
667
+ protected table: string,
668
+ protected attributes: Attributes,
669
+ protected oneIfSuccess?: boolean,
670
+ protected map?: (v: T) => T,
805
671
  buildParam?: (i: number) => string,
806
672
  ) {
807
673
  this.write = this.write.bind(this)
808
- if (typeof pool === "function") {
809
- this.execute = pool
810
- } else {
811
- this.pool = pool
812
- }
813
- this.param = buildParam
814
- this.map = toDB
674
+ this.param = buildParam ? buildParam : param
815
675
  const x = version(attributes)
816
676
  if (x) {
817
677
  this.version = x.name
@@ -827,18 +687,10 @@ export class MySQLWriter<T> {
827
687
  }
828
688
  const stmt = buildToSave(obj2, this.table, this.attributes, this.version, this.param)
829
689
  if (stmt.query) {
830
- if (this.execute) {
831
- if (this.oneIfSuccess) {
832
- return this.execute(stmt.query, stmt.params).then((ct) => (ct > 0 ? 1 : 0))
833
- } else {
834
- return this.execute(stmt.query, stmt.params)
835
- }
690
+ if (this.oneIfSuccess) {
691
+ return execute(this.pool, stmt.query, stmt.params).then((ct) => (ct > 0 ? 1 : 0))
836
692
  } else {
837
- if (this.oneIfSuccess) {
838
- return execute(this.pool as any, stmt.query, stmt.params).then((ct) => (ct > 0 ? 1 : 0))
839
- } else {
840
- return execute(this.pool as any, stmt.query, stmt.params)
841
- }
693
+ return execute(this.pool, stmt.query, stmt.params)
842
694
  }
843
695
  } else {
844
696
  return Promise.resolve(0)
@@ -847,37 +699,24 @@ export class MySQLWriter<T> {
847
699
  }
848
700
  // tslint:disable-next-line:max-classes-per-file
849
701
  export class MySQLStreamWriter<T> {
850
- list: T[] = []
851
- size = 0
852
- pool?: Pool
853
- version?: string
854
- executeBatch?: (statements: Statement[]) => Promise<number>
855
- map?: (v: T) => T
856
- param?: (i: number) => string
702
+ protected list: T[] = []
703
+ protected version?: string
704
+ protected param?: (i: number) => string
857
705
  constructor(
858
- pool: Pool | ((statements: Statement[]) => Promise<number>),
859
- public table: string,
860
- public attributes: Attributes,
861
- size?: number,
862
- toDB?: (v: T) => T,
706
+ protected pool: Pool,
707
+ protected table: string,
708
+ protected attributes: Attributes,
709
+ protected size: number = 1000,
710
+ protected map?: (v: T) => T,
863
711
  buildParam?: (i: number) => string,
864
712
  ) {
865
713
  this.write = this.write.bind(this)
866
714
  this.flush = this.flush.bind(this)
867
- if (typeof pool === "function") {
868
- this.executeBatch = pool
869
- } else {
870
- this.pool = pool
871
- }
872
- this.param = buildParam
873
- this.map = toDB
715
+ this.param = buildParam ? buildParam : param
874
716
  const x = version(attributes)
875
717
  if (x) {
876
718
  this.version = x.name
877
719
  }
878
- if (size) {
879
- this.size = size
880
- }
881
720
  }
882
721
  write(obj: T): Promise<number> {
883
722
  if (!obj) {
@@ -903,17 +742,10 @@ export class MySQLStreamWriter<T> {
903
742
  const total = this.list.length
904
743
  const stmt = buildToSaveBatch(this.list, this.table, this.attributes, this.version, this.param)
905
744
  if (stmt.length > 0) {
906
- if (this.executeBatch) {
907
- return this.executeBatch(stmt).then((r) => {
908
- this.list = []
909
- return total
910
- })
911
- } else {
912
- return executeBatch(this.pool as any, stmt).then((r) => {
913
- this.list = []
914
- return total
915
- })
916
- }
745
+ return executeBatch(this.pool as any, stmt).then((r) => {
746
+ this.list = []
747
+ return total
748
+ })
917
749
  } else {
918
750
  return Promise.resolve(0)
919
751
  }
@@ -922,27 +754,18 @@ export class MySQLStreamWriter<T> {
922
754
  }
923
755
  // tslint:disable-next-line:max-classes-per-file
924
756
  export class MySQLBatchWriter<T> {
925
- pool?: Pool
926
- version?: string
927
- execute?: (statements: Statement[]) => Promise<number>
928
- map?: (v: T) => T
929
- param?: (i: number) => string
757
+ protected version?: string
758
+ protected param?: (i: number) => string
930
759
  constructor(
931
- pool: Pool | ((statements: Statement[]) => Promise<number>),
932
- public table: string,
933
- public attributes: Attributes,
934
- public oneIfSuccess?: boolean,
935
- toDB?: (v: T) => T,
760
+ protected pool: Pool,
761
+ protected table: string,
762
+ protected attributes: Attributes,
763
+ protected oneIfSuccess?: boolean,
764
+ protected map?: (v: T) => T,
936
765
  buildParam?: (i: number) => string,
937
766
  ) {
938
767
  this.write = this.write.bind(this)
939
- if (typeof pool === "function") {
940
- this.execute = pool
941
- } else {
942
- this.pool = pool
943
- }
944
- this.param = buildParam
945
- this.map = toDB
768
+ this.param = buildParam ? buildParam : param
946
769
  const x = version(attributes)
947
770
  if (x) {
948
771
  this.version = x.name
@@ -962,18 +785,10 @@ export class MySQLBatchWriter<T> {
962
785
  }
963
786
  const stmts = buildToSaveBatch(list, this.table, this.attributes, this.version, this.param)
964
787
  if (stmts.length > 0) {
965
- if (this.execute) {
966
- if (this.oneIfSuccess) {
967
- return this.execute(stmts).then((ct) => stmts.length)
968
- } else {
969
- return this.execute(stmts)
970
- }
788
+ if (this.oneIfSuccess) {
789
+ return executeBatch(this.pool, stmts).then((ct) => stmts.length)
971
790
  } else {
972
- if (this.oneIfSuccess) {
973
- return executeBatch(this.pool as any, stmts).then((ct) => stmts.length)
974
- } else {
975
- return executeBatch(this.pool as any, stmts)
976
- }
791
+ return executeBatch(this.pool, stmts)
977
792
  }
978
793
  } else {
979
794
  return Promise.resolve(0)
@@ -993,7 +808,7 @@ export interface HealthChecker {
993
808
  export class MySQLChecker implements HealthChecker {
994
809
  protected readonly service: string
995
810
  constructor(
996
- protected readonly pool: Pool,
811
+ protected readonly pool: PromisePool,
997
812
  service?: string,
998
813
  protected readonly timeout = 4500,
999
814
  ) {
@@ -1050,6 +865,9 @@ export class MySQLChecker implements HealthChecker {
1050
865
  }
1051
866
  }
1052
867
 
868
+ export interface SimpleMap {
869
+ [key: string]: string | number | boolean | Date
870
+ }
1053
871
  export interface Formatter<T> {
1054
872
  format: (row: T) => string
1055
873
  }
@@ -1064,44 +882,60 @@ export interface QueryBuilder {
1064
882
  // tslint:disable-next-line:max-classes-per-file
1065
883
  export class Exporter<T> {
1066
884
  constructor(
1067
- public connection: Connection,
1068
- public buildQuery: (ctx?: any) => Promise<Statement>,
1069
- ft: (row: T) => string,
1070
- public write: (chunk: string) => boolean,
1071
- public end: (cb?: () => void) => void,
1072
- public attributes?: Attributes,
885
+ protected connection: Connection,
886
+ protected filename: string,
887
+ protected buildQuery: (ctx?: any) => Promise<Statement>,
888
+ protected format: (row: T) => string,
889
+ protected write: (chunk: string) => boolean,
890
+ protected end: (cb?: () => void) => void,
891
+ protected attributes?: Attributes,
892
+ protected logInfo?: (msg: string, m?: SimpleMap) => void,
893
+ protected progressSize: number = 10000,
1073
894
  ) {
1074
- this.format = ft
1075
895
  if (attributes) {
1076
896
  this.map = buildMap(attributes)
1077
897
  }
1078
898
  this.export = this.export.bind(this)
1079
899
  }
1080
900
  map?: StringMap
1081
- format: (row: T) => string
1082
901
  async export(ctx?: any): Promise<number> {
1083
- let idx = 0
1084
902
  const stmt = await this.buildQuery(ctx)
1085
903
  const reader = this.connection.query(stmt.query, stmt.params)
1086
904
  let er: any
905
+ let i = 0
906
+ let k = 0
1087
907
  reader.on("error", (err) => (er = err))
1088
908
  // (D2) WRITE ROW-BY-ROW
1089
909
  if (this.map) {
1090
910
  reader.on("result", async (row: any) => {
1091
- ++idx
911
+ ++i
912
+ k++
1092
913
  this.connection.pause()
1093
914
  const obj = mapOne<T>(row, this.map)
1094
915
  const data = this.format(obj)
1095
916
  this.write(data)
1096
917
  this.connection.resume()
918
+ if (k >= this.progressSize) {
919
+ if (this.logInfo) {
920
+ this.logInfo(`Progress: ${i} records processed of file '${this.filename}'`)
921
+ }
922
+ k = 0
923
+ }
1097
924
  })
1098
925
  } else {
1099
926
  reader.on("result", async (row: any) => {
1100
- ++idx
927
+ ++i
928
+ k++
1101
929
  this.connection.pause()
1102
930
  const data = this.format(row as T)
1103
931
  this.write(data)
1104
932
  this.connection.resume()
933
+ if (k >= this.progressSize) {
934
+ if (this.logInfo) {
935
+ this.logInfo(`Progress: ${i} records processed of file '${this.filename}'`)
936
+ }
937
+ k = 0
938
+ }
1105
939
  })
1106
940
  }
1107
941
  // (D3) CLOSE CONNECTION + FILE
@@ -1115,7 +949,7 @@ export class Exporter<T> {
1115
949
  if (err) {
1116
950
  reject(err)
1117
951
  } else {
1118
- resolve(idx)
952
+ resolve(i)
1119
953
  }
1120
954
  })
1121
955
  }
@@ -1126,11 +960,14 @@ export class Exporter<T> {
1126
960
  // tslint:disable-next-line:max-classes-per-file
1127
961
  export class ExportService<T> {
1128
962
  constructor(
1129
- public connection: Connection,
1130
- public queryBuilder: QueryBuilder,
1131
- public formatter: Formatter<T>,
1132
- public writer: FileWriter,
1133
- public attributes?: Attributes,
963
+ protected connection: Connection,
964
+ protected filename: string,
965
+ protected queryBuilder: QueryBuilder,
966
+ protected formatter: Formatter<T>,
967
+ protected writer: FileWriter,
968
+ protected attributes?: Attributes,
969
+ protected logInfo?: (msg: string, m?: SimpleMap) => void,
970
+ protected progressSize: number = 10000,
1134
971
  ) {
1135
972
  if (attributes) {
1136
973
  this.map = buildMap(attributes)
@@ -1139,28 +976,43 @@ export class ExportService<T> {
1139
976
  }
1140
977
  map?: StringMap
1141
978
  async export(ctx?: any): Promise<number> {
1142
- let idx = 0
1143
979
  const stmt = await this.queryBuilder.build(ctx)
1144
980
  const reader = this.connection.query(stmt.query, stmt.params)
1145
981
  let er: any
1146
982
  reader.on("error", (err) => (er = err))
983
+ let i = 0
984
+ let k = 0
1147
985
  // (D2) WRITE ROW-BY-ROW
1148
986
  if (this.map) {
1149
987
  reader.on("result", async (row: any) => {
1150
- ++idx
988
+ ++i
989
+ k++
1151
990
  this.connection.pause()
1152
991
  const obj = mapOne<T>(row, this.map)
1153
992
  const data = this.formatter.format(obj)
1154
993
  this.writer.write(data)
1155
994
  this.connection.resume()
995
+ if (k >= this.progressSize) {
996
+ if (this.logInfo) {
997
+ this.logInfo(`Progress: ${i} records processed of file '${this.filename}'`)
998
+ }
999
+ k = 0
1000
+ }
1156
1001
  })
1157
1002
  } else {
1158
1003
  reader.on("result", async (row: any) => {
1159
- ++idx
1004
+ ++i
1005
+ k++
1160
1006
  this.connection.pause()
1161
1007
  const data = this.formatter.format(row as T)
1162
1008
  this.writer.write(data)
1163
1009
  this.connection.resume()
1010
+ if (k >= this.progressSize) {
1011
+ if (this.logInfo) {
1012
+ this.logInfo(`Progress: ${i} records processed of file '${this.filename}'`)
1013
+ }
1014
+ k = 0
1015
+ }
1164
1016
  })
1165
1017
  }
1166
1018
  // (D3) CLOSE CONNECTION + FILE
@@ -1178,7 +1030,7 @@ export class ExportService<T> {
1178
1030
  if (err) {
1179
1031
  reject(err)
1180
1032
  } else {
1181
- resolve(idx)
1033
+ resolve(i)
1182
1034
  }
1183
1035
  })
1184
1036
  }