@nymphjs/driver-sqlite3 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/SQLite3Driver.d.ts +18 -2
- package/dist/SQLite3Driver.js +377 -99
- package/dist/SQLite3Driver.js.map +1 -1
- package/package.json +5 -4
- package/src/SQLite3Driver.ts +705 -249
package/src/SQLite3Driver.ts
CHANGED
|
@@ -1,4 +1,10 @@
|
|
|
1
1
|
import SQLite3 from 'better-sqlite3';
|
|
2
|
+
import type {
|
|
3
|
+
SearchTerm,
|
|
4
|
+
SearchOrTerm,
|
|
5
|
+
SearchNotTerm,
|
|
6
|
+
SearchSeriesTerm,
|
|
7
|
+
} from '@sciactive/tokenizer';
|
|
2
8
|
import {
|
|
3
9
|
NymphDriver,
|
|
4
10
|
type EntityConstructor,
|
|
@@ -220,6 +226,244 @@ export default class SQLite3Driver extends NymphDriver {
|
|
|
220
226
|
return this.store.connected;
|
|
221
227
|
}
|
|
222
228
|
|
|
229
|
+
private createEntitiesTable(etype: string) {
|
|
230
|
+
// Create the entity table.
|
|
231
|
+
this.queryRun(
|
|
232
|
+
`CREATE TABLE IF NOT EXISTS ${SQLite3Driver.escape(
|
|
233
|
+
`${this.prefix}entities_${etype}`,
|
|
234
|
+
)} ("guid" CHARACTER(24) PRIMARY KEY, "tags" TEXT, "cdate" REAL NOT NULL, "mdate" REAL NOT NULL);`,
|
|
235
|
+
);
|
|
236
|
+
this.queryRun(
|
|
237
|
+
`CREATE INDEX IF NOT EXISTS ${SQLite3Driver.escape(
|
|
238
|
+
`${this.prefix}entities_${etype}_id_cdate`,
|
|
239
|
+
)} ON ${SQLite3Driver.escape(
|
|
240
|
+
`${this.prefix}entities_${etype}`,
|
|
241
|
+
)} ("cdate");`,
|
|
242
|
+
);
|
|
243
|
+
this.queryRun(
|
|
244
|
+
`CREATE INDEX IF NOT EXISTS ${SQLite3Driver.escape(
|
|
245
|
+
`${this.prefix}entities_${etype}_id_mdate`,
|
|
246
|
+
)} ON ${SQLite3Driver.escape(
|
|
247
|
+
`${this.prefix}entities_${etype}`,
|
|
248
|
+
)} ("mdate");`,
|
|
249
|
+
);
|
|
250
|
+
this.queryRun(
|
|
251
|
+
`CREATE INDEX IF NOT EXISTS ${SQLite3Driver.escape(
|
|
252
|
+
`${this.prefix}entities_${etype}_id_tags`,
|
|
253
|
+
)} ON ${SQLite3Driver.escape(
|
|
254
|
+
`${this.prefix}entities_${etype}`,
|
|
255
|
+
)} ("tags");`,
|
|
256
|
+
);
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
private createDataTable(etype: string) {
|
|
260
|
+
// Create the data table.
|
|
261
|
+
this.queryRun(
|
|
262
|
+
`CREATE TABLE IF NOT EXISTS ${SQLite3Driver.escape(
|
|
263
|
+
`${this.prefix}data_${etype}`,
|
|
264
|
+
)} ("guid" CHARACTER(24) NOT NULL REFERENCES ${SQLite3Driver.escape(
|
|
265
|
+
`${this.prefix}entities_${etype}`,
|
|
266
|
+
)} ("guid") ON DELETE CASCADE, "name" TEXT NOT NULL, "value" CHARACTER(1) NOT NULL, "json" BLOB, "string" TEXT, "number" REAL, "truthy" INTEGER, PRIMARY KEY("guid", "name"));`,
|
|
267
|
+
);
|
|
268
|
+
this.queryRun(
|
|
269
|
+
`CREATE INDEX IF NOT EXISTS ${SQLite3Driver.escape(
|
|
270
|
+
`${this.prefix}data_${etype}_id_guid`,
|
|
271
|
+
)} ON ${SQLite3Driver.escape(`${this.prefix}data_${etype}`)} ("guid");`,
|
|
272
|
+
);
|
|
273
|
+
this.queryRun(
|
|
274
|
+
`CREATE INDEX IF NOT EXISTS ${SQLite3Driver.escape(
|
|
275
|
+
`${this.prefix}data_${etype}_id_guid_name`,
|
|
276
|
+
)} ON ${SQLite3Driver.escape(
|
|
277
|
+
`${this.prefix}data_${etype}`,
|
|
278
|
+
)} ("guid", "name");`,
|
|
279
|
+
);
|
|
280
|
+
this.queryRun(
|
|
281
|
+
`CREATE INDEX IF NOT EXISTS ${SQLite3Driver.escape(
|
|
282
|
+
`${this.prefix}data_${etype}_id_name`,
|
|
283
|
+
)} ON ${SQLite3Driver.escape(`${this.prefix}data_${etype}`)} ("name");`,
|
|
284
|
+
);
|
|
285
|
+
this.queryRun(
|
|
286
|
+
`CREATE INDEX IF NOT EXISTS ${SQLite3Driver.escape(
|
|
287
|
+
`${this.prefix}data_${etype}_id_name_string`,
|
|
288
|
+
)} ON ${SQLite3Driver.escape(
|
|
289
|
+
`${this.prefix}data_${etype}`,
|
|
290
|
+
)} ("name", "string");`,
|
|
291
|
+
);
|
|
292
|
+
this.queryRun(
|
|
293
|
+
`CREATE INDEX IF NOT EXISTS ${SQLite3Driver.escape(
|
|
294
|
+
`${this.prefix}data_${etype}_id_name_number`,
|
|
295
|
+
)} ON ${SQLite3Driver.escape(
|
|
296
|
+
`${this.prefix}data_${etype}`,
|
|
297
|
+
)} ("name", "number");`,
|
|
298
|
+
);
|
|
299
|
+
this.queryRun(
|
|
300
|
+
`CREATE INDEX IF NOT EXISTS ${SQLite3Driver.escape(
|
|
301
|
+
`${this.prefix}data_${etype}_id_guid_name_number`,
|
|
302
|
+
)} ON ${SQLite3Driver.escape(
|
|
303
|
+
`${this.prefix}data_${etype}`,
|
|
304
|
+
)} ("guid", "name", "number");`,
|
|
305
|
+
);
|
|
306
|
+
this.queryRun(
|
|
307
|
+
`CREATE INDEX IF NOT EXISTS ${SQLite3Driver.escape(
|
|
308
|
+
`${this.prefix}data_${etype}_id_name_truthy`,
|
|
309
|
+
)} ON ${SQLite3Driver.escape(
|
|
310
|
+
`${this.prefix}data_${etype}`,
|
|
311
|
+
)} ("name", "truthy");`,
|
|
312
|
+
);
|
|
313
|
+
this.queryRun(
|
|
314
|
+
`CREATE INDEX IF NOT EXISTS ${SQLite3Driver.escape(
|
|
315
|
+
`${this.prefix}data_${etype}_id_guid_name_truthy`,
|
|
316
|
+
)} ON ${SQLite3Driver.escape(
|
|
317
|
+
`${this.prefix}data_${etype}`,
|
|
318
|
+
)} ("guid", "name", "truthy");`,
|
|
319
|
+
);
|
|
320
|
+
this.queryRun(
|
|
321
|
+
`CREATE INDEX IF NOT EXISTS ${SQLite3Driver.escape(
|
|
322
|
+
`${this.prefix}data_${etype}_id_acuserread`,
|
|
323
|
+
)} ON ${SQLite3Driver.escape(
|
|
324
|
+
`${this.prefix}data_${etype}`,
|
|
325
|
+
)} ("guid") WHERE "name"=\'acUser\' AND "number" >= 1;`,
|
|
326
|
+
);
|
|
327
|
+
this.queryRun(
|
|
328
|
+
`CREATE INDEX IF NOT EXISTS ${SQLite3Driver.escape(
|
|
329
|
+
`${this.prefix}data_${etype}_id_acgroupread`,
|
|
330
|
+
)} ON ${SQLite3Driver.escape(
|
|
331
|
+
`${this.prefix}data_${etype}`,
|
|
332
|
+
)} ("guid") WHERE "name"=\'acGroup\' AND "number" >= 1;`,
|
|
333
|
+
);
|
|
334
|
+
this.queryRun(
|
|
335
|
+
`CREATE INDEX IF NOT EXISTS ${SQLite3Driver.escape(
|
|
336
|
+
`${this.prefix}data_${etype}_id_acotherread`,
|
|
337
|
+
)} ON ${SQLite3Driver.escape(
|
|
338
|
+
`${this.prefix}data_${etype}`,
|
|
339
|
+
)} ("guid") WHERE "name"=\'acOther\' AND "number" >= 1;`,
|
|
340
|
+
);
|
|
341
|
+
this.queryRun(
|
|
342
|
+
`CREATE INDEX IF NOT EXISTS ${SQLite3Driver.escape(
|
|
343
|
+
`${this.prefix}data_${etype}_id_acuser`,
|
|
344
|
+
)} ON ${SQLite3Driver.escape(
|
|
345
|
+
`${this.prefix}data_${etype}`,
|
|
346
|
+
)} ("guid") WHERE "name"=\'user\';`,
|
|
347
|
+
);
|
|
348
|
+
this.queryRun(
|
|
349
|
+
`CREATE INDEX IF NOT EXISTS ${SQLite3Driver.escape(
|
|
350
|
+
`${this.prefix}data_${etype}_id_acgroup`,
|
|
351
|
+
)} ON ${SQLite3Driver.escape(
|
|
352
|
+
`${this.prefix}data_${etype}`,
|
|
353
|
+
)} ("guid") WHERE "name"=\'group\';`,
|
|
354
|
+
);
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
private createReferencesTable(etype: string) {
|
|
358
|
+
// Create the references table.
|
|
359
|
+
this.queryRun(
|
|
360
|
+
`CREATE TABLE IF NOT EXISTS ${SQLite3Driver.escape(
|
|
361
|
+
`${this.prefix}references_${etype}`,
|
|
362
|
+
)} ("guid" CHARACTER(24) NOT NULL REFERENCES ${SQLite3Driver.escape(
|
|
363
|
+
`${this.prefix}entities_${etype}`,
|
|
364
|
+
)} ("guid") ON DELETE CASCADE, "name" TEXT NOT NULL, "reference" CHARACTER(24) NOT NULL, PRIMARY KEY("guid", "name", "reference"));`,
|
|
365
|
+
);
|
|
366
|
+
this.queryRun(
|
|
367
|
+
`CREATE INDEX IF NOT EXISTS ${SQLite3Driver.escape(
|
|
368
|
+
`${this.prefix}references_${etype}_id_guid`,
|
|
369
|
+
)} ON ${SQLite3Driver.escape(
|
|
370
|
+
`${this.prefix}references_${etype}`,
|
|
371
|
+
)} ("guid");`,
|
|
372
|
+
);
|
|
373
|
+
this.queryRun(
|
|
374
|
+
`CREATE INDEX IF NOT EXISTS ${SQLite3Driver.escape(
|
|
375
|
+
`${this.prefix}references_${etype}_id_name`,
|
|
376
|
+
)} ON ${SQLite3Driver.escape(
|
|
377
|
+
`${this.prefix}references_${etype}`,
|
|
378
|
+
)} ("name");`,
|
|
379
|
+
);
|
|
380
|
+
this.queryRun(
|
|
381
|
+
`CREATE INDEX IF NOT EXISTS ${SQLite3Driver.escape(
|
|
382
|
+
`${this.prefix}references_${etype}_id_name_reference`,
|
|
383
|
+
)} ON ${SQLite3Driver.escape(
|
|
384
|
+
`${this.prefix}references_${etype}`,
|
|
385
|
+
)} ("name", "reference");`,
|
|
386
|
+
);
|
|
387
|
+
this.queryRun(
|
|
388
|
+
`CREATE INDEX IF NOT EXISTS ${SQLite3Driver.escape(
|
|
389
|
+
`${this.prefix}references_${etype}_id_reference`,
|
|
390
|
+
)} ON ${SQLite3Driver.escape(
|
|
391
|
+
`${this.prefix}references_${etype}`,
|
|
392
|
+
)} ("reference");`,
|
|
393
|
+
);
|
|
394
|
+
this.queryRun(
|
|
395
|
+
`CREATE INDEX IF NOT EXISTS ${SQLite3Driver.escape(
|
|
396
|
+
`${this.prefix}references_${etype}_id_guid_name`,
|
|
397
|
+
)} ON ${SQLite3Driver.escape(
|
|
398
|
+
`${this.prefix}references_${etype}`,
|
|
399
|
+
)} ("guid", "name");`,
|
|
400
|
+
);
|
|
401
|
+
this.queryRun(
|
|
402
|
+
`CREATE INDEX IF NOT EXISTS ${SQLite3Driver.escape(
|
|
403
|
+
`${this.prefix}references_${etype}_id_guid_name_reference`,
|
|
404
|
+
)} ON ${SQLite3Driver.escape(
|
|
405
|
+
`${this.prefix}references_${etype}`,
|
|
406
|
+
)} ("guid", "name", "reference");`,
|
|
407
|
+
);
|
|
408
|
+
this.queryRun(
|
|
409
|
+
`CREATE INDEX IF NOT EXISTS ${SQLite3Driver.escape(
|
|
410
|
+
`${this.prefix}references_${etype}_id_reference_name_guid`,
|
|
411
|
+
)} ON ${SQLite3Driver.escape(
|
|
412
|
+
`${this.prefix}references_${etype}`,
|
|
413
|
+
)} ("reference", "name", "guid");`,
|
|
414
|
+
);
|
|
415
|
+
this.queryRun(
|
|
416
|
+
`CREATE INDEX IF NOT EXISTS ${SQLite3Driver.escape(
|
|
417
|
+
`${this.prefix}references_${etype}_id_reference_guid_name`,
|
|
418
|
+
)} ON ${SQLite3Driver.escape(
|
|
419
|
+
`${this.prefix}references_${etype}`,
|
|
420
|
+
)} ("reference", "guid", "name");`,
|
|
421
|
+
);
|
|
422
|
+
this.queryRun(
|
|
423
|
+
`CREATE INDEX IF NOT EXISTS ${SQLite3Driver.escape(
|
|
424
|
+
`${this.prefix}references_${etype}_id_guid_reference_nameuser`,
|
|
425
|
+
)} ON ${SQLite3Driver.escape(
|
|
426
|
+
`${this.prefix}references_${etype}`,
|
|
427
|
+
)} ("guid", "reference") WHERE "name"=\'user\';`,
|
|
428
|
+
);
|
|
429
|
+
this.queryRun(
|
|
430
|
+
`CREATE INDEX IF NOT EXISTS ${SQLite3Driver.escape(
|
|
431
|
+
`${this.prefix}references_${etype}_id_guid_reference_namegroup`,
|
|
432
|
+
)} ON ${SQLite3Driver.escape(
|
|
433
|
+
`${this.prefix}references_${etype}`,
|
|
434
|
+
)} ("guid", "reference") WHERE "name"=\'group\';`,
|
|
435
|
+
);
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
private createTokensTable(etype: string) {
|
|
439
|
+
// Create the tokens table.
|
|
440
|
+
this.queryRun(
|
|
441
|
+
`CREATE TABLE IF NOT EXISTS ${SQLite3Driver.escape(
|
|
442
|
+
`${this.prefix}tokens_${etype}`,
|
|
443
|
+
)} ("guid" CHARACTER(24) NOT NULL REFERENCES ${SQLite3Driver.escape(
|
|
444
|
+
`${this.prefix}entities_${etype}`,
|
|
445
|
+
)} ("guid") ON DELETE CASCADE, "name" TEXT NOT NULL, "token" INTEGER NOT NULL, "position" INTEGER NOT NULL, "stem" INTEGER NOT NULL, PRIMARY KEY("guid", "name", "token", "position"));`,
|
|
446
|
+
);
|
|
447
|
+
this.queryRun(
|
|
448
|
+
`CREATE INDEX IF NOT EXISTS ${SQLite3Driver.escape(
|
|
449
|
+
`${this.prefix}tokens_${etype}_id_name_token`,
|
|
450
|
+
)} ON ${SQLite3Driver.escape(
|
|
451
|
+
`${this.prefix}tokens_${etype}`,
|
|
452
|
+
)} ("name", "token");`,
|
|
453
|
+
);
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
private createUniquesTable(etype: string) {
|
|
457
|
+
// Create the unique strings table.
|
|
458
|
+
this.queryRun(
|
|
459
|
+
`CREATE TABLE IF NOT EXISTS ${SQLite3Driver.escape(
|
|
460
|
+
`${this.prefix}uniques_${etype}`,
|
|
461
|
+
)} ("guid" CHARACTER(24) NOT NULL REFERENCES ${SQLite3Driver.escape(
|
|
462
|
+
`${this.prefix}entities_${etype}`,
|
|
463
|
+
)} ("guid") ON DELETE CASCADE, "unique" TEXT NOT NULL UNIQUE, PRIMARY KEY("guid", "unique"));`,
|
|
464
|
+
);
|
|
465
|
+
}
|
|
466
|
+
|
|
223
467
|
/**
|
|
224
468
|
* Create entity tables in the database.
|
|
225
469
|
*
|
|
@@ -229,141 +473,11 @@ export default class SQLite3Driver extends NymphDriver {
|
|
|
229
473
|
this.startTransaction('nymph-tablecreation');
|
|
230
474
|
try {
|
|
231
475
|
if (etype != null) {
|
|
232
|
-
|
|
233
|
-
this.
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
);
|
|
238
|
-
this.queryRun(
|
|
239
|
-
`CREATE INDEX IF NOT EXISTS ${SQLite3Driver.escape(
|
|
240
|
-
`${this.prefix}entities_${etype}_id_cdate`,
|
|
241
|
-
)} ON ${SQLite3Driver.escape(
|
|
242
|
-
`${this.prefix}entities_${etype}`,
|
|
243
|
-
)} ("cdate");`,
|
|
244
|
-
);
|
|
245
|
-
this.queryRun(
|
|
246
|
-
`CREATE INDEX IF NOT EXISTS ${SQLite3Driver.escape(
|
|
247
|
-
`${this.prefix}entities_${etype}_id_mdate`,
|
|
248
|
-
)} ON ${SQLite3Driver.escape(
|
|
249
|
-
`${this.prefix}entities_${etype}`,
|
|
250
|
-
)} ("mdate");`,
|
|
251
|
-
);
|
|
252
|
-
this.queryRun(
|
|
253
|
-
`CREATE INDEX IF NOT EXISTS ${SQLite3Driver.escape(
|
|
254
|
-
`${this.prefix}entities_${etype}_id_tags`,
|
|
255
|
-
)} ON ${SQLite3Driver.escape(
|
|
256
|
-
`${this.prefix}entities_${etype}`,
|
|
257
|
-
)} ("tags");`,
|
|
258
|
-
);
|
|
259
|
-
// Create the data table.
|
|
260
|
-
this.queryRun(
|
|
261
|
-
`CREATE TABLE IF NOT EXISTS ${SQLite3Driver.escape(
|
|
262
|
-
`${this.prefix}data_${etype}`,
|
|
263
|
-
)} ("guid" CHARACTER(24) NOT NULL REFERENCES ${SQLite3Driver.escape(
|
|
264
|
-
`${this.prefix}entities_${etype}`,
|
|
265
|
-
)} ("guid") ON DELETE CASCADE, "name" TEXT NOT NULL, "value" CHARACTER(1) NOT NULL, "json" BLOB, "string" TEXT, "number" REAL, "truthy" INTEGER, PRIMARY KEY("guid", "name"));`,
|
|
266
|
-
);
|
|
267
|
-
this.queryRun(
|
|
268
|
-
`CREATE INDEX IF NOT EXISTS ${SQLite3Driver.escape(
|
|
269
|
-
`${this.prefix}data_${etype}_id_guid`,
|
|
270
|
-
)} ON ${SQLite3Driver.escape(
|
|
271
|
-
`${this.prefix}data_${etype}`,
|
|
272
|
-
)} ("guid");`,
|
|
273
|
-
);
|
|
274
|
-
this.queryRun(
|
|
275
|
-
`CREATE INDEX IF NOT EXISTS ${SQLite3Driver.escape(
|
|
276
|
-
`${this.prefix}data_${etype}_id_guid_name`,
|
|
277
|
-
)} ON ${SQLite3Driver.escape(
|
|
278
|
-
`${this.prefix}data_${etype}`,
|
|
279
|
-
)} ("guid", "name");`,
|
|
280
|
-
);
|
|
281
|
-
this.queryRun(
|
|
282
|
-
`CREATE INDEX IF NOT EXISTS ${SQLite3Driver.escape(
|
|
283
|
-
`${this.prefix}data_${etype}_id_guid__name_user`,
|
|
284
|
-
)} ON ${SQLite3Driver.escape(
|
|
285
|
-
`${this.prefix}data_${etype}`,
|
|
286
|
-
)} ("guid") WHERE "name" = \'user\';`,
|
|
287
|
-
);
|
|
288
|
-
this.queryRun(
|
|
289
|
-
`CREATE INDEX IF NOT EXISTS ${SQLite3Driver.escape(
|
|
290
|
-
`${this.prefix}data_${etype}_id_guid__name_group`,
|
|
291
|
-
)} ON ${SQLite3Driver.escape(
|
|
292
|
-
`${this.prefix}data_${etype}`,
|
|
293
|
-
)} ("guid") WHERE "name" = \'group\';`,
|
|
294
|
-
);
|
|
295
|
-
this.queryRun(
|
|
296
|
-
`CREATE INDEX IF NOT EXISTS ${SQLite3Driver.escape(
|
|
297
|
-
`${this.prefix}data_${etype}_id_name`,
|
|
298
|
-
)} ON ${SQLite3Driver.escape(
|
|
299
|
-
`${this.prefix}data_${etype}`,
|
|
300
|
-
)} ("name");`,
|
|
301
|
-
);
|
|
302
|
-
this.queryRun(
|
|
303
|
-
`CREATE INDEX IF NOT EXISTS ${SQLite3Driver.escape(
|
|
304
|
-
`${this.prefix}data_${etype}_id_name__truthy`,
|
|
305
|
-
)} ON ${SQLite3Driver.escape(
|
|
306
|
-
`${this.prefix}data_${etype}`,
|
|
307
|
-
)} ("name") WHERE "truthy" = 1;`,
|
|
308
|
-
);
|
|
309
|
-
this.queryRun(
|
|
310
|
-
`CREATE INDEX IF NOT EXISTS ${SQLite3Driver.escape(
|
|
311
|
-
`${this.prefix}data_${etype}_id_name__falsy`,
|
|
312
|
-
)} ON ${SQLite3Driver.escape(
|
|
313
|
-
`${this.prefix}data_${etype}`,
|
|
314
|
-
)} ("name") WHERE "truthy" <> 1;`,
|
|
315
|
-
);
|
|
316
|
-
this.queryRun(
|
|
317
|
-
`CREATE INDEX IF NOT EXISTS ${SQLite3Driver.escape(
|
|
318
|
-
`${this.prefix}data_${etype}_id_name_string`,
|
|
319
|
-
)} ON ${SQLite3Driver.escape(
|
|
320
|
-
`${this.prefix}data_${etype}`,
|
|
321
|
-
)} ("name", "string");`,
|
|
322
|
-
);
|
|
323
|
-
this.queryRun(
|
|
324
|
-
`CREATE INDEX IF NOT EXISTS ${SQLite3Driver.escape(
|
|
325
|
-
`${this.prefix}data_${etype}_id_name_number`,
|
|
326
|
-
)} ON ${SQLite3Driver.escape(
|
|
327
|
-
`${this.prefix}data_${etype}`,
|
|
328
|
-
)} ("name", "number");`,
|
|
329
|
-
);
|
|
330
|
-
// Create the references table.
|
|
331
|
-
this.queryRun(
|
|
332
|
-
`CREATE TABLE IF NOT EXISTS ${SQLite3Driver.escape(
|
|
333
|
-
`${this.prefix}references_${etype}`,
|
|
334
|
-
)} ("guid" CHARACTER(24) NOT NULL REFERENCES ${SQLite3Driver.escape(
|
|
335
|
-
`${this.prefix}entities_${etype}`,
|
|
336
|
-
)} ("guid") ON DELETE CASCADE, "name" TEXT NOT NULL, "reference" CHARACTER(24) NOT NULL, PRIMARY KEY("guid", "name", "reference"));`,
|
|
337
|
-
);
|
|
338
|
-
this.queryRun(
|
|
339
|
-
`CREATE INDEX IF NOT EXISTS ${SQLite3Driver.escape(
|
|
340
|
-
`${this.prefix}references_${etype}_id_guid`,
|
|
341
|
-
)} ON ${SQLite3Driver.escape(
|
|
342
|
-
`${this.prefix}references_${etype}`,
|
|
343
|
-
)} ("guid");`,
|
|
344
|
-
);
|
|
345
|
-
this.queryRun(
|
|
346
|
-
`CREATE INDEX IF NOT EXISTS ${SQLite3Driver.escape(
|
|
347
|
-
`${this.prefix}references_${etype}_id_name`,
|
|
348
|
-
)} ON ${SQLite3Driver.escape(
|
|
349
|
-
`${this.prefix}references_${etype}`,
|
|
350
|
-
)} ("name");`,
|
|
351
|
-
);
|
|
352
|
-
this.queryRun(
|
|
353
|
-
`CREATE INDEX IF NOT EXISTS ${SQLite3Driver.escape(
|
|
354
|
-
`${this.prefix}references_${etype}_id_name_reference`,
|
|
355
|
-
)} ON ${SQLite3Driver.escape(
|
|
356
|
-
`${this.prefix}references_${etype}`,
|
|
357
|
-
)} ("name", "reference");`,
|
|
358
|
-
);
|
|
359
|
-
// Create the unique strings table.
|
|
360
|
-
this.queryRun(
|
|
361
|
-
`CREATE TABLE IF NOT EXISTS ${SQLite3Driver.escape(
|
|
362
|
-
`${this.prefix}uniques_${etype}`,
|
|
363
|
-
)} ("guid" CHARACTER(24) NOT NULL REFERENCES ${SQLite3Driver.escape(
|
|
364
|
-
`${this.prefix}entities_${etype}`,
|
|
365
|
-
)} ("guid") ON DELETE CASCADE, "unique" TEXT NOT NULL UNIQUE, PRIMARY KEY("guid", "unique"));`,
|
|
366
|
-
);
|
|
476
|
+
this.createEntitiesTable(etype);
|
|
477
|
+
this.createDataTable(etype);
|
|
478
|
+
this.createReferencesTable(etype);
|
|
479
|
+
this.createTokensTable(etype);
|
|
480
|
+
this.createUniquesTable(etype);
|
|
367
481
|
} else {
|
|
368
482
|
// Create the UID table.
|
|
369
483
|
this.queryRun(
|
|
@@ -541,6 +655,17 @@ export default class SQLite3Driver extends NymphDriver {
|
|
|
541
655
|
},
|
|
542
656
|
},
|
|
543
657
|
);
|
|
658
|
+
this.queryRun(
|
|
659
|
+
`DELETE FROM ${SQLite3Driver.escape(
|
|
660
|
+
`${this.prefix}tokens_${etype}`,
|
|
661
|
+
)} WHERE "guid"=@guid;`,
|
|
662
|
+
{
|
|
663
|
+
etypes: [etype],
|
|
664
|
+
params: {
|
|
665
|
+
guid,
|
|
666
|
+
},
|
|
667
|
+
},
|
|
668
|
+
);
|
|
544
669
|
this.queryRun(
|
|
545
670
|
`DELETE FROM ${SQLite3Driver.escape(
|
|
546
671
|
`${this.prefix}uniques_${etype}`,
|
|
@@ -585,6 +710,23 @@ export default class SQLite3Driver extends NymphDriver {
|
|
|
585
710
|
return true;
|
|
586
711
|
}
|
|
587
712
|
|
|
713
|
+
public async getEtypes() {
|
|
714
|
+
const tables: IterableIterator<any> = this.queryArray(
|
|
715
|
+
"SELECT `name` FROM `sqlite_master` WHERE `type`='table' AND `name` LIKE @prefix;",
|
|
716
|
+
{
|
|
717
|
+
params: {
|
|
718
|
+
prefix: this.prefix + 'entities_' + '%',
|
|
719
|
+
},
|
|
720
|
+
},
|
|
721
|
+
);
|
|
722
|
+
const etypes: string[] = [];
|
|
723
|
+
for (const table of tables) {
|
|
724
|
+
etypes.push(table.name.substr((this.prefix + 'entities_').length));
|
|
725
|
+
}
|
|
726
|
+
|
|
727
|
+
return etypes;
|
|
728
|
+
}
|
|
729
|
+
|
|
588
730
|
public async *exportDataIterator(): AsyncGenerator<
|
|
589
731
|
{ type: 'comment' | 'uid' | 'entity'; content: string },
|
|
590
732
|
void,
|
|
@@ -647,18 +789,7 @@ export default class SQLite3Driver extends NymphDriver {
|
|
|
647
789
|
}
|
|
648
790
|
|
|
649
791
|
// Get the etypes.
|
|
650
|
-
const
|
|
651
|
-
"SELECT `name` FROM `sqlite_master` WHERE `type`='table' AND `name` LIKE @prefix;",
|
|
652
|
-
{
|
|
653
|
-
params: {
|
|
654
|
-
prefix: this.prefix + 'entities_' + '%',
|
|
655
|
-
},
|
|
656
|
-
},
|
|
657
|
-
);
|
|
658
|
-
const etypes = [];
|
|
659
|
-
for (const table of tables) {
|
|
660
|
-
etypes.push(table.name.substr((this.prefix + 'entities_').length));
|
|
661
|
-
}
|
|
792
|
+
const etypes = await this.getEtypes();
|
|
662
793
|
|
|
663
794
|
for (const etype of etypes) {
|
|
664
795
|
// Export entities.
|
|
@@ -990,6 +1121,147 @@ export default class SQLite3Driver extends NymphDriver {
|
|
|
990
1121
|
params[value] = svalue;
|
|
991
1122
|
}
|
|
992
1123
|
break;
|
|
1124
|
+
case 'search':
|
|
1125
|
+
case '!search':
|
|
1126
|
+
if (curValue[0] === 'cdate' || curValue[0] === 'mdate') {
|
|
1127
|
+
if (curQuery) {
|
|
1128
|
+
curQuery += typeIsOr ? ' OR ' : ' AND ';
|
|
1129
|
+
}
|
|
1130
|
+
curQuery += (xor(typeIsNot, clauseNot) ? 'NOT ' : '') + '(0)';
|
|
1131
|
+
break;
|
|
1132
|
+
} else {
|
|
1133
|
+
if (curQuery) {
|
|
1134
|
+
curQuery += typeIsOr ? ' OR ' : ' AND ';
|
|
1135
|
+
}
|
|
1136
|
+
|
|
1137
|
+
const name = `param${++count.i}`;
|
|
1138
|
+
|
|
1139
|
+
const queryPartToken = (term: SearchTerm) => {
|
|
1140
|
+
const value = `param${++count.i}`;
|
|
1141
|
+
params[value] = term.token;
|
|
1142
|
+
return (
|
|
1143
|
+
'EXISTS (SELECT "guid" FROM ' +
|
|
1144
|
+
SQLite3Driver.escape(this.prefix + 'tokens_' + etype) +
|
|
1145
|
+
' WHERE "guid"=' +
|
|
1146
|
+
ieTable +
|
|
1147
|
+
'."guid" AND "name"=@' +
|
|
1148
|
+
name +
|
|
1149
|
+
' AND "token"=@' +
|
|
1150
|
+
value +
|
|
1151
|
+
(term.nostemmed ? ' AND "stem"=0' : '') +
|
|
1152
|
+
')'
|
|
1153
|
+
);
|
|
1154
|
+
};
|
|
1155
|
+
|
|
1156
|
+
const queryPartSeries = (series: SearchSeriesTerm) => {
|
|
1157
|
+
const tokenTableSuffix = makeTableSuffix();
|
|
1158
|
+
const tokenParts = series.tokens.map((token, i) => {
|
|
1159
|
+
const value = `param${++count.i}`;
|
|
1160
|
+
params[value] = token.token;
|
|
1161
|
+
return {
|
|
1162
|
+
fromClause:
|
|
1163
|
+
i === 0
|
|
1164
|
+
? 'FROM ' +
|
|
1165
|
+
SQLite3Driver.escape(
|
|
1166
|
+
this.prefix + 'tokens_' + etype,
|
|
1167
|
+
) +
|
|
1168
|
+
' t' +
|
|
1169
|
+
tokenTableSuffix +
|
|
1170
|
+
'0'
|
|
1171
|
+
: 'JOIN ' +
|
|
1172
|
+
SQLite3Driver.escape(
|
|
1173
|
+
this.prefix + 'tokens_' + etype,
|
|
1174
|
+
) +
|
|
1175
|
+
' t' +
|
|
1176
|
+
tokenTableSuffix +
|
|
1177
|
+
i +
|
|
1178
|
+
' ON t' +
|
|
1179
|
+
tokenTableSuffix +
|
|
1180
|
+
i +
|
|
1181
|
+
'."guid" = t' +
|
|
1182
|
+
tokenTableSuffix +
|
|
1183
|
+
'0."guid" AND t' +
|
|
1184
|
+
tokenTableSuffix +
|
|
1185
|
+
i +
|
|
1186
|
+
'."name" = t' +
|
|
1187
|
+
tokenTableSuffix +
|
|
1188
|
+
'0."name" AND t' +
|
|
1189
|
+
tokenTableSuffix +
|
|
1190
|
+
i +
|
|
1191
|
+
'."position" = t' +
|
|
1192
|
+
tokenTableSuffix +
|
|
1193
|
+
'0."position" + ' +
|
|
1194
|
+
i,
|
|
1195
|
+
whereClause:
|
|
1196
|
+
't' +
|
|
1197
|
+
tokenTableSuffix +
|
|
1198
|
+
i +
|
|
1199
|
+
'."token"=@' +
|
|
1200
|
+
value +
|
|
1201
|
+
(token.nostemmed
|
|
1202
|
+
? ' AND t' + tokenTableSuffix + i + '."stem"=0'
|
|
1203
|
+
: ''),
|
|
1204
|
+
};
|
|
1205
|
+
});
|
|
1206
|
+
return (
|
|
1207
|
+
'EXISTS (SELECT t' +
|
|
1208
|
+
tokenTableSuffix +
|
|
1209
|
+
'0."guid" ' +
|
|
1210
|
+
tokenParts.map((part) => part.fromClause).join(' ') +
|
|
1211
|
+
' WHERE t' +
|
|
1212
|
+
tokenTableSuffix +
|
|
1213
|
+
'0."guid"=' +
|
|
1214
|
+
ieTable +
|
|
1215
|
+
'."guid" AND t' +
|
|
1216
|
+
tokenTableSuffix +
|
|
1217
|
+
'0."name"=@' +
|
|
1218
|
+
name +
|
|
1219
|
+
' AND ' +
|
|
1220
|
+
tokenParts.map((part) => part.whereClause).join(' AND ') +
|
|
1221
|
+
')'
|
|
1222
|
+
);
|
|
1223
|
+
};
|
|
1224
|
+
|
|
1225
|
+
const queryPartTerm = (
|
|
1226
|
+
term:
|
|
1227
|
+
| SearchTerm
|
|
1228
|
+
| SearchOrTerm
|
|
1229
|
+
| SearchNotTerm
|
|
1230
|
+
| SearchSeriesTerm,
|
|
1231
|
+
): string => {
|
|
1232
|
+
if (term.type === 'series') {
|
|
1233
|
+
return queryPartSeries(term);
|
|
1234
|
+
} else if (term.type === 'not') {
|
|
1235
|
+
return 'NOT ' + queryPartTerm(term.operand);
|
|
1236
|
+
} else if (term.type === 'or') {
|
|
1237
|
+
let queryParts: string[] = [];
|
|
1238
|
+
for (let operand of term.operands) {
|
|
1239
|
+
queryParts.push(queryPartTerm(operand));
|
|
1240
|
+
}
|
|
1241
|
+
return '(' + queryParts.join(' OR ') + ')';
|
|
1242
|
+
}
|
|
1243
|
+
return queryPartToken(term);
|
|
1244
|
+
};
|
|
1245
|
+
|
|
1246
|
+
const parsedFTSQuery = this.tokenizer.parseSearchQuery(
|
|
1247
|
+
curValue[1],
|
|
1248
|
+
);
|
|
1249
|
+
|
|
1250
|
+
// Run through the query and add terms.
|
|
1251
|
+
let termStrings: string[] = [];
|
|
1252
|
+
for (let term of parsedFTSQuery) {
|
|
1253
|
+
termStrings.push(queryPartTerm(term));
|
|
1254
|
+
}
|
|
1255
|
+
|
|
1256
|
+
curQuery +=
|
|
1257
|
+
(xor(typeIsNot, clauseNot) ? 'NOT ' : '') +
|
|
1258
|
+
'(' +
|
|
1259
|
+
termStrings.join(' AND ') +
|
|
1260
|
+
')';
|
|
1261
|
+
|
|
1262
|
+
params[name] = curValue[0];
|
|
1263
|
+
}
|
|
1264
|
+
break;
|
|
993
1265
|
case 'match':
|
|
994
1266
|
case '!match':
|
|
995
1267
|
if (curValue[0] === 'cdate') {
|
|
@@ -1782,14 +2054,18 @@ export default class SQLite3Driver extends NymphDriver {
|
|
|
1782
2054
|
return (result?.cur_uid as number | null) ?? null;
|
|
1783
2055
|
}
|
|
1784
2056
|
|
|
1785
|
-
public async importEntity({
|
|
1786
|
-
guid
|
|
1787
|
-
cdate
|
|
1788
|
-
mdate
|
|
1789
|
-
tags
|
|
1790
|
-
sdata
|
|
1791
|
-
etype
|
|
1792
|
-
}
|
|
2057
|
+
public async importEntity(entity: {
|
|
2058
|
+
guid: string;
|
|
2059
|
+
cdate: number;
|
|
2060
|
+
mdate: number;
|
|
2061
|
+
tags: string[];
|
|
2062
|
+
sdata: SerializedEntityData;
|
|
2063
|
+
etype: string;
|
|
2064
|
+
}) {
|
|
2065
|
+
return await this.importEntityInternal(entity, false);
|
|
2066
|
+
}
|
|
2067
|
+
|
|
2068
|
+
public async importEntityTokens(entity: {
|
|
1793
2069
|
guid: string;
|
|
1794
2070
|
cdate: number;
|
|
1795
2071
|
mdate: number;
|
|
@@ -1797,43 +2073,66 @@ export default class SQLite3Driver extends NymphDriver {
|
|
|
1797
2073
|
sdata: SerializedEntityData;
|
|
1798
2074
|
etype: string;
|
|
1799
2075
|
}) {
|
|
2076
|
+
return await this.importEntityInternal(entity, true);
|
|
2077
|
+
}
|
|
2078
|
+
|
|
2079
|
+
private async importEntityInternal(
|
|
2080
|
+
{
|
|
2081
|
+
guid,
|
|
2082
|
+
cdate,
|
|
2083
|
+
mdate,
|
|
2084
|
+
tags,
|
|
2085
|
+
sdata,
|
|
2086
|
+
etype,
|
|
2087
|
+
}: {
|
|
2088
|
+
guid: string;
|
|
2089
|
+
cdate: number;
|
|
2090
|
+
mdate: number;
|
|
2091
|
+
tags: string[];
|
|
2092
|
+
sdata: SerializedEntityData;
|
|
2093
|
+
etype: string;
|
|
2094
|
+
},
|
|
2095
|
+
onlyTokens: boolean,
|
|
2096
|
+
) {
|
|
1800
2097
|
try {
|
|
1801
|
-
|
|
1802
|
-
|
|
1803
|
-
|
|
1804
|
-
|
|
1805
|
-
|
|
1806
|
-
|
|
1807
|
-
|
|
1808
|
-
|
|
2098
|
+
if (!onlyTokens) {
|
|
2099
|
+
this.queryRun(
|
|
2100
|
+
`DELETE FROM ${SQLite3Driver.escape(
|
|
2101
|
+
`${this.prefix}entities_${etype}`,
|
|
2102
|
+
)} WHERE "guid"=@guid;`,
|
|
2103
|
+
{
|
|
2104
|
+
etypes: [etype],
|
|
2105
|
+
params: {
|
|
2106
|
+
guid,
|
|
2107
|
+
},
|
|
1809
2108
|
},
|
|
1810
|
-
|
|
1811
|
-
|
|
1812
|
-
|
|
1813
|
-
|
|
1814
|
-
|
|
1815
|
-
|
|
1816
|
-
|
|
1817
|
-
|
|
1818
|
-
|
|
1819
|
-
|
|
2109
|
+
);
|
|
2110
|
+
this.queryRun(
|
|
2111
|
+
`DELETE FROM ${SQLite3Driver.escape(
|
|
2112
|
+
`${this.prefix}data_${etype}`,
|
|
2113
|
+
)} WHERE "guid"=@guid;`,
|
|
2114
|
+
{
|
|
2115
|
+
etypes: [etype],
|
|
2116
|
+
params: {
|
|
2117
|
+
guid,
|
|
2118
|
+
},
|
|
1820
2119
|
},
|
|
1821
|
-
|
|
1822
|
-
|
|
1823
|
-
|
|
1824
|
-
|
|
1825
|
-
|
|
1826
|
-
|
|
1827
|
-
|
|
1828
|
-
|
|
1829
|
-
|
|
1830
|
-
|
|
2120
|
+
);
|
|
2121
|
+
this.queryRun(
|
|
2122
|
+
`DELETE FROM ${SQLite3Driver.escape(
|
|
2123
|
+
`${this.prefix}references_${etype}`,
|
|
2124
|
+
)} WHERE "guid"=@guid;`,
|
|
2125
|
+
{
|
|
2126
|
+
etypes: [etype],
|
|
2127
|
+
params: {
|
|
2128
|
+
guid,
|
|
2129
|
+
},
|
|
1831
2130
|
},
|
|
1832
|
-
|
|
1833
|
-
|
|
2131
|
+
);
|
|
2132
|
+
}
|
|
1834
2133
|
this.queryRun(
|
|
1835
2134
|
`DELETE FROM ${SQLite3Driver.escape(
|
|
1836
|
-
`${this.prefix}
|
|
2135
|
+
`${this.prefix}tokens_${etype}`,
|
|
1837
2136
|
)} WHERE "guid"=@guid;`,
|
|
1838
2137
|
{
|
|
1839
2138
|
etypes: [etype],
|
|
@@ -1842,93 +2141,168 @@ export default class SQLite3Driver extends NymphDriver {
|
|
|
1842
2141
|
},
|
|
1843
2142
|
},
|
|
1844
2143
|
);
|
|
1845
|
-
|
|
1846
|
-
|
|
1847
|
-
|
|
1848
|
-
|
|
1849
|
-
|
|
1850
|
-
|
|
1851
|
-
|
|
1852
|
-
|
|
1853
|
-
|
|
1854
|
-
|
|
1855
|
-
cdate,
|
|
1856
|
-
mdate,
|
|
2144
|
+
if (!onlyTokens) {
|
|
2145
|
+
this.queryRun(
|
|
2146
|
+
`DELETE FROM ${SQLite3Driver.escape(
|
|
2147
|
+
`${this.prefix}uniques_${etype}`,
|
|
2148
|
+
)} WHERE "guid"=@guid;`,
|
|
2149
|
+
{
|
|
2150
|
+
etypes: [etype],
|
|
2151
|
+
params: {
|
|
2152
|
+
guid,
|
|
2153
|
+
},
|
|
1857
2154
|
},
|
|
1858
|
-
|
|
1859
|
-
|
|
1860
|
-
|
|
1861
|
-
|
|
1862
|
-
const uvalue = JSON.parse(value);
|
|
1863
|
-
if (value === undefined) {
|
|
1864
|
-
continue;
|
|
1865
|
-
}
|
|
1866
|
-
const storageValue =
|
|
1867
|
-
typeof uvalue === 'number'
|
|
1868
|
-
? 'N'
|
|
1869
|
-
: typeof uvalue === 'string'
|
|
1870
|
-
? 'S'
|
|
1871
|
-
: 'J';
|
|
1872
|
-
const jsonValue = storageValue === 'J' ? value : null;
|
|
2155
|
+
);
|
|
2156
|
+
}
|
|
2157
|
+
|
|
2158
|
+
if (!onlyTokens) {
|
|
1873
2159
|
this.queryRun(
|
|
1874
2160
|
`INSERT INTO ${SQLite3Driver.escape(
|
|
1875
|
-
`${this.prefix}
|
|
1876
|
-
)} ("guid", "
|
|
2161
|
+
`${this.prefix}entities_${etype}`,
|
|
2162
|
+
)} ("guid", "tags", "cdate", "mdate") VALUES (@guid, @tags, @cdate, @mdate);`,
|
|
1877
2163
|
{
|
|
1878
2164
|
etypes: [etype],
|
|
1879
2165
|
params: {
|
|
1880
2166
|
guid,
|
|
1881
|
-
|
|
1882
|
-
|
|
1883
|
-
|
|
1884
|
-
string: storageValue === 'J' ? null : `${uvalue}`,
|
|
1885
|
-
number: Number(uvalue),
|
|
1886
|
-
truthy: uvalue ? 1 : 0,
|
|
2167
|
+
tags: ',' + tags.join(',') + ',',
|
|
2168
|
+
cdate,
|
|
2169
|
+
mdate,
|
|
1887
2170
|
},
|
|
1888
2171
|
},
|
|
1889
2172
|
);
|
|
1890
|
-
|
|
1891
|
-
for (const
|
|
2173
|
+
|
|
2174
|
+
for (const name in sdata) {
|
|
2175
|
+
const value = sdata[name];
|
|
2176
|
+
const uvalue = JSON.parse(value);
|
|
2177
|
+
if (value === undefined) {
|
|
2178
|
+
continue;
|
|
2179
|
+
}
|
|
2180
|
+
const storageValue =
|
|
2181
|
+
typeof uvalue === 'number'
|
|
2182
|
+
? 'N'
|
|
2183
|
+
: typeof uvalue === 'string'
|
|
2184
|
+
? 'S'
|
|
2185
|
+
: 'J';
|
|
2186
|
+
const jsonValue = storageValue === 'J' ? value : null;
|
|
2187
|
+
|
|
1892
2188
|
this.queryRun(
|
|
1893
2189
|
`INSERT INTO ${SQLite3Driver.escape(
|
|
1894
|
-
`${this.prefix}
|
|
1895
|
-
)} ("guid", "name", "
|
|
2190
|
+
`${this.prefix}data_${etype}`,
|
|
2191
|
+
)} ("guid", "name", "value", "json", "string", "number", "truthy") VALUES (@guid, @name, @storageValue, jsonb(@jsonValue), @string, @number, @truthy);`,
|
|
1896
2192
|
{
|
|
1897
2193
|
etypes: [etype],
|
|
1898
2194
|
params: {
|
|
1899
2195
|
guid,
|
|
1900
2196
|
name,
|
|
1901
|
-
|
|
2197
|
+
storageValue,
|
|
2198
|
+
jsonValue,
|
|
2199
|
+
string: storageValue === 'J' ? null : `${uvalue}`,
|
|
2200
|
+
number: Number(uvalue),
|
|
2201
|
+
truthy: uvalue ? 1 : 0,
|
|
1902
2202
|
},
|
|
1903
2203
|
},
|
|
1904
2204
|
);
|
|
2205
|
+
|
|
2206
|
+
const references = this.findReferences(value);
|
|
2207
|
+
for (const reference of references) {
|
|
2208
|
+
this.queryRun(
|
|
2209
|
+
`INSERT INTO ${SQLite3Driver.escape(
|
|
2210
|
+
`${this.prefix}references_${etype}`,
|
|
2211
|
+
)} ("guid", "name", "reference") VALUES (@guid, @name, @reference);`,
|
|
2212
|
+
{
|
|
2213
|
+
etypes: [etype],
|
|
2214
|
+
params: {
|
|
2215
|
+
guid,
|
|
2216
|
+
name,
|
|
2217
|
+
reference,
|
|
2218
|
+
},
|
|
2219
|
+
},
|
|
2220
|
+
);
|
|
2221
|
+
}
|
|
1905
2222
|
}
|
|
1906
2223
|
}
|
|
1907
|
-
|
|
1908
|
-
|
|
1909
|
-
|
|
1910
|
-
for (
|
|
2224
|
+
|
|
2225
|
+
const EntityClass = this.nymph.getEntityClassByEtype(etype);
|
|
2226
|
+
|
|
2227
|
+
for (let name in sdata) {
|
|
2228
|
+
let tokenString: string | null = null;
|
|
1911
2229
|
try {
|
|
1912
|
-
|
|
1913
|
-
`INSERT INTO ${SQLite3Driver.escape(
|
|
1914
|
-
`${this.prefix}uniques_${etype}`,
|
|
1915
|
-
)} ("guid", "unique") VALUES (@guid, @unique);`,
|
|
1916
|
-
{
|
|
1917
|
-
etypes: [etype],
|
|
1918
|
-
params: {
|
|
1919
|
-
guid,
|
|
1920
|
-
unique,
|
|
1921
|
-
},
|
|
1922
|
-
},
|
|
1923
|
-
);
|
|
2230
|
+
tokenString = EntityClass.getFTSText(name, JSON.parse(sdata[name]));
|
|
1924
2231
|
} catch (e: any) {
|
|
1925
|
-
|
|
1926
|
-
|
|
1927
|
-
|
|
1928
|
-
|
|
2232
|
+
// Ignore error.
|
|
2233
|
+
}
|
|
2234
|
+
|
|
2235
|
+
if (tokenString != null) {
|
|
2236
|
+
const tokens = this.tokenizer.tokenize(tokenString);
|
|
2237
|
+
while (tokens.length) {
|
|
2238
|
+
const currentTokens = tokens.splice(0, 100);
|
|
2239
|
+
const params: { [k: string]: any } = {
|
|
2240
|
+
guid,
|
|
2241
|
+
name,
|
|
2242
|
+
};
|
|
2243
|
+
const values: string[] = [];
|
|
2244
|
+
|
|
2245
|
+
for (let i = 0; i < currentTokens.length; i++) {
|
|
2246
|
+
const token = currentTokens[i];
|
|
2247
|
+
params['token' + i] = token.token;
|
|
2248
|
+
params['position' + i] = token.position;
|
|
2249
|
+
params['stem' + i] = token.stem ? 1 : 0;
|
|
2250
|
+
values.push(
|
|
2251
|
+
'(@guid, @name, @token' +
|
|
2252
|
+
i +
|
|
2253
|
+
', @position' +
|
|
2254
|
+
i +
|
|
2255
|
+
', @stem' +
|
|
2256
|
+
i +
|
|
2257
|
+
')',
|
|
2258
|
+
);
|
|
2259
|
+
}
|
|
2260
|
+
|
|
2261
|
+
this.queryRun(
|
|
2262
|
+
`INSERT INTO ${SQLite3Driver.escape(
|
|
2263
|
+
`${this.prefix}tokens_${etype}`,
|
|
2264
|
+
)} ("guid", "name", "token", "position", "stem") VALUES ${values.join(', ')};`,
|
|
2265
|
+
{
|
|
2266
|
+
etypes: [etype],
|
|
2267
|
+
params,
|
|
2268
|
+
},
|
|
1929
2269
|
);
|
|
1930
2270
|
}
|
|
1931
|
-
|
|
2271
|
+
}
|
|
2272
|
+
}
|
|
2273
|
+
|
|
2274
|
+
if (!onlyTokens) {
|
|
2275
|
+
const uniques = await EntityClass.getUniques({
|
|
2276
|
+
guid,
|
|
2277
|
+
cdate,
|
|
2278
|
+
mdate,
|
|
2279
|
+
tags,
|
|
2280
|
+
data: {},
|
|
2281
|
+
sdata,
|
|
2282
|
+
});
|
|
2283
|
+
for (const unique of uniques) {
|
|
2284
|
+
try {
|
|
2285
|
+
this.queryRun(
|
|
2286
|
+
`INSERT INTO ${SQLite3Driver.escape(
|
|
2287
|
+
`${this.prefix}uniques_${etype}`,
|
|
2288
|
+
)} ("guid", "unique") VALUES (@guid, @unique);`,
|
|
2289
|
+
{
|
|
2290
|
+
etypes: [etype],
|
|
2291
|
+
params: {
|
|
2292
|
+
guid,
|
|
2293
|
+
unique,
|
|
2294
|
+
},
|
|
2295
|
+
},
|
|
2296
|
+
);
|
|
2297
|
+
} catch (e: any) {
|
|
2298
|
+
if (e instanceof EntityUniqueConstraintError) {
|
|
2299
|
+
this.nymph.config.debugError(
|
|
2300
|
+
'sqlite3',
|
|
2301
|
+
`Import entity unique constraint violation for GUID "${guid}" on etype "${etype}": "${unique}"`,
|
|
2302
|
+
);
|
|
2303
|
+
}
|
|
2304
|
+
throw e;
|
|
2305
|
+
}
|
|
1932
2306
|
}
|
|
1933
2307
|
}
|
|
1934
2308
|
} catch (e: any) {
|
|
@@ -2079,6 +2453,8 @@ export default class SQLite3Driver extends NymphDriver {
|
|
|
2079
2453
|
uniques: string[],
|
|
2080
2454
|
etype: string,
|
|
2081
2455
|
) => {
|
|
2456
|
+
const EntityClass = this.nymph.getEntityClassByEtype(etype);
|
|
2457
|
+
|
|
2082
2458
|
const runInsertQuery = (name: string, value: any, svalue: string) => {
|
|
2083
2459
|
if (value === undefined) {
|
|
2084
2460
|
return;
|
|
@@ -2090,6 +2466,7 @@ export default class SQLite3Driver extends NymphDriver {
|
|
|
2090
2466
|
? 'S'
|
|
2091
2467
|
: 'J';
|
|
2092
2468
|
const jsonValue = storageValue === 'J' ? svalue : null;
|
|
2469
|
+
|
|
2093
2470
|
this.queryRun(
|
|
2094
2471
|
`INSERT INTO ${SQLite3Driver.escape(
|
|
2095
2472
|
`${this.prefix}data_${etype}`,
|
|
@@ -2107,6 +2484,7 @@ export default class SQLite3Driver extends NymphDriver {
|
|
|
2107
2484
|
},
|
|
2108
2485
|
},
|
|
2109
2486
|
);
|
|
2487
|
+
|
|
2110
2488
|
const references = this.findReferences(svalue);
|
|
2111
2489
|
for (const reference of references) {
|
|
2112
2490
|
this.queryRun(
|
|
@@ -2123,7 +2501,53 @@ export default class SQLite3Driver extends NymphDriver {
|
|
|
2123
2501
|
},
|
|
2124
2502
|
);
|
|
2125
2503
|
}
|
|
2504
|
+
|
|
2505
|
+
let tokenString: string | null = null;
|
|
2506
|
+
try {
|
|
2507
|
+
tokenString = EntityClass.getFTSText(name, value);
|
|
2508
|
+
} catch (e: any) {
|
|
2509
|
+
// Ignore error.
|
|
2510
|
+
}
|
|
2511
|
+
|
|
2512
|
+
if (tokenString != null) {
|
|
2513
|
+
const tokens = this.tokenizer.tokenize(tokenString);
|
|
2514
|
+
while (tokens.length) {
|
|
2515
|
+
const currentTokens = tokens.splice(0, 100);
|
|
2516
|
+
const params: { [k: string]: any } = {
|
|
2517
|
+
guid,
|
|
2518
|
+
name,
|
|
2519
|
+
};
|
|
2520
|
+
const values: string[] = [];
|
|
2521
|
+
|
|
2522
|
+
for (let i = 0; i < currentTokens.length; i++) {
|
|
2523
|
+
const token = currentTokens[i];
|
|
2524
|
+
params['token' + i] = token.token;
|
|
2525
|
+
params['position' + i] = token.position;
|
|
2526
|
+
params['stem' + i] = token.stem ? 1 : 0;
|
|
2527
|
+
values.push(
|
|
2528
|
+
'(@guid, @name, @token' +
|
|
2529
|
+
i +
|
|
2530
|
+
', @position' +
|
|
2531
|
+
i +
|
|
2532
|
+
', @stem' +
|
|
2533
|
+
i +
|
|
2534
|
+
')',
|
|
2535
|
+
);
|
|
2536
|
+
}
|
|
2537
|
+
|
|
2538
|
+
this.queryRun(
|
|
2539
|
+
`INSERT INTO ${SQLite3Driver.escape(
|
|
2540
|
+
`${this.prefix}tokens_${etype}`,
|
|
2541
|
+
)} ("guid", "name", "token", "position", "stem") VALUES ${values.join(', ')};`,
|
|
2542
|
+
{
|
|
2543
|
+
etypes: [etype],
|
|
2544
|
+
params,
|
|
2545
|
+
},
|
|
2546
|
+
);
|
|
2547
|
+
}
|
|
2548
|
+
}
|
|
2126
2549
|
};
|
|
2550
|
+
|
|
2127
2551
|
for (const unique of uniques) {
|
|
2128
2552
|
try {
|
|
2129
2553
|
this.queryRun(
|
|
@@ -2227,6 +2651,17 @@ export default class SQLite3Driver extends NymphDriver {
|
|
|
2227
2651
|
},
|
|
2228
2652
|
},
|
|
2229
2653
|
);
|
|
2654
|
+
this.queryRun(
|
|
2655
|
+
`DELETE FROM ${SQLite3Driver.escape(
|
|
2656
|
+
`${this.prefix}tokens_${etype}`,
|
|
2657
|
+
)} WHERE "guid"=@guid;`,
|
|
2658
|
+
{
|
|
2659
|
+
etypes: [etype],
|
|
2660
|
+
params: {
|
|
2661
|
+
guid,
|
|
2662
|
+
},
|
|
2663
|
+
},
|
|
2664
|
+
);
|
|
2230
2665
|
this.queryRun(
|
|
2231
2666
|
`DELETE FROM ${SQLite3Driver.escape(
|
|
2232
2667
|
`${this.prefix}uniques_${etype}`,
|
|
@@ -2316,7 +2751,7 @@ export default class SQLite3Driver extends NymphDriver {
|
|
|
2316
2751
|
return this.nymph;
|
|
2317
2752
|
}
|
|
2318
2753
|
|
|
2319
|
-
public async needsMigration(): Promise<
|
|
2754
|
+
public async needsMigration(): Promise<'json' | 'tokens' | false> {
|
|
2320
2755
|
const table: any = this.queryGet(
|
|
2321
2756
|
"SELECT `name` FROM `sqlite_master` WHERE `type`='table' AND `name` LIKE @prefix LIMIT 1;",
|
|
2322
2757
|
{
|
|
@@ -2334,8 +2769,29 @@ export default class SQLite3Driver extends NymphDriver {
|
|
|
2334
2769
|
},
|
|
2335
2770
|
},
|
|
2336
2771
|
);
|
|
2337
|
-
|
|
2772
|
+
if (!result?.exists) {
|
|
2773
|
+
return 'json';
|
|
2774
|
+
}
|
|
2775
|
+
}
|
|
2776
|
+
const table2: any = this.queryGet(
|
|
2777
|
+
"SELECT `name` FROM `sqlite_master` WHERE `type`='table' AND `name` LIKE @tokenTable LIMIT 1;",
|
|
2778
|
+
{
|
|
2779
|
+
params: {
|
|
2780
|
+
tokenTable: this.prefix + 'tokens_' + '%',
|
|
2781
|
+
},
|
|
2782
|
+
},
|
|
2783
|
+
);
|
|
2784
|
+
if (!table2 || !table2.name) {
|
|
2785
|
+
return 'tokens';
|
|
2338
2786
|
}
|
|
2339
2787
|
return false;
|
|
2340
2788
|
}
|
|
2789
|
+
|
|
2790
|
+
public async liveMigration(_migrationType: 'tokenTables') {
|
|
2791
|
+
const etypes = await this.getEtypes();
|
|
2792
|
+
|
|
2793
|
+
for (let etype of etypes) {
|
|
2794
|
+
this.createTokensTable(etype);
|
|
2795
|
+
}
|
|
2796
|
+
}
|
|
2341
2797
|
}
|