@bdkinc/knex-ibmi 0.0.5 → 0.0.7
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/CHANGELOG.md +10 -17
- package/dist/index.js +120 -11
- package/dist/index.mjs +120 -11
- package/package.json +1 -1
- package/src/execution/ibmi-transaction.ts +0 -1
- package/src/index.ts +52 -3
- package/src/query/ibmi-querycompiler.ts +101 -0
- package/src/schema/ibmi-compiler.ts +0 -5
package/CHANGELOG.md
CHANGED
|
@@ -1,21 +1,14 @@
|
|
|
1
|
-
##
|
|
2
|
-
-
|
|
3
|
-
- Internal enhancements
|
|
1
|
+
## 0.0.5 - July 23rd, 2023
|
|
2
|
+
- add unique and dropUnique methods
|
|
4
3
|
|
|
5
|
-
## 0.
|
|
6
|
-
-
|
|
4
|
+
## 0.0.4 - July 21st, 2023
|
|
5
|
+
- remove unnecessary compiler methods
|
|
7
6
|
|
|
8
|
-
## 0.
|
|
9
|
-
-
|
|
7
|
+
## 0.0.3 - July 19th, 2023
|
|
8
|
+
- add transaction support
|
|
10
9
|
|
|
11
|
-
## 0.
|
|
12
|
-
-
|
|
10
|
+
## 0.0.2 - July 15th, 2023
|
|
11
|
+
- update readme and code examples
|
|
13
12
|
|
|
14
|
-
## 0.1
|
|
15
|
-
-
|
|
16
|
-
|
|
17
|
-
## 0.1.1 - 4 Oct 2018
|
|
18
|
-
- Fix raw queries not running as expected #3
|
|
19
|
-
|
|
20
|
-
## 0.1.0 - 29 Sep 2018
|
|
21
|
-
- Initial release
|
|
13
|
+
## 0.0.1 - July 14th, 2023
|
|
14
|
+
- Imported DB2 Dialect and re-wrote
|
package/dist/index.js
CHANGED
|
@@ -37,15 +37,11 @@ module.exports = __toCommonJS(src_exports);
|
|
|
37
37
|
var process = __toESM(require("process"));
|
|
38
38
|
var import_knex = __toESM(require("knex"));
|
|
39
39
|
var odbc = __toESM(require("odbc"));
|
|
40
|
-
var
|
|
40
|
+
var console = __toESM(require("console"));
|
|
41
41
|
|
|
42
42
|
// src/schema/ibmi-compiler.ts
|
|
43
43
|
var import_compiler = __toESM(require("knex/lib/schema/compiler"));
|
|
44
|
-
var console = __toESM(require("console"));
|
|
45
44
|
var IBMiSchemaCompiler = class extends import_compiler.default {
|
|
46
|
-
constructor(client, builder) {
|
|
47
|
-
super(client, builder);
|
|
48
|
-
}
|
|
49
45
|
hasTable(tableName) {
|
|
50
46
|
const formattedTable = this.client.parameter(
|
|
51
47
|
// @ts-ignore
|
|
@@ -73,7 +69,6 @@ var IBMiSchemaCompiler = class extends import_compiler.default {
|
|
|
73
69
|
const sequence = this.builder._sequence;
|
|
74
70
|
for (let i = 0, l = sequence.length; i < l; i++) {
|
|
75
71
|
const query = sequence[i];
|
|
76
|
-
console.log(query.method, query);
|
|
77
72
|
this[query.method].apply(this, query.args);
|
|
78
73
|
}
|
|
79
74
|
return this.sequence;
|
|
@@ -188,7 +183,57 @@ var import_querycompiler = __toESM(require("knex/lib/query/querycompiler"));
|
|
|
188
183
|
var import_isObject2 = __toESM(require("lodash/isObject"));
|
|
189
184
|
var import_wrappingFormatter = require("knex/lib/formatter/wrappingFormatter");
|
|
190
185
|
var import_date_fns = require("date-fns");
|
|
186
|
+
var import_isEmpty = __toESM(require("lodash/isEmpty"));
|
|
191
187
|
var IBMiQueryCompiler = class extends import_querycompiler.default {
|
|
188
|
+
insert() {
|
|
189
|
+
const insertValues = this.single.insert || [];
|
|
190
|
+
let sql = `SELECT ${// @ts-ignore
|
|
191
|
+
this.single.returning ? (
|
|
192
|
+
// @ts-ignore
|
|
193
|
+
this.formatter.columnize(this.single.returning)
|
|
194
|
+
) : "IDENTITY_VAL_LOCAL()"} FROM FINAL TABLE(`;
|
|
195
|
+
sql += this.with() + `insert into ${this.tableName} `;
|
|
196
|
+
const { returning } = this.single;
|
|
197
|
+
const returningSql = returning ? (
|
|
198
|
+
// @ts-ignore
|
|
199
|
+
this._returning("insert", returning) + " "
|
|
200
|
+
) : "";
|
|
201
|
+
if (Array.isArray(insertValues)) {
|
|
202
|
+
if (insertValues.length === 0) {
|
|
203
|
+
return "";
|
|
204
|
+
}
|
|
205
|
+
} else if (typeof insertValues === "object" && (0, import_isEmpty.default)(insertValues)) {
|
|
206
|
+
return {
|
|
207
|
+
// @ts-ignore
|
|
208
|
+
sql: sql + returningSql + this._emptyInsertValue,
|
|
209
|
+
returning
|
|
210
|
+
};
|
|
211
|
+
}
|
|
212
|
+
sql += this._buildInsertData(insertValues, returningSql);
|
|
213
|
+
sql += ")";
|
|
214
|
+
return {
|
|
215
|
+
sql,
|
|
216
|
+
returning
|
|
217
|
+
};
|
|
218
|
+
}
|
|
219
|
+
_buildInsertData(insertValues, returningSql) {
|
|
220
|
+
let sql = "";
|
|
221
|
+
const insertData = this._prepInsert(insertValues);
|
|
222
|
+
if (typeof insertData === "string") {
|
|
223
|
+
sql += insertData;
|
|
224
|
+
} else {
|
|
225
|
+
if (insertData.columns.length) {
|
|
226
|
+
sql += `(${this.formatter.columnize(insertData.columns)}`;
|
|
227
|
+
sql += `) ${returningSql}values (` + // @ts-ignore
|
|
228
|
+
this._buildInsertValues(insertData) + ")";
|
|
229
|
+
} else if (insertValues.length === 1 && insertValues[0]) {
|
|
230
|
+
sql += returningSql + this._emptyInsertValue;
|
|
231
|
+
} else {
|
|
232
|
+
return "";
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
return sql;
|
|
236
|
+
}
|
|
192
237
|
_prepInsert(data) {
|
|
193
238
|
if ((0, import_isObject2.default)(data)) {
|
|
194
239
|
if (data.hasOwnProperty("migration_time")) {
|
|
@@ -242,6 +287,33 @@ var IBMiQueryCompiler = class extends import_querycompiler.default {
|
|
|
242
287
|
values
|
|
243
288
|
};
|
|
244
289
|
}
|
|
290
|
+
_returning(method, value, withTrigger) {
|
|
291
|
+
switch (method) {
|
|
292
|
+
case "update":
|
|
293
|
+
case "insert":
|
|
294
|
+
return value ? (
|
|
295
|
+
// @ts-ignore
|
|
296
|
+
`${withTrigger ? " into #out" : ""}`
|
|
297
|
+
) : "";
|
|
298
|
+
case "del":
|
|
299
|
+
return value ? (
|
|
300
|
+
// @ts-ignore
|
|
301
|
+
`${withTrigger ? " into #out" : ""}`
|
|
302
|
+
) : "";
|
|
303
|
+
case "rowcount":
|
|
304
|
+
return value ? ";select @@rowcount" : "";
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
columnizeWithPrefix(prefix, target) {
|
|
308
|
+
const columns = typeof target === "string" ? [target] : target;
|
|
309
|
+
let str = "", i = -1;
|
|
310
|
+
while (++i < columns.length) {
|
|
311
|
+
if (i > 0)
|
|
312
|
+
str += ", ";
|
|
313
|
+
str += prefix + this.wrap(columns[i]);
|
|
314
|
+
}
|
|
315
|
+
return str;
|
|
316
|
+
}
|
|
245
317
|
};
|
|
246
318
|
var ibmi_querycompiler_default = IBMiQueryCompiler;
|
|
247
319
|
|
|
@@ -288,13 +360,13 @@ var DB2Client = class extends import_knex.default.Client {
|
|
|
288
360
|
async acquireRawConnection() {
|
|
289
361
|
this.printDebug("acquiring raw connection");
|
|
290
362
|
const connectionConfig = this.config.connection;
|
|
291
|
-
|
|
363
|
+
console.log(this._getConnectionString(connectionConfig));
|
|
292
364
|
return await this.driver.pool(this._getConnectionString(connectionConfig));
|
|
293
365
|
}
|
|
294
366
|
// Used to explicitly close a connection, called internally by the pool manager
|
|
295
367
|
// when a connection times out or the pool is shutdown.
|
|
296
368
|
async destroyRawConnection(connection) {
|
|
297
|
-
|
|
369
|
+
console.log("destroy connection");
|
|
298
370
|
return await connection.close();
|
|
299
371
|
}
|
|
300
372
|
_getConnectionString(connectionConfig) {
|
|
@@ -324,18 +396,54 @@ var DB2Client = class extends import_knex.default.Client {
|
|
|
324
396
|
const connection = await pool.connect();
|
|
325
397
|
const statement = await connection.createStatement();
|
|
326
398
|
await statement.prepare(obj.sql);
|
|
399
|
+
console.log({ obj });
|
|
327
400
|
if (obj.bindings) {
|
|
328
401
|
await statement.bind(obj.bindings);
|
|
329
402
|
}
|
|
330
403
|
const result = await statement.execute();
|
|
331
|
-
|
|
404
|
+
if (result.statement.includes("IDENTITY_VAL_LOCAL()")) {
|
|
405
|
+
obj.response = {
|
|
406
|
+
rows: result.map(
|
|
407
|
+
(row) => result.columns.length > 0 ? row[result.columns[0].name] : row
|
|
408
|
+
),
|
|
409
|
+
rowCount: result.length
|
|
410
|
+
};
|
|
411
|
+
} else if (method === "update") {
|
|
412
|
+
console.log(this.queryCompiler);
|
|
413
|
+
let returningSelect = obj.sql.replace("update", "select * from ");
|
|
414
|
+
returningSelect = returningSelect.replace("where", "and");
|
|
415
|
+
returningSelect = returningSelect.replace("set", "where");
|
|
416
|
+
returningSelect = returningSelect.replace(this.tableName, "where");
|
|
417
|
+
const selectStatement = await connection.createStatement();
|
|
418
|
+
await selectStatement.prepare(returningSelect);
|
|
419
|
+
if (obj.bindings) {
|
|
420
|
+
await selectStatement.bind(obj.bindings);
|
|
421
|
+
}
|
|
422
|
+
const selected = await selectStatement.execute();
|
|
423
|
+
console.log(selected.columns);
|
|
424
|
+
obj.response = { rows: selected, rowCount: selected.length };
|
|
425
|
+
} else {
|
|
426
|
+
obj.response = { rows: result, rowCount: result.length };
|
|
427
|
+
}
|
|
332
428
|
} catch (err) {
|
|
333
|
-
|
|
429
|
+
console.error(err);
|
|
334
430
|
throw new Error(err);
|
|
335
431
|
}
|
|
336
432
|
}
|
|
337
433
|
return obj;
|
|
338
434
|
}
|
|
435
|
+
_selectAfterUpdate() {
|
|
436
|
+
const returnSelect = `; SELECT ${this.single.returning ? (
|
|
437
|
+
// @ts-ignore
|
|
438
|
+
this.formatter.columnize(this.single.returning)
|
|
439
|
+
) : "*"} from ${this.tableName} `;
|
|
440
|
+
let whereStatement = [this.where()];
|
|
441
|
+
console.log({ whereStatement });
|
|
442
|
+
for (const [key, value] of Object.entries(this.single.update)) {
|
|
443
|
+
whereStatement.push(`WHERE ${key} = ${value}`);
|
|
444
|
+
}
|
|
445
|
+
return returnSelect + whereStatement.join(" and ");
|
|
446
|
+
}
|
|
339
447
|
transaction(container, config, outerTx) {
|
|
340
448
|
return new ibmi_transaction_default(this, ...arguments);
|
|
341
449
|
}
|
|
@@ -357,7 +465,6 @@ var DB2Client = class extends import_knex.default.Client {
|
|
|
357
465
|
const resp = obj.response;
|
|
358
466
|
const method = obj.sqlMethod;
|
|
359
467
|
const { rows } = resp;
|
|
360
|
-
console2.log({ method, rows });
|
|
361
468
|
if (obj.output)
|
|
362
469
|
return obj.output.call(runner, resp);
|
|
363
470
|
switch (method) {
|
|
@@ -368,9 +475,11 @@ var DB2Client = class extends import_knex.default.Client {
|
|
|
368
475
|
case "first":
|
|
369
476
|
return rows[0];
|
|
370
477
|
case "insert":
|
|
478
|
+
return rows;
|
|
371
479
|
case "del":
|
|
372
480
|
case "delete":
|
|
373
481
|
case "update":
|
|
482
|
+
return rows;
|
|
374
483
|
case "counter":
|
|
375
484
|
return resp.rowCount;
|
|
376
485
|
default:
|
package/dist/index.mjs
CHANGED
|
@@ -2,15 +2,11 @@
|
|
|
2
2
|
import * as process from "process";
|
|
3
3
|
import knex from "knex";
|
|
4
4
|
import * as odbc from "odbc";
|
|
5
|
-
import * as
|
|
5
|
+
import * as console from "console";
|
|
6
6
|
|
|
7
7
|
// src/schema/ibmi-compiler.ts
|
|
8
8
|
import SchemaCompiler from "knex/lib/schema/compiler";
|
|
9
|
-
import * as console from "console";
|
|
10
9
|
var IBMiSchemaCompiler = class extends SchemaCompiler {
|
|
11
|
-
constructor(client, builder) {
|
|
12
|
-
super(client, builder);
|
|
13
|
-
}
|
|
14
10
|
hasTable(tableName) {
|
|
15
11
|
const formattedTable = this.client.parameter(
|
|
16
12
|
// @ts-ignore
|
|
@@ -38,7 +34,6 @@ var IBMiSchemaCompiler = class extends SchemaCompiler {
|
|
|
38
34
|
const sequence = this.builder._sequence;
|
|
39
35
|
for (let i = 0, l = sequence.length; i < l; i++) {
|
|
40
36
|
const query = sequence[i];
|
|
41
|
-
console.log(query.method, query);
|
|
42
37
|
this[query.method].apply(this, query.args);
|
|
43
38
|
}
|
|
44
39
|
return this.sequence;
|
|
@@ -153,7 +148,57 @@ import QueryCompiler from "knex/lib/query/querycompiler";
|
|
|
153
148
|
import isObject2 from "lodash/isObject";
|
|
154
149
|
import { rawOrFn as rawOrFn_ } from "knex/lib/formatter/wrappingFormatter";
|
|
155
150
|
import { format } from "date-fns";
|
|
151
|
+
import isEmpty from "lodash/isEmpty";
|
|
156
152
|
var IBMiQueryCompiler = class extends QueryCompiler {
|
|
153
|
+
insert() {
|
|
154
|
+
const insertValues = this.single.insert || [];
|
|
155
|
+
let sql = `SELECT ${// @ts-ignore
|
|
156
|
+
this.single.returning ? (
|
|
157
|
+
// @ts-ignore
|
|
158
|
+
this.formatter.columnize(this.single.returning)
|
|
159
|
+
) : "IDENTITY_VAL_LOCAL()"} FROM FINAL TABLE(`;
|
|
160
|
+
sql += this.with() + `insert into ${this.tableName} `;
|
|
161
|
+
const { returning } = this.single;
|
|
162
|
+
const returningSql = returning ? (
|
|
163
|
+
// @ts-ignore
|
|
164
|
+
this._returning("insert", returning) + " "
|
|
165
|
+
) : "";
|
|
166
|
+
if (Array.isArray(insertValues)) {
|
|
167
|
+
if (insertValues.length === 0) {
|
|
168
|
+
return "";
|
|
169
|
+
}
|
|
170
|
+
} else if (typeof insertValues === "object" && isEmpty(insertValues)) {
|
|
171
|
+
return {
|
|
172
|
+
// @ts-ignore
|
|
173
|
+
sql: sql + returningSql + this._emptyInsertValue,
|
|
174
|
+
returning
|
|
175
|
+
};
|
|
176
|
+
}
|
|
177
|
+
sql += this._buildInsertData(insertValues, returningSql);
|
|
178
|
+
sql += ")";
|
|
179
|
+
return {
|
|
180
|
+
sql,
|
|
181
|
+
returning
|
|
182
|
+
};
|
|
183
|
+
}
|
|
184
|
+
_buildInsertData(insertValues, returningSql) {
|
|
185
|
+
let sql = "";
|
|
186
|
+
const insertData = this._prepInsert(insertValues);
|
|
187
|
+
if (typeof insertData === "string") {
|
|
188
|
+
sql += insertData;
|
|
189
|
+
} else {
|
|
190
|
+
if (insertData.columns.length) {
|
|
191
|
+
sql += `(${this.formatter.columnize(insertData.columns)}`;
|
|
192
|
+
sql += `) ${returningSql}values (` + // @ts-ignore
|
|
193
|
+
this._buildInsertValues(insertData) + ")";
|
|
194
|
+
} else if (insertValues.length === 1 && insertValues[0]) {
|
|
195
|
+
sql += returningSql + this._emptyInsertValue;
|
|
196
|
+
} else {
|
|
197
|
+
return "";
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
return sql;
|
|
201
|
+
}
|
|
157
202
|
_prepInsert(data) {
|
|
158
203
|
if (isObject2(data)) {
|
|
159
204
|
if (data.hasOwnProperty("migration_time")) {
|
|
@@ -207,6 +252,33 @@ var IBMiQueryCompiler = class extends QueryCompiler {
|
|
|
207
252
|
values
|
|
208
253
|
};
|
|
209
254
|
}
|
|
255
|
+
_returning(method, value, withTrigger) {
|
|
256
|
+
switch (method) {
|
|
257
|
+
case "update":
|
|
258
|
+
case "insert":
|
|
259
|
+
return value ? (
|
|
260
|
+
// @ts-ignore
|
|
261
|
+
`${withTrigger ? " into #out" : ""}`
|
|
262
|
+
) : "";
|
|
263
|
+
case "del":
|
|
264
|
+
return value ? (
|
|
265
|
+
// @ts-ignore
|
|
266
|
+
`${withTrigger ? " into #out" : ""}`
|
|
267
|
+
) : "";
|
|
268
|
+
case "rowcount":
|
|
269
|
+
return value ? ";select @@rowcount" : "";
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
columnizeWithPrefix(prefix, target) {
|
|
273
|
+
const columns = typeof target === "string" ? [target] : target;
|
|
274
|
+
let str = "", i = -1;
|
|
275
|
+
while (++i < columns.length) {
|
|
276
|
+
if (i > 0)
|
|
277
|
+
str += ", ";
|
|
278
|
+
str += prefix + this.wrap(columns[i]);
|
|
279
|
+
}
|
|
280
|
+
return str;
|
|
281
|
+
}
|
|
210
282
|
};
|
|
211
283
|
var ibmi_querycompiler_default = IBMiQueryCompiler;
|
|
212
284
|
|
|
@@ -253,13 +325,13 @@ var DB2Client = class extends knex.Client {
|
|
|
253
325
|
async acquireRawConnection() {
|
|
254
326
|
this.printDebug("acquiring raw connection");
|
|
255
327
|
const connectionConfig = this.config.connection;
|
|
256
|
-
|
|
328
|
+
console.log(this._getConnectionString(connectionConfig));
|
|
257
329
|
return await this.driver.pool(this._getConnectionString(connectionConfig));
|
|
258
330
|
}
|
|
259
331
|
// Used to explicitly close a connection, called internally by the pool manager
|
|
260
332
|
// when a connection times out or the pool is shutdown.
|
|
261
333
|
async destroyRawConnection(connection) {
|
|
262
|
-
|
|
334
|
+
console.log("destroy connection");
|
|
263
335
|
return await connection.close();
|
|
264
336
|
}
|
|
265
337
|
_getConnectionString(connectionConfig) {
|
|
@@ -289,18 +361,54 @@ var DB2Client = class extends knex.Client {
|
|
|
289
361
|
const connection = await pool.connect();
|
|
290
362
|
const statement = await connection.createStatement();
|
|
291
363
|
await statement.prepare(obj.sql);
|
|
364
|
+
console.log({ obj });
|
|
292
365
|
if (obj.bindings) {
|
|
293
366
|
await statement.bind(obj.bindings);
|
|
294
367
|
}
|
|
295
368
|
const result = await statement.execute();
|
|
296
|
-
|
|
369
|
+
if (result.statement.includes("IDENTITY_VAL_LOCAL()")) {
|
|
370
|
+
obj.response = {
|
|
371
|
+
rows: result.map(
|
|
372
|
+
(row) => result.columns.length > 0 ? row[result.columns[0].name] : row
|
|
373
|
+
),
|
|
374
|
+
rowCount: result.length
|
|
375
|
+
};
|
|
376
|
+
} else if (method === "update") {
|
|
377
|
+
console.log(this.queryCompiler);
|
|
378
|
+
let returningSelect = obj.sql.replace("update", "select * from ");
|
|
379
|
+
returningSelect = returningSelect.replace("where", "and");
|
|
380
|
+
returningSelect = returningSelect.replace("set", "where");
|
|
381
|
+
returningSelect = returningSelect.replace(this.tableName, "where");
|
|
382
|
+
const selectStatement = await connection.createStatement();
|
|
383
|
+
await selectStatement.prepare(returningSelect);
|
|
384
|
+
if (obj.bindings) {
|
|
385
|
+
await selectStatement.bind(obj.bindings);
|
|
386
|
+
}
|
|
387
|
+
const selected = await selectStatement.execute();
|
|
388
|
+
console.log(selected.columns);
|
|
389
|
+
obj.response = { rows: selected, rowCount: selected.length };
|
|
390
|
+
} else {
|
|
391
|
+
obj.response = { rows: result, rowCount: result.length };
|
|
392
|
+
}
|
|
297
393
|
} catch (err) {
|
|
298
|
-
|
|
394
|
+
console.error(err);
|
|
299
395
|
throw new Error(err);
|
|
300
396
|
}
|
|
301
397
|
}
|
|
302
398
|
return obj;
|
|
303
399
|
}
|
|
400
|
+
_selectAfterUpdate() {
|
|
401
|
+
const returnSelect = `; SELECT ${this.single.returning ? (
|
|
402
|
+
// @ts-ignore
|
|
403
|
+
this.formatter.columnize(this.single.returning)
|
|
404
|
+
) : "*"} from ${this.tableName} `;
|
|
405
|
+
let whereStatement = [this.where()];
|
|
406
|
+
console.log({ whereStatement });
|
|
407
|
+
for (const [key, value] of Object.entries(this.single.update)) {
|
|
408
|
+
whereStatement.push(`WHERE ${key} = ${value}`);
|
|
409
|
+
}
|
|
410
|
+
return returnSelect + whereStatement.join(" and ");
|
|
411
|
+
}
|
|
304
412
|
transaction(container, config, outerTx) {
|
|
305
413
|
return new ibmi_transaction_default(this, ...arguments);
|
|
306
414
|
}
|
|
@@ -322,7 +430,6 @@ var DB2Client = class extends knex.Client {
|
|
|
322
430
|
const resp = obj.response;
|
|
323
431
|
const method = obj.sqlMethod;
|
|
324
432
|
const { rows } = resp;
|
|
325
|
-
console2.log({ method, rows });
|
|
326
433
|
if (obj.output)
|
|
327
434
|
return obj.output.call(runner, resp);
|
|
328
435
|
switch (method) {
|
|
@@ -333,9 +440,11 @@ var DB2Client = class extends knex.Client {
|
|
|
333
440
|
case "first":
|
|
334
441
|
return rows[0];
|
|
335
442
|
case "insert":
|
|
443
|
+
return rows;
|
|
336
444
|
case "del":
|
|
337
445
|
case "delete":
|
|
338
446
|
case "update":
|
|
447
|
+
return rows;
|
|
339
448
|
case "counter":
|
|
340
449
|
return resp.rowCount;
|
|
341
450
|
default:
|
package/package.json
CHANGED
package/src/index.ts
CHANGED
|
@@ -114,11 +114,45 @@ class DB2Client extends knex.Client {
|
|
|
114
114
|
const connection = await pool.connect();
|
|
115
115
|
const statement = await connection.createStatement();
|
|
116
116
|
await statement.prepare(obj.sql);
|
|
117
|
+
console.log({ obj });
|
|
117
118
|
if (obj.bindings) {
|
|
118
119
|
await statement.bind(obj.bindings);
|
|
119
120
|
}
|
|
120
121
|
const result = await statement.execute();
|
|
121
|
-
|
|
122
|
+
// this is hacky we check the SQL for the ID column
|
|
123
|
+
// most dialects return the ID of the inserted
|
|
124
|
+
// we check for the IDENTITY scalar function
|
|
125
|
+
// if that function is present, then we just return the value of the
|
|
126
|
+
// IDENTITY column
|
|
127
|
+
if (result.statement.includes("IDENTITY_VAL_LOCAL()")) {
|
|
128
|
+
obj.response = {
|
|
129
|
+
rows: result.map((row) =>
|
|
130
|
+
result.columns.length > 0 ? row[result.columns[0].name] : row,
|
|
131
|
+
),
|
|
132
|
+
rowCount: result.length,
|
|
133
|
+
};
|
|
134
|
+
} else if (method === "update") {
|
|
135
|
+
// if is in update we need to run a separate select query
|
|
136
|
+
// this also feels hacky and should be cleaned up
|
|
137
|
+
// it would be a lot easier if the table-reference function
|
|
138
|
+
// worked the same for updates as it does inserts
|
|
139
|
+
// on DB2 LUW it does work so if they ever add it we need to fix
|
|
140
|
+
console.log(this.queryCompiler)
|
|
141
|
+
let returningSelect = obj.sql.replace("update", "select * from ");
|
|
142
|
+
returningSelect = returningSelect.replace("where", "and");
|
|
143
|
+
returningSelect = returningSelect.replace("set", "where");
|
|
144
|
+
returningSelect = returningSelect.replace(this.tableName, "where");
|
|
145
|
+
const selectStatement = await connection.createStatement();
|
|
146
|
+
await selectStatement.prepare(returningSelect);
|
|
147
|
+
if (obj.bindings) {
|
|
148
|
+
await selectStatement.bind(obj.bindings);
|
|
149
|
+
}
|
|
150
|
+
const selected = await selectStatement.execute();
|
|
151
|
+
console.log(selected.columns)
|
|
152
|
+
obj.response = {rows: selected, rowCount: selected.length}
|
|
153
|
+
} else {
|
|
154
|
+
obj.response = { rows: result, rowCount: result.length };
|
|
155
|
+
}
|
|
122
156
|
} catch (err: any) {
|
|
123
157
|
console.error(err);
|
|
124
158
|
throw new Error(err);
|
|
@@ -128,6 +162,21 @@ class DB2Client extends knex.Client {
|
|
|
128
162
|
return obj;
|
|
129
163
|
}
|
|
130
164
|
|
|
165
|
+
_selectAfterUpdate() {
|
|
166
|
+
const returnSelect = `; SELECT ${
|
|
167
|
+
this.single.returning
|
|
168
|
+
? // @ts-ignore
|
|
169
|
+
this.formatter.columnize(this.single.returning)
|
|
170
|
+
: "*"
|
|
171
|
+
} from ${this.tableName} `;
|
|
172
|
+
let whereStatement = [this.where()];
|
|
173
|
+
console.log({ whereStatement });
|
|
174
|
+
for (const [key, value] of Object.entries(this.single.update)) {
|
|
175
|
+
whereStatement.push(`WHERE ${key} = ${value}`);
|
|
176
|
+
}
|
|
177
|
+
return returnSelect + whereStatement.join(" and ");
|
|
178
|
+
}
|
|
179
|
+
|
|
131
180
|
transaction(container: any, config: any, outerTx: any): Knex.Transaction {
|
|
132
181
|
// @ts-ignore
|
|
133
182
|
return new Transaction(this, ...arguments);
|
|
@@ -154,13 +203,11 @@ class DB2Client extends knex.Client {
|
|
|
154
203
|
}
|
|
155
204
|
|
|
156
205
|
processResponse(obj: any, runner: any) {
|
|
157
|
-
// TODO: verify correctness
|
|
158
206
|
if (obj === null) return null;
|
|
159
207
|
|
|
160
208
|
const resp = obj.response;
|
|
161
209
|
const method = obj.sqlMethod;
|
|
162
210
|
const { rows } = resp;
|
|
163
|
-
console.log({ method, rows });
|
|
164
211
|
|
|
165
212
|
if (obj.output) return obj.output.call(runner, resp);
|
|
166
213
|
|
|
@@ -172,9 +219,11 @@ class DB2Client extends knex.Client {
|
|
|
172
219
|
case "first":
|
|
173
220
|
return rows[0];
|
|
174
221
|
case "insert":
|
|
222
|
+
return rows;
|
|
175
223
|
case "del":
|
|
176
224
|
case "delete":
|
|
177
225
|
case "update":
|
|
226
|
+
return rows;
|
|
178
227
|
case "counter":
|
|
179
228
|
return resp.rowCount;
|
|
180
229
|
default:
|
|
@@ -3,8 +3,79 @@ import isObject from "lodash/isObject";
|
|
|
3
3
|
import { rawOrFn as rawOrFn_ } from "knex/lib/formatter/wrappingFormatter";
|
|
4
4
|
import { format } from "date-fns";
|
|
5
5
|
import * as console from "console";
|
|
6
|
+
import isEmpty from "lodash/isEmpty";
|
|
6
7
|
|
|
7
8
|
class IBMiQueryCompiler extends QueryCompiler {
|
|
9
|
+
insert() {
|
|
10
|
+
// @ts-ignore
|
|
11
|
+
const insertValues = this.single.insert || [];
|
|
12
|
+
// we need to return a value
|
|
13
|
+
// we need to wrap the insert statement in a select statement
|
|
14
|
+
// we use the "IDENTITY_VAL_LOCAL()" function to return the IDENTITY
|
|
15
|
+
// unless specified in a return
|
|
16
|
+
// @ts-ignore
|
|
17
|
+
let sql = `SELECT ${
|
|
18
|
+
// @ts-ignore
|
|
19
|
+
this.single.returning
|
|
20
|
+
? // @ts-ignore
|
|
21
|
+
this.formatter.columnize(this.single.returning)
|
|
22
|
+
: "IDENTITY_VAL_LOCAL()"
|
|
23
|
+
} FROM FINAL TABLE(`;
|
|
24
|
+
// @ts-ignore
|
|
25
|
+
sql += this.with() + `insert into ${this.tableName} `;
|
|
26
|
+
// @ts-ignore
|
|
27
|
+
const { returning } = this.single;
|
|
28
|
+
const returningSql = returning
|
|
29
|
+
? // @ts-ignore
|
|
30
|
+
this._returning("insert", returning) + " "
|
|
31
|
+
: "";
|
|
32
|
+
|
|
33
|
+
if (Array.isArray(insertValues)) {
|
|
34
|
+
if (insertValues.length === 0) {
|
|
35
|
+
return "";
|
|
36
|
+
}
|
|
37
|
+
} else if (typeof insertValues === "object" && isEmpty(insertValues)) {
|
|
38
|
+
return {
|
|
39
|
+
// @ts-ignore
|
|
40
|
+
sql: sql + returningSql + this._emptyInsertValue,
|
|
41
|
+
returning,
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// @ts-ignore
|
|
46
|
+
sql += this._buildInsertData(insertValues, returningSql);
|
|
47
|
+
sql += ")";
|
|
48
|
+
|
|
49
|
+
return {
|
|
50
|
+
sql,
|
|
51
|
+
returning,
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
_buildInsertData(insertValues, returningSql) {
|
|
56
|
+
let sql = "";
|
|
57
|
+
const insertData = this._prepInsert(insertValues);
|
|
58
|
+
if (typeof insertData === "string") {
|
|
59
|
+
sql += insertData;
|
|
60
|
+
} else {
|
|
61
|
+
if (insertData.columns.length) {
|
|
62
|
+
// @ts-ignore
|
|
63
|
+
sql += `(${this.formatter.columnize(insertData.columns)}`;
|
|
64
|
+
sql +=
|
|
65
|
+
`) ${returningSql}values (` +
|
|
66
|
+
// @ts-ignore
|
|
67
|
+
this._buildInsertValues(insertData) +
|
|
68
|
+
")";
|
|
69
|
+
} else if (insertValues.length === 1 && insertValues[0]) {
|
|
70
|
+
// @ts-ignore
|
|
71
|
+
sql += returningSql + this._emptyInsertValue;
|
|
72
|
+
} else {
|
|
73
|
+
return "";
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
return sql;
|
|
77
|
+
}
|
|
78
|
+
|
|
8
79
|
_prepInsert(data) {
|
|
9
80
|
if (isObject(data)) {
|
|
10
81
|
if (data.hasOwnProperty("migration_time")) {
|
|
@@ -55,6 +126,36 @@ class IBMiQueryCompiler extends QueryCompiler {
|
|
|
55
126
|
values,
|
|
56
127
|
};
|
|
57
128
|
}
|
|
129
|
+
|
|
130
|
+
_returning(method, value, withTrigger) {
|
|
131
|
+
// currently a placeholder in case I need to update return values
|
|
132
|
+
switch (method) {
|
|
133
|
+
case "update":
|
|
134
|
+
case "insert":
|
|
135
|
+
return value
|
|
136
|
+
? // @ts-ignore
|
|
137
|
+
`${withTrigger ? " into #out" : ""}`
|
|
138
|
+
: "";
|
|
139
|
+
case "del":
|
|
140
|
+
return value
|
|
141
|
+
? // @ts-ignore
|
|
142
|
+
`${withTrigger ? " into #out" : ""}`
|
|
143
|
+
: "";
|
|
144
|
+
case "rowcount":
|
|
145
|
+
return value ? ";select @@rowcount" : "";
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
columnizeWithPrefix(prefix, target) {
|
|
150
|
+
const columns = typeof target === "string" ? [target] : target;
|
|
151
|
+
let str = "",
|
|
152
|
+
i = -1;
|
|
153
|
+
while (++i < columns.length) {
|
|
154
|
+
if (i > 0) str += ", ";
|
|
155
|
+
str += prefix + this.wrap(columns[i]);
|
|
156
|
+
}
|
|
157
|
+
return str;
|
|
158
|
+
}
|
|
58
159
|
}
|
|
59
160
|
|
|
60
161
|
export default IBMiQueryCompiler;
|
|
@@ -2,10 +2,6 @@ import SchemaCompiler from "knex/lib/schema/compiler";
|
|
|
2
2
|
import * as console from "console";
|
|
3
3
|
|
|
4
4
|
class IBMiSchemaCompiler extends SchemaCompiler {
|
|
5
|
-
constructor(client, builder) {
|
|
6
|
-
super(client, builder);
|
|
7
|
-
}
|
|
8
|
-
|
|
9
5
|
hasTable(tableName) {
|
|
10
6
|
// @ts-ignore
|
|
11
7
|
const formattedTable = this.client.parameter(
|
|
@@ -42,7 +38,6 @@ class IBMiSchemaCompiler extends SchemaCompiler {
|
|
|
42
38
|
const sequence = this.builder._sequence;
|
|
43
39
|
for (let i = 0, l = sequence.length; i < l; i++) {
|
|
44
40
|
const query = sequence[i];
|
|
45
|
-
console.log(query.method, query);
|
|
46
41
|
this[query.method].apply(this, query.args);
|
|
47
42
|
}
|
|
48
43
|
// @ts-ignore
|