@bdkinc/knex-ibmi 0.0.16 → 0.0.18

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
@@ -17,7 +17,6 @@ This is an external dialect for [knex](https://github.com/tgriesser/knex). This
17
17
  Currently, this dialect has limited functionality compared to the Knex built-in dialects. Below are some of the limitations:
18
18
 
19
19
  - No streaming support
20
- - Updates return the value of the first column in that row. Make sure your identifier is the first column in the table. The returning option does not work on updates.
21
20
  - Possibly other missing functionality
22
21
  - Journaling must be handled separately. After a migration is ran journaling can be configured on the newly created tables. I recommend using the schema utility in the i access client solutions software.
23
22
 
package/dist/index.d.mts CHANGED
@@ -1,91 +1,3 @@
1
- import * as odbc from 'odbc';
2
- import { Connection } from 'odbc';
3
- import { knex, Knex } from 'knex';
4
- import SchemaCompiler from 'knex/lib/schema/compiler';
5
- import TableCompiler from 'knex/lib/schema/tablecompiler';
6
- import ColumnCompiler from 'knex/lib/schema/columncompiler';
7
- import QueryCompiler from 'knex/lib/query/querycompiler';
8
-
9
- declare class IBMiSchemaCompiler extends SchemaCompiler {
10
- hasTable(tableName: any): void;
11
- toSQL(): any;
12
- }
13
-
14
- declare class IBMiTableCompiler extends TableCompiler {
15
- createQuery(columns: any, ifNot: any, like: any): void;
16
- dropUnique(columns: any, indexName: any): void;
17
- unique(columns: any, indexName: any): void;
18
- addColumns(columns: any, prefix: any): void;
19
- commit(conn: any, value: any): Promise<any>;
20
- }
21
-
22
- declare class IBMiColumnCompiler extends ColumnCompiler {
23
- increments(options?: {
24
- primaryKey: boolean;
25
- }): string;
26
- }
27
-
28
- declare class IBMiQueryCompiler extends QueryCompiler {
29
- insert(): "" | {
30
- sql: string;
31
- returning: any;
32
- };
33
- _buildInsertData(insertValues: any, returningSql: any): string;
34
- _prepInsert(data: any): any;
35
- _returning(method: any, value: any, withTrigger: any): string | undefined;
36
- columnizeWithPrefix(prefix: any, target: any): string;
37
- }
38
-
39
- declare class DB2Client extends knex.Client {
40
- constructor(config: any);
41
- _driver(): typeof odbc;
42
- printDebug(message: string): void;
43
- acquireRawConnection(): Promise<any>;
44
- destroyRawConnection(connection: Connection): Promise<void>;
45
- _getConnectionString(connectionConfig: any): string;
46
- _query(connection: any, obj: any): Promise<any>;
47
- _selectAfterUpdate(): string;
48
- transaction(container: any, config: any, outerTx: any): Knex.Transaction;
49
- schemaCompiler(): IBMiSchemaCompiler;
50
- tableCompiler(): IBMiTableCompiler;
51
- columnCompiler(): IBMiColumnCompiler;
52
- queryCompiler(): IBMiQueryCompiler;
53
- processResponse(obj: any, runner: any): any;
54
- }
55
- interface DB2PoolConfig {
56
- min: number;
57
- max: number;
58
- }
59
- interface DB2ConnectionParams {
60
- CMT?: number;
61
- CONNTYPE?: number;
62
- DBQ?: string;
63
- MAXDECPREC?: 31 | 63;
64
- MAXDECSCALE?: number;
65
- MINDIVSCALE?: 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9;
66
- NAM?: 0 | 1;
67
- DFT?: 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7;
68
- DSP?: 0 | 1 | 2 | 3 | 4;
69
- DEC?: 0 | 1;
70
- DECFLOATERROROPTION?: 0 | 1;
71
- DECFLOATROUNDMODE?: 0 | 1 | 2 | 3 | 4 | 5 | 6;
72
- MAPDECIMALFLOATDESCRIBE?: 1 | 3;
73
- }
74
- interface DB2ConnectionConfig {
75
- database: string;
76
- host: string;
77
- port: 50000 | number;
78
- user: string;
79
- password: string;
80
- driver: "IBM i Access ODBC Driver" | string;
81
- connectionStringParams?: DB2ConnectionParams;
82
- pool?: DB2PoolConfig;
83
- }
84
- interface DB2Config {
85
- client: any;
86
- connection: DB2ConnectionConfig;
87
- pool?: DB2PoolConfig;
88
- }
89
- declare const DB2Dialect: typeof DB2Client;
90
-
91
- export { DB2Config, DB2Dialect, DB2Client as default };
1
+ declare module "knex/lib/query/querycompiler" {}
2
+ declare module "knex/lib/schema/tablecompiler" {}
3
+ declare module "knex/lib/schema/compiler" {}
package/dist/index.d.ts CHANGED
@@ -1,91 +1,3 @@
1
- import * as odbc from 'odbc';
2
- import { Connection } from 'odbc';
3
- import { knex, Knex } from 'knex';
4
- import SchemaCompiler from 'knex/lib/schema/compiler';
5
- import TableCompiler from 'knex/lib/schema/tablecompiler';
6
- import ColumnCompiler from 'knex/lib/schema/columncompiler';
7
- import QueryCompiler from 'knex/lib/query/querycompiler';
8
-
9
- declare class IBMiSchemaCompiler extends SchemaCompiler {
10
- hasTable(tableName: any): void;
11
- toSQL(): any;
12
- }
13
-
14
- declare class IBMiTableCompiler extends TableCompiler {
15
- createQuery(columns: any, ifNot: any, like: any): void;
16
- dropUnique(columns: any, indexName: any): void;
17
- unique(columns: any, indexName: any): void;
18
- addColumns(columns: any, prefix: any): void;
19
- commit(conn: any, value: any): Promise<any>;
20
- }
21
-
22
- declare class IBMiColumnCompiler extends ColumnCompiler {
23
- increments(options?: {
24
- primaryKey: boolean;
25
- }): string;
26
- }
27
-
28
- declare class IBMiQueryCompiler extends QueryCompiler {
29
- insert(): "" | {
30
- sql: string;
31
- returning: any;
32
- };
33
- _buildInsertData(insertValues: any, returningSql: any): string;
34
- _prepInsert(data: any): any;
35
- _returning(method: any, value: any, withTrigger: any): string | undefined;
36
- columnizeWithPrefix(prefix: any, target: any): string;
37
- }
38
-
39
- declare class DB2Client extends knex.Client {
40
- constructor(config: any);
41
- _driver(): typeof odbc;
42
- printDebug(message: string): void;
43
- acquireRawConnection(): Promise<any>;
44
- destroyRawConnection(connection: Connection): Promise<void>;
45
- _getConnectionString(connectionConfig: any): string;
46
- _query(connection: any, obj: any): Promise<any>;
47
- _selectAfterUpdate(): string;
48
- transaction(container: any, config: any, outerTx: any): Knex.Transaction;
49
- schemaCompiler(): IBMiSchemaCompiler;
50
- tableCompiler(): IBMiTableCompiler;
51
- columnCompiler(): IBMiColumnCompiler;
52
- queryCompiler(): IBMiQueryCompiler;
53
- processResponse(obj: any, runner: any): any;
54
- }
55
- interface DB2PoolConfig {
56
- min: number;
57
- max: number;
58
- }
59
- interface DB2ConnectionParams {
60
- CMT?: number;
61
- CONNTYPE?: number;
62
- DBQ?: string;
63
- MAXDECPREC?: 31 | 63;
64
- MAXDECSCALE?: number;
65
- MINDIVSCALE?: 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9;
66
- NAM?: 0 | 1;
67
- DFT?: 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7;
68
- DSP?: 0 | 1 | 2 | 3 | 4;
69
- DEC?: 0 | 1;
70
- DECFLOATERROROPTION?: 0 | 1;
71
- DECFLOATROUNDMODE?: 0 | 1 | 2 | 3 | 4 | 5 | 6;
72
- MAPDECIMALFLOATDESCRIBE?: 1 | 3;
73
- }
74
- interface DB2ConnectionConfig {
75
- database: string;
76
- host: string;
77
- port: 50000 | number;
78
- user: string;
79
- password: string;
80
- driver: "IBM i Access ODBC Driver" | string;
81
- connectionStringParams?: DB2ConnectionParams;
82
- pool?: DB2PoolConfig;
83
- }
84
- interface DB2Config {
85
- client: any;
86
- connection: DB2ConnectionConfig;
87
- pool?: DB2PoolConfig;
88
- }
89
- declare const DB2Dialect: typeof DB2Client;
90
-
91
- export { DB2Config, DB2Dialect, DB2Client as default };
1
+ declare module "knex/lib/query/querycompiler" {}
2
+ declare module "knex/lib/schema/tablecompiler" {}
3
+ declare module "knex/lib/schema/compiler" {}
package/dist/index.js CHANGED
@@ -37,7 +37,7 @@ module.exports = __toCommonJS(src_exports);
37
37
  var process = __toESM(require("process"));
38
38
  var import_knex = require("knex");
39
39
  var odbc = __toESM(require("odbc"));
40
- var console = __toESM(require("console"));
40
+ var console2 = __toESM(require("console"));
41
41
 
42
42
  // src/schema/ibmi-compiler.ts
43
43
  var import_compiler = __toESM(require("knex/lib/schema/compiler"));
@@ -182,6 +182,7 @@ var import_isObject2 = __toESM(require("lodash/isObject"));
182
182
  var import_wrappingFormatter = require("knex/lib/formatter/wrappingFormatter");
183
183
  var import_date_fns = require("date-fns");
184
184
  var import_isEmpty = __toESM(require("lodash/isEmpty"));
185
+ var console = __toESM(require("console"));
185
186
  var IBMiQueryCompiler = class extends import_querycompiler.default {
186
187
  insert() {
187
188
  const insertValues = this.single.insert || [];
@@ -285,7 +286,51 @@ var IBMiQueryCompiler = class extends import_querycompiler.default {
285
286
  values
286
287
  };
287
288
  }
289
+ update() {
290
+ const withSQL = this.with();
291
+ const updates = this._prepUpdate(this.single.update);
292
+ const where = this.where();
293
+ const order = this.order();
294
+ const limit = this.limit();
295
+ const { returning } = this.single;
296
+ const values = Object.values(this.single.update).map((a) => `${a}`).join(", ");
297
+ console.log({
298
+ returning,
299
+ // @ts-ignore
300
+ where,
301
+ // @ts-ignore
302
+ updates,
303
+ // @ts-ignore
304
+ single: this.single.update,
305
+ // @ts-ignore
306
+ grouped: this.grouped.where,
307
+ values
308
+ });
309
+ const moreWheres = (
310
+ // @ts-ignore
311
+ this.grouped.where && this.grouped.where.length > 0 ? (
312
+ // @ts-ignore
313
+ this.grouped.where.map((w) => {
314
+ if (this.single.update.hasOwnProperty(w.column))
315
+ return;
316
+ if (!w.value)
317
+ return;
318
+ return `"${w.column}" ${w.not ? "!" : ""}${w.operator} ${w.value}`;
319
+ })
320
+ ) : []
321
+ );
322
+ let selectReturning = returning ? `select ${returning.map((a) => `"${a}"`).join(", ")} from ${// @ts-ignore
323
+ this.tableName} where ${Object.entries(this.single.update).map(([key, value]) => `"${key}" = '${value}'`).join(" and ")}${moreWheres.length > 0 && " and "}${moreWheres.join(
324
+ " and "
325
+ )}` : "";
326
+ console.log({ selectReturning });
327
+ const sql = withSQL + // @ts-ignore
328
+ `update ${this.single.only ? "only " : ""}${this.tableName} set ` + // @ts-ignore
329
+ updates.join(", ") + (where ? ` ${where}` : "") + (order ? ` ${order}` : "") + (limit ? ` ${limit}` : "");
330
+ return { sql, returning, selectReturning };
331
+ }
288
332
  _returning(method, value, withTrigger) {
333
+ console.log("_returning", value);
289
334
  switch (method) {
290
335
  case "update":
291
336
  case "insert":
@@ -299,7 +344,7 @@ var IBMiQueryCompiler = class extends import_querycompiler.default {
299
344
  `${withTrigger ? " into #out" : ""}`
300
345
  ) : "";
301
346
  case "rowcount":
302
- return value ? ";select @@rowcount" : "";
347
+ return value ? "select @@rowcount" : "";
303
348
  }
304
349
  }
305
350
  columnizeWithPrefix(prefix, target) {
@@ -358,7 +403,7 @@ var DB2Client = class extends import_knex.knex.Client {
358
403
  async acquireRawConnection() {
359
404
  this.printDebug("acquiring raw connection");
360
405
  const connectionConfig = this.config.connection;
361
- console.log(this._getConnectionString(connectionConfig));
406
+ console2.log(this._getConnectionString(connectionConfig));
362
407
  if (this.config?.connection?.pool) {
363
408
  const poolConfig = {
364
409
  connectionString: this._getConnectionString(connectionConfig),
@@ -382,7 +427,7 @@ var DB2Client = class extends import_knex.knex.Client {
382
427
  // Used to explicitly close a connection, called internally by the pool manager
383
428
  // when a connection times out or the pool is shutdown.
384
429
  async destroyRawConnection(connection) {
385
- console.log("destroy connection");
430
+ console2.log("destroy connection");
386
431
  return await connection.close();
387
432
  }
388
433
  _getConnectionString(connectionConfig) {
@@ -409,7 +454,7 @@ var DB2Client = class extends import_knex.knex.Client {
409
454
  }
410
455
  } else {
411
456
  await connection.beginTransaction();
412
- console.log("transaction begun");
457
+ console2.log("transaction begun");
413
458
  try {
414
459
  const statement = await connection.createStatement();
415
460
  await statement.prepare(obj.sql);
@@ -420,70 +465,38 @@ var DB2Client = class extends import_knex.knex.Client {
420
465
  if (result.statement.includes("IDENTITY_VAL_LOCAL()")) {
421
466
  obj.response = {
422
467
  rows: result.map(
423
- (row) => result.columns.length > 0 ? row[result.columns[0].name] : row
468
+ (row) => result.columns && result.columns?.length > 0 ? row[result.columns[0].name] : row
424
469
  ),
425
- rowCount: result.length
470
+ rowCount: result.count
426
471
  };
427
472
  } else if (method === "update") {
428
- if (obj.sql.includes("knex_migrations_lock")) {
429
- console.log("migrations_lock");
430
- const rows = await connection.query(
431
- // @ts-ignore
432
- `select * from "knex_migrations_lock"`
433
- );
434
- console.log({ rows });
435
- console.log(rows.map((row) => row.index));
473
+ if (obj.selectReturning) {
474
+ const returningSelect = await connection.query(obj.selectReturning);
436
475
  obj.response = {
437
- rows: rows.length,
438
- rowCount: rows.length
476
+ rows: returningSelect,
477
+ rowCount: result.count
439
478
  };
440
479
  } else {
441
- let returningSelect = obj.sql.replace("update", "select * from ");
442
- returningSelect = returningSelect.replace("where", "and");
443
- returningSelect = returningSelect.replace("set", "where");
444
- returningSelect = returningSelect.replace(this.tableName, "where");
445
- const selectStatement = await connection.createStatement();
446
- await selectStatement.prepare(returningSelect);
447
- console.log({ returningSelect });
448
- if (obj.bindings) {
449
- await selectStatement.bind(obj.bindings);
450
- }
451
- const selected = await selectStatement.execute();
452
480
  obj.response = {
453
- rows: selected.map(
454
- (row) => selected.columns.length > 0 ? row[selected.columns[0].name] : row
455
- ),
456
- rowCount: selected.length
481
+ rows: result,
482
+ rowCount: result.count
457
483
  };
458
484
  }
459
485
  } else {
460
- obj.response = { rows: result, rowCount: result.length };
486
+ obj.response = { rows: result, rowCount: result.count };
461
487
  }
462
488
  } catch (err) {
463
- console.error(err);
489
+ console2.error(err);
464
490
  await connection.rollback();
465
491
  throw new Error(err);
466
492
  } finally {
467
- console.log("transaction committed");
493
+ console2.log("transaction committed");
468
494
  await connection.commit();
469
495
  }
470
496
  }
471
- console.log({ obj });
497
+ console2.log({ obj });
472
498
  return obj;
473
499
  }
474
- _selectAfterUpdate() {
475
- const returnSelect = `; SELECT ${// @ts-ignore
476
- this.single.returning ? (
477
- // @ts-ignore
478
- this.formatter.columnize(this.single.returning)
479
- ) : "*"} from ${this.tableName} `;
480
- let whereStatement = [this.where()];
481
- console.log({ whereStatement });
482
- for (const [key, value] of Object.entries(this.single.update)) {
483
- whereStatement.push(`WHERE ${key} = ${value}`);
484
- }
485
- return returnSelect + whereStatement.join(" and ");
486
- }
487
500
  transaction(container, config, outerTx) {
488
501
  return new ibmi_transaction_default(this, ...arguments);
489
502
  }
@@ -504,7 +517,7 @@ var DB2Client = class extends import_knex.knex.Client {
504
517
  return null;
505
518
  const resp = obj.response;
506
519
  const method = obj.sqlMethod;
507
- const { rows } = resp;
520
+ const { rows, rowCount } = resp;
508
521
  if (obj.output)
509
522
  return obj.output.call(runner, resp);
510
523
  switch (method) {
@@ -519,11 +532,14 @@ var DB2Client = class extends import_knex.knex.Client {
519
532
  case "del":
520
533
  case "delete":
521
534
  case "update":
522
- return rows;
535
+ if (obj.selectReturning) {
536
+ return rows;
537
+ }
538
+ return rowCount;
523
539
  case "counter":
524
- return resp.rowCount;
540
+ return rowCount;
525
541
  default:
526
- return resp;
542
+ return rows;
527
543
  }
528
544
  }
529
545
  };
package/dist/index.mjs CHANGED
@@ -2,7 +2,7 @@
2
2
  import * as process from "process";
3
3
  import { knex } from "knex";
4
4
  import * as odbc from "odbc";
5
- import * as console from "console";
5
+ import * as console2 from "console";
6
6
 
7
7
  // src/schema/ibmi-compiler.ts
8
8
  import SchemaCompiler from "knex/lib/schema/compiler";
@@ -147,6 +147,7 @@ import isObject2 from "lodash/isObject";
147
147
  import { rawOrFn as rawOrFn_ } from "knex/lib/formatter/wrappingFormatter";
148
148
  import { format } from "date-fns";
149
149
  import isEmpty from "lodash/isEmpty";
150
+ import * as console from "console";
150
151
  var IBMiQueryCompiler = class extends QueryCompiler {
151
152
  insert() {
152
153
  const insertValues = this.single.insert || [];
@@ -250,7 +251,51 @@ var IBMiQueryCompiler = class extends QueryCompiler {
250
251
  values
251
252
  };
252
253
  }
254
+ update() {
255
+ const withSQL = this.with();
256
+ const updates = this._prepUpdate(this.single.update);
257
+ const where = this.where();
258
+ const order = this.order();
259
+ const limit = this.limit();
260
+ const { returning } = this.single;
261
+ const values = Object.values(this.single.update).map((a) => `${a}`).join(", ");
262
+ console.log({
263
+ returning,
264
+ // @ts-ignore
265
+ where,
266
+ // @ts-ignore
267
+ updates,
268
+ // @ts-ignore
269
+ single: this.single.update,
270
+ // @ts-ignore
271
+ grouped: this.grouped.where,
272
+ values
273
+ });
274
+ const moreWheres = (
275
+ // @ts-ignore
276
+ this.grouped.where && this.grouped.where.length > 0 ? (
277
+ // @ts-ignore
278
+ this.grouped.where.map((w) => {
279
+ if (this.single.update.hasOwnProperty(w.column))
280
+ return;
281
+ if (!w.value)
282
+ return;
283
+ return `"${w.column}" ${w.not ? "!" : ""}${w.operator} ${w.value}`;
284
+ })
285
+ ) : []
286
+ );
287
+ let selectReturning = returning ? `select ${returning.map((a) => `"${a}"`).join(", ")} from ${// @ts-ignore
288
+ this.tableName} where ${Object.entries(this.single.update).map(([key, value]) => `"${key}" = '${value}'`).join(" and ")}${moreWheres.length > 0 && " and "}${moreWheres.join(
289
+ " and "
290
+ )}` : "";
291
+ console.log({ selectReturning });
292
+ const sql = withSQL + // @ts-ignore
293
+ `update ${this.single.only ? "only " : ""}${this.tableName} set ` + // @ts-ignore
294
+ updates.join(", ") + (where ? ` ${where}` : "") + (order ? ` ${order}` : "") + (limit ? ` ${limit}` : "");
295
+ return { sql, returning, selectReturning };
296
+ }
253
297
  _returning(method, value, withTrigger) {
298
+ console.log("_returning", value);
254
299
  switch (method) {
255
300
  case "update":
256
301
  case "insert":
@@ -264,7 +309,7 @@ var IBMiQueryCompiler = class extends QueryCompiler {
264
309
  `${withTrigger ? " into #out" : ""}`
265
310
  ) : "";
266
311
  case "rowcount":
267
- return value ? ";select @@rowcount" : "";
312
+ return value ? "select @@rowcount" : "";
268
313
  }
269
314
  }
270
315
  columnizeWithPrefix(prefix, target) {
@@ -323,7 +368,7 @@ var DB2Client = class extends knex.Client {
323
368
  async acquireRawConnection() {
324
369
  this.printDebug("acquiring raw connection");
325
370
  const connectionConfig = this.config.connection;
326
- console.log(this._getConnectionString(connectionConfig));
371
+ console2.log(this._getConnectionString(connectionConfig));
327
372
  if (this.config?.connection?.pool) {
328
373
  const poolConfig = {
329
374
  connectionString: this._getConnectionString(connectionConfig),
@@ -347,7 +392,7 @@ var DB2Client = class extends knex.Client {
347
392
  // Used to explicitly close a connection, called internally by the pool manager
348
393
  // when a connection times out or the pool is shutdown.
349
394
  async destroyRawConnection(connection) {
350
- console.log("destroy connection");
395
+ console2.log("destroy connection");
351
396
  return await connection.close();
352
397
  }
353
398
  _getConnectionString(connectionConfig) {
@@ -374,7 +419,7 @@ var DB2Client = class extends knex.Client {
374
419
  }
375
420
  } else {
376
421
  await connection.beginTransaction();
377
- console.log("transaction begun");
422
+ console2.log("transaction begun");
378
423
  try {
379
424
  const statement = await connection.createStatement();
380
425
  await statement.prepare(obj.sql);
@@ -385,70 +430,38 @@ var DB2Client = class extends knex.Client {
385
430
  if (result.statement.includes("IDENTITY_VAL_LOCAL()")) {
386
431
  obj.response = {
387
432
  rows: result.map(
388
- (row) => result.columns.length > 0 ? row[result.columns[0].name] : row
433
+ (row) => result.columns && result.columns?.length > 0 ? row[result.columns[0].name] : row
389
434
  ),
390
- rowCount: result.length
435
+ rowCount: result.count
391
436
  };
392
437
  } else if (method === "update") {
393
- if (obj.sql.includes("knex_migrations_lock")) {
394
- console.log("migrations_lock");
395
- const rows = await connection.query(
396
- // @ts-ignore
397
- `select * from "knex_migrations_lock"`
398
- );
399
- console.log({ rows });
400
- console.log(rows.map((row) => row.index));
438
+ if (obj.selectReturning) {
439
+ const returningSelect = await connection.query(obj.selectReturning);
401
440
  obj.response = {
402
- rows: rows.length,
403
- rowCount: rows.length
441
+ rows: returningSelect,
442
+ rowCount: result.count
404
443
  };
405
444
  } else {
406
- let returningSelect = obj.sql.replace("update", "select * from ");
407
- returningSelect = returningSelect.replace("where", "and");
408
- returningSelect = returningSelect.replace("set", "where");
409
- returningSelect = returningSelect.replace(this.tableName, "where");
410
- const selectStatement = await connection.createStatement();
411
- await selectStatement.prepare(returningSelect);
412
- console.log({ returningSelect });
413
- if (obj.bindings) {
414
- await selectStatement.bind(obj.bindings);
415
- }
416
- const selected = await selectStatement.execute();
417
445
  obj.response = {
418
- rows: selected.map(
419
- (row) => selected.columns.length > 0 ? row[selected.columns[0].name] : row
420
- ),
421
- rowCount: selected.length
446
+ rows: result,
447
+ rowCount: result.count
422
448
  };
423
449
  }
424
450
  } else {
425
- obj.response = { rows: result, rowCount: result.length };
451
+ obj.response = { rows: result, rowCount: result.count };
426
452
  }
427
453
  } catch (err) {
428
- console.error(err);
454
+ console2.error(err);
429
455
  await connection.rollback();
430
456
  throw new Error(err);
431
457
  } finally {
432
- console.log("transaction committed");
458
+ console2.log("transaction committed");
433
459
  await connection.commit();
434
460
  }
435
461
  }
436
- console.log({ obj });
462
+ console2.log({ obj });
437
463
  return obj;
438
464
  }
439
- _selectAfterUpdate() {
440
- const returnSelect = `; SELECT ${// @ts-ignore
441
- this.single.returning ? (
442
- // @ts-ignore
443
- this.formatter.columnize(this.single.returning)
444
- ) : "*"} from ${this.tableName} `;
445
- let whereStatement = [this.where()];
446
- console.log({ whereStatement });
447
- for (const [key, value] of Object.entries(this.single.update)) {
448
- whereStatement.push(`WHERE ${key} = ${value}`);
449
- }
450
- return returnSelect + whereStatement.join(" and ");
451
- }
452
465
  transaction(container, config, outerTx) {
453
466
  return new ibmi_transaction_default(this, ...arguments);
454
467
  }
@@ -469,7 +482,7 @@ var DB2Client = class extends knex.Client {
469
482
  return null;
470
483
  const resp = obj.response;
471
484
  const method = obj.sqlMethod;
472
- const { rows } = resp;
485
+ const { rows, rowCount } = resp;
473
486
  if (obj.output)
474
487
  return obj.output.call(runner, resp);
475
488
  switch (method) {
@@ -484,11 +497,14 @@ var DB2Client = class extends knex.Client {
484
497
  case "del":
485
498
  case "delete":
486
499
  case "update":
487
- return rows;
500
+ if (obj.selectReturning) {
501
+ return rows;
502
+ }
503
+ return rowCount;
488
504
  case "counter":
489
- return resp.rowCount;
505
+ return rowCount;
490
506
  default:
491
- return resp;
507
+ return rows;
492
508
  }
493
509
  }
494
510
  };
package/package.json CHANGED
@@ -1,8 +1,9 @@
1
1
  {
2
2
  "name": "@bdkinc/knex-ibmi",
3
- "version": "0.0.16",
3
+ "version": "0.0.18",
4
4
  "description": "Knex dialect for IBMi",
5
- "main": "dist/index.js",
5
+ "main": "dist/index",
6
+ "types": "dist/index",
6
7
  "module": "dist/index.mjs",
7
8
  "exports": {
8
9
  "import": "./dist/index.mjs",
@@ -14,6 +15,7 @@
14
15
  "engineStrict": true,
15
16
  "scripts": {
16
17
  "build": "tsup src/index.ts --dts --format esm,cjs",
18
+ "build:dev": "tsup src/index.ts --format esm,cjs",
17
19
  "lint:scripts": "eslint . --ext .ts",
18
20
  "format:scripts": "prettier . --write"
19
21
  },
@@ -1,3 +1,4 @@
1
+ // @ts-ignore
1
2
  import Transaction from "knex/lib/execution/transaction";
2
3
 
3
4
  class IBMiTransaction extends Transaction {
package/src/index.d.ts ADDED
@@ -0,0 +1,4 @@
1
+ declare module "knex/lib/query/querycompiler" {}
2
+ declare module "knex/lib/schema/tablecompiler" {}
3
+ declare module "knex/lib/schema/compiler" {}
4
+
package/src/index.ts CHANGED
@@ -145,56 +145,27 @@ class DB2Client extends knex.Client {
145
145
  if (result.statement.includes("IDENTITY_VAL_LOCAL()")) {
146
146
  obj.response = {
147
147
  rows: result.map((row) =>
148
- result.columns.length > 0 ? row[result.columns[0].name] : row,
148
+ result.columns && result.columns?.length > 0
149
+ ? row[result.columns[0].name]
150
+ : row,
149
151
  ),
150
- rowCount: result.length,
152
+ rowCount: result.count,
151
153
  };
152
- // @ts-ignore
153
154
  } else if (method === "update") {
154
- // if is in update we need to run a separate select query
155
- // this also feels hacky and should be cleaned up
156
- // it would be a lot easier if the table-reference function
157
- // worked the same for updates as it does inserts
158
- // on DB2 LUW it does work so if they ever add it we need to fix
159
- // @ts-ignore
160
- if (obj.sql.includes("knex_migrations_lock")) {
161
- // even more hacky for migrations
162
- console.log("migrations_lock");
163
- // @ts-ignore
164
- const rows = await connection.query(
165
- // @ts-ignore
166
- `select * from \"knex_migrations_lock\"`,
167
- );
168
- console.log({ rows });
169
- console.log(rows.map((row) => row.index));
155
+ if (obj.selectReturning) {
156
+ const returningSelect = await connection.query(obj.selectReturning);
170
157
  obj.response = {
171
- rows: rows.length,
172
- rowCount: rows.length,
158
+ rows: returningSelect,
159
+ rowCount: result.count,
173
160
  };
174
161
  } else {
175
- let returningSelect = obj.sql.replace("update", "select * from ");
176
- returningSelect = returningSelect.replace("where", "and");
177
- returningSelect = returningSelect.replace("set", "where");
178
- // @ts-ignore
179
- returningSelect = returningSelect.replace(this.tableName, "where");
180
- const selectStatement = await connection.createStatement();
181
- await selectStatement.prepare(returningSelect);
182
- console.log({ returningSelect });
183
- if (obj.bindings) {
184
- await selectStatement.bind(obj.bindings);
185
- }
186
- const selected = await selectStatement.execute();
187
162
  obj.response = {
188
- rows: selected.map((row) =>
189
- selected.columns.length > 0
190
- ? row[selected.columns[0].name]
191
- : row,
192
- ),
193
- rowCount: selected.length,
163
+ rows: result,
164
+ rowCount: result.count,
194
165
  };
195
166
  }
196
167
  } else {
197
- obj.response = { rows: result, rowCount: result.length };
168
+ obj.response = { rows: result, rowCount: result.count };
198
169
  }
199
170
  } catch (err: any) {
200
171
  console.error(err);
@@ -210,25 +181,6 @@ class DB2Client extends knex.Client {
210
181
  return obj;
211
182
  }
212
183
 
213
- _selectAfterUpdate() {
214
- const returnSelect = `; SELECT ${
215
- // @ts-ignore
216
- this.single.returning
217
- ? // @ts-ignore
218
- this.formatter.columnize(this.single.returning)
219
- : "*"
220
- // @ts-ignore
221
- } from ${this.tableName} `;
222
- // @ts-ignore
223
- let whereStatement = [this.where()];
224
- console.log({ whereStatement });
225
- // @ts-ignore
226
- for (const [key, value] of Object.entries(this.single.update)) {
227
- whereStatement.push(`WHERE ${key} = ${value}`);
228
- }
229
- return returnSelect + whereStatement.join(" and ");
230
- }
231
-
232
184
  transaction(container: any, config: any, outerTx: any): Knex.Transaction {
233
185
  // @ts-ignore
234
186
  return new Transaction(this, ...arguments);
@@ -259,7 +211,7 @@ class DB2Client extends knex.Client {
259
211
 
260
212
  const resp = obj.response;
261
213
  const method = obj.sqlMethod;
262
- const { rows } = resp;
214
+ const { rows, rowCount } = resp;
263
215
 
264
216
  if (obj.output) return obj.output.call(runner, resp);
265
217
 
@@ -275,11 +227,14 @@ class DB2Client extends knex.Client {
275
227
  case "del":
276
228
  case "delete":
277
229
  case "update":
278
- return rows;
230
+ if (obj.selectReturning) {
231
+ return rows;
232
+ }
233
+ return rowCount;
279
234
  case "counter":
280
- return resp.rowCount;
235
+ return rowCount;
281
236
  default:
282
- return resp;
237
+ return rows;
283
238
  }
284
239
  }
285
240
  }
@@ -1,9 +1,10 @@
1
+ // @ts-ignore
1
2
  import QueryCompiler from "knex/lib/query/querycompiler";
2
3
  import isObject from "lodash/isObject";
3
4
  import { rawOrFn as rawOrFn_ } from "knex/lib/formatter/wrappingFormatter";
4
5
  import { format } from "date-fns";
5
- import * as console from "console";
6
6
  import isEmpty from "lodash/isEmpty";
7
+ import * as console from "console";
7
8
 
8
9
  class IBMiQueryCompiler extends QueryCompiler {
9
10
  insert() {
@@ -127,8 +128,81 @@ class IBMiQueryCompiler extends QueryCompiler {
127
128
  };
128
129
  }
129
130
 
131
+ update() {
132
+ // @ts-ignore
133
+ const withSQL = this.with();
134
+ // @ts-ignore
135
+ const updates = this._prepUpdate(this.single.update);
136
+ // @ts-ignore
137
+ const where = this.where();
138
+ // @ts-ignore
139
+ const order = this.order();
140
+ // @ts-ignore
141
+ const limit = this.limit();
142
+ // @ts-ignore
143
+ const { returning } = this.single;
144
+ // @ts-ignore
145
+ const values = Object.values(this.single.update)
146
+ .map((a) => `${a}`)
147
+ .join(", ");
148
+
149
+ // @ts-ignore
150
+ console.log({
151
+ returning,
152
+ // @ts-ignore
153
+ where,
154
+ // @ts-ignore
155
+ updates,
156
+ // @ts-ignore
157
+ single: this.single.update,
158
+ // @ts-ignore
159
+ grouped: this.grouped.where,
160
+ values,
161
+ });
162
+ // @ts-ignore
163
+ const moreWheres =
164
+ // @ts-ignore
165
+ this.grouped.where && this.grouped.where.length > 0
166
+ ? // @ts-ignore
167
+ this.grouped.where.map((w) => {
168
+ // @ts-ignore
169
+ if (this.single.update.hasOwnProperty(w.column)) return;
170
+ if (!w.value) return;
171
+ return `"${w.column}" ${w.not ? "!" : ""}${w.operator} ${w.value}`;
172
+ })
173
+ : [];
174
+
175
+ let selectReturning = returning
176
+ ? `select ${returning.map((a) => `"${a}"`).join(", ")} from ${
177
+ // @ts-ignore
178
+ this.tableName
179
+ // @ts-ignore
180
+ } where ${Object.entries(this.single.update)
181
+ .map(([key, value]) => `"${key}" = '${value}'`)
182
+ .join(" and ")}${moreWheres.length > 0 && " and "}${moreWheres.join(
183
+ " and ",
184
+ )}`
185
+ : "";
186
+
187
+ console.log({ selectReturning });
188
+
189
+ const sql =
190
+ withSQL +
191
+ // @ts-ignore
192
+ `update ${this.single.only ? "only " : ""}${this.tableName}` +
193
+ " set " +
194
+ // @ts-ignore
195
+ updates.join(", ") +
196
+ (where ? ` ${where}` : "") +
197
+ (order ? ` ${order}` : "") +
198
+ (limit ? ` ${limit}` : "");
199
+
200
+ return { sql, returning, selectReturning };
201
+ }
202
+
130
203
  _returning(method, value, withTrigger) {
131
204
  // currently a placeholder in case I need to update return values
205
+ console.log("_returning", value);
132
206
  switch (method) {
133
207
  case "update":
134
208
  case "insert":
@@ -142,7 +216,7 @@ class IBMiQueryCompiler extends QueryCompiler {
142
216
  `${withTrigger ? " into #out" : ""}`
143
217
  : "";
144
218
  case "rowcount":
145
- return value ? ";select @@rowcount" : "";
219
+ return value ? "select @@rowcount" : "";
146
220
  }
147
221
  }
148
222
 
@@ -1,3 +1,4 @@
1
+ // @ts-ignore
1
2
  import ColumnCompiler from "knex/lib/schema/columncompiler";
2
3
 
3
4
  class IBMiColumnCompiler extends ColumnCompiler {
@@ -1,3 +1,4 @@
1
+ // @ts-ignore
1
2
  import SchemaCompiler from "knex/lib/schema/compiler";
2
3
 
3
4
  class IBMiSchemaCompiler extends SchemaCompiler {
@@ -1,3 +1,4 @@
1
+ // @ts-ignore
1
2
  import TableCompiler from "knex/lib/schema/tablecompiler";
2
3
  import isObject from "lodash/isObject";
3
4