@nymphjs/driver-postgresql 1.0.0-alpha.9 → 1.0.0-beta.1

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.
@@ -1,13 +1,4 @@
1
1
  "use strict";
2
- var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
- return new (P || (P = Promise))(function (resolve, reject) {
5
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
- step((generator = generator.apply(thisArg, _arguments || [])).next());
9
- });
10
- };
11
2
  var __importDefault = (this && this.__importDefault) || function (mod) {
12
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
13
4
  };
@@ -15,18 +6,23 @@ Object.defineProperty(exports, "__esModule", { value: true });
15
6
  const child_process_1 = __importDefault(require("child_process"));
16
7
  const pg_1 = require("pg");
17
8
  const pg_format_1 = __importDefault(require("pg-format"));
18
- const nanoid_1 = require("nanoid");
19
9
  const nymph_1 = require("@nymphjs/nymph");
10
+ const guid_1 = require("@nymphjs/guid");
20
11
  const conf_1 = require("./conf");
21
- const makeTableSuffix = (0, nanoid_1.customAlphabet)('0123456789abcdefghijklmnopqrstuvwxyz', 20);
22
12
  class PostgreSQLDriver extends nymph_1.NymphDriver {
13
+ static escape(input) {
14
+ return pg_format_1.default.ident(input);
15
+ }
16
+ static escapeValue(input) {
17
+ return pg_format_1.default.literal(input);
18
+ }
23
19
  constructor(config, link, transaction) {
24
20
  super();
25
21
  this.connected = false;
26
22
  this.transaction = null;
27
- this.config = Object.assign(Object.assign({}, conf_1.PostgreSQLDriverConfigDefaults), config);
23
+ this.config = { ...conf_1.PostgreSQLDriverConfigDefaults, ...config };
28
24
  const { host, user, password, database, port, customPoolConfig } = this.config;
29
- this.postgresqlConfig = customPoolConfig !== null && customPoolConfig !== void 0 ? customPoolConfig : {
25
+ this.postgresqlConfig = customPoolConfig ?? {
30
26
  host,
31
27
  user,
32
28
  password,
@@ -45,68 +41,56 @@ class PostgreSQLDriver extends nymph_1.NymphDriver {
45
41
  this.connect();
46
42
  }
47
43
  }
48
- static escape(input) {
49
- return pg_format_1.default.ident(input);
50
- }
51
- static escapeValue(input) {
52
- return pg_format_1.default.literal(input);
53
- }
54
44
  getConnection() {
55
45
  if (this.transaction != null && this.transaction.connection != null) {
56
46
  return Promise.resolve(this.transaction.connection);
57
47
  }
58
48
  return new Promise((resolve, reject) => this.link.connect((err, client, done) => err ? reject(err) : resolve({ client, done })));
59
49
  }
60
- connect() {
61
- return __awaiter(this, void 0, void 0, function* () {
50
+ async connect() {
51
+ try {
52
+ if (this.connected) {
53
+ const connection = await new Promise((resolve, reject) => this.link.connect((err, client, done) => err ? reject(err) : resolve({ client, done })));
54
+ await new Promise((resolve, reject) => connection.client.query('SELECT 1;', [], (err, res) => {
55
+ if (err) {
56
+ reject(err);
57
+ }
58
+ resolve(0);
59
+ }));
60
+ connection.done();
61
+ }
62
+ }
63
+ catch (e) {
64
+ this.connected = false;
65
+ }
66
+ if (!this.connected) {
62
67
  try {
63
- if (this.connected) {
64
- const connection = yield new Promise((resolve, reject) => this.link.connect((err, client, done) => err ? reject(err) : resolve({ client, done })));
65
- yield new Promise((resolve, reject) => connection.client.query('SELECT 1;', [], (err, res) => {
66
- if (err) {
67
- reject(err);
68
- }
69
- resolve(0);
70
- }));
71
- connection.done();
72
- }
68
+ this.link = new pg_1.Pool(this.postgresqlConfig);
69
+ this.connected = true;
73
70
  }
74
71
  catch (e) {
75
- this.connected = false;
76
- }
77
- if (!this.connected) {
78
- try {
79
- this.link = new pg_1.Pool(this.postgresqlConfig);
80
- this.connected = true;
72
+ if (this.postgresqlConfig.host === 'localhost' &&
73
+ this.postgresqlConfig.user === 'nymph' &&
74
+ this.postgresqlConfig.password === 'password' &&
75
+ this.postgresqlConfig.database === 'nymph') {
76
+ throw new nymph_1.NotConfiguredError("It seems the config hasn't been set up correctly.");
81
77
  }
82
- catch (e) {
83
- if (this.postgresqlConfig.host === 'localhost' &&
84
- this.postgresqlConfig.user === 'nymph' &&
85
- this.postgresqlConfig.password === 'password' &&
86
- this.postgresqlConfig.database === 'nymph') {
87
- throw new nymph_1.NotConfiguredError("It seems the config hasn't been set up correctly.");
88
- }
89
- else {
90
- throw new nymph_1.UnableToConnectError('Could not connect: ' + (e === null || e === void 0 ? void 0 : e.message));
91
- }
78
+ else {
79
+ throw new nymph_1.UnableToConnectError('Could not connect: ' + e?.message);
92
80
  }
93
81
  }
94
- return this.connected;
95
- });
82
+ }
83
+ return this.connected;
96
84
  }
97
- disconnect() {
98
- return __awaiter(this, void 0, void 0, function* () {
99
- if (this.connected) {
100
- yield new Promise((resolve) => this.link.end(() => resolve(0)));
101
- this.connected = false;
102
- }
103
- return this.connected;
104
- });
85
+ async disconnect() {
86
+ if (this.connected) {
87
+ await new Promise((resolve) => this.link.end(() => resolve(0)));
88
+ this.connected = false;
89
+ }
90
+ return this.connected;
105
91
  }
106
- inTransaction() {
107
- return __awaiter(this, void 0, void 0, function* () {
108
- return !!this.transaction;
109
- });
92
+ async inTransaction() {
93
+ return !!this.transaction;
110
94
  }
111
95
  isConnected() {
112
96
  return this.connected;
@@ -202,36 +186,34 @@ class PostgreSQLDriver extends nymph_1.NymphDriver {
202
186
  }
203
187
  return { query, params };
204
188
  }
205
- query(runQuery, query, etypes = []) {
206
- return __awaiter(this, void 0, void 0, function* () {
207
- try {
208
- return yield runQuery();
209
- }
210
- catch (e) {
211
- const errorCode = e === null || e === void 0 ? void 0 : e.code;
212
- if (errorCode === '42P01' && this.createTables()) {
213
- for (let etype of etypes) {
214
- this.createTables(etype);
215
- }
216
- try {
217
- return yield runQuery();
218
- }
219
- catch (e2) {
220
- throw new nymph_1.QueryFailedError('Query failed: ' + (e2 === null || e2 === void 0 ? void 0 : e2.code) + ' - ' + (e2 === null || e2 === void 0 ? void 0 : e2.message), query);
221
- }
189
+ async query(runQuery, query, etypes = []) {
190
+ try {
191
+ return await runQuery();
192
+ }
193
+ catch (e) {
194
+ const errorCode = e?.code;
195
+ if (errorCode === '42P01' && this.createTables()) {
196
+ for (let etype of etypes) {
197
+ this.createTables(etype);
222
198
  }
223
- else {
224
- throw e;
199
+ try {
200
+ return await runQuery();
201
+ }
202
+ catch (e2) {
203
+ throw new nymph_1.QueryFailedError('Query failed: ' + e2?.code + ' - ' + e2?.message, query);
225
204
  }
226
205
  }
227
- });
206
+ else {
207
+ throw e;
208
+ }
209
+ }
228
210
  }
229
211
  querySync(runQuery, query, etypes = []) {
230
212
  try {
231
213
  return runQuery();
232
214
  }
233
215
  catch (e) {
234
- const errorCode = e === null || e === void 0 ? void 0 : e.code;
216
+ const errorCode = e?.code;
235
217
  if (errorCode === '42P01' && this.createTables()) {
236
218
  for (let etype of etypes) {
237
219
  this.createTables(etype);
@@ -240,7 +222,7 @@ class PostgreSQLDriver extends nymph_1.NymphDriver {
240
222
  return runQuery();
241
223
  }
242
224
  catch (e2) {
243
- throw new nymph_1.QueryFailedError('Query failed: ' + (e2 === null || e2 === void 0 ? void 0 : e2.code) + ' - ' + (e2 === null || e2 === void 0 ? void 0 : e2.message), query);
225
+ throw new nymph_1.QueryFailedError('Query failed: ' + e2?.code + ' - ' + e2?.message, query);
244
226
  }
245
227
  }
246
228
  else {
@@ -250,11 +232,10 @@ class PostgreSQLDriver extends nymph_1.NymphDriver {
250
232
  }
251
233
  queryIter(query, { etypes = [], params = {}, } = {}) {
252
234
  const { query: newQuery, params: newParams } = this.translateQuery(query, params);
253
- return this.query(() => __awaiter(this, void 0, void 0, function* () {
254
- const results = yield new Promise((resolve, reject) => {
255
- var _a, _b, _c;
235
+ return this.query(async () => {
236
+ const results = await new Promise((resolve, reject) => {
256
237
  try {
257
- ((_c = (_b = (_a = this.transaction) === null || _a === void 0 ? void 0 : _a.connection) === null || _b === void 0 ? void 0 : _b.client) !== null && _c !== void 0 ? _c : this.link)
238
+ (this.transaction?.connection?.client ?? this.link)
258
239
  .query(newQuery, newParams)
259
240
  .then((results) => resolve(results), (error) => reject(error));
260
241
  }
@@ -263,7 +244,7 @@ class PostgreSQLDriver extends nymph_1.NymphDriver {
263
244
  }
264
245
  });
265
246
  return results.rows;
266
- }), `${query} -- ${JSON.stringify(params)}`, etypes);
247
+ }, `${query} -- ${JSON.stringify(params)}`, etypes);
267
248
  }
268
249
  queryIterSync(query, { etypes = [], params = {}, } = {}) {
269
250
  const { query: newQuery, params: newParams } = this.translateQuery(query, params);
@@ -296,11 +277,10 @@ class PostgreSQLDriver extends nymph_1.NymphDriver {
296
277
  }
297
278
  queryGet(query, { etypes = [], params = {}, } = {}) {
298
279
  const { query: newQuery, params: newParams } = this.translateQuery(query, params);
299
- return this.query(() => __awaiter(this, void 0, void 0, function* () {
300
- const results = yield new Promise((resolve, reject) => {
301
- var _a, _b, _c;
280
+ return this.query(async () => {
281
+ const results = await new Promise((resolve, reject) => {
302
282
  try {
303
- ((_c = (_b = (_a = this.transaction) === null || _a === void 0 ? void 0 : _a.connection) === null || _b === void 0 ? void 0 : _b.client) !== null && _c !== void 0 ? _c : this.link)
283
+ (this.transaction?.connection?.client ?? this.link)
304
284
  .query(newQuery, newParams)
305
285
  .then((results) => resolve(results), (error) => reject(error));
306
286
  }
@@ -309,16 +289,14 @@ class PostgreSQLDriver extends nymph_1.NymphDriver {
309
289
  }
310
290
  });
311
291
  return results.rows[0];
312
- }), `${query} -- ${JSON.stringify(params)}`, etypes);
292
+ }, `${query} -- ${JSON.stringify(params)}`, etypes);
313
293
  }
314
294
  queryRun(query, { etypes = [], params = {}, } = {}) {
315
295
  const { query: newQuery, params: newParams } = this.translateQuery(query, params);
316
- return this.query(() => __awaiter(this, void 0, void 0, function* () {
317
- var _a;
318
- const results = yield new Promise((resolve, reject) => {
319
- var _a, _b, _c;
296
+ return this.query(async () => {
297
+ const results = await new Promise((resolve, reject) => {
320
298
  try {
321
- ((_c = (_b = (_a = this.transaction) === null || _a === void 0 ? void 0 : _a.connection) === null || _b === void 0 ? void 0 : _b.client) !== null && _c !== void 0 ? _c : this.link)
299
+ (this.transaction?.connection?.client ?? this.link)
322
300
  .query(newQuery, newParams)
323
301
  .then((results) => resolve(results), (error) => reject(error));
324
302
  }
@@ -326,13 +304,12 @@ class PostgreSQLDriver extends nymph_1.NymphDriver {
326
304
  reject(e);
327
305
  }
328
306
  });
329
- return { rowCount: (_a = results.rowCount) !== null && _a !== void 0 ? _a : 0 };
330
- }), `${query} -- ${JSON.stringify(params)}`, etypes);
307
+ return { rowCount: results.rowCount ?? 0 };
308
+ }, `${query} -- ${JSON.stringify(params)}`, etypes);
331
309
  }
332
310
  queryRunSync(query, { etypes = [], params = {}, } = {}) {
333
311
  const { query: newQuery, params: newParams } = this.translateQuery(query, params);
334
312
  return this.querySync(() => {
335
- var _a;
336
313
  const output = child_process_1.default.spawnSync(process.argv0, [__dirname + '/runPostgresqlSync.js'], {
337
314
  input: JSON.stringify({
338
315
  postgresqlConfig: this.postgresqlConfig,
@@ -346,7 +323,7 @@ class PostgreSQLDriver extends nymph_1.NymphDriver {
346
323
  });
347
324
  try {
348
325
  const results = JSON.parse(output.stdout);
349
- return { rowCount: (_a = results.rowCount) !== null && _a !== void 0 ? _a : 0 };
326
+ return { rowCount: results.rowCount ?? 0 };
350
327
  }
351
328
  catch (e) {
352
329
  }
@@ -360,155 +337,145 @@ class PostgreSQLDriver extends nymph_1.NymphDriver {
360
337
  }
361
338
  }, `${query} -- ${JSON.stringify(params)}`, etypes);
362
339
  }
363
- commit(name) {
364
- var _a;
365
- return __awaiter(this, void 0, void 0, function* () {
366
- if (name == null || typeof name !== 'string' || name.length === 0) {
367
- throw new nymph_1.InvalidParametersError('Transaction commit attempted without a name.');
368
- }
369
- if (!this.transaction || this.transaction.count === 0) {
370
- this.transaction = null;
371
- return true;
372
- }
373
- yield this.queryRun(`RELEASE SAVEPOINT ${PostgreSQLDriver.escape(name)};`);
374
- this.transaction.count--;
375
- if (this.transaction.count === 0) {
376
- yield this.queryRun('COMMIT;');
377
- (_a = this.transaction.connection) === null || _a === void 0 ? void 0 : _a.done();
378
- this.transaction.connection = null;
379
- this.transaction = null;
380
- }
340
+ async commit(name) {
341
+ if (name == null || typeof name !== 'string' || name.length === 0) {
342
+ throw new nymph_1.InvalidParametersError('Transaction commit attempted without a name.');
343
+ }
344
+ if (!this.transaction || this.transaction.count === 0) {
345
+ this.transaction = null;
381
346
  return true;
382
- });
383
- }
384
- deleteEntityByID(guid, className) {
385
- return __awaiter(this, void 0, void 0, function* () {
386
- let EntityClass;
387
- if (typeof className === 'string' || className == null) {
388
- const GetEntityClass = this.nymph.getEntityClass(className !== null && className !== void 0 ? className : 'Entity');
389
- EntityClass = GetEntityClass;
390
- }
391
- else {
392
- EntityClass = className;
393
- }
394
- const etype = EntityClass.ETYPE;
395
- yield this.internalTransaction('nymph-delete');
396
- try {
397
- yield this.queryRun(`DELETE FROM ${PostgreSQLDriver.escape(`${this.prefix}entities_${etype}`)} WHERE "guid"=decode(@guid, 'hex');`, {
398
- etypes: [etype],
399
- params: {
400
- guid,
401
- },
402
- });
403
- yield this.queryRun(`DELETE FROM ${PostgreSQLDriver.escape(`${this.prefix}data_${etype}`)} WHERE "guid"=decode(@guid, 'hex');`, {
404
- etypes: [etype],
405
- params: {
406
- guid,
407
- },
408
- });
409
- yield this.queryRun(`DELETE FROM ${PostgreSQLDriver.escape(`${this.prefix}comparisons_${etype}`)} WHERE "guid"=decode(@guid, 'hex');`, {
410
- etypes: [etype],
411
- params: {
412
- guid,
413
- },
414
- });
415
- yield this.queryRun(`DELETE FROM ${PostgreSQLDriver.escape(`${this.prefix}references_${etype}`)} WHERE "guid"=decode(@guid, 'hex');`, {
416
- etypes: [etype],
417
- params: {
418
- guid,
419
- },
420
- });
421
- yield this.commit('nymph-delete');
422
- if (this.nymph.config.cache) {
423
- this.cleanCache(guid);
424
- }
425
- return true;
426
- }
427
- catch (e) {
428
- yield this.rollback('nymph-delete');
429
- throw e;
430
- }
431
- });
347
+ }
348
+ await this.queryRun(`RELEASE SAVEPOINT ${PostgreSQLDriver.escape(name)};`);
349
+ this.transaction.count--;
350
+ if (this.transaction.count === 0) {
351
+ await this.queryRun('COMMIT;');
352
+ this.transaction.connection?.done();
353
+ this.transaction.connection = null;
354
+ this.transaction = null;
355
+ }
356
+ return true;
432
357
  }
433
- deleteUID(name) {
434
- return __awaiter(this, void 0, void 0, function* () {
435
- if (!name) {
436
- throw new nymph_1.InvalidParametersError('Name not given for UID');
437
- }
438
- yield this.queryRun(`DELETE FROM ${PostgreSQLDriver.escape(`${this.prefix}uids`)} WHERE "name"=@name;`, {
358
+ async deleteEntityByID(guid, className) {
359
+ let EntityClass;
360
+ if (typeof className === 'string' || className == null) {
361
+ const GetEntityClass = this.nymph.getEntityClass(className ?? 'Entity');
362
+ EntityClass = GetEntityClass;
363
+ }
364
+ else {
365
+ EntityClass = className;
366
+ }
367
+ const etype = EntityClass.ETYPE;
368
+ await this.internalTransaction('nymph-delete');
369
+ try {
370
+ await this.queryRun(`DELETE FROM ${PostgreSQLDriver.escape(`${this.prefix}entities_${etype}`)} WHERE "guid"=decode(@guid, 'hex');`, {
371
+ etypes: [etype],
439
372
  params: {
440
- name,
373
+ guid,
441
374
  },
442
375
  });
376
+ await this.queryRun(`DELETE FROM ${PostgreSQLDriver.escape(`${this.prefix}data_${etype}`)} WHERE "guid"=decode(@guid, 'hex');`, {
377
+ etypes: [etype],
378
+ params: {
379
+ guid,
380
+ },
381
+ });
382
+ await this.queryRun(`DELETE FROM ${PostgreSQLDriver.escape(`${this.prefix}comparisons_${etype}`)} WHERE "guid"=decode(@guid, 'hex');`, {
383
+ etypes: [etype],
384
+ params: {
385
+ guid,
386
+ },
387
+ });
388
+ await this.queryRun(`DELETE FROM ${PostgreSQLDriver.escape(`${this.prefix}references_${etype}`)} WHERE "guid"=decode(@guid, 'hex');`, {
389
+ etypes: [etype],
390
+ params: {
391
+ guid,
392
+ },
393
+ });
394
+ await this.commit('nymph-delete');
395
+ if (this.nymph.config.cache) {
396
+ this.cleanCache(guid);
397
+ }
443
398
  return true;
399
+ }
400
+ catch (e) {
401
+ await this.rollback('nymph-delete');
402
+ throw e;
403
+ }
404
+ }
405
+ async deleteUID(name) {
406
+ if (!name) {
407
+ throw new nymph_1.InvalidParametersError('Name not given for UID');
408
+ }
409
+ await this.queryRun(`DELETE FROM ${PostgreSQLDriver.escape(`${this.prefix}uids`)} WHERE "name"=@name;`, {
410
+ params: {
411
+ name,
412
+ },
444
413
  });
414
+ return true;
445
415
  }
446
- exportEntities(writeLine) {
447
- return __awaiter(this, void 0, void 0, function* () {
448
- writeLine('#nex2');
449
- writeLine('# Nymph Entity Exchange v2');
450
- writeLine('# http://nymph.io');
451
- writeLine('#');
452
- writeLine('# Generation Time: ' + new Date().toLocaleString());
453
- writeLine('');
454
- writeLine('#');
455
- writeLine('# UIDs');
456
- writeLine('#');
457
- writeLine('');
458
- let uids = yield this.queryIter(`SELECT * FROM ${PostgreSQLDriver.escape(`${this.prefix}uids`)} ORDER BY "name";`);
459
- for (const uid of uids) {
460
- writeLine(`<${uid.name}>[${uid.cur_uid}]`);
461
- }
462
- writeLine('');
463
- writeLine('#');
464
- writeLine('# Entities');
465
- writeLine('#');
466
- writeLine('');
467
- const tables = yield this.queryIter('SELECT relname FROM pg_stat_user_tables ORDER BY relname;');
468
- const etypes = [];
469
- for (const tableRow of tables) {
470
- const table = tableRow.relname;
471
- if (table.startsWith(this.prefix + 'entities_')) {
472
- etypes.push(table.substr((this.prefix + 'entities_').length));
473
- }
416
+ async exportEntities(writeLine) {
417
+ writeLine('#nex2');
418
+ writeLine('# Nymph Entity Exchange v2');
419
+ writeLine('# http://nymph.io');
420
+ writeLine('#');
421
+ writeLine('# Generation Time: ' + new Date().toLocaleString());
422
+ writeLine('');
423
+ writeLine('#');
424
+ writeLine('# UIDs');
425
+ writeLine('#');
426
+ writeLine('');
427
+ let uids = await this.queryIter(`SELECT * FROM ${PostgreSQLDriver.escape(`${this.prefix}uids`)} ORDER BY "name";`);
428
+ for (const uid of uids) {
429
+ writeLine(`<${uid.name}>[${uid.cur_uid}]`);
430
+ }
431
+ writeLine('');
432
+ writeLine('#');
433
+ writeLine('# Entities');
434
+ writeLine('#');
435
+ writeLine('');
436
+ const tables = await this.queryIter('SELECT relname FROM pg_stat_user_tables ORDER BY relname;');
437
+ const etypes = [];
438
+ for (const tableRow of tables) {
439
+ const table = tableRow.relname;
440
+ if (table.startsWith(this.prefix + 'entities_')) {
441
+ etypes.push(table.substr((this.prefix + 'entities_').length));
474
442
  }
475
- for (const etype of etypes) {
476
- const dataIterator = (yield this.queryIter(`SELECT encode(e."guid", 'hex') as "guid", e."tags", e."cdate", e."mdate", d."name" AS "dname", d."value" AS "dvalue", c."string", c."number"
443
+ }
444
+ for (const etype of etypes) {
445
+ const dataIterator = (await this.queryIter(`SELECT encode(e."guid", 'hex') AS "guid", e."tags", e."cdate", e."mdate", d."name" AS "dname", d."value" AS "dvalue", c."string", c."number"
477
446
  FROM ${PostgreSQLDriver.escape(`${this.prefix}entities_${etype}`)} e
478
447
  LEFT JOIN ${PostgreSQLDriver.escape(`${this.prefix}data_${etype}`)} d ON e."guid"=d."guid"
479
448
  INNER JOIN ${PostgreSQLDriver.escape(`${this.prefix}comparisons_${etype}`)} c ON d."guid"=c."guid" AND d."name"=c."name"
480
449
  ORDER BY e."guid";`))[Symbol.iterator]();
481
- let datum = dataIterator.next();
482
- while (!datum.done) {
483
- const guid = datum.value.guid;
484
- const tags = datum.value.tags.join(',');
485
- const cdate = datum.value.cdate;
486
- const mdate = datum.value.mdate;
487
- writeLine(`{${guid}}<${etype}>[${tags}]`);
488
- writeLine(`\tcdate=${JSON.stringify(cdate)}`);
489
- writeLine(`\tmdate=${JSON.stringify(mdate)}`);
490
- if (datum.value.dname != null) {
491
- do {
492
- const value = datum.value.dvalue === 'N'
493
- ? JSON.stringify(Number(datum.value.number))
494
- : datum.value.dvalue === 'S'
495
- ? JSON.stringify(datum.value.string)
496
- : datum.value.dvalue;
497
- writeLine(`\t${datum.value.dname}=${value}`);
498
- datum = dataIterator.next();
499
- } while (!datum.done && datum.value.guid === guid);
500
- }
501
- else {
450
+ let datum = dataIterator.next();
451
+ while (!datum.done) {
452
+ const guid = datum.value.guid;
453
+ const tags = datum.value.tags.join(',');
454
+ const cdate = datum.value.cdate;
455
+ const mdate = datum.value.mdate;
456
+ writeLine(`{${guid}}<${etype}>[${tags}]`);
457
+ writeLine(`\tcdate=${JSON.stringify(cdate)}`);
458
+ writeLine(`\tmdate=${JSON.stringify(mdate)}`);
459
+ if (datum.value.dname != null) {
460
+ do {
461
+ const value = datum.value.dvalue === 'N'
462
+ ? JSON.stringify(Number(datum.value.number))
463
+ : datum.value.dvalue === 'S'
464
+ ? JSON.stringify(datum.value.string)
465
+ : datum.value.dvalue;
466
+ writeLine(`\t${datum.value.dname}=${value}`);
502
467
  datum = dataIterator.next();
503
- }
468
+ } while (!datum.done && datum.value.guid === guid);
469
+ }
470
+ else {
471
+ datum = dataIterator.next();
504
472
  }
505
473
  }
506
- return;
507
- });
474
+ }
475
+ return;
508
476
  }
509
477
  makeEntityQuery(options, formattedSelectors, etype, count = { i: 0 }, params = {}, subquery = false, tableSuffix = '', etypes = []) {
510
- var _a, _b;
511
- if (typeof ((_a = options.class) === null || _a === void 0 ? void 0 : _a.alterOptions) === 'function') {
478
+ if (typeof options.class?.alterOptions === 'function') {
512
479
  options = options.class.alterOptions(options);
513
480
  }
514
481
  const eTable = `e${tableSuffix}`;
@@ -516,7 +483,8 @@ class PostgreSQLDriver extends nymph_1.NymphDriver {
516
483
  const cTable = `c${tableSuffix}`;
517
484
  const fTable = `f${tableSuffix}`;
518
485
  const ieTable = `ie${tableSuffix}`;
519
- const sort = (_b = options.sort) !== null && _b !== void 0 ? _b : 'cdate';
486
+ const countTable = `count${tableSuffix}`;
487
+ const sort = options.sort ?? 'cdate';
520
488
  const queryParts = this.iterateSelectorsForQuery(formattedSelectors, (key, value, typeIsOr, typeIsNot) => {
521
489
  const clauseNot = key.startsWith('!');
522
490
  let curQuery = '';
@@ -1265,7 +1233,7 @@ class PostgreSQLDriver extends nymph_1.NymphDriver {
1265
1233
  const [qrefOptions, ...qrefSelectors] = curValue[1];
1266
1234
  const QrefEntityClass = qrefOptions.class;
1267
1235
  etypes.push(QrefEntityClass.ETYPE);
1268
- const qrefQuery = this.makeEntityQuery(Object.assign(Object.assign({}, qrefOptions), { return: 'guid', class: QrefEntityClass }), qrefSelectors, QrefEntityClass.ETYPE, count, params, false, makeTableSuffix(), etypes);
1236
+ const qrefQuery = this.makeEntityQuery({ ...qrefOptions, return: 'guid', class: QrefEntityClass }, qrefSelectors, QrefEntityClass.ETYPE, count, params, false, (0, guid_1.makeTableSuffix)(), etypes);
1269
1237
  if (curQuery) {
1270
1238
  curQuery += typeIsOr ? ' OR ' : ' AND ';
1271
1239
  }
@@ -1314,18 +1282,32 @@ class PostgreSQLDriver extends nymph_1.NymphDriver {
1314
1282
  offset = ` OFFSET ${Math.floor(isNaN(Number(options.offset)) ? 0 : Number(options.offset))}`;
1315
1283
  }
1316
1284
  const whereClause = queryParts.join(') AND (');
1317
- if (options.return === 'guid') {
1285
+ if (options.return === 'count') {
1286
+ if (limit || offset) {
1287
+ query = `SELECT COUNT(${countTable}."guid") AS "count" FROM (
1288
+ SELECT COUNT(${ieTable}."guid") AS "guid"
1289
+ FROM ${PostgreSQLDriver.escape(`${this.prefix}entities_${etype}`)} ${ieTable}
1290
+ WHERE (${whereClause})${limit}${offset}
1291
+ ) ${countTable}`;
1292
+ }
1293
+ else {
1294
+ query = `SELECT COUNT(${ieTable}."guid") AS "count"
1295
+ FROM ${PostgreSQLDriver.escape(`${this.prefix}entities_${etype}`)} ${ieTable}
1296
+ WHERE (${whereClause})`;
1297
+ }
1298
+ }
1299
+ else if (options.return === 'guid') {
1318
1300
  const guidColumn = tableSuffix === ''
1319
1301
  ? `encode(${ieTable}."guid", 'hex')`
1320
1302
  : `${ieTable}."guid"`;
1321
- query = `SELECT ${guidColumn} as "guid"
1303
+ query = `SELECT ${guidColumn} AS "guid"
1322
1304
  FROM ${PostgreSQLDriver.escape(`${this.prefix}entities_${etype}`)} ${ieTable}
1323
1305
  WHERE (${whereClause})
1324
1306
  ORDER BY ${ieTable}.${sortBy}${limit}${offset}`;
1325
1307
  }
1326
1308
  else {
1327
1309
  query = `SELECT
1328
- encode(${eTable}."guid", 'hex') as "guid",
1310
+ encode(${eTable}."guid", 'hex') AS "guid",
1329
1311
  ${eTable}."tags",
1330
1312
  ${eTable}."cdate",
1331
1313
  ${eTable}."mdate",
@@ -1359,18 +1341,30 @@ class PostgreSQLDriver extends nymph_1.NymphDriver {
1359
1341
  if ('offset' in options) {
1360
1342
  offset = ` OFFSET ${Math.floor(isNaN(Number(options.offset)) ? 0 : Number(options.offset))}`;
1361
1343
  }
1362
- if (options.return === 'guid') {
1344
+ if (options.return === 'count') {
1345
+ if (limit || offset) {
1346
+ query = `SELECT COUNT(${countTable}."guid") AS "count" FROM (
1347
+ SELECT COUNT(${ieTable}."guid") AS "guid"
1348
+ FROM ${PostgreSQLDriver.escape(`${this.prefix}entities_${etype}`)} ${ieTable}${limit}${offset}
1349
+ ) ${countTable}`;
1350
+ }
1351
+ else {
1352
+ query = `SELECT COUNT(${ieTable}."guid") AS "count"
1353
+ FROM ${PostgreSQLDriver.escape(`${this.prefix}entities_${etype}`)} ${ieTable}`;
1354
+ }
1355
+ }
1356
+ else if (options.return === 'guid') {
1363
1357
  const guidColumn = tableSuffix === ''
1364
1358
  ? `encode(${ieTable}."guid", 'hex')`
1365
1359
  : `${ieTable}."guid"`;
1366
- query = `SELECT ${guidColumn} as "guid"
1360
+ query = `SELECT ${guidColumn} AS "guid"
1367
1361
  FROM ${PostgreSQLDriver.escape(`${this.prefix}entities_${etype}`)} ${ieTable}
1368
1362
  ORDER BY ${ieTable}.${sortBy}${limit}${offset}`;
1369
1363
  }
1370
1364
  else {
1371
1365
  if (limit || offset) {
1372
1366
  query = `SELECT
1373
- encode(${eTable}."guid", 'hex') as "guid",
1367
+ encode(${eTable}."guid", 'hex') AS "guid",
1374
1368
  ${eTable}."tags",
1375
1369
  ${eTable}."cdate",
1376
1370
  ${eTable}."mdate",
@@ -1390,7 +1384,7 @@ class PostgreSQLDriver extends nymph_1.NymphDriver {
1390
1384
  }
1391
1385
  else {
1392
1386
  query = `SELECT
1393
- encode(${eTable}."guid", 'hex') as "guid",
1387
+ encode(${eTable}."guid", 'hex') AS "guid",
1394
1388
  ${eTable}."tags",
1395
1389
  ${eTable}."cdate",
1396
1390
  ${eTable}."mdate",
@@ -1424,37 +1418,35 @@ class PostgreSQLDriver extends nymph_1.NymphDriver {
1424
1418
  }
1425
1419
  performQuerySync(options, formattedSelectors, etype) {
1426
1420
  const { query, params, etypes } = this.makeEntityQuery(options, formattedSelectors, etype);
1427
- const result = this.queryIterSync(query, { etypes, params })[Symbol.iterator]();
1421
+ const result = (this.queryIterSync(query, { etypes, params }) || [])[Symbol.iterator]();
1428
1422
  return {
1429
1423
  result,
1430
1424
  };
1431
1425
  }
1432
- getEntities(options = {}, ...selectors) {
1433
- return __awaiter(this, void 0, void 0, function* () {
1434
- const { result: resultPromise, process } = this.getEntitesRowLike(options, selectors, (options, formattedSelectors, etype) => this.performQuery(options, formattedSelectors, etype), () => {
1435
- const next = result.next();
1436
- return next.done ? null : next.value;
1437
- }, () => undefined, (row) => row.guid, (row) => ({
1438
- tags: row.tags,
1439
- cdate: isNaN(Number(row.cdate)) ? null : Number(row.cdate),
1440
- mdate: isNaN(Number(row.mdate)) ? null : Number(row.mdate),
1441
- }), (row) => ({
1442
- name: row.name,
1443
- svalue: row.value === 'N'
1444
- ? JSON.stringify(Number(row.number))
1445
- : row.value === 'S'
1446
- ? JSON.stringify(row.string)
1447
- : row.value,
1448
- }));
1449
- const result = yield resultPromise;
1450
- return process();
1451
- });
1426
+ async getEntities(options = {}, ...selectors) {
1427
+ const { result: resultPromise, process } = this.getEntitesRowLike(options, selectors, (options, formattedSelectors, etype) => this.performQuery(options, formattedSelectors, etype), () => {
1428
+ const next = result.next();
1429
+ return next.done ? null : next.value;
1430
+ }, () => undefined, (row) => Number(row.count), (row) => row.guid, (row) => ({
1431
+ tags: row.tags,
1432
+ cdate: isNaN(Number(row.cdate)) ? null : Number(row.cdate),
1433
+ mdate: isNaN(Number(row.mdate)) ? null : Number(row.mdate),
1434
+ }), (row) => ({
1435
+ name: row.name,
1436
+ svalue: row.value === 'N'
1437
+ ? JSON.stringify(Number(row.number))
1438
+ : row.value === 'S'
1439
+ ? JSON.stringify(row.string)
1440
+ : row.value,
1441
+ }));
1442
+ const result = await resultPromise;
1443
+ return process();
1452
1444
  }
1453
1445
  getEntitiesSync(options = {}, ...selectors) {
1454
1446
  const { result, process } = this.getEntitesRowLike(options, selectors, (options, formattedSelectors, etype) => this.performQuerySync(options, formattedSelectors, etype), () => {
1455
1447
  const next = result.next();
1456
1448
  return next.done ? null : next.value;
1457
- }, () => undefined, (row) => row.guid, (row) => ({
1449
+ }, () => undefined, (row) => Number(row.count), (row) => row.guid, (row) => ({
1458
1450
  tags: row.tags,
1459
1451
  cdate: isNaN(Number(row.cdate)) ? null : Number(row.cdate),
1460
1452
  mdate: isNaN(Number(row.mdate)) ? null : Number(row.mdate),
@@ -1468,219 +1460,72 @@ class PostgreSQLDriver extends nymph_1.NymphDriver {
1468
1460
  }));
1469
1461
  return process();
1470
1462
  }
1471
- getUID(name) {
1472
- return __awaiter(this, void 0, void 0, function* () {
1473
- if (name == null) {
1474
- throw new nymph_1.InvalidParametersError('Name not given for UID.');
1475
- }
1476
- const result = yield this.queryGet(`SELECT "cur_uid" FROM ${PostgreSQLDriver.escape(`${this.prefix}uids`)} WHERE "name"=@name;`, {
1477
- params: {
1478
- name: name,
1479
- },
1480
- });
1481
- return (result === null || result === void 0 ? void 0 : result.cur_uid) == null ? null : Number(result.cur_uid);
1482
- });
1483
- }
1484
- import(filename) {
1485
- return __awaiter(this, void 0, void 0, function* () {
1486
- try {
1487
- const result = yield this.importFromFile(filename, (guid, tags, sdata, etype) => __awaiter(this, void 0, void 0, function* () {
1488
- yield this.queryRun(`DELETE FROM ${PostgreSQLDriver.escape(`${this.prefix}entities_${etype}`)} WHERE "guid"=decode(@guid, 'hex');`, {
1489
- etypes: [etype],
1490
- params: {
1491
- guid,
1492
- },
1493
- });
1494
- yield this.queryRun(`INSERT INTO ${PostgreSQLDriver.escape(`${this.prefix}entities_${etype}`)} ("guid", "tags", "cdate", "mdate") VALUES (decode(@guid, 'hex'), @tags, @cdate, @mdate);`, {
1495
- etypes: [etype],
1496
- params: {
1497
- guid,
1498
- tags,
1499
- cdate: isNaN(Number(JSON.parse(sdata.cdate)))
1500
- ? null
1501
- : Number(JSON.parse(sdata.cdate)),
1502
- mdate: isNaN(Number(JSON.parse(sdata.mdate)))
1503
- ? null
1504
- : Number(JSON.parse(sdata.mdate)),
1505
- },
1506
- });
1507
- const promises = [];
1508
- promises.push(this.queryRun(`DELETE FROM ${PostgreSQLDriver.escape(`${this.prefix}data_${etype}`)} WHERE "guid"=decode(@guid, 'hex');`, {
1509
- etypes: [etype],
1510
- params: {
1511
- guid,
1512
- },
1513
- }));
1514
- promises.push(this.queryRun(`DELETE FROM ${PostgreSQLDriver.escape(`${this.prefix}comparisons_${etype}`)} WHERE "guid"=decode(@guid, 'hex');`, {
1515
- etypes: [etype],
1516
- params: {
1517
- guid,
1518
- },
1519
- }));
1520
- promises.push(this.queryRun(`DELETE FROM ${PostgreSQLDriver.escape(`${this.prefix}references_${etype}`)} WHERE "guid"=decode(@guid, 'hex');`, {
1521
- etypes: [etype],
1522
- params: {
1523
- guid,
1524
- },
1525
- }));
1526
- yield Promise.all(promises);
1527
- delete sdata.cdate;
1528
- delete sdata.mdate;
1529
- for (const name in sdata) {
1530
- const value = sdata[name];
1531
- const uvalue = JSON.parse(value);
1532
- if (value === undefined) {
1533
- continue;
1534
- }
1535
- const storageValue = typeof uvalue === 'number'
1536
- ? 'N'
1537
- : typeof uvalue === 'string'
1538
- ? 'S'
1539
- : value;
1540
- const promises = [];
1541
- promises.push(this.queryRun(`INSERT INTO ${PostgreSQLDriver.escape(`${this.prefix}data_${etype}`)} ("guid", "name", "value") VALUES (decode(@guid, 'hex'), @name, @storageValue);`, {
1542
- etypes: [etype],
1543
- params: {
1544
- guid,
1545
- name,
1546
- storageValue,
1547
- },
1548
- }));
1549
- promises.push(this.queryRun(`INSERT INTO ${PostgreSQLDriver.escape(`${this.prefix}comparisons_${etype}`)} ("guid", "name", "truthy", "string", "number") VALUES (decode(@guid, 'hex'), @name, @truthy, @string, @number);`, {
1550
- etypes: [etype],
1551
- params: {
1552
- guid,
1553
- name,
1554
- truthy: !!uvalue,
1555
- string: `${uvalue}`,
1556
- number: isNaN(Number(uvalue)) ? null : Number(uvalue),
1557
- },
1558
- }));
1559
- const references = this.findReferences(value);
1560
- for (const reference of references) {
1561
- promises.push(this.queryRun(`INSERT INTO ${PostgreSQLDriver.escape(`${this.prefix}references_${etype}`)} ("guid", "name", "reference") VALUES (decode(@guid, 'hex'), @name, decode(@reference, 'hex'));`, {
1562
- etypes: [etype],
1563
- params: {
1564
- guid,
1565
- name,
1566
- reference,
1567
- },
1568
- }));
1569
- }
1570
- }
1571
- yield Promise.all(promises);
1572
- }), (name, curUid) => __awaiter(this, void 0, void 0, function* () {
1573
- yield this.queryRun(`DELETE FROM ${PostgreSQLDriver.escape(`${this.prefix}uids`)} WHERE "name"=@name;`, {
1574
- params: {
1575
- name,
1576
- },
1577
- });
1578
- yield this.queryRun(`INSERT INTO ${PostgreSQLDriver.escape(`${this.prefix}uids`)} ("name", "cur_uid") VALUES (@name, @curUid);`, {
1579
- params: {
1580
- name,
1581
- curUid,
1582
- },
1583
- });
1584
- }), () => __awaiter(this, void 0, void 0, function* () {
1585
- yield this.internalTransaction('nymph-import');
1586
- }), () => __awaiter(this, void 0, void 0, function* () {
1587
- yield this.commit('nymph-import');
1588
- }));
1589
- return result;
1590
- }
1591
- catch (e) {
1592
- yield this.rollback('nymph-import');
1593
- return false;
1594
- }
1463
+ async getUID(name) {
1464
+ if (name == null) {
1465
+ throw new nymph_1.InvalidParametersError('Name not given for UID.');
1466
+ }
1467
+ const result = await this.queryGet(`SELECT "cur_uid" FROM ${PostgreSQLDriver.escape(`${this.prefix}uids`)} WHERE "name"=@name;`, {
1468
+ params: {
1469
+ name: name,
1470
+ },
1595
1471
  });
1472
+ return result?.cur_uid == null ? null : Number(result.cur_uid);
1596
1473
  }
1597
- newUID(name) {
1598
- return __awaiter(this, void 0, void 0, function* () {
1599
- if (name == null) {
1600
- throw new nymph_1.InvalidParametersError('Name not given for UID.');
1601
- }
1602
- yield this.internalTransaction('nymph-newuid');
1603
- try {
1604
- const lock = yield this.queryGet(`SELECT "cur_uid" FROM ${PostgreSQLDriver.escape(`${this.prefix}uids`)} WHERE "name"=@name FOR UPDATE;`, {
1474
+ async import(filename) {
1475
+ try {
1476
+ const result = await this.importFromFile(filename, async (guid, tags, sdata, etype) => {
1477
+ await this.queryRun(`DELETE FROM ${PostgreSQLDriver.escape(`${this.prefix}entities_${etype}`)} WHERE "guid"=decode(@guid, 'hex');`, {
1478
+ etypes: [etype],
1605
1479
  params: {
1606
- name,
1480
+ guid,
1607
1481
  },
1608
1482
  });
1609
- let curUid = (lock === null || lock === void 0 ? void 0 : lock.cur_uid) == null ? undefined : Number(lock.cur_uid);
1610
- if (curUid == null) {
1611
- curUid = 1;
1612
- yield this.queryRun(`INSERT INTO ${PostgreSQLDriver.escape(`${this.prefix}uids`)} ("name", "cur_uid") VALUES (@name, @curUid);`, {
1613
- params: {
1614
- name,
1615
- curUid,
1616
- },
1617
- });
1618
- }
1619
- else {
1620
- curUid++;
1621
- yield this.queryRun(`UPDATE ${PostgreSQLDriver.escape(`${this.prefix}uids`)} SET "cur_uid"=@curUid WHERE "name"=@name;`, {
1622
- params: {
1623
- name,
1624
- curUid,
1625
- },
1626
- });
1627
- }
1628
- yield this.commit('nymph-newuid');
1629
- return curUid;
1630
- }
1631
- catch (e) {
1632
- yield this.rollback('nymph-newuid');
1633
- throw e;
1634
- }
1635
- });
1636
- }
1637
- renameUID(oldName, newName) {
1638
- return __awaiter(this, void 0, void 0, function* () {
1639
- if (oldName == null || newName == null) {
1640
- throw new nymph_1.InvalidParametersError('Name not given for UID.');
1641
- }
1642
- yield this.queryRun(`UPDATE ${PostgreSQLDriver.escape(`${this.prefix}uids`)} SET "name"=@newName WHERE "name"=@oldName;`, {
1643
- params: {
1644
- newName,
1645
- oldName,
1646
- },
1647
- });
1648
- return true;
1649
- });
1650
- }
1651
- rollback(name) {
1652
- var _a;
1653
- return __awaiter(this, void 0, void 0, function* () {
1654
- if (name == null || typeof name !== 'string' || name.length === 0) {
1655
- throw new nymph_1.InvalidParametersError('Transaction rollback attempted without a name.');
1656
- }
1657
- if (!this.transaction || this.transaction.count === 0) {
1658
- this.transaction = null;
1659
- return true;
1660
- }
1661
- yield this.queryRun(`ROLLBACK TO SAVEPOINT ${PostgreSQLDriver.escape(name)};`);
1662
- this.transaction.count--;
1663
- if (this.transaction.count === 0) {
1664
- yield this.queryRun('ROLLBACK;');
1665
- (_a = this.transaction.connection) === null || _a === void 0 ? void 0 : _a.done();
1666
- this.transaction.connection = null;
1667
- this.transaction = null;
1668
- }
1669
- return true;
1670
- });
1671
- }
1672
- saveEntity(entity) {
1673
- return __awaiter(this, void 0, void 0, function* () {
1674
- const insertData = (guid, data, sdata, etype) => __awaiter(this, void 0, void 0, function* () {
1675
- const runInsertQuery = (name, value, svalue) => __awaiter(this, void 0, void 0, function* () {
1483
+ await this.queryRun(`INSERT INTO ${PostgreSQLDriver.escape(`${this.prefix}entities_${etype}`)} ("guid", "tags", "cdate", "mdate") VALUES (decode(@guid, 'hex'), @tags, @cdate, @mdate);`, {
1484
+ etypes: [etype],
1485
+ params: {
1486
+ guid,
1487
+ tags,
1488
+ cdate: isNaN(Number(JSON.parse(sdata.cdate)))
1489
+ ? null
1490
+ : Number(JSON.parse(sdata.cdate)),
1491
+ mdate: isNaN(Number(JSON.parse(sdata.mdate)))
1492
+ ? null
1493
+ : Number(JSON.parse(sdata.mdate)),
1494
+ },
1495
+ });
1496
+ const promises = [];
1497
+ promises.push(this.queryRun(`DELETE FROM ${PostgreSQLDriver.escape(`${this.prefix}data_${etype}`)} WHERE "guid"=decode(@guid, 'hex');`, {
1498
+ etypes: [etype],
1499
+ params: {
1500
+ guid,
1501
+ },
1502
+ }));
1503
+ promises.push(this.queryRun(`DELETE FROM ${PostgreSQLDriver.escape(`${this.prefix}comparisons_${etype}`)} WHERE "guid"=decode(@guid, 'hex');`, {
1504
+ etypes: [etype],
1505
+ params: {
1506
+ guid,
1507
+ },
1508
+ }));
1509
+ promises.push(this.queryRun(`DELETE FROM ${PostgreSQLDriver.escape(`${this.prefix}references_${etype}`)} WHERE "guid"=decode(@guid, 'hex');`, {
1510
+ etypes: [etype],
1511
+ params: {
1512
+ guid,
1513
+ },
1514
+ }));
1515
+ await Promise.all(promises);
1516
+ delete sdata.cdate;
1517
+ delete sdata.mdate;
1518
+ for (const name in sdata) {
1519
+ const value = sdata[name];
1520
+ const uvalue = JSON.parse(value);
1676
1521
  if (value === undefined) {
1677
- return;
1522
+ continue;
1678
1523
  }
1679
- const storageValue = typeof value === 'number'
1524
+ const storageValue = typeof uvalue === 'number'
1680
1525
  ? 'N'
1681
- : typeof value === 'string'
1526
+ : typeof uvalue === 'string'
1682
1527
  ? 'S'
1683
- : svalue;
1528
+ : value;
1684
1529
  const promises = [];
1685
1530
  promises.push(this.queryRun(`INSERT INTO ${PostgreSQLDriver.escape(`${this.prefix}data_${etype}`)} ("guid", "name", "value") VALUES (decode(@guid, 'hex'), @name, @storageValue);`, {
1686
1531
  etypes: [etype],
@@ -1695,12 +1540,12 @@ class PostgreSQLDriver extends nymph_1.NymphDriver {
1695
1540
  params: {
1696
1541
  guid,
1697
1542
  name,
1698
- truthy: !!value,
1699
- string: `${value}`,
1700
- number: isNaN(Number(value)) ? null : Number(value),
1543
+ truthy: !!uvalue,
1544
+ string: `${uvalue}`,
1545
+ number: isNaN(Number(uvalue)) ? null : Number(uvalue),
1701
1546
  },
1702
1547
  }));
1703
- const references = this.findReferences(svalue);
1548
+ const references = this.findReferences(value);
1704
1549
  for (const reference of references) {
1705
1550
  promises.push(this.queryRun(`INSERT INTO ${PostgreSQLDriver.escape(`${this.prefix}references_${etype}`)} ("guid", "name", "reference") VALUES (decode(@guid, 'hex'), @name, decode(@reference, 'hex'));`, {
1706
1551
  etypes: [etype],
@@ -1711,165 +1556,293 @@ class PostgreSQLDriver extends nymph_1.NymphDriver {
1711
1556
  },
1712
1557
  }));
1713
1558
  }
1714
- yield Promise.all(promises);
1715
- });
1716
- for (const name in data) {
1717
- yield runInsertQuery(name, data[name], JSON.stringify(data[name]));
1718
- }
1719
- for (const name in sdata) {
1720
- yield runInsertQuery(name, JSON.parse(sdata[name]), sdata[name]);
1721
1559
  }
1560
+ await Promise.all(promises);
1561
+ }, async (name, curUid) => {
1562
+ await this.queryRun(`DELETE FROM ${PostgreSQLDriver.escape(`${this.prefix}uids`)} WHERE "name"=@name;`, {
1563
+ params: {
1564
+ name,
1565
+ },
1566
+ });
1567
+ await this.queryRun(`INSERT INTO ${PostgreSQLDriver.escape(`${this.prefix}uids`)} ("name", "cur_uid") VALUES (@name, @curUid);`, {
1568
+ params: {
1569
+ name,
1570
+ curUid,
1571
+ },
1572
+ });
1573
+ }, async () => {
1574
+ await this.internalTransaction('nymph-import');
1575
+ }, async () => {
1576
+ await this.commit('nymph-import');
1722
1577
  });
1723
- try {
1724
- const result = yield this.saveEntityRowLike(entity, (_entity, guid, tags, data, sdata, cdate, etype) => __awaiter(this, void 0, void 0, function* () {
1725
- yield this.queryRun(`INSERT INTO ${PostgreSQLDriver.escape(`${this.prefix}entities_${etype}`)} ("guid", "tags", "cdate", "mdate") VALUES (decode(@guid, 'hex'), @tags, @cdate, @cdate);`, {
1726
- etypes: [etype],
1727
- params: {
1728
- guid,
1729
- tags,
1730
- cdate,
1731
- },
1732
- });
1733
- yield insertData(guid, data, sdata, etype);
1734
- return true;
1735
- }), (entity, guid, tags, data, sdata, mdate, etype) => __awaiter(this, void 0, void 0, function* () {
1736
- const promises = [];
1737
- promises.push(this.queryRun(`SELECT 1 FROM ${PostgreSQLDriver.escape(`${this.prefix}entities_${etype}`)} WHERE "guid"=decode(@guid, 'hex') FOR UPDATE;`, {
1578
+ return result;
1579
+ }
1580
+ catch (e) {
1581
+ await this.rollback('nymph-import');
1582
+ return false;
1583
+ }
1584
+ }
1585
+ async newUID(name) {
1586
+ if (name == null) {
1587
+ throw new nymph_1.InvalidParametersError('Name not given for UID.');
1588
+ }
1589
+ await this.internalTransaction('nymph-newuid');
1590
+ try {
1591
+ const lock = await this.queryGet(`SELECT "cur_uid" FROM ${PostgreSQLDriver.escape(`${this.prefix}uids`)} WHERE "name"=@name FOR UPDATE;`, {
1592
+ params: {
1593
+ name,
1594
+ },
1595
+ });
1596
+ let curUid = lock?.cur_uid == null ? undefined : Number(lock.cur_uid);
1597
+ if (curUid == null) {
1598
+ curUid = 1;
1599
+ await this.queryRun(`INSERT INTO ${PostgreSQLDriver.escape(`${this.prefix}uids`)} ("name", "cur_uid") VALUES (@name, @curUid);`, {
1600
+ params: {
1601
+ name,
1602
+ curUid,
1603
+ },
1604
+ });
1605
+ }
1606
+ else {
1607
+ curUid++;
1608
+ await this.queryRun(`UPDATE ${PostgreSQLDriver.escape(`${this.prefix}uids`)} SET "cur_uid"=@curUid WHERE "name"=@name;`, {
1609
+ params: {
1610
+ name,
1611
+ curUid,
1612
+ },
1613
+ });
1614
+ }
1615
+ await this.commit('nymph-newuid');
1616
+ return curUid;
1617
+ }
1618
+ catch (e) {
1619
+ await this.rollback('nymph-newuid');
1620
+ throw e;
1621
+ }
1622
+ }
1623
+ async renameUID(oldName, newName) {
1624
+ if (oldName == null || newName == null) {
1625
+ throw new nymph_1.InvalidParametersError('Name not given for UID.');
1626
+ }
1627
+ await this.queryRun(`UPDATE ${PostgreSQLDriver.escape(`${this.prefix}uids`)} SET "name"=@newName WHERE "name"=@oldName;`, {
1628
+ params: {
1629
+ newName,
1630
+ oldName,
1631
+ },
1632
+ });
1633
+ return true;
1634
+ }
1635
+ async rollback(name) {
1636
+ if (name == null || typeof name !== 'string' || name.length === 0) {
1637
+ throw new nymph_1.InvalidParametersError('Transaction rollback attempted without a name.');
1638
+ }
1639
+ if (!this.transaction || this.transaction.count === 0) {
1640
+ this.transaction = null;
1641
+ return true;
1642
+ }
1643
+ await this.queryRun(`ROLLBACK TO SAVEPOINT ${PostgreSQLDriver.escape(name)};`);
1644
+ this.transaction.count--;
1645
+ if (this.transaction.count === 0) {
1646
+ await this.queryRun('ROLLBACK;');
1647
+ this.transaction.connection?.done();
1648
+ this.transaction.connection = null;
1649
+ this.transaction = null;
1650
+ }
1651
+ return true;
1652
+ }
1653
+ async saveEntity(entity) {
1654
+ const insertData = async (guid, data, sdata, etype) => {
1655
+ const runInsertQuery = async (name, value, svalue) => {
1656
+ if (value === undefined) {
1657
+ return;
1658
+ }
1659
+ const storageValue = typeof value === 'number'
1660
+ ? 'N'
1661
+ : typeof value === 'string'
1662
+ ? 'S'
1663
+ : svalue;
1664
+ const promises = [];
1665
+ promises.push(this.queryRun(`INSERT INTO ${PostgreSQLDriver.escape(`${this.prefix}data_${etype}`)} ("guid", "name", "value") VALUES (decode(@guid, 'hex'), @name, @storageValue);`, {
1666
+ etypes: [etype],
1667
+ params: {
1668
+ guid,
1669
+ name,
1670
+ storageValue,
1671
+ },
1672
+ }));
1673
+ promises.push(this.queryRun(`INSERT INTO ${PostgreSQLDriver.escape(`${this.prefix}comparisons_${etype}`)} ("guid", "name", "truthy", "string", "number") VALUES (decode(@guid, 'hex'), @name, @truthy, @string, @number);`, {
1674
+ etypes: [etype],
1675
+ params: {
1676
+ guid,
1677
+ name,
1678
+ truthy: !!value,
1679
+ string: `${value}`,
1680
+ number: isNaN(Number(value)) ? null : Number(value),
1681
+ },
1682
+ }));
1683
+ const references = this.findReferences(svalue);
1684
+ for (const reference of references) {
1685
+ promises.push(this.queryRun(`INSERT INTO ${PostgreSQLDriver.escape(`${this.prefix}references_${etype}`)} ("guid", "name", "reference") VALUES (decode(@guid, 'hex'), @name, decode(@reference, 'hex'));`, {
1738
1686
  etypes: [etype],
1739
1687
  params: {
1740
1688
  guid,
1689
+ name,
1690
+ reference,
1741
1691
  },
1742
1692
  }));
1743
- promises.push(this.queryRun(`SELECT 1 FROM ${PostgreSQLDriver.escape(`${this.prefix}data_${etype}`)} WHERE "guid"=decode(@guid, 'hex') FOR UPDATE;`, {
1693
+ }
1694
+ await Promise.all(promises);
1695
+ };
1696
+ for (const name in data) {
1697
+ await runInsertQuery(name, data[name], JSON.stringify(data[name]));
1698
+ }
1699
+ for (const name in sdata) {
1700
+ await runInsertQuery(name, JSON.parse(sdata[name]), sdata[name]);
1701
+ }
1702
+ };
1703
+ try {
1704
+ const result = await this.saveEntityRowLike(entity, async (_entity, guid, tags, data, sdata, cdate, etype) => {
1705
+ await this.queryRun(`INSERT INTO ${PostgreSQLDriver.escape(`${this.prefix}entities_${etype}`)} ("guid", "tags", "cdate", "mdate") VALUES (decode(@guid, 'hex'), @tags, @cdate, @cdate);`, {
1706
+ etypes: [etype],
1707
+ params: {
1708
+ guid,
1709
+ tags,
1710
+ cdate,
1711
+ },
1712
+ });
1713
+ await insertData(guid, data, sdata, etype);
1714
+ return true;
1715
+ }, async (entity, guid, tags, data, sdata, mdate, etype) => {
1716
+ const promises = [];
1717
+ promises.push(this.queryRun(`SELECT 1 FROM ${PostgreSQLDriver.escape(`${this.prefix}entities_${etype}`)} WHERE "guid"=decode(@guid, 'hex') FOR UPDATE;`, {
1718
+ etypes: [etype],
1719
+ params: {
1720
+ guid,
1721
+ },
1722
+ }));
1723
+ promises.push(this.queryRun(`SELECT 1 FROM ${PostgreSQLDriver.escape(`${this.prefix}data_${etype}`)} WHERE "guid"=decode(@guid, 'hex') FOR UPDATE;`, {
1724
+ etypes: [etype],
1725
+ params: {
1726
+ guid,
1727
+ },
1728
+ }));
1729
+ promises.push(this.queryRun(`SELECT 1 FROM ${PostgreSQLDriver.escape(`${this.prefix}comparisons_${etype}`)} WHERE "guid"=decode(@guid, 'hex') FOR UPDATE;`, {
1730
+ etypes: [etype],
1731
+ params: {
1732
+ guid,
1733
+ },
1734
+ }));
1735
+ promises.push(this.queryRun(`SELECT 1 FROM ${PostgreSQLDriver.escape(`${this.prefix}references_${etype}`)} WHERE "guid"=decode(@guid, 'hex') FOR UPDATE;`, {
1736
+ etypes: [etype],
1737
+ params: {
1738
+ guid,
1739
+ },
1740
+ }));
1741
+ await Promise.all(promises);
1742
+ const info = await this.queryRun(`UPDATE ${PostgreSQLDriver.escape(`${this.prefix}entities_${etype}`)} SET "tags"=@tags, "mdate"=@mdate WHERE "guid"=decode(@guid, 'hex') AND "mdate" <= @emdate;`, {
1743
+ etypes: [etype],
1744
+ params: {
1745
+ tags,
1746
+ mdate,
1747
+ guid,
1748
+ emdate: isNaN(Number(entity.mdate)) ? 0 : Number(entity.mdate),
1749
+ },
1750
+ });
1751
+ let success = false;
1752
+ if (info.rowCount === 1) {
1753
+ const promises = [];
1754
+ promises.push(this.queryRun(`DELETE FROM ${PostgreSQLDriver.escape(`${this.prefix}data_${etype}`)} WHERE "guid"=decode(@guid, 'hex');`, {
1744
1755
  etypes: [etype],
1745
1756
  params: {
1746
1757
  guid,
1747
1758
  },
1748
1759
  }));
1749
- promises.push(this.queryRun(`SELECT 1 FROM ${PostgreSQLDriver.escape(`${this.prefix}comparisons_${etype}`)} WHERE "guid"=decode(@guid, 'hex') FOR UPDATE;`, {
1760
+ promises.push(this.queryRun(`DELETE FROM ${PostgreSQLDriver.escape(`${this.prefix}comparisons_${etype}`)} WHERE "guid"=decode(@guid, 'hex');`, {
1750
1761
  etypes: [etype],
1751
1762
  params: {
1752
1763
  guid,
1753
1764
  },
1754
1765
  }));
1755
- promises.push(this.queryRun(`SELECT 1 FROM ${PostgreSQLDriver.escape(`${this.prefix}references_${etype}`)} WHERE "guid"=decode(@guid, 'hex') FOR UPDATE;`, {
1766
+ promises.push(this.queryRun(`DELETE FROM ${PostgreSQLDriver.escape(`${this.prefix}references_${etype}`)} WHERE "guid"=decode(@guid, 'hex');`, {
1756
1767
  etypes: [etype],
1757
1768
  params: {
1758
1769
  guid,
1759
1770
  },
1760
1771
  }));
1761
- yield Promise.all(promises);
1762
- const info = yield this.queryRun(`UPDATE ${PostgreSQLDriver.escape(`${this.prefix}entities_${etype}`)} SET "tags"=@tags, "mdate"=@mdate WHERE "guid"=decode(@guid, 'hex') AND "mdate" <= @emdate;`, {
1763
- etypes: [etype],
1764
- params: {
1765
- tags,
1766
- mdate,
1767
- guid,
1768
- emdate: isNaN(Number(entity.mdate)) ? 0 : Number(entity.mdate),
1769
- },
1770
- });
1771
- let success = false;
1772
- if (info.rowCount === 1) {
1773
- const promises = [];
1774
- promises.push(this.queryRun(`DELETE FROM ${PostgreSQLDriver.escape(`${this.prefix}data_${etype}`)} WHERE "guid"=decode(@guid, 'hex');`, {
1775
- etypes: [etype],
1776
- params: {
1777
- guid,
1778
- },
1779
- }));
1780
- promises.push(this.queryRun(`DELETE FROM ${PostgreSQLDriver.escape(`${this.prefix}comparisons_${etype}`)} WHERE "guid"=decode(@guid, 'hex');`, {
1781
- etypes: [etype],
1782
- params: {
1783
- guid,
1784
- },
1785
- }));
1786
- promises.push(this.queryRun(`DELETE FROM ${PostgreSQLDriver.escape(`${this.prefix}references_${etype}`)} WHERE "guid"=decode(@guid, 'hex');`, {
1787
- etypes: [etype],
1788
- params: {
1789
- guid,
1790
- },
1791
- }));
1792
- yield Promise.all(promises);
1793
- yield insertData(guid, data, sdata, etype);
1794
- success = true;
1795
- }
1796
- return success;
1797
- }), () => __awaiter(this, void 0, void 0, function* () {
1798
- yield this.internalTransaction('nymph-save');
1799
- }), (success) => __awaiter(this, void 0, void 0, function* () {
1800
- if (success) {
1801
- yield this.commit('nymph-save');
1802
- }
1803
- else {
1804
- yield this.rollback('nymph-save');
1805
- }
1806
- return success;
1807
- }));
1808
- return result;
1809
- }
1810
- catch (e) {
1811
- yield this.rollback('nymph-save');
1812
- throw e;
1813
- }
1814
- });
1772
+ await Promise.all(promises);
1773
+ await insertData(guid, data, sdata, etype);
1774
+ success = true;
1775
+ }
1776
+ return success;
1777
+ }, async () => {
1778
+ await this.internalTransaction('nymph-save');
1779
+ }, async (success) => {
1780
+ if (success) {
1781
+ await this.commit('nymph-save');
1782
+ }
1783
+ else {
1784
+ await this.rollback('nymph-save');
1785
+ }
1786
+ return success;
1787
+ });
1788
+ return result;
1789
+ }
1790
+ catch (e) {
1791
+ await this.rollback('nymph-save');
1792
+ throw e;
1793
+ }
1815
1794
  }
1816
- setUID(name, curUid) {
1817
- return __awaiter(this, void 0, void 0, function* () {
1818
- if (name == null) {
1819
- throw new nymph_1.InvalidParametersError('Name not given for UID.');
1820
- }
1821
- yield this.internalTransaction('nymph-setuid');
1822
- try {
1823
- yield this.queryRun(`DELETE FROM ${PostgreSQLDriver.escape(`${this.prefix}uids`)} WHERE "name"=@name;`, {
1824
- params: {
1825
- name,
1826
- curUid,
1827
- },
1828
- });
1829
- yield this.queryRun(`INSERT INTO ${PostgreSQLDriver.escape(`${this.prefix}uids`)} ("name", "cur_uid") VALUES (@name, @curUid);`, {
1830
- params: {
1831
- name,
1832
- curUid,
1833
- },
1834
- });
1835
- yield this.commit('nymph-setuid');
1836
- return true;
1837
- }
1838
- catch (e) {
1839
- yield this.rollback('nymph-setuid');
1840
- throw e;
1841
- }
1842
- });
1795
+ async setUID(name, curUid) {
1796
+ if (name == null) {
1797
+ throw new nymph_1.InvalidParametersError('Name not given for UID.');
1798
+ }
1799
+ await this.internalTransaction('nymph-setuid');
1800
+ try {
1801
+ await this.queryRun(`DELETE FROM ${PostgreSQLDriver.escape(`${this.prefix}uids`)} WHERE "name"=@name;`, {
1802
+ params: {
1803
+ name,
1804
+ curUid,
1805
+ },
1806
+ });
1807
+ await this.queryRun(`INSERT INTO ${PostgreSQLDriver.escape(`${this.prefix}uids`)} ("name", "cur_uid") VALUES (@name, @curUid);`, {
1808
+ params: {
1809
+ name,
1810
+ curUid,
1811
+ },
1812
+ });
1813
+ await this.commit('nymph-setuid');
1814
+ return true;
1815
+ }
1816
+ catch (e) {
1817
+ await this.rollback('nymph-setuid');
1818
+ throw e;
1819
+ }
1843
1820
  }
1844
- internalTransaction(name) {
1845
- return __awaiter(this, void 0, void 0, function* () {
1846
- if (name == null || typeof name !== 'string' || name.length === 0) {
1847
- throw new nymph_1.InvalidParametersError('Transaction start attempted without a name.');
1848
- }
1849
- if (!this.transaction || this.transaction.count === 0) {
1850
- this.transaction = {
1851
- count: 0,
1852
- connection: yield this.getConnection(),
1853
- };
1854
- yield this.queryRun('BEGIN;');
1855
- }
1856
- yield this.queryRun(`SAVEPOINT ${PostgreSQLDriver.escape(name)};`);
1857
- this.transaction.count++;
1858
- return this.transaction;
1859
- });
1821
+ async internalTransaction(name) {
1822
+ if (name == null || typeof name !== 'string' || name.length === 0) {
1823
+ throw new nymph_1.InvalidParametersError('Transaction start attempted without a name.');
1824
+ }
1825
+ if (!this.transaction || this.transaction.count === 0) {
1826
+ this.transaction = {
1827
+ count: 0,
1828
+ connection: await this.getConnection(),
1829
+ };
1830
+ await this.queryRun('BEGIN;');
1831
+ }
1832
+ await this.queryRun(`SAVEPOINT ${PostgreSQLDriver.escape(name)};`);
1833
+ this.transaction.count++;
1834
+ return this.transaction;
1860
1835
  }
1861
- startTransaction(name) {
1862
- return __awaiter(this, void 0, void 0, function* () {
1863
- const inTransaction = this.inTransaction();
1864
- const transaction = yield this.internalTransaction(name);
1865
- if (!inTransaction) {
1866
- this.transaction = null;
1867
- }
1868
- const nymph = this.nymph.clone();
1869
- nymph.driver = new PostgreSQLDriver(this.config, this.link, transaction);
1870
- nymph.driver.init(nymph);
1871
- return nymph;
1872
- });
1836
+ async startTransaction(name) {
1837
+ const inTransaction = this.inTransaction();
1838
+ const transaction = await this.internalTransaction(name);
1839
+ if (!inTransaction) {
1840
+ this.transaction = null;
1841
+ }
1842
+ const nymph = this.nymph.clone();
1843
+ nymph.driver = new PostgreSQLDriver(this.config, this.link, transaction);
1844
+ nymph.driver.init(nymph);
1845
+ return nymph;
1873
1846
  }
1874
1847
  }
1875
1848
  exports.default = PostgreSQLDriver;