@bdkinc/knex-ibmi 0.0.2 → 0.0.3

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/dist/index.mjs CHANGED
@@ -1,103 +1,434 @@
1
- // src/index.ts
2
- import * as process from "process";
3
- import knex from "knex";
4
- import * as odbc from "odbc";
5
- var DB2Client = class extends knex.Client {
6
- constructor(config = {}) {
7
- super(config);
8
- this.driverName = "odbc";
9
- if (this.driverName && config.connection) {
10
- this.initializeDriver();
11
- if (!config.pool || config.pool && config.pool.max !== 0) {
12
- this.initializePool(config);
13
- }
14
- }
15
- }
16
- _driver() {
17
- return odbc;
18
- }
19
- wrapIdentifierImpl(value) {
20
- return value;
21
- }
22
- printDebug(message) {
23
- if (process.env.DEBUG === "true") {
24
- this.logger.debug(message);
25
- }
26
- }
27
- // Get a raw connection, called by the pool manager whenever a new
28
- // connection needs to be added to the pool.
29
- async acquireRawConnection() {
30
- this.printDebug("acquiring raw connection");
31
- const connectionConfig = this.config.connection;
32
- return await this.driver.connect(
33
- this._getConnectionString(connectionConfig)
34
- );
35
- }
36
- // Used to explicitly close a connection, called internally by the pool manager
37
- // when a connection times out or the pool is shutdown.
38
- async destroyRawConnection(connection) {
39
- return await connection.close();
40
- }
41
- _getConnectionString(connectionConfig = {}) {
42
- const connectionStringParams = connectionConfig.connectionStringParams || {};
43
- const connectionStringExtension = Object.keys(
44
- connectionStringParams
45
- ).reduce((result, key) => {
46
- const value = connectionStringParams[key];
47
- return `${result}${key}=${value};`;
48
- }, "");
49
- return `${`DRIVER=${connectionConfig.driver};SYSTEM=${connectionConfig.host};HOSTNAME=${connectionConfig.host};PORT=${connectionConfig.port};DATABASE=${connectionConfig.database};UID=${connectionConfig.user};PWD=${connectionConfig.password};`}${connectionStringExtension}`;
50
- }
51
- // Runs the query on the specified connection, providing the bindings
52
- // and any other necessary prep work.
53
- async _query(connection, obj) {
54
- if (!obj || typeof obj == "string")
55
- obj = { sql: obj };
56
- const method = (obj.method !== "raw" ? obj.method : obj.sql.split(" ")[0]).toLowerCase();
57
- obj.sqlMethod = method;
58
- if (method === "select" || method === "first" || method === "pluck") {
59
- const rows = await connection.query(obj.sql, obj.bindings);
60
- if (rows) {
61
- obj.response = { rows, rowCount: rows.length };
62
- }
63
- return obj;
64
- }
65
- const statement = await connection.createStatement();
66
- await statement.prepare(obj.sql);
67
- await statement.bind(obj.bindings);
68
- obj.response = await statement.execute();
69
- return obj;
70
- }
71
- processResponse(obj, runner) {
72
- if (obj === null)
73
- return null;
74
- const resp = obj.response;
75
- const method = obj.sqlMethod;
76
- const { rows } = resp;
77
- if (obj.output)
78
- return obj.output.call(runner, resp);
79
- switch (method) {
80
- case "select":
81
- case "pluck":
82
- case "first": {
83
- if (method === "pluck")
84
- return rows.map(obj.pluck);
85
- return method === "first" ? rows[0] : rows;
86
- }
87
- case "insert":
88
- case "del":
89
- case "delete":
90
- case "update":
91
- case "counter":
92
- return resp.rowCount;
93
- default:
94
- return resp;
95
- }
96
- }
97
- };
98
- var DB2Dialect = DB2Client;
99
- var src_default = DB2Client;
100
- export {
101
- DB2Dialect,
102
- src_default as default
103
- };
1
+ // src/index.ts
2
+ import * as process from "process";
3
+ import knex from "knex";
4
+ import * as odbc from "odbc";
5
+ import * as console5 from "console";
6
+
7
+ // src/schema/ibmi-compiler.ts
8
+ import SchemaCompiler from "knex/lib/schema/compiler";
9
+ import * as console from "console";
10
+ var IBMiSchemaCompiler = class extends SchemaCompiler {
11
+ constructor(client, builder) {
12
+ super(client, builder);
13
+ }
14
+ hasTable(tableName) {
15
+ const formattedTable = this.client.parameter(
16
+ prefixedTableName(this.schema, tableName),
17
+ this.builder,
18
+ this.bindingsHolder
19
+ );
20
+ const bindings = [tableName.toUpperCase()];
21
+ let sql = `SELECT TABLE_NAME FROM QSYS2.SYSTABLES WHERE TYPE = 'T' AND TABLE_NAME = ${formattedTable}`;
22
+ if (this.schema) {
23
+ sql += " AND TABLE_SCHEMA = ?";
24
+ bindings.push(this.schema);
25
+ }
26
+ this.pushQuery({
27
+ sql,
28
+ bindings,
29
+ output: (resp) => {
30
+ return resp.rowCount > 0;
31
+ }
32
+ });
33
+ }
34
+ toSQL() {
35
+ const sequence = this.builder._sequence;
36
+ for (let i = 0, l = sequence.length; i < l; i++) {
37
+ const query = sequence[i];
38
+ console.log(query.method, query);
39
+ this[query.method].apply(this, query.args);
40
+ }
41
+ return this.sequence;
42
+ }
43
+ };
44
+ function prefixedTableName(prefix, table) {
45
+ return prefix ? `${prefix}.${table}` : table;
46
+ }
47
+ var ibmi_compiler_default = IBMiSchemaCompiler;
48
+
49
+ // src/schema/ibmi-tablecompiler.ts
50
+ import TableCompiler from "knex/lib/schema/tablecompiler";
51
+ 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
+ createQuery(columns, ifNot, like) {
90
+ let createStatement = ifNot ? `if object_id('${this.tableName()}', 'U') is null ` : "";
91
+ if (like) {
92
+ createStatement += `SELECT * INTO ${this.tableName()} FROM ${this.tableNameLike()} WHERE 0=1`;
93
+ } else {
94
+ createStatement += "CREATE TABLE " + this.tableName() + (this._formatting ? " (\n " : " (") + columns.sql.join(this._formatting ? ",\n " : ", ") + this._addChecks() + ")";
95
+ }
96
+ this.pushQuery(createStatement);
97
+ if (this.single.comment) {
98
+ this.comment(this.single.comment);
99
+ }
100
+ if (like) {
101
+ this.addColumns(columns, this.addColumnsPrefix);
102
+ }
103
+ }
104
+ // All of the columns to "add" for the query
105
+ addColumns(columns, prefix) {
106
+ prefix = prefix || this.addColumnsPrefix;
107
+ if (columns.sql.length > 0) {
108
+ const columnSql = columns.sql.map((column) => {
109
+ return prefix + column;
110
+ });
111
+ this.pushQuery({
112
+ sql: (this.lowerCase ? "alter table " : "ALTER TABLE ") + this.tableName() + " " + columnSql.join(" "),
113
+ bindings: columns.bindings
114
+ });
115
+ }
116
+ }
117
+ async commit(conn, value) {
118
+ return await conn.commit();
119
+ }
120
+ };
121
+ var ibmi_tablecompiler_default = IBMiTableCompiler;
122
+
123
+ // src/schema/ibmi-columncompiler.ts
124
+ import ColumnCompiler from "knex/lib/schema/columncompiler";
125
+ import * as console2 from "console";
126
+ var IBMiColumnCompiler = class extends ColumnCompiler {
127
+ constructor(client, tableCompiler, columnBuilder) {
128
+ super(client, tableCompiler, columnBuilder);
129
+ }
130
+ increments(options = { primaryKey: true }) {
131
+ return "int not null generated always as identity (start with 1, increment by 1)" + (this.tableCompiler._canBeAddPrimaryKey(options) ? " primary key" : "");
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}`;
144
+ }
145
+ };
146
+ var ibmi_columncompiler_default = IBMiColumnCompiler;
147
+
148
+ // src/execution/ibmi-transaction.ts
149
+ import Transaction from "knex/lib/execution/transaction";
150
+ import * as console3 from "console";
151
+ var IBMiTransaction = class extends Transaction {
152
+ async begin(conn) {
153
+ const connection = await conn.connect();
154
+ await connection.beginTransaction();
155
+ return connection;
156
+ }
157
+ async rollback(conn) {
158
+ console3.log({ conn });
159
+ const connection = await conn.connect();
160
+ await connection.rollback();
161
+ return connection;
162
+ }
163
+ async commit(conn) {
164
+ await conn.commit();
165
+ return conn;
166
+ }
167
+ };
168
+ var ibmi_transaction_default = IBMiTransaction;
169
+
170
+ // src/query/ibmi-querycompiler.ts
171
+ 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
+ import isObject2 from "lodash/isObject";
176
+ import {
177
+ wrap as wrap_,
178
+ rawOrFn as rawOrFn_
179
+ } from "knex/lib/formatter/wrappingFormatter";
180
+ import { format } from "date-fns";
181
+ import * as console4 from "console";
182
+ var IBMiQueryCompiler = class extends QueryCompiler {
183
+ _prepInsert(data) {
184
+ if (isObject2(data)) {
185
+ console4.log("data is object", data);
186
+ if (data.hasOwnProperty("migration_time")) {
187
+ console4.log("data has migration_time", data.migration_time);
188
+ const parsed = new Date(data.migration_time);
189
+ console4.log(parsed);
190
+ data.migration_time = format(parsed, "yyyy-MM-dd HH:mm:ss");
191
+ console4.log(data.migration_time);
192
+ }
193
+ console4.log("data date after change", data);
194
+ }
195
+ const isRaw = rawOrFn_(
196
+ data,
197
+ void 0,
198
+ this.builder,
199
+ this.client,
200
+ this.bindingsHolder
201
+ );
202
+ if (isRaw)
203
+ return isRaw;
204
+ let columns = [];
205
+ const values = [];
206
+ if (!Array.isArray(data))
207
+ data = data ? [data] : [];
208
+ let i = -1;
209
+ while (++i < data.length) {
210
+ if (data[i] == null)
211
+ break;
212
+ if (i === 0)
213
+ columns = Object.keys(data[i]).sort();
214
+ const row = new Array(columns.length);
215
+ const keys = Object.keys(data[i]);
216
+ let j = -1;
217
+ while (++j < keys.length) {
218
+ const key = keys[j];
219
+ let idx = columns.indexOf(key);
220
+ if (idx === -1) {
221
+ columns = columns.concat(key).sort();
222
+ idx = columns.indexOf(key);
223
+ let k = -1;
224
+ while (++k < values.length) {
225
+ values[k].splice(idx, 0, void 0);
226
+ }
227
+ row.splice(idx, 0, void 0);
228
+ }
229
+ row[idx] = data[i][key];
230
+ }
231
+ values.push(row);
232
+ }
233
+ return {
234
+ columns,
235
+ values
236
+ };
237
+ }
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
+ };
287
+ var ibmi_querycompiler_default = IBMiQueryCompiler;
288
+
289
+ // src/index.ts
290
+ var DB2Client = class extends knex.Client {
291
+ constructor(config) {
292
+ super(config);
293
+ this.driverName = "odbc";
294
+ if (this.dialect && !this.config.client) {
295
+ this.logger.warn(
296
+ `Using 'this.dialect' to identify the client is deprecated and support for it will be removed in the future. Please use configuration option 'client' instead.`
297
+ );
298
+ }
299
+ const dbClient = this.config.client || this.dialect;
300
+ if (!dbClient) {
301
+ throw new Error(
302
+ `knex: Required configuration option 'client' is missing.`
303
+ );
304
+ }
305
+ if (config.version) {
306
+ this.version = config.version;
307
+ }
308
+ if (this.driverName && config.connection) {
309
+ this.initializeDriver();
310
+ if (!config.pool || config.pool && config.pool.max !== 0) {
311
+ this.initializePool(config);
312
+ }
313
+ }
314
+ this.valueForUndefined = this.raw("DEFAULT");
315
+ if (config.useNullAsDefault) {
316
+ this.valueForUndefined = null;
317
+ }
318
+ }
319
+ _driver() {
320
+ return odbc;
321
+ }
322
+ wrapIdentifierImpl(value) {
323
+ if (value.includes("knex_migrations")) {
324
+ return value.toUpperCase();
325
+ }
326
+ return value;
327
+ }
328
+ printDebug(message) {
329
+ if (process.env.DEBUG === "true") {
330
+ this.logger.debug(message);
331
+ }
332
+ }
333
+ // Get a raw connection, called by the pool manager whenever a new
334
+ // connection needs to be added to the pool.
335
+ async acquireRawConnection() {
336
+ this.printDebug("acquiring raw connection");
337
+ const connectionConfig = this.config.connection;
338
+ console5.log(this._getConnectionString(connectionConfig));
339
+ return await this.driver.pool(this._getConnectionString(connectionConfig));
340
+ }
341
+ // Used to explicitly close a connection, called internally by the pool manager
342
+ // when a connection times out or the pool is shutdown.
343
+ async destroyRawConnection(connection) {
344
+ console5.log("destroy connection");
345
+ return await connection.close();
346
+ }
347
+ _getConnectionString(connectionConfig) {
348
+ const connectionStringParams = connectionConfig.connectionStringParams || {};
349
+ const connectionStringExtension = Object.keys(
350
+ connectionStringParams
351
+ ).reduce((result, key) => {
352
+ const value = connectionStringParams[key];
353
+ return `${result}${key}=${value};`;
354
+ }, "");
355
+ return `${`DRIVER=${connectionConfig.driver};SYSTEM=${connectionConfig.host};HOSTNAME=${connectionConfig.host};PORT=${connectionConfig.port};DATABASE=${connectionConfig.database};UID=${connectionConfig.user};PWD=${connectionConfig.password};`}${connectionStringExtension}`;
356
+ }
357
+ // Runs the query on the specified connection, providing the bindings
358
+ // and any other necessary prep work.
359
+ async _query(pool, obj) {
360
+ if (!obj || typeof obj == "string")
361
+ obj = { sql: obj };
362
+ const method = (obj.hasOwnProperty("method") && obj.method !== "raw" ? obj.method : obj.sql.split(" ")[0]).toLowerCase();
363
+ obj.sqlMethod = method;
364
+ if (method === "select" || method === "first" || method === "pluck") {
365
+ const rows = await pool.query(obj.sql, obj.bindings);
366
+ if (rows) {
367
+ obj.response = { rows, rowCount: rows.length };
368
+ }
369
+ } else {
370
+ try {
371
+ const connection = await pool.connect();
372
+ const statement = await connection.createStatement();
373
+ await statement.prepare(obj.sql);
374
+ if (obj.bindings) {
375
+ await statement.bind(obj.bindings);
376
+ }
377
+ const result = await statement.execute();
378
+ obj.response = { rows: [result.count], rowCount: result.count };
379
+ } catch (err) {
380
+ console5.error(err);
381
+ throw new Error(err);
382
+ }
383
+ }
384
+ console5.log({ obj });
385
+ return obj;
386
+ }
387
+ transaction() {
388
+ return new ibmi_transaction_default(this, ...arguments);
389
+ }
390
+ schemaCompiler() {
391
+ return new ibmi_compiler_default(this, ...arguments);
392
+ }
393
+ tableCompiler() {
394
+ return new ibmi_tablecompiler_default(this, ...arguments);
395
+ }
396
+ columnCompiler() {
397
+ return new ibmi_columncompiler_default(this, ...arguments);
398
+ }
399
+ queryCompiler() {
400
+ return new ibmi_querycompiler_default(this, ...arguments);
401
+ }
402
+ processResponse(obj, runner) {
403
+ if (obj === null)
404
+ return null;
405
+ const resp = obj.response;
406
+ const method = obj.sqlMethod;
407
+ const { rows } = resp;
408
+ if (obj.output)
409
+ return obj.output.call(runner, resp);
410
+ switch (method) {
411
+ case "select":
412
+ case "pluck":
413
+ case "first": {
414
+ if (method === "pluck")
415
+ return rows.map(obj.pluck);
416
+ return method === "first" ? rows[0] : rows;
417
+ }
418
+ case "insert":
419
+ case "del":
420
+ case "delete":
421
+ case "update":
422
+ case "counter":
423
+ return resp.rowCount;
424
+ default:
425
+ return resp;
426
+ }
427
+ }
428
+ };
429
+ var DB2Dialect = DB2Client;
430
+ var src_default = DB2Client;
431
+ export {
432
+ DB2Dialect,
433
+ src_default as default
434
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bdkinc/knex-ibmi",
3
- "version": "0.0.2",
3
+ "version": "0.0.3",
4
4
  "description": "Knex dialect for IBMi",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",
@@ -58,7 +58,9 @@
58
58
  "LICENSE"
59
59
  ],
60
60
  "dependencies": {
61
+ "date-fns": "^2.30.0",
61
62
  "knex": "^2",
63
+ "lodash": "^4.17.21",
62
64
  "odbc": "^2.4.8"
63
65
  }
64
66
  }
@@ -0,0 +1,25 @@
1
+ import Transaction from "knex/lib/execution/transaction";
2
+ import * as console from "console";
3
+ import { connect } from "odbc";
4
+
5
+ class IBMiTransaction extends Transaction {
6
+ async begin(conn) {
7
+ const connection = await conn.connect();
8
+ await connection.beginTransaction();
9
+ return connection;
10
+ }
11
+
12
+ async rollback(conn) {
13
+ console.log({ conn });
14
+ const connection = await conn.connect();
15
+ await connection.rollback();
16
+ return connection;
17
+ }
18
+
19
+ async commit(conn) {
20
+ await conn.commit();
21
+ return conn;
22
+ }
23
+ }
24
+
25
+ export default IBMiTransaction;