@oino-ts/db-mssql 0.7.2 → 0.8.0
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/cjs/OINODbMsSql.js +23 -58
- package/dist/esm/OINODbMsSql.js +23 -58
- package/package.json +2 -2
- package/src/OINODbMsSql.ts +23 -57
package/dist/cjs/OINODbMsSql.js
CHANGED
|
@@ -34,7 +34,6 @@ class OINOMsSqlData extends db_1.OINODbDataSet {
|
|
|
34
34
|
this._recordsets = data;
|
|
35
35
|
this._rows = this._recordsets[0];
|
|
36
36
|
}
|
|
37
|
-
// OINOLog.debug("OINOMsSqlData.constructor", {_rows:this._rows})
|
|
38
37
|
if (this.isEmpty()) {
|
|
39
38
|
this._currentRecordset = -1;
|
|
40
39
|
this._currentRow = -1;
|
|
@@ -65,7 +64,6 @@ class OINOMsSqlData extends db_1.OINODbDataSet {
|
|
|
65
64
|
*
|
|
66
65
|
*/
|
|
67
66
|
async next() {
|
|
68
|
-
// OINOLog.debug("OINODbDataSet.next", {currentRow:this._currentRow, length:this.sqlResult.data.length})
|
|
69
67
|
if (this._currentRow < this._rows.length - 1) {
|
|
70
68
|
this._currentRow = this._currentRow + 1;
|
|
71
69
|
}
|
|
@@ -111,7 +109,6 @@ class OINODbMsSql extends db_1.OINODb {
|
|
|
111
109
|
*/
|
|
112
110
|
constructor(params) {
|
|
113
111
|
super(params);
|
|
114
|
-
// OINOLog.debug("OINODbMsSql.constructor", {params:params})
|
|
115
112
|
if (this._params.type !== "OINODbMsSql") {
|
|
116
113
|
throw new Error(db_1.OINO_ERROR_PREFIX + ": Not OINODbMsSql-type: " + this._params.type);
|
|
117
114
|
}
|
|
@@ -131,44 +128,18 @@ class OINODbMsSql extends db_1.OINODb {
|
|
|
131
128
|
});
|
|
132
129
|
delete this._params.password; // do not store password in db object
|
|
133
130
|
this._pool.on("error", (conn) => {
|
|
134
|
-
db_1.OINOLog.error("OINODbMsSql error event", conn);
|
|
131
|
+
db_1.OINOLog.error("@oinots/db", "OINODbMsSql", "constructor", "OINODbMsSql error event", conn);
|
|
135
132
|
});
|
|
136
|
-
// this._pool.on("debug", (event:any) => {
|
|
137
|
-
// console.log("OINODbMsSql debug",event)
|
|
138
|
-
// })
|
|
139
133
|
}
|
|
140
134
|
async _query(sql) {
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
// console.log("OINODbMsSql._query result:" + JSON.stringify(sql_res.recordsets))
|
|
146
|
-
const result = new OINOMsSqlData(sql_res.recordsets);
|
|
147
|
-
return Promise.resolve(result);
|
|
148
|
-
}
|
|
149
|
-
catch (err) {
|
|
150
|
-
db_1.OINOLog.error("OINODbMsSql._query exception", { err: err });
|
|
151
|
-
throw err;
|
|
152
|
-
}
|
|
153
|
-
finally {
|
|
154
|
-
// console.log("OINODbMsSql._query finally");
|
|
155
|
-
}
|
|
156
|
-
// OINOLog.debug("OINODbMsSql._query", {result:query_result})
|
|
135
|
+
const request = this._pool.request(); // this does not need to be released but the pool will handle it
|
|
136
|
+
const sql_res = await request.query(sql);
|
|
137
|
+
const result = new OINOMsSqlData(sql_res.recordsets);
|
|
138
|
+
return result;
|
|
157
139
|
}
|
|
158
140
|
async _exec(sql) {
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
const sql_res = await this._pool.request().query(sql);
|
|
162
|
-
// console.log("OINODbMsSql._exec result", sql_res);
|
|
163
|
-
return Promise.resolve(new OINOMsSqlData(db_1.OINODB_EMPTY_ROWS));
|
|
164
|
-
}
|
|
165
|
-
catch (err) {
|
|
166
|
-
db_1.OINOLog.error("OINODbMsSql._exec exception", { err: err });
|
|
167
|
-
throw err;
|
|
168
|
-
}
|
|
169
|
-
finally {
|
|
170
|
-
}
|
|
171
|
-
// OINOLog.debug("OINODbMsSql._exec", {result:query_result})
|
|
141
|
+
const sql_res = await this._pool.request().query(sql);
|
|
142
|
+
return new OINOMsSqlData(db_1.OINODB_EMPTY_ROWS);
|
|
172
143
|
}
|
|
173
144
|
/**
|
|
174
145
|
* Print a table name using database specific SQL escaping.
|
|
@@ -197,7 +168,6 @@ class OINODbMsSql extends db_1.OINODb {
|
|
|
197
168
|
*
|
|
198
169
|
*/
|
|
199
170
|
printCellAsSqlValue(cellValue, sqlType) {
|
|
200
|
-
// OINOLog.debug("OINODbMsSql.printCellAsSqlValue", {cellValue:cellValue, sqlType:sqlType})
|
|
201
171
|
if (cellValue === null) {
|
|
202
172
|
return "NULL";
|
|
203
173
|
}
|
|
@@ -243,7 +213,6 @@ class OINODbMsSql extends db_1.OINODb {
|
|
|
243
213
|
*
|
|
244
214
|
*/
|
|
245
215
|
parseSqlValueAsCell(sqlValue, sqlType) {
|
|
246
|
-
// OINOLog.debug("OINODbMsSql.parseSqlValueAsCell", {sqlValue:sqlValue, sqlType:sqlType})
|
|
247
216
|
if ((sqlValue === null) || (sqlValue == "NULL")) {
|
|
248
217
|
return null;
|
|
249
218
|
}
|
|
@@ -275,7 +244,6 @@ class OINODbMsSql extends db_1.OINODb {
|
|
|
275
244
|
result += "TOP " + limit_parts[0] + " ";
|
|
276
245
|
}
|
|
277
246
|
result += columnNames + " FROM " + tableName;
|
|
278
|
-
// OINOLog.debug("OINODb.printSqlSelect", {tableName:tableName, columnNames:columnNames, whereCondition:whereCondition, orderCondition:orderCondition, limitCondition:limitCondition })
|
|
279
247
|
if (whereCondition != "") {
|
|
280
248
|
result += " WHERE " + whereCondition;
|
|
281
249
|
}
|
|
@@ -287,14 +255,15 @@ class OINODbMsSql extends db_1.OINODb {
|
|
|
287
255
|
}
|
|
288
256
|
if ((limitCondition != "") && (limit_parts.length == 2)) {
|
|
289
257
|
if (orderCondition == "") {
|
|
290
|
-
db_1.OINOLog.error("OINODbMsSql
|
|
258
|
+
db_1.OINOLog.error("@oinots/db", "OINODbMsSql", "printSqlSelect", "LIMIT without ORDER BY is not supported in MS SQL Server");
|
|
259
|
+
throw new Error(db_1.OINO_ERROR_PREFIX + "LIMIT without ORDER BY is not supported in MS SQL Server");
|
|
291
260
|
}
|
|
292
261
|
else {
|
|
293
262
|
result += " OFFSET " + limit_parts[1] + " ROWS FETCH NEXT " + limit_parts[0] + " ROWS ONLY";
|
|
294
263
|
}
|
|
295
264
|
}
|
|
296
265
|
result += ";";
|
|
297
|
-
|
|
266
|
+
db_1.OINOLog.debug("@oinots/db", "OINODbMsSql", "printSqlSelect", "Result", { sql: result });
|
|
298
267
|
return result;
|
|
299
268
|
}
|
|
300
269
|
/**
|
|
@@ -306,14 +275,12 @@ class OINODbMsSql extends db_1.OINODb {
|
|
|
306
275
|
try {
|
|
307
276
|
// make sure that any items are correctly URL encoded in the connection string
|
|
308
277
|
await this._pool.connect();
|
|
309
|
-
// OINOLog.info("OINODbMsSql.connect: Connected to database server.")
|
|
310
|
-
// await this._pool.request().query("SELECT 1 as test")
|
|
311
278
|
this.isConnected = true;
|
|
312
279
|
}
|
|
313
|
-
catch (
|
|
280
|
+
catch (e) {
|
|
314
281
|
// ... error checks
|
|
315
|
-
result.setError(500, "Exception connecting to database: " +
|
|
316
|
-
db_1.OINOLog.
|
|
282
|
+
result.setError(500, "Exception connecting to database: " + e.message, "OINODbMsSql.connect");
|
|
283
|
+
db_1.OINOLog.exception("@oinots/db", "OINODbMsSql", "connect", "Exception", { message: e.message, stack: e.stack });
|
|
317
284
|
}
|
|
318
285
|
return Promise.resolve(result);
|
|
319
286
|
}
|
|
@@ -330,9 +297,7 @@ class OINODbMsSql extends db_1.OINODb {
|
|
|
330
297
|
db_1.OINOBenchmark.start("OINODb", "validate");
|
|
331
298
|
try {
|
|
332
299
|
const sql = this._getValidateSql(this._params.database);
|
|
333
|
-
// OINOLog.debug("OINODbMsSql.validate", {sql:sql})
|
|
334
300
|
const sql_res = await this.sqlSelect(sql);
|
|
335
|
-
// OINOLog.debug("OINODbMsSql.validate", {sql_res:sql_res})
|
|
336
301
|
if (sql_res.isEmpty()) {
|
|
337
302
|
result.setError(400, "DB returned no rows for select!", "OINODbMsSql.validate");
|
|
338
303
|
}
|
|
@@ -349,6 +314,7 @@ class OINODbMsSql extends db_1.OINODb {
|
|
|
349
314
|
}
|
|
350
315
|
catch (e) {
|
|
351
316
|
result.setError(500, "Exception in validating connection: " + e.message, "OINODbMsSql.validate");
|
|
317
|
+
db_1.OINOLog.exception("@oinots/db", "OINODbMsSql", "validate", "Exception", { message: e.message, stack: e.stack });
|
|
352
318
|
}
|
|
353
319
|
db_1.OINOBenchmark.end("OINODb", "validate");
|
|
354
320
|
return result;
|
|
@@ -363,10 +329,10 @@ class OINODbMsSql extends db_1.OINODb {
|
|
|
363
329
|
db_1.OINOBenchmark.start("OINODb", "sqlSelect");
|
|
364
330
|
let result;
|
|
365
331
|
try {
|
|
366
|
-
// OINOLog.debug("OINODbMsSql.sqlSelect", {sql:sql})
|
|
367
332
|
result = await this._query(sql);
|
|
368
333
|
}
|
|
369
334
|
catch (e) {
|
|
335
|
+
db_1.OINOLog.exception("@oinots/db", "OINODbMsSql", "sqlSelect", "SQL select exception", { message: e.message, stack: e.stack });
|
|
370
336
|
result = new OINOMsSqlData(db_1.OINODB_EMPTY_ROWS, [db_1.OINO_ERROR_PREFIX + " (sqlSelect): OINODbMsSql.sqlSelect exception in _db.query: " + e.message]);
|
|
371
337
|
}
|
|
372
338
|
db_1.OINOBenchmark.end("OINODb", "sqlSelect");
|
|
@@ -385,6 +351,7 @@ class OINODbMsSql extends db_1.OINODb {
|
|
|
385
351
|
result = await this._exec(sql);
|
|
386
352
|
}
|
|
387
353
|
catch (e) {
|
|
354
|
+
db_1.OINOLog.exception("@oinots/db", "OINODbMsSql", "sqlExec", "SQL exec exception", { message: e.message, stack: e.stack });
|
|
388
355
|
result = new OINOMsSqlData(db_1.OINODB_EMPTY_ROWS, [db_1.OINO_ERROR_PREFIX + " (sqlExec): exception in _db.exec [" + e.message + "]"]);
|
|
389
356
|
}
|
|
390
357
|
db_1.OINOBenchmark.end("OINODb", "sqlExec");
|
|
@@ -438,10 +405,9 @@ WHERE C.TABLE_CATALOG = '${dbName}';`;
|
|
|
438
405
|
*/
|
|
439
406
|
async initializeApiDatamodel(api) {
|
|
440
407
|
//"SELECT COLUMN_NAME, IS_NULLABLE, DATA_TYPE, CHARACTER_MAXIMUM_LENGTH, NUMERIC_PRECISION, NUMERIC_PRECISION_RADIX
|
|
441
|
-
const
|
|
442
|
-
while (!
|
|
443
|
-
const row =
|
|
444
|
-
// OINOLog.debug("OINODbMsSql.initializeApiDatamodel", { description:row })
|
|
408
|
+
const schema_res = await this.sqlSelect(this._getSchemaSql(this._params.database, api.params.tableName));
|
|
409
|
+
while (!schema_res.isEof()) {
|
|
410
|
+
const row = schema_res.getRow();
|
|
445
411
|
const field_name = row[0]?.toString() || "";
|
|
446
412
|
const sql_type = row[2] || "";
|
|
447
413
|
const char_field_length = row[3] || 0;
|
|
@@ -455,13 +421,12 @@ WHERE C.TABLE_CATALOG = '${dbName}';`;
|
|
|
455
421
|
isNotNull: row[1] == "NO"
|
|
456
422
|
};
|
|
457
423
|
if (api.isFieldIncluded(field_name) == false) {
|
|
458
|
-
db_1.OINOLog.info("OINODbMsSql
|
|
424
|
+
db_1.OINOLog.info("@oinots/db", "OINODbMsSql", "initializeApiDatamodel", "Field excluded in API parameters.", { field: field_name });
|
|
459
425
|
if (field_params.isPrimaryKey) {
|
|
460
426
|
throw new Error(db_1.OINO_ERROR_PREFIX + "Primary key field excluded in API parameters: " + field_name);
|
|
461
427
|
}
|
|
462
428
|
}
|
|
463
429
|
else {
|
|
464
|
-
// OINOLog.debug("OINODbMsSql.initializeApiDatamodel: next field ", {field_name: field_name, sql_type:sql_type, char_field_length:char_field_length, numeric_field_length1:numeric_field_length1, numeric_field_length2:numeric_field_length2, field_params:field_params })
|
|
465
430
|
if ((sql_type == "tinyint") || (sql_type == "smallint") || (sql_type == "int") || (sql_type == "bigint") || (sql_type == "float") || (sql_type == "real")) {
|
|
466
431
|
api.datamodel.addField(new db_1.OINONumberDataField(this, field_name, sql_type, field_params));
|
|
467
432
|
}
|
|
@@ -486,13 +451,13 @@ WHERE C.TABLE_CATALOG = '${dbName}';`;
|
|
|
486
451
|
api.datamodel.addField(new db_1.OINOBooleanDataField(this, field_name, sql_type, field_params));
|
|
487
452
|
}
|
|
488
453
|
else {
|
|
489
|
-
db_1.OINOLog.info("OINODbMsSql
|
|
454
|
+
db_1.OINOLog.info("@oinots/db", "OINODbMsSql", "initializeApiDatamodel", "Unrecognized field type treated as string", { field_name: field_name, sql_type: sql_type, char_length: char_field_length, numeric_field_length1: numeric_field_length1, numeric_field_length2: numeric_field_length2, field_params: field_params });
|
|
490
455
|
api.datamodel.addField(new db_1.OINOStringDataField(this, field_name, sql_type, field_params, 0));
|
|
491
456
|
}
|
|
492
457
|
}
|
|
493
|
-
await
|
|
458
|
+
await schema_res.next();
|
|
494
459
|
}
|
|
495
|
-
db_1.OINOLog.
|
|
460
|
+
db_1.OINOLog.info("@oinots/db", "OINODbMsSql", "initializeApiDatamodel", "\n" + api.datamodel.printDebug("\n"));
|
|
496
461
|
return Promise.resolve();
|
|
497
462
|
}
|
|
498
463
|
}
|
package/dist/esm/OINODbMsSql.js
CHANGED
|
@@ -31,7 +31,6 @@ class OINOMsSqlData extends OINODbDataSet {
|
|
|
31
31
|
this._recordsets = data;
|
|
32
32
|
this._rows = this._recordsets[0];
|
|
33
33
|
}
|
|
34
|
-
// OINOLog.debug("OINOMsSqlData.constructor", {_rows:this._rows})
|
|
35
34
|
if (this.isEmpty()) {
|
|
36
35
|
this._currentRecordset = -1;
|
|
37
36
|
this._currentRow = -1;
|
|
@@ -62,7 +61,6 @@ class OINOMsSqlData extends OINODbDataSet {
|
|
|
62
61
|
*
|
|
63
62
|
*/
|
|
64
63
|
async next() {
|
|
65
|
-
// OINOLog.debug("OINODbDataSet.next", {currentRow:this._currentRow, length:this.sqlResult.data.length})
|
|
66
64
|
if (this._currentRow < this._rows.length - 1) {
|
|
67
65
|
this._currentRow = this._currentRow + 1;
|
|
68
66
|
}
|
|
@@ -108,7 +106,6 @@ export class OINODbMsSql extends OINODb {
|
|
|
108
106
|
*/
|
|
109
107
|
constructor(params) {
|
|
110
108
|
super(params);
|
|
111
|
-
// OINOLog.debug("OINODbMsSql.constructor", {params:params})
|
|
112
109
|
if (this._params.type !== "OINODbMsSql") {
|
|
113
110
|
throw new Error(OINO_ERROR_PREFIX + ": Not OINODbMsSql-type: " + this._params.type);
|
|
114
111
|
}
|
|
@@ -128,44 +125,18 @@ export class OINODbMsSql extends OINODb {
|
|
|
128
125
|
});
|
|
129
126
|
delete this._params.password; // do not store password in db object
|
|
130
127
|
this._pool.on("error", (conn) => {
|
|
131
|
-
OINOLog.error("OINODbMsSql error event", conn);
|
|
128
|
+
OINOLog.error("@oinots/db", "OINODbMsSql", "constructor", "OINODbMsSql error event", conn);
|
|
132
129
|
});
|
|
133
|
-
// this._pool.on("debug", (event:any) => {
|
|
134
|
-
// console.log("OINODbMsSql debug",event)
|
|
135
|
-
// })
|
|
136
130
|
}
|
|
137
131
|
async _query(sql) {
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
// console.log("OINODbMsSql._query result:" + JSON.stringify(sql_res.recordsets))
|
|
143
|
-
const result = new OINOMsSqlData(sql_res.recordsets);
|
|
144
|
-
return Promise.resolve(result);
|
|
145
|
-
}
|
|
146
|
-
catch (err) {
|
|
147
|
-
OINOLog.error("OINODbMsSql._query exception", { err: err });
|
|
148
|
-
throw err;
|
|
149
|
-
}
|
|
150
|
-
finally {
|
|
151
|
-
// console.log("OINODbMsSql._query finally");
|
|
152
|
-
}
|
|
153
|
-
// OINOLog.debug("OINODbMsSql._query", {result:query_result})
|
|
132
|
+
const request = this._pool.request(); // this does not need to be released but the pool will handle it
|
|
133
|
+
const sql_res = await request.query(sql);
|
|
134
|
+
const result = new OINOMsSqlData(sql_res.recordsets);
|
|
135
|
+
return result;
|
|
154
136
|
}
|
|
155
137
|
async _exec(sql) {
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
const sql_res = await this._pool.request().query(sql);
|
|
159
|
-
// console.log("OINODbMsSql._exec result", sql_res);
|
|
160
|
-
return Promise.resolve(new OINOMsSqlData(OINODB_EMPTY_ROWS));
|
|
161
|
-
}
|
|
162
|
-
catch (err) {
|
|
163
|
-
OINOLog.error("OINODbMsSql._exec exception", { err: err });
|
|
164
|
-
throw err;
|
|
165
|
-
}
|
|
166
|
-
finally {
|
|
167
|
-
}
|
|
168
|
-
// OINOLog.debug("OINODbMsSql._exec", {result:query_result})
|
|
138
|
+
const sql_res = await this._pool.request().query(sql);
|
|
139
|
+
return new OINOMsSqlData(OINODB_EMPTY_ROWS);
|
|
169
140
|
}
|
|
170
141
|
/**
|
|
171
142
|
* Print a table name using database specific SQL escaping.
|
|
@@ -194,7 +165,6 @@ export class OINODbMsSql extends OINODb {
|
|
|
194
165
|
*
|
|
195
166
|
*/
|
|
196
167
|
printCellAsSqlValue(cellValue, sqlType) {
|
|
197
|
-
// OINOLog.debug("OINODbMsSql.printCellAsSqlValue", {cellValue:cellValue, sqlType:sqlType})
|
|
198
168
|
if (cellValue === null) {
|
|
199
169
|
return "NULL";
|
|
200
170
|
}
|
|
@@ -240,7 +210,6 @@ export class OINODbMsSql extends OINODb {
|
|
|
240
210
|
*
|
|
241
211
|
*/
|
|
242
212
|
parseSqlValueAsCell(sqlValue, sqlType) {
|
|
243
|
-
// OINOLog.debug("OINODbMsSql.parseSqlValueAsCell", {sqlValue:sqlValue, sqlType:sqlType})
|
|
244
213
|
if ((sqlValue === null) || (sqlValue == "NULL")) {
|
|
245
214
|
return null;
|
|
246
215
|
}
|
|
@@ -272,7 +241,6 @@ export class OINODbMsSql extends OINODb {
|
|
|
272
241
|
result += "TOP " + limit_parts[0] + " ";
|
|
273
242
|
}
|
|
274
243
|
result += columnNames + " FROM " + tableName;
|
|
275
|
-
// OINOLog.debug("OINODb.printSqlSelect", {tableName:tableName, columnNames:columnNames, whereCondition:whereCondition, orderCondition:orderCondition, limitCondition:limitCondition })
|
|
276
244
|
if (whereCondition != "") {
|
|
277
245
|
result += " WHERE " + whereCondition;
|
|
278
246
|
}
|
|
@@ -284,14 +252,15 @@ export class OINODbMsSql extends OINODb {
|
|
|
284
252
|
}
|
|
285
253
|
if ((limitCondition != "") && (limit_parts.length == 2)) {
|
|
286
254
|
if (orderCondition == "") {
|
|
287
|
-
OINOLog.error("OINODbMsSql
|
|
255
|
+
OINOLog.error("@oinots/db", "OINODbMsSql", "printSqlSelect", "LIMIT without ORDER BY is not supported in MS SQL Server");
|
|
256
|
+
throw new Error(OINO_ERROR_PREFIX + "LIMIT without ORDER BY is not supported in MS SQL Server");
|
|
288
257
|
}
|
|
289
258
|
else {
|
|
290
259
|
result += " OFFSET " + limit_parts[1] + " ROWS FETCH NEXT " + limit_parts[0] + " ROWS ONLY";
|
|
291
260
|
}
|
|
292
261
|
}
|
|
293
262
|
result += ";";
|
|
294
|
-
|
|
263
|
+
OINOLog.debug("@oinots/db", "OINODbMsSql", "printSqlSelect", "Result", { sql: result });
|
|
295
264
|
return result;
|
|
296
265
|
}
|
|
297
266
|
/**
|
|
@@ -303,14 +272,12 @@ export class OINODbMsSql extends OINODb {
|
|
|
303
272
|
try {
|
|
304
273
|
// make sure that any items are correctly URL encoded in the connection string
|
|
305
274
|
await this._pool.connect();
|
|
306
|
-
// OINOLog.info("OINODbMsSql.connect: Connected to database server.")
|
|
307
|
-
// await this._pool.request().query("SELECT 1 as test")
|
|
308
275
|
this.isConnected = true;
|
|
309
276
|
}
|
|
310
|
-
catch (
|
|
277
|
+
catch (e) {
|
|
311
278
|
// ... error checks
|
|
312
|
-
result.setError(500, "Exception connecting to database: " +
|
|
313
|
-
OINOLog.
|
|
279
|
+
result.setError(500, "Exception connecting to database: " + e.message, "OINODbMsSql.connect");
|
|
280
|
+
OINOLog.exception("@oinots/db", "OINODbMsSql", "connect", "Exception", { message: e.message, stack: e.stack });
|
|
314
281
|
}
|
|
315
282
|
return Promise.resolve(result);
|
|
316
283
|
}
|
|
@@ -327,9 +294,7 @@ export class OINODbMsSql extends OINODb {
|
|
|
327
294
|
OINOBenchmark.start("OINODb", "validate");
|
|
328
295
|
try {
|
|
329
296
|
const sql = this._getValidateSql(this._params.database);
|
|
330
|
-
// OINOLog.debug("OINODbMsSql.validate", {sql:sql})
|
|
331
297
|
const sql_res = await this.sqlSelect(sql);
|
|
332
|
-
// OINOLog.debug("OINODbMsSql.validate", {sql_res:sql_res})
|
|
333
298
|
if (sql_res.isEmpty()) {
|
|
334
299
|
result.setError(400, "DB returned no rows for select!", "OINODbMsSql.validate");
|
|
335
300
|
}
|
|
@@ -346,6 +311,7 @@ export class OINODbMsSql extends OINODb {
|
|
|
346
311
|
}
|
|
347
312
|
catch (e) {
|
|
348
313
|
result.setError(500, "Exception in validating connection: " + e.message, "OINODbMsSql.validate");
|
|
314
|
+
OINOLog.exception("@oinots/db", "OINODbMsSql", "validate", "Exception", { message: e.message, stack: e.stack });
|
|
349
315
|
}
|
|
350
316
|
OINOBenchmark.end("OINODb", "validate");
|
|
351
317
|
return result;
|
|
@@ -360,10 +326,10 @@ export class OINODbMsSql extends OINODb {
|
|
|
360
326
|
OINOBenchmark.start("OINODb", "sqlSelect");
|
|
361
327
|
let result;
|
|
362
328
|
try {
|
|
363
|
-
// OINOLog.debug("OINODbMsSql.sqlSelect", {sql:sql})
|
|
364
329
|
result = await this._query(sql);
|
|
365
330
|
}
|
|
366
331
|
catch (e) {
|
|
332
|
+
OINOLog.exception("@oinots/db", "OINODbMsSql", "sqlSelect", "SQL select exception", { message: e.message, stack: e.stack });
|
|
367
333
|
result = new OINOMsSqlData(OINODB_EMPTY_ROWS, [OINO_ERROR_PREFIX + " (sqlSelect): OINODbMsSql.sqlSelect exception in _db.query: " + e.message]);
|
|
368
334
|
}
|
|
369
335
|
OINOBenchmark.end("OINODb", "sqlSelect");
|
|
@@ -382,6 +348,7 @@ export class OINODbMsSql extends OINODb {
|
|
|
382
348
|
result = await this._exec(sql);
|
|
383
349
|
}
|
|
384
350
|
catch (e) {
|
|
351
|
+
OINOLog.exception("@oinots/db", "OINODbMsSql", "sqlExec", "SQL exec exception", { message: e.message, stack: e.stack });
|
|
385
352
|
result = new OINOMsSqlData(OINODB_EMPTY_ROWS, [OINO_ERROR_PREFIX + " (sqlExec): exception in _db.exec [" + e.message + "]"]);
|
|
386
353
|
}
|
|
387
354
|
OINOBenchmark.end("OINODb", "sqlExec");
|
|
@@ -435,10 +402,9 @@ WHERE C.TABLE_CATALOG = '${dbName}';`;
|
|
|
435
402
|
*/
|
|
436
403
|
async initializeApiDatamodel(api) {
|
|
437
404
|
//"SELECT COLUMN_NAME, IS_NULLABLE, DATA_TYPE, CHARACTER_MAXIMUM_LENGTH, NUMERIC_PRECISION, NUMERIC_PRECISION_RADIX
|
|
438
|
-
const
|
|
439
|
-
while (!
|
|
440
|
-
const row =
|
|
441
|
-
// OINOLog.debug("OINODbMsSql.initializeApiDatamodel", { description:row })
|
|
405
|
+
const schema_res = await this.sqlSelect(this._getSchemaSql(this._params.database, api.params.tableName));
|
|
406
|
+
while (!schema_res.isEof()) {
|
|
407
|
+
const row = schema_res.getRow();
|
|
442
408
|
const field_name = row[0]?.toString() || "";
|
|
443
409
|
const sql_type = row[2] || "";
|
|
444
410
|
const char_field_length = row[3] || 0;
|
|
@@ -452,13 +418,12 @@ WHERE C.TABLE_CATALOG = '${dbName}';`;
|
|
|
452
418
|
isNotNull: row[1] == "NO"
|
|
453
419
|
};
|
|
454
420
|
if (api.isFieldIncluded(field_name) == false) {
|
|
455
|
-
OINOLog.info("OINODbMsSql
|
|
421
|
+
OINOLog.info("@oinots/db", "OINODbMsSql", "initializeApiDatamodel", "Field excluded in API parameters.", { field: field_name });
|
|
456
422
|
if (field_params.isPrimaryKey) {
|
|
457
423
|
throw new Error(OINO_ERROR_PREFIX + "Primary key field excluded in API parameters: " + field_name);
|
|
458
424
|
}
|
|
459
425
|
}
|
|
460
426
|
else {
|
|
461
|
-
// OINOLog.debug("OINODbMsSql.initializeApiDatamodel: next field ", {field_name: field_name, sql_type:sql_type, char_field_length:char_field_length, numeric_field_length1:numeric_field_length1, numeric_field_length2:numeric_field_length2, field_params:field_params })
|
|
462
427
|
if ((sql_type == "tinyint") || (sql_type == "smallint") || (sql_type == "int") || (sql_type == "bigint") || (sql_type == "float") || (sql_type == "real")) {
|
|
463
428
|
api.datamodel.addField(new OINONumberDataField(this, field_name, sql_type, field_params));
|
|
464
429
|
}
|
|
@@ -483,13 +448,13 @@ WHERE C.TABLE_CATALOG = '${dbName}';`;
|
|
|
483
448
|
api.datamodel.addField(new OINOBooleanDataField(this, field_name, sql_type, field_params));
|
|
484
449
|
}
|
|
485
450
|
else {
|
|
486
|
-
OINOLog.info("OINODbMsSql
|
|
451
|
+
OINOLog.info("@oinots/db", "OINODbMsSql", "initializeApiDatamodel", "Unrecognized field type treated as string", { field_name: field_name, sql_type: sql_type, char_length: char_field_length, numeric_field_length1: numeric_field_length1, numeric_field_length2: numeric_field_length2, field_params: field_params });
|
|
487
452
|
api.datamodel.addField(new OINOStringDataField(this, field_name, sql_type, field_params, 0));
|
|
488
453
|
}
|
|
489
454
|
}
|
|
490
|
-
await
|
|
455
|
+
await schema_res.next();
|
|
491
456
|
}
|
|
492
|
-
OINOLog.
|
|
457
|
+
OINOLog.info("@oinots/db", "OINODbMsSql", "initializeApiDatamodel", "\n" + api.datamodel.printDebug("\n"));
|
|
493
458
|
return Promise.resolve();
|
|
494
459
|
}
|
|
495
460
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@oino-ts/db-mssql",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.8.0",
|
|
4
4
|
"description": "OINO TS package for using Microsoft Sql databases.",
|
|
5
5
|
"author": "Matias Kiviniemi (pragmatta)",
|
|
6
6
|
"license": "MPL-2.0",
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
"module": "./dist/esm/index.js",
|
|
23
23
|
"types": "./dist/types/index.d.ts",
|
|
24
24
|
"dependencies": {
|
|
25
|
-
"@oino-ts/db": "0.
|
|
25
|
+
"@oino-ts/db": "0.8.0",
|
|
26
26
|
"mssql": "^11.0.1"
|
|
27
27
|
},
|
|
28
28
|
"devDependencies": {
|
package/src/OINODbMsSql.ts
CHANGED
|
@@ -36,7 +36,6 @@ class OINOMsSqlData extends OINODbDataSet {
|
|
|
36
36
|
this._recordsets = data as OINODataRow[][]
|
|
37
37
|
this._rows = this._recordsets[0]
|
|
38
38
|
}
|
|
39
|
-
// OINOLog.debug("OINOMsSqlData.constructor", {_rows:this._rows})
|
|
40
39
|
if (this.isEmpty()) {
|
|
41
40
|
this._currentRecordset = -1
|
|
42
41
|
this._currentRow = -1
|
|
@@ -69,7 +68,6 @@ class OINOMsSqlData extends OINODbDataSet {
|
|
|
69
68
|
*
|
|
70
69
|
*/
|
|
71
70
|
async next():Promise<boolean> {
|
|
72
|
-
// OINOLog.debug("OINODbDataSet.next", {currentRow:this._currentRow, length:this.sqlResult.data.length})
|
|
73
71
|
if (this._currentRow < this._rows.length-1) {
|
|
74
72
|
this._currentRow = this._currentRow + 1
|
|
75
73
|
|
|
@@ -121,7 +119,6 @@ export class OINODbMsSql extends OINODb {
|
|
|
121
119
|
constructor(params:OINODbParams) {
|
|
122
120
|
super(params)
|
|
123
121
|
|
|
124
|
-
// OINOLog.debug("OINODbMsSql.constructor", {params:params})
|
|
125
122
|
if (this._params.type !== "OINODbMsSql") {
|
|
126
123
|
throw new Error(OINO_ERROR_PREFIX + ": Not OINODbMsSql-type: " + this._params.type)
|
|
127
124
|
}
|
|
@@ -142,45 +139,20 @@ export class OINODbMsSql extends OINODb {
|
|
|
142
139
|
delete this._params.password // do not store password in db object
|
|
143
140
|
|
|
144
141
|
this._pool.on("error", (conn:any) => {
|
|
145
|
-
OINOLog.error("OINODbMsSql error event", conn)
|
|
142
|
+
OINOLog.error("@oinots/db", "OINODbMsSql", "constructor", "OINODbMsSql error event", conn)
|
|
146
143
|
})
|
|
147
|
-
// this._pool.on("debug", (event:any) => {
|
|
148
|
-
// console.log("OINODbMsSql debug",event)
|
|
149
|
-
// })
|
|
150
144
|
}
|
|
151
145
|
|
|
152
146
|
private async _query(sql:string):Promise<OINOMsSqlData> {
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
// console.log("OINODbMsSql._query result:" + JSON.stringify(sql_res.recordsets))
|
|
158
|
-
const result:OINOMsSqlData = new OINOMsSqlData(sql_res.recordsets)
|
|
159
|
-
return Promise.resolve(result)
|
|
160
|
-
|
|
161
|
-
} catch (err) {
|
|
162
|
-
OINOLog.error("OINODbMsSql._query exception", {err:err})
|
|
163
|
-
throw err;
|
|
164
|
-
|
|
165
|
-
} finally {
|
|
166
|
-
// console.log("OINODbMsSql._query finally");
|
|
167
|
-
}
|
|
168
|
-
// OINOLog.debug("OINODbMsSql._query", {result:query_result})
|
|
147
|
+
const request = this._pool.request() // this does not need to be released but the pool will handle it
|
|
148
|
+
const sql_res = await request.query(sql)
|
|
149
|
+
const result:OINOMsSqlData = new OINOMsSqlData(sql_res.recordsets)
|
|
150
|
+
return result
|
|
169
151
|
}
|
|
170
152
|
|
|
171
153
|
private async _exec(sql:string):Promise<OINOMsSqlData> {
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
const sql_res = await this._pool.request().query(sql);
|
|
175
|
-
// console.log("OINODbMsSql._exec result", sql_res);
|
|
176
|
-
return Promise.resolve(new OINOMsSqlData(OINODB_EMPTY_ROWS))
|
|
177
|
-
|
|
178
|
-
} catch (err) {
|
|
179
|
-
OINOLog.error("OINODbMsSql._exec exception", {err:err})
|
|
180
|
-
throw err;
|
|
181
|
-
} finally {
|
|
182
|
-
}
|
|
183
|
-
// OINOLog.debug("OINODbMsSql._exec", {result:query_result})
|
|
154
|
+
const sql_res = await this._pool.request().query(sql);
|
|
155
|
+
return new OINOMsSqlData(OINODB_EMPTY_ROWS)
|
|
184
156
|
}
|
|
185
157
|
|
|
186
158
|
/**
|
|
@@ -213,7 +185,6 @@ export class OINODbMsSql extends OINODb {
|
|
|
213
185
|
*
|
|
214
186
|
*/
|
|
215
187
|
printCellAsSqlValue(cellValue:OINODataCell, sqlType: string): string {
|
|
216
|
-
// OINOLog.debug("OINODbMsSql.printCellAsSqlValue", {cellValue:cellValue, sqlType:sqlType})
|
|
217
188
|
if (cellValue === null) {
|
|
218
189
|
return "NULL"
|
|
219
190
|
|
|
@@ -259,7 +230,6 @@ export class OINODbMsSql extends OINODb {
|
|
|
259
230
|
*
|
|
260
231
|
*/
|
|
261
232
|
parseSqlValueAsCell(sqlValue:OINODataCell, sqlType: string): OINODataCell {
|
|
262
|
-
// OINOLog.debug("OINODbMsSql.parseSqlValueAsCell", {sqlValue:sqlValue, sqlType:sqlType})
|
|
263
233
|
if ((sqlValue === null) || (sqlValue == "NULL")) {
|
|
264
234
|
return null
|
|
265
235
|
|
|
@@ -293,7 +263,6 @@ export class OINODbMsSql extends OINODb {
|
|
|
293
263
|
result += "TOP " + limit_parts[0] + " "
|
|
294
264
|
}
|
|
295
265
|
result += columnNames + " FROM " + tableName
|
|
296
|
-
// OINOLog.debug("OINODb.printSqlSelect", {tableName:tableName, columnNames:columnNames, whereCondition:whereCondition, orderCondition:orderCondition, limitCondition:limitCondition })
|
|
297
266
|
if (whereCondition != "") {
|
|
298
267
|
result += " WHERE " + whereCondition
|
|
299
268
|
}
|
|
@@ -305,13 +274,14 @@ export class OINODbMsSql extends OINODb {
|
|
|
305
274
|
}
|
|
306
275
|
if ((limitCondition != "") && (limit_parts.length == 2)) {
|
|
307
276
|
if (orderCondition == "") {
|
|
308
|
-
OINOLog.error("OINODbMsSql
|
|
277
|
+
OINOLog.error("@oinots/db", "OINODbMsSql", "printSqlSelect", "LIMIT without ORDER BY is not supported in MS SQL Server")
|
|
278
|
+
throw new Error(OINO_ERROR_PREFIX + "LIMIT without ORDER BY is not supported in MS SQL Server")
|
|
309
279
|
} else {
|
|
310
280
|
result += " OFFSET " + limit_parts[1] + " ROWS FETCH NEXT " + limit_parts[0] + " ROWS ONLY"
|
|
311
281
|
}
|
|
312
282
|
}
|
|
313
283
|
result += ";"
|
|
314
|
-
|
|
284
|
+
OINOLog.debug("@oinots/db", "OINODbMsSql", "printSqlSelect", "Result", {sql:result})
|
|
315
285
|
return result;
|
|
316
286
|
}
|
|
317
287
|
|
|
@@ -324,14 +294,12 @@ export class OINODbMsSql extends OINODb {
|
|
|
324
294
|
try {
|
|
325
295
|
// make sure that any items are correctly URL encoded in the connection string
|
|
326
296
|
await this._pool.connect()
|
|
327
|
-
// OINOLog.info("OINODbMsSql.connect: Connected to database server.")
|
|
328
|
-
// await this._pool.request().query("SELECT 1 as test")
|
|
329
297
|
this.isConnected = true
|
|
330
298
|
|
|
331
|
-
} catch (
|
|
299
|
+
} catch (e:any) {
|
|
332
300
|
// ... error checks
|
|
333
|
-
result.setError(500, "Exception connecting to database: " +
|
|
334
|
-
OINOLog.
|
|
301
|
+
result.setError(500, "Exception connecting to database: " + e.message, "OINODbMsSql.connect")
|
|
302
|
+
OINOLog.exception("@oinots/db", "OINODbMsSql", "connect", "Exception", {message:e.message, stack:e.stack})
|
|
335
303
|
}
|
|
336
304
|
return Promise.resolve(result)
|
|
337
305
|
}
|
|
@@ -349,9 +317,7 @@ export class OINODbMsSql extends OINODb {
|
|
|
349
317
|
OINOBenchmark.start("OINODb", "validate")
|
|
350
318
|
try {
|
|
351
319
|
const sql = this._getValidateSql(this._params.database)
|
|
352
|
-
// OINOLog.debug("OINODbMsSql.validate", {sql:sql})
|
|
353
320
|
const sql_res:OINODbDataSet = await this.sqlSelect(sql)
|
|
354
|
-
// OINOLog.debug("OINODbMsSql.validate", {sql_res:sql_res})
|
|
355
321
|
if (sql_res.isEmpty()) {
|
|
356
322
|
result.setError(400, "DB returned no rows for select!", "OINODbMsSql.validate")
|
|
357
323
|
|
|
@@ -367,6 +333,7 @@ export class OINODbMsSql extends OINODb {
|
|
|
367
333
|
}
|
|
368
334
|
} catch (e:any) {
|
|
369
335
|
result.setError(500, "Exception in validating connection: " + e.message, "OINODbMsSql.validate")
|
|
336
|
+
OINOLog.exception("@oinots/db", "OINODbMsSql", "validate", "Exception", {message:e.message, stack:e.stack})
|
|
370
337
|
}
|
|
371
338
|
OINOBenchmark.end("OINODb", "validate")
|
|
372
339
|
return result
|
|
@@ -382,10 +349,10 @@ export class OINODbMsSql extends OINODb {
|
|
|
382
349
|
OINOBenchmark.start("OINODb", "sqlSelect")
|
|
383
350
|
let result:OINODbDataSet
|
|
384
351
|
try {
|
|
385
|
-
// OINOLog.debug("OINODbMsSql.sqlSelect", {sql:sql})
|
|
386
352
|
result = await this._query(sql)
|
|
387
353
|
|
|
388
354
|
} catch (e:any) {
|
|
355
|
+
OINOLog.exception("@oinots/db", "OINODbMsSql", "sqlSelect", "SQL select exception", {message:e.message, stack:e.stack})
|
|
389
356
|
result = new OINOMsSqlData(OINODB_EMPTY_ROWS, [OINO_ERROR_PREFIX + " (sqlSelect): OINODbMsSql.sqlSelect exception in _db.query: " + e.message])
|
|
390
357
|
}
|
|
391
358
|
OINOBenchmark.end("OINODb", "sqlSelect")
|
|
@@ -405,6 +372,7 @@ export class OINODbMsSql extends OINODb {
|
|
|
405
372
|
result = await this._exec(sql)
|
|
406
373
|
|
|
407
374
|
} catch (e:any) {
|
|
375
|
+
OINOLog.exception("@oinots/db", "OINODbMsSql", "sqlExec", "SQL exec exception", {message:e.message, stack:e.stack})
|
|
408
376
|
result = new OINOMsSqlData(OINODB_EMPTY_ROWS, [OINO_ERROR_PREFIX + " (sqlExec): exception in _db.exec [" + e.message + "]"])
|
|
409
377
|
}
|
|
410
378
|
OINOBenchmark.end("OINODb", "sqlExec")
|
|
@@ -464,10 +432,9 @@ WHERE C.TABLE_CATALOG = '${dbName}';`
|
|
|
464
432
|
async initializeApiDatamodel(api:OINODbApi): Promise<void> {
|
|
465
433
|
|
|
466
434
|
//"SELECT COLUMN_NAME, IS_NULLABLE, DATA_TYPE, CHARACTER_MAXIMUM_LENGTH, NUMERIC_PRECISION, NUMERIC_PRECISION_RADIX
|
|
467
|
-
const
|
|
468
|
-
while (!
|
|
469
|
-
const row:OINODataRow =
|
|
470
|
-
// OINOLog.debug("OINODbMsSql.initializeApiDatamodel", { description:row })
|
|
435
|
+
const schema_res:OINODbDataSet = await this.sqlSelect(this._getSchemaSql(this._params.database, api.params.tableName))
|
|
436
|
+
while (!schema_res.isEof()) {
|
|
437
|
+
const row:OINODataRow = schema_res.getRow()
|
|
471
438
|
const field_name:string = row[0]?.toString() || ""
|
|
472
439
|
const sql_type:string = row[2] as string || ""
|
|
473
440
|
const char_field_length:number = row[3] as number || 0
|
|
@@ -481,13 +448,12 @@ WHERE C.TABLE_CATALOG = '${dbName}';`
|
|
|
481
448
|
isNotNull: row[1] == "NO"
|
|
482
449
|
}
|
|
483
450
|
if (api.isFieldIncluded(field_name) == false) {
|
|
484
|
-
OINOLog.info("OINODbMsSql
|
|
451
|
+
OINOLog.info("@oinots/db", "OINODbMsSql", "initializeApiDatamodel", "Field excluded in API parameters.", {field:field_name})
|
|
485
452
|
if (field_params.isPrimaryKey) {
|
|
486
453
|
throw new Error(OINO_ERROR_PREFIX + "Primary key field excluded in API parameters: " + field_name)
|
|
487
454
|
}
|
|
488
455
|
|
|
489
456
|
} else {
|
|
490
|
-
// OINOLog.debug("OINODbMsSql.initializeApiDatamodel: next field ", {field_name: field_name, sql_type:sql_type, char_field_length:char_field_length, numeric_field_length1:numeric_field_length1, numeric_field_length2:numeric_field_length2, field_params:field_params })
|
|
491
457
|
if ((sql_type == "tinyint") || (sql_type == "smallint") || (sql_type == "int") || (sql_type == "bigint") || (sql_type == "float") || (sql_type == "real")) {
|
|
492
458
|
api.datamodel.addField(new OINONumberDataField(this, field_name, sql_type, field_params ))
|
|
493
459
|
|
|
@@ -511,13 +477,13 @@ WHERE C.TABLE_CATALOG = '${dbName}';`
|
|
|
511
477
|
api.datamodel.addField(new OINOBooleanDataField(this, field_name, sql_type, field_params))
|
|
512
478
|
|
|
513
479
|
} else {
|
|
514
|
-
OINOLog.info("OINODbMsSql
|
|
480
|
+
OINOLog.info("@oinots/db", "OINODbMsSql", "initializeApiDatamodel", "Unrecognized field type treated as string", {field_name: field_name, sql_type:sql_type, char_length: char_field_length, numeric_field_length1:numeric_field_length1, numeric_field_length2:numeric_field_length2, field_params:field_params })
|
|
515
481
|
api.datamodel.addField(new OINOStringDataField(this, field_name, sql_type, field_params, 0))
|
|
516
482
|
}
|
|
517
483
|
}
|
|
518
|
-
await
|
|
484
|
+
await schema_res.next()
|
|
519
485
|
}
|
|
520
|
-
OINOLog.
|
|
486
|
+
OINOLog.info("@oinots/db", "OINODbMsSql", "initializeApiDatamodel", "\n" + api.datamodel.printDebug("\n"))
|
|
521
487
|
return Promise.resolve()
|
|
522
488
|
}
|
|
523
489
|
|