@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(db_1.OINO_ERROR_PREFIX + ": Invalid Posgresql data type!"); // TODO: maybe check all rows
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(db_1.OINO_ERROR_PREFIX + ": Not OINODbPostgresql-type: " + this._params.type);
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
- db_1.OINOLog.error("@oino-ts/db-postgresql", "OINODbPostgresql", ".on(error)", "Error-event", { err: err });
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
- const query_result = await this._pool.query({ rowMode: "array", text: sql });
116
- return Promise.resolve(query_result.rows);
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
- const query_result = await this._pool.query({ rowMode: "array", text: sql });
120
- if (Array.isArray(query_result) == true) {
121
- return Promise.resolve(query_result.flatMap((q) => q.rows));
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
- else if (query_result.rows) {
124
- return Promise.resolve(query_result.rows);
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
- else {
127
- return Promise.resolve(db_1.OINODB_EMPTY_ROWS); // return empty row if no rows returned
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 db_1.OINOResult();
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
- db_1.OINOLog.exception("@oino-ts/db-postgresql", "OINODbPostgresql", "connect", "exception in connect", { message: e.message, stack: e.stack });
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
- db_1.OINOBenchmark.startMetric("OINODb", "validate");
246
- let result = new db_1.OINOResult();
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.sqlSelect(sql);
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
- db_1.OINOLog.exception("@oino-ts/db-postgresql", "OINODbPostgresql", "validate", "exception in validate", { message: e.message, stack: e.stack });
312
+ common_1.OINOLog.exception("@oino-ts/db-postgresql", "OINODbPostgresql", "validate", "exception in validate", { message: e.message, stack: e.stack });
266
313
  }
267
- db_1.OINOBenchmark.endMetric("OINODb", "validate");
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
- db_1.OINOBenchmark.startMetric("OINODb", "sqlSelect");
278
- let result;
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
- db_1.OINOBenchmark.endMetric("OINODb", "sqlSelect");
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
- db_1.OINOBenchmark.startMetric("OINODb", "sqlExec");
297
- let result;
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
- db_1.OINOBenchmark.endMetric("OINODb", "sqlExec");
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.sqlSelect(this._getSchemaSql(this._params.database, api.params.tableName.toLowerCase()));
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
- db_1.OINOLog.info("@oino-ts/db-postgresql", "OINODbPostgresql", "initializeApiDatamodel", "Field excluded in API parameters.", { field: field_name });
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(db_1.OINO_ERROR_PREFIX + "Primary key field excluded in API parameters: " + field_name);
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
- db_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 });
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
- db_1.OINOLog.info("@oino-ts/db-postgresql", "OINODbPostgresql", "initializeApiDatamodel", "\n" + api.datamodel.printDebug("\n"));
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 { OINODb, OINODbDataSet, OINOBooleanDataField, OINONumberDataField, OINOStringDataField, OINO_ERROR_PREFIX, OINOBenchmark, OINODatetimeDataField, OINOBlobDataField, OINOLog, OINOResult, OINODB_EMPTY_ROW, OINODB_EMPTY_ROWS } from "@oino-ts/db";
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
- const query_result = await this._pool.query({ rowMode: "array", text: sql });
113
- return Promise.resolve(query_result.rows);
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
- const query_result = await this._pool.query({ rowMode: "array", text: sql });
117
- if (Array.isArray(query_result) == true) {
118
- return Promise.resolve(query_result.flatMap((q) => q.rows));
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
- else if (query_result.rows) {
121
- return Promise.resolve(query_result.rows);
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
- else {
124
- return Promise.resolve(OINODB_EMPTY_ROWS); // return empty row if no rows returned
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.sqlSelect(sql);
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
- OINOBenchmark.startMetric("OINODb", "sqlSelect");
275
- let result;
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
- OINOBenchmark.startMetric("OINODb", "sqlExec");
294
- let result;
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.sqlSelect(this._getSchemaSql(this._params.database, api.params.tableName.toLowerCase()));
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 { OINODb, OINODbParams, OINODbDataSet, OINODbApi, OINODataCell, OINOResult } from "@oino-ts/db";
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.18.1",
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.18.1",
23
+ "@oino-ts/db": "0.20.0",
24
24
  "pg": "^8.11.3"
25
25
  },
26
26
  "devDependencies": {
@@ -4,9 +4,10 @@
4
4
  * file, You can obtain one at https://mozilla.org/MPL/2.0/.
5
5
  */
6
6
 
7
- import { OINODb, OINODbParams, OINODbDataSet, OINODbApi, OINOBooleanDataField, OINONumberDataField, OINOStringDataField, OINODbDataFieldParams, OINO_ERROR_PREFIX, OINODataRow, OINODataCell, OINOBenchmark, OINODatetimeDataField, OINOBlobDataField, OINOLog, OINOResult, OINODB_EMPTY_ROW, OINODB_EMPTY_ROWS } from "@oino-ts/db";
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<OINODataRow[]> {
127
- const query_result:QueryResult = await this._pool.query({rowMode: "array", text: sql})
128
- return Promise.resolve(query_result.rows)
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<OINODataRow[]> {
132
- const query_result:QueryResult = await this._pool.query({rowMode: "array", text: sql})
133
- if (Array.isArray(query_result) == true) {
134
- return Promise.resolve(query_result.flatMap((q) => q.rows))
135
- } else if (query_result.rows) {
136
- return Promise.resolve(query_result.rows)
137
- } else {
138
- return Promise.resolve(OINODB_EMPTY_ROWS) // return empty row if no rows returned
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.sqlSelect(sql)
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
- OINOBenchmark.startMetric("OINODb", "sqlSelect")
295
- let result:OINODbDataSet
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
- OINOBenchmark.startMetric("OINODb", "sqlExec")
315
- let result:OINODbDataSet
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.sqlSelect(this._getSchemaSql(this._params.database, api.params.tableName.toLowerCase()))
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() || ""