@bdkinc/knex-ibmi 0.0.3 → 0.0.5
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 +3 -2
- package/dist/index.js +56 -136
- package/dist/index.mjs +55 -138
- package/package.json +1 -1
- package/src/execution/ibmi-transaction.ts +0 -2
- package/src/index.ts +8 -18
- package/src/query/ibmi-querycompiler.ts +6 -78
- package/src/schema/ibmi-columncompiler.ts +1 -22
- package/src/schema/ibmi-compiler.ts +8 -1
- package/src/schema/ibmi-tablecompiler.ts +57 -53
package/README.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
[](https://npmjs.org/package/@bdkinc/knex-ibmi)
|
|
2
2
|
|
|
3
3
|
**Disclaimer: this library is in early stages of development. Please submit an issue for any bugs encounter or any questions you have.**
|
|
4
4
|
|
|
@@ -19,6 +19,7 @@ Currently, this dialect has limited functionality compared to the Knex built-in
|
|
|
19
19
|
- No streaming support
|
|
20
20
|
- Possibly other missing functionality
|
|
21
21
|
- Uses a pool for all connections
|
|
22
|
+
- 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.
|
|
22
23
|
|
|
23
24
|
## Installing
|
|
24
25
|
|
|
@@ -106,7 +107,7 @@ try {
|
|
|
106
107
|
|
|
107
108
|
## Configuring your driver
|
|
108
109
|
|
|
109
|
-
If you don't know the name of your installed driver, then look in
|
|
110
|
+
If you don't know the name of your installed driver, then look in `odbcinst.ini`. You can find the full path of the file by running `odbcinst -j`.
|
|
110
111
|
There you should see an entry like the one below:
|
|
111
112
|
|
|
112
113
|
```
|
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 = __toESM(require("knex"));
|
|
39
39
|
var odbc = __toESM(require("odbc"));
|
|
40
|
-
var
|
|
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"));
|
|
@@ -48,11 +48,14 @@ var IBMiSchemaCompiler = class extends import_compiler.default {
|
|
|
48
48
|
}
|
|
49
49
|
hasTable(tableName) {
|
|
50
50
|
const formattedTable = this.client.parameter(
|
|
51
|
+
// @ts-ignore
|
|
51
52
|
prefixedTableName(this.schema, tableName),
|
|
53
|
+
// @ts-ignore
|
|
52
54
|
this.builder,
|
|
55
|
+
// @ts-ignore
|
|
53
56
|
this.bindingsHolder
|
|
54
57
|
);
|
|
55
|
-
const bindings = [tableName
|
|
58
|
+
const bindings = [tableName];
|
|
56
59
|
let sql = `SELECT TABLE_NAME FROM QSYS2.SYSTABLES WHERE TYPE = 'T' AND TABLE_NAME = ${formattedTable}`;
|
|
57
60
|
if (this.schema) {
|
|
58
61
|
sql += " AND TABLE_SCHEMA = ?";
|
|
@@ -83,50 +86,18 @@ var ibmi_compiler_default = IBMiSchemaCompiler;
|
|
|
83
86
|
|
|
84
87
|
// src/schema/ibmi-tablecompiler.ts
|
|
85
88
|
var import_tablecompiler = __toESM(require("knex/lib/schema/tablecompiler"));
|
|
89
|
+
var import_isObject = __toESM(require("lodash/isObject"));
|
|
86
90
|
var IBMiTableCompiler = class extends import_tablecompiler.default {
|
|
87
|
-
constructor(client, tableBuilder) {
|
|
88
|
-
super(client, tableBuilder);
|
|
89
|
-
}
|
|
90
|
-
unique(columns, indexName) {
|
|
91
|
-
let deferrable;
|
|
92
|
-
let useConstraint = false;
|
|
93
|
-
let predicate;
|
|
94
|
-
if (typeof indexName === "object") {
|
|
95
|
-
({ indexName, deferrable, useConstraint, predicate } = indexName);
|
|
96
|
-
}
|
|
97
|
-
if (deferrable && deferrable !== "not deferrable") {
|
|
98
|
-
this.client.logger.warn(
|
|
99
|
-
`ibmi: unique index [${indexName}] will not be deferrable ${deferrable} because mssql does not support deferred constraints.`
|
|
100
|
-
);
|
|
101
|
-
}
|
|
102
|
-
if (useConstraint && predicate) {
|
|
103
|
-
throw new Error("ibmi cannot create constraint with predicate");
|
|
104
|
-
}
|
|
105
|
-
indexName = indexName ? this.formatter.wrap(indexName) : this._indexCommand("unique", this.tableNameRaw, columns);
|
|
106
|
-
if (!Array.isArray(columns)) {
|
|
107
|
-
columns = [columns];
|
|
108
|
-
}
|
|
109
|
-
if (useConstraint) {
|
|
110
|
-
this.pushQuery(
|
|
111
|
-
`ALTER TABLE ${this.tableName()} ADD CONSTRAINT ${indexName} UNIQUE (${this.formatter.columnize(
|
|
112
|
-
columns
|
|
113
|
-
)})`
|
|
114
|
-
);
|
|
115
|
-
} else {
|
|
116
|
-
const predicateQuery = predicate ? " " + this.client.queryCompiler(predicate).where() : " WHERE " + columns.map((column) => this.formatter.columnize(column) + " IS NOT NULL").join(" AND ");
|
|
117
|
-
this.pushQuery(
|
|
118
|
-
`CREATE UNIQUE INDEX ${indexName} ON ${this.tableName()} (${this.formatter.columnize(
|
|
119
|
-
columns
|
|
120
|
-
)})${predicateQuery}`
|
|
121
|
-
);
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
91
|
createQuery(columns, ifNot, like) {
|
|
125
92
|
let createStatement = ifNot ? `if object_id('${this.tableName()}', 'U') is null ` : "";
|
|
126
93
|
if (like) {
|
|
127
94
|
createStatement += `SELECT * INTO ${this.tableName()} FROM ${this.tableNameLike()} WHERE 0=1`;
|
|
128
95
|
} else {
|
|
129
|
-
createStatement += "CREATE TABLE " +
|
|
96
|
+
createStatement += "CREATE TABLE " + // @ts-ignore
|
|
97
|
+
this.tableName() + // @ts-ignore
|
|
98
|
+
(this._formatting ? " (\n " : " (") + // @ts-ignore
|
|
99
|
+
columns.sql.join(this._formatting ? ",\n " : ", ") + // @ts-ignore
|
|
100
|
+
this._addChecks() + ")";
|
|
130
101
|
}
|
|
131
102
|
this.pushQuery(createStatement);
|
|
132
103
|
if (this.single.comment) {
|
|
@@ -136,6 +107,29 @@ var IBMiTableCompiler = class extends import_tablecompiler.default {
|
|
|
136
107
|
this.addColumns(columns, this.addColumnsPrefix);
|
|
137
108
|
}
|
|
138
109
|
}
|
|
110
|
+
dropUnique(columns, indexName) {
|
|
111
|
+
indexName = indexName ? this.formatter.wrap(indexName) : this._indexCommand("unique", this.tableNameRaw, columns);
|
|
112
|
+
this.pushQuery(`drop index ${indexName}`);
|
|
113
|
+
}
|
|
114
|
+
unique(columns, indexName) {
|
|
115
|
+
let deferrable;
|
|
116
|
+
let predicate;
|
|
117
|
+
if ((0, import_isObject.default)(indexName)) {
|
|
118
|
+
({ indexName, deferrable, predicate } = indexName);
|
|
119
|
+
}
|
|
120
|
+
if (deferrable && deferrable !== "not deferrable") {
|
|
121
|
+
this.client.logger.warn(
|
|
122
|
+
`IBMi: unique index \`${indexName}\` will not be deferrable ${deferrable}.`
|
|
123
|
+
);
|
|
124
|
+
}
|
|
125
|
+
indexName = indexName ? this.formatter.wrap(indexName) : this._indexCommand("unique", this.tableNameRaw, columns);
|
|
126
|
+
columns = this.formatter.columnize(columns);
|
|
127
|
+
const predicateQuery = predicate ? " " + this.client.queryCompiler(predicate).where() : "";
|
|
128
|
+
this.pushQuery(
|
|
129
|
+
// @ts-ignore
|
|
130
|
+
`CREATE UNIQUE INDEX ${indexName} ON ${this.tableName()} (${columns})${predicateQuery}`
|
|
131
|
+
);
|
|
132
|
+
}
|
|
139
133
|
// All of the columns to "add" for the query
|
|
140
134
|
addColumns(columns, prefix) {
|
|
141
135
|
prefix = prefix || this.addColumnsPrefix;
|
|
@@ -144,7 +138,11 @@ var IBMiTableCompiler = class extends import_tablecompiler.default {
|
|
|
144
138
|
return prefix + column;
|
|
145
139
|
});
|
|
146
140
|
this.pushQuery({
|
|
147
|
-
sql: (
|
|
141
|
+
sql: (
|
|
142
|
+
// @ts-ignore
|
|
143
|
+
(this.lowerCase ? "alter table " : "ALTER TABLE ") + // @ts-ignore
|
|
144
|
+
this.tableName() + " " + columnSql.join(" ")
|
|
145
|
+
),
|
|
148
146
|
bindings: columns.bindings
|
|
149
147
|
});
|
|
150
148
|
}
|
|
@@ -157,32 +155,16 @@ var ibmi_tablecompiler_default = IBMiTableCompiler;
|
|
|
157
155
|
|
|
158
156
|
// src/schema/ibmi-columncompiler.ts
|
|
159
157
|
var import_columncompiler = __toESM(require("knex/lib/schema/columncompiler"));
|
|
160
|
-
var console2 = __toESM(require("console"));
|
|
161
158
|
var IBMiColumnCompiler = class extends import_columncompiler.default {
|
|
162
|
-
constructor(client, tableCompiler, columnBuilder) {
|
|
163
|
-
super(client, tableCompiler, columnBuilder);
|
|
164
|
-
}
|
|
165
159
|
increments(options = { primaryKey: true }) {
|
|
166
|
-
return "int not null generated always as identity (start with 1, increment by 1)" +
|
|
167
|
-
|
|
168
|
-
datetime(withoutTz = false, precision) {
|
|
169
|
-
let useTz;
|
|
170
|
-
if (isObject(withoutTz)) {
|
|
171
|
-
({ useTz, precision } = withoutTz);
|
|
172
|
-
} else {
|
|
173
|
-
useTz = !withoutTz;
|
|
174
|
-
}
|
|
175
|
-
useTz = typeof useTz === "boolean" ? useTz : true;
|
|
176
|
-
precision = precision !== void 0 && precision !== null ? "(" + precision + ")" : "";
|
|
177
|
-
console2.log(useTz, precision);
|
|
178
|
-
return `${useTz ? "timestamptz" : "timestamp"}${precision}`;
|
|
160
|
+
return "int not null generated always as identity (start with 1, increment by 1)" + // @ts-ignore
|
|
161
|
+
(this.tableCompiler._canBeAddPrimaryKey(options) ? " primary key" : "");
|
|
179
162
|
}
|
|
180
163
|
};
|
|
181
164
|
var ibmi_columncompiler_default = IBMiColumnCompiler;
|
|
182
165
|
|
|
183
166
|
// src/execution/ibmi-transaction.ts
|
|
184
167
|
var import_transaction = __toESM(require("knex/lib/execution/transaction"));
|
|
185
|
-
var console3 = __toESM(require("console"));
|
|
186
168
|
var IBMiTransaction = class extends import_transaction.default {
|
|
187
169
|
async begin(conn) {
|
|
188
170
|
const connection = await conn.connect();
|
|
@@ -190,7 +172,6 @@ var IBMiTransaction = class extends import_transaction.default {
|
|
|
190
172
|
return connection;
|
|
191
173
|
}
|
|
192
174
|
async rollback(conn) {
|
|
193
|
-
console3.log({ conn });
|
|
194
175
|
const connection = await conn.connect();
|
|
195
176
|
await connection.rollback();
|
|
196
177
|
return connection;
|
|
@@ -204,31 +185,25 @@ var ibmi_transaction_default = IBMiTransaction;
|
|
|
204
185
|
|
|
205
186
|
// src/query/ibmi-querycompiler.ts
|
|
206
187
|
var import_querycompiler = __toESM(require("knex/lib/query/querycompiler"));
|
|
207
|
-
var
|
|
208
|
-
var import_isEmpty = __toESM(require("lodash/isEmpty"));
|
|
209
|
-
var import_omitBy = __toESM(require("lodash/omitBy"));
|
|
210
|
-
var import_isObject = __toESM(require("lodash/isObject"));
|
|
188
|
+
var import_isObject2 = __toESM(require("lodash/isObject"));
|
|
211
189
|
var import_wrappingFormatter = require("knex/lib/formatter/wrappingFormatter");
|
|
212
190
|
var import_date_fns = require("date-fns");
|
|
213
|
-
var console4 = __toESM(require("console"));
|
|
214
191
|
var IBMiQueryCompiler = class extends import_querycompiler.default {
|
|
215
192
|
_prepInsert(data) {
|
|
216
|
-
if ((0,
|
|
217
|
-
console4.log("data is object", data);
|
|
193
|
+
if ((0, import_isObject2.default)(data)) {
|
|
218
194
|
if (data.hasOwnProperty("migration_time")) {
|
|
219
|
-
console4.log("data has migration_time", data.migration_time);
|
|
220
195
|
const parsed = new Date(data.migration_time);
|
|
221
|
-
console4.log(parsed);
|
|
222
196
|
data.migration_time = (0, import_date_fns.format)(parsed, "yyyy-MM-dd HH:mm:ss");
|
|
223
|
-
console4.log(data.migration_time);
|
|
224
197
|
}
|
|
225
|
-
console4.log("data date after change", data);
|
|
226
198
|
}
|
|
227
199
|
const isRaw = (0, import_wrappingFormatter.rawOrFn)(
|
|
228
200
|
data,
|
|
229
201
|
void 0,
|
|
202
|
+
// @ts-ignore
|
|
230
203
|
this.builder,
|
|
204
|
+
// @ts-ignore
|
|
231
205
|
this.client,
|
|
206
|
+
// @ts-ignore
|
|
232
207
|
this.bindingsHolder
|
|
233
208
|
);
|
|
234
209
|
if (isRaw)
|
|
@@ -267,54 +242,6 @@ var IBMiQueryCompiler = class extends import_querycompiler.default {
|
|
|
267
242
|
values
|
|
268
243
|
};
|
|
269
244
|
}
|
|
270
|
-
_prepUpdate(data = {}) {
|
|
271
|
-
const { counter = {} } = this.single;
|
|
272
|
-
for (const column of Object.keys(counter)) {
|
|
273
|
-
if ((0, import_has.default)(data, column)) {
|
|
274
|
-
this.client.logger.warn(
|
|
275
|
-
`increment/decrement called for a column that has already been specified in main .update() call. Ignoring increment/decrement and using value from .update() call.`
|
|
276
|
-
);
|
|
277
|
-
continue;
|
|
278
|
-
}
|
|
279
|
-
let value = counter[column];
|
|
280
|
-
const symbol = value < 0 ? "-" : "+";
|
|
281
|
-
if (symbol === "-") {
|
|
282
|
-
value = -value;
|
|
283
|
-
}
|
|
284
|
-
data[column] = this.client.raw(`?? ${symbol} ?`, [column, value]);
|
|
285
|
-
}
|
|
286
|
-
data = (0, import_omitBy.default)(data, (value) => typeof value === "undefined");
|
|
287
|
-
const vals = [];
|
|
288
|
-
const columns = Object.keys(data);
|
|
289
|
-
let i = -1;
|
|
290
|
-
while (++i < columns.length) {
|
|
291
|
-
vals.push(
|
|
292
|
-
(0, import_wrappingFormatter.wrap)(
|
|
293
|
-
columns[i],
|
|
294
|
-
void 0,
|
|
295
|
-
this.builder,
|
|
296
|
-
this.client,
|
|
297
|
-
this.bindingsHolder
|
|
298
|
-
) + " = " + this.client.parameter(
|
|
299
|
-
data[columns[i]],
|
|
300
|
-
this.builder,
|
|
301
|
-
this.bindingsHolder
|
|
302
|
-
)
|
|
303
|
-
);
|
|
304
|
-
}
|
|
305
|
-
if ((0, import_isEmpty.default)(vals)) {
|
|
306
|
-
throw new Error(
|
|
307
|
-
[
|
|
308
|
-
"Empty .update() call detected!",
|
|
309
|
-
"Update data does not contain any values to update.",
|
|
310
|
-
"This will result in a faulty query.",
|
|
311
|
-
this.single.table ? `Table: ${this.single.table}.` : "",
|
|
312
|
-
this.single.update ? `Columns: ${Object.keys(this.single.update)}.` : ""
|
|
313
|
-
].join(" ")
|
|
314
|
-
);
|
|
315
|
-
}
|
|
316
|
-
return vals;
|
|
317
|
-
}
|
|
318
245
|
};
|
|
319
246
|
var ibmi_querycompiler_default = IBMiQueryCompiler;
|
|
320
247
|
|
|
@@ -351,12 +278,6 @@ var DB2Client = class extends import_knex.default.Client {
|
|
|
351
278
|
_driver() {
|
|
352
279
|
return odbc;
|
|
353
280
|
}
|
|
354
|
-
wrapIdentifierImpl(value) {
|
|
355
|
-
if (value.includes("knex_migrations")) {
|
|
356
|
-
return value.toUpperCase();
|
|
357
|
-
}
|
|
358
|
-
return value;
|
|
359
|
-
}
|
|
360
281
|
printDebug(message) {
|
|
361
282
|
if (process.env.DEBUG === "true") {
|
|
362
283
|
this.logger.debug(message);
|
|
@@ -367,13 +288,13 @@ var DB2Client = class extends import_knex.default.Client {
|
|
|
367
288
|
async acquireRawConnection() {
|
|
368
289
|
this.printDebug("acquiring raw connection");
|
|
369
290
|
const connectionConfig = this.config.connection;
|
|
370
|
-
|
|
291
|
+
console2.log(this._getConnectionString(connectionConfig));
|
|
371
292
|
return await this.driver.pool(this._getConnectionString(connectionConfig));
|
|
372
293
|
}
|
|
373
294
|
// Used to explicitly close a connection, called internally by the pool manager
|
|
374
295
|
// when a connection times out or the pool is shutdown.
|
|
375
296
|
async destroyRawConnection(connection) {
|
|
376
|
-
|
|
297
|
+
console2.log("destroy connection");
|
|
377
298
|
return await connection.close();
|
|
378
299
|
}
|
|
379
300
|
_getConnectionString(connectionConfig) {
|
|
@@ -407,16 +328,15 @@ var DB2Client = class extends import_knex.default.Client {
|
|
|
407
328
|
await statement.bind(obj.bindings);
|
|
408
329
|
}
|
|
409
330
|
const result = await statement.execute();
|
|
410
|
-
obj.response = {
|
|
331
|
+
obj.response = { rowCount: result.count };
|
|
411
332
|
} catch (err) {
|
|
412
|
-
|
|
333
|
+
console2.error(err);
|
|
413
334
|
throw new Error(err);
|
|
414
335
|
}
|
|
415
336
|
}
|
|
416
|
-
console5.log({ obj });
|
|
417
337
|
return obj;
|
|
418
338
|
}
|
|
419
|
-
transaction() {
|
|
339
|
+
transaction(container, config, outerTx) {
|
|
420
340
|
return new ibmi_transaction_default(this, ...arguments);
|
|
421
341
|
}
|
|
422
342
|
schemaCompiler() {
|
|
@@ -437,16 +357,16 @@ var DB2Client = class extends import_knex.default.Client {
|
|
|
437
357
|
const resp = obj.response;
|
|
438
358
|
const method = obj.sqlMethod;
|
|
439
359
|
const { rows } = resp;
|
|
360
|
+
console2.log({ method, rows });
|
|
440
361
|
if (obj.output)
|
|
441
362
|
return obj.output.call(runner, resp);
|
|
442
363
|
switch (method) {
|
|
443
364
|
case "select":
|
|
365
|
+
return rows;
|
|
444
366
|
case "pluck":
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
return method === "first" ? rows[0] : rows;
|
|
449
|
-
}
|
|
367
|
+
return rows.map(obj.pluck);
|
|
368
|
+
case "first":
|
|
369
|
+
return rows[0];
|
|
450
370
|
case "insert":
|
|
451
371
|
case "del":
|
|
452
372
|
case "delete":
|
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
|
|
5
|
+
import * as console2 from "console";
|
|
6
6
|
|
|
7
7
|
// src/schema/ibmi-compiler.ts
|
|
8
8
|
import SchemaCompiler from "knex/lib/schema/compiler";
|
|
@@ -13,11 +13,14 @@ var IBMiSchemaCompiler = class extends SchemaCompiler {
|
|
|
13
13
|
}
|
|
14
14
|
hasTable(tableName) {
|
|
15
15
|
const formattedTable = this.client.parameter(
|
|
16
|
+
// @ts-ignore
|
|
16
17
|
prefixedTableName(this.schema, tableName),
|
|
18
|
+
// @ts-ignore
|
|
17
19
|
this.builder,
|
|
20
|
+
// @ts-ignore
|
|
18
21
|
this.bindingsHolder
|
|
19
22
|
);
|
|
20
|
-
const bindings = [tableName
|
|
23
|
+
const bindings = [tableName];
|
|
21
24
|
let sql = `SELECT TABLE_NAME FROM QSYS2.SYSTABLES WHERE TYPE = 'T' AND TABLE_NAME = ${formattedTable}`;
|
|
22
25
|
if (this.schema) {
|
|
23
26
|
sql += " AND TABLE_SCHEMA = ?";
|
|
@@ -48,50 +51,18 @@ var ibmi_compiler_default = IBMiSchemaCompiler;
|
|
|
48
51
|
|
|
49
52
|
// src/schema/ibmi-tablecompiler.ts
|
|
50
53
|
import TableCompiler from "knex/lib/schema/tablecompiler";
|
|
54
|
+
import isObject from "lodash/isObject";
|
|
51
55
|
var IBMiTableCompiler = class extends TableCompiler {
|
|
52
|
-
constructor(client, tableBuilder) {
|
|
53
|
-
super(client, tableBuilder);
|
|
54
|
-
}
|
|
55
|
-
unique(columns, indexName) {
|
|
56
|
-
let deferrable;
|
|
57
|
-
let useConstraint = false;
|
|
58
|
-
let predicate;
|
|
59
|
-
if (typeof indexName === "object") {
|
|
60
|
-
({ indexName, deferrable, useConstraint, predicate } = indexName);
|
|
61
|
-
}
|
|
62
|
-
if (deferrable && deferrable !== "not deferrable") {
|
|
63
|
-
this.client.logger.warn(
|
|
64
|
-
`ibmi: unique index [${indexName}] will not be deferrable ${deferrable} because mssql does not support deferred constraints.`
|
|
65
|
-
);
|
|
66
|
-
}
|
|
67
|
-
if (useConstraint && predicate) {
|
|
68
|
-
throw new Error("ibmi cannot create constraint with predicate");
|
|
69
|
-
}
|
|
70
|
-
indexName = indexName ? this.formatter.wrap(indexName) : this._indexCommand("unique", this.tableNameRaw, columns);
|
|
71
|
-
if (!Array.isArray(columns)) {
|
|
72
|
-
columns = [columns];
|
|
73
|
-
}
|
|
74
|
-
if (useConstraint) {
|
|
75
|
-
this.pushQuery(
|
|
76
|
-
`ALTER TABLE ${this.tableName()} ADD CONSTRAINT ${indexName} UNIQUE (${this.formatter.columnize(
|
|
77
|
-
columns
|
|
78
|
-
)})`
|
|
79
|
-
);
|
|
80
|
-
} else {
|
|
81
|
-
const predicateQuery = predicate ? " " + this.client.queryCompiler(predicate).where() : " WHERE " + columns.map((column) => this.formatter.columnize(column) + " IS NOT NULL").join(" AND ");
|
|
82
|
-
this.pushQuery(
|
|
83
|
-
`CREATE UNIQUE INDEX ${indexName} ON ${this.tableName()} (${this.formatter.columnize(
|
|
84
|
-
columns
|
|
85
|
-
)})${predicateQuery}`
|
|
86
|
-
);
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
56
|
createQuery(columns, ifNot, like) {
|
|
90
57
|
let createStatement = ifNot ? `if object_id('${this.tableName()}', 'U') is null ` : "";
|
|
91
58
|
if (like) {
|
|
92
59
|
createStatement += `SELECT * INTO ${this.tableName()} FROM ${this.tableNameLike()} WHERE 0=1`;
|
|
93
60
|
} else {
|
|
94
|
-
createStatement += "CREATE TABLE " +
|
|
61
|
+
createStatement += "CREATE TABLE " + // @ts-ignore
|
|
62
|
+
this.tableName() + // @ts-ignore
|
|
63
|
+
(this._formatting ? " (\n " : " (") + // @ts-ignore
|
|
64
|
+
columns.sql.join(this._formatting ? ",\n " : ", ") + // @ts-ignore
|
|
65
|
+
this._addChecks() + ")";
|
|
95
66
|
}
|
|
96
67
|
this.pushQuery(createStatement);
|
|
97
68
|
if (this.single.comment) {
|
|
@@ -101,6 +72,29 @@ var IBMiTableCompiler = class extends TableCompiler {
|
|
|
101
72
|
this.addColumns(columns, this.addColumnsPrefix);
|
|
102
73
|
}
|
|
103
74
|
}
|
|
75
|
+
dropUnique(columns, indexName) {
|
|
76
|
+
indexName = indexName ? this.formatter.wrap(indexName) : this._indexCommand("unique", this.tableNameRaw, columns);
|
|
77
|
+
this.pushQuery(`drop index ${indexName}`);
|
|
78
|
+
}
|
|
79
|
+
unique(columns, indexName) {
|
|
80
|
+
let deferrable;
|
|
81
|
+
let predicate;
|
|
82
|
+
if (isObject(indexName)) {
|
|
83
|
+
({ indexName, deferrable, predicate } = indexName);
|
|
84
|
+
}
|
|
85
|
+
if (deferrable && deferrable !== "not deferrable") {
|
|
86
|
+
this.client.logger.warn(
|
|
87
|
+
`IBMi: unique index \`${indexName}\` will not be deferrable ${deferrable}.`
|
|
88
|
+
);
|
|
89
|
+
}
|
|
90
|
+
indexName = indexName ? this.formatter.wrap(indexName) : this._indexCommand("unique", this.tableNameRaw, columns);
|
|
91
|
+
columns = this.formatter.columnize(columns);
|
|
92
|
+
const predicateQuery = predicate ? " " + this.client.queryCompiler(predicate).where() : "";
|
|
93
|
+
this.pushQuery(
|
|
94
|
+
// @ts-ignore
|
|
95
|
+
`CREATE UNIQUE INDEX ${indexName} ON ${this.tableName()} (${columns})${predicateQuery}`
|
|
96
|
+
);
|
|
97
|
+
}
|
|
104
98
|
// All of the columns to "add" for the query
|
|
105
99
|
addColumns(columns, prefix) {
|
|
106
100
|
prefix = prefix || this.addColumnsPrefix;
|
|
@@ -109,7 +103,11 @@ var IBMiTableCompiler = class extends TableCompiler {
|
|
|
109
103
|
return prefix + column;
|
|
110
104
|
});
|
|
111
105
|
this.pushQuery({
|
|
112
|
-
sql: (
|
|
106
|
+
sql: (
|
|
107
|
+
// @ts-ignore
|
|
108
|
+
(this.lowerCase ? "alter table " : "ALTER TABLE ") + // @ts-ignore
|
|
109
|
+
this.tableName() + " " + columnSql.join(" ")
|
|
110
|
+
),
|
|
113
111
|
bindings: columns.bindings
|
|
114
112
|
});
|
|
115
113
|
}
|
|
@@ -122,32 +120,16 @@ var ibmi_tablecompiler_default = IBMiTableCompiler;
|
|
|
122
120
|
|
|
123
121
|
// src/schema/ibmi-columncompiler.ts
|
|
124
122
|
import ColumnCompiler from "knex/lib/schema/columncompiler";
|
|
125
|
-
import * as console2 from "console";
|
|
126
123
|
var IBMiColumnCompiler = class extends ColumnCompiler {
|
|
127
|
-
constructor(client, tableCompiler, columnBuilder) {
|
|
128
|
-
super(client, tableCompiler, columnBuilder);
|
|
129
|
-
}
|
|
130
124
|
increments(options = { primaryKey: true }) {
|
|
131
|
-
return "int not null generated always as identity (start with 1, increment by 1)" +
|
|
132
|
-
|
|
133
|
-
datetime(withoutTz = false, precision) {
|
|
134
|
-
let useTz;
|
|
135
|
-
if (isObject(withoutTz)) {
|
|
136
|
-
({ useTz, precision } = withoutTz);
|
|
137
|
-
} else {
|
|
138
|
-
useTz = !withoutTz;
|
|
139
|
-
}
|
|
140
|
-
useTz = typeof useTz === "boolean" ? useTz : true;
|
|
141
|
-
precision = precision !== void 0 && precision !== null ? "(" + precision + ")" : "";
|
|
142
|
-
console2.log(useTz, precision);
|
|
143
|
-
return `${useTz ? "timestamptz" : "timestamp"}${precision}`;
|
|
125
|
+
return "int not null generated always as identity (start with 1, increment by 1)" + // @ts-ignore
|
|
126
|
+
(this.tableCompiler._canBeAddPrimaryKey(options) ? " primary key" : "");
|
|
144
127
|
}
|
|
145
128
|
};
|
|
146
129
|
var ibmi_columncompiler_default = IBMiColumnCompiler;
|
|
147
130
|
|
|
148
131
|
// src/execution/ibmi-transaction.ts
|
|
149
132
|
import Transaction from "knex/lib/execution/transaction";
|
|
150
|
-
import * as console3 from "console";
|
|
151
133
|
var IBMiTransaction = class extends Transaction {
|
|
152
134
|
async begin(conn) {
|
|
153
135
|
const connection = await conn.connect();
|
|
@@ -155,7 +137,6 @@ var IBMiTransaction = class extends Transaction {
|
|
|
155
137
|
return connection;
|
|
156
138
|
}
|
|
157
139
|
async rollback(conn) {
|
|
158
|
-
console3.log({ conn });
|
|
159
140
|
const connection = await conn.connect();
|
|
160
141
|
await connection.rollback();
|
|
161
142
|
return connection;
|
|
@@ -169,34 +150,25 @@ var ibmi_transaction_default = IBMiTransaction;
|
|
|
169
150
|
|
|
170
151
|
// src/query/ibmi-querycompiler.ts
|
|
171
152
|
import QueryCompiler from "knex/lib/query/querycompiler";
|
|
172
|
-
import has from "lodash/has";
|
|
173
|
-
import isEmpty from "lodash/isEmpty";
|
|
174
|
-
import omitBy from "lodash/omitBy";
|
|
175
153
|
import isObject2 from "lodash/isObject";
|
|
176
|
-
import {
|
|
177
|
-
wrap as wrap_,
|
|
178
|
-
rawOrFn as rawOrFn_
|
|
179
|
-
} from "knex/lib/formatter/wrappingFormatter";
|
|
154
|
+
import { rawOrFn as rawOrFn_ } from "knex/lib/formatter/wrappingFormatter";
|
|
180
155
|
import { format } from "date-fns";
|
|
181
|
-
import * as console4 from "console";
|
|
182
156
|
var IBMiQueryCompiler = class extends QueryCompiler {
|
|
183
157
|
_prepInsert(data) {
|
|
184
158
|
if (isObject2(data)) {
|
|
185
|
-
console4.log("data is object", data);
|
|
186
159
|
if (data.hasOwnProperty("migration_time")) {
|
|
187
|
-
console4.log("data has migration_time", data.migration_time);
|
|
188
160
|
const parsed = new Date(data.migration_time);
|
|
189
|
-
console4.log(parsed);
|
|
190
161
|
data.migration_time = format(parsed, "yyyy-MM-dd HH:mm:ss");
|
|
191
|
-
console4.log(data.migration_time);
|
|
192
162
|
}
|
|
193
|
-
console4.log("data date after change", data);
|
|
194
163
|
}
|
|
195
164
|
const isRaw = rawOrFn_(
|
|
196
165
|
data,
|
|
197
166
|
void 0,
|
|
167
|
+
// @ts-ignore
|
|
198
168
|
this.builder,
|
|
169
|
+
// @ts-ignore
|
|
199
170
|
this.client,
|
|
171
|
+
// @ts-ignore
|
|
200
172
|
this.bindingsHolder
|
|
201
173
|
);
|
|
202
174
|
if (isRaw)
|
|
@@ -235,54 +207,6 @@ var IBMiQueryCompiler = class extends QueryCompiler {
|
|
|
235
207
|
values
|
|
236
208
|
};
|
|
237
209
|
}
|
|
238
|
-
_prepUpdate(data = {}) {
|
|
239
|
-
const { counter = {} } = this.single;
|
|
240
|
-
for (const column of Object.keys(counter)) {
|
|
241
|
-
if (has(data, column)) {
|
|
242
|
-
this.client.logger.warn(
|
|
243
|
-
`increment/decrement called for a column that has already been specified in main .update() call. Ignoring increment/decrement and using value from .update() call.`
|
|
244
|
-
);
|
|
245
|
-
continue;
|
|
246
|
-
}
|
|
247
|
-
let value = counter[column];
|
|
248
|
-
const symbol = value < 0 ? "-" : "+";
|
|
249
|
-
if (symbol === "-") {
|
|
250
|
-
value = -value;
|
|
251
|
-
}
|
|
252
|
-
data[column] = this.client.raw(`?? ${symbol} ?`, [column, value]);
|
|
253
|
-
}
|
|
254
|
-
data = omitBy(data, (value) => typeof value === "undefined");
|
|
255
|
-
const vals = [];
|
|
256
|
-
const columns = Object.keys(data);
|
|
257
|
-
let i = -1;
|
|
258
|
-
while (++i < columns.length) {
|
|
259
|
-
vals.push(
|
|
260
|
-
wrap_(
|
|
261
|
-
columns[i],
|
|
262
|
-
void 0,
|
|
263
|
-
this.builder,
|
|
264
|
-
this.client,
|
|
265
|
-
this.bindingsHolder
|
|
266
|
-
) + " = " + this.client.parameter(
|
|
267
|
-
data[columns[i]],
|
|
268
|
-
this.builder,
|
|
269
|
-
this.bindingsHolder
|
|
270
|
-
)
|
|
271
|
-
);
|
|
272
|
-
}
|
|
273
|
-
if (isEmpty(vals)) {
|
|
274
|
-
throw new Error(
|
|
275
|
-
[
|
|
276
|
-
"Empty .update() call detected!",
|
|
277
|
-
"Update data does not contain any values to update.",
|
|
278
|
-
"This will result in a faulty query.",
|
|
279
|
-
this.single.table ? `Table: ${this.single.table}.` : "",
|
|
280
|
-
this.single.update ? `Columns: ${Object.keys(this.single.update)}.` : ""
|
|
281
|
-
].join(" ")
|
|
282
|
-
);
|
|
283
|
-
}
|
|
284
|
-
return vals;
|
|
285
|
-
}
|
|
286
210
|
};
|
|
287
211
|
var ibmi_querycompiler_default = IBMiQueryCompiler;
|
|
288
212
|
|
|
@@ -319,12 +243,6 @@ var DB2Client = class extends knex.Client {
|
|
|
319
243
|
_driver() {
|
|
320
244
|
return odbc;
|
|
321
245
|
}
|
|
322
|
-
wrapIdentifierImpl(value) {
|
|
323
|
-
if (value.includes("knex_migrations")) {
|
|
324
|
-
return value.toUpperCase();
|
|
325
|
-
}
|
|
326
|
-
return value;
|
|
327
|
-
}
|
|
328
246
|
printDebug(message) {
|
|
329
247
|
if (process.env.DEBUG === "true") {
|
|
330
248
|
this.logger.debug(message);
|
|
@@ -335,13 +253,13 @@ var DB2Client = class extends knex.Client {
|
|
|
335
253
|
async acquireRawConnection() {
|
|
336
254
|
this.printDebug("acquiring raw connection");
|
|
337
255
|
const connectionConfig = this.config.connection;
|
|
338
|
-
|
|
256
|
+
console2.log(this._getConnectionString(connectionConfig));
|
|
339
257
|
return await this.driver.pool(this._getConnectionString(connectionConfig));
|
|
340
258
|
}
|
|
341
259
|
// Used to explicitly close a connection, called internally by the pool manager
|
|
342
260
|
// when a connection times out or the pool is shutdown.
|
|
343
261
|
async destroyRawConnection(connection) {
|
|
344
|
-
|
|
262
|
+
console2.log("destroy connection");
|
|
345
263
|
return await connection.close();
|
|
346
264
|
}
|
|
347
265
|
_getConnectionString(connectionConfig) {
|
|
@@ -375,16 +293,15 @@ var DB2Client = class extends knex.Client {
|
|
|
375
293
|
await statement.bind(obj.bindings);
|
|
376
294
|
}
|
|
377
295
|
const result = await statement.execute();
|
|
378
|
-
obj.response = {
|
|
296
|
+
obj.response = { rowCount: result.count };
|
|
379
297
|
} catch (err) {
|
|
380
|
-
|
|
298
|
+
console2.error(err);
|
|
381
299
|
throw new Error(err);
|
|
382
300
|
}
|
|
383
301
|
}
|
|
384
|
-
console5.log({ obj });
|
|
385
302
|
return obj;
|
|
386
303
|
}
|
|
387
|
-
transaction() {
|
|
304
|
+
transaction(container, config, outerTx) {
|
|
388
305
|
return new ibmi_transaction_default(this, ...arguments);
|
|
389
306
|
}
|
|
390
307
|
schemaCompiler() {
|
|
@@ -405,16 +322,16 @@ var DB2Client = class extends knex.Client {
|
|
|
405
322
|
const resp = obj.response;
|
|
406
323
|
const method = obj.sqlMethod;
|
|
407
324
|
const { rows } = resp;
|
|
325
|
+
console2.log({ method, rows });
|
|
408
326
|
if (obj.output)
|
|
409
327
|
return obj.output.call(runner, resp);
|
|
410
328
|
switch (method) {
|
|
411
329
|
case "select":
|
|
330
|
+
return rows;
|
|
412
331
|
case "pluck":
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
return method === "first" ? rows[0] : rows;
|
|
417
|
-
}
|
|
332
|
+
return rows.map(obj.pluck);
|
|
333
|
+
case "first":
|
|
334
|
+
return rows[0];
|
|
418
335
|
case "insert":
|
|
419
336
|
case "del":
|
|
420
337
|
case "delete":
|
package/package.json
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import Transaction from "knex/lib/execution/transaction";
|
|
2
2
|
import * as console from "console";
|
|
3
|
-
import { connect } from "odbc";
|
|
4
3
|
|
|
5
4
|
class IBMiTransaction extends Transaction {
|
|
6
5
|
async begin(conn) {
|
|
@@ -10,7 +9,6 @@ class IBMiTransaction extends Transaction {
|
|
|
10
9
|
}
|
|
11
10
|
|
|
12
11
|
async rollback(conn) {
|
|
13
|
-
console.log({ conn });
|
|
14
12
|
const connection = await conn.connect();
|
|
15
13
|
await connection.rollback();
|
|
16
14
|
return connection;
|
package/src/index.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as process from "process";
|
|
2
2
|
import { Connection } from "odbc";
|
|
3
|
-
import knex from "knex";
|
|
3
|
+
import knex, { Knex } from "knex";
|
|
4
4
|
import * as odbc from "odbc";
|
|
5
5
|
import * as console from "console";
|
|
6
6
|
import SchemaCompiler from "./schema/ibmi-compiler";
|
|
@@ -12,7 +12,6 @@ import QueryCompiler from "./query/ibmi-querycompiler";
|
|
|
12
12
|
class DB2Client extends knex.Client {
|
|
13
13
|
constructor(config) {
|
|
14
14
|
super(config);
|
|
15
|
-
|
|
16
15
|
this.driverName = "odbc";
|
|
17
16
|
|
|
18
17
|
if (this.dialect && !this.config.client) {
|
|
@@ -49,15 +48,6 @@ class DB2Client extends knex.Client {
|
|
|
49
48
|
return odbc;
|
|
50
49
|
}
|
|
51
50
|
|
|
52
|
-
wrapIdentifierImpl(value: any) {
|
|
53
|
-
// override default wrapper ("). we don't want to use it since
|
|
54
|
-
// it makes identifiers case-sensitive in DB2
|
|
55
|
-
if (value.includes("knex_migrations")) {
|
|
56
|
-
return value.toUpperCase();
|
|
57
|
-
}
|
|
58
|
-
return value;
|
|
59
|
-
}
|
|
60
|
-
|
|
61
51
|
printDebug(message: string) {
|
|
62
52
|
if (process.env.DEBUG === "true") {
|
|
63
53
|
// @ts-ignore
|
|
@@ -128,18 +118,17 @@ class DB2Client extends knex.Client {
|
|
|
128
118
|
await statement.bind(obj.bindings);
|
|
129
119
|
}
|
|
130
120
|
const result = await statement.execute();
|
|
131
|
-
obj.response = {
|
|
121
|
+
obj.response = { rowCount: result.count };
|
|
132
122
|
} catch (err: any) {
|
|
133
123
|
console.error(err);
|
|
134
124
|
throw new Error(err);
|
|
135
125
|
}
|
|
136
126
|
}
|
|
137
|
-
console.log({ obj });
|
|
138
127
|
|
|
139
128
|
return obj;
|
|
140
129
|
}
|
|
141
130
|
|
|
142
|
-
transaction() {
|
|
131
|
+
transaction(container: any, config: any, outerTx: any): Knex.Transaction {
|
|
143
132
|
// @ts-ignore
|
|
144
133
|
return new Transaction(this, ...arguments);
|
|
145
134
|
}
|
|
@@ -171,16 +160,17 @@ class DB2Client extends knex.Client {
|
|
|
171
160
|
const resp = obj.response;
|
|
172
161
|
const method = obj.sqlMethod;
|
|
173
162
|
const { rows } = resp;
|
|
163
|
+
console.log({ method, rows });
|
|
174
164
|
|
|
175
165
|
if (obj.output) return obj.output.call(runner, resp);
|
|
176
166
|
|
|
177
167
|
switch (method) {
|
|
178
168
|
case "select":
|
|
169
|
+
return rows;
|
|
179
170
|
case "pluck":
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
return
|
|
183
|
-
}
|
|
171
|
+
return rows.map(obj.pluck);
|
|
172
|
+
case "first":
|
|
173
|
+
return rows[0];
|
|
184
174
|
case "insert":
|
|
185
175
|
case "del":
|
|
186
176
|
case "delete":
|
|
@@ -1,33 +1,26 @@
|
|
|
1
1
|
import QueryCompiler from "knex/lib/query/querycompiler";
|
|
2
|
-
import has from "lodash/has";
|
|
3
|
-
import isEmpty from "lodash/isEmpty";
|
|
4
|
-
import omitBy from "lodash/omitBy";
|
|
5
2
|
import isObject from "lodash/isObject";
|
|
6
|
-
import {
|
|
7
|
-
|
|
8
|
-
rawOrFn as rawOrFn_,
|
|
9
|
-
} from "knex/lib/formatter/wrappingFormatter";
|
|
10
|
-
import { format, parseISO } from "date-fns";
|
|
3
|
+
import { rawOrFn as rawOrFn_ } from "knex/lib/formatter/wrappingFormatter";
|
|
4
|
+
import { format } from "date-fns";
|
|
11
5
|
import * as console from "console";
|
|
12
6
|
|
|
13
7
|
class IBMiQueryCompiler extends QueryCompiler {
|
|
14
8
|
_prepInsert(data) {
|
|
15
9
|
if (isObject(data)) {
|
|
16
|
-
console.log("data is object", data);
|
|
17
10
|
if (data.hasOwnProperty("migration_time")) {
|
|
18
|
-
console.log("data has migration_time", data.migration_time);
|
|
19
11
|
const parsed = new Date(data.migration_time);
|
|
20
|
-
console.log(parsed);
|
|
21
12
|
data.migration_time = format(parsed, "yyyy-MM-dd HH:mm:ss");
|
|
22
|
-
console.log(data.migration_time);
|
|
23
13
|
}
|
|
24
|
-
console.log("data date after change", data);
|
|
25
14
|
}
|
|
15
|
+
|
|
26
16
|
const isRaw = rawOrFn_(
|
|
27
17
|
data,
|
|
28
18
|
undefined,
|
|
19
|
+
// @ts-ignore
|
|
29
20
|
this.builder,
|
|
21
|
+
// @ts-ignore
|
|
30
22
|
this.client,
|
|
23
|
+
// @ts-ignore
|
|
31
24
|
this.bindingsHolder,
|
|
32
25
|
);
|
|
33
26
|
if (isRaw) return isRaw;
|
|
@@ -62,71 +55,6 @@ class IBMiQueryCompiler extends QueryCompiler {
|
|
|
62
55
|
values,
|
|
63
56
|
};
|
|
64
57
|
}
|
|
65
|
-
|
|
66
|
-
_prepUpdate(data = {}): any[] {
|
|
67
|
-
const { counter = {} } = this.single;
|
|
68
|
-
|
|
69
|
-
for (const column of Object.keys(counter)) {
|
|
70
|
-
//Skip?
|
|
71
|
-
if (has(data, column)) {
|
|
72
|
-
//Needed?
|
|
73
|
-
this.client.logger.warn(
|
|
74
|
-
`increment/decrement called for a column that has already been specified in main .update() call. Ignoring increment/decrement and using value from .update() call.`,
|
|
75
|
-
);
|
|
76
|
-
continue;
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
let value = counter[column];
|
|
80
|
-
|
|
81
|
-
const symbol = value < 0 ? "-" : "+";
|
|
82
|
-
|
|
83
|
-
if (symbol === "-") {
|
|
84
|
-
value = -value;
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
data[column] = this.client.raw(`?? ${symbol} ?`, [column, value]);
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
data = omitBy(data, (value) => typeof value === "undefined");
|
|
91
|
-
|
|
92
|
-
const vals = [];
|
|
93
|
-
const columns = Object.keys(data);
|
|
94
|
-
let i = -1;
|
|
95
|
-
|
|
96
|
-
while (++i < columns.length) {
|
|
97
|
-
vals.push(
|
|
98
|
-
wrap_(
|
|
99
|
-
columns[i],
|
|
100
|
-
undefined,
|
|
101
|
-
this.builder,
|
|
102
|
-
this.client,
|
|
103
|
-
this.bindingsHolder,
|
|
104
|
-
) +
|
|
105
|
-
" = " +
|
|
106
|
-
this.client.parameter(
|
|
107
|
-
data[columns[i]],
|
|
108
|
-
this.builder,
|
|
109
|
-
this.bindingsHolder,
|
|
110
|
-
),
|
|
111
|
-
);
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
if (isEmpty(vals)) {
|
|
115
|
-
throw new Error(
|
|
116
|
-
[
|
|
117
|
-
"Empty .update() call detected!",
|
|
118
|
-
"Update data does not contain any values to update.",
|
|
119
|
-
"This will result in a faulty query.",
|
|
120
|
-
this.single.table ? `Table: ${this.single.table}.` : "",
|
|
121
|
-
this.single.update
|
|
122
|
-
? `Columns: ${Object.keys(this.single.update)}.`
|
|
123
|
-
: "",
|
|
124
|
-
].join(" "),
|
|
125
|
-
);
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
return vals;
|
|
129
|
-
}
|
|
130
58
|
}
|
|
131
59
|
|
|
132
60
|
export default IBMiQueryCompiler;
|
|
@@ -1,34 +1,13 @@
|
|
|
1
1
|
import ColumnCompiler from "knex/lib/schema/columncompiler";
|
|
2
|
-
import * as console from "console";
|
|
3
2
|
|
|
4
3
|
class IBMiColumnCompiler extends ColumnCompiler {
|
|
5
|
-
constructor(client, tableCompiler, columnBuilder) {
|
|
6
|
-
super(client, tableCompiler, columnBuilder);
|
|
7
|
-
}
|
|
8
|
-
|
|
9
4
|
increments(options = { primaryKey: true }) {
|
|
10
5
|
return (
|
|
11
6
|
"int not null generated always as identity (start with 1, increment by 1)" +
|
|
7
|
+
// @ts-ignore
|
|
12
8
|
(this.tableCompiler._canBeAddPrimaryKey(options) ? " primary key" : "")
|
|
13
9
|
);
|
|
14
10
|
}
|
|
15
|
-
|
|
16
|
-
datetime(withoutTz = false, precision) {
|
|
17
|
-
let useTz;
|
|
18
|
-
if (isObject(withoutTz)) {
|
|
19
|
-
({ useTz, precision } = withoutTz);
|
|
20
|
-
} else {
|
|
21
|
-
useTz = !withoutTz;
|
|
22
|
-
}
|
|
23
|
-
useTz = typeof useTz === "boolean" ? useTz : true;
|
|
24
|
-
precision =
|
|
25
|
-
precision !== undefined && precision !== null
|
|
26
|
-
? "(" + precision + ")"
|
|
27
|
-
: "";
|
|
28
|
-
|
|
29
|
-
console.log(useTz, precision);
|
|
30
|
-
return `${useTz ? "timestamptz" : "timestamp"}${precision}`;
|
|
31
|
-
}
|
|
32
11
|
}
|
|
33
12
|
|
|
34
13
|
export default IBMiColumnCompiler;
|
|
@@ -7,20 +7,27 @@ class IBMiSchemaCompiler extends SchemaCompiler {
|
|
|
7
7
|
}
|
|
8
8
|
|
|
9
9
|
hasTable(tableName) {
|
|
10
|
+
// @ts-ignore
|
|
10
11
|
const formattedTable = this.client.parameter(
|
|
12
|
+
// @ts-ignore
|
|
11
13
|
prefixedTableName(this.schema, tableName),
|
|
14
|
+
// @ts-ignore
|
|
12
15
|
this.builder,
|
|
16
|
+
// @ts-ignore
|
|
13
17
|
this.bindingsHolder,
|
|
14
18
|
);
|
|
15
|
-
const bindings = [tableName
|
|
19
|
+
const bindings = [tableName];
|
|
16
20
|
let sql =
|
|
17
21
|
`SELECT TABLE_NAME FROM QSYS2.SYSTABLES ` +
|
|
18
22
|
`WHERE TYPE = 'T' AND TABLE_NAME = ${formattedTable}`;
|
|
23
|
+
// @ts-ignore
|
|
19
24
|
if (this.schema) {
|
|
20
25
|
sql += " AND TABLE_SCHEMA = ?";
|
|
26
|
+
// @ts-ignore
|
|
21
27
|
bindings.push(this.schema);
|
|
22
28
|
}
|
|
23
29
|
|
|
30
|
+
// @ts-ignore
|
|
24
31
|
this.pushQuery({
|
|
25
32
|
sql,
|
|
26
33
|
bindings,
|
|
@@ -1,98 +1,102 @@
|
|
|
1
1
|
import TableCompiler from "knex/lib/schema/tablecompiler";
|
|
2
|
+
import isObject from "lodash/isObject";
|
|
2
3
|
|
|
3
4
|
class IBMiTableCompiler extends TableCompiler {
|
|
4
|
-
constructor(client, tableBuilder) {
|
|
5
|
-
super(client, tableBuilder);
|
|
6
|
-
}
|
|
7
|
-
|
|
8
|
-
unique(columns, indexName) {
|
|
9
|
-
/** @type {string | undefined} */
|
|
10
|
-
let deferrable;
|
|
11
|
-
let useConstraint = false;
|
|
12
|
-
let predicate;
|
|
13
|
-
if (typeof indexName === "object") {
|
|
14
|
-
({ indexName, deferrable, useConstraint, predicate } = indexName);
|
|
15
|
-
}
|
|
16
|
-
if (deferrable && deferrable !== 'not deferrable') {
|
|
17
|
-
this.client.logger.warn(
|
|
18
|
-
`ibmi: unique index [${indexName}] will not be deferrable ${deferrable} because mssql does not support deferred constraints.`
|
|
19
|
-
);
|
|
20
|
-
}
|
|
21
|
-
if (useConstraint && predicate) {
|
|
22
|
-
throw new Error('ibmi cannot create constraint with predicate');
|
|
23
|
-
}
|
|
24
|
-
indexName = indexName
|
|
25
|
-
? this.formatter.wrap(indexName)
|
|
26
|
-
: this._indexCommand('unique', this.tableNameRaw, columns);
|
|
27
|
-
|
|
28
|
-
if (!Array.isArray(columns)) {
|
|
29
|
-
columns = [columns];
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
if (useConstraint) {
|
|
33
|
-
// mssql supports unique indexes and unique constraints.
|
|
34
|
-
// unique indexes cannot be used with foreign key relationships hence unique constraints are used instead.
|
|
35
|
-
this.pushQuery(
|
|
36
|
-
`ALTER TABLE ${this.tableName()} ADD CONSTRAINT ${indexName} UNIQUE (${this.formatter.columnize(
|
|
37
|
-
columns
|
|
38
|
-
)})`
|
|
39
|
-
);
|
|
40
|
-
} else {
|
|
41
|
-
// default to making unique index that allows null https://stackoverflow.com/a/767702/360060
|
|
42
|
-
// to be more or less compatible with other DBs (if any of the columns is NULL then "duplicates" are allowed)
|
|
43
|
-
const predicateQuery = predicate
|
|
44
|
-
? ' ' + this.client.queryCompiler(predicate).where()
|
|
45
|
-
: ' WHERE ' +
|
|
46
|
-
columns
|
|
47
|
-
.map((column) => this.formatter.columnize(column) + ' IS NOT NULL')
|
|
48
|
-
.join(' AND ');
|
|
49
|
-
this.pushQuery(
|
|
50
|
-
`CREATE UNIQUE INDEX ${indexName} ON ${this.tableName()} (${this.formatter.columnize(
|
|
51
|
-
columns
|
|
52
|
-
)})${predicateQuery}`
|
|
53
|
-
);
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
|
|
57
5
|
createQuery(columns, ifNot, like) {
|
|
58
6
|
let createStatement = ifNot
|
|
7
|
+
// @ts-ignore
|
|
59
8
|
? `if object_id('${this.tableName()}', 'U') is null `
|
|
60
9
|
: "";
|
|
61
10
|
|
|
62
11
|
if (like) {
|
|
63
12
|
// This query copy only columns and not all indexes and keys like other databases.
|
|
13
|
+
// @ts-ignore
|
|
64
14
|
createStatement += `SELECT * INTO ${this.tableName()} FROM ${this.tableNameLike()} WHERE 0=1`;
|
|
65
15
|
} else {
|
|
66
16
|
createStatement +=
|
|
67
17
|
"CREATE TABLE " +
|
|
18
|
+
// @ts-ignore
|
|
68
19
|
this.tableName() +
|
|
20
|
+
// @ts-ignore
|
|
69
21
|
(this._formatting ? " (\n " : " (") +
|
|
22
|
+
// @ts-ignore
|
|
70
23
|
columns.sql.join(this._formatting ? ",\n " : ", ") +
|
|
24
|
+
// @ts-ignore
|
|
71
25
|
this._addChecks() +
|
|
72
26
|
")";
|
|
73
27
|
}
|
|
74
28
|
|
|
29
|
+
// @ts-ignore
|
|
75
30
|
this.pushQuery(createStatement);
|
|
76
31
|
|
|
32
|
+
// @ts-ignore
|
|
77
33
|
if (this.single.comment) {
|
|
34
|
+
// @ts-ignore
|
|
78
35
|
this.comment(this.single.comment);
|
|
79
36
|
}
|
|
80
37
|
if (like) {
|
|
38
|
+
// @ts-ignore
|
|
81
39
|
this.addColumns(columns, this.addColumnsPrefix);
|
|
82
40
|
}
|
|
83
41
|
}
|
|
84
42
|
|
|
43
|
+
dropUnique(columns, indexName) {
|
|
44
|
+
indexName = indexName
|
|
45
|
+
// @ts-ignore
|
|
46
|
+
? this.formatter.wrap(indexName)
|
|
47
|
+
// @ts-ignore
|
|
48
|
+
: this._indexCommand('unique', this.tableNameRaw, columns);
|
|
49
|
+
// @ts-ignore
|
|
50
|
+
this.pushQuery(`drop index ${indexName}`);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
unique(columns, indexName) {
|
|
54
|
+
let deferrable;
|
|
55
|
+
let predicate;
|
|
56
|
+
if (isObject(indexName)) {
|
|
57
|
+
({ indexName, deferrable, predicate } = indexName);
|
|
58
|
+
}
|
|
59
|
+
if (deferrable && deferrable !== 'not deferrable') {
|
|
60
|
+
// @ts-ignore
|
|
61
|
+
this.client.logger.warn(
|
|
62
|
+
`IBMi: unique index \`${indexName}\` will not be deferrable ${deferrable}.`
|
|
63
|
+
);
|
|
64
|
+
}
|
|
65
|
+
indexName = indexName
|
|
66
|
+
// @ts-ignore
|
|
67
|
+
? this.formatter.wrap(indexName)
|
|
68
|
+
// @ts-ignore
|
|
69
|
+
: this._indexCommand('unique', this.tableNameRaw, columns);
|
|
70
|
+
// @ts-ignore
|
|
71
|
+
columns = this.formatter.columnize(columns);
|
|
72
|
+
|
|
73
|
+
const predicateQuery = predicate
|
|
74
|
+
// @ts-ignore
|
|
75
|
+
? ' ' + this.client.queryCompiler(predicate).where()
|
|
76
|
+
: '';
|
|
77
|
+
|
|
78
|
+
// @ts-ignore
|
|
79
|
+
this.pushQuery(
|
|
80
|
+
// @ts-ignore
|
|
81
|
+
`CREATE UNIQUE INDEX ${indexName} ON ${this.tableName()} (${columns})${predicateQuery}`
|
|
82
|
+
);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
85
|
// All of the columns to "add" for the query
|
|
86
86
|
addColumns(columns, prefix) {
|
|
87
|
+
// @ts-ignore
|
|
87
88
|
prefix = prefix || this.addColumnsPrefix;
|
|
88
89
|
|
|
89
90
|
if (columns.sql.length > 0) {
|
|
90
91
|
const columnSql = columns.sql.map((column) => {
|
|
91
92
|
return prefix + column;
|
|
92
93
|
});
|
|
94
|
+
// @ts-ignore
|
|
93
95
|
this.pushQuery({
|
|
94
96
|
sql:
|
|
97
|
+
// @ts-ignore
|
|
95
98
|
(this.lowerCase ? 'alter table ' : 'ALTER TABLE ') +
|
|
99
|
+
// @ts-ignore
|
|
96
100
|
this.tableName() +
|
|
97
101
|
' ' +
|
|
98
102
|
columnSql.join(' '),
|