@bdkinc/knex-ibmi 0.3.21 → 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/LICENSE CHANGED
File without changes
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}` : "");
@@ -412,42 +409,61 @@ var DB2Client = class extends import_knex.knex.Client {
412
409
  }
413
410
  // Runs the query on the specified connection, providing the bindings
414
411
  async _query(connection, obj) {
415
- if (!obj || typeof obj == "string") {
416
- obj = { sql: obj };
417
- }
418
- const method = (obj.hasOwnProperty("method") && obj.method !== "raw" ? obj.method : obj.sql.split(" ")[0]).toLowerCase();
419
- obj.sqlMethod = method;
420
- if (method === "select" || method === "first" || method === "pluck") {
421
- const rows = await connection.query(obj.sql, obj.bindings);
422
- if (rows) {
423
- obj.response = { rows, rowCount: rows.length };
424
- }
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);
425
417
  } else {
426
- try {
427
- const statement = await connection.createStatement();
428
- await statement.prepare(obj.sql);
429
- if (obj.bindings) {
430
- await statement.bind(obj.bindings);
431
- }
432
- const result = await statement.execute();
433
- this.printDebug(result);
434
- if (result.statement.includes("IDENTITY_VAL_LOCAL()")) {
435
- obj.response = {
436
- rows: result.map(
437
- (row) => result.columns && result.columns?.length > 0 ? row[result.columns[0].name] : row
438
- ),
439
- rowCount: result.count
440
- };
441
- } else {
442
- obj.response = { rows: result, rowCount: result.count };
443
- }
444
- } catch (err) {
445
- this.printError(JSON.stringify(err));
446
- }
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 };
447
426
  }
448
- this.printDebug(obj);
449
427
  return obj;
450
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
+ }
451
467
  async _stream(connection, obj, stream, options) {
452
468
  if (!obj.sql) throw new Error("A query is required to stream results");
453
469
  return new Promise((resolve, reject) => {
@@ -463,29 +479,9 @@ var DB2Client = class extends import_knex.knex.Client {
463
479
  (error, cursor) => {
464
480
  if (error) {
465
481
  this.printError(JSON.stringify(error, null, 2));
482
+ return;
466
483
  }
467
- const readableStream = new import_node_stream.Readable({
468
- objectMode: true,
469
- read() {
470
- cursor.fetch((error2, result) => {
471
- if (error2) {
472
- console.log(JSON.stringify(error2, null, 2));
473
- }
474
- if (!cursor.noData) {
475
- this.push(result);
476
- } else {
477
- cursor.close((error3) => {
478
- if (error3) {
479
- console.log(JSON.stringify(error3, null, 2));
480
- }
481
- if (result) {
482
- this.push(result);
483
- }
484
- });
485
- }
486
- });
487
- }
488
- });
484
+ const readableStream = this._createCursorStream(cursor);
489
485
  readableStream.on("error", (err) => {
490
486
  reject(err);
491
487
  stream.emit("error", err);
@@ -495,6 +491,32 @@ var DB2Client = class extends import_knex.knex.Client {
495
491
  );
496
492
  });
497
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
+ }
498
520
  transaction(container, config, outerTx) {
499
521
  return new ibmi_transaction_default(this, container, config, outerTx);
500
522
  }
@@ -512,30 +534,40 @@ var DB2Client = class extends import_knex.knex.Client {
512
534
  }
513
535
  processResponse(obj, runner) {
514
536
  if (obj === null) return null;
515
- const resp = obj.response;
516
- const method = obj.sqlMethod;
517
- 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) {
518
547
  this.printDebug("response undefined" + obj);
548
+ return void 0;
519
549
  }
520
- const { rows, rowCount } = resp;
521
- if (obj.output) return obj.output.call(runner, resp);
522
- switch (method) {
523
- 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 */:
524
559
  return rows;
525
- case "pluck":
560
+ case "pluck" /* PLUCK */:
526
561
  return rows.map(obj.pluck);
527
- case "first":
562
+ case "first" /* FIRST */:
528
563
  return rows[0];
529
- case "insert":
564
+ case "insert" /* INSERT */:
530
565
  return rows;
531
- case "del":
532
- case "delete":
533
- case "update":
534
- if (obj.select) {
535
- return rows;
536
- }
537
- return rowCount;
538
- 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 */:
539
571
  return rowCount;
540
572
  default:
541
573
  return rows;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bdkinc/knex-ibmi",
3
- "version": "0.3.21",
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",