@oino-ts/db-postgresql 0.18.1 → 0.20.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.
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
*/
|
|
7
7
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
8
|
exports.OINODbPostgresql = void 0;
|
|
9
|
+
const common_1 = require("@oino-ts/common");
|
|
9
10
|
const db_1 = require("@oino-ts/db");
|
|
10
11
|
const pg_1 = require("pg");
|
|
11
12
|
/**
|
|
@@ -21,7 +22,7 @@ class OINOPostgresqlData extends db_1.OINODbDataSet {
|
|
|
21
22
|
constructor(data, messages = []) {
|
|
22
23
|
super(data, messages);
|
|
23
24
|
if ((data != null) && !(Array.isArray(data))) {
|
|
24
|
-
throw new Error(
|
|
25
|
+
throw new Error(common_1.OINO_ERROR_PREFIX + ": Invalid Posgresql data type!"); // TODO: maybe check all rows
|
|
25
26
|
}
|
|
26
27
|
this._rows = data;
|
|
27
28
|
if (this.isEmpty()) {
|
|
@@ -95,13 +96,13 @@ class OINODbPostgresql extends db_1.OINODb {
|
|
|
95
96
|
constructor(params) {
|
|
96
97
|
super(params);
|
|
97
98
|
if (this._params.type !== "OINODbPostgresql") {
|
|
98
|
-
throw new Error(
|
|
99
|
+
throw new Error(common_1.OINO_ERROR_PREFIX + ": Not OINODbPostgresql-type: " + this._params.type);
|
|
99
100
|
}
|
|
100
101
|
const ssl_enabled = !(this._params.url == "localhost" || this._params.url == "127.0.0.1");
|
|
101
102
|
this._pool = new pg_1.Pool({ host: this._params.url, database: this._params.database, port: this._params.port, user: this._params.user, password: this._params.password, ssl: ssl_enabled });
|
|
102
103
|
delete this._params.password;
|
|
103
104
|
this._pool.on("error", (err) => {
|
|
104
|
-
|
|
105
|
+
common_1.OINOLog.error("@oino-ts/db-postgresql", "OINODbPostgresql", ".on(error)", "Error-event", { err: err });
|
|
105
106
|
});
|
|
106
107
|
}
|
|
107
108
|
_parseFieldLength(fieldLength) {
|
|
@@ -112,19 +113,56 @@ class OINODbPostgresql extends db_1.OINODb {
|
|
|
112
113
|
return result;
|
|
113
114
|
}
|
|
114
115
|
async _query(sql) {
|
|
115
|
-
|
|
116
|
-
|
|
116
|
+
let connection = null;
|
|
117
|
+
try {
|
|
118
|
+
connection = await this._pool.connect();
|
|
119
|
+
const query_result = await connection.query({ rowMode: "array", text: sql });
|
|
120
|
+
let rows;
|
|
121
|
+
if (Array.isArray(query_result) == true) {
|
|
122
|
+
rows = query_result.flatMap((q) => q.rows);
|
|
123
|
+
}
|
|
124
|
+
else if (query_result.rows) {
|
|
125
|
+
rows = query_result.rows;
|
|
126
|
+
}
|
|
127
|
+
else {
|
|
128
|
+
rows = db_1.OINODB_EMPTY_ROWS; // return empty row if no rows returned
|
|
129
|
+
}
|
|
130
|
+
return new OINOPostgresqlData(rows, []);
|
|
131
|
+
}
|
|
132
|
+
catch (e) {
|
|
133
|
+
return new OINOPostgresqlData(db_1.OINODB_EMPTY_ROWS, []).setError(500, common_1.OINO_ERROR_PREFIX + ": Exception in db query: " + e.message, "OINODbPostgresql._query");
|
|
134
|
+
}
|
|
135
|
+
finally {
|
|
136
|
+
if (connection) {
|
|
137
|
+
connection.release();
|
|
138
|
+
}
|
|
139
|
+
}
|
|
117
140
|
}
|
|
118
141
|
async _exec(sql) {
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
142
|
+
let connection = null;
|
|
143
|
+
try {
|
|
144
|
+
connection = await this._pool.connect();
|
|
145
|
+
const query_result = await connection.query({ rowMode: "array", text: sql });
|
|
146
|
+
let rows;
|
|
147
|
+
if (Array.isArray(query_result) == true) {
|
|
148
|
+
rows = query_result.flatMap((q) => q.rows);
|
|
149
|
+
}
|
|
150
|
+
else if (query_result.rows) {
|
|
151
|
+
rows = query_result.rows;
|
|
152
|
+
}
|
|
153
|
+
else {
|
|
154
|
+
rows = db_1.OINODB_EMPTY_ROWS; // return empty row if no rows returned
|
|
155
|
+
}
|
|
156
|
+
// if (rows.length > 0) { console.log("OINODbPostgresql._exec: rows", rows) }
|
|
157
|
+
return new OINOPostgresqlData(rows, []);
|
|
122
158
|
}
|
|
123
|
-
|
|
124
|
-
return
|
|
159
|
+
catch (e) {
|
|
160
|
+
return new OINOPostgresqlData(db_1.OINODB_EMPTY_ROWS, []).setError(500, common_1.OINO_ERROR_PREFIX + ": Exception in db exec: " + e.message, "OINODbPostgresql._exec");
|
|
125
161
|
}
|
|
126
|
-
|
|
127
|
-
|
|
162
|
+
finally {
|
|
163
|
+
if (connection) {
|
|
164
|
+
connection.release();
|
|
165
|
+
}
|
|
128
166
|
}
|
|
129
167
|
}
|
|
130
168
|
/**
|
|
@@ -225,15 +263,24 @@ class OINODbPostgresql extends db_1.OINODb {
|
|
|
225
263
|
*
|
|
226
264
|
*/
|
|
227
265
|
async connect() {
|
|
228
|
-
let result = new
|
|
266
|
+
let result = new common_1.OINOResult();
|
|
267
|
+
if (this.isConnected) {
|
|
268
|
+
return result;
|
|
269
|
+
}
|
|
270
|
+
let connection = null;
|
|
229
271
|
try {
|
|
230
272
|
// make sure that any items are correctly URL encoded in the connection string
|
|
231
|
-
await this._pool.connect();
|
|
273
|
+
connection = await this._pool.connect();
|
|
232
274
|
this.isConnected = true;
|
|
233
275
|
}
|
|
234
276
|
catch (e) {
|
|
235
277
|
result.setError(500, "Exception connecting to database: " + e.message, "OINODbPostgresql.connect");
|
|
236
|
-
|
|
278
|
+
common_1.OINOLog.exception("@oino-ts/db-postgresql", "OINODbPostgresql", "connect", "exception in connect", { message: e.message, stack: e.stack });
|
|
279
|
+
}
|
|
280
|
+
finally {
|
|
281
|
+
if (connection) {
|
|
282
|
+
connection.release();
|
|
283
|
+
}
|
|
237
284
|
}
|
|
238
285
|
return result;
|
|
239
286
|
}
|
|
@@ -242,11 +289,11 @@ class OINODbPostgresql extends db_1.OINODb {
|
|
|
242
289
|
*
|
|
243
290
|
*/
|
|
244
291
|
async validate() {
|
|
245
|
-
|
|
246
|
-
let result = new
|
|
292
|
+
common_1.OINOBenchmark.startMetric("OINODb", "validate");
|
|
293
|
+
let result = new common_1.OINOResult();
|
|
247
294
|
try {
|
|
248
295
|
const sql = this._getValidateSql(this._params.database);
|
|
249
|
-
const sql_res = await this.
|
|
296
|
+
const sql_res = await this._query(sql);
|
|
250
297
|
if (sql_res.isEmpty()) {
|
|
251
298
|
result.setError(400, "DB returned no rows for select!", "OINODbPostgresql.validate");
|
|
252
299
|
}
|
|
@@ -262,11 +309,24 @@ class OINODbPostgresql extends db_1.OINODb {
|
|
|
262
309
|
}
|
|
263
310
|
catch (e) {
|
|
264
311
|
result.setError(500, "Exception validating connection: " + e.message, "OINODbPostgresql.validate");
|
|
265
|
-
|
|
312
|
+
common_1.OINOLog.exception("@oino-ts/db-postgresql", "OINODbPostgresql", "validate", "exception in validate", { message: e.message, stack: e.stack });
|
|
266
313
|
}
|
|
267
|
-
|
|
314
|
+
common_1.OINOBenchmark.endMetric("OINODb", "validate");
|
|
268
315
|
return result;
|
|
269
316
|
}
|
|
317
|
+
/**
|
|
318
|
+
* Disconnect from database.
|
|
319
|
+
*
|
|
320
|
+
*/
|
|
321
|
+
async disconnect() {
|
|
322
|
+
if (this.isConnected) {
|
|
323
|
+
this._pool.end().catch((e) => {
|
|
324
|
+
common_1.OINOLog.exception("@oino-ts/db-postgresql", "OINODbPostgresql", "disconnect", "exception in pool end", { message: e.message, stack: e.stack });
|
|
325
|
+
});
|
|
326
|
+
}
|
|
327
|
+
this.isConnected = false;
|
|
328
|
+
this.isValidated = false;
|
|
329
|
+
}
|
|
270
330
|
/**
|
|
271
331
|
* Execute a select operation.
|
|
272
332
|
*
|
|
@@ -274,16 +334,12 @@ class OINODbPostgresql extends db_1.OINODb {
|
|
|
274
334
|
*
|
|
275
335
|
*/
|
|
276
336
|
async sqlSelect(sql) {
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
try {
|
|
280
|
-
const rows = await this._query(sql);
|
|
281
|
-
result = new OINOPostgresqlData(rows, []);
|
|
282
|
-
}
|
|
283
|
-
catch (e) {
|
|
284
|
-
result = new OINOPostgresqlData(db_1.OINODB_EMPTY_ROWS, [db_1.OINO_ERROR_PREFIX + " (sqlSelect): exception in _db.query [" + e.message + "]"]);
|
|
337
|
+
if (!this.isValidated) {
|
|
338
|
+
throw new Error(common_1.OINO_ERROR_PREFIX + ": Database connection not validated!");
|
|
285
339
|
}
|
|
286
|
-
|
|
340
|
+
common_1.OINOBenchmark.startMetric("OINODb", "sqlSelect");
|
|
341
|
+
let result = await this._query(sql);
|
|
342
|
+
common_1.OINOBenchmark.endMetric("OINODb", "sqlSelect");
|
|
287
343
|
return result;
|
|
288
344
|
}
|
|
289
345
|
/**
|
|
@@ -293,16 +349,12 @@ class OINODbPostgresql extends db_1.OINODb {
|
|
|
293
349
|
*
|
|
294
350
|
*/
|
|
295
351
|
async sqlExec(sql) {
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
try {
|
|
299
|
-
const rows = await this._exec(sql);
|
|
300
|
-
result = new OINOPostgresqlData(rows, []);
|
|
301
|
-
}
|
|
302
|
-
catch (e) {
|
|
303
|
-
result = new OINOPostgresqlData(db_1.OINODB_EMPTY_ROWS, [db_1.OINO_ERROR_PREFIX + " (sqlExec): exception in _db.exec [" + e.message + "]"]);
|
|
352
|
+
if (!this.isValidated) {
|
|
353
|
+
throw new Error(common_1.OINO_ERROR_PREFIX + ": Database connection not validated!");
|
|
304
354
|
}
|
|
305
|
-
|
|
355
|
+
common_1.OINOBenchmark.startMetric("OINODb", "sqlExec");
|
|
356
|
+
let result = await this._exec(sql);
|
|
357
|
+
common_1.OINOBenchmark.endMetric("OINODb", "sqlExec");
|
|
306
358
|
return result;
|
|
307
359
|
}
|
|
308
360
|
_getSchemaSql(dbName, tableName) {
|
|
@@ -358,7 +410,7 @@ WHERE col.table_catalog = '${dbName}'`;
|
|
|
358
410
|
*
|
|
359
411
|
*/
|
|
360
412
|
async initializeApiDatamodel(api) {
|
|
361
|
-
const schema_res = await this.
|
|
413
|
+
const schema_res = await this._query(this._getSchemaSql(this._params.database, api.params.tableName.toLowerCase()));
|
|
362
414
|
while (!schema_res.isEof()) {
|
|
363
415
|
const row = schema_res.getRow();
|
|
364
416
|
const field_name = row[0]?.toString() || "";
|
|
@@ -375,9 +427,9 @@ WHERE col.table_catalog = '${dbName}'`;
|
|
|
375
427
|
isAutoInc: default_val.startsWith("nextval(")
|
|
376
428
|
};
|
|
377
429
|
if (api.isFieldIncluded(field_name) == false) {
|
|
378
|
-
|
|
430
|
+
common_1.OINOLog.info("@oino-ts/db-postgresql", "OINODbPostgresql", "initializeApiDatamodel", "Field excluded in API parameters.", { field: field_name });
|
|
379
431
|
if (field_params.isPrimaryKey) {
|
|
380
|
-
throw new Error(
|
|
432
|
+
throw new Error(common_1.OINO_ERROR_PREFIX + "Primary key field excluded in API parameters: " + field_name);
|
|
381
433
|
}
|
|
382
434
|
}
|
|
383
435
|
else {
|
|
@@ -405,13 +457,13 @@ WHERE col.table_catalog = '${dbName}'`;
|
|
|
405
457
|
api.datamodel.addField(new db_1.OINOStringDataField(this, field_name, sql_type, field_params, numeric_precision + numeric_scale + 1));
|
|
406
458
|
}
|
|
407
459
|
else {
|
|
408
|
-
|
|
460
|
+
common_1.OINOLog.info("@oino-ts/db-postgresql", "OINODbPostgresql", "initializeApiDatamodel", "Unrecognized field type treated as string", { field_name: field_name, sql_type: sql_type, field_length: field_length, field_params: field_params });
|
|
409
461
|
api.datamodel.addField(new db_1.OINOStringDataField(this, field_name, sql_type, field_params, 0));
|
|
410
462
|
}
|
|
411
463
|
}
|
|
412
464
|
await schema_res.next();
|
|
413
465
|
}
|
|
414
|
-
|
|
466
|
+
common_1.OINOLog.info("@oino-ts/db-postgresql", "OINODbPostgresql", "initializeApiDatamodel", "\n" + api.datamodel.printDebug("\n"));
|
|
415
467
|
return Promise.resolve();
|
|
416
468
|
}
|
|
417
469
|
}
|
|
@@ -3,7 +3,8 @@
|
|
|
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 {
|
|
6
|
+
import { OINO_ERROR_PREFIX, OINOBenchmark, OINOLog, OINOResult } from "@oino-ts/common";
|
|
7
|
+
import { OINODb, OINODbDataSet, OINOBooleanDataField, OINONumberDataField, OINOStringDataField, OINODatetimeDataField, OINOBlobDataField, OINODB_EMPTY_ROW, OINODB_EMPTY_ROWS } from "@oino-ts/db";
|
|
7
8
|
import { Pool } from "pg";
|
|
8
9
|
/**
|
|
9
10
|
* Implmentation of OINODbDataSet for Postgresql.
|
|
@@ -109,19 +110,56 @@ export class OINODbPostgresql extends OINODb {
|
|
|
109
110
|
return result;
|
|
110
111
|
}
|
|
111
112
|
async _query(sql) {
|
|
112
|
-
|
|
113
|
-
|
|
113
|
+
let connection = null;
|
|
114
|
+
try {
|
|
115
|
+
connection = await this._pool.connect();
|
|
116
|
+
const query_result = await connection.query({ rowMode: "array", text: sql });
|
|
117
|
+
let rows;
|
|
118
|
+
if (Array.isArray(query_result) == true) {
|
|
119
|
+
rows = query_result.flatMap((q) => q.rows);
|
|
120
|
+
}
|
|
121
|
+
else if (query_result.rows) {
|
|
122
|
+
rows = query_result.rows;
|
|
123
|
+
}
|
|
124
|
+
else {
|
|
125
|
+
rows = OINODB_EMPTY_ROWS; // return empty row if no rows returned
|
|
126
|
+
}
|
|
127
|
+
return new OINOPostgresqlData(rows, []);
|
|
128
|
+
}
|
|
129
|
+
catch (e) {
|
|
130
|
+
return new OINOPostgresqlData(OINODB_EMPTY_ROWS, []).setError(500, OINO_ERROR_PREFIX + ": Exception in db query: " + e.message, "OINODbPostgresql._query");
|
|
131
|
+
}
|
|
132
|
+
finally {
|
|
133
|
+
if (connection) {
|
|
134
|
+
connection.release();
|
|
135
|
+
}
|
|
136
|
+
}
|
|
114
137
|
}
|
|
115
138
|
async _exec(sql) {
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
139
|
+
let connection = null;
|
|
140
|
+
try {
|
|
141
|
+
connection = await this._pool.connect();
|
|
142
|
+
const query_result = await connection.query({ rowMode: "array", text: sql });
|
|
143
|
+
let rows;
|
|
144
|
+
if (Array.isArray(query_result) == true) {
|
|
145
|
+
rows = query_result.flatMap((q) => q.rows);
|
|
146
|
+
}
|
|
147
|
+
else if (query_result.rows) {
|
|
148
|
+
rows = query_result.rows;
|
|
149
|
+
}
|
|
150
|
+
else {
|
|
151
|
+
rows = OINODB_EMPTY_ROWS; // return empty row if no rows returned
|
|
152
|
+
}
|
|
153
|
+
// if (rows.length > 0) { console.log("OINODbPostgresql._exec: rows", rows) }
|
|
154
|
+
return new OINOPostgresqlData(rows, []);
|
|
119
155
|
}
|
|
120
|
-
|
|
121
|
-
return
|
|
156
|
+
catch (e) {
|
|
157
|
+
return new OINOPostgresqlData(OINODB_EMPTY_ROWS, []).setError(500, OINO_ERROR_PREFIX + ": Exception in db exec: " + e.message, "OINODbPostgresql._exec");
|
|
122
158
|
}
|
|
123
|
-
|
|
124
|
-
|
|
159
|
+
finally {
|
|
160
|
+
if (connection) {
|
|
161
|
+
connection.release();
|
|
162
|
+
}
|
|
125
163
|
}
|
|
126
164
|
}
|
|
127
165
|
/**
|
|
@@ -223,15 +261,24 @@ export class OINODbPostgresql extends OINODb {
|
|
|
223
261
|
*/
|
|
224
262
|
async connect() {
|
|
225
263
|
let result = new OINOResult();
|
|
264
|
+
if (this.isConnected) {
|
|
265
|
+
return result;
|
|
266
|
+
}
|
|
267
|
+
let connection = null;
|
|
226
268
|
try {
|
|
227
269
|
// make sure that any items are correctly URL encoded in the connection string
|
|
228
|
-
await this._pool.connect();
|
|
270
|
+
connection = await this._pool.connect();
|
|
229
271
|
this.isConnected = true;
|
|
230
272
|
}
|
|
231
273
|
catch (e) {
|
|
232
274
|
result.setError(500, "Exception connecting to database: " + e.message, "OINODbPostgresql.connect");
|
|
233
275
|
OINOLog.exception("@oino-ts/db-postgresql", "OINODbPostgresql", "connect", "exception in connect", { message: e.message, stack: e.stack });
|
|
234
276
|
}
|
|
277
|
+
finally {
|
|
278
|
+
if (connection) {
|
|
279
|
+
connection.release();
|
|
280
|
+
}
|
|
281
|
+
}
|
|
235
282
|
return result;
|
|
236
283
|
}
|
|
237
284
|
/**
|
|
@@ -243,7 +290,7 @@ export class OINODbPostgresql extends OINODb {
|
|
|
243
290
|
let result = new OINOResult();
|
|
244
291
|
try {
|
|
245
292
|
const sql = this._getValidateSql(this._params.database);
|
|
246
|
-
const sql_res = await this.
|
|
293
|
+
const sql_res = await this._query(sql);
|
|
247
294
|
if (sql_res.isEmpty()) {
|
|
248
295
|
result.setError(400, "DB returned no rows for select!", "OINODbPostgresql.validate");
|
|
249
296
|
}
|
|
@@ -264,6 +311,19 @@ export class OINODbPostgresql extends OINODb {
|
|
|
264
311
|
OINOBenchmark.endMetric("OINODb", "validate");
|
|
265
312
|
return result;
|
|
266
313
|
}
|
|
314
|
+
/**
|
|
315
|
+
* Disconnect from database.
|
|
316
|
+
*
|
|
317
|
+
*/
|
|
318
|
+
async disconnect() {
|
|
319
|
+
if (this.isConnected) {
|
|
320
|
+
this._pool.end().catch((e) => {
|
|
321
|
+
OINOLog.exception("@oino-ts/db-postgresql", "OINODbPostgresql", "disconnect", "exception in pool end", { message: e.message, stack: e.stack });
|
|
322
|
+
});
|
|
323
|
+
}
|
|
324
|
+
this.isConnected = false;
|
|
325
|
+
this.isValidated = false;
|
|
326
|
+
}
|
|
267
327
|
/**
|
|
268
328
|
* Execute a select operation.
|
|
269
329
|
*
|
|
@@ -271,15 +331,11 @@ export class OINODbPostgresql extends OINODb {
|
|
|
271
331
|
*
|
|
272
332
|
*/
|
|
273
333
|
async sqlSelect(sql) {
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
try {
|
|
277
|
-
const rows = await this._query(sql);
|
|
278
|
-
result = new OINOPostgresqlData(rows, []);
|
|
279
|
-
}
|
|
280
|
-
catch (e) {
|
|
281
|
-
result = new OINOPostgresqlData(OINODB_EMPTY_ROWS, [OINO_ERROR_PREFIX + " (sqlSelect): exception in _db.query [" + e.message + "]"]);
|
|
334
|
+
if (!this.isValidated) {
|
|
335
|
+
throw new Error(OINO_ERROR_PREFIX + ": Database connection not validated!");
|
|
282
336
|
}
|
|
337
|
+
OINOBenchmark.startMetric("OINODb", "sqlSelect");
|
|
338
|
+
let result = await this._query(sql);
|
|
283
339
|
OINOBenchmark.endMetric("OINODb", "sqlSelect");
|
|
284
340
|
return result;
|
|
285
341
|
}
|
|
@@ -290,15 +346,11 @@ export class OINODbPostgresql extends OINODb {
|
|
|
290
346
|
*
|
|
291
347
|
*/
|
|
292
348
|
async sqlExec(sql) {
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
try {
|
|
296
|
-
const rows = await this._exec(sql);
|
|
297
|
-
result = new OINOPostgresqlData(rows, []);
|
|
298
|
-
}
|
|
299
|
-
catch (e) {
|
|
300
|
-
result = new OINOPostgresqlData(OINODB_EMPTY_ROWS, [OINO_ERROR_PREFIX + " (sqlExec): exception in _db.exec [" + e.message + "]"]);
|
|
349
|
+
if (!this.isValidated) {
|
|
350
|
+
throw new Error(OINO_ERROR_PREFIX + ": Database connection not validated!");
|
|
301
351
|
}
|
|
352
|
+
OINOBenchmark.startMetric("OINODb", "sqlExec");
|
|
353
|
+
let result = await this._exec(sql);
|
|
302
354
|
OINOBenchmark.endMetric("OINODb", "sqlExec");
|
|
303
355
|
return result;
|
|
304
356
|
}
|
|
@@ -355,7 +407,7 @@ WHERE col.table_catalog = '${dbName}'`;
|
|
|
355
407
|
*
|
|
356
408
|
*/
|
|
357
409
|
async initializeApiDatamodel(api) {
|
|
358
|
-
const schema_res = await this.
|
|
410
|
+
const schema_res = await this._query(this._getSchemaSql(this._params.database, api.params.tableName.toLowerCase()));
|
|
359
411
|
while (!schema_res.isEof()) {
|
|
360
412
|
const row = schema_res.getRow();
|
|
361
413
|
const field_name = row[0]?.toString() || "";
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { OINOResult } from "@oino-ts/common";
|
|
2
|
+
import { OINODb, OINODbParams, OINODbDataSet, OINODbApi, OINODataCell } from "@oino-ts/db";
|
|
2
3
|
/**
|
|
3
4
|
* Implementation of Postgresql-database.
|
|
4
5
|
*
|
|
@@ -62,6 +63,11 @@ export declare class OINODbPostgresql extends OINODb {
|
|
|
62
63
|
*
|
|
63
64
|
*/
|
|
64
65
|
validate(): Promise<OINOResult>;
|
|
66
|
+
/**
|
|
67
|
+
* Disconnect from database.
|
|
68
|
+
*
|
|
69
|
+
*/
|
|
70
|
+
disconnect(): Promise<void>;
|
|
65
71
|
/**
|
|
66
72
|
* Execute a select operation.
|
|
67
73
|
*
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@oino-ts/db-postgresql",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.20.0",
|
|
4
4
|
"description": "OINO TS package for using Postgresql databases.",
|
|
5
5
|
"author": "Matias Kiviniemi (pragmatta)",
|
|
6
6
|
"license": "MPL-2.0",
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
"module": "./dist/esm/index.js",
|
|
21
21
|
"types": "./dist/types/index.d.ts",
|
|
22
22
|
"dependencies": {
|
|
23
|
-
"@oino-ts/db": "0.
|
|
23
|
+
"@oino-ts/db": "0.20.0",
|
|
24
24
|
"pg": "^8.11.3"
|
|
25
25
|
},
|
|
26
26
|
"devDependencies": {
|
package/src/OINODbPostgresql.ts
CHANGED
|
@@ -4,9 +4,10 @@
|
|
|
4
4
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
import {
|
|
7
|
+
import { OINO_ERROR_PREFIX, OINOBenchmark, OINOLog, OINOResult } from "@oino-ts/common";
|
|
8
|
+
import { OINODb, OINODbParams, OINODbDataSet, OINODbApi, OINOBooleanDataField, OINONumberDataField, OINOStringDataField, OINODbDataFieldParams, OINODataRow, OINODataCell, OINODatetimeDataField, OINOBlobDataField, OINODB_EMPTY_ROW, OINODB_EMPTY_ROWS } from "@oino-ts/db";
|
|
8
9
|
|
|
9
|
-
import { Pool, QueryResult } from "pg";
|
|
10
|
+
import { Pool, PoolClient, QueryResult } from "pg";
|
|
10
11
|
|
|
11
12
|
|
|
12
13
|
/**
|
|
@@ -123,19 +124,50 @@ export class OINODbPostgresql extends OINODb {
|
|
|
123
124
|
return result
|
|
124
125
|
}
|
|
125
126
|
|
|
126
|
-
private async _query(sql:string):Promise<
|
|
127
|
-
|
|
128
|
-
|
|
127
|
+
private async _query(sql:string):Promise<OINODbDataSet> {
|
|
128
|
+
let connection:PoolClient|null = null
|
|
129
|
+
try {
|
|
130
|
+
connection = await this._pool.connect()
|
|
131
|
+
const query_result = await connection.query({rowMode: "array", text: sql})
|
|
132
|
+
let rows:OINODataRow[]
|
|
133
|
+
if (Array.isArray(query_result) == true) {
|
|
134
|
+
rows = query_result.flatMap((q) => q.rows)
|
|
135
|
+
} else if (query_result.rows) {
|
|
136
|
+
rows = query_result.rows
|
|
137
|
+
} else {
|
|
138
|
+
rows = OINODB_EMPTY_ROWS // return empty row if no rows returned
|
|
139
|
+
}
|
|
140
|
+
return new OINOPostgresqlData(rows, [])
|
|
141
|
+
} catch (e:any) {
|
|
142
|
+
return new OINOPostgresqlData(OINODB_EMPTY_ROWS, []).setError(500, OINO_ERROR_PREFIX + ": Exception in db query: " + e.message, "OINODbPostgresql._query") as OINOPostgresqlData
|
|
143
|
+
} finally {
|
|
144
|
+
if (connection) {
|
|
145
|
+
connection.release()
|
|
146
|
+
}
|
|
147
|
+
}
|
|
129
148
|
}
|
|
130
149
|
|
|
131
|
-
private async _exec(sql:string):Promise<
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
150
|
+
private async _exec(sql:string):Promise<OINODbDataSet> {
|
|
151
|
+
let connection:PoolClient|null = null
|
|
152
|
+
try {
|
|
153
|
+
connection = await this._pool.connect()
|
|
154
|
+
const query_result:QueryResult = await connection.query({rowMode: "array", text: sql})
|
|
155
|
+
let rows:OINODataRow[]
|
|
156
|
+
if (Array.isArray(query_result) == true) {
|
|
157
|
+
rows = query_result.flatMap((q) => q.rows)
|
|
158
|
+
} else if (query_result.rows) {
|
|
159
|
+
rows = query_result.rows
|
|
160
|
+
} else {
|
|
161
|
+
rows = OINODB_EMPTY_ROWS // return empty row if no rows returned
|
|
162
|
+
}
|
|
163
|
+
// if (rows.length > 0) { console.log("OINODbPostgresql._exec: rows", rows) }
|
|
164
|
+
return new OINOPostgresqlData(rows, [])
|
|
165
|
+
} catch (e:any) {
|
|
166
|
+
return new OINOPostgresqlData(OINODB_EMPTY_ROWS, []).setError(500, OINO_ERROR_PREFIX + ": Exception in db exec: " + e.message, "OINODbPostgresql._exec") as OINOPostgresqlData
|
|
167
|
+
} finally {
|
|
168
|
+
if (connection) {
|
|
169
|
+
connection.release()
|
|
170
|
+
}
|
|
139
171
|
}
|
|
140
172
|
}
|
|
141
173
|
|
|
@@ -242,15 +274,24 @@ export class OINODbPostgresql extends OINODb {
|
|
|
242
274
|
*/
|
|
243
275
|
async connect(): Promise<OINOResult> {
|
|
244
276
|
let result:OINOResult = new OINOResult()
|
|
277
|
+
if (this.isConnected) {
|
|
278
|
+
return result
|
|
279
|
+
}
|
|
280
|
+
let connection:PoolClient|null = null
|
|
245
281
|
try {
|
|
246
282
|
// make sure that any items are correctly URL encoded in the connection string
|
|
247
|
-
await this._pool.connect()
|
|
283
|
+
connection = await this._pool.connect()
|
|
248
284
|
this.isConnected = true
|
|
249
285
|
|
|
250
286
|
} catch (e:any) {
|
|
251
287
|
result.setError(500, "Exception connecting to database: " + e.message, "OINODbPostgresql.connect")
|
|
252
288
|
OINOLog.exception("@oino-ts/db-postgresql", "OINODbPostgresql", "connect", "exception in connect", {message:e.message, stack:e.stack})
|
|
253
|
-
}
|
|
289
|
+
} finally {
|
|
290
|
+
if (connection) {
|
|
291
|
+
connection.release()
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
|
|
254
295
|
return result
|
|
255
296
|
}
|
|
256
297
|
|
|
@@ -263,7 +304,7 @@ export class OINODbPostgresql extends OINODb {
|
|
|
263
304
|
let result:OINOResult = new OINOResult()
|
|
264
305
|
try {
|
|
265
306
|
const sql = this._getValidateSql(this._params.database)
|
|
266
|
-
const sql_res:OINODbDataSet = await this.
|
|
307
|
+
const sql_res:OINODbDataSet = await this._query(sql)
|
|
267
308
|
if (sql_res.isEmpty()) {
|
|
268
309
|
result.setError(400, "DB returned no rows for select!", "OINODbPostgresql.validate")
|
|
269
310
|
|
|
@@ -284,6 +325,21 @@ export class OINODbPostgresql extends OINODb {
|
|
|
284
325
|
return result
|
|
285
326
|
}
|
|
286
327
|
|
|
328
|
+
/**
|
|
329
|
+
* Disconnect from database.
|
|
330
|
+
*
|
|
331
|
+
*/
|
|
332
|
+
async disconnect(): Promise<void> {
|
|
333
|
+
if (this.isConnected) {
|
|
334
|
+
this._pool.end().catch((e:any) => {
|
|
335
|
+
OINOLog.exception("@oino-ts/db-postgresql", "OINODbPostgresql", "disconnect", "exception in pool end", {message:e.message, stack:e.stack})
|
|
336
|
+
})
|
|
337
|
+
}
|
|
338
|
+
this.isConnected = false
|
|
339
|
+
this.isValidated = false
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
|
|
287
343
|
/**
|
|
288
344
|
* Execute a select operation.
|
|
289
345
|
*
|
|
@@ -291,15 +347,11 @@ export class OINODbPostgresql extends OINODb {
|
|
|
291
347
|
*
|
|
292
348
|
*/
|
|
293
349
|
async sqlSelect(sql:string): Promise<OINODbDataSet> {
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
try {
|
|
297
|
-
const rows:OINODataRow[] = await this._query(sql)
|
|
298
|
-
result = new OINOPostgresqlData(rows, [])
|
|
299
|
-
|
|
300
|
-
} catch (e:any) {
|
|
301
|
-
result = new OINOPostgresqlData(OINODB_EMPTY_ROWS, [OINO_ERROR_PREFIX + " (sqlSelect): exception in _db.query [" + e.message + "]"])
|
|
350
|
+
if (!this.isValidated) {
|
|
351
|
+
throw new Error(OINO_ERROR_PREFIX + ": Database connection not validated!")
|
|
302
352
|
}
|
|
353
|
+
OINOBenchmark.startMetric("OINODb", "sqlSelect")
|
|
354
|
+
let result:OINODbDataSet = await this._query(sql)
|
|
303
355
|
OINOBenchmark.endMetric("OINODb", "sqlSelect")
|
|
304
356
|
return result
|
|
305
357
|
}
|
|
@@ -311,15 +363,11 @@ export class OINODbPostgresql extends OINODb {
|
|
|
311
363
|
*
|
|
312
364
|
*/
|
|
313
365
|
async sqlExec(sql:string): Promise<OINODbDataSet> {
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
try {
|
|
317
|
-
const rows:OINODataRow[] = await this._exec(sql)
|
|
318
|
-
result = new OINOPostgresqlData(rows, [])
|
|
319
|
-
|
|
320
|
-
} catch (e:any) {
|
|
321
|
-
result = new OINOPostgresqlData(OINODB_EMPTY_ROWS, [OINO_ERROR_PREFIX + " (sqlExec): exception in _db.exec [" + e.message + "]"])
|
|
366
|
+
if (!this.isValidated) {
|
|
367
|
+
throw new Error(OINO_ERROR_PREFIX + ": Database connection not validated!")
|
|
322
368
|
}
|
|
369
|
+
OINOBenchmark.startMetric("OINODb", "sqlExec")
|
|
370
|
+
let result:OINODbDataSet = await this._exec(sql)
|
|
323
371
|
OINOBenchmark.endMetric("OINODb", "sqlExec")
|
|
324
372
|
return result
|
|
325
373
|
}
|
|
@@ -382,7 +430,7 @@ WHERE col.table_catalog = '${dbName}'`
|
|
|
382
430
|
*/
|
|
383
431
|
async initializeApiDatamodel(api:OINODbApi): Promise<void> {
|
|
384
432
|
|
|
385
|
-
const schema_res:OINODbDataSet = await this.
|
|
433
|
+
const schema_res:OINODbDataSet = await this._query(this._getSchemaSql(this._params.database, api.params.tableName.toLowerCase()))
|
|
386
434
|
while (!schema_res.isEof()) {
|
|
387
435
|
const row:OINODataRow = schema_res.getRow()
|
|
388
436
|
const field_name:string = row[0]?.toString() || ""
|