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