@nymphjs/driver-sqlite3 1.0.0-beta.98 → 1.0.0-beta.99
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +14 -0
- package/dist/SQLite3Driver.d.ts +18 -2
- package/dist/SQLite3Driver.js +377 -110
- package/dist/SQLite3Driver.js.map +1 -1
- package/package.json +5 -4
- package/src/SQLite3Driver.ts +705 -327
package/dist/SQLite3Driver.js
CHANGED
|
@@ -174,6 +174,53 @@ export default class SQLite3Driver extends NymphDriver {
|
|
|
174
174
|
isConnected() {
|
|
175
175
|
return this.store.connected;
|
|
176
176
|
}
|
|
177
|
+
createEntitiesTable(etype) {
|
|
178
|
+
// Create the entity table.
|
|
179
|
+
this.queryRun(`CREATE TABLE IF NOT EXISTS ${SQLite3Driver.escape(`${this.prefix}entities_${etype}`)} ("guid" CHARACTER(24) PRIMARY KEY, "tags" TEXT, "cdate" REAL NOT NULL, "mdate" REAL NOT NULL);`);
|
|
180
|
+
this.queryRun(`CREATE INDEX IF NOT EXISTS ${SQLite3Driver.escape(`${this.prefix}entities_${etype}_id_cdate`)} ON ${SQLite3Driver.escape(`${this.prefix}entities_${etype}`)} ("cdate");`);
|
|
181
|
+
this.queryRun(`CREATE INDEX IF NOT EXISTS ${SQLite3Driver.escape(`${this.prefix}entities_${etype}_id_mdate`)} ON ${SQLite3Driver.escape(`${this.prefix}entities_${etype}`)} ("mdate");`);
|
|
182
|
+
this.queryRun(`CREATE INDEX IF NOT EXISTS ${SQLite3Driver.escape(`${this.prefix}entities_${etype}_id_tags`)} ON ${SQLite3Driver.escape(`${this.prefix}entities_${etype}`)} ("tags");`);
|
|
183
|
+
}
|
|
184
|
+
createDataTable(etype) {
|
|
185
|
+
// Create the data table.
|
|
186
|
+
this.queryRun(`CREATE TABLE IF NOT EXISTS ${SQLite3Driver.escape(`${this.prefix}data_${etype}`)} ("guid" CHARACTER(24) NOT NULL REFERENCES ${SQLite3Driver.escape(`${this.prefix}entities_${etype}`)} ("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"));`);
|
|
187
|
+
this.queryRun(`CREATE INDEX IF NOT EXISTS ${SQLite3Driver.escape(`${this.prefix}data_${etype}_id_guid`)} ON ${SQLite3Driver.escape(`${this.prefix}data_${etype}`)} ("guid");`);
|
|
188
|
+
this.queryRun(`CREATE INDEX IF NOT EXISTS ${SQLite3Driver.escape(`${this.prefix}data_${etype}_id_guid_name`)} ON ${SQLite3Driver.escape(`${this.prefix}data_${etype}`)} ("guid", "name");`);
|
|
189
|
+
this.queryRun(`CREATE INDEX IF NOT EXISTS ${SQLite3Driver.escape(`${this.prefix}data_${etype}_id_name`)} ON ${SQLite3Driver.escape(`${this.prefix}data_${etype}`)} ("name");`);
|
|
190
|
+
this.queryRun(`CREATE INDEX IF NOT EXISTS ${SQLite3Driver.escape(`${this.prefix}data_${etype}_id_name_string`)} ON ${SQLite3Driver.escape(`${this.prefix}data_${etype}`)} ("name", "string");`);
|
|
191
|
+
this.queryRun(`CREATE INDEX IF NOT EXISTS ${SQLite3Driver.escape(`${this.prefix}data_${etype}_id_name_number`)} ON ${SQLite3Driver.escape(`${this.prefix}data_${etype}`)} ("name", "number");`);
|
|
192
|
+
this.queryRun(`CREATE INDEX IF NOT EXISTS ${SQLite3Driver.escape(`${this.prefix}data_${etype}_id_guid_name_number`)} ON ${SQLite3Driver.escape(`${this.prefix}data_${etype}`)} ("guid", "name", "number");`);
|
|
193
|
+
this.queryRun(`CREATE INDEX IF NOT EXISTS ${SQLite3Driver.escape(`${this.prefix}data_${etype}_id_name_truthy`)} ON ${SQLite3Driver.escape(`${this.prefix}data_${etype}`)} ("name", "truthy");`);
|
|
194
|
+
this.queryRun(`CREATE INDEX IF NOT EXISTS ${SQLite3Driver.escape(`${this.prefix}data_${etype}_id_guid_name_truthy`)} ON ${SQLite3Driver.escape(`${this.prefix}data_${etype}`)} ("guid", "name", "truthy");`);
|
|
195
|
+
this.queryRun(`CREATE INDEX IF NOT EXISTS ${SQLite3Driver.escape(`${this.prefix}data_${etype}_id_acuserread`)} ON ${SQLite3Driver.escape(`${this.prefix}data_${etype}`)} ("guid") WHERE "name"=\'acUser\' AND "number" >= 1;`);
|
|
196
|
+
this.queryRun(`CREATE INDEX IF NOT EXISTS ${SQLite3Driver.escape(`${this.prefix}data_${etype}_id_acgroupread`)} ON ${SQLite3Driver.escape(`${this.prefix}data_${etype}`)} ("guid") WHERE "name"=\'acGroup\' AND "number" >= 1;`);
|
|
197
|
+
this.queryRun(`CREATE INDEX IF NOT EXISTS ${SQLite3Driver.escape(`${this.prefix}data_${etype}_id_acotherread`)} ON ${SQLite3Driver.escape(`${this.prefix}data_${etype}`)} ("guid") WHERE "name"=\'acOther\' AND "number" >= 1;`);
|
|
198
|
+
this.queryRun(`CREATE INDEX IF NOT EXISTS ${SQLite3Driver.escape(`${this.prefix}data_${etype}_id_acuser`)} ON ${SQLite3Driver.escape(`${this.prefix}data_${etype}`)} ("guid") WHERE "name"=\'user\';`);
|
|
199
|
+
this.queryRun(`CREATE INDEX IF NOT EXISTS ${SQLite3Driver.escape(`${this.prefix}data_${etype}_id_acgroup`)} ON ${SQLite3Driver.escape(`${this.prefix}data_${etype}`)} ("guid") WHERE "name"=\'group\';`);
|
|
200
|
+
}
|
|
201
|
+
createReferencesTable(etype) {
|
|
202
|
+
// Create the references table.
|
|
203
|
+
this.queryRun(`CREATE TABLE IF NOT EXISTS ${SQLite3Driver.escape(`${this.prefix}references_${etype}`)} ("guid" CHARACTER(24) NOT NULL REFERENCES ${SQLite3Driver.escape(`${this.prefix}entities_${etype}`)} ("guid") ON DELETE CASCADE, "name" TEXT NOT NULL, "reference" CHARACTER(24) NOT NULL, PRIMARY KEY("guid", "name", "reference"));`);
|
|
204
|
+
this.queryRun(`CREATE INDEX IF NOT EXISTS ${SQLite3Driver.escape(`${this.prefix}references_${etype}_id_guid`)} ON ${SQLite3Driver.escape(`${this.prefix}references_${etype}`)} ("guid");`);
|
|
205
|
+
this.queryRun(`CREATE INDEX IF NOT EXISTS ${SQLite3Driver.escape(`${this.prefix}references_${etype}_id_name`)} ON ${SQLite3Driver.escape(`${this.prefix}references_${etype}`)} ("name");`);
|
|
206
|
+
this.queryRun(`CREATE INDEX IF NOT EXISTS ${SQLite3Driver.escape(`${this.prefix}references_${etype}_id_name_reference`)} ON ${SQLite3Driver.escape(`${this.prefix}references_${etype}`)} ("name", "reference");`);
|
|
207
|
+
this.queryRun(`CREATE INDEX IF NOT EXISTS ${SQLite3Driver.escape(`${this.prefix}references_${etype}_id_reference`)} ON ${SQLite3Driver.escape(`${this.prefix}references_${etype}`)} ("reference");`);
|
|
208
|
+
this.queryRun(`CREATE INDEX IF NOT EXISTS ${SQLite3Driver.escape(`${this.prefix}references_${etype}_id_guid_name`)} ON ${SQLite3Driver.escape(`${this.prefix}references_${etype}`)} ("guid", "name");`);
|
|
209
|
+
this.queryRun(`CREATE INDEX IF NOT EXISTS ${SQLite3Driver.escape(`${this.prefix}references_${etype}_id_guid_name_reference`)} ON ${SQLite3Driver.escape(`${this.prefix}references_${etype}`)} ("guid", "name", "reference");`);
|
|
210
|
+
this.queryRun(`CREATE INDEX IF NOT EXISTS ${SQLite3Driver.escape(`${this.prefix}references_${etype}_id_reference_name_guid`)} ON ${SQLite3Driver.escape(`${this.prefix}references_${etype}`)} ("reference", "name", "guid");`);
|
|
211
|
+
this.queryRun(`CREATE INDEX IF NOT EXISTS ${SQLite3Driver.escape(`${this.prefix}references_${etype}_id_reference_guid_name`)} ON ${SQLite3Driver.escape(`${this.prefix}references_${etype}`)} ("reference", "guid", "name");`);
|
|
212
|
+
this.queryRun(`CREATE INDEX IF NOT EXISTS ${SQLite3Driver.escape(`${this.prefix}references_${etype}_id_guid_reference_nameuser`)} ON ${SQLite3Driver.escape(`${this.prefix}references_${etype}`)} ("guid", "reference") WHERE "name"=\'user\';`);
|
|
213
|
+
this.queryRun(`CREATE INDEX IF NOT EXISTS ${SQLite3Driver.escape(`${this.prefix}references_${etype}_id_guid_reference_namegroup`)} ON ${SQLite3Driver.escape(`${this.prefix}references_${etype}`)} ("guid", "reference") WHERE "name"=\'group\';`);
|
|
214
|
+
}
|
|
215
|
+
createTokensTable(etype) {
|
|
216
|
+
// Create the tokens table.
|
|
217
|
+
this.queryRun(`CREATE TABLE IF NOT EXISTS ${SQLite3Driver.escape(`${this.prefix}tokens_${etype}`)} ("guid" CHARACTER(24) NOT NULL REFERENCES ${SQLite3Driver.escape(`${this.prefix}entities_${etype}`)} ("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"));`);
|
|
218
|
+
this.queryRun(`CREATE INDEX IF NOT EXISTS ${SQLite3Driver.escape(`${this.prefix}tokens_${etype}_id_name_token`)} ON ${SQLite3Driver.escape(`${this.prefix}tokens_${etype}`)} ("name", "token");`);
|
|
219
|
+
}
|
|
220
|
+
createUniquesTable(etype) {
|
|
221
|
+
// Create the unique strings table.
|
|
222
|
+
this.queryRun(`CREATE TABLE IF NOT EXISTS ${SQLite3Driver.escape(`${this.prefix}uniques_${etype}`)} ("guid" CHARACTER(24) NOT NULL REFERENCES ${SQLite3Driver.escape(`${this.prefix}entities_${etype}`)} ("guid") ON DELETE CASCADE, "unique" TEXT NOT NULL UNIQUE, PRIMARY KEY("guid", "unique"));`);
|
|
223
|
+
}
|
|
177
224
|
/**
|
|
178
225
|
* Create entity tables in the database.
|
|
179
226
|
*
|
|
@@ -183,40 +230,11 @@ export default class SQLite3Driver extends NymphDriver {
|
|
|
183
230
|
this.startTransaction('nymph-tablecreation');
|
|
184
231
|
try {
|
|
185
232
|
if (etype != null) {
|
|
186
|
-
|
|
187
|
-
this.
|
|
188
|
-
this.
|
|
189
|
-
this.
|
|
190
|
-
this.
|
|
191
|
-
// Create the data table.
|
|
192
|
-
this.queryRun(`CREATE TABLE IF NOT EXISTS ${SQLite3Driver.escape(`${this.prefix}data_${etype}`)} ("guid" CHARACTER(24) NOT NULL REFERENCES ${SQLite3Driver.escape(`${this.prefix}entities_${etype}`)} ("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"));`);
|
|
193
|
-
this.queryRun(`CREATE INDEX IF NOT EXISTS ${SQLite3Driver.escape(`${this.prefix}data_${etype}_id_guid`)} ON ${SQLite3Driver.escape(`${this.prefix}data_${etype}`)} ("guid");`);
|
|
194
|
-
this.queryRun(`CREATE INDEX IF NOT EXISTS ${SQLite3Driver.escape(`${this.prefix}data_${etype}_id_guid_name`)} ON ${SQLite3Driver.escape(`${this.prefix}data_${etype}`)} ("guid", "name");`);
|
|
195
|
-
this.queryRun(`CREATE INDEX IF NOT EXISTS ${SQLite3Driver.escape(`${this.prefix}data_${etype}_id_name`)} ON ${SQLite3Driver.escape(`${this.prefix}data_${etype}`)} ("name");`);
|
|
196
|
-
this.queryRun(`CREATE INDEX IF NOT EXISTS ${SQLite3Driver.escape(`${this.prefix}data_${etype}_id_name_string`)} ON ${SQLite3Driver.escape(`${this.prefix}data_${etype}`)} ("name", "string");`);
|
|
197
|
-
this.queryRun(`CREATE INDEX IF NOT EXISTS ${SQLite3Driver.escape(`${this.prefix}data_${etype}_id_name_number`)} ON ${SQLite3Driver.escape(`${this.prefix}data_${etype}`)} ("name", "number");`);
|
|
198
|
-
this.queryRun(`CREATE INDEX IF NOT EXISTS ${SQLite3Driver.escape(`${this.prefix}data_${etype}_id_guid_name_number`)} ON ${SQLite3Driver.escape(`${this.prefix}data_${etype}`)} ("guid", "name", "number");`);
|
|
199
|
-
this.queryRun(`CREATE INDEX IF NOT EXISTS ${SQLite3Driver.escape(`${this.prefix}data_${etype}_id_name_truthy`)} ON ${SQLite3Driver.escape(`${this.prefix}data_${etype}`)} ("name", "truthy");`);
|
|
200
|
-
this.queryRun(`CREATE INDEX IF NOT EXISTS ${SQLite3Driver.escape(`${this.prefix}data_${etype}_id_guid_name_truthy`)} ON ${SQLite3Driver.escape(`${this.prefix}data_${etype}`)} ("guid", "name", "truthy");`);
|
|
201
|
-
this.queryRun(`CREATE INDEX IF NOT EXISTS ${SQLite3Driver.escape(`${this.prefix}data_${etype}_id_acuserread`)} ON ${SQLite3Driver.escape(`${this.prefix}data_${etype}`)} ("guid") WHERE "name"=\'acUser\' AND "number" >= 1;`);
|
|
202
|
-
this.queryRun(`CREATE INDEX IF NOT EXISTS ${SQLite3Driver.escape(`${this.prefix}data_${etype}_id_acgroupread`)} ON ${SQLite3Driver.escape(`${this.prefix}data_${etype}`)} ("guid") WHERE "name"=\'acGroup\' AND "number" >= 1;`);
|
|
203
|
-
this.queryRun(`CREATE INDEX IF NOT EXISTS ${SQLite3Driver.escape(`${this.prefix}data_${etype}_id_acotherread`)} ON ${SQLite3Driver.escape(`${this.prefix}data_${etype}`)} ("guid") WHERE "name"=\'acOther\' AND "number" >= 1;`);
|
|
204
|
-
this.queryRun(`CREATE INDEX IF NOT EXISTS ${SQLite3Driver.escape(`${this.prefix}data_${etype}_id_acuser`)} ON ${SQLite3Driver.escape(`${this.prefix}data_${etype}`)} ("guid") WHERE "name"=\'user\';`);
|
|
205
|
-
this.queryRun(`CREATE INDEX IF NOT EXISTS ${SQLite3Driver.escape(`${this.prefix}data_${etype}_id_acgroup`)} ON ${SQLite3Driver.escape(`${this.prefix}data_${etype}`)} ("guid") WHERE "name"=\'group\';`);
|
|
206
|
-
// Create the references table.
|
|
207
|
-
this.queryRun(`CREATE TABLE IF NOT EXISTS ${SQLite3Driver.escape(`${this.prefix}references_${etype}`)} ("guid" CHARACTER(24) NOT NULL REFERENCES ${SQLite3Driver.escape(`${this.prefix}entities_${etype}`)} ("guid") ON DELETE CASCADE, "name" TEXT NOT NULL, "reference" CHARACTER(24) NOT NULL, PRIMARY KEY("guid", "name", "reference"));`);
|
|
208
|
-
this.queryRun(`CREATE INDEX IF NOT EXISTS ${SQLite3Driver.escape(`${this.prefix}references_${etype}_id_guid`)} ON ${SQLite3Driver.escape(`${this.prefix}references_${etype}`)} ("guid");`);
|
|
209
|
-
this.queryRun(`CREATE INDEX IF NOT EXISTS ${SQLite3Driver.escape(`${this.prefix}references_${etype}_id_name`)} ON ${SQLite3Driver.escape(`${this.prefix}references_${etype}`)} ("name");`);
|
|
210
|
-
this.queryRun(`CREATE INDEX IF NOT EXISTS ${SQLite3Driver.escape(`${this.prefix}references_${etype}_id_name_reference`)} ON ${SQLite3Driver.escape(`${this.prefix}references_${etype}`)} ("name", "reference");`);
|
|
211
|
-
this.queryRun(`CREATE INDEX IF NOT EXISTS ${SQLite3Driver.escape(`${this.prefix}references_${etype}_id_reference`)} ON ${SQLite3Driver.escape(`${this.prefix}references_${etype}`)} ("reference");`);
|
|
212
|
-
this.queryRun(`CREATE INDEX IF NOT EXISTS ${SQLite3Driver.escape(`${this.prefix}references_${etype}_id_guid_name`)} ON ${SQLite3Driver.escape(`${this.prefix}references_${etype}`)} ("guid", "name");`);
|
|
213
|
-
this.queryRun(`CREATE INDEX IF NOT EXISTS ${SQLite3Driver.escape(`${this.prefix}references_${etype}_id_guid_name_reference`)} ON ${SQLite3Driver.escape(`${this.prefix}references_${etype}`)} ("guid", "name", "reference");`);
|
|
214
|
-
this.queryRun(`CREATE INDEX IF NOT EXISTS ${SQLite3Driver.escape(`${this.prefix}references_${etype}_id_reference_name_guid`)} ON ${SQLite3Driver.escape(`${this.prefix}references_${etype}`)} ("reference", "name", "guid");`);
|
|
215
|
-
this.queryRun(`CREATE INDEX IF NOT EXISTS ${SQLite3Driver.escape(`${this.prefix}references_${etype}_id_reference_guid_name`)} ON ${SQLite3Driver.escape(`${this.prefix}references_${etype}`)} ("reference", "guid", "name");`);
|
|
216
|
-
this.queryRun(`CREATE INDEX IF NOT EXISTS ${SQLite3Driver.escape(`${this.prefix}references_${etype}_id_guid_reference_nameuser`)} ON ${SQLite3Driver.escape(`${this.prefix}references_${etype}`)} ("guid", "reference") WHERE "name"=\'user\';`);
|
|
217
|
-
this.queryRun(`CREATE INDEX IF NOT EXISTS ${SQLite3Driver.escape(`${this.prefix}references_${etype}_id_guid_reference_namegroup`)} ON ${SQLite3Driver.escape(`${this.prefix}references_${etype}`)} ("guid", "reference") WHERE "name"=\'group\';`);
|
|
218
|
-
// Create the unique strings table.
|
|
219
|
-
this.queryRun(`CREATE TABLE IF NOT EXISTS ${SQLite3Driver.escape(`${this.prefix}uniques_${etype}`)} ("guid" CHARACTER(24) NOT NULL REFERENCES ${SQLite3Driver.escape(`${this.prefix}entities_${etype}`)} ("guid") ON DELETE CASCADE, "unique" TEXT NOT NULL UNIQUE, PRIMARY KEY("guid", "unique"));`);
|
|
233
|
+
this.createEntitiesTable(etype);
|
|
234
|
+
this.createDataTable(etype);
|
|
235
|
+
this.createReferencesTable(etype);
|
|
236
|
+
this.createTokensTable(etype);
|
|
237
|
+
this.createUniquesTable(etype);
|
|
220
238
|
}
|
|
221
239
|
else {
|
|
222
240
|
// Create the UID table.
|
|
@@ -319,6 +337,12 @@ export default class SQLite3Driver extends NymphDriver {
|
|
|
319
337
|
guid,
|
|
320
338
|
},
|
|
321
339
|
});
|
|
340
|
+
this.queryRun(`DELETE FROM ${SQLite3Driver.escape(`${this.prefix}tokens_${etype}`)} WHERE "guid"=@guid;`, {
|
|
341
|
+
etypes: [etype],
|
|
342
|
+
params: {
|
|
343
|
+
guid,
|
|
344
|
+
},
|
|
345
|
+
});
|
|
322
346
|
this.queryRun(`DELETE FROM ${SQLite3Driver.escape(`${this.prefix}uniques_${etype}`)} WHERE "guid"=@guid;`, {
|
|
323
347
|
etypes: [etype],
|
|
324
348
|
params: {
|
|
@@ -351,6 +375,18 @@ export default class SQLite3Driver extends NymphDriver {
|
|
|
351
375
|
await this.commit('nymph-delete-uid');
|
|
352
376
|
return true;
|
|
353
377
|
}
|
|
378
|
+
async getEtypes() {
|
|
379
|
+
const tables = this.queryArray("SELECT `name` FROM `sqlite_master` WHERE `type`='table' AND `name` LIKE @prefix;", {
|
|
380
|
+
params: {
|
|
381
|
+
prefix: this.prefix + 'entities_' + '%',
|
|
382
|
+
},
|
|
383
|
+
});
|
|
384
|
+
const etypes = [];
|
|
385
|
+
for (const table of tables) {
|
|
386
|
+
etypes.push(table.name.substr((this.prefix + 'entities_').length));
|
|
387
|
+
}
|
|
388
|
+
return etypes;
|
|
389
|
+
}
|
|
354
390
|
async *exportDataIterator() {
|
|
355
391
|
if (yield {
|
|
356
392
|
type: 'comment',
|
|
@@ -395,15 +431,7 @@ export default class SQLite3Driver extends NymphDriver {
|
|
|
395
431
|
return;
|
|
396
432
|
}
|
|
397
433
|
// Get the etypes.
|
|
398
|
-
const
|
|
399
|
-
params: {
|
|
400
|
-
prefix: this.prefix + 'entities_' + '%',
|
|
401
|
-
},
|
|
402
|
-
});
|
|
403
|
-
const etypes = [];
|
|
404
|
-
for (const table of tables) {
|
|
405
|
-
etypes.push(table.name.substr((this.prefix + 'entities_').length));
|
|
406
|
-
}
|
|
434
|
+
const etypes = await this.getEtypes();
|
|
407
435
|
for (const etype of etypes) {
|
|
408
436
|
// Export entities.
|
|
409
437
|
const dataIterator = this.queryArray(`SELECT e.*, d."name", d."value", json(d."json") as "json", d."string", d."number" FROM ${SQLite3Driver.escape(`${this.prefix}entities_${etype}`)} e LEFT JOIN ${SQLite3Driver.escape(`${this.prefix}data_${etype}`)} d USING ("guid") ORDER BY e."guid";`)[Symbol.iterator]();
|
|
@@ -720,6 +748,124 @@ export default class SQLite3Driver extends NymphDriver {
|
|
|
720
748
|
params[value] = svalue;
|
|
721
749
|
}
|
|
722
750
|
break;
|
|
751
|
+
case 'search':
|
|
752
|
+
case '!search':
|
|
753
|
+
if (curValue[0] === 'cdate' || curValue[0] === 'mdate') {
|
|
754
|
+
if (curQuery) {
|
|
755
|
+
curQuery += typeIsOr ? ' OR ' : ' AND ';
|
|
756
|
+
}
|
|
757
|
+
curQuery += (xor(typeIsNot, clauseNot) ? 'NOT ' : '') + '(0)';
|
|
758
|
+
break;
|
|
759
|
+
}
|
|
760
|
+
else {
|
|
761
|
+
if (curQuery) {
|
|
762
|
+
curQuery += typeIsOr ? ' OR ' : ' AND ';
|
|
763
|
+
}
|
|
764
|
+
const name = `param${++count.i}`;
|
|
765
|
+
const queryPartToken = (term) => {
|
|
766
|
+
const value = `param${++count.i}`;
|
|
767
|
+
params[value] = term.token;
|
|
768
|
+
return ('EXISTS (SELECT "guid" FROM ' +
|
|
769
|
+
SQLite3Driver.escape(this.prefix + 'tokens_' + etype) +
|
|
770
|
+
' WHERE "guid"=' +
|
|
771
|
+
ieTable +
|
|
772
|
+
'."guid" AND "name"=@' +
|
|
773
|
+
name +
|
|
774
|
+
' AND "token"=@' +
|
|
775
|
+
value +
|
|
776
|
+
(term.nostemmed ? ' AND "stem"=0' : '') +
|
|
777
|
+
')');
|
|
778
|
+
};
|
|
779
|
+
const queryPartSeries = (series) => {
|
|
780
|
+
const tokenTableSuffix = makeTableSuffix();
|
|
781
|
+
const tokenParts = series.tokens.map((token, i) => {
|
|
782
|
+
const value = `param${++count.i}`;
|
|
783
|
+
params[value] = token.token;
|
|
784
|
+
return {
|
|
785
|
+
fromClause: i === 0
|
|
786
|
+
? 'FROM ' +
|
|
787
|
+
SQLite3Driver.escape(this.prefix + 'tokens_' + etype) +
|
|
788
|
+
' t' +
|
|
789
|
+
tokenTableSuffix +
|
|
790
|
+
'0'
|
|
791
|
+
: 'JOIN ' +
|
|
792
|
+
SQLite3Driver.escape(this.prefix + 'tokens_' + etype) +
|
|
793
|
+
' t' +
|
|
794
|
+
tokenTableSuffix +
|
|
795
|
+
i +
|
|
796
|
+
' ON t' +
|
|
797
|
+
tokenTableSuffix +
|
|
798
|
+
i +
|
|
799
|
+
'."guid" = t' +
|
|
800
|
+
tokenTableSuffix +
|
|
801
|
+
'0."guid" AND t' +
|
|
802
|
+
tokenTableSuffix +
|
|
803
|
+
i +
|
|
804
|
+
'."name" = t' +
|
|
805
|
+
tokenTableSuffix +
|
|
806
|
+
'0."name" AND t' +
|
|
807
|
+
tokenTableSuffix +
|
|
808
|
+
i +
|
|
809
|
+
'."position" = t' +
|
|
810
|
+
tokenTableSuffix +
|
|
811
|
+
'0."position" + ' +
|
|
812
|
+
i,
|
|
813
|
+
whereClause: 't' +
|
|
814
|
+
tokenTableSuffix +
|
|
815
|
+
i +
|
|
816
|
+
'."token"=@' +
|
|
817
|
+
value +
|
|
818
|
+
(token.nostemmed
|
|
819
|
+
? ' AND t' + tokenTableSuffix + i + '."stem"=0'
|
|
820
|
+
: ''),
|
|
821
|
+
};
|
|
822
|
+
});
|
|
823
|
+
return ('EXISTS (SELECT t' +
|
|
824
|
+
tokenTableSuffix +
|
|
825
|
+
'0."guid" ' +
|
|
826
|
+
tokenParts.map((part) => part.fromClause).join(' ') +
|
|
827
|
+
' WHERE t' +
|
|
828
|
+
tokenTableSuffix +
|
|
829
|
+
'0."guid"=' +
|
|
830
|
+
ieTable +
|
|
831
|
+
'."guid" AND t' +
|
|
832
|
+
tokenTableSuffix +
|
|
833
|
+
'0."name"=@' +
|
|
834
|
+
name +
|
|
835
|
+
' AND ' +
|
|
836
|
+
tokenParts.map((part) => part.whereClause).join(' AND ') +
|
|
837
|
+
')');
|
|
838
|
+
};
|
|
839
|
+
const queryPartTerm = (term) => {
|
|
840
|
+
if (term.type === 'series') {
|
|
841
|
+
return queryPartSeries(term);
|
|
842
|
+
}
|
|
843
|
+
else if (term.type === 'not') {
|
|
844
|
+
return 'NOT ' + queryPartTerm(term.operand);
|
|
845
|
+
}
|
|
846
|
+
else if (term.type === 'or') {
|
|
847
|
+
let queryParts = [];
|
|
848
|
+
for (let operand of term.operands) {
|
|
849
|
+
queryParts.push(queryPartTerm(operand));
|
|
850
|
+
}
|
|
851
|
+
return '(' + queryParts.join(' OR ') + ')';
|
|
852
|
+
}
|
|
853
|
+
return queryPartToken(term);
|
|
854
|
+
};
|
|
855
|
+
const parsedFTSQuery = this.tokenizer.parseSearchQuery(curValue[1]);
|
|
856
|
+
// Run through the query and add terms.
|
|
857
|
+
let termStrings = [];
|
|
858
|
+
for (let term of parsedFTSQuery) {
|
|
859
|
+
termStrings.push(queryPartTerm(term));
|
|
860
|
+
}
|
|
861
|
+
curQuery +=
|
|
862
|
+
(xor(typeIsNot, clauseNot) ? 'NOT ' : '') +
|
|
863
|
+
'(' +
|
|
864
|
+
termStrings.join(' AND ') +
|
|
865
|
+
')';
|
|
866
|
+
params[name] = curValue[0];
|
|
867
|
+
}
|
|
868
|
+
break;
|
|
723
869
|
case 'match':
|
|
724
870
|
case '!match':
|
|
725
871
|
if (curValue[0] === 'cdate') {
|
|
@@ -1430,95 +1576,158 @@ export default class SQLite3Driver extends NymphDriver {
|
|
|
1430
1576
|
});
|
|
1431
1577
|
return result?.cur_uid ?? null;
|
|
1432
1578
|
}
|
|
1433
|
-
async importEntity(
|
|
1579
|
+
async importEntity(entity) {
|
|
1580
|
+
return await this.importEntityInternal(entity, false);
|
|
1581
|
+
}
|
|
1582
|
+
async importEntityTokens(entity) {
|
|
1583
|
+
return await this.importEntityInternal(entity, true);
|
|
1584
|
+
}
|
|
1585
|
+
async importEntityInternal({ guid, cdate, mdate, tags, sdata, etype, }, onlyTokens) {
|
|
1434
1586
|
try {
|
|
1435
|
-
|
|
1436
|
-
|
|
1437
|
-
|
|
1438
|
-
|
|
1439
|
-
|
|
1440
|
-
|
|
1441
|
-
|
|
1442
|
-
|
|
1443
|
-
|
|
1444
|
-
|
|
1445
|
-
|
|
1446
|
-
|
|
1447
|
-
|
|
1448
|
-
|
|
1449
|
-
|
|
1450
|
-
|
|
1451
|
-
|
|
1452
|
-
|
|
1453
|
-
|
|
1454
|
-
|
|
1455
|
-
|
|
1456
|
-
guid,
|
|
1457
|
-
},
|
|
1458
|
-
});
|
|
1459
|
-
this.queryRun(`INSERT INTO ${SQLite3Driver.escape(`${this.prefix}entities_${etype}`)} ("guid", "tags", "cdate", "mdate") VALUES (@guid, @tags, @cdate, @mdate);`, {
|
|
1587
|
+
if (!onlyTokens) {
|
|
1588
|
+
this.queryRun(`DELETE FROM ${SQLite3Driver.escape(`${this.prefix}entities_${etype}`)} WHERE "guid"=@guid;`, {
|
|
1589
|
+
etypes: [etype],
|
|
1590
|
+
params: {
|
|
1591
|
+
guid,
|
|
1592
|
+
},
|
|
1593
|
+
});
|
|
1594
|
+
this.queryRun(`DELETE FROM ${SQLite3Driver.escape(`${this.prefix}data_${etype}`)} WHERE "guid"=@guid;`, {
|
|
1595
|
+
etypes: [etype],
|
|
1596
|
+
params: {
|
|
1597
|
+
guid,
|
|
1598
|
+
},
|
|
1599
|
+
});
|
|
1600
|
+
this.queryRun(`DELETE FROM ${SQLite3Driver.escape(`${this.prefix}references_${etype}`)} WHERE "guid"=@guid;`, {
|
|
1601
|
+
etypes: [etype],
|
|
1602
|
+
params: {
|
|
1603
|
+
guid,
|
|
1604
|
+
},
|
|
1605
|
+
});
|
|
1606
|
+
}
|
|
1607
|
+
this.queryRun(`DELETE FROM ${SQLite3Driver.escape(`${this.prefix}tokens_${etype}`)} WHERE "guid"=@guid;`, {
|
|
1460
1608
|
etypes: [etype],
|
|
1461
1609
|
params: {
|
|
1462
1610
|
guid,
|
|
1463
|
-
tags: ',' + tags.join(',') + ',',
|
|
1464
|
-
cdate,
|
|
1465
|
-
mdate,
|
|
1466
1611
|
},
|
|
1467
1612
|
});
|
|
1468
|
-
|
|
1469
|
-
|
|
1470
|
-
const uvalue = JSON.parse(value);
|
|
1471
|
-
if (value === undefined) {
|
|
1472
|
-
continue;
|
|
1473
|
-
}
|
|
1474
|
-
const storageValue = typeof uvalue === 'number'
|
|
1475
|
-
? 'N'
|
|
1476
|
-
: typeof uvalue === 'string'
|
|
1477
|
-
? 'S'
|
|
1478
|
-
: 'J';
|
|
1479
|
-
const jsonValue = storageValue === 'J' ? value : null;
|
|
1480
|
-
this.queryRun(`INSERT INTO ${SQLite3Driver.escape(`${this.prefix}data_${etype}`)} ("guid", "name", "value", "json", "string", "number", "truthy") VALUES (@guid, @name, @storageValue, jsonb(@jsonValue), @string, @number, @truthy);`, {
|
|
1613
|
+
if (!onlyTokens) {
|
|
1614
|
+
this.queryRun(`DELETE FROM ${SQLite3Driver.escape(`${this.prefix}uniques_${etype}`)} WHERE "guid"=@guid;`, {
|
|
1481
1615
|
etypes: [etype],
|
|
1482
1616
|
params: {
|
|
1483
1617
|
guid,
|
|
1484
|
-
name,
|
|
1485
|
-
storageValue,
|
|
1486
|
-
jsonValue,
|
|
1487
|
-
string: storageValue === 'J' ? null : `${uvalue}`,
|
|
1488
|
-
number: Number(uvalue),
|
|
1489
|
-
truthy: uvalue ? 1 : 0,
|
|
1490
1618
|
},
|
|
1491
1619
|
});
|
|
1492
|
-
|
|
1493
|
-
|
|
1494
|
-
|
|
1620
|
+
}
|
|
1621
|
+
if (!onlyTokens) {
|
|
1622
|
+
this.queryRun(`INSERT INTO ${SQLite3Driver.escape(`${this.prefix}entities_${etype}`)} ("guid", "tags", "cdate", "mdate") VALUES (@guid, @tags, @cdate, @mdate);`, {
|
|
1623
|
+
etypes: [etype],
|
|
1624
|
+
params: {
|
|
1625
|
+
guid,
|
|
1626
|
+
tags: ',' + tags.join(',') + ',',
|
|
1627
|
+
cdate,
|
|
1628
|
+
mdate,
|
|
1629
|
+
},
|
|
1630
|
+
});
|
|
1631
|
+
for (const name in sdata) {
|
|
1632
|
+
const value = sdata[name];
|
|
1633
|
+
const uvalue = JSON.parse(value);
|
|
1634
|
+
if (value === undefined) {
|
|
1635
|
+
continue;
|
|
1636
|
+
}
|
|
1637
|
+
const storageValue = typeof uvalue === 'number'
|
|
1638
|
+
? 'N'
|
|
1639
|
+
: typeof uvalue === 'string'
|
|
1640
|
+
? 'S'
|
|
1641
|
+
: 'J';
|
|
1642
|
+
const jsonValue = storageValue === 'J' ? value : null;
|
|
1643
|
+
this.queryRun(`INSERT INTO ${SQLite3Driver.escape(`${this.prefix}data_${etype}`)} ("guid", "name", "value", "json", "string", "number", "truthy") VALUES (@guid, @name, @storageValue, jsonb(@jsonValue), @string, @number, @truthy);`, {
|
|
1495
1644
|
etypes: [etype],
|
|
1496
1645
|
params: {
|
|
1497
1646
|
guid,
|
|
1498
1647
|
name,
|
|
1499
|
-
|
|
1648
|
+
storageValue,
|
|
1649
|
+
jsonValue,
|
|
1650
|
+
string: storageValue === 'J' ? null : `${uvalue}`,
|
|
1651
|
+
number: Number(uvalue),
|
|
1652
|
+
truthy: uvalue ? 1 : 0,
|
|
1500
1653
|
},
|
|
1501
1654
|
});
|
|
1655
|
+
const references = this.findReferences(value);
|
|
1656
|
+
for (const reference of references) {
|
|
1657
|
+
this.queryRun(`INSERT INTO ${SQLite3Driver.escape(`${this.prefix}references_${etype}`)} ("guid", "name", "reference") VALUES (@guid, @name, @reference);`, {
|
|
1658
|
+
etypes: [etype],
|
|
1659
|
+
params: {
|
|
1660
|
+
guid,
|
|
1661
|
+
name,
|
|
1662
|
+
reference,
|
|
1663
|
+
},
|
|
1664
|
+
});
|
|
1665
|
+
}
|
|
1502
1666
|
}
|
|
1503
1667
|
}
|
|
1504
|
-
const
|
|
1505
|
-
|
|
1506
|
-
|
|
1507
|
-
for (const unique of uniques) {
|
|
1668
|
+
const EntityClass = this.nymph.getEntityClassByEtype(etype);
|
|
1669
|
+
for (let name in sdata) {
|
|
1670
|
+
let tokenString = null;
|
|
1508
1671
|
try {
|
|
1509
|
-
|
|
1510
|
-
etypes: [etype],
|
|
1511
|
-
params: {
|
|
1512
|
-
guid,
|
|
1513
|
-
unique,
|
|
1514
|
-
},
|
|
1515
|
-
});
|
|
1672
|
+
tokenString = EntityClass.getFTSText(name, JSON.parse(sdata[name]));
|
|
1516
1673
|
}
|
|
1517
1674
|
catch (e) {
|
|
1518
|
-
|
|
1519
|
-
|
|
1675
|
+
// Ignore error.
|
|
1676
|
+
}
|
|
1677
|
+
if (tokenString != null) {
|
|
1678
|
+
const tokens = this.tokenizer.tokenize(tokenString);
|
|
1679
|
+
while (tokens.length) {
|
|
1680
|
+
const currentTokens = tokens.splice(0, 100);
|
|
1681
|
+
const params = {
|
|
1682
|
+
guid,
|
|
1683
|
+
name,
|
|
1684
|
+
};
|
|
1685
|
+
const values = [];
|
|
1686
|
+
for (let i = 0; i < currentTokens.length; i++) {
|
|
1687
|
+
const token = currentTokens[i];
|
|
1688
|
+
params['token' + i] = token.token;
|
|
1689
|
+
params['position' + i] = token.position;
|
|
1690
|
+
params['stem' + i] = token.stem ? 1 : 0;
|
|
1691
|
+
values.push('(@guid, @name, @token' +
|
|
1692
|
+
i +
|
|
1693
|
+
', @position' +
|
|
1694
|
+
i +
|
|
1695
|
+
', @stem' +
|
|
1696
|
+
i +
|
|
1697
|
+
')');
|
|
1698
|
+
}
|
|
1699
|
+
this.queryRun(`INSERT INTO ${SQLite3Driver.escape(`${this.prefix}tokens_${etype}`)} ("guid", "name", "token", "position", "stem") VALUES ${values.join(', ')};`, {
|
|
1700
|
+
etypes: [etype],
|
|
1701
|
+
params,
|
|
1702
|
+
});
|
|
1703
|
+
}
|
|
1704
|
+
}
|
|
1705
|
+
}
|
|
1706
|
+
if (!onlyTokens) {
|
|
1707
|
+
const uniques = await EntityClass.getUniques({
|
|
1708
|
+
guid,
|
|
1709
|
+
cdate,
|
|
1710
|
+
mdate,
|
|
1711
|
+
tags,
|
|
1712
|
+
data: {},
|
|
1713
|
+
sdata,
|
|
1714
|
+
});
|
|
1715
|
+
for (const unique of uniques) {
|
|
1716
|
+
try {
|
|
1717
|
+
this.queryRun(`INSERT INTO ${SQLite3Driver.escape(`${this.prefix}uniques_${etype}`)} ("guid", "unique") VALUES (@guid, @unique);`, {
|
|
1718
|
+
etypes: [etype],
|
|
1719
|
+
params: {
|
|
1720
|
+
guid,
|
|
1721
|
+
unique,
|
|
1722
|
+
},
|
|
1723
|
+
});
|
|
1724
|
+
}
|
|
1725
|
+
catch (e) {
|
|
1726
|
+
if (e instanceof EntityUniqueConstraintError) {
|
|
1727
|
+
this.nymph.config.debugError('sqlite3', `Import entity unique constraint violation for GUID "${guid}" on etype "${etype}": "${unique}"`);
|
|
1728
|
+
}
|
|
1729
|
+
throw e;
|
|
1520
1730
|
}
|
|
1521
|
-
throw e;
|
|
1522
1731
|
}
|
|
1523
1732
|
}
|
|
1524
1733
|
}
|
|
@@ -1623,6 +1832,7 @@ export default class SQLite3Driver extends NymphDriver {
|
|
|
1623
1832
|
}
|
|
1624
1833
|
async saveEntity(entity) {
|
|
1625
1834
|
const insertData = (guid, data, sdata, uniques, etype) => {
|
|
1835
|
+
const EntityClass = this.nymph.getEntityClassByEtype(etype);
|
|
1626
1836
|
const runInsertQuery = (name, value, svalue) => {
|
|
1627
1837
|
if (value === undefined) {
|
|
1628
1838
|
return;
|
|
@@ -1656,6 +1866,41 @@ export default class SQLite3Driver extends NymphDriver {
|
|
|
1656
1866
|
},
|
|
1657
1867
|
});
|
|
1658
1868
|
}
|
|
1869
|
+
let tokenString = null;
|
|
1870
|
+
try {
|
|
1871
|
+
tokenString = EntityClass.getFTSText(name, value);
|
|
1872
|
+
}
|
|
1873
|
+
catch (e) {
|
|
1874
|
+
// Ignore error.
|
|
1875
|
+
}
|
|
1876
|
+
if (tokenString != null) {
|
|
1877
|
+
const tokens = this.tokenizer.tokenize(tokenString);
|
|
1878
|
+
while (tokens.length) {
|
|
1879
|
+
const currentTokens = tokens.splice(0, 100);
|
|
1880
|
+
const params = {
|
|
1881
|
+
guid,
|
|
1882
|
+
name,
|
|
1883
|
+
};
|
|
1884
|
+
const values = [];
|
|
1885
|
+
for (let i = 0; i < currentTokens.length; i++) {
|
|
1886
|
+
const token = currentTokens[i];
|
|
1887
|
+
params['token' + i] = token.token;
|
|
1888
|
+
params['position' + i] = token.position;
|
|
1889
|
+
params['stem' + i] = token.stem ? 1 : 0;
|
|
1890
|
+
values.push('(@guid, @name, @token' +
|
|
1891
|
+
i +
|
|
1892
|
+
', @position' +
|
|
1893
|
+
i +
|
|
1894
|
+
', @stem' +
|
|
1895
|
+
i +
|
|
1896
|
+
')');
|
|
1897
|
+
}
|
|
1898
|
+
this.queryRun(`INSERT INTO ${SQLite3Driver.escape(`${this.prefix}tokens_${etype}`)} ("guid", "name", "token", "position", "stem") VALUES ${values.join(', ')};`, {
|
|
1899
|
+
etypes: [etype],
|
|
1900
|
+
params,
|
|
1901
|
+
});
|
|
1902
|
+
}
|
|
1903
|
+
}
|
|
1659
1904
|
};
|
|
1660
1905
|
for (const unique of uniques) {
|
|
1661
1906
|
try {
|
|
@@ -1726,6 +1971,12 @@ export default class SQLite3Driver extends NymphDriver {
|
|
|
1726
1971
|
guid,
|
|
1727
1972
|
},
|
|
1728
1973
|
});
|
|
1974
|
+
this.queryRun(`DELETE FROM ${SQLite3Driver.escape(`${this.prefix}tokens_${etype}`)} WHERE "guid"=@guid;`, {
|
|
1975
|
+
etypes: [etype],
|
|
1976
|
+
params: {
|
|
1977
|
+
guid,
|
|
1978
|
+
},
|
|
1979
|
+
});
|
|
1729
1980
|
this.queryRun(`DELETE FROM ${SQLite3Driver.escape(`${this.prefix}uniques_${etype}`)} WHERE "guid"=@guid;`, {
|
|
1730
1981
|
etypes: [etype],
|
|
1731
1982
|
params: {
|
|
@@ -1805,9 +2056,25 @@ export default class SQLite3Driver extends NymphDriver {
|
|
|
1805
2056
|
table: table.name,
|
|
1806
2057
|
},
|
|
1807
2058
|
});
|
|
1808
|
-
|
|
2059
|
+
if (!result?.exists) {
|
|
2060
|
+
return 'json';
|
|
2061
|
+
}
|
|
2062
|
+
}
|
|
2063
|
+
const table2 = this.queryGet("SELECT `name` FROM `sqlite_master` WHERE `type`='table' AND `name` LIKE @tokenTable LIMIT 1;", {
|
|
2064
|
+
params: {
|
|
2065
|
+
tokenTable: this.prefix + 'tokens_' + '%',
|
|
2066
|
+
},
|
|
2067
|
+
});
|
|
2068
|
+
if (!table2 || !table2.name) {
|
|
2069
|
+
return 'tokens';
|
|
1809
2070
|
}
|
|
1810
2071
|
return false;
|
|
1811
2072
|
}
|
|
2073
|
+
async liveMigration(_migrationType) {
|
|
2074
|
+
const etypes = await this.getEtypes();
|
|
2075
|
+
for (let etype of etypes) {
|
|
2076
|
+
this.createTokensTable(etype);
|
|
2077
|
+
}
|
|
2078
|
+
}
|
|
1812
2079
|
}
|
|
1813
2080
|
//# sourceMappingURL=SQLite3Driver.js.map
|