@nymphjs/driver-postgresql 1.0.0-beta.97 → 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 +20 -0
- package/dist/PostgreSQLDriver.d.ts +18 -2
- package/dist/PostgreSQLDriver.js +454 -137
- package/dist/PostgreSQLDriver.js.map +1 -1
- package/package.json +5 -4
- package/src/PostgreSQLDriver.ts +1075 -426
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,81 +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
|
-
|
|
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
|
+
)} (
|
|
317
330
|
"guid" BYTEA NOT NULL,
|
|
318
331
|
"name" TEXT NOT NULL,
|
|
319
332
|
"value" CHARACTER(1) NOT NULL,
|
|
@@ -327,173 +340,269 @@ export default class PostgreSQLDriver extends NymphDriver {
|
|
|
327
340
|
`${this.prefix}entities_${etype}`,
|
|
328
341
|
)} ("guid") MATCH SIMPLE ON UPDATE NO ACTION ON DELETE CASCADE
|
|
329
342
|
) WITH ( OIDS=FALSE );`,
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
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
|
-
|
|
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
|
+
)} (
|
|
497
606
|
"guid" BYTEA NOT NULL,
|
|
498
607
|
"name" TEXT NOT NULL,
|
|
499
608
|
"reference" BYTEA NOT NULL,
|
|
@@ -503,61 +612,207 @@ export default class PostgreSQLDriver extends NymphDriver {
|
|
|
503
612
|
`${this.prefix}entities_${etype}`,
|
|
504
613
|
)} ("guid") MATCH SIMPLE ON UPDATE NO ACTION ON DELETE CASCADE
|
|
505
614
|
) WITH ( OIDS=FALSE );`,
|
|
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
|
-
|
|
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
|
+
)} (
|
|
561
816
|
"guid" BYTEA NOT NULL,
|
|
562
817
|
"unique" TEXT NOT NULL UNIQUE,
|
|
563
818
|
PRIMARY KEY ("guid", "unique"),
|
|
@@ -566,8 +821,30 @@ export default class PostgreSQLDriver extends NymphDriver {
|
|
|
566
821
|
`${this.prefix}entities_${etype}`,
|
|
567
822
|
)} ("guid") MATCH SIMPLE ON UPDATE NO ACTION ON DELETE CASCADE
|
|
568
823
|
) WITH ( OIDS=FALSE );`,
|
|
569
|
-
|
|
570
|
-
|
|
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);
|
|
571
848
|
} else {
|
|
572
849
|
// Add trigram extensions.
|
|
573
850
|
try {
|
|
@@ -883,6 +1160,17 @@ export default class PostgreSQLDriver extends NymphDriver {
|
|
|
883
1160
|
},
|
|
884
1161
|
},
|
|
885
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
|
+
);
|
|
886
1174
|
await this.queryRun(
|
|
887
1175
|
`DELETE FROM ${PostgreSQLDriver.escape(
|
|
888
1176
|
`${this.prefix}uniques_${etype}`,
|
|
@@ -925,6 +1213,24 @@ export default class PostgreSQLDriver extends NymphDriver {
|
|
|
925
1213
|
return true;
|
|
926
1214
|
}
|
|
927
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
|
+
|
|
928
1234
|
public async *exportDataIterator(): AsyncGenerator<
|
|
929
1235
|
{ type: 'comment' | 'uid' | 'entity'; content: string },
|
|
930
1236
|
void,
|
|
@@ -987,19 +1293,7 @@ export default class PostgreSQLDriver extends NymphDriver {
|
|
|
987
1293
|
}
|
|
988
1294
|
|
|
989
1295
|
// Get the etypes.
|
|
990
|
-
const
|
|
991
|
-
'SELECT "table_name" AS "table_name" FROM "information_schema"."tables" WHERE "table_catalog"=@db AND "table_schema"=\'public\' AND "table_name" LIKE @prefix;',
|
|
992
|
-
{
|
|
993
|
-
params: {
|
|
994
|
-
db: this.config.database,
|
|
995
|
-
prefix: this.prefix + 'entities_' + '%',
|
|
996
|
-
},
|
|
997
|
-
},
|
|
998
|
-
);
|
|
999
|
-
const etypes = [];
|
|
1000
|
-
for (const table of tables) {
|
|
1001
|
-
etypes.push(table.table_name.substr((this.prefix + 'entities_').length));
|
|
1002
|
-
}
|
|
1296
|
+
const etypes = await this.getEtypes();
|
|
1003
1297
|
|
|
1004
1298
|
for (const etype of etypes) {
|
|
1005
1299
|
// Export entities.
|
|
@@ -1341,6 +1635,148 @@ export default class PostgreSQLDriver extends NymphDriver {
|
|
|
1341
1635
|
params[value] = PostgreSQLDriver.escapeNullSequences(svalue);
|
|
1342
1636
|
}
|
|
1343
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;
|
|
1344
1780
|
case 'match':
|
|
1345
1781
|
case '!match':
|
|
1346
1782
|
if (curValue[0] === 'cdate') {
|
|
@@ -2179,14 +2615,18 @@ export default class PostgreSQLDriver extends NymphDriver {
|
|
|
2179
2615
|
return result?.cur_uid == null ? null : Number(result.cur_uid);
|
|
2180
2616
|
}
|
|
2181
2617
|
|
|
2182
|
-
public async importEntity({
|
|
2183
|
-
guid
|
|
2184
|
-
cdate
|
|
2185
|
-
mdate
|
|
2186
|
-
tags
|
|
2187
|
-
sdata
|
|
2188
|
-
etype
|
|
2189
|
-
}
|
|
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: {
|
|
2190
2630
|
guid: string;
|
|
2191
2631
|
cdate: number;
|
|
2192
2632
|
mdate: number;
|
|
@@ -2194,51 +2634,74 @@ export default class PostgreSQLDriver extends NymphDriver {
|
|
|
2194
2634
|
sdata: SerializedEntityData;
|
|
2195
2635
|
etype: string;
|
|
2196
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
|
+
) {
|
|
2197
2658
|
try {
|
|
2198
2659
|
let promises = [];
|
|
2199
|
-
|
|
2200
|
-
|
|
2201
|
-
|
|
2202
|
-
|
|
2203
|
-
|
|
2204
|
-
|
|
2205
|
-
|
|
2206
|
-
|
|
2207
|
-
|
|
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
|
+
},
|
|
2208
2671
|
},
|
|
2209
|
-
|
|
2210
|
-
)
|
|
2211
|
-
|
|
2212
|
-
|
|
2213
|
-
|
|
2214
|
-
|
|
2215
|
-
|
|
2216
|
-
|
|
2217
|
-
|
|
2218
|
-
|
|
2219
|
-
|
|
2220
|
-
|
|
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
|
+
},
|
|
2221
2684
|
},
|
|
2222
|
-
|
|
2223
|
-
)
|
|
2224
|
-
|
|
2225
|
-
|
|
2226
|
-
|
|
2227
|
-
|
|
2228
|
-
|
|
2229
|
-
|
|
2230
|
-
|
|
2231
|
-
|
|
2232
|
-
|
|
2233
|
-
|
|
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
|
+
},
|
|
2234
2697
|
},
|
|
2235
|
-
|
|
2236
|
-
)
|
|
2237
|
-
|
|
2698
|
+
),
|
|
2699
|
+
);
|
|
2700
|
+
}
|
|
2238
2701
|
promises.push(
|
|
2239
2702
|
this.queryRun(
|
|
2240
2703
|
`DELETE FROM ${PostgreSQLDriver.escape(
|
|
2241
|
-
`${this.prefix}
|
|
2704
|
+
`${this.prefix}tokens_${etype}`,
|
|
2242
2705
|
)} WHERE "guid"=decode(@guid, 'hex');`,
|
|
2243
2706
|
{
|
|
2244
2707
|
etypes: [etype],
|
|
@@ -2248,106 +2711,188 @@ export default class PostgreSQLDriver extends NymphDriver {
|
|
|
2248
2711
|
},
|
|
2249
2712
|
),
|
|
2250
2713
|
);
|
|
2251
|
-
|
|
2252
|
-
promises = [];
|
|
2253
|
-
await this.queryRun(
|
|
2254
|
-
`INSERT INTO ${PostgreSQLDriver.escape(
|
|
2255
|
-
`${this.prefix}entities_${etype}`,
|
|
2256
|
-
)} ("guid", "tags", "cdate", "mdate") VALUES (decode(@guid, 'hex'), @tags, @cdate, @mdate);`,
|
|
2257
|
-
{
|
|
2258
|
-
etypes: [etype],
|
|
2259
|
-
params: {
|
|
2260
|
-
guid,
|
|
2261
|
-
tags,
|
|
2262
|
-
cdate: isNaN(cdate) ? null : cdate,
|
|
2263
|
-
mdate: isNaN(mdate) ? null : mdate,
|
|
2264
|
-
},
|
|
2265
|
-
},
|
|
2266
|
-
);
|
|
2267
|
-
for (const name in sdata) {
|
|
2268
|
-
const value = sdata[name];
|
|
2269
|
-
const uvalue = JSON.parse(value);
|
|
2270
|
-
if (value === undefined) {
|
|
2271
|
-
continue;
|
|
2272
|
-
}
|
|
2273
|
-
const storageValue =
|
|
2274
|
-
typeof uvalue === 'number'
|
|
2275
|
-
? 'N'
|
|
2276
|
-
: typeof uvalue === 'string'
|
|
2277
|
-
? 'S'
|
|
2278
|
-
: 'J';
|
|
2279
|
-
const jsonValue =
|
|
2280
|
-
storageValue === 'J'
|
|
2281
|
-
? PostgreSQLDriver.escapeNullSequences(value)
|
|
2282
|
-
: null;
|
|
2714
|
+
if (!onlyTokens) {
|
|
2283
2715
|
promises.push(
|
|
2284
2716
|
this.queryRun(
|
|
2285
|
-
`
|
|
2286
|
-
`${this.prefix}
|
|
2287
|
-
)}
|
|
2717
|
+
`DELETE FROM ${PostgreSQLDriver.escape(
|
|
2718
|
+
`${this.prefix}uniques_${etype}`,
|
|
2719
|
+
)} WHERE "guid"=decode(@guid, 'hex');`,
|
|
2288
2720
|
{
|
|
2289
2721
|
etypes: [etype],
|
|
2290
2722
|
params: {
|
|
2291
2723
|
guid,
|
|
2292
|
-
name,
|
|
2293
|
-
storageValue,
|
|
2294
|
-
jsonValue,
|
|
2295
|
-
string:
|
|
2296
|
-
storageValue === 'J'
|
|
2297
|
-
? null
|
|
2298
|
-
: PostgreSQLDriver.escapeNulls(`${uvalue}`),
|
|
2299
|
-
number: isNaN(Number(uvalue)) ? null : Number(uvalue),
|
|
2300
|
-
truthy: !!uvalue,
|
|
2301
2724
|
},
|
|
2302
2725
|
},
|
|
2303
2726
|
),
|
|
2304
2727
|
);
|
|
2305
|
-
|
|
2306
|
-
|
|
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
|
+
|
|
2307
2766
|
promises.push(
|
|
2308
2767
|
this.queryRun(
|
|
2309
2768
|
`INSERT INTO ${PostgreSQLDriver.escape(
|
|
2310
|
-
`${this.prefix}
|
|
2311
|
-
)} ("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);`,
|
|
2312
2771
|
{
|
|
2313
2772
|
etypes: [etype],
|
|
2314
2773
|
params: {
|
|
2315
2774
|
guid,
|
|
2316
2775
|
name,
|
|
2317
|
-
|
|
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,
|
|
2318
2784
|
},
|
|
2319
2785
|
},
|
|
2320
2786
|
),
|
|
2321
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
|
+
}
|
|
2322
2807
|
}
|
|
2323
2808
|
}
|
|
2324
|
-
|
|
2325
|
-
|
|
2326
|
-
|
|
2327
|
-
for (
|
|
2328
|
-
|
|
2329
|
-
|
|
2330
|
-
|
|
2331
|
-
|
|
2332
|
-
|
|
2333
|
-
|
|
2334
|
-
|
|
2335
|
-
|
|
2336
|
-
|
|
2337
|
-
|
|
2338
|
-
|
|
2339
|
-
}
|
|
2340
|
-
|
|
2341
|
-
|
|
2342
|
-
|
|
2343
|
-
|
|
2344
|
-
|
|
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
|
+
')',
|
|
2345
2843
|
);
|
|
2346
2844
|
}
|
|
2347
|
-
|
|
2348
|
-
|
|
2349
|
-
|
|
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
|
+
}
|
|
2350
2894
|
}
|
|
2895
|
+
|
|
2351
2896
|
await Promise.all(promises);
|
|
2352
2897
|
} catch (e: any) {
|
|
2353
2898
|
this.nymph.config.debugError('postgresql', `Import entity error: "${e}"`);
|
|
@@ -2491,6 +3036,8 @@ export default class PostgreSQLDriver extends NymphDriver {
|
|
|
2491
3036
|
uniques: string[],
|
|
2492
3037
|
etype: string,
|
|
2493
3038
|
) => {
|
|
3039
|
+
const EntityClass = this.nymph.getEntityClassByEtype(etype);
|
|
3040
|
+
|
|
2494
3041
|
const runInsertQuery = async (
|
|
2495
3042
|
name: string,
|
|
2496
3043
|
value: any,
|
|
@@ -2509,7 +3056,9 @@ export default class PostgreSQLDriver extends NymphDriver {
|
|
|
2509
3056
|
storageValue === 'J'
|
|
2510
3057
|
? PostgreSQLDriver.escapeNullSequences(svalue)
|
|
2511
3058
|
: null;
|
|
3059
|
+
|
|
2512
3060
|
const promises = [];
|
|
3061
|
+
|
|
2513
3062
|
promises.push(
|
|
2514
3063
|
this.queryRun(
|
|
2515
3064
|
`INSERT INTO ${PostgreSQLDriver.escape(
|
|
@@ -2532,6 +3081,7 @@ export default class PostgreSQLDriver extends NymphDriver {
|
|
|
2532
3081
|
},
|
|
2533
3082
|
),
|
|
2534
3083
|
);
|
|
3084
|
+
|
|
2535
3085
|
const references = this.findReferences(svalue);
|
|
2536
3086
|
for (const reference of references) {
|
|
2537
3087
|
promises.push(
|
|
@@ -2550,8 +3100,57 @@ export default class PostgreSQLDriver extends NymphDriver {
|
|
|
2550
3100
|
),
|
|
2551
3101
|
);
|
|
2552
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
|
+
|
|
2553
3151
|
await Promise.all(promises);
|
|
2554
3152
|
};
|
|
3153
|
+
|
|
2555
3154
|
for (const unique of uniques) {
|
|
2556
3155
|
try {
|
|
2557
3156
|
await this.queryRun(
|
|
@@ -2657,6 +3256,19 @@ export default class PostgreSQLDriver extends NymphDriver {
|
|
|
2657
3256
|
},
|
|
2658
3257
|
),
|
|
2659
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
|
+
);
|
|
2660
3272
|
promises.push(
|
|
2661
3273
|
this.queryRun(
|
|
2662
3274
|
`SELECT 1 FROM ${PostgreSQLDriver.escape(
|
|
@@ -2714,6 +3326,19 @@ export default class PostgreSQLDriver extends NymphDriver {
|
|
|
2714
3326
|
},
|
|
2715
3327
|
),
|
|
2716
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
|
+
);
|
|
2717
3342
|
promises.push(
|
|
2718
3343
|
this.queryRun(
|
|
2719
3344
|
`DELETE FROM ${PostgreSQLDriver.escape(
|
|
@@ -2834,7 +3459,7 @@ export default class PostgreSQLDriver extends NymphDriver {
|
|
|
2834
3459
|
return nymph;
|
|
2835
3460
|
}
|
|
2836
3461
|
|
|
2837
|
-
public async needsMigration(): Promise<
|
|
3462
|
+
public async needsMigration(): Promise<'json' | 'tokens' | false> {
|
|
2838
3463
|
const table = await this.queryGet(
|
|
2839
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;',
|
|
2840
3465
|
{
|
|
@@ -2854,8 +3479,32 @@ export default class PostgreSQLDriver extends NymphDriver {
|
|
|
2854
3479
|
},
|
|
2855
3480
|
},
|
|
2856
3481
|
);
|
|
2857
|
-
|
|
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';
|
|
2858
3497
|
}
|
|
2859
3498
|
return false;
|
|
2860
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
|
+
}
|
|
2861
3510
|
}
|