@nymphjs/driver-postgresql 1.0.0-beta.98 → 1.0.0-beta.99
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/CHANGELOG.md +14 -0
- package/dist/PostgreSQLDriver.d.ts +18 -2
- package/dist/PostgreSQLDriver.js +454 -165
- package/dist/PostgreSQLDriver.js.map +1 -1
- package/package.json +5 -4
- package/src/PostgreSQLDriver.ts +1075 -618
package/src/PostgreSQLDriver.ts
CHANGED
|
@@ -2,6 +2,12 @@ import pg from 'pg';
|
|
|
2
2
|
import type { Pool, PoolClient, PoolConfig, QueryResult } from 'pg';
|
|
3
3
|
import format from 'pg-format';
|
|
4
4
|
import Cursor from 'pg-cursor';
|
|
5
|
+
import type {
|
|
6
|
+
SearchTerm,
|
|
7
|
+
SearchOrTerm,
|
|
8
|
+
SearchNotTerm,
|
|
9
|
+
SearchSeriesTerm,
|
|
10
|
+
} from '@sciactive/tokenizer';
|
|
5
11
|
import {
|
|
6
12
|
NymphDriver,
|
|
7
13
|
type EntityConstructor,
|
|
@@ -239,87 +245,88 @@ export default class PostgreSQLDriver extends NymphDriver {
|
|
|
239
245
|
return this.connected;
|
|
240
246
|
}
|
|
241
247
|
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
// Create the entity table.
|
|
252
|
-
await this.queryRun(
|
|
253
|
-
`CREATE TABLE IF NOT EXISTS ${PostgreSQLDriver.escape(
|
|
254
|
-
`${this.prefix}entities_${etype}`,
|
|
255
|
-
)} (
|
|
248
|
+
private async createEntitiesTable(
|
|
249
|
+
etype: string,
|
|
250
|
+
connection: PostgreSQLDriverConnection,
|
|
251
|
+
) {
|
|
252
|
+
// Create the entity table.
|
|
253
|
+
await this.queryRun(
|
|
254
|
+
`CREATE TABLE IF NOT EXISTS ${PostgreSQLDriver.escape(
|
|
255
|
+
`${this.prefix}entities_${etype}`,
|
|
256
|
+
)} (
|
|
256
257
|
"guid" BYTEA NOT NULL,
|
|
257
258
|
"tags" TEXT[],
|
|
258
259
|
"cdate" DOUBLE PRECISION NOT NULL,
|
|
259
260
|
"mdate" DOUBLE PRECISION NOT NULL,
|
|
260
261
|
PRIMARY KEY ("guid")
|
|
261
262
|
) WITH ( OIDS=FALSE );`,
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
263
|
+
{ connection },
|
|
264
|
+
);
|
|
265
|
+
await this.queryRun(
|
|
266
|
+
`ALTER TABLE ${PostgreSQLDriver.escape(
|
|
267
|
+
`${this.prefix}entities_${etype}`,
|
|
268
|
+
)} OWNER TO ${PostgreSQLDriver.escape(this.config.user)};`,
|
|
269
|
+
{ connection },
|
|
270
|
+
);
|
|
271
|
+
await this.queryRun(
|
|
272
|
+
`DROP INDEX IF EXISTS ${PostgreSQLDriver.escape(
|
|
273
|
+
`${this.prefix}entities_${etype}_id_cdate`,
|
|
274
|
+
)};`,
|
|
275
|
+
{ connection },
|
|
276
|
+
);
|
|
277
|
+
await this.queryRun(
|
|
278
|
+
`CREATE INDEX ${PostgreSQLDriver.escape(
|
|
279
|
+
`${this.prefix}entities_${etype}_id_cdate`,
|
|
280
|
+
)} ON ${PostgreSQLDriver.escape(
|
|
281
|
+
`${this.prefix}entities_${etype}`,
|
|
282
|
+
)} USING btree ("cdate");`,
|
|
283
|
+
{ connection },
|
|
284
|
+
);
|
|
285
|
+
await this.queryRun(
|
|
286
|
+
`DROP INDEX IF EXISTS ${PostgreSQLDriver.escape(
|
|
287
|
+
`${this.prefix}entities_${etype}_id_mdate`,
|
|
288
|
+
)};`,
|
|
289
|
+
{ connection },
|
|
290
|
+
);
|
|
291
|
+
await this.queryRun(
|
|
292
|
+
`CREATE INDEX ${PostgreSQLDriver.escape(
|
|
293
|
+
`${this.prefix}entities_${etype}_id_mdate`,
|
|
294
|
+
)} ON ${PostgreSQLDriver.escape(
|
|
295
|
+
`${this.prefix}entities_${etype}`,
|
|
296
|
+
)} USING btree ("mdate");`,
|
|
297
|
+
{ connection },
|
|
298
|
+
);
|
|
299
|
+
await this.queryRun(
|
|
300
|
+
`DROP INDEX IF EXISTS ${PostgreSQLDriver.escape(
|
|
301
|
+
`${this.prefix}entities_${etype}_id_tags`,
|
|
302
|
+
)};`,
|
|
303
|
+
{ connection },
|
|
304
|
+
);
|
|
305
|
+
await this.queryRun(
|
|
306
|
+
`CREATE INDEX ${PostgreSQLDriver.escape(
|
|
307
|
+
`${this.prefix}entities_${etype}_id_tags`,
|
|
308
|
+
)} ON ${PostgreSQLDriver.escape(
|
|
309
|
+
`${this.prefix}entities_${etype}`,
|
|
310
|
+
)} USING gin ("tags");`,
|
|
311
|
+
{ connection },
|
|
312
|
+
);
|
|
313
|
+
await this.queryRun(
|
|
314
|
+
`ALTER TABLE ${PostgreSQLDriver.escape(
|
|
315
|
+
`${this.prefix}entities_${etype}`,
|
|
316
|
+
)} SET ( autovacuum_vacuum_scale_factor = 0.05, autovacuum_analyze_scale_factor = 0.05 );`,
|
|
317
|
+
{ connection },
|
|
318
|
+
);
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
private async createDataTable(
|
|
322
|
+
etype: string,
|
|
323
|
+
connection: PostgreSQLDriverConnection,
|
|
324
|
+
) {
|
|
325
|
+
// Create the data table.
|
|
326
|
+
await this.queryRun(
|
|
327
|
+
`CREATE TABLE IF NOT EXISTS ${PostgreSQLDriver.escape(
|
|
328
|
+
`${this.prefix}data_${etype}`,
|
|
329
|
+
)} (
|
|
323
330
|
"guid" BYTEA NOT NULL,
|
|
324
331
|
"name" TEXT NOT NULL,
|
|
325
332
|
"value" CHARACTER(1) NOT NULL,
|
|
@@ -333,263 +340,269 @@ export default class PostgreSQLDriver extends NymphDriver {
|
|
|
333
340
|
`${this.prefix}entities_${etype}`,
|
|
334
341
|
)} ("guid") MATCH SIMPLE ON UPDATE NO ACTION ON DELETE CASCADE
|
|
335
342
|
) WITH ( OIDS=FALSE );`,
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
343
|
+
{ connection },
|
|
344
|
+
);
|
|
345
|
+
await this.queryRun(
|
|
346
|
+
`ALTER TABLE ${PostgreSQLDriver.escape(
|
|
347
|
+
`${this.prefix}data_${etype}`,
|
|
348
|
+
)} OWNER TO ${PostgreSQLDriver.escape(this.config.user)};`,
|
|
349
|
+
{ connection },
|
|
350
|
+
);
|
|
351
|
+
await this.queryRun(
|
|
352
|
+
`DROP INDEX IF EXISTS ${PostgreSQLDriver.escape(
|
|
353
|
+
`${this.prefix}data_${etype}_id_guid`,
|
|
354
|
+
)};`,
|
|
355
|
+
{ connection },
|
|
356
|
+
);
|
|
357
|
+
await this.queryRun(
|
|
358
|
+
`CREATE INDEX ${PostgreSQLDriver.escape(
|
|
359
|
+
`${this.prefix}data_${etype}_id_guid`,
|
|
360
|
+
)} ON ${PostgreSQLDriver.escape(
|
|
361
|
+
`${this.prefix}data_${etype}`,
|
|
362
|
+
)} USING btree ("guid");`,
|
|
363
|
+
{ connection },
|
|
364
|
+
);
|
|
365
|
+
await this.queryRun(
|
|
366
|
+
`DROP INDEX IF EXISTS ${PostgreSQLDriver.escape(
|
|
367
|
+
`${this.prefix}data_${etype}_id_guid_name`,
|
|
368
|
+
)};`,
|
|
369
|
+
{ connection },
|
|
370
|
+
);
|
|
371
|
+
await this.queryRun(
|
|
372
|
+
`CREATE INDEX ${PostgreSQLDriver.escape(
|
|
373
|
+
`${this.prefix}data_${etype}_id_guid_name`,
|
|
374
|
+
)} ON ${PostgreSQLDriver.escape(
|
|
375
|
+
`${this.prefix}data_${etype}`,
|
|
376
|
+
)} USING btree ("guid", "name");`,
|
|
377
|
+
{ connection },
|
|
378
|
+
);
|
|
379
|
+
await this.queryRun(
|
|
380
|
+
`DROP INDEX IF EXISTS ${PostgreSQLDriver.escape(
|
|
381
|
+
`${this.prefix}data_${etype}_id_guid_name__user`,
|
|
382
|
+
)};`,
|
|
383
|
+
{ connection },
|
|
384
|
+
);
|
|
385
|
+
await this.queryRun(
|
|
386
|
+
`CREATE INDEX ${PostgreSQLDriver.escape(
|
|
387
|
+
`${this.prefix}data_${etype}_id_guid_name__user`,
|
|
388
|
+
)} ON ${PostgreSQLDriver.escape(
|
|
389
|
+
`${this.prefix}data_${etype}`,
|
|
390
|
+
)} USING btree ("guid") WHERE "name" = 'user'::text;`,
|
|
391
|
+
{ connection },
|
|
392
|
+
);
|
|
393
|
+
await this.queryRun(
|
|
394
|
+
`DROP INDEX IF EXISTS ${PostgreSQLDriver.escape(
|
|
395
|
+
`${this.prefix}data_${etype}_id_guid_name__group`,
|
|
396
|
+
)};`,
|
|
397
|
+
{ connection },
|
|
398
|
+
);
|
|
399
|
+
await this.queryRun(
|
|
400
|
+
`CREATE INDEX ${PostgreSQLDriver.escape(
|
|
401
|
+
`${this.prefix}data_${etype}_id_guid_name__group`,
|
|
402
|
+
)} ON ${PostgreSQLDriver.escape(
|
|
403
|
+
`${this.prefix}data_${etype}`,
|
|
404
|
+
)} USING btree ("guid") WHERE "name" = 'group'::text;`,
|
|
405
|
+
{ connection },
|
|
406
|
+
);
|
|
407
|
+
await this.queryRun(
|
|
408
|
+
`DROP INDEX IF EXISTS ${PostgreSQLDriver.escape(
|
|
409
|
+
`${this.prefix}data_${etype}_id_name`,
|
|
410
|
+
)};`,
|
|
411
|
+
{ connection },
|
|
412
|
+
);
|
|
413
|
+
await this.queryRun(
|
|
414
|
+
`CREATE INDEX ${PostgreSQLDriver.escape(
|
|
415
|
+
`${this.prefix}data_${etype}_id_name`,
|
|
416
|
+
)} ON ${PostgreSQLDriver.escape(
|
|
417
|
+
`${this.prefix}data_${etype}`,
|
|
418
|
+
)} USING btree ("name");`,
|
|
419
|
+
{ connection },
|
|
420
|
+
);
|
|
421
|
+
await this.queryRun(
|
|
422
|
+
`DROP INDEX IF EXISTS ${PostgreSQLDriver.escape(
|
|
423
|
+
`${this.prefix}data_${etype}_id_name_string`,
|
|
424
|
+
)};`,
|
|
425
|
+
{ connection },
|
|
426
|
+
);
|
|
427
|
+
await this.queryRun(
|
|
428
|
+
`CREATE INDEX ${PostgreSQLDriver.escape(
|
|
429
|
+
`${this.prefix}data_${etype}_id_name_string`,
|
|
430
|
+
)} ON ${PostgreSQLDriver.escape(
|
|
431
|
+
`${this.prefix}data_${etype}`,
|
|
432
|
+
)} USING btree ("name", LEFT("string", 512));`,
|
|
433
|
+
{ connection },
|
|
434
|
+
);
|
|
435
|
+
await this.queryRun(
|
|
436
|
+
`DROP INDEX IF EXISTS ${PostgreSQLDriver.escape(
|
|
437
|
+
`${this.prefix}data_${etype}_id_name_number`,
|
|
438
|
+
)};`,
|
|
439
|
+
{ connection },
|
|
440
|
+
);
|
|
441
|
+
await this.queryRun(
|
|
442
|
+
`CREATE INDEX ${PostgreSQLDriver.escape(
|
|
443
|
+
`${this.prefix}data_${etype}_id_name_number`,
|
|
444
|
+
)} ON ${PostgreSQLDriver.escape(
|
|
445
|
+
`${this.prefix}data_${etype}`,
|
|
446
|
+
)} USING btree ("name", "number");`,
|
|
447
|
+
{ connection },
|
|
448
|
+
);
|
|
449
|
+
await this.queryRun(
|
|
450
|
+
`DROP INDEX IF EXISTS ${PostgreSQLDriver.escape(
|
|
451
|
+
`${this.prefix}data_${etype}_id_guid_name_number`,
|
|
452
|
+
)};`,
|
|
453
|
+
{ connection },
|
|
454
|
+
);
|
|
455
|
+
await this.queryRun(
|
|
456
|
+
`CREATE INDEX ${PostgreSQLDriver.escape(
|
|
457
|
+
`${this.prefix}data_${etype}_id_guid_name_number`,
|
|
458
|
+
)} ON ${PostgreSQLDriver.escape(
|
|
459
|
+
`${this.prefix}data_${etype}`,
|
|
460
|
+
)} USING btree ("guid", "name", "number");`,
|
|
461
|
+
{ connection },
|
|
462
|
+
);
|
|
463
|
+
await this.queryRun(
|
|
464
|
+
`DROP INDEX IF EXISTS ${PostgreSQLDriver.escape(
|
|
465
|
+
`${this.prefix}data_${etype}_id_name_truthy`,
|
|
466
|
+
)};`,
|
|
467
|
+
{ connection },
|
|
468
|
+
);
|
|
469
|
+
await this.queryRun(
|
|
470
|
+
`CREATE INDEX ${PostgreSQLDriver.escape(
|
|
471
|
+
`${this.prefix}data_${etype}_id_name_truthy`,
|
|
472
|
+
)} ON ${PostgreSQLDriver.escape(
|
|
473
|
+
`${this.prefix}data_${etype}`,
|
|
474
|
+
)} USING btree ("name", "truthy");`,
|
|
475
|
+
{ connection },
|
|
476
|
+
);
|
|
477
|
+
await this.queryRun(
|
|
478
|
+
`DROP INDEX IF EXISTS ${PostgreSQLDriver.escape(
|
|
479
|
+
`${this.prefix}data_${etype}_id_guid_name_truthy`,
|
|
480
|
+
)};`,
|
|
481
|
+
{ connection },
|
|
482
|
+
);
|
|
483
|
+
await this.queryRun(
|
|
484
|
+
`CREATE INDEX ${PostgreSQLDriver.escape(
|
|
485
|
+
`${this.prefix}data_${etype}_id_guid_name_truthy`,
|
|
486
|
+
)} ON ${PostgreSQLDriver.escape(
|
|
487
|
+
`${this.prefix}data_${etype}`,
|
|
488
|
+
)} USING btree ("guid", "name", "truthy");`,
|
|
489
|
+
{ connection },
|
|
490
|
+
);
|
|
491
|
+
await this.queryRun(
|
|
492
|
+
`DROP INDEX IF EXISTS ${PostgreSQLDriver.escape(
|
|
493
|
+
`${this.prefix}data_${etype}_id_string`,
|
|
494
|
+
)};`,
|
|
495
|
+
{ connection },
|
|
496
|
+
);
|
|
497
|
+
await this.queryRun(
|
|
498
|
+
`CREATE INDEX ${PostgreSQLDriver.escape(
|
|
499
|
+
`${this.prefix}data_${etype}_id_string`,
|
|
500
|
+
)} ON ${PostgreSQLDriver.escape(
|
|
501
|
+
`${this.prefix}data_${etype}`,
|
|
502
|
+
)} USING gin ("string" gin_trgm_ops);`,
|
|
503
|
+
{ connection },
|
|
504
|
+
);
|
|
505
|
+
await this.queryRun(
|
|
506
|
+
`DROP INDEX IF EXISTS ${PostgreSQLDriver.escape(
|
|
507
|
+
`${this.prefix}data_${etype}_id_json`,
|
|
508
|
+
)};`,
|
|
509
|
+
{ connection },
|
|
510
|
+
);
|
|
511
|
+
await this.queryRun(
|
|
512
|
+
`CREATE INDEX ${PostgreSQLDriver.escape(
|
|
513
|
+
`${this.prefix}data_${etype}_id_json`,
|
|
514
|
+
)} ON ${PostgreSQLDriver.escape(
|
|
515
|
+
`${this.prefix}data_${etype}`,
|
|
516
|
+
)} USING gin ("json");`,
|
|
517
|
+
{ connection },
|
|
518
|
+
);
|
|
519
|
+
await this.queryRun(
|
|
520
|
+
`DROP INDEX IF EXISTS ${PostgreSQLDriver.escape(
|
|
521
|
+
`${this.prefix}data_${etype}_id_acuserread`,
|
|
522
|
+
)};`,
|
|
523
|
+
{ connection },
|
|
524
|
+
);
|
|
525
|
+
await this.queryRun(
|
|
526
|
+
`CREATE INDEX ${PostgreSQLDriver.escape(
|
|
527
|
+
`${this.prefix}data_${etype}_id_acuserread`,
|
|
528
|
+
)} ON ${PostgreSQLDriver.escape(
|
|
529
|
+
`${this.prefix}data_${etype}`,
|
|
530
|
+
)} USING btree ("guid") WHERE "name"='acUser' AND "number" >= 1;`,
|
|
531
|
+
{ connection },
|
|
532
|
+
);
|
|
533
|
+
await this.queryRun(
|
|
534
|
+
`DROP INDEX IF EXISTS ${PostgreSQLDriver.escape(
|
|
535
|
+
`${this.prefix}data_${etype}_id_acgroupread`,
|
|
536
|
+
)};`,
|
|
537
|
+
{ connection },
|
|
538
|
+
);
|
|
539
|
+
await this.queryRun(
|
|
540
|
+
`CREATE INDEX ${PostgreSQLDriver.escape(
|
|
541
|
+
`${this.prefix}data_${etype}_id_acgroupread`,
|
|
542
|
+
)} ON ${PostgreSQLDriver.escape(
|
|
543
|
+
`${this.prefix}data_${etype}`,
|
|
544
|
+
)} USING btree ("guid") WHERE "name"='acGroup' AND "number" >= 1;`,
|
|
545
|
+
{ connection },
|
|
546
|
+
);
|
|
547
|
+
await this.queryRun(
|
|
548
|
+
`DROP INDEX IF EXISTS ${PostgreSQLDriver.escape(
|
|
549
|
+
`${this.prefix}data_${etype}_id_acotherread`,
|
|
550
|
+
)};`,
|
|
551
|
+
{ connection },
|
|
552
|
+
);
|
|
553
|
+
await this.queryRun(
|
|
554
|
+
`CREATE INDEX ${PostgreSQLDriver.escape(
|
|
555
|
+
`${this.prefix}data_${etype}_id_acotherread`,
|
|
556
|
+
)} ON ${PostgreSQLDriver.escape(
|
|
557
|
+
`${this.prefix}data_${etype}`,
|
|
558
|
+
)} USING btree ("guid") WHERE "name"='acOther' AND "number" >= 1;`,
|
|
559
|
+
{ connection },
|
|
560
|
+
);
|
|
561
|
+
await this.queryRun(
|
|
562
|
+
`DROP INDEX IF EXISTS ${PostgreSQLDriver.escape(
|
|
563
|
+
`${this.prefix}data_${etype}_id_acuser`,
|
|
564
|
+
)};`,
|
|
565
|
+
{ connection },
|
|
566
|
+
);
|
|
567
|
+
await this.queryRun(
|
|
568
|
+
`CREATE INDEX ${PostgreSQLDriver.escape(
|
|
569
|
+
`${this.prefix}data_${etype}_id_acuser`,
|
|
570
|
+
)} ON ${PostgreSQLDriver.escape(
|
|
571
|
+
`${this.prefix}data_${etype}`,
|
|
572
|
+
)} USING btree ("guid") WHERE "name"='user';`,
|
|
573
|
+
{ connection },
|
|
574
|
+
);
|
|
575
|
+
await this.queryRun(
|
|
576
|
+
`DROP INDEX IF EXISTS ${PostgreSQLDriver.escape(
|
|
577
|
+
`${this.prefix}data_${etype}_id_acgroup`,
|
|
578
|
+
)};`,
|
|
579
|
+
{ connection },
|
|
580
|
+
);
|
|
581
|
+
await this.queryRun(
|
|
582
|
+
`CREATE INDEX ${PostgreSQLDriver.escape(
|
|
583
|
+
`${this.prefix}data_${etype}_id_acgroup`,
|
|
584
|
+
)} ON ${PostgreSQLDriver.escape(
|
|
585
|
+
`${this.prefix}data_${etype}`,
|
|
586
|
+
)} USING btree ("guid") WHERE "name"='group';`,
|
|
587
|
+
{ connection },
|
|
588
|
+
);
|
|
589
|
+
await this.queryRun(
|
|
590
|
+
`ALTER TABLE ${PostgreSQLDriver.escape(
|
|
591
|
+
`${this.prefix}data_${etype}`,
|
|
592
|
+
)} SET ( autovacuum_vacuum_scale_factor = 0.05, autovacuum_analyze_scale_factor = 0.05 );`,
|
|
593
|
+
{ connection },
|
|
594
|
+
);
|
|
595
|
+
}
|
|
596
|
+
|
|
597
|
+
private async createReferencesTable(
|
|
598
|
+
etype: string,
|
|
599
|
+
connection: PostgreSQLDriverConnection,
|
|
600
|
+
) {
|
|
601
|
+
// Create the references table.
|
|
602
|
+
await this.queryRun(
|
|
603
|
+
`CREATE TABLE IF NOT EXISTS ${PostgreSQLDriver.escape(
|
|
604
|
+
`${this.prefix}references_${etype}`,
|
|
605
|
+
)} (
|
|
593
606
|
"guid" BYTEA NOT NULL,
|
|
594
607
|
"name" TEXT NOT NULL,
|
|
595
608
|
"reference" BYTEA NOT NULL,
|
|
@@ -599,151 +612,207 @@ export default class PostgreSQLDriver extends NymphDriver {
|
|
|
599
612
|
`${this.prefix}entities_${etype}`,
|
|
600
613
|
)} ("guid") MATCH SIMPLE ON UPDATE NO ACTION ON DELETE CASCADE
|
|
601
614
|
) WITH ( OIDS=FALSE );`,
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
615
|
+
{ connection },
|
|
616
|
+
);
|
|
617
|
+
await this.queryRun(
|
|
618
|
+
`ALTER TABLE ${PostgreSQLDriver.escape(
|
|
619
|
+
`${this.prefix}references_${etype}`,
|
|
620
|
+
)} OWNER TO ${PostgreSQLDriver.escape(this.config.user)};`,
|
|
621
|
+
{ connection },
|
|
622
|
+
);
|
|
623
|
+
await this.queryRun(
|
|
624
|
+
`DROP INDEX IF EXISTS ${PostgreSQLDriver.escape(
|
|
625
|
+
`${this.prefix}references_${etype}_id_guid`,
|
|
626
|
+
)};`,
|
|
627
|
+
{ connection },
|
|
628
|
+
);
|
|
629
|
+
await this.queryRun(
|
|
630
|
+
`CREATE INDEX ${PostgreSQLDriver.escape(
|
|
631
|
+
`${this.prefix}references_${etype}_id_guid`,
|
|
632
|
+
)} ON ${PostgreSQLDriver.escape(
|
|
633
|
+
`${this.prefix}references_${etype}`,
|
|
634
|
+
)} USING btree ("guid");`,
|
|
635
|
+
{ connection },
|
|
636
|
+
);
|
|
637
|
+
await this.queryRun(
|
|
638
|
+
`DROP INDEX IF EXISTS ${PostgreSQLDriver.escape(
|
|
639
|
+
`${this.prefix}references_${etype}_id_name`,
|
|
640
|
+
)};`,
|
|
641
|
+
{ connection },
|
|
642
|
+
);
|
|
643
|
+
await this.queryRun(
|
|
644
|
+
`CREATE INDEX ${PostgreSQLDriver.escape(
|
|
645
|
+
`${this.prefix}references_${etype}_id_name`,
|
|
646
|
+
)} ON ${PostgreSQLDriver.escape(
|
|
647
|
+
`${this.prefix}references_${etype}`,
|
|
648
|
+
)} USING btree ("name");`,
|
|
649
|
+
{ connection },
|
|
650
|
+
);
|
|
651
|
+
await this.queryRun(
|
|
652
|
+
`DROP INDEX IF EXISTS ${PostgreSQLDriver.escape(
|
|
653
|
+
`${this.prefix}references_${etype}_id_name_reference`,
|
|
654
|
+
)};`,
|
|
655
|
+
{ connection },
|
|
656
|
+
);
|
|
657
|
+
await this.queryRun(
|
|
658
|
+
`CREATE INDEX ${PostgreSQLDriver.escape(
|
|
659
|
+
`${this.prefix}references_${etype}_id_name_reference`,
|
|
660
|
+
)} ON ${PostgreSQLDriver.escape(
|
|
661
|
+
`${this.prefix}references_${etype}`,
|
|
662
|
+
)} USING btree ("name", "reference");`,
|
|
663
|
+
{ connection },
|
|
664
|
+
);
|
|
665
|
+
await this.queryRun(
|
|
666
|
+
`DROP INDEX IF EXISTS ${PostgreSQLDriver.escape(
|
|
667
|
+
`${this.prefix}references_${etype}_id_reference`,
|
|
668
|
+
)};`,
|
|
669
|
+
{ connection },
|
|
670
|
+
);
|
|
671
|
+
await this.queryRun(
|
|
672
|
+
`CREATE INDEX ${PostgreSQLDriver.escape(
|
|
673
|
+
`${this.prefix}references_${etype}_id_reference`,
|
|
674
|
+
)} ON ${PostgreSQLDriver.escape(
|
|
675
|
+
`${this.prefix}references_${etype}`,
|
|
676
|
+
)} USING btree ("reference");`,
|
|
677
|
+
{ connection },
|
|
678
|
+
);
|
|
679
|
+
await this.queryRun(
|
|
680
|
+
`DROP INDEX IF EXISTS ${PostgreSQLDriver.escape(
|
|
681
|
+
`${this.prefix}references_${etype}_id_guid_name_reference`,
|
|
682
|
+
)};`,
|
|
683
|
+
{ connection },
|
|
684
|
+
);
|
|
685
|
+
await this.queryRun(
|
|
686
|
+
`CREATE INDEX ${PostgreSQLDriver.escape(
|
|
687
|
+
`${this.prefix}references_${etype}_id_guid_name_reference`,
|
|
688
|
+
)} ON ${PostgreSQLDriver.escape(
|
|
689
|
+
`${this.prefix}references_${etype}`,
|
|
690
|
+
)} USING btree ("guid", "name", "reference");`,
|
|
691
|
+
{ connection },
|
|
692
|
+
);
|
|
693
|
+
await this.queryRun(
|
|
694
|
+
`DROP INDEX IF EXISTS ${PostgreSQLDriver.escape(
|
|
695
|
+
`${this.prefix}references_${etype}_id_reference_name_guid`,
|
|
696
|
+
)};`,
|
|
697
|
+
{ connection },
|
|
698
|
+
);
|
|
699
|
+
await this.queryRun(
|
|
700
|
+
`CREATE INDEX ${PostgreSQLDriver.escape(
|
|
701
|
+
`${this.prefix}references_${etype}_id_reference_name_guid`,
|
|
702
|
+
)} ON ${PostgreSQLDriver.escape(
|
|
703
|
+
`${this.prefix}references_${etype}`,
|
|
704
|
+
)} USING btree ("reference", "name", "guid");`,
|
|
705
|
+
{ connection },
|
|
706
|
+
);
|
|
707
|
+
await this.queryRun(
|
|
708
|
+
`DROP INDEX IF EXISTS ${PostgreSQLDriver.escape(
|
|
709
|
+
`${this.prefix}references_${etype}_id_reference_guid_name`,
|
|
710
|
+
)};`,
|
|
711
|
+
{ connection },
|
|
712
|
+
);
|
|
713
|
+
await this.queryRun(
|
|
714
|
+
`CREATE INDEX ${PostgreSQLDriver.escape(
|
|
715
|
+
`${this.prefix}references_${etype}_id_reference_guid_name`,
|
|
716
|
+
)} ON ${PostgreSQLDriver.escape(
|
|
717
|
+
`${this.prefix}references_${etype}`,
|
|
718
|
+
)} USING btree ("reference", "guid", "name");`,
|
|
719
|
+
{ connection },
|
|
720
|
+
);
|
|
721
|
+
await this.queryRun(
|
|
722
|
+
`DROP INDEX IF EXISTS ${PostgreSQLDriver.escape(
|
|
723
|
+
`${this.prefix}references_${etype}_id_guid_reference_nameuser`,
|
|
724
|
+
)};`,
|
|
725
|
+
{ connection },
|
|
726
|
+
);
|
|
727
|
+
await this.queryRun(
|
|
728
|
+
`CREATE INDEX ${PostgreSQLDriver.escape(
|
|
729
|
+
`${this.prefix}references_${etype}_id_guid_reference_nameuser`,
|
|
730
|
+
)} ON ${PostgreSQLDriver.escape(
|
|
731
|
+
`${this.prefix}references_${etype}`,
|
|
732
|
+
)} USING btree ("guid", "reference") WHERE "name"='user';`,
|
|
733
|
+
{ connection },
|
|
734
|
+
);
|
|
735
|
+
await this.queryRun(
|
|
736
|
+
`DROP INDEX IF EXISTS ${PostgreSQLDriver.escape(
|
|
737
|
+
`${this.prefix}references_${etype}_id_guid_reference_namegroup`,
|
|
738
|
+
)};`,
|
|
739
|
+
{ connection },
|
|
740
|
+
);
|
|
741
|
+
await this.queryRun(
|
|
742
|
+
`CREATE INDEX ${PostgreSQLDriver.escape(
|
|
743
|
+
`${this.prefix}references_${etype}_id_guid_reference_namegroup`,
|
|
744
|
+
)} ON ${PostgreSQLDriver.escape(
|
|
745
|
+
`${this.prefix}references_${etype}`,
|
|
746
|
+
)} USING btree ("guid", "reference") WHERE "name"='group';`,
|
|
747
|
+
{ connection },
|
|
748
|
+
);
|
|
749
|
+
await this.queryRun(
|
|
750
|
+
`ALTER TABLE ${PostgreSQLDriver.escape(
|
|
751
|
+
`${this.prefix}references_${etype}`,
|
|
752
|
+
)} SET ( autovacuum_vacuum_scale_factor = 0.05, autovacuum_analyze_scale_factor = 0.05 );`,
|
|
753
|
+
{ connection },
|
|
754
|
+
);
|
|
755
|
+
}
|
|
756
|
+
|
|
757
|
+
private async createTokensTable(
|
|
758
|
+
etype: string,
|
|
759
|
+
connection: PostgreSQLDriverConnection,
|
|
760
|
+
) {
|
|
761
|
+
// Create the tokens table.
|
|
762
|
+
await this.queryRun(
|
|
763
|
+
`CREATE TABLE IF NOT EXISTS ${PostgreSQLDriver.escape(
|
|
764
|
+
`${this.prefix}tokens_${etype}`,
|
|
765
|
+
)} (
|
|
766
|
+
"guid" BYTEA NOT NULL,
|
|
767
|
+
"name" TEXT NOT NULL,
|
|
768
|
+
"token" INTEGER NOT NULL,
|
|
769
|
+
"position" INTEGER NOT NULL,
|
|
770
|
+
"stem" BOOLEAN NOT NULL,
|
|
771
|
+
PRIMARY KEY ("guid", "name", "token", "position"),
|
|
772
|
+
FOREIGN KEY ("guid")
|
|
773
|
+
REFERENCES ${PostgreSQLDriver.escape(
|
|
774
|
+
`${this.prefix}entities_${etype}`,
|
|
775
|
+
)} ("guid") MATCH SIMPLE ON UPDATE NO ACTION ON DELETE CASCADE
|
|
776
|
+
) WITH ( OIDS=FALSE );`,
|
|
777
|
+
{ connection },
|
|
778
|
+
);
|
|
779
|
+
await this.queryRun(
|
|
780
|
+
`ALTER TABLE ${PostgreSQLDriver.escape(
|
|
781
|
+
`${this.prefix}tokens_${etype}`,
|
|
782
|
+
)} OWNER TO ${PostgreSQLDriver.escape(this.config.user)};`,
|
|
783
|
+
{ connection },
|
|
784
|
+
);
|
|
785
|
+
await this.queryRun(
|
|
786
|
+
`DROP INDEX IF EXISTS ${PostgreSQLDriver.escape(
|
|
787
|
+
`${this.prefix}tokens_${etype}_id_name_token`,
|
|
788
|
+
)};`,
|
|
789
|
+
{ connection },
|
|
790
|
+
);
|
|
791
|
+
await this.queryRun(
|
|
792
|
+
`CREATE INDEX ${PostgreSQLDriver.escape(
|
|
793
|
+
`${this.prefix}tokens_${etype}_id_name_token`,
|
|
794
|
+
)} ON ${PostgreSQLDriver.escape(
|
|
795
|
+
`${this.prefix}tokens_${etype}`,
|
|
796
|
+
)} USING btree ("name", "token");`,
|
|
797
|
+
{ connection },
|
|
798
|
+
);
|
|
799
|
+
await this.queryRun(
|
|
800
|
+
`ALTER TABLE ${PostgreSQLDriver.escape(
|
|
801
|
+
`${this.prefix}tokens_${etype}`,
|
|
802
|
+
)} SET ( autovacuum_vacuum_scale_factor = 0.05, autovacuum_analyze_scale_factor = 0.05 );`,
|
|
803
|
+
{ connection },
|
|
804
|
+
);
|
|
805
|
+
}
|
|
806
|
+
|
|
807
|
+
private async createUniquesTable(
|
|
808
|
+
etype: string,
|
|
809
|
+
connection: PostgreSQLDriverConnection,
|
|
810
|
+
) {
|
|
811
|
+
// Create the unique strings table.
|
|
812
|
+
await this.queryRun(
|
|
813
|
+
`CREATE TABLE IF NOT EXISTS ${PostgreSQLDriver.escape(
|
|
814
|
+
`${this.prefix}uniques_${etype}`,
|
|
815
|
+
)} (
|
|
747
816
|
"guid" BYTEA NOT NULL,
|
|
748
817
|
"unique" TEXT NOT NULL UNIQUE,
|
|
749
818
|
PRIMARY KEY ("guid", "unique"),
|
|
@@ -752,14 +821,30 @@ export default class PostgreSQLDriver extends NymphDriver {
|
|
|
752
821
|
`${this.prefix}entities_${etype}`,
|
|
753
822
|
)} ("guid") MATCH SIMPLE ON UPDATE NO ACTION ON DELETE CASCADE
|
|
754
823
|
) WITH ( OIDS=FALSE );`,
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
824
|
+
{ connection },
|
|
825
|
+
);
|
|
826
|
+
await this.queryRun(
|
|
827
|
+
`ALTER TABLE ${PostgreSQLDriver.escape(
|
|
828
|
+
`${this.prefix}uniques_${etype}`,
|
|
829
|
+
)} OWNER TO ${PostgreSQLDriver.escape(this.config.user)};`,
|
|
830
|
+
{ connection },
|
|
831
|
+
);
|
|
832
|
+
}
|
|
833
|
+
|
|
834
|
+
/**
|
|
835
|
+
* Create entity tables in the database.
|
|
836
|
+
*
|
|
837
|
+
* @param etype The entity type to create a table for. If this is blank, the default tables are created.
|
|
838
|
+
* @returns True on success, false on failure.
|
|
839
|
+
*/
|
|
840
|
+
private async createTables(etype: string | null = null) {
|
|
841
|
+
const connection = await this.getConnection(true);
|
|
842
|
+
if (etype != null) {
|
|
843
|
+
await this.createEntitiesTable(etype, connection);
|
|
844
|
+
await this.createDataTable(etype, connection);
|
|
845
|
+
await this.createReferencesTable(etype, connection);
|
|
846
|
+
await this.createTokensTable(etype, connection);
|
|
847
|
+
await this.createUniquesTable(etype, connection);
|
|
763
848
|
} else {
|
|
764
849
|
// Add trigram extensions.
|
|
765
850
|
try {
|
|
@@ -1075,6 +1160,17 @@ export default class PostgreSQLDriver extends NymphDriver {
|
|
|
1075
1160
|
},
|
|
1076
1161
|
},
|
|
1077
1162
|
);
|
|
1163
|
+
await this.queryRun(
|
|
1164
|
+
`DELETE FROM ${PostgreSQLDriver.escape(
|
|
1165
|
+
`${this.prefix}tokens_${etype}`,
|
|
1166
|
+
)} WHERE "guid"=decode(@guid, 'hex');`,
|
|
1167
|
+
{
|
|
1168
|
+
etypes: [etype],
|
|
1169
|
+
params: {
|
|
1170
|
+
guid,
|
|
1171
|
+
},
|
|
1172
|
+
},
|
|
1173
|
+
);
|
|
1078
1174
|
await this.queryRun(
|
|
1079
1175
|
`DELETE FROM ${PostgreSQLDriver.escape(
|
|
1080
1176
|
`${this.prefix}uniques_${etype}`,
|
|
@@ -1117,6 +1213,24 @@ export default class PostgreSQLDriver extends NymphDriver {
|
|
|
1117
1213
|
return true;
|
|
1118
1214
|
}
|
|
1119
1215
|
|
|
1216
|
+
public async getEtypes() {
|
|
1217
|
+
const tables = await this.queryArray(
|
|
1218
|
+
'SELECT "table_name" AS "table_name" FROM "information_schema"."tables" WHERE "table_catalog"=@db AND "table_schema"=\'public\' AND "table_name" LIKE @prefix;',
|
|
1219
|
+
{
|
|
1220
|
+
params: {
|
|
1221
|
+
db: this.config.database,
|
|
1222
|
+
prefix: this.prefix + 'entities_' + '%',
|
|
1223
|
+
},
|
|
1224
|
+
},
|
|
1225
|
+
);
|
|
1226
|
+
const etypes: string[] = [];
|
|
1227
|
+
for (const table of tables) {
|
|
1228
|
+
etypes.push(table.table_name.substr((this.prefix + 'entities_').length));
|
|
1229
|
+
}
|
|
1230
|
+
|
|
1231
|
+
return etypes;
|
|
1232
|
+
}
|
|
1233
|
+
|
|
1120
1234
|
public async *exportDataIterator(): AsyncGenerator<
|
|
1121
1235
|
{ type: 'comment' | 'uid' | 'entity'; content: string },
|
|
1122
1236
|
void,
|
|
@@ -1179,19 +1293,7 @@ export default class PostgreSQLDriver extends NymphDriver {
|
|
|
1179
1293
|
}
|
|
1180
1294
|
|
|
1181
1295
|
// Get the etypes.
|
|
1182
|
-
const
|
|
1183
|
-
'SELECT "table_name" AS "table_name" FROM "information_schema"."tables" WHERE "table_catalog"=@db AND "table_schema"=\'public\' AND "table_name" LIKE @prefix;',
|
|
1184
|
-
{
|
|
1185
|
-
params: {
|
|
1186
|
-
db: this.config.database,
|
|
1187
|
-
prefix: this.prefix + 'entities_' + '%',
|
|
1188
|
-
},
|
|
1189
|
-
},
|
|
1190
|
-
);
|
|
1191
|
-
const etypes = [];
|
|
1192
|
-
for (const table of tables) {
|
|
1193
|
-
etypes.push(table.table_name.substr((this.prefix + 'entities_').length));
|
|
1194
|
-
}
|
|
1296
|
+
const etypes = await this.getEtypes();
|
|
1195
1297
|
|
|
1196
1298
|
for (const etype of etypes) {
|
|
1197
1299
|
// Export entities.
|
|
@@ -1533,6 +1635,148 @@ export default class PostgreSQLDriver extends NymphDriver {
|
|
|
1533
1635
|
params[value] = PostgreSQLDriver.escapeNullSequences(svalue);
|
|
1534
1636
|
}
|
|
1535
1637
|
break;
|
|
1638
|
+
case 'search':
|
|
1639
|
+
case '!search':
|
|
1640
|
+
if (curValue[0] === 'cdate' || curValue[0] === 'mdate') {
|
|
1641
|
+
if (curQuery) {
|
|
1642
|
+
curQuery += typeIsOr ? ' OR ' : ' AND ';
|
|
1643
|
+
}
|
|
1644
|
+
curQuery +=
|
|
1645
|
+
(xor(typeIsNot, clauseNot) ? 'NOT ' : '') + '(FALSE)';
|
|
1646
|
+
break;
|
|
1647
|
+
} else {
|
|
1648
|
+
if (curQuery) {
|
|
1649
|
+
curQuery += typeIsOr ? ' OR ' : ' AND ';
|
|
1650
|
+
}
|
|
1651
|
+
|
|
1652
|
+
const name = `param${++count.i}`;
|
|
1653
|
+
|
|
1654
|
+
const queryPartToken = (term: SearchTerm) => {
|
|
1655
|
+
const value = `param${++count.i}`;
|
|
1656
|
+
params[value] = term.token;
|
|
1657
|
+
return (
|
|
1658
|
+
'EXISTS (SELECT "guid" FROM ' +
|
|
1659
|
+
PostgreSQLDriver.escape(this.prefix + 'tokens_' + etype) +
|
|
1660
|
+
' WHERE "guid"=' +
|
|
1661
|
+
ieTable +
|
|
1662
|
+
'."guid" AND "name"=@' +
|
|
1663
|
+
name +
|
|
1664
|
+
' AND "token"=@' +
|
|
1665
|
+
value +
|
|
1666
|
+
(term.nostemmed ? ' AND "stem"=FALSE' : '') +
|
|
1667
|
+
')'
|
|
1668
|
+
);
|
|
1669
|
+
};
|
|
1670
|
+
|
|
1671
|
+
const queryPartSeries = (series: SearchSeriesTerm) => {
|
|
1672
|
+
const tokenTableSuffix = makeTableSuffix();
|
|
1673
|
+
const tokenParts = series.tokens.map((token, i) => {
|
|
1674
|
+
const value = `param${++count.i}`;
|
|
1675
|
+
params[value] = token.token;
|
|
1676
|
+
return {
|
|
1677
|
+
fromClause:
|
|
1678
|
+
i === 0
|
|
1679
|
+
? 'FROM ' +
|
|
1680
|
+
PostgreSQLDriver.escape(
|
|
1681
|
+
this.prefix + 'tokens_' + etype,
|
|
1682
|
+
) +
|
|
1683
|
+
' t' +
|
|
1684
|
+
tokenTableSuffix +
|
|
1685
|
+
'0'
|
|
1686
|
+
: 'JOIN ' +
|
|
1687
|
+
PostgreSQLDriver.escape(
|
|
1688
|
+
this.prefix + 'tokens_' + etype,
|
|
1689
|
+
) +
|
|
1690
|
+
' t' +
|
|
1691
|
+
tokenTableSuffix +
|
|
1692
|
+
i +
|
|
1693
|
+
' ON t' +
|
|
1694
|
+
tokenTableSuffix +
|
|
1695
|
+
i +
|
|
1696
|
+
'."guid" = t' +
|
|
1697
|
+
tokenTableSuffix +
|
|
1698
|
+
'0."guid" AND t' +
|
|
1699
|
+
tokenTableSuffix +
|
|
1700
|
+
i +
|
|
1701
|
+
'."name" = t' +
|
|
1702
|
+
tokenTableSuffix +
|
|
1703
|
+
'0."name" AND t' +
|
|
1704
|
+
tokenTableSuffix +
|
|
1705
|
+
i +
|
|
1706
|
+
'."position" = t' +
|
|
1707
|
+
tokenTableSuffix +
|
|
1708
|
+
'0."position" + ' +
|
|
1709
|
+
i,
|
|
1710
|
+
whereClause:
|
|
1711
|
+
't' +
|
|
1712
|
+
tokenTableSuffix +
|
|
1713
|
+
i +
|
|
1714
|
+
'."token"=@' +
|
|
1715
|
+
value +
|
|
1716
|
+
(token.nostemmed
|
|
1717
|
+
? ' AND t' + tokenTableSuffix + i + '."stem"=FALSE'
|
|
1718
|
+
: ''),
|
|
1719
|
+
};
|
|
1720
|
+
});
|
|
1721
|
+
return (
|
|
1722
|
+
'EXISTS (SELECT t' +
|
|
1723
|
+
tokenTableSuffix +
|
|
1724
|
+
'0."guid" ' +
|
|
1725
|
+
tokenParts.map((part) => part.fromClause).join(' ') +
|
|
1726
|
+
' WHERE t' +
|
|
1727
|
+
tokenTableSuffix +
|
|
1728
|
+
'0."guid"=' +
|
|
1729
|
+
ieTable +
|
|
1730
|
+
'."guid" AND t' +
|
|
1731
|
+
tokenTableSuffix +
|
|
1732
|
+
'0."name"=@' +
|
|
1733
|
+
name +
|
|
1734
|
+
' AND ' +
|
|
1735
|
+
tokenParts.map((part) => part.whereClause).join(' AND ') +
|
|
1736
|
+
')'
|
|
1737
|
+
);
|
|
1738
|
+
};
|
|
1739
|
+
|
|
1740
|
+
const queryPartTerm = (
|
|
1741
|
+
term:
|
|
1742
|
+
| SearchTerm
|
|
1743
|
+
| SearchOrTerm
|
|
1744
|
+
| SearchNotTerm
|
|
1745
|
+
| SearchSeriesTerm,
|
|
1746
|
+
): string => {
|
|
1747
|
+
if (term.type === 'series') {
|
|
1748
|
+
return queryPartSeries(term);
|
|
1749
|
+
} else if (term.type === 'not') {
|
|
1750
|
+
return 'NOT ' + queryPartTerm(term.operand);
|
|
1751
|
+
} else if (term.type === 'or') {
|
|
1752
|
+
let queryParts: string[] = [];
|
|
1753
|
+
for (let operand of term.operands) {
|
|
1754
|
+
queryParts.push(queryPartTerm(operand));
|
|
1755
|
+
}
|
|
1756
|
+
return '(' + queryParts.join(' OR ') + ')';
|
|
1757
|
+
}
|
|
1758
|
+
return queryPartToken(term);
|
|
1759
|
+
};
|
|
1760
|
+
|
|
1761
|
+
const parsedFTSQuery = this.tokenizer.parseSearchQuery(
|
|
1762
|
+
curValue[1],
|
|
1763
|
+
);
|
|
1764
|
+
|
|
1765
|
+
// Run through the query and add terms.
|
|
1766
|
+
let termStrings: string[] = [];
|
|
1767
|
+
for (let term of parsedFTSQuery) {
|
|
1768
|
+
termStrings.push(queryPartTerm(term));
|
|
1769
|
+
}
|
|
1770
|
+
|
|
1771
|
+
curQuery +=
|
|
1772
|
+
(xor(typeIsNot, clauseNot) ? 'NOT ' : '') +
|
|
1773
|
+
'(' +
|
|
1774
|
+
termStrings.join(' AND ') +
|
|
1775
|
+
')';
|
|
1776
|
+
|
|
1777
|
+
params[name] = curValue[0];
|
|
1778
|
+
}
|
|
1779
|
+
break;
|
|
1536
1780
|
case 'match':
|
|
1537
1781
|
case '!match':
|
|
1538
1782
|
if (curValue[0] === 'cdate') {
|
|
@@ -2371,14 +2615,18 @@ export default class PostgreSQLDriver extends NymphDriver {
|
|
|
2371
2615
|
return result?.cur_uid == null ? null : Number(result.cur_uid);
|
|
2372
2616
|
}
|
|
2373
2617
|
|
|
2374
|
-
public async importEntity({
|
|
2375
|
-
guid
|
|
2376
|
-
cdate
|
|
2377
|
-
mdate
|
|
2378
|
-
tags
|
|
2379
|
-
sdata
|
|
2380
|
-
etype
|
|
2381
|
-
}
|
|
2618
|
+
public async importEntity(entity: {
|
|
2619
|
+
guid: string;
|
|
2620
|
+
cdate: number;
|
|
2621
|
+
mdate: number;
|
|
2622
|
+
tags: string[];
|
|
2623
|
+
sdata: SerializedEntityData;
|
|
2624
|
+
etype: string;
|
|
2625
|
+
}) {
|
|
2626
|
+
return await this.importEntityInternal(entity, false);
|
|
2627
|
+
}
|
|
2628
|
+
|
|
2629
|
+
public async importEntityTokens(entity: {
|
|
2382
2630
|
guid: string;
|
|
2383
2631
|
cdate: number;
|
|
2384
2632
|
mdate: number;
|
|
@@ -2386,51 +2634,74 @@ export default class PostgreSQLDriver extends NymphDriver {
|
|
|
2386
2634
|
sdata: SerializedEntityData;
|
|
2387
2635
|
etype: string;
|
|
2388
2636
|
}) {
|
|
2637
|
+
return await this.importEntityInternal(entity, true);
|
|
2638
|
+
}
|
|
2639
|
+
|
|
2640
|
+
private async importEntityInternal(
|
|
2641
|
+
{
|
|
2642
|
+
guid,
|
|
2643
|
+
cdate,
|
|
2644
|
+
mdate,
|
|
2645
|
+
tags,
|
|
2646
|
+
sdata,
|
|
2647
|
+
etype,
|
|
2648
|
+
}: {
|
|
2649
|
+
guid: string;
|
|
2650
|
+
cdate: number;
|
|
2651
|
+
mdate: number;
|
|
2652
|
+
tags: string[];
|
|
2653
|
+
sdata: SerializedEntityData;
|
|
2654
|
+
etype: string;
|
|
2655
|
+
},
|
|
2656
|
+
onlyTokens: boolean,
|
|
2657
|
+
) {
|
|
2389
2658
|
try {
|
|
2390
2659
|
let promises = [];
|
|
2391
|
-
|
|
2392
|
-
|
|
2393
|
-
|
|
2394
|
-
|
|
2395
|
-
|
|
2396
|
-
|
|
2397
|
-
|
|
2398
|
-
|
|
2399
|
-
|
|
2660
|
+
if (!onlyTokens) {
|
|
2661
|
+
promises.push(
|
|
2662
|
+
this.queryRun(
|
|
2663
|
+
`DELETE FROM ${PostgreSQLDriver.escape(
|
|
2664
|
+
`${this.prefix}entities_${etype}`,
|
|
2665
|
+
)} WHERE "guid"=decode(@guid, 'hex');`,
|
|
2666
|
+
{
|
|
2667
|
+
etypes: [etype],
|
|
2668
|
+
params: {
|
|
2669
|
+
guid,
|
|
2670
|
+
},
|
|
2400
2671
|
},
|
|
2401
|
-
|
|
2402
|
-
)
|
|
2403
|
-
|
|
2404
|
-
|
|
2405
|
-
|
|
2406
|
-
|
|
2407
|
-
|
|
2408
|
-
|
|
2409
|
-
|
|
2410
|
-
|
|
2411
|
-
|
|
2412
|
-
|
|
2672
|
+
),
|
|
2673
|
+
);
|
|
2674
|
+
promises.push(
|
|
2675
|
+
this.queryRun(
|
|
2676
|
+
`DELETE FROM ${PostgreSQLDriver.escape(
|
|
2677
|
+
`${this.prefix}data_${etype}`,
|
|
2678
|
+
)} WHERE "guid"=decode(@guid, 'hex');`,
|
|
2679
|
+
{
|
|
2680
|
+
etypes: [etype],
|
|
2681
|
+
params: {
|
|
2682
|
+
guid,
|
|
2683
|
+
},
|
|
2413
2684
|
},
|
|
2414
|
-
|
|
2415
|
-
)
|
|
2416
|
-
|
|
2417
|
-
|
|
2418
|
-
|
|
2419
|
-
|
|
2420
|
-
|
|
2421
|
-
|
|
2422
|
-
|
|
2423
|
-
|
|
2424
|
-
|
|
2425
|
-
|
|
2685
|
+
),
|
|
2686
|
+
);
|
|
2687
|
+
promises.push(
|
|
2688
|
+
this.queryRun(
|
|
2689
|
+
`DELETE FROM ${PostgreSQLDriver.escape(
|
|
2690
|
+
`${this.prefix}references_${etype}`,
|
|
2691
|
+
)} WHERE "guid"=decode(@guid, 'hex');`,
|
|
2692
|
+
{
|
|
2693
|
+
etypes: [etype],
|
|
2694
|
+
params: {
|
|
2695
|
+
guid,
|
|
2696
|
+
},
|
|
2426
2697
|
},
|
|
2427
|
-
|
|
2428
|
-
)
|
|
2429
|
-
|
|
2698
|
+
),
|
|
2699
|
+
);
|
|
2700
|
+
}
|
|
2430
2701
|
promises.push(
|
|
2431
2702
|
this.queryRun(
|
|
2432
2703
|
`DELETE FROM ${PostgreSQLDriver.escape(
|
|
2433
|
-
`${this.prefix}
|
|
2704
|
+
`${this.prefix}tokens_${etype}`,
|
|
2434
2705
|
)} WHERE "guid"=decode(@guid, 'hex');`,
|
|
2435
2706
|
{
|
|
2436
2707
|
etypes: [etype],
|
|
@@ -2440,106 +2711,188 @@ export default class PostgreSQLDriver extends NymphDriver {
|
|
|
2440
2711
|
},
|
|
2441
2712
|
),
|
|
2442
2713
|
);
|
|
2443
|
-
|
|
2444
|
-
promises = [];
|
|
2445
|
-
await this.queryRun(
|
|
2446
|
-
`INSERT INTO ${PostgreSQLDriver.escape(
|
|
2447
|
-
`${this.prefix}entities_${etype}`,
|
|
2448
|
-
)} ("guid", "tags", "cdate", "mdate") VALUES (decode(@guid, 'hex'), @tags, @cdate, @mdate);`,
|
|
2449
|
-
{
|
|
2450
|
-
etypes: [etype],
|
|
2451
|
-
params: {
|
|
2452
|
-
guid,
|
|
2453
|
-
tags,
|
|
2454
|
-
cdate: isNaN(cdate) ? null : cdate,
|
|
2455
|
-
mdate: isNaN(mdate) ? null : mdate,
|
|
2456
|
-
},
|
|
2457
|
-
},
|
|
2458
|
-
);
|
|
2459
|
-
for (const name in sdata) {
|
|
2460
|
-
const value = sdata[name];
|
|
2461
|
-
const uvalue = JSON.parse(value);
|
|
2462
|
-
if (value === undefined) {
|
|
2463
|
-
continue;
|
|
2464
|
-
}
|
|
2465
|
-
const storageValue =
|
|
2466
|
-
typeof uvalue === 'number'
|
|
2467
|
-
? 'N'
|
|
2468
|
-
: typeof uvalue === 'string'
|
|
2469
|
-
? 'S'
|
|
2470
|
-
: 'J';
|
|
2471
|
-
const jsonValue =
|
|
2472
|
-
storageValue === 'J'
|
|
2473
|
-
? PostgreSQLDriver.escapeNullSequences(value)
|
|
2474
|
-
: null;
|
|
2714
|
+
if (!onlyTokens) {
|
|
2475
2715
|
promises.push(
|
|
2476
2716
|
this.queryRun(
|
|
2477
|
-
`
|
|
2478
|
-
`${this.prefix}
|
|
2479
|
-
)}
|
|
2717
|
+
`DELETE FROM ${PostgreSQLDriver.escape(
|
|
2718
|
+
`${this.prefix}uniques_${etype}`,
|
|
2719
|
+
)} WHERE "guid"=decode(@guid, 'hex');`,
|
|
2480
2720
|
{
|
|
2481
2721
|
etypes: [etype],
|
|
2482
2722
|
params: {
|
|
2483
2723
|
guid,
|
|
2484
|
-
name,
|
|
2485
|
-
storageValue,
|
|
2486
|
-
jsonValue,
|
|
2487
|
-
string:
|
|
2488
|
-
storageValue === 'J'
|
|
2489
|
-
? null
|
|
2490
|
-
: PostgreSQLDriver.escapeNulls(`${uvalue}`),
|
|
2491
|
-
number: isNaN(Number(uvalue)) ? null : Number(uvalue),
|
|
2492
|
-
truthy: !!uvalue,
|
|
2493
2724
|
},
|
|
2494
2725
|
},
|
|
2495
2726
|
),
|
|
2496
2727
|
);
|
|
2497
|
-
|
|
2498
|
-
|
|
2728
|
+
}
|
|
2729
|
+
|
|
2730
|
+
await Promise.all(promises);
|
|
2731
|
+
promises = [];
|
|
2732
|
+
|
|
2733
|
+
if (!onlyTokens) {
|
|
2734
|
+
await this.queryRun(
|
|
2735
|
+
`INSERT INTO ${PostgreSQLDriver.escape(
|
|
2736
|
+
`${this.prefix}entities_${etype}`,
|
|
2737
|
+
)} ("guid", "tags", "cdate", "mdate") VALUES (decode(@guid, 'hex'), @tags, @cdate, @mdate);`,
|
|
2738
|
+
{
|
|
2739
|
+
etypes: [etype],
|
|
2740
|
+
params: {
|
|
2741
|
+
guid,
|
|
2742
|
+
tags,
|
|
2743
|
+
cdate: isNaN(cdate) ? null : cdate,
|
|
2744
|
+
mdate: isNaN(mdate) ? null : mdate,
|
|
2745
|
+
},
|
|
2746
|
+
},
|
|
2747
|
+
);
|
|
2748
|
+
|
|
2749
|
+
for (const name in sdata) {
|
|
2750
|
+
const value = sdata[name];
|
|
2751
|
+
const uvalue = JSON.parse(value);
|
|
2752
|
+
if (value === undefined) {
|
|
2753
|
+
continue;
|
|
2754
|
+
}
|
|
2755
|
+
const storageValue =
|
|
2756
|
+
typeof uvalue === 'number'
|
|
2757
|
+
? 'N'
|
|
2758
|
+
: typeof uvalue === 'string'
|
|
2759
|
+
? 'S'
|
|
2760
|
+
: 'J';
|
|
2761
|
+
const jsonValue =
|
|
2762
|
+
storageValue === 'J'
|
|
2763
|
+
? PostgreSQLDriver.escapeNullSequences(value)
|
|
2764
|
+
: null;
|
|
2765
|
+
|
|
2499
2766
|
promises.push(
|
|
2500
2767
|
this.queryRun(
|
|
2501
2768
|
`INSERT INTO ${PostgreSQLDriver.escape(
|
|
2502
|
-
`${this.prefix}
|
|
2503
|
-
)} ("guid", "name", "
|
|
2769
|
+
`${this.prefix}data_${etype}`,
|
|
2770
|
+
)} ("guid", "name", "value", "json", "string", "number", "truthy") VALUES (decode(@guid, 'hex'), @name, @storageValue, @jsonValue, @string, @number, @truthy);`,
|
|
2504
2771
|
{
|
|
2505
2772
|
etypes: [etype],
|
|
2506
2773
|
params: {
|
|
2507
2774
|
guid,
|
|
2508
2775
|
name,
|
|
2509
|
-
|
|
2776
|
+
storageValue,
|
|
2777
|
+
jsonValue,
|
|
2778
|
+
string:
|
|
2779
|
+
storageValue === 'J'
|
|
2780
|
+
? null
|
|
2781
|
+
: PostgreSQLDriver.escapeNulls(`${uvalue}`),
|
|
2782
|
+
number: isNaN(Number(uvalue)) ? null : Number(uvalue),
|
|
2783
|
+
truthy: !!uvalue,
|
|
2510
2784
|
},
|
|
2511
2785
|
},
|
|
2512
2786
|
),
|
|
2513
2787
|
);
|
|
2788
|
+
|
|
2789
|
+
const references = this.findReferences(value);
|
|
2790
|
+
for (const reference of references) {
|
|
2791
|
+
promises.push(
|
|
2792
|
+
this.queryRun(
|
|
2793
|
+
`INSERT INTO ${PostgreSQLDriver.escape(
|
|
2794
|
+
`${this.prefix}references_${etype}`,
|
|
2795
|
+
)} ("guid", "name", "reference") VALUES (decode(@guid, 'hex'), @name, decode(@reference, 'hex'));`,
|
|
2796
|
+
{
|
|
2797
|
+
etypes: [etype],
|
|
2798
|
+
params: {
|
|
2799
|
+
guid,
|
|
2800
|
+
name,
|
|
2801
|
+
reference,
|
|
2802
|
+
},
|
|
2803
|
+
},
|
|
2804
|
+
),
|
|
2805
|
+
);
|
|
2806
|
+
}
|
|
2514
2807
|
}
|
|
2515
2808
|
}
|
|
2516
|
-
|
|
2517
|
-
|
|
2518
|
-
|
|
2519
|
-
for (
|
|
2520
|
-
|
|
2521
|
-
|
|
2522
|
-
|
|
2523
|
-
|
|
2524
|
-
|
|
2525
|
-
|
|
2526
|
-
|
|
2527
|
-
|
|
2528
|
-
|
|
2529
|
-
|
|
2530
|
-
|
|
2531
|
-
}
|
|
2532
|
-
|
|
2533
|
-
|
|
2534
|
-
|
|
2535
|
-
|
|
2536
|
-
|
|
2809
|
+
|
|
2810
|
+
const EntityClass = this.nymph.getEntityClassByEtype(etype);
|
|
2811
|
+
|
|
2812
|
+
for (let name in sdata) {
|
|
2813
|
+
let tokenString: string | null = null;
|
|
2814
|
+
try {
|
|
2815
|
+
tokenString = EntityClass.getFTSText(name, JSON.parse(sdata[name]));
|
|
2816
|
+
} catch (e: any) {
|
|
2817
|
+
// Ignore error.
|
|
2818
|
+
}
|
|
2819
|
+
|
|
2820
|
+
if (tokenString != null) {
|
|
2821
|
+
const tokens = this.tokenizer.tokenize(tokenString);
|
|
2822
|
+
while (tokens.length) {
|
|
2823
|
+
const currentTokens = tokens.splice(0, 100);
|
|
2824
|
+
const params: { [k: string]: any } = {
|
|
2825
|
+
guid,
|
|
2826
|
+
name,
|
|
2827
|
+
};
|
|
2828
|
+
const values: string[] = [];
|
|
2829
|
+
|
|
2830
|
+
for (let i = 0; i < currentTokens.length; i++) {
|
|
2831
|
+
const token = currentTokens[i];
|
|
2832
|
+
params['token' + i] = token.token;
|
|
2833
|
+
params['position' + i] = token.position;
|
|
2834
|
+
params['stem' + i] = token.stem;
|
|
2835
|
+
values.push(
|
|
2836
|
+
"(decode(@guid, 'hex'), @name, @token" +
|
|
2837
|
+
i +
|
|
2838
|
+
', @position' +
|
|
2839
|
+
i +
|
|
2840
|
+
', @stem' +
|
|
2841
|
+
i +
|
|
2842
|
+
')',
|
|
2537
2843
|
);
|
|
2538
2844
|
}
|
|
2539
|
-
|
|
2540
|
-
|
|
2541
|
-
|
|
2845
|
+
|
|
2846
|
+
promises.push(
|
|
2847
|
+
this.queryRun(
|
|
2848
|
+
`INSERT INTO ${PostgreSQLDriver.escape(
|
|
2849
|
+
`${this.prefix}tokens_${etype}`,
|
|
2850
|
+
)} ("guid", "name", "token", "position", "stem") VALUES ${values.join(', ')};`,
|
|
2851
|
+
{
|
|
2852
|
+
etypes: [etype],
|
|
2853
|
+
params,
|
|
2854
|
+
},
|
|
2855
|
+
),
|
|
2856
|
+
);
|
|
2857
|
+
}
|
|
2858
|
+
}
|
|
2859
|
+
}
|
|
2860
|
+
|
|
2861
|
+
if (!onlyTokens) {
|
|
2862
|
+
const uniques = await EntityClass.getUniques({
|
|
2863
|
+
guid,
|
|
2864
|
+
cdate,
|
|
2865
|
+
mdate,
|
|
2866
|
+
tags,
|
|
2867
|
+
data: {},
|
|
2868
|
+
sdata,
|
|
2869
|
+
});
|
|
2870
|
+
for (const unique of uniques) {
|
|
2871
|
+
promises.push(
|
|
2872
|
+
this.queryRun(
|
|
2873
|
+
`INSERT INTO ${PostgreSQLDriver.escape(
|
|
2874
|
+
`${this.prefix}uniques_${etype}`,
|
|
2875
|
+
)} ("guid", "unique") VALUES (decode(@guid, 'hex'), @unique);`,
|
|
2876
|
+
{
|
|
2877
|
+
etypes: [etype],
|
|
2878
|
+
params: {
|
|
2879
|
+
guid,
|
|
2880
|
+
unique,
|
|
2881
|
+
},
|
|
2882
|
+
},
|
|
2883
|
+
).catch((e: any) => {
|
|
2884
|
+
if (e instanceof EntityUniqueConstraintError) {
|
|
2885
|
+
this.nymph.config.debugError(
|
|
2886
|
+
'postgresql',
|
|
2887
|
+
`Import entity unique constraint violation for GUID "${guid}" on etype "${etype}": "${unique}"`,
|
|
2888
|
+
);
|
|
2889
|
+
}
|
|
2890
|
+
return e;
|
|
2891
|
+
}),
|
|
2892
|
+
);
|
|
2893
|
+
}
|
|
2542
2894
|
}
|
|
2895
|
+
|
|
2543
2896
|
await Promise.all(promises);
|
|
2544
2897
|
} catch (e: any) {
|
|
2545
2898
|
this.nymph.config.debugError('postgresql', `Import entity error: "${e}"`);
|
|
@@ -2683,6 +3036,8 @@ export default class PostgreSQLDriver extends NymphDriver {
|
|
|
2683
3036
|
uniques: string[],
|
|
2684
3037
|
etype: string,
|
|
2685
3038
|
) => {
|
|
3039
|
+
const EntityClass = this.nymph.getEntityClassByEtype(etype);
|
|
3040
|
+
|
|
2686
3041
|
const runInsertQuery = async (
|
|
2687
3042
|
name: string,
|
|
2688
3043
|
value: any,
|
|
@@ -2701,7 +3056,9 @@ export default class PostgreSQLDriver extends NymphDriver {
|
|
|
2701
3056
|
storageValue === 'J'
|
|
2702
3057
|
? PostgreSQLDriver.escapeNullSequences(svalue)
|
|
2703
3058
|
: null;
|
|
3059
|
+
|
|
2704
3060
|
const promises = [];
|
|
3061
|
+
|
|
2705
3062
|
promises.push(
|
|
2706
3063
|
this.queryRun(
|
|
2707
3064
|
`INSERT INTO ${PostgreSQLDriver.escape(
|
|
@@ -2724,6 +3081,7 @@ export default class PostgreSQLDriver extends NymphDriver {
|
|
|
2724
3081
|
},
|
|
2725
3082
|
),
|
|
2726
3083
|
);
|
|
3084
|
+
|
|
2727
3085
|
const references = this.findReferences(svalue);
|
|
2728
3086
|
for (const reference of references) {
|
|
2729
3087
|
promises.push(
|
|
@@ -2742,8 +3100,57 @@ export default class PostgreSQLDriver extends NymphDriver {
|
|
|
2742
3100
|
),
|
|
2743
3101
|
);
|
|
2744
3102
|
}
|
|
3103
|
+
|
|
3104
|
+
let tokenString: string | null = null;
|
|
3105
|
+
try {
|
|
3106
|
+
tokenString = EntityClass.getFTSText(name, value);
|
|
3107
|
+
} catch (e: any) {
|
|
3108
|
+
// Ignore error.
|
|
3109
|
+
}
|
|
3110
|
+
|
|
3111
|
+
if (tokenString != null) {
|
|
3112
|
+
const tokens = this.tokenizer.tokenize(tokenString);
|
|
3113
|
+
while (tokens.length) {
|
|
3114
|
+
const currentTokens = tokens.splice(0, 100);
|
|
3115
|
+
const params: { [k: string]: any } = {
|
|
3116
|
+
guid,
|
|
3117
|
+
name,
|
|
3118
|
+
};
|
|
3119
|
+
const values: string[] = [];
|
|
3120
|
+
|
|
3121
|
+
for (let i = 0; i < currentTokens.length; i++) {
|
|
3122
|
+
const token = currentTokens[i];
|
|
3123
|
+
params['token' + i] = token.token;
|
|
3124
|
+
params['position' + i] = token.position;
|
|
3125
|
+
params['stem' + i] = token.stem;
|
|
3126
|
+
values.push(
|
|
3127
|
+
"(decode(@guid, 'hex'), @name, @token" +
|
|
3128
|
+
i +
|
|
3129
|
+
', @position' +
|
|
3130
|
+
i +
|
|
3131
|
+
', @stem' +
|
|
3132
|
+
i +
|
|
3133
|
+
')',
|
|
3134
|
+
);
|
|
3135
|
+
}
|
|
3136
|
+
|
|
3137
|
+
promises.push(
|
|
3138
|
+
this.queryRun(
|
|
3139
|
+
`INSERT INTO ${PostgreSQLDriver.escape(
|
|
3140
|
+
`${this.prefix}tokens_${etype}`,
|
|
3141
|
+
)} ("guid", "name", "token", "position", "stem") VALUES ${values.join(', ')};`,
|
|
3142
|
+
{
|
|
3143
|
+
etypes: [etype],
|
|
3144
|
+
params,
|
|
3145
|
+
},
|
|
3146
|
+
),
|
|
3147
|
+
);
|
|
3148
|
+
}
|
|
3149
|
+
}
|
|
3150
|
+
|
|
2745
3151
|
await Promise.all(promises);
|
|
2746
3152
|
};
|
|
3153
|
+
|
|
2747
3154
|
for (const unique of uniques) {
|
|
2748
3155
|
try {
|
|
2749
3156
|
await this.queryRun(
|
|
@@ -2849,6 +3256,19 @@ export default class PostgreSQLDriver extends NymphDriver {
|
|
|
2849
3256
|
},
|
|
2850
3257
|
),
|
|
2851
3258
|
);
|
|
3259
|
+
promises.push(
|
|
3260
|
+
this.queryRun(
|
|
3261
|
+
`SELECT 1 FROM ${PostgreSQLDriver.escape(
|
|
3262
|
+
`${this.prefix}tokens_${etype}`,
|
|
3263
|
+
)} WHERE "guid"=decode(@guid, 'hex') FOR UPDATE;`,
|
|
3264
|
+
{
|
|
3265
|
+
etypes: [etype],
|
|
3266
|
+
params: {
|
|
3267
|
+
guid,
|
|
3268
|
+
},
|
|
3269
|
+
},
|
|
3270
|
+
),
|
|
3271
|
+
);
|
|
2852
3272
|
promises.push(
|
|
2853
3273
|
this.queryRun(
|
|
2854
3274
|
`SELECT 1 FROM ${PostgreSQLDriver.escape(
|
|
@@ -2906,6 +3326,19 @@ export default class PostgreSQLDriver extends NymphDriver {
|
|
|
2906
3326
|
},
|
|
2907
3327
|
),
|
|
2908
3328
|
);
|
|
3329
|
+
promises.push(
|
|
3330
|
+
this.queryRun(
|
|
3331
|
+
`DELETE FROM ${PostgreSQLDriver.escape(
|
|
3332
|
+
`${this.prefix}tokens_${etype}`,
|
|
3333
|
+
)} WHERE "guid"=decode(@guid, 'hex');`,
|
|
3334
|
+
{
|
|
3335
|
+
etypes: [etype],
|
|
3336
|
+
params: {
|
|
3337
|
+
guid,
|
|
3338
|
+
},
|
|
3339
|
+
},
|
|
3340
|
+
),
|
|
3341
|
+
);
|
|
2909
3342
|
promises.push(
|
|
2910
3343
|
this.queryRun(
|
|
2911
3344
|
`DELETE FROM ${PostgreSQLDriver.escape(
|
|
@@ -3026,7 +3459,7 @@ export default class PostgreSQLDriver extends NymphDriver {
|
|
|
3026
3459
|
return nymph;
|
|
3027
3460
|
}
|
|
3028
3461
|
|
|
3029
|
-
public async needsMigration(): Promise<
|
|
3462
|
+
public async needsMigration(): Promise<'json' | 'tokens' | false> {
|
|
3030
3463
|
const table = await this.queryGet(
|
|
3031
3464
|
'SELECT "table_name" AS "table_name" FROM "information_schema"."tables" WHERE "table_catalog"=@db AND "table_schema"=\'public\' AND "table_name" LIKE @prefix LIMIT 1;',
|
|
3032
3465
|
{
|
|
@@ -3046,8 +3479,32 @@ export default class PostgreSQLDriver extends NymphDriver {
|
|
|
3046
3479
|
},
|
|
3047
3480
|
},
|
|
3048
3481
|
);
|
|
3049
|
-
|
|
3482
|
+
if (!result?.exists) {
|
|
3483
|
+
return 'json';
|
|
3484
|
+
}
|
|
3485
|
+
}
|
|
3486
|
+
const table2 = await this.queryGet(
|
|
3487
|
+
'SELECT "table_name" AS "table_name" FROM "information_schema"."tables" WHERE "table_catalog"=@db AND "table_schema"=\'public\' AND "table_name" LIKE @tokenTable LIMIT 1;',
|
|
3488
|
+
{
|
|
3489
|
+
params: {
|
|
3490
|
+
db: this.config.database,
|
|
3491
|
+
tokenTable: this.prefix + 'tokens_' + '%',
|
|
3492
|
+
},
|
|
3493
|
+
},
|
|
3494
|
+
);
|
|
3495
|
+
if (!table2 || !table2.table_name) {
|
|
3496
|
+
return 'tokens';
|
|
3050
3497
|
}
|
|
3051
3498
|
return false;
|
|
3052
3499
|
}
|
|
3500
|
+
|
|
3501
|
+
public async liveMigration(_migrationType: 'tokenTables') {
|
|
3502
|
+
const etypes = await this.getEtypes();
|
|
3503
|
+
|
|
3504
|
+
const connection = await this.getConnection(true);
|
|
3505
|
+
for (let etype of etypes) {
|
|
3506
|
+
await this.createTokensTable(etype, connection);
|
|
3507
|
+
}
|
|
3508
|
+
connection.done();
|
|
3509
|
+
}
|
|
3053
3510
|
}
|