mysql2-core 0.3.8 → 0.3.10

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,49 +97,44 @@ 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
  })
116
115
  }
117
- execute(sql: string, args?: any[], ctx?: any): Promise<number> {
118
- const p = ctx ? ctx : this.pool
119
- return execute(p, sql, args)
116
+ execute(sql: string, args?: any[]): Promise<number> {
117
+ return execute(this.pool, sql, args)
120
118
  }
121
- executeBatch(statements: Statement[], firstSuccess?: boolean, ctx?: any): Promise<number> {
122
- const p = ctx ? ctx : this.pool
123
- return executeBatch(p, statements, firstSuccess)
119
+ executeBatch(statements: Statement[], firstAffected?: boolean): Promise<number> {
120
+ return executeBatch(this.pool, statements, firstAffected)
124
121
  }
125
- query<T>(sql: string, args?: any[], m?: StringMap, bools?: Attribute[], ctx?: any): Promise<T[]> {
126
- const p = ctx ? ctx : this.pool
127
- return query(p, sql, args, m, bools)
122
+ query<T>(sql: string, args?: any[], m?: StringMap, bools?: Attribute[]): Promise<T[]> {
123
+ return query(this.pool, sql, args, m, bools)
128
124
  }
129
- queryOne<T>(sql: string, args?: any[], m?: StringMap, bools?: Attribute[], ctx?: any): Promise<T | null> {
130
- const p = ctx ? ctx : this.pool
131
- return queryOne(p, sql, args, m, bools)
125
+ queryOne<T>(sql: string, args?: any[], m?: StringMap, bools?: Attribute[]): Promise<T | null> {
126
+ return queryOne(this.pool, sql, args, m, bools)
132
127
  }
133
- executeScalar<T>(sql: string, args?: any[], ctx?: any): Promise<T> {
134
- const p = ctx ? ctx : this.pool
135
- return executeScalar<T>(p, sql, args)
128
+ executeScalar<T>(sql: string, args?: any[]): Promise<T | null> {
129
+ return executeScalar<T>(this.pool, sql, args)
136
130
  }
137
- count(sql: string, args?: any[], ctx?: any): Promise<number> {
138
- const p = ctx ? ctx : this.pool
139
- return count(p, sql, args)
131
+ count(sql: string, args?: any[]): Promise<number> {
132
+ return count(this.pool, sql, args)
140
133
  }
141
134
  }
142
135
  // tslint:disable-next-line:max-classes-per-file
143
136
  export class PoolConnectionManager implements Transaction {
137
+ protected released = false
144
138
  constructor(protected connection: PoolConnection) {
145
139
  this.param = this.param.bind(this)
146
140
  this.execute = this.execute.bind(this)
@@ -156,335 +150,219 @@ export class PoolConnectionManager implements Transaction {
156
150
  }
157
151
  commit(): Promise<void> {
158
152
  return new Promise<void>((resolve, reject) => {
159
- this.connection.commit((er3) => {
160
- if (er3) {
161
- return reject(er3)
153
+ this.connection.commit((err) => {
154
+ if (err) {
155
+ return this.connection.rollback(() => {
156
+ this.release()
157
+ return reject(err)
158
+ })
162
159
  }
160
+ this.release()
163
161
  return resolve()
164
162
  })
165
163
  })
166
164
  }
167
165
  rollback(): Promise<void> {
168
166
  return new Promise<void>((resolve, reject) => {
169
- this.connection.rollback((er3) => {
170
- if (er3) {
171
- return reject(er3)
167
+ this.connection.rollback((err) => {
168
+ this.release()
169
+ if (err) {
170
+ return reject(err)
172
171
  }
173
172
  return resolve()
174
173
  })
175
174
  })
176
175
  }
177
- execute(sql: string, args?: any[], ctx?: any): Promise<number> {
178
- const p = ctx ? ctx : this.connection
179
- return execute(p, sql, args)
176
+ protected release(): void {
177
+ if (this.released) {
178
+ return
179
+ }
180
+ this.released = true
181
+ this.connection.release()
182
+ }
183
+ execute(sql: string, args?: any[]): Promise<number> {
184
+ return execute(this.connection, sql, args)
180
185
  }
181
- executeBatch(statements: Statement[], firstSuccess?: boolean, ctx?: any): Promise<number> {
182
- const p = ctx ? ctx : this.connection
183
- return executeBatchConnection(p, statements, firstSuccess)
186
+ executeBatch(statements: Statement[], firstAffected?: boolean): Promise<number> {
187
+ return executeBatchConnection(this.connection, statements, firstAffected)
184
188
  }
185
189
  query<T>(sql: string, args?: any[], m?: StringMap, bools?: Attribute[], ctx?: any): Promise<T[]> {
186
- const p = ctx ? ctx : this.connection
187
- return query(p, sql, args, m, bools)
190
+ return query(this.connection, sql, args, m, bools)
188
191
  }
189
- queryOne<T>(sql: string, args?: any[], m?: StringMap, bools?: Attribute[], ctx?: any): Promise<T | null> {
190
- const p = ctx ? ctx : this.connection
191
- return queryOne(p, sql, args, m, bools)
192
+ queryOne<T>(sql: string, args?: any[], m?: StringMap, bools?: Attribute[]): Promise<T | null> {
193
+ return queryOne(this.connection, sql, args, m, bools)
192
194
  }
193
- executeScalar<T>(sql: string, args?: any[], ctx?: any): Promise<T> {
194
- const p = ctx ? ctx : this.connection
195
- return executeScalar<T>(p, sql, args)
195
+ executeScalar<T>(sql: string, args?: any[]): Promise<T | null> {
196
+ return executeScalar<T>(this.connection, sql, args)
196
197
  }
197
- count(sql: string, args?: any[], ctx?: any): Promise<number> {
198
- const p = ctx ? ctx : this.connection
199
- return count(p, sql, args)
198
+ count(sql: string, args?: any[]): Promise<number> {
199
+ return count(this.connection, sql, args)
200
200
  }
201
201
  }
202
- export async function executeBatch(pool: Pool, statements: Statement[], firstSuccess?: boolean): Promise<number> {
202
+ export async function executeBatch(pool: Pool, statements: Statement[], firstAffected?: boolean): Promise<number> {
203
203
  if (!statements || statements.length === 0) {
204
- return Promise.resolve(0)
205
- } else if (statements.length === 1) {
204
+ return 0
205
+ }
206
+ if (statements.length === 1) {
206
207
  return execute(pool, statements[0].query, statements[0].params)
207
208
  }
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
- })
209
+ const connection = await getConnection(pool)
210
+ try {
211
+ return await executeBatchConnectionTx(connection, statements, firstAffected)
212
+ } finally {
213
+ connection.release()
214
+ }
216
215
  }
217
- export async function executeBatchConnectionTx(connection: PoolConnection, statements: Statement[], firstSuccess?: boolean): Promise<number> {
216
+ export async function executeBatchConnectionTx(connection: PoolConnection, statements: Statement[], firstAffected?: boolean): Promise<number> {
218
217
  if (!statements || statements.length === 0) {
219
- return Promise.resolve(0)
220
- } else if (statements.length === 1) {
218
+ return 0
219
+ }
220
+ if (statements.length === 1) {
221
221
  return execute(connection, statements[0].query, statements[0].params)
222
222
  }
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
223
+ await beginTransaction(connection, true)
224
+ try {
225
+ let count = 0
226
+
227
+ if (resource.multipleStatements) {
228
+ if (firstAffected) {
229
+ const firstCount = await execute(connection, statements[0].query, statements[0].params)
230
+
231
+ count = firstCount
341
232
 
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
233
+ if (firstCount === 0) {
234
+ await commit(connection, true)
235
+ return 0
346
236
  }
347
- commit(connection, true)
348
- return count
349
- } catch (err) {
350
- rollback(connection)
351
- throw err
237
+ const remaining = statements.slice(1)
238
+ count += await executeMultipleStatements(connection, remaining)
239
+ } else {
240
+ count = await executeMultipleStatements(connection, statements)
352
241
  }
353
242
  } 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
243
+ const start = firstAffected ? 1 : 0
244
+ if (firstAffected) {
245
+ const firstCount = await execute(connection, statements[0].query, statements[0].params)
246
+ count = firstCount
247
+ if (firstCount === 0) {
248
+ await commit(connection, true)
249
+ return 0
362
250
  }
363
- commit(connection, true)
364
- return count
365
- } catch (err) {
366
- rollback(connection)
367
- throw err
251
+ }
252
+ for (let i = start; i < statements.length; i++) {
253
+ const item = statements[i]
254
+ count += await execute(connection, item.query, item.params)
368
255
  }
369
256
  }
257
+
258
+ await commit(connection, true)
259
+
260
+ return count
261
+ } catch (err) {
262
+ try {
263
+ await rollback(connection)
264
+ } catch {
265
+ // Preserve the original error.
266
+ }
267
+ throw buildError(err)
370
268
  }
371
269
  }
372
- export async function executeBatchConnection(connection: PoolConnection, statements: Statement[], firstSuccess?: boolean): Promise<number> {
270
+
271
+ export async function executeBatchConnection(connection: PoolConnection, statements: Statement[], firstAffected?: boolean): Promise<number> {
373
272
  if (!statements || statements.length === 0) {
374
- return Promise.resolve(0)
375
- } else if (statements.length === 1) {
273
+ return 0
274
+ }
275
+
276
+ if (statements.length === 1) {
376
277
  return execute(connection, statements[0].query, statements[0].params)
377
278
  }
279
+
378
280
  if (resource.multipleStatements) {
379
- 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
- })
281
+ if (firstAffected) {
282
+ const firstCount = await execute(connection, statements[0].query, statements[0].params)
283
+
284
+ if (firstCount === 0) {
285
+ return 0
286
+ }
287
+
288
+ return firstCount + (await executeMultipleStatements(connection, statements.slice(1)))
451
289
  }
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
290
+
291
+ return executeMultipleStatements(connection, statements)
292
+ }
293
+
294
+ let count = 0
295
+ const start = firstAffected ? 1 : 0
296
+
297
+ if (firstAffected) {
298
+ const firstCount = await execute(connection, statements[0].query, statements[0].params)
299
+
300
+ count = firstCount
301
+
302
+ if (firstCount === 0) {
303
+ return 0
304
+ }
305
+ }
306
+
307
+ for (let i = start; i < statements.length; i++) {
308
+ const item = statements[i]
309
+
310
+ count += await execute(connection, item.query, item.params)
311
+ }
312
+
313
+ return count
314
+ }
315
+
316
+ async function executeMultipleStatements(connection: PoolConnection, statements: Statement[]): Promise<number> {
317
+ if (!statements || statements.length === 0) {
318
+ return 0
319
+ }
320
+
321
+ const queries: string[] = []
322
+ const params: any[] = []
323
+
324
+ for (const item of statements) {
325
+ queries.push(ensureSemicolon(item.query))
326
+
327
+ if (item.params && item.params.length > 0) {
328
+ params.push(...item.params)
329
+ }
330
+ }
331
+
332
+ return new Promise<number>((resolve, reject) => {
333
+ connection.query<any>(queries.join(""), toArray(params), (err, results) => {
334
+ if (err) {
335
+ buildError(err)
336
+ return reject(err)
472
337
  }
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
338
+
339
+ return resolve(getAffectedRows(results))
340
+ })
341
+ })
342
+ }
343
+ function ensureSemicolon(sql: string): string {
344
+ return sql.endsWith(";") ? sql : `${sql};`
345
+ }
346
+ function getAffectedRows(results: any): number {
347
+ if (!results) {
348
+ return 0
349
+ }
350
+
351
+ if (Array.isArray(results)) {
352
+ let count = 0
353
+
354
+ for (const result of results) {
355
+ if (result && typeof result.affectedRows === "number") {
356
+ count += result.affectedRows
485
357
  }
486
358
  }
359
+
360
+ return count
487
361
  }
362
+ if (typeof results.affectedRows === "number") {
363
+ return results.affectedRows
364
+ }
365
+ return 0
488
366
  }
489
367
  function buildError(err: any): any {
490
368
  if (err.errno === 1062 && err.code === "ER_DUP_ENTRY") {
@@ -496,36 +374,33 @@ function buildError(err: any): any {
496
374
  export async function execute(pool: Pool | PoolConnection, sql: string, args?: any[]): Promise<number> {
497
375
  const p = toArray(args)
498
376
  return new Promise<number>((resolve, reject) => {
499
- return pool.execute<ResultSetHeader>(sql, p, (err, res) => {
377
+ pool.execute<ResultSetHeader>(sql, p, (err, res) => {
500
378
  if (err) {
501
379
  buildError(err)
502
380
  return reject(err)
503
- } else {
504
- return resolve(res.affectedRows)
505
381
  }
382
+ return resolve(res.affectedRows)
506
383
  })
507
384
  })
508
385
  }
509
386
  export async function query<T>(pool: Pool | PoolConnection, sql: string, args?: any[], m?: StringMap, bools?: Attribute[]): Promise<T[]> {
510
387
  const p = toArray(args)
511
- return new Promise((resolve, reject) => {
512
- return pool.query<T[] & ResultSetHeader>(sql, p, (err, results, fields) => {
388
+ return new Promise<T[]>((resolve, reject) => {
389
+ pool.query<T[] & ResultSetHeader>(sql, p, (err, results, fields) => {
513
390
  if (err) {
514
391
  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
392
  }
393
+ if (results.length === 0) {
394
+ return resolve([])
395
+ }
396
+ const arrayResult = results.map((item) => {
397
+ if (Array.isArray(item)) {
398
+ return formatData<T>(fields, item)
399
+ }
400
+
401
+ return item
402
+ })
403
+ return resolve(handleResults(arrayResult, m, bools))
529
404
  })
530
405
  })
531
406
  }
@@ -535,30 +410,22 @@ export function queryOne<T>(pool: Pool | PoolConnection, sql: string, args?: any
535
410
  return r && r.length > 0 ? r[0] : null
536
411
  })
537
412
  }
538
- export function executeScalar<T>(pool: Pool | PoolConnection, sql: string, args?: any[]): Promise<T> {
413
+ export function executeScalar<T>(pool: Pool | PoolConnection, sql: string, args?: any[]): Promise<T | null> {
539
414
  return queryOne<T>(pool, sql, args).then((r) => {
540
415
  if (!r) {
541
416
  return null
542
- } else {
543
- const keys = Object.keys(r)
544
- return (r as any)[keys[0]]
545
417
  }
418
+ const keys = Object.keys(r)
419
+ return (r as any)[keys[0]]
546
420
  })
547
421
  }
548
422
 
549
423
  export function count(pool: Pool | PoolConnection, sql: string, args?: any[]): Promise<number> {
550
- return executeScalar<number>(pool, sql, args)
424
+ return executeScalar<number>(pool, sql, args).then((res) => (res !== null ? res : 0))
551
425
  }
552
426
 
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> {
561
- const s = buildToSave(obj, table, attrs, ver, buildParam)
427
+ export function save<T>(pool: Pool | PoolConnection | ((sql: string, args?: any[]) => Promise<number>), obj: T, table: string, attrs: Attributes, buildParam?: (i: number) => string): Promise<number> {
428
+ const s = buildToSave(obj, table, attrs, buildParam)
562
429
  if (!s.query) {
563
430
  return Promise.resolve(-1)
564
431
  }
@@ -568,15 +435,8 @@ export function save<T>(
568
435
  return execute(pool, s.query, s.params)
569
436
  }
570
437
  }
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> {
579
- const s = buildToSaveBatch(objs, table, attrs, ver, buildParam)
438
+ export function saveBatch<T>(pool: Pool | ((statements: Statement[]) => Promise<number>), objs: T[], table: string, attrs: Attributes, buildParam?: (i: number) => string): Promise<number> {
439
+ const s = buildToSaveBatch(objs, table, attrs, buildParam)
580
440
  if (typeof pool === "function") {
581
441
  return pool(s)
582
442
  } else {
@@ -588,64 +448,61 @@ export function toArray(arr?: any[]): any[] {
588
448
  return []
589
449
  }
590
450
  const p: any[] = []
591
- const l = arr.length
592
- for (let i = 0; i < l; i++) {
593
- if (arr[i] === undefined || arr[i] == null) {
451
+ for (const value of arr) {
452
+ if (value === undefined || value === null) {
594
453
  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
- }
454
+ continue
455
+ }
456
+ if (typeof value === "object") {
457
+ if (value instanceof Date) {
458
+ p.push(value)
459
+ continue
460
+ }
461
+ if (resource.string) {
462
+ p.push(JSON.stringify(value))
607
463
  } else {
608
- p.push(arr[i])
464
+ p.push(value)
609
465
  }
466
+ continue
610
467
  }
468
+ p.push(value)
611
469
  }
612
470
  return p
613
471
  }
614
- export function handleResults<T>(r: T[], m?: StringMap, bools?: Attribute[]) {
472
+ export function handleResults<T>(r: T[], m?: StringMap, bools?: Attribute[]): T[] {
615
473
  if (m) {
616
474
  const res = mapArray(r, m)
617
475
  if (bools && bools.length > 0) {
618
476
  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
477
  }
478
+ return res
479
+ }
480
+ if (bools && bools.length > 0) {
481
+ return handleBool(r, bools)
628
482
  }
483
+ return r
629
484
  }
630
- export function handleBool<T>(objs: T[], bools: Attribute[]) {
485
+ export function handleBool<T>(objs: T[], bools: Attribute[]): T[] {
631
486
  if (!bools || bools.length === 0 || !objs) {
632
487
  return objs
633
488
  }
634
489
  for (const obj of objs) {
635
490
  const o: any = obj
636
491
  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
- }
492
+ if (!field.name) {
493
+ continue
494
+ }
495
+ const v = o[field.name]
496
+ if (typeof v === "boolean" || v == null) {
497
+ continue
498
+ }
499
+ const b = field.true
500
+ if (b == null) {
501
+ // tslint:disable-next-line:triple-equals
502
+ o[field.name] = "1" == v || "T" == v || "Y" == v || "true" == v || "on" == v
503
+ } else {
504
+ // tslint:disable-next-line:triple-equals
505
+ o[field.name] = v == b
649
506
  }
650
507
  }
651
508
  }
@@ -655,7 +512,7 @@ export function formatData<T>(nameColumn: FieldPacket[], data: any, m?: StringMa
655
512
  const result: any = {}
656
513
  nameColumn.forEach((item, index) => {
657
514
  let key = item.name
658
- if (m) {
515
+ if (m && m[item.name]) {
659
516
  key = m[item.name]
660
517
  }
661
518
  result[key] = data[index]
@@ -689,10 +546,8 @@ export function mapArray<T>(results: T[], m?: StringMap): T[] {
689
546
  if (mkeys.length === 0) {
690
547
  return results
691
548
  }
692
- const objs = []
693
- const length = results.length
694
- for (let i = 0; i < length; i++) {
695
- const obj = results[i]
549
+ const objs: T[] = []
550
+ for (const obj of results) {
696
551
  const obj2: any = {}
697
552
  const keys = Object.keys(obj as any)
698
553
  for (const key of keys) {
@@ -751,11 +606,11 @@ export function isEmpty(s: string): boolean {
751
606
  return !(s && s.length > 0)
752
607
  }
753
608
  // tslint:disable-next-line:max-classes-per-file
754
- export class StringService {
609
+ export class StringAdapter {
755
610
  constructor(
756
611
  protected pool: Pool | PoolConnection,
757
- public table: string,
758
- public column: string,
612
+ protected table: string,
613
+ protected column: string,
759
614
  ) {
760
615
  this.load = this.load.bind(this)
761
616
  this.save = this.save.bind(this)
@@ -779,44 +634,19 @@ export class StringService {
779
634
  }
780
635
  }
781
636
 
782
- export function version(attrs: Attributes): Attribute | undefined {
783
- const ks = Object.keys(attrs)
784
- for (const k of ks) {
785
- const attr = attrs[k]
786
- if (attr.version) {
787
- attr.name = k
788
- return attr
789
- }
790
- }
791
- return undefined
792
- }
793
637
  // tslint:disable-next-line:max-classes-per-file
794
638
  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
639
+ protected param?: (i: number) => string
800
640
  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,
641
+ protected pool: Pool | PoolConnection,
642
+ protected table: string,
643
+ protected attributes: Attributes,
644
+ protected oneIfSuccess?: boolean,
645
+ protected map?: (v: T) => T,
806
646
  buildParam?: (i: number) => string,
807
647
  ) {
808
648
  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
816
- const x = version(attributes)
817
- if (x) {
818
- this.version = x.name
819
- }
649
+ this.param = buildParam ? buildParam : param
820
650
  }
821
651
  write(obj: T): Promise<number> {
822
652
  if (!obj) {
@@ -826,20 +656,12 @@ export class MySQLWriter<T> {
826
656
  if (this.map) {
827
657
  obj2 = this.map(obj)
828
658
  }
829
- const stmt = buildToSave(obj2, this.table, this.attributes, this.version, this.param)
659
+ const stmt = buildToSave(obj2, this.table, this.attributes, this.param)
830
660
  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
- }
661
+ if (this.oneIfSuccess) {
662
+ return execute(this.pool, stmt.query, stmt.params).then((ct) => (ct > 0 ? 1 : 0))
837
663
  } 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
- }
664
+ return execute(this.pool, stmt.query, stmt.params)
843
665
  }
844
666
  } else {
845
667
  return Promise.resolve(0)
@@ -848,37 +670,19 @@ export class MySQLWriter<T> {
848
670
  }
849
671
  // tslint:disable-next-line:max-classes-per-file
850
672
  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
673
+ protected list: T[] = []
674
+ protected param?: (i: number) => string
858
675
  constructor(
859
- pool: Pool | ((statements: Statement[]) => Promise<number>),
860
- public table: string,
861
- public attributes: Attributes,
862
- size?: number,
863
- toDB?: (v: T) => T,
676
+ protected pool: Pool,
677
+ protected table: string,
678
+ protected attributes: Attributes,
679
+ protected size: number = 1000,
680
+ protected map?: (v: T) => T,
864
681
  buildParam?: (i: number) => string,
865
682
  ) {
866
683
  this.write = this.write.bind(this)
867
684
  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
875
- const x = version(attributes)
876
- if (x) {
877
- this.version = x.name
878
- }
879
- if (size) {
880
- this.size = size
881
- }
685
+ this.param = buildParam ? buildParam : param
882
686
  }
883
687
  write(obj: T): Promise<number> {
884
688
  if (!obj) {
@@ -901,21 +705,14 @@ export class MySQLStreamWriter<T> {
901
705
  if (!this.list || this.list.length === 0) {
902
706
  return Promise.resolve(0)
903
707
  } else {
904
- const total = this.list.length
905
- const stmt = buildToSaveBatch(this.list, this.table, this.attributes, this.version, this.param)
708
+ const stmt = buildToSaveBatch(this.list, this.table, this.attributes, this.param)
906
709
  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
- }
710
+ return executeBatch(this.pool as any, stmt).then((r) => {
711
+ this.list = []
712
+ return stmt.length
713
+ })
918
714
  } else {
715
+ this.list = []
919
716
  return Promise.resolve(0)
920
717
  }
921
718
  }
@@ -923,31 +720,17 @@ export class MySQLStreamWriter<T> {
923
720
  }
924
721
  // tslint:disable-next-line:max-classes-per-file
925
722
  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
723
+ protected param?: (i: number) => string
931
724
  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,
725
+ protected pool: Pool,
726
+ protected table: string,
727
+ protected attributes: Attributes,
728
+ protected oneIfSuccess?: boolean,
729
+ protected map?: (v: T) => T,
937
730
  buildParam?: (i: number) => string,
938
731
  ) {
939
732
  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
947
- const x = version(attributes)
948
- if (x) {
949
- this.version = x.name
950
- }
733
+ this.param = buildParam ? buildParam : param
951
734
  }
952
735
  write(objs: T[]): Promise<number> {
953
736
  if (!objs || objs.length === 0) {
@@ -961,20 +744,12 @@ export class MySQLBatchWriter<T> {
961
744
  list.push(obj2)
962
745
  }
963
746
  }
964
- const stmts = buildToSaveBatch(list, this.table, this.attributes, this.version, this.param)
747
+ const stmts = buildToSaveBatch(list, this.table, this.attributes, this.param)
965
748
  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
- }
749
+ if (this.oneIfSuccess) {
750
+ return executeBatch(this.pool, stmts).then((ct) => stmts.length)
972
751
  } 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
- }
752
+ return executeBatch(this.pool, stmts)
978
753
  }
979
754
  } else {
980
755
  return Promise.resolve(0)
@@ -1051,6 +826,9 @@ export class MySQLChecker implements HealthChecker {
1051
826
  }
1052
827
  }
1053
828
 
829
+ export interface SimpleMap {
830
+ [key: string]: string | number | boolean | Date
831
+ }
1054
832
  export interface Formatter<T> {
1055
833
  format: (row: T) => string
1056
834
  }
@@ -1065,44 +843,60 @@ export interface QueryBuilder {
1065
843
  // tslint:disable-next-line:max-classes-per-file
1066
844
  export class Exporter<T> {
1067
845
  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,
846
+ protected connection: Connection,
847
+ protected filename: string,
848
+ protected buildQuery: (ctx?: any) => Promise<Statement>,
849
+ protected format: (row: T) => string,
850
+ protected write: (chunk: string) => boolean,
851
+ protected end: (cb?: () => void) => void,
852
+ protected attributes?: Attributes,
853
+ protected logInfo?: (msg: string, m?: SimpleMap) => void,
854
+ protected progressSize: number = 10000,
1074
855
  ) {
1075
- this.format = ft
1076
856
  if (attributes) {
1077
857
  this.map = buildMap(attributes)
1078
858
  }
1079
859
  this.export = this.export.bind(this)
1080
860
  }
1081
861
  map?: StringMap
1082
- format: (row: T) => string
1083
862
  async export(ctx?: any): Promise<number> {
1084
- let idx = 0
1085
863
  const stmt = await this.buildQuery(ctx)
1086
864
  const reader = this.connection.query(stmt.query, stmt.params)
1087
865
  let er: any
866
+ let i = 0
867
+ let j = 0
1088
868
  reader.on("error", (err) => (er = err))
1089
869
  // (D2) WRITE ROW-BY-ROW
1090
870
  if (this.map) {
1091
871
  reader.on("result", async (row: any) => {
1092
- ++idx
872
+ ++i
873
+ j++
1093
874
  this.connection.pause()
1094
875
  const obj = mapOne<T>(row, this.map)
1095
876
  const data = this.format(obj)
1096
877
  this.write(data)
1097
878
  this.connection.resume()
879
+ if (j >= this.progressSize) {
880
+ if (this.logInfo) {
881
+ this.logInfo(`Progress: ${i} records processed of file '${this.filename}'`)
882
+ }
883
+ j = 0
884
+ }
1098
885
  })
1099
886
  } else {
1100
887
  reader.on("result", async (row: any) => {
1101
- ++idx
888
+ ++i
889
+ j++
1102
890
  this.connection.pause()
1103
891
  const data = this.format(row as T)
1104
892
  this.write(data)
1105
893
  this.connection.resume()
894
+ if (j >= this.progressSize) {
895
+ if (this.logInfo) {
896
+ this.logInfo(`Progress: ${i} records processed of file '${this.filename}'`)
897
+ }
898
+ j = 0
899
+ }
1106
900
  })
1107
901
  }
1108
902
  // (D3) CLOSE CONNECTION + FILE
@@ -1116,7 +910,7 @@ export class Exporter<T> {
1116
910
  if (err) {
1117
911
  reject(err)
1118
912
  } else {
1119
- resolve(idx)
913
+ resolve(i)
1120
914
  }
1121
915
  })
1122
916
  }
@@ -1127,11 +921,14 @@ export class Exporter<T> {
1127
921
  // tslint:disable-next-line:max-classes-per-file
1128
922
  export class ExportService<T> {
1129
923
  constructor(
1130
- public connection: Connection,
1131
- public queryBuilder: QueryBuilder,
1132
- public formatter: Formatter<T>,
1133
- public writer: FileWriter,
1134
- public attributes?: Attributes,
924
+ protected connection: Connection,
925
+ protected filename: string,
926
+ protected queryBuilder: QueryBuilder,
927
+ protected formatter: Formatter<T>,
928
+ protected writer: FileWriter,
929
+ protected attributes?: Attributes,
930
+ protected logInfo?: (msg: string, m?: SimpleMap) => void,
931
+ protected progressSize: number = 10000,
1135
932
  ) {
1136
933
  if (attributes) {
1137
934
  this.map = buildMap(attributes)
@@ -1140,28 +937,43 @@ export class ExportService<T> {
1140
937
  }
1141
938
  map?: StringMap
1142
939
  async export(ctx?: any): Promise<number> {
1143
- let idx = 0
1144
940
  const stmt = await this.queryBuilder.build(ctx)
1145
941
  const reader = this.connection.query(stmt.query, stmt.params)
1146
942
  let er: any
1147
943
  reader.on("error", (err) => (er = err))
944
+ let i = 0
945
+ let j = 0
1148
946
  // (D2) WRITE ROW-BY-ROW
1149
947
  if (this.map) {
1150
948
  reader.on("result", async (row: any) => {
1151
- ++idx
949
+ ++i
950
+ j++
1152
951
  this.connection.pause()
1153
952
  const obj = mapOne<T>(row, this.map)
1154
953
  const data = this.formatter.format(obj)
1155
954
  this.writer.write(data)
1156
955
  this.connection.resume()
956
+ if (j >= this.progressSize) {
957
+ if (this.logInfo) {
958
+ this.logInfo(`Progress: ${i} records processed of file '${this.filename}'`)
959
+ }
960
+ j = 0
961
+ }
1157
962
  })
1158
963
  } else {
1159
964
  reader.on("result", async (row: any) => {
1160
- ++idx
965
+ ++i
966
+ j++
1161
967
  this.connection.pause()
1162
968
  const data = this.formatter.format(row as T)
1163
969
  this.writer.write(data)
1164
970
  this.connection.resume()
971
+ if (j >= this.progressSize) {
972
+ if (this.logInfo) {
973
+ this.logInfo(`Progress: ${i} records processed of file '${this.filename}'`)
974
+ }
975
+ j = 0
976
+ }
1165
977
  })
1166
978
  }
1167
979
  // (D3) CLOSE CONNECTION + FILE
@@ -1179,7 +991,7 @@ export class ExportService<T> {
1179
991
  if (err) {
1180
992
  reject(err)
1181
993
  } else {
1182
- resolve(idx)
994
+ resolve(i)
1183
995
  }
1184
996
  })
1185
997
  }