@oino-ts/db-mssql 0.21.2 → 1.0.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/README.md +183 -183
- package/dist/cjs/OINODbMsSql.js +70 -69
- package/dist/esm/OINODbMsSql.js +64 -63
- package/dist/types/OINODbMsSql.d.ts +12 -12
- package/package.json +40 -40
- package/src/OINODbMsSql.ts +541 -540
- package/src/index.ts +1 -1
package/dist/cjs/OINODbMsSql.js
CHANGED
|
@@ -10,12 +10,12 @@ const common_1 = require("@oino-ts/common");
|
|
|
10
10
|
const db_1 = require("@oino-ts/db");
|
|
11
11
|
const mssql_1 = require("mssql");
|
|
12
12
|
/**
|
|
13
|
-
* Implmentation of
|
|
13
|
+
* Implmentation of OINODataSet for MsSql.
|
|
14
14
|
*
|
|
15
15
|
*/
|
|
16
|
-
class OINOMsSqlData extends
|
|
16
|
+
class OINOMsSqlData extends common_1.OINODataSet {
|
|
17
17
|
_recordsets;
|
|
18
|
-
_rows =
|
|
18
|
+
_rows = common_1.OINO_EMPTY_ROWS;
|
|
19
19
|
_currentRecordset;
|
|
20
20
|
_currentRow;
|
|
21
21
|
_eof;
|
|
@@ -87,7 +87,7 @@ class OINOMsSqlData extends db_1.OINODbDataSet {
|
|
|
87
87
|
return this._rows[this._currentRow];
|
|
88
88
|
}
|
|
89
89
|
else {
|
|
90
|
-
return
|
|
90
|
+
return common_1.OINO_EMPTY_ROW;
|
|
91
91
|
}
|
|
92
92
|
}
|
|
93
93
|
/**
|
|
@@ -110,15 +110,15 @@ class OINODbMsSql extends db_1.OINODb {
|
|
|
110
110
|
*/
|
|
111
111
|
constructor(params) {
|
|
112
112
|
super(params);
|
|
113
|
-
if (this.
|
|
114
|
-
throw new Error(common_1.OINO_ERROR_PREFIX + ": Not OINODbMsSql-type: " + this.
|
|
113
|
+
if (this.dbParams.type !== "OINODbMsSql") {
|
|
114
|
+
throw new Error(common_1.OINO_ERROR_PREFIX + ": Not OINODbMsSql-type: " + this.dbParams.type);
|
|
115
115
|
}
|
|
116
116
|
this._pool = new mssql_1.ConnectionPool({
|
|
117
|
-
user: this.
|
|
118
|
-
password: this.
|
|
119
|
-
server: this.
|
|
120
|
-
port: this.
|
|
121
|
-
database: this.
|
|
117
|
+
user: this.dbParams.user,
|
|
118
|
+
password: this.dbParams.password,
|
|
119
|
+
server: this.dbParams.url,
|
|
120
|
+
port: this.dbParams.port,
|
|
121
|
+
database: this.dbParams.database,
|
|
122
122
|
arrayRowMode: true,
|
|
123
123
|
options: {
|
|
124
124
|
encrypt: true, // Use encryption for Azure SQL Database
|
|
@@ -127,7 +127,7 @@ class OINODbMsSql extends db_1.OINODb {
|
|
|
127
127
|
trustServerCertificate: true // Change to false for production
|
|
128
128
|
}
|
|
129
129
|
});
|
|
130
|
-
delete this.
|
|
130
|
+
delete this.dbParams.password; // do not store password in db object
|
|
131
131
|
this._pool.on("error", (conn) => {
|
|
132
132
|
common_1.OINOLog.error("@oino-ts/db-mssql", "OINODbMsSql", "constructor", "OINODbMsSql error event", conn);
|
|
133
133
|
});
|
|
@@ -141,7 +141,7 @@ class OINODbMsSql extends db_1.OINODb {
|
|
|
141
141
|
}
|
|
142
142
|
catch (e) {
|
|
143
143
|
common_1.OINOLog.exception("@oino-ts/db-mssql", "OINODbMsSql", "_query", "exception in SQL query", { message: e.message, stack: e.stack, sql: sql });
|
|
144
|
-
return new OINOMsSqlData(
|
|
144
|
+
return new OINOMsSqlData(common_1.OINO_EMPTY_ROWS, []).setError(500, common_1.OINO_ERROR_PREFIX + ": Exception in db query: " + e.message, "OINODbMsSql._query");
|
|
145
145
|
}
|
|
146
146
|
}
|
|
147
147
|
async _exec(sql) {
|
|
@@ -153,7 +153,7 @@ class OINODbMsSql extends db_1.OINODb {
|
|
|
153
153
|
}
|
|
154
154
|
catch (e) {
|
|
155
155
|
common_1.OINOLog.exception("@oino-ts/db-mssql", "OINODbMsSql", "_exec", "exception in SQL exec", { message: e.message, stack: e.stack, sql: sql });
|
|
156
|
-
return new OINOMsSqlData(
|
|
156
|
+
return new OINOMsSqlData(common_1.OINO_EMPTY_ROWS, []).setError(500, common_1.OINO_ERROR_PREFIX + ": Exception in db exec: " + e.message, "OINODbMsSql._exec");
|
|
157
157
|
}
|
|
158
158
|
}
|
|
159
159
|
/**
|
|
@@ -162,7 +162,7 @@ class OINODbMsSql extends db_1.OINODb {
|
|
|
162
162
|
* @param sqlTable name of the table
|
|
163
163
|
*
|
|
164
164
|
*/
|
|
165
|
-
|
|
165
|
+
printTableName(sqlTable) {
|
|
166
166
|
return "[" + sqlTable + "]";
|
|
167
167
|
}
|
|
168
168
|
/**
|
|
@@ -171,7 +171,7 @@ class OINODbMsSql extends db_1.OINODb {
|
|
|
171
171
|
* @param sqlColumn name of the column
|
|
172
172
|
*
|
|
173
173
|
*/
|
|
174
|
-
|
|
174
|
+
printColumnName(sqlColumn) {
|
|
175
175
|
return "[" + sqlColumn + "]";
|
|
176
176
|
}
|
|
177
177
|
/**
|
|
@@ -179,20 +179,20 @@ class OINODbMsSql extends db_1.OINODb {
|
|
|
179
179
|
* type with the correct SQL escaping.
|
|
180
180
|
*
|
|
181
181
|
* @param cellValue data from sql results
|
|
182
|
-
* @param
|
|
182
|
+
* @param nativeType native type name for table column
|
|
183
183
|
*
|
|
184
184
|
*/
|
|
185
|
-
|
|
185
|
+
printCellAsValue(cellValue, nativeType) {
|
|
186
186
|
if (cellValue === null) {
|
|
187
187
|
return "NULL";
|
|
188
188
|
}
|
|
189
189
|
else if (cellValue === undefined) {
|
|
190
190
|
return "UNDEFINED";
|
|
191
191
|
}
|
|
192
|
-
else if ((
|
|
192
|
+
else if ((nativeType == "int") || (nativeType == "smallint") || (nativeType == "float")) {
|
|
193
193
|
return cellValue.toString();
|
|
194
194
|
}
|
|
195
|
-
else if ((
|
|
195
|
+
else if ((nativeType == "longblob") || (nativeType == "binary") || (nativeType == "varbinary")) {
|
|
196
196
|
if (cellValue instanceof Buffer) {
|
|
197
197
|
return "0x" + cellValue.toString("hex") + "";
|
|
198
198
|
}
|
|
@@ -203,11 +203,11 @@ class OINODbMsSql extends db_1.OINODb {
|
|
|
203
203
|
return "'" + cellValue?.toString() + "'";
|
|
204
204
|
}
|
|
205
205
|
}
|
|
206
|
-
else if (((
|
|
206
|
+
else if (((nativeType == "date") || (nativeType == "datetime") || (nativeType == "datetime2") || (nativeType == "timestamp")) && (cellValue instanceof Date)) {
|
|
207
207
|
return "'" + cellValue.toISOString().substring(0, 23) + "'";
|
|
208
208
|
}
|
|
209
209
|
else {
|
|
210
|
-
return this.
|
|
210
|
+
return this.printStringValue(cellValue.toString());
|
|
211
211
|
}
|
|
212
212
|
}
|
|
213
213
|
/**
|
|
@@ -216,7 +216,7 @@ class OINODbMsSql extends db_1.OINODb {
|
|
|
216
216
|
* @param sqlString string value
|
|
217
217
|
*
|
|
218
218
|
*/
|
|
219
|
-
|
|
219
|
+
printStringValue(sqlString) {
|
|
220
220
|
return "'" + sqlString.replaceAll("'", "''") + "'";
|
|
221
221
|
}
|
|
222
222
|
/**
|
|
@@ -224,20 +224,20 @@ class OINODbMsSql extends db_1.OINODb {
|
|
|
224
224
|
* type.
|
|
225
225
|
*
|
|
226
226
|
* @param sqlValue data from serialization
|
|
227
|
-
* @param
|
|
227
|
+
* @param nativeType native type name for table column
|
|
228
228
|
*
|
|
229
229
|
*/
|
|
230
|
-
|
|
230
|
+
parseValueAsCell(sqlValue, nativeType) {
|
|
231
231
|
if ((sqlValue === null) || (sqlValue == "NULL")) {
|
|
232
232
|
return null;
|
|
233
233
|
}
|
|
234
234
|
else if (sqlValue === undefined) {
|
|
235
235
|
return undefined;
|
|
236
236
|
}
|
|
237
|
-
else if (((
|
|
237
|
+
else if (((nativeType == "date") || (nativeType == "datetime") || (nativeType == "datetime2")) && (typeof (sqlValue) == "string") && (sqlValue != "")) {
|
|
238
238
|
return new Date(sqlValue);
|
|
239
239
|
}
|
|
240
|
-
else if (
|
|
240
|
+
else if (nativeType == "bit") {
|
|
241
241
|
return (sqlValue === 1) || (sqlValue === true); // sometimes boolean and sometimes number
|
|
242
242
|
}
|
|
243
243
|
else {
|
|
@@ -334,7 +334,7 @@ class OINODbMsSql extends db_1.OINODb {
|
|
|
334
334
|
}
|
|
335
335
|
common_1.OINOBenchmark.startMetric("OINODb", "validate");
|
|
336
336
|
try {
|
|
337
|
-
const sql = this._getValidateSql(this.
|
|
337
|
+
const sql = this._getValidateSql(this.dbParams.database);
|
|
338
338
|
const sql_res = await this._query(sql);
|
|
339
339
|
if (sql_res.isEmpty()) {
|
|
340
340
|
result.setError(400, "DB returned no rows for select!", "OINODbMsSql.validate");
|
|
@@ -404,54 +404,55 @@ class OINODbMsSql extends db_1.OINODb {
|
|
|
404
404
|
return result;
|
|
405
405
|
}
|
|
406
406
|
_getSchemaSql(dbName, tableName) {
|
|
407
|
-
const sql = `SELECT
|
|
408
|
-
C.COLUMN_NAME,
|
|
409
|
-
C.IS_NULLABLE,
|
|
410
|
-
C.DATA_TYPE,
|
|
411
|
-
C.CHARACTER_MAXIMUM_LENGTH,
|
|
412
|
-
C.NUMERIC_PRECISION,
|
|
413
|
-
C.NUMERIC_PRECISION_RADIX,
|
|
414
|
-
CONST.CONSTRAINT_TYPES,
|
|
415
|
-
COLUMNPROPERTY(OBJECT_ID(C.TABLE_SCHEMA + '.' + C.TABLE_NAME), C.COLUMN_NAME, 'IsIdentity') AS IS_AUTO_INCREMENT,
|
|
416
|
-
COLUMNPROPERTY(OBJECT_ID(C.TABLE_SCHEMA + '.' + C.TABLE_NAME), C.COLUMN_NAME, 'IsComputed') AS IS_COMPUTED
|
|
417
|
-
FROM
|
|
418
|
-
INFORMATION_SCHEMA.COLUMNS as C LEFT JOIN
|
|
419
|
-
(
|
|
420
|
-
SELECT TC.TABLE_NAME, KU.COLUMN_NAME, STRING_AGG(TC.CONSTRAINT_TYPE, ',') as CONSTRAINT_TYPES
|
|
421
|
-
FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS AS TC
|
|
422
|
-
INNER JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE AS KU ON TC.CONSTRAINT_NAME = KU.CONSTRAINT_NAME
|
|
423
|
-
GROUP BY TC.TABLE_NAME, KU.COLUMN_NAME
|
|
424
|
-
) as CONST
|
|
425
|
-
ON C.TABLE_NAME = CONST.TABLE_NAME AND C.COLUMN_NAME = CONST.COLUMN_NAME
|
|
426
|
-
WHERE C.TABLE_CATALOG = '${dbName}' AND C.TABLE_NAME = '${tableName}'
|
|
407
|
+
const sql = `SELECT
|
|
408
|
+
C.COLUMN_NAME,
|
|
409
|
+
C.IS_NULLABLE,
|
|
410
|
+
C.DATA_TYPE,
|
|
411
|
+
C.CHARACTER_MAXIMUM_LENGTH,
|
|
412
|
+
C.NUMERIC_PRECISION,
|
|
413
|
+
C.NUMERIC_PRECISION_RADIX,
|
|
414
|
+
CONST.CONSTRAINT_TYPES,
|
|
415
|
+
COLUMNPROPERTY(OBJECT_ID(C.TABLE_SCHEMA + '.' + C.TABLE_NAME), C.COLUMN_NAME, 'IsIdentity') AS IS_AUTO_INCREMENT,
|
|
416
|
+
COLUMNPROPERTY(OBJECT_ID(C.TABLE_SCHEMA + '.' + C.TABLE_NAME), C.COLUMN_NAME, 'IsComputed') AS IS_COMPUTED
|
|
417
|
+
FROM
|
|
418
|
+
INFORMATION_SCHEMA.COLUMNS as C LEFT JOIN
|
|
419
|
+
(
|
|
420
|
+
SELECT TC.TABLE_NAME, KU.COLUMN_NAME, STRING_AGG(TC.CONSTRAINT_TYPE, ',') as CONSTRAINT_TYPES
|
|
421
|
+
FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS AS TC
|
|
422
|
+
INNER JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE AS KU ON TC.CONSTRAINT_NAME = KU.CONSTRAINT_NAME
|
|
423
|
+
GROUP BY TC.TABLE_NAME, KU.COLUMN_NAME
|
|
424
|
+
) as CONST
|
|
425
|
+
ON C.TABLE_NAME = CONST.TABLE_NAME AND C.COLUMN_NAME = CONST.COLUMN_NAME
|
|
426
|
+
WHERE C.TABLE_CATALOG = '${dbName}' AND C.TABLE_NAME = '${tableName}'
|
|
427
427
|
ORDER BY C.ORDINAL_POSITION;`;
|
|
428
428
|
return sql;
|
|
429
429
|
}
|
|
430
430
|
_getValidateSql(dbName) {
|
|
431
|
-
const sql = `SELECT
|
|
432
|
-
count(C.COLUMN_NAME) AS COLUMN_COUNT
|
|
433
|
-
FROM
|
|
434
|
-
INFORMATION_SCHEMA.COLUMNS as C LEFT JOIN
|
|
435
|
-
(
|
|
436
|
-
SELECT TC.TABLE_NAME, KU.COLUMN_NAME, STRING_AGG(TC.CONSTRAINT_TYPE, ',') as CONSTRAINT_TYPES
|
|
437
|
-
FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS AS TC
|
|
438
|
-
INNER JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE AS KU ON TC.CONSTRAINT_NAME = KU.CONSTRAINT_NAME
|
|
439
|
-
GROUP BY TC.TABLE_NAME, KU.COLUMN_NAME
|
|
440
|
-
) as CONST
|
|
441
|
-
ON C.TABLE_NAME = CONST.TABLE_NAME AND C.COLUMN_NAME = CONST.COLUMN_NAME
|
|
431
|
+
const sql = `SELECT
|
|
432
|
+
count(C.COLUMN_NAME) AS COLUMN_COUNT
|
|
433
|
+
FROM
|
|
434
|
+
INFORMATION_SCHEMA.COLUMNS as C LEFT JOIN
|
|
435
|
+
(
|
|
436
|
+
SELECT TC.TABLE_NAME, KU.COLUMN_NAME, STRING_AGG(TC.CONSTRAINT_TYPE, ',') as CONSTRAINT_TYPES
|
|
437
|
+
FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS AS TC
|
|
438
|
+
INNER JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE AS KU ON TC.CONSTRAINT_NAME = KU.CONSTRAINT_NAME
|
|
439
|
+
GROUP BY TC.TABLE_NAME, KU.COLUMN_NAME
|
|
440
|
+
) as CONST
|
|
441
|
+
ON C.TABLE_NAME = CONST.TABLE_NAME AND C.COLUMN_NAME = CONST.COLUMN_NAME
|
|
442
442
|
WHERE C.TABLE_CATALOG = '${dbName}';`;
|
|
443
443
|
return sql;
|
|
444
444
|
}
|
|
445
445
|
/**
|
|
446
|
-
* Initialize a data model by getting the SQL schema and populating
|
|
446
|
+
* Initialize a data model by getting the SQL schema and populating OINODataFields of
|
|
447
447
|
* the model.
|
|
448
448
|
*
|
|
449
449
|
* @param api api which data model to initialize.
|
|
450
450
|
*
|
|
451
451
|
*/
|
|
452
452
|
async initializeApiDatamodel(api) {
|
|
453
|
+
api.initializeDatamodel(new db_1.OINODbDataModel(api));
|
|
453
454
|
//"SELECT COLUMN_NAME, IS_NULLABLE, DATA_TYPE, CHARACTER_MAXIMUM_LENGTH, NUMERIC_PRECISION, NUMERIC_PRECISION_RADIX
|
|
454
|
-
const schema_res = await this.sqlSelect(this._getSchemaSql(this.
|
|
455
|
+
const schema_res = await this.sqlSelect(this._getSchemaSql(this.dbParams.database, api.params.tableName));
|
|
455
456
|
while (!schema_res.isEof()) {
|
|
456
457
|
const row = schema_res.getRow();
|
|
457
458
|
const field_name = row[0]?.toString() || "";
|
|
@@ -474,31 +475,31 @@ WHERE C.TABLE_CATALOG = '${dbName}';`;
|
|
|
474
475
|
}
|
|
475
476
|
else {
|
|
476
477
|
if ((sql_type == "tinyint") || (sql_type == "smallint") || (sql_type == "int") || (sql_type == "bigint") || (sql_type == "float") || (sql_type == "real")) {
|
|
477
|
-
api.datamodel.addField(new
|
|
478
|
+
api.datamodel.addField(new common_1.OINONumberDataField(this, field_name, sql_type, field_params));
|
|
478
479
|
}
|
|
479
480
|
else if ((sql_type == "date") || (sql_type == "datetime") || (sql_type == "datetime2")) {
|
|
480
481
|
if (api.params.useDatesAsString) {
|
|
481
|
-
api.datamodel.addField(new
|
|
482
|
+
api.datamodel.addField(new common_1.OINOStringDataField(this, field_name, sql_type, field_params, 0));
|
|
482
483
|
}
|
|
483
484
|
else {
|
|
484
|
-
api.datamodel.addField(new
|
|
485
|
+
api.datamodel.addField(new common_1.OINODatetimeDataField(this, field_name, sql_type, field_params));
|
|
485
486
|
}
|
|
486
487
|
}
|
|
487
488
|
else if ((sql_type == "ntext") || (sql_type == "nchar") || (sql_type == "nvarchar") || (sql_type == "text") || (sql_type == "char") || (sql_type == "varchar")) {
|
|
488
|
-
api.datamodel.addField(new
|
|
489
|
+
api.datamodel.addField(new common_1.OINOStringDataField(this, field_name, sql_type, field_params, char_field_length));
|
|
489
490
|
}
|
|
490
491
|
else if ((sql_type == "binary") || (sql_type == "varbinary") || (sql_type == "image")) {
|
|
491
|
-
api.datamodel.addField(new
|
|
492
|
+
api.datamodel.addField(new common_1.OINOBlobDataField(this, field_name, sql_type, field_params, char_field_length));
|
|
492
493
|
}
|
|
493
494
|
else if ((sql_type == "numeric") || (sql_type == "decimal") || (sql_type == "money")) {
|
|
494
|
-
api.datamodel.addField(new
|
|
495
|
+
api.datamodel.addField(new common_1.OINOStringDataField(this, field_name, sql_type, field_params, numeric_field_length1 + numeric_field_length2 + 1));
|
|
495
496
|
}
|
|
496
497
|
else if ((sql_type == "bit")) {
|
|
497
|
-
api.datamodel.addField(new
|
|
498
|
+
api.datamodel.addField(new common_1.OINOBooleanDataField(this, field_name, sql_type, field_params));
|
|
498
499
|
}
|
|
499
500
|
else {
|
|
500
501
|
common_1.OINOLog.info("@oino-ts/db-mssql", "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 });
|
|
501
|
-
api.datamodel.addField(new
|
|
502
|
+
api.datamodel.addField(new common_1.OINOStringDataField(this, field_name, sql_type, field_params, 0));
|
|
502
503
|
}
|
|
503
504
|
}
|
|
504
505
|
await schema_res.next();
|
package/dist/esm/OINODbMsSql.js
CHANGED
|
@@ -3,16 +3,16 @@
|
|
|
3
3
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
4
4
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
|
5
5
|
*/
|
|
6
|
-
import { OINO_ERROR_PREFIX, OINOBenchmark, OINO_INFO_PREFIX, OINOLog, OINOResult } from "@oino-ts/common";
|
|
7
|
-
import { OINODb,
|
|
6
|
+
import { OINO_ERROR_PREFIX, OINOBenchmark, OINO_INFO_PREFIX, OINOLog, OINOResult, OINODataSet, OINOBooleanDataField, OINONumberDataField, OINOStringDataField, OINODatetimeDataField, OINOBlobDataField, OINO_EMPTY_ROW, OINO_EMPTY_ROWS } from "@oino-ts/common";
|
|
7
|
+
import { OINODb, OINODbDataModel } from "@oino-ts/db";
|
|
8
8
|
import { ConnectionPool } from "mssql";
|
|
9
9
|
/**
|
|
10
|
-
* Implmentation of
|
|
10
|
+
* Implmentation of OINODataSet for MsSql.
|
|
11
11
|
*
|
|
12
12
|
*/
|
|
13
|
-
class OINOMsSqlData extends
|
|
13
|
+
class OINOMsSqlData extends OINODataSet {
|
|
14
14
|
_recordsets;
|
|
15
|
-
_rows =
|
|
15
|
+
_rows = OINO_EMPTY_ROWS;
|
|
16
16
|
_currentRecordset;
|
|
17
17
|
_currentRow;
|
|
18
18
|
_eof;
|
|
@@ -84,7 +84,7 @@ class OINOMsSqlData extends OINODbDataSet {
|
|
|
84
84
|
return this._rows[this._currentRow];
|
|
85
85
|
}
|
|
86
86
|
else {
|
|
87
|
-
return
|
|
87
|
+
return OINO_EMPTY_ROW;
|
|
88
88
|
}
|
|
89
89
|
}
|
|
90
90
|
/**
|
|
@@ -107,15 +107,15 @@ export class OINODbMsSql extends OINODb {
|
|
|
107
107
|
*/
|
|
108
108
|
constructor(params) {
|
|
109
109
|
super(params);
|
|
110
|
-
if (this.
|
|
111
|
-
throw new Error(OINO_ERROR_PREFIX + ": Not OINODbMsSql-type: " + this.
|
|
110
|
+
if (this.dbParams.type !== "OINODbMsSql") {
|
|
111
|
+
throw new Error(OINO_ERROR_PREFIX + ": Not OINODbMsSql-type: " + this.dbParams.type);
|
|
112
112
|
}
|
|
113
113
|
this._pool = new ConnectionPool({
|
|
114
|
-
user: this.
|
|
115
|
-
password: this.
|
|
116
|
-
server: this.
|
|
117
|
-
port: this.
|
|
118
|
-
database: this.
|
|
114
|
+
user: this.dbParams.user,
|
|
115
|
+
password: this.dbParams.password,
|
|
116
|
+
server: this.dbParams.url,
|
|
117
|
+
port: this.dbParams.port,
|
|
118
|
+
database: this.dbParams.database,
|
|
119
119
|
arrayRowMode: true,
|
|
120
120
|
options: {
|
|
121
121
|
encrypt: true, // Use encryption for Azure SQL Database
|
|
@@ -124,7 +124,7 @@ export class OINODbMsSql extends OINODb {
|
|
|
124
124
|
trustServerCertificate: true // Change to false for production
|
|
125
125
|
}
|
|
126
126
|
});
|
|
127
|
-
delete this.
|
|
127
|
+
delete this.dbParams.password; // do not store password in db object
|
|
128
128
|
this._pool.on("error", (conn) => {
|
|
129
129
|
OINOLog.error("@oino-ts/db-mssql", "OINODbMsSql", "constructor", "OINODbMsSql error event", conn);
|
|
130
130
|
});
|
|
@@ -138,7 +138,7 @@ export class OINODbMsSql extends OINODb {
|
|
|
138
138
|
}
|
|
139
139
|
catch (e) {
|
|
140
140
|
OINOLog.exception("@oino-ts/db-mssql", "OINODbMsSql", "_query", "exception in SQL query", { message: e.message, stack: e.stack, sql: sql });
|
|
141
|
-
return new OINOMsSqlData(
|
|
141
|
+
return new OINOMsSqlData(OINO_EMPTY_ROWS, []).setError(500, OINO_ERROR_PREFIX + ": Exception in db query: " + e.message, "OINODbMsSql._query");
|
|
142
142
|
}
|
|
143
143
|
}
|
|
144
144
|
async _exec(sql) {
|
|
@@ -150,7 +150,7 @@ export class OINODbMsSql extends OINODb {
|
|
|
150
150
|
}
|
|
151
151
|
catch (e) {
|
|
152
152
|
OINOLog.exception("@oino-ts/db-mssql", "OINODbMsSql", "_exec", "exception in SQL exec", { message: e.message, stack: e.stack, sql: sql });
|
|
153
|
-
return new OINOMsSqlData(
|
|
153
|
+
return new OINOMsSqlData(OINO_EMPTY_ROWS, []).setError(500, OINO_ERROR_PREFIX + ": Exception in db exec: " + e.message, "OINODbMsSql._exec");
|
|
154
154
|
}
|
|
155
155
|
}
|
|
156
156
|
/**
|
|
@@ -159,7 +159,7 @@ export class OINODbMsSql extends OINODb {
|
|
|
159
159
|
* @param sqlTable name of the table
|
|
160
160
|
*
|
|
161
161
|
*/
|
|
162
|
-
|
|
162
|
+
printTableName(sqlTable) {
|
|
163
163
|
return "[" + sqlTable + "]";
|
|
164
164
|
}
|
|
165
165
|
/**
|
|
@@ -168,7 +168,7 @@ export class OINODbMsSql extends OINODb {
|
|
|
168
168
|
* @param sqlColumn name of the column
|
|
169
169
|
*
|
|
170
170
|
*/
|
|
171
|
-
|
|
171
|
+
printColumnName(sqlColumn) {
|
|
172
172
|
return "[" + sqlColumn + "]";
|
|
173
173
|
}
|
|
174
174
|
/**
|
|
@@ -176,20 +176,20 @@ export class OINODbMsSql extends OINODb {
|
|
|
176
176
|
* type with the correct SQL escaping.
|
|
177
177
|
*
|
|
178
178
|
* @param cellValue data from sql results
|
|
179
|
-
* @param
|
|
179
|
+
* @param nativeType native type name for table column
|
|
180
180
|
*
|
|
181
181
|
*/
|
|
182
|
-
|
|
182
|
+
printCellAsValue(cellValue, nativeType) {
|
|
183
183
|
if (cellValue === null) {
|
|
184
184
|
return "NULL";
|
|
185
185
|
}
|
|
186
186
|
else if (cellValue === undefined) {
|
|
187
187
|
return "UNDEFINED";
|
|
188
188
|
}
|
|
189
|
-
else if ((
|
|
189
|
+
else if ((nativeType == "int") || (nativeType == "smallint") || (nativeType == "float")) {
|
|
190
190
|
return cellValue.toString();
|
|
191
191
|
}
|
|
192
|
-
else if ((
|
|
192
|
+
else if ((nativeType == "longblob") || (nativeType == "binary") || (nativeType == "varbinary")) {
|
|
193
193
|
if (cellValue instanceof Buffer) {
|
|
194
194
|
return "0x" + cellValue.toString("hex") + "";
|
|
195
195
|
}
|
|
@@ -200,11 +200,11 @@ export class OINODbMsSql extends OINODb {
|
|
|
200
200
|
return "'" + cellValue?.toString() + "'";
|
|
201
201
|
}
|
|
202
202
|
}
|
|
203
|
-
else if (((
|
|
203
|
+
else if (((nativeType == "date") || (nativeType == "datetime") || (nativeType == "datetime2") || (nativeType == "timestamp")) && (cellValue instanceof Date)) {
|
|
204
204
|
return "'" + cellValue.toISOString().substring(0, 23) + "'";
|
|
205
205
|
}
|
|
206
206
|
else {
|
|
207
|
-
return this.
|
|
207
|
+
return this.printStringValue(cellValue.toString());
|
|
208
208
|
}
|
|
209
209
|
}
|
|
210
210
|
/**
|
|
@@ -213,7 +213,7 @@ export class OINODbMsSql extends OINODb {
|
|
|
213
213
|
* @param sqlString string value
|
|
214
214
|
*
|
|
215
215
|
*/
|
|
216
|
-
|
|
216
|
+
printStringValue(sqlString) {
|
|
217
217
|
return "'" + sqlString.replaceAll("'", "''") + "'";
|
|
218
218
|
}
|
|
219
219
|
/**
|
|
@@ -221,20 +221,20 @@ export class OINODbMsSql extends OINODb {
|
|
|
221
221
|
* type.
|
|
222
222
|
*
|
|
223
223
|
* @param sqlValue data from serialization
|
|
224
|
-
* @param
|
|
224
|
+
* @param nativeType native type name for table column
|
|
225
225
|
*
|
|
226
226
|
*/
|
|
227
|
-
|
|
227
|
+
parseValueAsCell(sqlValue, nativeType) {
|
|
228
228
|
if ((sqlValue === null) || (sqlValue == "NULL")) {
|
|
229
229
|
return null;
|
|
230
230
|
}
|
|
231
231
|
else if (sqlValue === undefined) {
|
|
232
232
|
return undefined;
|
|
233
233
|
}
|
|
234
|
-
else if (((
|
|
234
|
+
else if (((nativeType == "date") || (nativeType == "datetime") || (nativeType == "datetime2")) && (typeof (sqlValue) == "string") && (sqlValue != "")) {
|
|
235
235
|
return new Date(sqlValue);
|
|
236
236
|
}
|
|
237
|
-
else if (
|
|
237
|
+
else if (nativeType == "bit") {
|
|
238
238
|
return (sqlValue === 1) || (sqlValue === true); // sometimes boolean and sometimes number
|
|
239
239
|
}
|
|
240
240
|
else {
|
|
@@ -331,7 +331,7 @@ export class OINODbMsSql extends OINODb {
|
|
|
331
331
|
}
|
|
332
332
|
OINOBenchmark.startMetric("OINODb", "validate");
|
|
333
333
|
try {
|
|
334
|
-
const sql = this._getValidateSql(this.
|
|
334
|
+
const sql = this._getValidateSql(this.dbParams.database);
|
|
335
335
|
const sql_res = await this._query(sql);
|
|
336
336
|
if (sql_res.isEmpty()) {
|
|
337
337
|
result.setError(400, "DB returned no rows for select!", "OINODbMsSql.validate");
|
|
@@ -401,54 +401,55 @@ export class OINODbMsSql extends OINODb {
|
|
|
401
401
|
return result;
|
|
402
402
|
}
|
|
403
403
|
_getSchemaSql(dbName, tableName) {
|
|
404
|
-
const sql = `SELECT
|
|
405
|
-
C.COLUMN_NAME,
|
|
406
|
-
C.IS_NULLABLE,
|
|
407
|
-
C.DATA_TYPE,
|
|
408
|
-
C.CHARACTER_MAXIMUM_LENGTH,
|
|
409
|
-
C.NUMERIC_PRECISION,
|
|
410
|
-
C.NUMERIC_PRECISION_RADIX,
|
|
411
|
-
CONST.CONSTRAINT_TYPES,
|
|
412
|
-
COLUMNPROPERTY(OBJECT_ID(C.TABLE_SCHEMA + '.' + C.TABLE_NAME), C.COLUMN_NAME, 'IsIdentity') AS IS_AUTO_INCREMENT,
|
|
413
|
-
COLUMNPROPERTY(OBJECT_ID(C.TABLE_SCHEMA + '.' + C.TABLE_NAME), C.COLUMN_NAME, 'IsComputed') AS IS_COMPUTED
|
|
414
|
-
FROM
|
|
415
|
-
INFORMATION_SCHEMA.COLUMNS as C LEFT JOIN
|
|
416
|
-
(
|
|
417
|
-
SELECT TC.TABLE_NAME, KU.COLUMN_NAME, STRING_AGG(TC.CONSTRAINT_TYPE, ',') as CONSTRAINT_TYPES
|
|
418
|
-
FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS AS TC
|
|
419
|
-
INNER JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE AS KU ON TC.CONSTRAINT_NAME = KU.CONSTRAINT_NAME
|
|
420
|
-
GROUP BY TC.TABLE_NAME, KU.COLUMN_NAME
|
|
421
|
-
) as CONST
|
|
422
|
-
ON C.TABLE_NAME = CONST.TABLE_NAME AND C.COLUMN_NAME = CONST.COLUMN_NAME
|
|
423
|
-
WHERE C.TABLE_CATALOG = '${dbName}' AND C.TABLE_NAME = '${tableName}'
|
|
404
|
+
const sql = `SELECT
|
|
405
|
+
C.COLUMN_NAME,
|
|
406
|
+
C.IS_NULLABLE,
|
|
407
|
+
C.DATA_TYPE,
|
|
408
|
+
C.CHARACTER_MAXIMUM_LENGTH,
|
|
409
|
+
C.NUMERIC_PRECISION,
|
|
410
|
+
C.NUMERIC_PRECISION_RADIX,
|
|
411
|
+
CONST.CONSTRAINT_TYPES,
|
|
412
|
+
COLUMNPROPERTY(OBJECT_ID(C.TABLE_SCHEMA + '.' + C.TABLE_NAME), C.COLUMN_NAME, 'IsIdentity') AS IS_AUTO_INCREMENT,
|
|
413
|
+
COLUMNPROPERTY(OBJECT_ID(C.TABLE_SCHEMA + '.' + C.TABLE_NAME), C.COLUMN_NAME, 'IsComputed') AS IS_COMPUTED
|
|
414
|
+
FROM
|
|
415
|
+
INFORMATION_SCHEMA.COLUMNS as C LEFT JOIN
|
|
416
|
+
(
|
|
417
|
+
SELECT TC.TABLE_NAME, KU.COLUMN_NAME, STRING_AGG(TC.CONSTRAINT_TYPE, ',') as CONSTRAINT_TYPES
|
|
418
|
+
FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS AS TC
|
|
419
|
+
INNER JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE AS KU ON TC.CONSTRAINT_NAME = KU.CONSTRAINT_NAME
|
|
420
|
+
GROUP BY TC.TABLE_NAME, KU.COLUMN_NAME
|
|
421
|
+
) as CONST
|
|
422
|
+
ON C.TABLE_NAME = CONST.TABLE_NAME AND C.COLUMN_NAME = CONST.COLUMN_NAME
|
|
423
|
+
WHERE C.TABLE_CATALOG = '${dbName}' AND C.TABLE_NAME = '${tableName}'
|
|
424
424
|
ORDER BY C.ORDINAL_POSITION;`;
|
|
425
425
|
return sql;
|
|
426
426
|
}
|
|
427
427
|
_getValidateSql(dbName) {
|
|
428
|
-
const sql = `SELECT
|
|
429
|
-
count(C.COLUMN_NAME) AS COLUMN_COUNT
|
|
430
|
-
FROM
|
|
431
|
-
INFORMATION_SCHEMA.COLUMNS as C LEFT JOIN
|
|
432
|
-
(
|
|
433
|
-
SELECT TC.TABLE_NAME, KU.COLUMN_NAME, STRING_AGG(TC.CONSTRAINT_TYPE, ',') as CONSTRAINT_TYPES
|
|
434
|
-
FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS AS TC
|
|
435
|
-
INNER JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE AS KU ON TC.CONSTRAINT_NAME = KU.CONSTRAINT_NAME
|
|
436
|
-
GROUP BY TC.TABLE_NAME, KU.COLUMN_NAME
|
|
437
|
-
) as CONST
|
|
438
|
-
ON C.TABLE_NAME = CONST.TABLE_NAME AND C.COLUMN_NAME = CONST.COLUMN_NAME
|
|
428
|
+
const sql = `SELECT
|
|
429
|
+
count(C.COLUMN_NAME) AS COLUMN_COUNT
|
|
430
|
+
FROM
|
|
431
|
+
INFORMATION_SCHEMA.COLUMNS as C LEFT JOIN
|
|
432
|
+
(
|
|
433
|
+
SELECT TC.TABLE_NAME, KU.COLUMN_NAME, STRING_AGG(TC.CONSTRAINT_TYPE, ',') as CONSTRAINT_TYPES
|
|
434
|
+
FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS AS TC
|
|
435
|
+
INNER JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE AS KU ON TC.CONSTRAINT_NAME = KU.CONSTRAINT_NAME
|
|
436
|
+
GROUP BY TC.TABLE_NAME, KU.COLUMN_NAME
|
|
437
|
+
) as CONST
|
|
438
|
+
ON C.TABLE_NAME = CONST.TABLE_NAME AND C.COLUMN_NAME = CONST.COLUMN_NAME
|
|
439
439
|
WHERE C.TABLE_CATALOG = '${dbName}';`;
|
|
440
440
|
return sql;
|
|
441
441
|
}
|
|
442
442
|
/**
|
|
443
|
-
* Initialize a data model by getting the SQL schema and populating
|
|
443
|
+
* Initialize a data model by getting the SQL schema and populating OINODataFields of
|
|
444
444
|
* the model.
|
|
445
445
|
*
|
|
446
446
|
* @param api api which data model to initialize.
|
|
447
447
|
*
|
|
448
448
|
*/
|
|
449
449
|
async initializeApiDatamodel(api) {
|
|
450
|
+
api.initializeDatamodel(new OINODbDataModel(api));
|
|
450
451
|
//"SELECT COLUMN_NAME, IS_NULLABLE, DATA_TYPE, CHARACTER_MAXIMUM_LENGTH, NUMERIC_PRECISION, NUMERIC_PRECISION_RADIX
|
|
451
|
-
const schema_res = await this.sqlSelect(this._getSchemaSql(this.
|
|
452
|
+
const schema_res = await this.sqlSelect(this._getSchemaSql(this.dbParams.database, api.params.tableName));
|
|
452
453
|
while (!schema_res.isEof()) {
|
|
453
454
|
const row = schema_res.getRow();
|
|
454
455
|
const field_name = row[0]?.toString() || "";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { OINOResult } from "@oino-ts/common";
|
|
2
|
-
import { OINODb,
|
|
1
|
+
import { OINOResult, OINODataSet, OINODataCell } from "@oino-ts/common";
|
|
2
|
+
import { OINODb, OINODbApi, OINODbParams } from "@oino-ts/db";
|
|
3
3
|
/**
|
|
4
4
|
* Implementation of MsSql-database.
|
|
5
5
|
*
|
|
@@ -19,39 +19,39 @@ export declare class OINODbMsSql extends OINODb {
|
|
|
19
19
|
* @param sqlTable name of the table
|
|
20
20
|
*
|
|
21
21
|
*/
|
|
22
|
-
|
|
22
|
+
printTableName(sqlTable: string): string;
|
|
23
23
|
/**
|
|
24
24
|
* Print a column name with correct SQL escaping.
|
|
25
25
|
*
|
|
26
26
|
* @param sqlColumn name of the column
|
|
27
27
|
*
|
|
28
28
|
*/
|
|
29
|
-
|
|
29
|
+
printColumnName(sqlColumn: string): string;
|
|
30
30
|
/**
|
|
31
31
|
* Print a single data value from serialization using the context of the native data
|
|
32
32
|
* type with the correct SQL escaping.
|
|
33
33
|
*
|
|
34
34
|
* @param cellValue data from sql results
|
|
35
|
-
* @param
|
|
35
|
+
* @param nativeType native type name for table column
|
|
36
36
|
*
|
|
37
37
|
*/
|
|
38
|
-
|
|
38
|
+
printCellAsValue(cellValue: OINODataCell, nativeType: string): string;
|
|
39
39
|
/**
|
|
40
40
|
* Print a single string value as valid sql literal
|
|
41
41
|
*
|
|
42
42
|
* @param sqlString string value
|
|
43
43
|
*
|
|
44
44
|
*/
|
|
45
|
-
|
|
45
|
+
printStringValue(sqlString: string): string;
|
|
46
46
|
/**
|
|
47
47
|
* Parse a single SQL result value for serialization using the context of the native data
|
|
48
48
|
* type.
|
|
49
49
|
*
|
|
50
50
|
* @param sqlValue data from serialization
|
|
51
|
-
* @param
|
|
51
|
+
* @param nativeType native type name for table column
|
|
52
52
|
*
|
|
53
53
|
*/
|
|
54
|
-
|
|
54
|
+
parseValueAsCell(sqlValue: OINODataCell, nativeType: string): OINODataCell;
|
|
55
55
|
/**
|
|
56
56
|
* Print SQL select statement with DB specific formatting.
|
|
57
57
|
*
|
|
@@ -95,18 +95,18 @@ export declare class OINODbMsSql extends OINODb {
|
|
|
95
95
|
* @param sql SQL statement.
|
|
96
96
|
*
|
|
97
97
|
*/
|
|
98
|
-
sqlSelect(sql: string): Promise<
|
|
98
|
+
sqlSelect(sql: string): Promise<OINODataSet>;
|
|
99
99
|
/**
|
|
100
100
|
* Execute other sql operations.
|
|
101
101
|
*
|
|
102
102
|
* @param sql SQL statement.
|
|
103
103
|
*
|
|
104
104
|
*/
|
|
105
|
-
sqlExec(sql: string): Promise<
|
|
105
|
+
sqlExec(sql: string): Promise<OINODataSet>;
|
|
106
106
|
private _getSchemaSql;
|
|
107
107
|
private _getValidateSql;
|
|
108
108
|
/**
|
|
109
|
-
* Initialize a data model by getting the SQL schema and populating
|
|
109
|
+
* Initialize a data model by getting the SQL schema and populating OINODataFields of
|
|
110
110
|
* the model.
|
|
111
111
|
*
|
|
112
112
|
* @param api api which data model to initialize.
|