@bdkinc/knex-ibmi 0.3.20 → 0.3.22

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/README.md CHANGED
@@ -248,3 +248,16 @@ If that still doesn't work, then unixodbc is probably looking for the config fil
248
248
  A common case is that the configs are in `/etc` but your system expects them to be somewhere else.
249
249
  In such a case, override the path unixodbc looks in via the `ODBCSYSINI` and `ODBCINI` environment variables.
250
250
  E.g., `ODBCINI=/etc ODBCSYSINI=/etc`.
251
+
252
+ ## Bundling with Vite
253
+ If you are bundling your application with Vite, then you will need to add this to your config.
254
+
255
+ ```javascript
256
+ // vite.config.js
257
+
258
+ export default {
259
+ optimizeDeps: {
260
+ exclude: ["@mapbox"],
261
+ }
262
+ }
263
+ ```
package/dist/index.d.ts CHANGED
@@ -48,6 +48,26 @@ declare class IBMiQueryCompiler extends QueryCompiler {
48
48
  columnizeWithPrefix(prefix: string, target: any): string;
49
49
  }
50
50
 
51
+ interface QueryObject {
52
+ response?: {
53
+ rows: any[];
54
+ rowCount: number;
55
+ };
56
+ sqlMethod: SqlMethod;
57
+ output?: (runner: any, response: any) => any;
58
+ pluck?: (row: any) => any;
59
+ select?: boolean;
60
+ }
61
+ declare enum SqlMethod {
62
+ SELECT = "select",
63
+ PLUCK = "pluck",
64
+ FIRST = "first",
65
+ INSERT = "insert",
66
+ DELETE = "del",
67
+ DELETE_ALT = "delete",
68
+ UPDATE = "update",
69
+ COUNTER = "counter"
70
+ }
51
71
  declare class DB2Client extends knex.Client {
52
72
  constructor(config: Knex.Config<DB2Config>);
53
73
  _driver(): typeof odbc;
@@ -58,19 +78,28 @@ declare class DB2Client extends knex.Client {
58
78
  acquireRawConnection(): Promise<any>;
59
79
  destroyRawConnection(connection: any): Promise<any>;
60
80
  _getConnectionString(connectionConfig: DB2ConnectionConfig): string;
61
- _query(connection: any, obj: any): Promise<any>;
81
+ _query(connection: Connection, obj: any): Promise<any>;
82
+ private normalizeQueryObject;
83
+ private determineQueryMethod;
84
+ private isSelectMethod;
85
+ private executeSelectQuery;
86
+ private executeStatementQuery;
87
+ private formatStatementResponse;
62
88
  _stream(connection: Connection, obj: {
63
89
  sql: string;
64
90
  bindings: any[];
65
91
  }, stream: any, options: {
66
92
  fetchSize?: number;
67
93
  }): Promise<unknown>;
94
+ private _createCursorStream;
68
95
  transaction(container: any, config: any, outerTx: any): Knex.Transaction;
69
96
  schemaCompiler(tableBuilder: any): IBMiSchemaCompiler;
70
97
  tableCompiler(tableBuilder: any): IBMiTableCompiler;
71
98
  columnCompiler(tableCompiler: any, columnCompiler: any): IBMiColumnCompiler;
72
99
  queryCompiler(builder: Knex.QueryBuilder, bindings?: any[]): IBMiQueryCompiler;
73
- processResponse(obj: any, runner: any): any;
100
+ processResponse(obj: QueryObject | null, runner: any): any;
101
+ private validateResponse;
102
+ private processSqlMethod;
74
103
  }
75
104
  interface DB2PoolConfig {
76
105
  min?: number;
@@ -91,8 +120,20 @@ interface DB2ConnectionParams {
91
120
  DECFLOATERROROPTION?: 0 | 1;
92
121
  DECFLOATROUNDMODE?: 0 | 1 | 2 | 3 | 4 | 5 | 6;
93
122
  MAPDECIMALFLOATDESCRIBE?: 1 | 3;
123
+ TFT?: 0 | 1 | 2 | 3 | 4;
124
+ TSP?: 0 | 1 | 2 | 3;
125
+ TSFT?: 0 | 1;
126
+ XMLCURIMPPARSE?: 0 | 1;
127
+ XMLDECLARATION?: 1 | 2 | 3 | 4;
94
128
  ALLOWPROCCALLS?: 0 | 1;
95
129
  XDYNAMIC?: 0 | 1;
130
+ DFTPKGLIB?: string;
131
+ PKG?: 0 | 1 | 2;
132
+ BLOCKFETCH?: 0 | 1;
133
+ COMPRESSION?: 0 | 1;
134
+ CONCURRENCY?: 0 | 1;
135
+ CURSORSENSITIVITY?: 0 | 1 | 2;
136
+ EXTCOLINFO?: "SQL_DESC_AUTO_UNIQUE_VALUE" | "SQL_DESC_BASE_COLUMN_NAME" | "SQL_DESC_BASE_TABLE_NAME and SQL_DESC_TABLE_NAME" | "SQL_DESC_LABEL" | "SQL_DESC_SCHEMA_NAME" | "SQL_DESC_SEARCHABLE" | "SQL_DESC_UNNAMED" | "SQL_DESC_UPDATABLE";
96
137
  }
97
138
  interface DB2ConnectionConfig {
98
139
  database: string;
package/dist/index.js CHANGED
@@ -205,17 +205,13 @@ var IBMiQueryCompiler = class extends import_querycompiler.default {
205
205
  _buildInsertData(insertValues, returningSql) {
206
206
  let sql = "";
207
207
  const insertData = this._prepInsert(insertValues);
208
- if (typeof insertData === "string") {
209
- sql += insertData;
208
+ if (insertData.columns.length) {
209
+ sql += `(${this.formatter.columnize(insertData.columns)}`;
210
+ sql += `) ${returningSql}values (` + this._buildInsertValues(insertData) + ")";
211
+ } else if (insertValues.length === 1 && insertValues[0]) {
212
+ sql += returningSql + this._emptyInsertValue;
210
213
  } else {
211
- if (insertData.columns.length) {
212
- sql += `(${this.formatter.columnize(insertData.columns)}`;
213
- sql += `) ${returningSql}values (` + this._buildInsertValues(insertData) + ")";
214
- } else if (insertValues.length === 1 && insertValues[0]) {
215
- sql += returningSql + this._emptyInsertValue;
216
- } else {
217
- return "";
218
- }
214
+ return "";
219
215
  }
220
216
  return sql;
221
217
  }
@@ -280,6 +276,7 @@ var IBMiQueryCompiler = class extends import_querycompiler.default {
280
276
  const { returning } = this.single;
281
277
  let sql = "";
282
278
  if (returning) {
279
+ console.error("IBMi DB2 does not support returning in update statements, only inserts");
283
280
  sql += `select ${this.formatter.columnize(this.single.returning)} from FINAL TABLE(`;
284
281
  }
285
282
  sql += withSQL + `update ${this.single.only ? "only " : ""}${this.tableName} set ` + updates.join(", ") + (where ? ` ${where}` : "") + (order ? ` ${order}` : "") + (limit ? ` ${limit}` : "");
@@ -360,7 +357,6 @@ var DB2Client = class extends import_knex.knex.Client {
360
357
  if (this.logger.error) {
361
358
  this.logger.error("knex-ibmi: " + message);
362
359
  }
363
- throw new Error(message);
364
360
  }
365
361
  printWarn(message) {
366
362
  if (import_node_process.default.env.DEBUG === "true") {
@@ -413,42 +409,61 @@ var DB2Client = class extends import_knex.knex.Client {
413
409
  }
414
410
  // Runs the query on the specified connection, providing the bindings
415
411
  async _query(connection, obj) {
416
- if (!obj || typeof obj == "string") {
417
- obj = { sql: obj };
418
- }
419
- const method = (obj.hasOwnProperty("method") && obj.method !== "raw" ? obj.method : obj.sql.split(" ")[0]).toLowerCase();
420
- obj.sqlMethod = method;
421
- if (method === "select" || method === "first" || method === "pluck") {
422
- const rows = await connection.query(obj.sql, obj.bindings);
423
- if (rows) {
424
- obj.response = { rows, rowCount: rows.length };
425
- }
412
+ const queryObject = this.normalizeQueryObject(obj);
413
+ const method = this.determineQueryMethod(queryObject);
414
+ queryObject.sqlMethod = method;
415
+ if (this.isSelectMethod(method)) {
416
+ await this.executeSelectQuery(connection, queryObject);
426
417
  } else {
427
- try {
428
- const statement = await connection.createStatement();
429
- await statement.prepare(obj.sql);
430
- if (obj.bindings) {
431
- await statement.bind(obj.bindings);
432
- }
433
- const result = await statement.execute();
434
- this.printDebug(result);
435
- if (result.statement.includes("IDENTITY_VAL_LOCAL()")) {
436
- obj.response = {
437
- rows: result.map(
438
- (row) => result.columns && result.columns?.length > 0 ? row[result.columns[0].name] : row
439
- ),
440
- rowCount: result.count
441
- };
442
- } else {
443
- obj.response = { rows: result, rowCount: result.count };
444
- }
445
- } catch (err) {
446
- this.printError(JSON.stringify(err));
447
- }
418
+ await this.executeStatementQuery(connection, queryObject);
419
+ }
420
+ this.printDebug(queryObject);
421
+ return queryObject;
422
+ }
423
+ normalizeQueryObject(obj) {
424
+ if (!obj || typeof obj === "string") {
425
+ return { sql: obj };
448
426
  }
449
- this.printDebug(obj);
450
427
  return obj;
451
428
  }
429
+ determineQueryMethod(obj) {
430
+ return (obj.hasOwnProperty("method") && obj.method !== "raw" ? obj.method : obj.sql.split(" ")[0]).toLowerCase();
431
+ }
432
+ isSelectMethod(method) {
433
+ return method === "select" || method === "first" || method === "pluck";
434
+ }
435
+ async executeSelectQuery(connection, obj) {
436
+ const rows = await connection.query(obj.sql, obj.bindings);
437
+ if (rows) {
438
+ obj.response = { rows, rowCount: rows.length };
439
+ }
440
+ }
441
+ async executeStatementQuery(connection, obj) {
442
+ try {
443
+ const statement = await connection.createStatement();
444
+ await statement.prepare(obj.sql);
445
+ if (obj.bindings) {
446
+ await statement.bind(obj.bindings);
447
+ }
448
+ const result = await statement.execute();
449
+ this.printDebug(String(result));
450
+ obj.response = this.formatStatementResponse(result);
451
+ } catch (err) {
452
+ this.printError(JSON.stringify(err));
453
+ }
454
+ }
455
+ formatStatementResponse(result) {
456
+ if (result.statement.includes("IDENTITY_VAL_LOCAL()")) {
457
+ return {
458
+ rows: result.map(
459
+ (row) => result.columns && result.columns?.length > 0 ? row[result.columns[0].name] : row
460
+ ),
461
+ rowCount: result.count
462
+ };
463
+ } else {
464
+ return { rows: result, rowCount: result.count };
465
+ }
466
+ }
452
467
  async _stream(connection, obj, stream, options) {
453
468
  if (!obj.sql) throw new Error("A query is required to stream results");
454
469
  return new Promise((resolve, reject) => {
@@ -464,29 +479,9 @@ var DB2Client = class extends import_knex.knex.Client {
464
479
  (error, cursor) => {
465
480
  if (error) {
466
481
  this.printError(JSON.stringify(error, null, 2));
482
+ return;
467
483
  }
468
- const readableStream = new import_node_stream.Readable({
469
- objectMode: true,
470
- read() {
471
- cursor.fetch((error2, result) => {
472
- if (error2) {
473
- console.log(JSON.stringify(error2, null, 2));
474
- }
475
- if (!cursor.noData) {
476
- this.push(result);
477
- } else {
478
- cursor.close((error3) => {
479
- if (error3) {
480
- console.log(JSON.stringify(error3, null, 2));
481
- }
482
- if (result) {
483
- this.push(result);
484
- }
485
- });
486
- }
487
- });
488
- }
489
- });
484
+ const readableStream = this._createCursorStream(cursor);
490
485
  readableStream.on("error", (err) => {
491
486
  reject(err);
492
487
  stream.emit("error", err);
@@ -496,6 +491,32 @@ var DB2Client = class extends import_knex.knex.Client {
496
491
  );
497
492
  });
498
493
  }
494
+ _createCursorStream(cursor) {
495
+ const parentThis = this;
496
+ return new import_node_stream.Readable({
497
+ objectMode: true,
498
+ read() {
499
+ cursor.fetch((error, result) => {
500
+ if (error) {
501
+ parentThis.printError(JSON.stringify(error, null, 2));
502
+ }
503
+ if (!cursor.noData) {
504
+ this.push(result);
505
+ } else {
506
+ cursor.close((closeError) => {
507
+ if (closeError) {
508
+ parentThis.printError(JSON.stringify(closeError, null, 2));
509
+ }
510
+ if (result) {
511
+ this.push(result);
512
+ }
513
+ this.push(null);
514
+ });
515
+ }
516
+ });
517
+ }
518
+ });
519
+ }
499
520
  transaction(container, config, outerTx) {
500
521
  return new ibmi_transaction_default(this, container, config, outerTx);
501
522
  }
@@ -513,30 +534,40 @@ var DB2Client = class extends import_knex.knex.Client {
513
534
  }
514
535
  processResponse(obj, runner) {
515
536
  if (obj === null) return null;
516
- const resp = obj.response;
517
- const method = obj.sqlMethod;
518
- if (!resp) {
537
+ const validationResult = this.validateResponse(obj);
538
+ if (validationResult !== null) return validationResult;
539
+ const { response } = obj;
540
+ if (obj.output) {
541
+ return obj.output(runner, response);
542
+ }
543
+ return this.processSqlMethod(obj);
544
+ }
545
+ validateResponse(obj) {
546
+ if (!obj.response) {
519
547
  this.printDebug("response undefined" + obj);
548
+ return void 0;
520
549
  }
521
- const { rows, rowCount } = resp;
522
- if (obj.output) return obj.output.call(runner, resp);
523
- switch (method) {
524
- case "select":
550
+ if (!obj.response.rows) {
551
+ return this.printError("rows undefined" + obj);
552
+ }
553
+ return null;
554
+ }
555
+ processSqlMethod(obj) {
556
+ const { rows, rowCount } = obj.response;
557
+ switch (obj.sqlMethod) {
558
+ case "select" /* SELECT */:
525
559
  return rows;
526
- case "pluck":
560
+ case "pluck" /* PLUCK */:
527
561
  return rows.map(obj.pluck);
528
- case "first":
562
+ case "first" /* FIRST */:
529
563
  return rows[0];
530
- case "insert":
564
+ case "insert" /* INSERT */:
531
565
  return rows;
532
- case "del":
533
- case "delete":
534
- case "update":
535
- if (obj.select) {
536
- return rows;
537
- }
538
- return rowCount;
539
- case "counter":
566
+ case "del" /* DELETE */:
567
+ case "delete" /* DELETE_ALT */:
568
+ case "update" /* UPDATE */:
569
+ return obj.select ? rows : rowCount;
570
+ case "counter" /* COUNTER */:
540
571
  return rowCount;
541
572
  default:
542
573
  return rows;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bdkinc/knex-ibmi",
3
- "version": "0.3.20",
3
+ "version": "0.3.22",
4
4
  "description": "Knex dialect for IBMi",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",