pogi 2.10.2 → 3.0.0-beta2
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/.vscode/launch.json +47 -15
- package/CHANGELOG.md +11 -0
- package/docs/API/PgDb.md +25 -0
- package/docs/notification.md +19 -0
- package/jest.config.js +23 -0
- package/lib/bin/generateInterface.js +3 -3
- package/lib/bin/generateInterface.js.map +1 -1
- package/lib/connectionOptions.d.ts +10 -0
- package/lib/index.d.ts +1 -1
- package/lib/pgConverters.d.ts +9 -8
- package/lib/pgConverters.js +46 -32
- package/lib/pgConverters.js.map +1 -1
- package/lib/pgConverters.test.d.ts +1 -0
- package/lib/pgConverters.test.js +13 -0
- package/lib/pgConverters.test.js.map +1 -0
- package/lib/pgDb.d.ts +27 -27
- package/lib/pgDb.js +293 -100
- package/lib/pgDb.js.map +1 -1
- package/lib/pgDb.test.d.ts +1 -0
- package/lib/pgDb.test.js +1126 -0
- package/lib/pgDb.test.js.map +1 -0
- package/lib/pgDbInterface.d.ts +53 -0
- package/lib/pgDbInterface.js +11 -0
- package/lib/pgDbInterface.js.map +1 -0
- package/lib/pgDbOperators.d.ts +3 -3
- package/lib/pgDbOperators.js +4 -7
- package/lib/pgDbOperators.js.map +1 -1
- package/lib/pgDbOperators.test.d.ts +1 -0
- package/lib/pgDbOperators.test.js +313 -0
- package/lib/pgDbOperators.test.js.map +1 -0
- package/lib/pgSchema.d.ts +10 -9
- package/lib/pgSchema.js.map +1 -1
- package/lib/pgSchemaInterface.d.ts +12 -0
- package/lib/pgSchemaInterface.js +3 -0
- package/lib/pgSchemaInterface.js.map +1 -0
- package/lib/pgTable.d.ts +15 -40
- package/lib/pgTable.js +54 -54
- package/lib/pgTable.js.map +1 -1
- package/lib/pgTableInterface.d.ts +102 -0
- package/lib/pgTableInterface.js +4 -0
- package/lib/pgTableInterface.js.map +1 -0
- package/lib/pgUtils.d.ts +16 -6
- package/lib/pgUtils.js +162 -31
- package/lib/pgUtils.js.map +1 -1
- package/lib/queryAble.d.ts +20 -53
- package/lib/queryAble.js +149 -80
- package/lib/queryAble.js.map +1 -1
- package/lib/queryAbleInterface.d.ts +55 -0
- package/lib/queryAbleInterface.js +7 -0
- package/lib/queryAbleInterface.js.map +1 -0
- package/lib/queryWhere.d.ts +2 -2
- package/lib/queryWhere.js +19 -23
- package/lib/queryWhere.js.map +1 -1
- package/mkdocs.yml +1 -0
- package/package.json +21 -11
- package/src/bin/generateInterface.ts +2 -2
- package/src/connectionOptions.ts +48 -13
- package/src/index.d.ts +7 -0
- package/src/index.ts +1 -1
- package/src/pgConverters.test.ts +10 -0
- package/src/pgConverters.ts +34 -22
- package/src/pgDb.test.ts +1324 -0
- package/src/pgDb.ts +318 -122
- package/src/pgDbInterface.ts +57 -0
- package/src/pgDbOperators.test.ts +478 -0
- package/src/pgDbOperators.ts +45 -22
- package/src/pgSchema.ts +10 -9
- package/src/pgSchemaInterface.ts +12 -0
- package/src/pgTable.ts +66 -98
- package/src/pgTableInterface.ts +131 -0
- package/src/pgUtils.ts +166 -42
- package/src/queryAble.ts +167 -125
- package/src/queryAbleInterface.ts +104 -0
- package/src/queryWhere.ts +42 -43
- package/{spec/resources → src/test}/init.sql +23 -0
- package/src/test/pgServiceRestartTest.ts +1500 -0
- package/{spec/resources → src/test}/throw_exception.sql +0 -0
- package/{spec/resources → src/test}/tricky.sql +0 -0
- package/{src/tsconfig.json → tsconfig.json} +12 -11
- package/spec/run.js +0 -5
- package/spec/support/jasmine.json +0 -9
- package/src/test/pgDbOperatorSpec.ts +0 -492
- package/src/test/pgDbSpec.ts +0 -994
package/lib/pgDb.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.PgDb = exports.
|
|
3
|
+
exports.PgDb = exports.FieldType = void 0;
|
|
4
4
|
const tslib_1 = require("tslib");
|
|
5
5
|
const queryAble_1 = require("./queryAble");
|
|
6
6
|
const pgTable_1 = require("./pgTable");
|
|
@@ -32,13 +32,20 @@ FROM pg_proc p
|
|
|
32
32
|
WHERE n.nspname NOT IN ('pg_catalog', 'pg_constraint', 'information_schema')
|
|
33
33
|
AND tr.oid is null;`;
|
|
34
34
|
const GET_CURRENT_SCHEMAS = "SELECT current_schemas(false)";
|
|
35
|
-
const LIST_SPECIAL_TYPE_FIELDS = `SELECT c.nspname as schema_name, b.relname as table_name, a.attname as column_name, a.atttypid as typid
|
|
35
|
+
const LIST_SPECIAL_TYPE_FIELDS = `SELECT c.nspname as schema_name, b.relname as table_name, a.attname as column_name, a.atttypid as typid, t.typcategory
|
|
36
36
|
FROM pg_attribute a
|
|
37
37
|
JOIN pg_class b ON (a.attrelid = b.oid)
|
|
38
38
|
JOIN pg_type t ON (a.atttypid = t.oid)
|
|
39
39
|
JOIN pg_namespace c ON (b.relnamespace=c.oid)
|
|
40
40
|
WHERE (a.atttypid in (114, 3802, 1082, 1083, 1114, 1184, 1266, 3614) or t.typcategory='A')
|
|
41
41
|
AND reltype>0 `;
|
|
42
|
+
const TYPE2OID = `SELECT t.oid, typname FROM pg_catalog.pg_type t WHERE typname in (
|
|
43
|
+
'_bool',
|
|
44
|
+
'int8','_int2','_int4','_int8','_float4','float8','_float8',
|
|
45
|
+
'_text','_varchar',
|
|
46
|
+
'json','jsonb', '_json','_jsonb',
|
|
47
|
+
'date','time','timestamp','timestamptz','timetz','_date','_time','_timestamp','_timestamptz','_timetz',
|
|
48
|
+
'tsvector')`;
|
|
42
49
|
var FieldType;
|
|
43
50
|
(function (FieldType) {
|
|
44
51
|
FieldType[FieldType["JSON"] = 0] = "JSON";
|
|
@@ -46,25 +53,29 @@ var FieldType;
|
|
|
46
53
|
FieldType[FieldType["TIME"] = 2] = "TIME";
|
|
47
54
|
FieldType[FieldType["TSVECTOR"] = 3] = "TSVECTOR";
|
|
48
55
|
})(FieldType = exports.FieldType || (exports.FieldType = {}));
|
|
49
|
-
var TranzactionIsolationLevel;
|
|
50
|
-
(function (TranzactionIsolationLevel) {
|
|
51
|
-
TranzactionIsolationLevel["serializable"] = "SERIALIZABLE";
|
|
52
|
-
TranzactionIsolationLevel["repeatableRead"] = "REPEATABLE READ";
|
|
53
|
-
TranzactionIsolationLevel["readCommitted"] = "READ COMMITTED";
|
|
54
|
-
TranzactionIsolationLevel["readUncommitted"] = "READ UNCOMMITTED";
|
|
55
|
-
})(TranzactionIsolationLevel = exports.TranzactionIsolationLevel || (exports.TranzactionIsolationLevel = {}));
|
|
56
56
|
class PgDb extends queryAble_1.QueryAble {
|
|
57
|
-
constructor(pgdb
|
|
57
|
+
constructor(pgdb) {
|
|
58
58
|
super();
|
|
59
|
+
this.connection = null;
|
|
59
60
|
this.tables = {};
|
|
60
61
|
this.fn = {};
|
|
61
62
|
this.pgdbTypeParsers = {};
|
|
63
|
+
this.knownOids = {};
|
|
62
64
|
this.listeners = new EventEmitter();
|
|
65
|
+
this.connectionForListen = null;
|
|
66
|
+
this._needToRestartConnectionForListen = false;
|
|
67
|
+
this.restartConnectionForListen = null;
|
|
68
|
+
this.notificationListener = (notification) => this.listeners.emit(notification.channel, notification);
|
|
69
|
+
this.errorListener = (e) => {
|
|
70
|
+
this._needToRestartConnectionForListen = true;
|
|
71
|
+
this.tryToFixConnectionForListenActively();
|
|
72
|
+
};
|
|
63
73
|
this.schemas = {};
|
|
64
|
-
this.config = pgdb.config;
|
|
74
|
+
this.config = pgdb.config || {};
|
|
65
75
|
this.pool = pgdb.pool;
|
|
66
76
|
this.postProcessResult = pgdb.postProcessResult;
|
|
67
77
|
this.pgdbTypeParsers = pgdb.pgdbTypeParsers || {};
|
|
78
|
+
this.knownOids = pgdb.knownOids || {};
|
|
68
79
|
this.db = this;
|
|
69
80
|
if (pgdb.getLogger) {
|
|
70
81
|
this.setLogger(pgdb.getLogger());
|
|
@@ -80,14 +91,14 @@ class PgDb extends queryAble_1.QueryAble {
|
|
|
80
91
|
schema[tableName] = schema.tables[tableName];
|
|
81
92
|
}
|
|
82
93
|
}
|
|
83
|
-
this.defaultSchemas = pgdb.defaultSchemas;
|
|
94
|
+
this.defaultSchemas = pgdb.defaultSchemas || [];
|
|
84
95
|
this.setDefaultTablesAndFunctions();
|
|
85
96
|
}
|
|
86
97
|
setPostProcessResult(f) {
|
|
87
98
|
this.postProcessResult = f;
|
|
88
99
|
}
|
|
89
100
|
static getInstance(config) {
|
|
90
|
-
return tslib_1.__awaiter(this, void 0, void 0, function* () {
|
|
101
|
+
return (0, tslib_1.__awaiter)(this, void 0, void 0, function* () {
|
|
91
102
|
if (config.connectionString) {
|
|
92
103
|
let res = CONNECTION_URL_REGEXP.exec(config.connectionString);
|
|
93
104
|
if (res) {
|
|
@@ -102,7 +113,7 @@ class PgDb extends queryAble_1.QueryAble {
|
|
|
102
113
|
if (!PgDb.instances) {
|
|
103
114
|
PgDb.instances = {};
|
|
104
115
|
}
|
|
105
|
-
if (PgDb.instances[connectionString]) {
|
|
116
|
+
if (PgDb.instances[connectionString] != null) {
|
|
106
117
|
return PgDb.instances[connectionString];
|
|
107
118
|
}
|
|
108
119
|
else {
|
|
@@ -113,18 +124,18 @@ class PgDb extends queryAble_1.QueryAble {
|
|
|
113
124
|
});
|
|
114
125
|
}
|
|
115
126
|
close() {
|
|
116
|
-
return tslib_1.__awaiter(this, void 0, void 0, function* () {
|
|
127
|
+
return (0, tslib_1.__awaiter)(this, void 0, void 0, function* () {
|
|
117
128
|
for (let cs in PgDb.instances) {
|
|
118
129
|
let db = yield PgDb.instances[cs];
|
|
119
130
|
if (db.pool == this.pool) {
|
|
120
131
|
delete PgDb.instances[cs];
|
|
121
132
|
}
|
|
122
133
|
}
|
|
123
|
-
yield this.pool.end();
|
|
134
|
+
yield new Promise((resolve) => this.pool.end(resolve));
|
|
124
135
|
});
|
|
125
136
|
}
|
|
126
137
|
static connect(config) {
|
|
127
|
-
return tslib_1.__awaiter(this, void 0, void 0, function* () {
|
|
138
|
+
return (0, tslib_1.__awaiter)(this, void 0, void 0, function* () {
|
|
128
139
|
if (config.connectionString) {
|
|
129
140
|
let res = CONNECTION_URL_REGEXP.exec(config.connectionString);
|
|
130
141
|
if (res) {
|
|
@@ -141,7 +152,7 @@ class PgDb extends queryAble_1.QueryAble {
|
|
|
141
152
|
});
|
|
142
153
|
}
|
|
143
154
|
init() {
|
|
144
|
-
return tslib_1.__awaiter(this, void 0, void 0, function* () {
|
|
155
|
+
return (0, tslib_1.__awaiter)(this, void 0, void 0, function* () {
|
|
145
156
|
this.pool = new pg.Pool(_.omit(this.config, ['logger', 'skipUndefined']));
|
|
146
157
|
if (this.config.logger)
|
|
147
158
|
this.setLogger(this.config.logger);
|
|
@@ -154,16 +165,16 @@ class PgDb extends queryAble_1.QueryAble {
|
|
|
154
165
|
});
|
|
155
166
|
}
|
|
156
167
|
reload() {
|
|
157
|
-
return tslib_1.__awaiter(this, void 0, void 0, function* () {
|
|
168
|
+
return (0, tslib_1.__awaiter)(this, void 0, void 0, function* () {
|
|
158
169
|
yield this.initSchemasAndTables();
|
|
159
170
|
yield this.initFieldTypes();
|
|
160
171
|
});
|
|
161
172
|
}
|
|
162
173
|
initSchemasAndTables() {
|
|
163
|
-
return tslib_1.__awaiter(this, void 0, void 0, function* () {
|
|
174
|
+
return (0, tslib_1.__awaiter)(this, void 0, void 0, function* () {
|
|
164
175
|
let schemasAndTables = yield this.query(LIST_SCHEMAS_TABLES);
|
|
165
176
|
let functions = yield this.query(GET_SCHEMAS_PROCEDURES);
|
|
166
|
-
this.defaultSchemas =
|
|
177
|
+
this.defaultSchemas = yield this.queryOneField(GET_CURRENT_SCHEMAS);
|
|
167
178
|
let oldSchemaNames = Object.keys(this.schemas);
|
|
168
179
|
for (let sc of oldSchemaNames) {
|
|
169
180
|
if (this[sc] === this.schemas[sc])
|
|
@@ -203,145 +214,225 @@ class PgDb extends queryAble_1.QueryAble {
|
|
|
203
214
|
}
|
|
204
215
|
}
|
|
205
216
|
initFieldTypes() {
|
|
206
|
-
return tslib_1.__awaiter(this, void 0, void 0, function* () {
|
|
217
|
+
return (0, tslib_1.__awaiter)(this, void 0, void 0, function* () {
|
|
207
218
|
let schemaNames = "'" + Object.keys(this.schemas).join("', '") + "'";
|
|
208
219
|
if (schemaNames == "''") {
|
|
209
220
|
this.getLogger(true).error("No readable schema found!");
|
|
210
221
|
return;
|
|
211
222
|
}
|
|
223
|
+
let type2oid = {};
|
|
224
|
+
let res = yield this.query(TYPE2OID);
|
|
225
|
+
for (let tt of res || []) {
|
|
226
|
+
type2oid[tt.typname] = +tt.oid;
|
|
227
|
+
}
|
|
212
228
|
let specialTypeFields = yield this.query(LIST_SPECIAL_TYPE_FIELDS + ' AND c.nspname in (' + schemaNames + ')');
|
|
213
229
|
for (let r of specialTypeFields) {
|
|
214
230
|
if (this.schemas[r.schema_name][r.table_name]) {
|
|
215
231
|
this.schemas[r.schema_name][r.table_name].fieldTypes[r.column_name] =
|
|
216
|
-
([
|
|
217
|
-
([
|
|
218
|
-
([
|
|
232
|
+
([type2oid['json'], type2oid['jsonb']].indexOf(r.typid) > -1) ? FieldType.JSON :
|
|
233
|
+
([type2oid['tsvector']].indexOf(r.typid) > -1) ? FieldType.TSVECTOR :
|
|
234
|
+
([type2oid['date'], type2oid['time'], type2oid['timestamp'], type2oid['timestamptz'], type2oid['timetz']].indexOf(r.typid) > -1) ? FieldType.TIME :
|
|
219
235
|
FieldType.ARRAY;
|
|
220
236
|
}
|
|
221
237
|
}
|
|
238
|
+
let builtInArrayTypeParsers = [
|
|
239
|
+
{
|
|
240
|
+
oidList: [
|
|
241
|
+
type2oid['_bool']
|
|
242
|
+
],
|
|
243
|
+
parser: PgConverters.parseBooleanArray
|
|
244
|
+
},
|
|
245
|
+
{
|
|
246
|
+
oidList: [
|
|
247
|
+
type2oid['_int2'],
|
|
248
|
+
type2oid['_int4'],
|
|
249
|
+
type2oid['_float4'],
|
|
250
|
+
],
|
|
251
|
+
parser: PgConverters.parseNumberArray
|
|
252
|
+
},
|
|
253
|
+
{
|
|
254
|
+
oidList: [
|
|
255
|
+
type2oid['_text'],
|
|
256
|
+
type2oid['_varchar']
|
|
257
|
+
],
|
|
258
|
+
parser: PgConverters.parseArray
|
|
259
|
+
},
|
|
260
|
+
{
|
|
261
|
+
oidList: [
|
|
262
|
+
type2oid['_json'],
|
|
263
|
+
type2oid['_jsonb']
|
|
264
|
+
],
|
|
265
|
+
parser: PgConverters.parseJsonArray
|
|
266
|
+
},
|
|
267
|
+
{
|
|
268
|
+
oidList: [
|
|
269
|
+
type2oid['_date'],
|
|
270
|
+
type2oid['_time'],
|
|
271
|
+
type2oid['_timetz'],
|
|
272
|
+
type2oid['_timestamp'],
|
|
273
|
+
type2oid['_timestamptz'],
|
|
274
|
+
],
|
|
275
|
+
parser: PgConverters.parseDateArray
|
|
276
|
+
}
|
|
277
|
+
];
|
|
278
|
+
builtInArrayTypeParsers.forEach(parserObj => {
|
|
279
|
+
parserObj.oidList.forEach(oid => {
|
|
280
|
+
pg.types.setTypeParser(oid, parserObj.parser);
|
|
281
|
+
delete this.pgdbTypeParsers[oid];
|
|
282
|
+
this.knownOids[oid] = true;
|
|
283
|
+
});
|
|
284
|
+
});
|
|
222
285
|
for (let r of specialTypeFields) {
|
|
286
|
+
if (this.knownOids[r.typid] && !this.pgdbTypeParsers[r.typid]) {
|
|
287
|
+
continue;
|
|
288
|
+
}
|
|
223
289
|
switch (r.typid) {
|
|
224
|
-
case
|
|
225
|
-
case
|
|
226
|
-
case
|
|
227
|
-
case
|
|
228
|
-
case
|
|
229
|
-
case
|
|
230
|
-
case
|
|
231
|
-
case
|
|
232
|
-
|
|
233
|
-
case
|
|
234
|
-
case 1007:
|
|
235
|
-
case 1021:
|
|
236
|
-
pg.types.setTypeParser(r.typid, PgConverters.arraySplitToNum);
|
|
237
|
-
break;
|
|
238
|
-
case 1009:
|
|
239
|
-
case 1015:
|
|
240
|
-
pg.types.setTypeParser(r.typid, PgConverters.arraySplit);
|
|
241
|
-
break;
|
|
242
|
-
case 3807:
|
|
243
|
-
pg.types.setTypeParser(r.typid, PgConverters.arraySplitToJson);
|
|
244
|
-
break;
|
|
245
|
-
case 1016:
|
|
246
|
-
case 1022:
|
|
247
|
-
break;
|
|
248
|
-
case 1115:
|
|
249
|
-
case 1182:
|
|
250
|
-
case 1183:
|
|
251
|
-
case 1185:
|
|
252
|
-
case 1270:
|
|
253
|
-
pg.types.setTypeParser(r.typid, PgConverters.arraySplitToDate);
|
|
290
|
+
case type2oid['json']:
|
|
291
|
+
case type2oid['jsonb']:
|
|
292
|
+
case type2oid['date']:
|
|
293
|
+
case type2oid['time']:
|
|
294
|
+
case type2oid['timetz']:
|
|
295
|
+
case type2oid['timestamp']:
|
|
296
|
+
case type2oid['timestamptz']:
|
|
297
|
+
case type2oid['tsvector']:
|
|
298
|
+
case type2oid['_int8']:
|
|
299
|
+
case type2oid['_float8']:
|
|
254
300
|
break;
|
|
255
301
|
default:
|
|
256
|
-
pg.types.setTypeParser(r.typid, PgConverters.
|
|
302
|
+
pg.types.setTypeParser(r.typid, PgConverters.parseArray);
|
|
303
|
+
delete this.pgdbTypeParsers[r.typid];
|
|
257
304
|
}
|
|
258
305
|
}
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
306
|
+
this.pgdbTypeParsers[type2oid['int8']] = PgConverters.parseNumberWithValidation;
|
|
307
|
+
this.pgdbTypeParsers[type2oid['float8']] = PgConverters.parseNumberWithValidation;
|
|
308
|
+
this.pgdbTypeParsers[type2oid['_int8']] = PgConverters.parseNumberArrayWithValidation;
|
|
309
|
+
this.pgdbTypeParsers[type2oid['_float8']] = PgConverters.parseNumberArrayWithValidation;
|
|
310
|
+
this.knownOids[type2oid['int8']] = true;
|
|
311
|
+
this.knownOids[type2oid['float8']] = true;
|
|
312
|
+
this.knownOids[type2oid['_int8']] = true;
|
|
313
|
+
this.knownOids[type2oid['_float8']] = true;
|
|
314
|
+
let allUsedTypeFields = yield this.queryOneColumn(`
|
|
315
|
+
SELECT distinct a.atttypid as typid
|
|
316
|
+
FROM pg_attribute a
|
|
317
|
+
JOIN pg_class b ON (a.attrelid = b.oid)
|
|
318
|
+
JOIN pg_type t ON (a.atttypid = t.oid)
|
|
319
|
+
JOIN pg_namespace c ON (b.relnamespace=c.oid)
|
|
320
|
+
WHERE
|
|
321
|
+
reltype>0 AND
|
|
322
|
+
c.nspname in (${schemaNames})`);
|
|
323
|
+
allUsedTypeFields.forEach(oid => this.knownOids[oid] = true);
|
|
263
324
|
});
|
|
264
325
|
}
|
|
265
326
|
setTypeParser(typeName, parser, schemaName) {
|
|
266
|
-
return tslib_1.__awaiter(this, void 0, void 0, function* () {
|
|
327
|
+
return (0, tslib_1.__awaiter)(this, void 0, void 0, function* () {
|
|
267
328
|
try {
|
|
268
329
|
if (schemaName) {
|
|
269
330
|
let oid = yield this.queryOneField(GET_OID_FOR_COLUMN_TYPE_FOR_SCHEMA, { typeName, schemaName });
|
|
270
331
|
pg.types.setTypeParser(oid, parser);
|
|
271
332
|
delete this.pgdbTypeParsers[oid];
|
|
333
|
+
this.knownOids[oid] = true;
|
|
272
334
|
}
|
|
273
335
|
else {
|
|
274
336
|
let list = yield this.queryOneColumn(GET_OID_FOR_COLUMN_TYPE, { typeName });
|
|
275
337
|
list.forEach(oid => {
|
|
276
338
|
pg.types.setTypeParser(oid, parser);
|
|
277
339
|
delete this.pgdbTypeParsers[oid];
|
|
340
|
+
this.knownOids[oid] = true;
|
|
278
341
|
});
|
|
279
342
|
}
|
|
280
343
|
}
|
|
281
344
|
catch (e) {
|
|
282
|
-
throw Error('Not existing type: ' + typeName);
|
|
345
|
+
throw new Error('Not existing type: ' + typeName);
|
|
283
346
|
}
|
|
284
347
|
});
|
|
285
348
|
}
|
|
286
349
|
setPgDbTypeParser(typeName, parser, schemaName) {
|
|
287
|
-
return tslib_1.__awaiter(this, void 0, void 0, function* () {
|
|
350
|
+
return (0, tslib_1.__awaiter)(this, void 0, void 0, function* () {
|
|
288
351
|
try {
|
|
289
352
|
if (schemaName) {
|
|
290
353
|
let oid = yield this.queryOneField(GET_OID_FOR_COLUMN_TYPE_FOR_SCHEMA, { typeName, schemaName });
|
|
291
354
|
this.pgdbTypeParsers[oid] = parser;
|
|
355
|
+
this.knownOids[oid] = true;
|
|
292
356
|
}
|
|
293
357
|
else {
|
|
294
358
|
let list = yield this.queryOneColumn(GET_OID_FOR_COLUMN_TYPE, { typeName });
|
|
295
|
-
list.forEach(oid =>
|
|
359
|
+
list.forEach(oid => {
|
|
360
|
+
this.pgdbTypeParsers[oid] = parser;
|
|
361
|
+
this.knownOids[oid] = true;
|
|
362
|
+
});
|
|
296
363
|
}
|
|
297
364
|
}
|
|
298
365
|
catch (e) {
|
|
299
|
-
throw Error('Not existing type: ' + typeName);
|
|
366
|
+
throw new Error('Not existing type: ' + typeName);
|
|
367
|
+
}
|
|
368
|
+
});
|
|
369
|
+
}
|
|
370
|
+
resetMissingParsers(connection, oidList) {
|
|
371
|
+
return (0, tslib_1.__awaiter)(this, void 0, void 0, function* () {
|
|
372
|
+
let unknownOids = oidList.filter(oid => !this.knownOids[oid]);
|
|
373
|
+
if (unknownOids.length) {
|
|
374
|
+
let fieldsData = yield connection.query(`select oid, typcategory from pg_type where oid = ANY($1)`, [unknownOids]);
|
|
375
|
+
fieldsData.rows.forEach(fieldData => {
|
|
376
|
+
if (fieldData.typcategory == 'A') {
|
|
377
|
+
this.pgdbTypeParsers[fieldData.oid] = PgConverters.parseArray;
|
|
378
|
+
}
|
|
379
|
+
this.knownOids[fieldData.oid] = true;
|
|
380
|
+
});
|
|
300
381
|
}
|
|
301
382
|
});
|
|
302
383
|
}
|
|
303
384
|
dedicatedConnectionBegin() {
|
|
304
|
-
return tslib_1.__awaiter(this, void 0, void 0, function* () {
|
|
385
|
+
return (0, tslib_1.__awaiter)(this, void 0, void 0, function* () {
|
|
386
|
+
if (this.needToFixConnectionForListen()) {
|
|
387
|
+
yield this.runRestartConnectionForListen();
|
|
388
|
+
}
|
|
305
389
|
let pgDb = new PgDb(this);
|
|
306
390
|
pgDb.connection = yield this.pool.connect();
|
|
391
|
+
pgDb.connection.on('error', queryAble_1.QueryAble.connectionErrorListener);
|
|
307
392
|
return pgDb;
|
|
308
393
|
});
|
|
309
394
|
}
|
|
310
395
|
dedicatedConnectionEnd() {
|
|
311
|
-
return tslib_1.__awaiter(this, void 0, void 0, function* () {
|
|
396
|
+
return (0, tslib_1.__awaiter)(this, void 0, void 0, function* () {
|
|
312
397
|
if (this.connection) {
|
|
313
|
-
|
|
398
|
+
this.connection.off('error', queryAble_1.QueryAble.connectionErrorListener);
|
|
399
|
+
try {
|
|
400
|
+
yield this.connection.release();
|
|
401
|
+
}
|
|
402
|
+
catch (err) {
|
|
403
|
+
this.getLogger().error('Error while dedicated connection end.', err);
|
|
404
|
+
}
|
|
314
405
|
this.connection = null;
|
|
315
406
|
}
|
|
316
407
|
return this;
|
|
317
408
|
});
|
|
318
409
|
}
|
|
319
410
|
savePoint(name) {
|
|
320
|
-
return tslib_1.__awaiter(this, void 0, void 0, function* () {
|
|
411
|
+
return (0, tslib_1.__awaiter)(this, void 0, void 0, function* () {
|
|
321
412
|
if (this.isTransactionActive()) {
|
|
322
413
|
name = (name || '').replace(/"/g, '');
|
|
323
414
|
yield this.query(`SAVEPOINT "${name}"`);
|
|
324
415
|
}
|
|
325
416
|
else {
|
|
326
|
-
throw Error('No active transaction');
|
|
417
|
+
throw new Error('No active transaction');
|
|
327
418
|
}
|
|
328
419
|
return this;
|
|
329
420
|
});
|
|
330
421
|
}
|
|
331
422
|
savePointRelease(name) {
|
|
332
|
-
return tslib_1.__awaiter(this, void 0, void 0, function* () {
|
|
423
|
+
return (0, tslib_1.__awaiter)(this, void 0, void 0, function* () {
|
|
333
424
|
if (this.isTransactionActive()) {
|
|
334
425
|
name = (name || '').replace(/"/g, '');
|
|
335
426
|
yield this.query(`RELEASE SAVEPOINT "${name}"`);
|
|
336
427
|
}
|
|
337
428
|
else {
|
|
338
|
-
throw Error('No active transaction');
|
|
429
|
+
throw new Error('No active transaction');
|
|
339
430
|
}
|
|
340
431
|
return this;
|
|
341
432
|
});
|
|
342
433
|
}
|
|
343
434
|
transactionBegin(options) {
|
|
344
|
-
return tslib_1.__awaiter(this, void 0, void 0, function* () {
|
|
435
|
+
return (0, tslib_1.__awaiter)(this, void 0, void 0, function* () {
|
|
345
436
|
let pgDb = this.connection ? this : yield this.dedicatedConnectionBegin();
|
|
346
437
|
let q = 'BEGIN';
|
|
347
438
|
if (options === null || options === void 0 ? void 0 : options.isolationLevel) {
|
|
@@ -358,13 +449,13 @@ class PgDb extends queryAble_1.QueryAble {
|
|
|
358
449
|
});
|
|
359
450
|
}
|
|
360
451
|
transactionCommit() {
|
|
361
|
-
return tslib_1.__awaiter(this, void 0, void 0, function* () {
|
|
452
|
+
return (0, tslib_1.__awaiter)(this, void 0, void 0, function* () {
|
|
362
453
|
yield this.query('COMMIT');
|
|
363
454
|
return this.dedicatedConnectionEnd();
|
|
364
455
|
});
|
|
365
456
|
}
|
|
366
457
|
transactionRollback(options) {
|
|
367
|
-
return tslib_1.__awaiter(this, void 0, void 0, function* () {
|
|
458
|
+
return (0, tslib_1.__awaiter)(this, void 0, void 0, function* () {
|
|
368
459
|
if (options === null || options === void 0 ? void 0 : options.savePoint) {
|
|
369
460
|
let name = (options.savePoint || '').replace(/"/g, '');
|
|
370
461
|
yield this.query(`ROLLBACK TO SAVEPOINT "${name}"`);
|
|
@@ -380,7 +471,7 @@ class PgDb extends queryAble_1.QueryAble {
|
|
|
380
471
|
return this.connection != null;
|
|
381
472
|
}
|
|
382
473
|
execute(fileName, statementTransformerFunction) {
|
|
383
|
-
return tslib_1.__awaiter(this, void 0, void 0, function* () {
|
|
474
|
+
return (0, tslib_1.__awaiter)(this, void 0, void 0, function* () {
|
|
384
475
|
let isTransactionInPlace = this.isTransactionActive();
|
|
385
476
|
let pgdb = isTransactionInPlace ? this : yield this.dedicatedConnectionBegin();
|
|
386
477
|
let runStatementList = (statementList) => {
|
|
@@ -434,7 +525,7 @@ class PgDb extends queryAble_1.QueryAble {
|
|
|
434
525
|
let s = line.slice(SQL_TOKENIZER_REGEXP.lastIndex - 1);
|
|
435
526
|
let token = s.match(SQL_$_ESCAPE_REGEXP);
|
|
436
527
|
if (!token) {
|
|
437
|
-
throw Error('Invalid sql in line: ' + line);
|
|
528
|
+
throw new Error('Invalid sql in line: ' + line);
|
|
438
529
|
}
|
|
439
530
|
inQuotedString = token[0];
|
|
440
531
|
SQL_TOKENIZER_REGEXP.lastIndex += inQuotedString.length - 1;
|
|
@@ -523,46 +614,148 @@ class PgDb extends queryAble_1.QueryAble {
|
|
|
523
614
|
});
|
|
524
615
|
}
|
|
525
616
|
listen(channel, callback) {
|
|
526
|
-
return tslib_1.__awaiter(this, void 0, void 0, function* () {
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
617
|
+
return (0, tslib_1.__awaiter)(this, void 0, void 0, function* () {
|
|
618
|
+
let restartConnectionError = null;
|
|
619
|
+
if (this.needToFixConnectionForListen()) {
|
|
620
|
+
restartConnectionError = yield this.runRestartConnectionForListen();
|
|
530
621
|
}
|
|
531
|
-
if (
|
|
532
|
-
|
|
622
|
+
if (this.listeners.listenerCount(channel)) {
|
|
623
|
+
this.listeners.on(channel, callback);
|
|
624
|
+
}
|
|
625
|
+
else {
|
|
626
|
+
if (restartConnectionError) {
|
|
627
|
+
throw restartConnectionError;
|
|
628
|
+
}
|
|
629
|
+
try {
|
|
630
|
+
if (!this.connectionForListen) {
|
|
631
|
+
yield this.initConnectionForListen();
|
|
632
|
+
}
|
|
633
|
+
yield this.connectionForListen.query(`LISTEN "${channel}"`);
|
|
634
|
+
}
|
|
635
|
+
catch (err) {
|
|
636
|
+
this._needToRestartConnectionForListen = true;
|
|
637
|
+
throw err;
|
|
638
|
+
}
|
|
639
|
+
this.listeners.on(channel, callback);
|
|
533
640
|
}
|
|
534
|
-
this.listeners.on(channel, callback);
|
|
535
641
|
});
|
|
536
642
|
}
|
|
537
643
|
unlisten(channel, callback) {
|
|
538
|
-
return tslib_1.__awaiter(this, void 0, void 0, function* () {
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
644
|
+
return (0, tslib_1.__awaiter)(this, void 0, void 0, function* () {
|
|
645
|
+
let restartConnectionError = null;
|
|
646
|
+
if (this.needToFixConnectionForListen()) {
|
|
647
|
+
restartConnectionError = yield this.runRestartConnectionForListen();
|
|
542
648
|
}
|
|
543
|
-
if (callback) {
|
|
649
|
+
if (callback && this.listeners.listenerCount(channel) > 1) {
|
|
544
650
|
this.listeners.removeListener(channel, callback);
|
|
545
651
|
}
|
|
546
652
|
else {
|
|
653
|
+
if (restartConnectionError) {
|
|
654
|
+
throw restartConnectionError;
|
|
655
|
+
}
|
|
656
|
+
try {
|
|
657
|
+
yield this.internalQuery({ connection: this.connectionForListen, sql: `UNLISTEN "${channel}"` });
|
|
658
|
+
if (this.connectionForListen && this.listeners.eventNames().length == 1) {
|
|
659
|
+
this.connectionForListen.removeAllListeners('notification');
|
|
660
|
+
this.connectionForListen.release();
|
|
661
|
+
this.connectionForListen = null;
|
|
662
|
+
}
|
|
663
|
+
}
|
|
664
|
+
catch (err) {
|
|
665
|
+
this._needToRestartConnectionForListen = true;
|
|
666
|
+
throw err;
|
|
667
|
+
}
|
|
547
668
|
this.listeners.removeAllListeners(channel);
|
|
548
669
|
}
|
|
549
|
-
if (!this.listeners.listenerCount(channel)) {
|
|
550
|
-
yield this.internalQuery({ connection: this.connectionForListen, sql: 'UNLISTEN ' + channel });
|
|
551
|
-
}
|
|
552
|
-
let allListeners = this.listeners.eventNames().reduce((sum, ename) => sum + this.listeners.listenerCount(ename), 0);
|
|
553
|
-
if (!allListeners && this.connectionForListen) {
|
|
554
|
-
this.connectionForListen.removeAllListeners('notification');
|
|
555
|
-
this.connectionForListen.release();
|
|
556
|
-
this.connectionForListen = null;
|
|
557
|
-
}
|
|
558
670
|
});
|
|
559
671
|
}
|
|
560
672
|
notify(channel, payload) {
|
|
561
|
-
return tslib_1.__awaiter(this, void 0, void 0, function* () {
|
|
673
|
+
return (0, tslib_1.__awaiter)(this, void 0, void 0, function* () {
|
|
674
|
+
if (this.needToFixConnectionForListen()) {
|
|
675
|
+
let restartConnectionError = yield this.runRestartConnectionForListen();
|
|
676
|
+
if (restartConnectionError) {
|
|
677
|
+
throw restartConnectionError;
|
|
678
|
+
}
|
|
679
|
+
}
|
|
680
|
+
let hasConnectionForListen = !!this.connectionForListen;
|
|
562
681
|
let connection = this.connectionForListen || this.connection;
|
|
563
682
|
let sql = 'SELECT pg_notify(:channel, :payload)';
|
|
564
683
|
let params = { channel, payload };
|
|
565
|
-
|
|
684
|
+
try {
|
|
685
|
+
return this.internalQuery({ connection, sql, params });
|
|
686
|
+
}
|
|
687
|
+
catch (err) {
|
|
688
|
+
if (hasConnectionForListen) {
|
|
689
|
+
this._needToRestartConnectionForListen = true;
|
|
690
|
+
}
|
|
691
|
+
throw err;
|
|
692
|
+
}
|
|
693
|
+
});
|
|
694
|
+
}
|
|
695
|
+
runRestartConnectionForListen() {
|
|
696
|
+
return (0, tslib_1.__awaiter)(this, void 0, void 0, function* () {
|
|
697
|
+
if (!this._needToRestartConnectionForListen) {
|
|
698
|
+
return null;
|
|
699
|
+
}
|
|
700
|
+
let errorResult = null;
|
|
701
|
+
if (!this.restartConnectionForListen) {
|
|
702
|
+
this.restartConnectionForListen = (() => (0, tslib_1.__awaiter)(this, void 0, void 0, function* () {
|
|
703
|
+
let eventNames = this.listeners.eventNames();
|
|
704
|
+
if (this.connectionForListen) {
|
|
705
|
+
try {
|
|
706
|
+
this.connectionForListen.on('notification', this.notificationListener);
|
|
707
|
+
this.connectionForListen.on('error', this.errorListener);
|
|
708
|
+
}
|
|
709
|
+
catch (e) { }
|
|
710
|
+
try {
|
|
711
|
+
yield this.connectionForListen.release();
|
|
712
|
+
}
|
|
713
|
+
catch (e) { }
|
|
714
|
+
this.connectionForListen = null;
|
|
715
|
+
}
|
|
716
|
+
let error = null;
|
|
717
|
+
if (eventNames.length) {
|
|
718
|
+
try {
|
|
719
|
+
yield this.initConnectionForListen();
|
|
720
|
+
for (let channel of eventNames) {
|
|
721
|
+
yield this.connectionForListen.query(`LISTEN "${channel}"`);
|
|
722
|
+
}
|
|
723
|
+
}
|
|
724
|
+
catch (err) {
|
|
725
|
+
error = err;
|
|
726
|
+
}
|
|
727
|
+
}
|
|
728
|
+
return error;
|
|
729
|
+
}))();
|
|
730
|
+
errorResult = yield this.restartConnectionForListen;
|
|
731
|
+
this.restartConnectionForListen = null;
|
|
732
|
+
}
|
|
733
|
+
else {
|
|
734
|
+
errorResult = yield this.restartConnectionForListen;
|
|
735
|
+
}
|
|
736
|
+
if (!errorResult) {
|
|
737
|
+
this._needToRestartConnectionForListen = false;
|
|
738
|
+
}
|
|
739
|
+
return errorResult;
|
|
740
|
+
});
|
|
741
|
+
}
|
|
742
|
+
needToFixConnectionForListen() {
|
|
743
|
+
return this._needToRestartConnectionForListen;
|
|
744
|
+
}
|
|
745
|
+
tryToFixConnectionForListenActively() {
|
|
746
|
+
return (0, tslib_1.__awaiter)(this, void 0, void 0, function* () {
|
|
747
|
+
yield new Promise(r => setTimeout(r, 1000));
|
|
748
|
+
let error = yield this.runRestartConnectionForListen();
|
|
749
|
+
if (error) {
|
|
750
|
+
yield this.tryToFixConnectionForListenActively();
|
|
751
|
+
}
|
|
752
|
+
});
|
|
753
|
+
}
|
|
754
|
+
initConnectionForListen() {
|
|
755
|
+
return (0, tslib_1.__awaiter)(this, void 0, void 0, function* () {
|
|
756
|
+
this.connectionForListen = yield this.pool.connect();
|
|
757
|
+
this.connectionForListen.on('notification', this.notificationListener);
|
|
758
|
+
this.connectionForListen.on('error', this.errorListener);
|
|
566
759
|
});
|
|
567
760
|
}
|
|
568
761
|
}
|