@nymphjs/driver-sqlite3 1.0.0-beta.11 → 1.0.0-beta.111
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 +501 -0
- package/README.md +1 -1
- package/dist/SQLite3Driver.d.ts +104 -14
- package/dist/SQLite3Driver.js +1551 -569
- package/dist/SQLite3Driver.js.map +1 -1
- package/dist/SQLite3Driver.test.js +54 -15
- package/dist/SQLite3Driver.test.js.map +1 -1
- package/dist/conf/d.d.ts +58 -1
- package/dist/conf/d.js +1 -2
- package/dist/conf/defaults.d.ts +1 -1
- package/dist/conf/defaults.js +3 -4
- package/dist/conf/defaults.js.map +1 -1
- package/dist/conf/index.d.ts +2 -2
- package/dist/conf/index.js +2 -8
- package/dist/conf/index.js.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.js +4 -24
- package/dist/index.js.map +1 -1
- package/jest.config.js +12 -2
- package/package.json +19 -16
- package/src/SQLite3Driver.test.ts +53 -9
- package/src/SQLite3Driver.ts +2303 -882
- package/src/conf/d.ts +26 -2
- package/src/conf/defaults.ts +3 -2
- package/src/conf/index.ts +2 -2
- package/src/index.ts +2 -2
- package/tsconfig.json +5 -3
- package/typedoc.json +4 -0
package/dist/SQLite3Driver.js
CHANGED
|
@@ -1,29 +1,39 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
};
|
|
5
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
const better_sqlite3_1 = __importDefault(require("better-sqlite3"));
|
|
7
|
-
const nymph_1 = require("@nymphjs/nymph");
|
|
8
|
-
const guid_1 = require("@nymphjs/guid");
|
|
9
|
-
const conf_1 = require("./conf");
|
|
1
|
+
import SQLite3 from 'better-sqlite3';
|
|
2
|
+
import { NymphDriver, EntityUniqueConstraintError, InvalidParametersError, NotConfiguredError, QueryFailedError, UnableToConnectError, xor, } from '@nymphjs/nymph';
|
|
3
|
+
import { makeTableSuffix } from '@nymphjs/guid';
|
|
4
|
+
import { SQLite3DriverConfigDefaults as defaults, } from './conf/index.js';
|
|
10
5
|
class InternalStore {
|
|
6
|
+
link;
|
|
7
|
+
linkWrite;
|
|
8
|
+
connected = false;
|
|
9
|
+
transactionsStarted = 0;
|
|
11
10
|
constructor(link) {
|
|
12
|
-
this.connected = false;
|
|
13
|
-
this.transactionsStarted = 0;
|
|
14
11
|
this.link = link;
|
|
15
12
|
}
|
|
16
13
|
}
|
|
17
|
-
|
|
14
|
+
/**
|
|
15
|
+
* The SQLite3 Nymph database driver.
|
|
16
|
+
*/
|
|
17
|
+
export default class SQLite3Driver extends NymphDriver {
|
|
18
|
+
config;
|
|
19
|
+
prefix;
|
|
20
|
+
// @ts-ignore: this is assigned in connect(), which is called by the constructor.
|
|
21
|
+
store;
|
|
18
22
|
static escape(input) {
|
|
19
23
|
if (input.indexOf('\x00') !== -1) {
|
|
20
|
-
throw new
|
|
24
|
+
throw new InvalidParametersError('SQLite3 identifiers (like entity ETYPE) cannot contain null characters.');
|
|
21
25
|
}
|
|
22
26
|
return '"' + input.replace(/"/g, () => '""') + '"';
|
|
23
27
|
}
|
|
28
|
+
static escapeValue(input) {
|
|
29
|
+
return "'" + input.replace(/'/g, () => "''") + "'";
|
|
30
|
+
}
|
|
24
31
|
constructor(config, store) {
|
|
25
32
|
super();
|
|
26
|
-
this.config = { ...
|
|
33
|
+
this.config = { ...defaults, ...config };
|
|
34
|
+
if (this.config.filename === ':memory:') {
|
|
35
|
+
this.config.explicitWrite = true;
|
|
36
|
+
}
|
|
27
37
|
this.prefix = this.config.prefix;
|
|
28
38
|
if (store) {
|
|
29
39
|
this.store = store;
|
|
@@ -32,53 +42,126 @@ class SQLite3Driver extends nymph_1.NymphDriver {
|
|
|
32
42
|
this.connect();
|
|
33
43
|
}
|
|
34
44
|
}
|
|
45
|
+
/**
|
|
46
|
+
* This is used internally by Nymph. Don't call it yourself.
|
|
47
|
+
*
|
|
48
|
+
* @returns A clone of this instance.
|
|
49
|
+
*/
|
|
35
50
|
clone() {
|
|
36
51
|
return new SQLite3Driver(this.config, this.store);
|
|
37
52
|
}
|
|
38
|
-
|
|
39
|
-
|
|
53
|
+
/**
|
|
54
|
+
* Connect to the SQLite3 database.
|
|
55
|
+
*
|
|
56
|
+
* @returns Whether this instance is connected to a SQLite3 database.
|
|
57
|
+
*/
|
|
58
|
+
connect() {
|
|
40
59
|
if (this.store && this.store.connected) {
|
|
41
|
-
return true;
|
|
60
|
+
return Promise.resolve(true);
|
|
42
61
|
}
|
|
62
|
+
// Connecting
|
|
63
|
+
this._connect(false);
|
|
64
|
+
return Promise.resolve(this.store.connected);
|
|
65
|
+
}
|
|
66
|
+
_connect(write) {
|
|
67
|
+
const { filename, fileMustExist, timeout, explicitWrite, wal, verbose } = this.config;
|
|
43
68
|
try {
|
|
44
|
-
const
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
69
|
+
const setOptions = (link) => {
|
|
70
|
+
// Set database and connection options.
|
|
71
|
+
if (wal) {
|
|
72
|
+
link.pragma('journal_mode = WAL;');
|
|
73
|
+
}
|
|
74
|
+
link.pragma('encoding = "UTF-8";');
|
|
75
|
+
link.pragma('foreign_keys = 1;');
|
|
76
|
+
link.pragma('case_sensitive_like = 1;');
|
|
77
|
+
for (let pragma of this.config.pragmas) {
|
|
78
|
+
link.pragma(pragma);
|
|
79
|
+
}
|
|
80
|
+
// Create the preg_match and regexp functions.
|
|
81
|
+
link.function('regexp', { deterministic: true }, ((pattern, subject) => (this.posixRegexMatch(pattern, subject) ? 1 : 0)));
|
|
82
|
+
};
|
|
83
|
+
let link;
|
|
84
|
+
try {
|
|
85
|
+
link = new SQLite3(filename, {
|
|
86
|
+
readonly: !explicitWrite && !write,
|
|
87
|
+
fileMustExist,
|
|
88
|
+
timeout,
|
|
89
|
+
verbose,
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
catch (e) {
|
|
93
|
+
if (e.code === 'SQLITE_CANTOPEN' &&
|
|
94
|
+
!explicitWrite &&
|
|
95
|
+
!write &&
|
|
96
|
+
!this.config.fileMustExist) {
|
|
97
|
+
// This happens when the file doesn't exist and we attempt to open it
|
|
98
|
+
// readonly.
|
|
99
|
+
// First open it in write mode.
|
|
100
|
+
const writeLink = new SQLite3(filename, {
|
|
101
|
+
readonly: false,
|
|
102
|
+
fileMustExist,
|
|
103
|
+
timeout,
|
|
104
|
+
verbose,
|
|
105
|
+
});
|
|
106
|
+
setOptions(writeLink);
|
|
107
|
+
writeLink.close();
|
|
108
|
+
// Now open in readonly.
|
|
109
|
+
link = new SQLite3(filename, {
|
|
110
|
+
readonly: true,
|
|
111
|
+
fileMustExist,
|
|
112
|
+
timeout,
|
|
113
|
+
verbose,
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
else {
|
|
117
|
+
throw e;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
50
120
|
if (!this.store) {
|
|
121
|
+
if (write) {
|
|
122
|
+
throw new Error('Tried to open in write without opening in read first.');
|
|
123
|
+
}
|
|
51
124
|
this.store = new InternalStore(link);
|
|
52
125
|
}
|
|
126
|
+
else if (write) {
|
|
127
|
+
this.store.linkWrite = link;
|
|
128
|
+
}
|
|
53
129
|
else {
|
|
54
130
|
this.store.link = link;
|
|
55
131
|
}
|
|
56
132
|
this.store.connected = true;
|
|
57
|
-
|
|
58
|
-
this.store.link.pragma('journal_mode = WAL;');
|
|
59
|
-
}
|
|
60
|
-
this.store.link.pragma('encoding = "UTF-8";');
|
|
61
|
-
this.store.link.pragma('foreign_keys = 1;');
|
|
62
|
-
this.store.link.pragma('case_sensitive_like = 1;');
|
|
63
|
-
this.store.link.function('regexp', { deterministic: true }, (pattern, subject) => this.posixRegexMatch(pattern, subject) ? 1 : 0);
|
|
133
|
+
setOptions(link);
|
|
64
134
|
}
|
|
65
135
|
catch (e) {
|
|
66
136
|
if (this.store) {
|
|
67
137
|
this.store.connected = false;
|
|
68
138
|
}
|
|
69
139
|
if (filename === ':memory:') {
|
|
70
|
-
throw new
|
|
140
|
+
throw new NotConfiguredError("It seems the config hasn't been set up correctly. Could not connect: " +
|
|
141
|
+
e?.message);
|
|
71
142
|
}
|
|
72
143
|
else {
|
|
73
|
-
throw new
|
|
144
|
+
throw new UnableToConnectError('Could not connect: ' + e?.message);
|
|
74
145
|
}
|
|
75
146
|
}
|
|
76
|
-
return this.store.connected;
|
|
77
147
|
}
|
|
148
|
+
/**
|
|
149
|
+
* Disconnect from the SQLite3 database.
|
|
150
|
+
*
|
|
151
|
+
* @returns Whether this instance is connected to a SQLite3 database.
|
|
152
|
+
*/
|
|
78
153
|
async disconnect() {
|
|
79
154
|
if (this.store.connected) {
|
|
80
|
-
this.store.
|
|
155
|
+
if (this.store.linkWrite && !this.config.explicitWrite) {
|
|
156
|
+
this.store.linkWrite.exec('PRAGMA optimize;');
|
|
157
|
+
this.store.linkWrite.close();
|
|
158
|
+
this.store.linkWrite = undefined;
|
|
159
|
+
}
|
|
160
|
+
if (this.config.explicitWrite) {
|
|
161
|
+
this.store.link.exec('PRAGMA optimize;');
|
|
162
|
+
}
|
|
81
163
|
this.store.link.close();
|
|
164
|
+
this.store.transactionsStarted = 0;
|
|
82
165
|
this.store.connected = false;
|
|
83
166
|
}
|
|
84
167
|
return this.store.connected;
|
|
@@ -86,51 +169,106 @@ class SQLite3Driver extends nymph_1.NymphDriver {
|
|
|
86
169
|
async inTransaction() {
|
|
87
170
|
return this.store.transactionsStarted > 0;
|
|
88
171
|
}
|
|
172
|
+
/**
|
|
173
|
+
* Check connection status.
|
|
174
|
+
*
|
|
175
|
+
* @returns Whether this instance is connected to a SQLite3 database.
|
|
176
|
+
*/
|
|
89
177
|
isConnected() {
|
|
90
178
|
return this.store.connected;
|
|
91
179
|
}
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
}
|
|
180
|
+
createEntitiesTable(etype) {
|
|
181
|
+
// Create the entity table.
|
|
182
|
+
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, "user" CHARACTER(24), "group" CHARACTER(24), "acUser" INT(1), "acGroup" INT(1), "acOther" INT(1), "acRead" TEXT, "acWrite" TEXT, "acFull" TEXT);`);
|
|
183
|
+
this.queryRun(`CREATE INDEX IF NOT EXISTS ${SQLite3Driver.escape(`${this.prefix}entities_${etype}_id_cdate`)} ON ${SQLite3Driver.escape(`${this.prefix}entities_${etype}`)} ("cdate");`);
|
|
184
|
+
this.queryRun(`CREATE INDEX IF NOT EXISTS ${SQLite3Driver.escape(`${this.prefix}entities_${etype}_id_mdate`)} ON ${SQLite3Driver.escape(`${this.prefix}entities_${etype}`)} ("mdate");`);
|
|
185
|
+
this.queryRun(`CREATE INDEX IF NOT EXISTS ${SQLite3Driver.escape(`${this.prefix}entities_${etype}_id_tags`)} ON ${SQLite3Driver.escape(`${this.prefix}entities_${etype}`)} ("tags");`);
|
|
186
|
+
this.createEntitiesTilmeldIndexes(etype);
|
|
96
187
|
}
|
|
188
|
+
addTilmeldColumnsAndIndexes(etype) {
|
|
189
|
+
this.queryRun(`ALTER TABLE ${SQLite3Driver.escape(`${this.prefix}entities_${etype}`)} ADD COLUMN "user" CHARACTER(24);`);
|
|
190
|
+
this.queryRun(`ALTER TABLE ${SQLite3Driver.escape(`${this.prefix}entities_${etype}`)} ADD COLUMN "group" CHARACTER(24);`);
|
|
191
|
+
this.queryRun(`ALTER TABLE ${SQLite3Driver.escape(`${this.prefix}entities_${etype}`)} ADD COLUMN "acUser" INT(1);`);
|
|
192
|
+
this.queryRun(`ALTER TABLE ${SQLite3Driver.escape(`${this.prefix}entities_${etype}`)} ADD COLUMN "acGroup" INT(1);`);
|
|
193
|
+
this.queryRun(`ALTER TABLE ${SQLite3Driver.escape(`${this.prefix}entities_${etype}`)} ADD COLUMN "acOther" INT(1);`);
|
|
194
|
+
this.queryRun(`ALTER TABLE ${SQLite3Driver.escape(`${this.prefix}entities_${etype}`)} ADD COLUMN "acRead" TEXT;`);
|
|
195
|
+
this.queryRun(`ALTER TABLE ${SQLite3Driver.escape(`${this.prefix}entities_${etype}`)} ADD COLUMN "acWrite" TEXT;`);
|
|
196
|
+
this.queryRun(`ALTER TABLE ${SQLite3Driver.escape(`${this.prefix}entities_${etype}`)} ADD COLUMN "acFull" TEXT;`);
|
|
197
|
+
this.createEntitiesTilmeldIndexes(etype);
|
|
198
|
+
}
|
|
199
|
+
createEntitiesTilmeldIndexes(etype) {
|
|
200
|
+
this.queryRun(`CREATE INDEX IF NOT EXISTS ${SQLite3Driver.escape(`${this.prefix}entities_${etype}_id_user_acUser`)} ON ${SQLite3Driver.escape(`${this.prefix}entities_${etype}`)} ("user", "acUser");`);
|
|
201
|
+
this.queryRun(`CREATE INDEX IF NOT EXISTS ${SQLite3Driver.escape(`${this.prefix}entities_${etype}_id_group_acGroup`)} ON ${SQLite3Driver.escape(`${this.prefix}entities_${etype}`)} ("group", "acGroup");`);
|
|
202
|
+
this.queryRun(`CREATE INDEX IF NOT EXISTS ${SQLite3Driver.escape(`${this.prefix}entities_${etype}_id_acUser`)} ON ${SQLite3Driver.escape(`${this.prefix}entities_${etype}`)} ("acUser");`);
|
|
203
|
+
this.queryRun(`CREATE INDEX IF NOT EXISTS ${SQLite3Driver.escape(`${this.prefix}entities_${etype}_id_acGroup`)} ON ${SQLite3Driver.escape(`${this.prefix}entities_${etype}`)} ("acGroup");`);
|
|
204
|
+
this.queryRun(`CREATE INDEX IF NOT EXISTS ${SQLite3Driver.escape(`${this.prefix}entities_${etype}_id_acOther`)} ON ${SQLite3Driver.escape(`${this.prefix}entities_${etype}`)} ("acOther");`);
|
|
205
|
+
this.queryRun(`CREATE INDEX IF NOT EXISTS ${SQLite3Driver.escape(`${this.prefix}entities_${etype}_id_acRead`)} ON ${SQLite3Driver.escape(`${this.prefix}entities_${etype}`)} ("acRead");`);
|
|
206
|
+
this.queryRun(`CREATE INDEX IF NOT EXISTS ${SQLite3Driver.escape(`${this.prefix}entities_${etype}_id_acWrite`)} ON ${SQLite3Driver.escape(`${this.prefix}entities_${etype}`)} ("acWrite");`);
|
|
207
|
+
this.queryRun(`CREATE INDEX IF NOT EXISTS ${SQLite3Driver.escape(`${this.prefix}entities_${etype}_id_acFull`)} ON ${SQLite3Driver.escape(`${this.prefix}entities_${etype}`)} ("acFull");`);
|
|
208
|
+
}
|
|
209
|
+
createDataTable(etype) {
|
|
210
|
+
// Create the data table.
|
|
211
|
+
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"));`);
|
|
212
|
+
this.queryRun(`CREATE INDEX IF NOT EXISTS ${SQLite3Driver.escape(`${this.prefix}data_${etype}_id_guid`)} ON ${SQLite3Driver.escape(`${this.prefix}data_${etype}`)} ("guid");`);
|
|
213
|
+
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");`);
|
|
214
|
+
this.queryRun(`CREATE INDEX IF NOT EXISTS ${SQLite3Driver.escape(`${this.prefix}data_${etype}_id_name`)} ON ${SQLite3Driver.escape(`${this.prefix}data_${etype}`)} ("name");`);
|
|
215
|
+
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");`);
|
|
216
|
+
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");`);
|
|
217
|
+
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");`);
|
|
218
|
+
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");`);
|
|
219
|
+
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");`);
|
|
220
|
+
}
|
|
221
|
+
createReferencesTable(etype) {
|
|
222
|
+
// Create the references table.
|
|
223
|
+
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"));`);
|
|
224
|
+
this.queryRun(`CREATE INDEX IF NOT EXISTS ${SQLite3Driver.escape(`${this.prefix}references_${etype}_id_guid`)} ON ${SQLite3Driver.escape(`${this.prefix}references_${etype}`)} ("guid");`);
|
|
225
|
+
this.queryRun(`CREATE INDEX IF NOT EXISTS ${SQLite3Driver.escape(`${this.prefix}references_${etype}_id_name`)} ON ${SQLite3Driver.escape(`${this.prefix}references_${etype}`)} ("name");`);
|
|
226
|
+
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");`);
|
|
227
|
+
this.queryRun(`CREATE INDEX IF NOT EXISTS ${SQLite3Driver.escape(`${this.prefix}references_${etype}_id_reference`)} ON ${SQLite3Driver.escape(`${this.prefix}references_${etype}`)} ("reference");`);
|
|
228
|
+
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");`);
|
|
229
|
+
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");`);
|
|
230
|
+
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");`);
|
|
231
|
+
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");`);
|
|
232
|
+
}
|
|
233
|
+
createTokensTable(etype) {
|
|
234
|
+
// Create the tokens table.
|
|
235
|
+
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"));`);
|
|
236
|
+
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");`);
|
|
237
|
+
}
|
|
238
|
+
createUniquesTable(etype) {
|
|
239
|
+
// Create the unique strings table.
|
|
240
|
+
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"));`);
|
|
241
|
+
}
|
|
242
|
+
/**
|
|
243
|
+
* Create entity tables in the database.
|
|
244
|
+
*
|
|
245
|
+
* @param etype The entity type to create a table for. If this is blank, the default tables are created.
|
|
246
|
+
*/
|
|
97
247
|
createTables(etype = null) {
|
|
98
|
-
this.checkReadOnlyMode();
|
|
99
248
|
this.startTransaction('nymph-tablecreation');
|
|
100
249
|
try {
|
|
101
250
|
if (etype != null) {
|
|
102
|
-
this.
|
|
103
|
-
this.
|
|
104
|
-
this.
|
|
105
|
-
this.
|
|
106
|
-
this.
|
|
107
|
-
this.queryRun(`CREATE INDEX IF NOT EXISTS ${SQLite3Driver.escape(`${this.prefix}data_${etype}_id_guid`)} ON ${SQLite3Driver.escape(`${this.prefix}data_${etype}`)} ("guid");`);
|
|
108
|
-
this.queryRun(`CREATE INDEX IF NOT EXISTS ${SQLite3Driver.escape(`${this.prefix}data_${etype}_id_name`)} ON ${SQLite3Driver.escape(`${this.prefix}data_${etype}`)} ("name");`);
|
|
109
|
-
this.queryRun(`CREATE INDEX IF NOT EXISTS ${SQLite3Driver.escape(`${this.prefix}data_${etype}_id_value`)} ON ${SQLite3Driver.escape(`${this.prefix}data_${etype}`)} ("value");`);
|
|
110
|
-
this.queryRun(`CREATE INDEX IF NOT EXISTS ${SQLite3Driver.escape(`${this.prefix}data_${etype}_id_guid__name_user`)} ON ${SQLite3Driver.escape(`${this.prefix}data_${etype}`)} ("guid") WHERE "name" = \'user\';`);
|
|
111
|
-
this.queryRun(`CREATE INDEX IF NOT EXISTS ${SQLite3Driver.escape(`${this.prefix}data_${etype}_id_guid__name_group`)} ON ${SQLite3Driver.escape(`${this.prefix}data_${etype}`)} ("guid") WHERE "name" = \'group\';`);
|
|
112
|
-
this.queryRun(`CREATE TABLE IF NOT EXISTS ${SQLite3Driver.escape(`${this.prefix}comparisons_${etype}`)} ("guid" CHARACTER(24) NOT NULL REFERENCES ${SQLite3Driver.escape(`${this.prefix}entities_${etype}`)} ("guid") ON DELETE CASCADE, "name" TEXT NOT NULL, "truthy" INTEGER, "string" TEXT, "number" REAL, PRIMARY KEY("guid", "name"));`);
|
|
113
|
-
this.queryRun(`CREATE INDEX IF NOT EXISTS ${SQLite3Driver.escape(`${this.prefix}comparisons_${etype}_id_guid`)} ON ${SQLite3Driver.escape(`${this.prefix}comparisons_${etype}`)} ("guid");`);
|
|
114
|
-
this.queryRun(`CREATE INDEX IF NOT EXISTS ${SQLite3Driver.escape(`${this.prefix}comparisons_${etype}_id_name`)} ON ${SQLite3Driver.escape(`${this.prefix}comparisons_${etype}`)} ("name");`);
|
|
115
|
-
this.queryRun(`CREATE INDEX IF NOT EXISTS ${SQLite3Driver.escape(`${this.prefix}comparisons_${etype}_id_name__truthy`)} ON ${SQLite3Driver.escape(`${this.prefix}comparisons_${etype}`)} ("name") WHERE "truthy" = 1;`);
|
|
116
|
-
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"));`);
|
|
117
|
-
this.queryRun(`CREATE INDEX IF NOT EXISTS ${SQLite3Driver.escape(`${this.prefix}references_${etype}_id_guid`)} ON ${SQLite3Driver.escape(`${this.prefix}references_${etype}`)} ("guid");`);
|
|
118
|
-
this.queryRun(`CREATE INDEX IF NOT EXISTS ${SQLite3Driver.escape(`${this.prefix}references_${etype}_id_name`)} ON ${SQLite3Driver.escape(`${this.prefix}references_${etype}`)} ("name");`);
|
|
119
|
-
this.queryRun(`CREATE INDEX IF NOT EXISTS ${SQLite3Driver.escape(`${this.prefix}references_${etype}_id_reference`)} ON ${SQLite3Driver.escape(`${this.prefix}references_${etype}`)} ("reference");`);
|
|
251
|
+
this.createEntitiesTable(etype);
|
|
252
|
+
this.createDataTable(etype);
|
|
253
|
+
this.createReferencesTable(etype);
|
|
254
|
+
this.createTokensTable(etype);
|
|
255
|
+
this.createUniquesTable(etype);
|
|
120
256
|
}
|
|
121
257
|
else {
|
|
258
|
+
// Create the UID table.
|
|
122
259
|
this.queryRun(`CREATE TABLE IF NOT EXISTS ${SQLite3Driver.escape(`${this.prefix}uids`)} ("name" TEXT PRIMARY KEY NOT NULL, "cur_uid" INTEGER NOT NULL);`);
|
|
123
260
|
}
|
|
124
|
-
this.commit('nymph-tablecreation');
|
|
125
|
-
return true;
|
|
126
261
|
}
|
|
127
262
|
catch (e) {
|
|
128
263
|
this.rollback('nymph-tablecreation');
|
|
129
264
|
throw e;
|
|
130
265
|
}
|
|
266
|
+
this.commit('nymph-tablecreation');
|
|
267
|
+
return true;
|
|
131
268
|
}
|
|
132
269
|
query(runQuery, query, etypes = []) {
|
|
133
270
|
try {
|
|
271
|
+
this.nymph.config.debugInfo('sqlite3:query', query);
|
|
134
272
|
return runQuery();
|
|
135
273
|
}
|
|
136
274
|
catch (e) {
|
|
@@ -146,32 +284,45 @@ class SQLite3Driver extends nymph_1.NymphDriver {
|
|
|
146
284
|
return runQuery();
|
|
147
285
|
}
|
|
148
286
|
catch (e2) {
|
|
149
|
-
throw new
|
|
287
|
+
throw new QueryFailedError('Query failed: ' + e2?.code + ' - ' + e2?.message, query, e2?.code);
|
|
150
288
|
}
|
|
151
289
|
}
|
|
290
|
+
else if (errorCode === 'SQLITE_CONSTRAINT_UNIQUE' &&
|
|
291
|
+
errorMsg.match(/^UNIQUE constraint failed: /)) {
|
|
292
|
+
throw new EntityUniqueConstraintError(`Unique constraint violation.`);
|
|
293
|
+
}
|
|
152
294
|
else {
|
|
153
|
-
throw new
|
|
295
|
+
throw new QueryFailedError('Query failed: ' + e?.code + ' - ' + e?.message, query, e?.code);
|
|
154
296
|
}
|
|
155
297
|
}
|
|
156
298
|
}
|
|
157
|
-
|
|
158
|
-
return this.query(() => this.store.
|
|
299
|
+
queryArray(query, { etypes = [], params = {}, } = {}) {
|
|
300
|
+
return this.query(() => (this.store.linkWrite || this.store.link)
|
|
301
|
+
.prepare(query)
|
|
302
|
+
.iterate(params), `${query} -- ${JSON.stringify(params)}`, etypes);
|
|
159
303
|
}
|
|
160
304
|
queryGet(query, { etypes = [], params = {}, } = {}) {
|
|
161
|
-
return this.query(() => this.store.link.prepare(query).get(params), `${query} -- ${JSON.stringify(params)}`, etypes);
|
|
305
|
+
return this.query(() => (this.store.linkWrite || this.store.link).prepare(query).get(params), `${query} -- ${JSON.stringify(params)}`, etypes);
|
|
162
306
|
}
|
|
163
307
|
queryRun(query, { etypes = [], params = {}, } = {}) {
|
|
164
|
-
return this.query(() => this.store.link.prepare(query).run(params), `${query} -- ${JSON.stringify(params)}`, etypes);
|
|
308
|
+
return this.query(() => (this.store.linkWrite || this.store.link).prepare(query).run(params), `${query} -- ${JSON.stringify(params)}`, etypes);
|
|
165
309
|
}
|
|
166
310
|
async commit(name) {
|
|
167
311
|
if (name == null || typeof name !== 'string' || name.length === 0) {
|
|
168
|
-
throw new
|
|
312
|
+
throw new InvalidParametersError('Transaction commit attempted without a name.');
|
|
169
313
|
}
|
|
170
314
|
if (this.store.transactionsStarted === 0) {
|
|
171
315
|
return true;
|
|
172
316
|
}
|
|
173
317
|
this.queryRun(`RELEASE SAVEPOINT ${SQLite3Driver.escape(name)};`);
|
|
174
318
|
this.store.transactionsStarted--;
|
|
319
|
+
if (this.store.transactionsStarted === 0 &&
|
|
320
|
+
this.store.linkWrite &&
|
|
321
|
+
!this.config.explicitWrite) {
|
|
322
|
+
this.store.linkWrite.exec('PRAGMA optimize;');
|
|
323
|
+
this.store.linkWrite.close();
|
|
324
|
+
this.store.linkWrite = undefined;
|
|
325
|
+
}
|
|
175
326
|
return true;
|
|
176
327
|
}
|
|
177
328
|
async deleteEntityByID(guid, className) {
|
|
@@ -184,7 +335,6 @@ class SQLite3Driver extends nymph_1.NymphDriver {
|
|
|
184
335
|
EntityClass = className;
|
|
185
336
|
}
|
|
186
337
|
const etype = EntityClass.ETYPE;
|
|
187
|
-
this.checkReadOnlyMode();
|
|
188
338
|
await this.startTransaction('nymph-delete');
|
|
189
339
|
try {
|
|
190
340
|
this.queryRun(`DELETE FROM ${SQLite3Driver.escape(`${this.prefix}entities_${etype}`)} WHERE "guid"=@guid;`, {
|
|
@@ -199,108 +349,256 @@ class SQLite3Driver extends nymph_1.NymphDriver {
|
|
|
199
349
|
guid,
|
|
200
350
|
},
|
|
201
351
|
});
|
|
202
|
-
this.queryRun(`DELETE FROM ${SQLite3Driver.escape(`${this.prefix}
|
|
352
|
+
this.queryRun(`DELETE FROM ${SQLite3Driver.escape(`${this.prefix}references_${etype}`)} WHERE "guid"=@guid;`, {
|
|
203
353
|
etypes: [etype],
|
|
204
354
|
params: {
|
|
205
355
|
guid,
|
|
206
356
|
},
|
|
207
357
|
});
|
|
208
|
-
this.queryRun(`DELETE FROM ${SQLite3Driver.escape(`${this.prefix}
|
|
358
|
+
this.queryRun(`DELETE FROM ${SQLite3Driver.escape(`${this.prefix}tokens_${etype}`)} WHERE "guid"=@guid;`, {
|
|
359
|
+
etypes: [etype],
|
|
360
|
+
params: {
|
|
361
|
+
guid,
|
|
362
|
+
},
|
|
363
|
+
});
|
|
364
|
+
this.queryRun(`DELETE FROM ${SQLite3Driver.escape(`${this.prefix}uniques_${etype}`)} WHERE "guid"=@guid;`, {
|
|
209
365
|
etypes: [etype],
|
|
210
366
|
params: {
|
|
211
367
|
guid,
|
|
212
368
|
},
|
|
213
369
|
});
|
|
214
|
-
await this.commit('nymph-delete');
|
|
215
|
-
if (this.nymph.config.cache) {
|
|
216
|
-
this.cleanCache(guid);
|
|
217
|
-
}
|
|
218
|
-
return true;
|
|
219
370
|
}
|
|
220
371
|
catch (e) {
|
|
372
|
+
this.nymph.config.debugError('sqlite3', `Delete entity error: "${e}"`);
|
|
221
373
|
await this.rollback('nymph-delete');
|
|
222
374
|
throw e;
|
|
223
375
|
}
|
|
376
|
+
await this.commit('nymph-delete');
|
|
377
|
+
// Remove any cached versions of this entity.
|
|
378
|
+
if (this.nymph.config.cache) {
|
|
379
|
+
this.cleanCache(guid);
|
|
380
|
+
}
|
|
381
|
+
return true;
|
|
224
382
|
}
|
|
225
383
|
async deleteUID(name) {
|
|
226
384
|
if (!name) {
|
|
227
|
-
throw new
|
|
385
|
+
throw new InvalidParametersError('Name not given for UID');
|
|
228
386
|
}
|
|
229
|
-
this.
|
|
387
|
+
await this.startTransaction('nymph-delete-uid');
|
|
230
388
|
this.queryRun(`DELETE FROM ${SQLite3Driver.escape(`${this.prefix}uids`)} WHERE "name"=@name;`, {
|
|
231
389
|
params: {
|
|
232
390
|
name,
|
|
233
391
|
},
|
|
234
392
|
});
|
|
393
|
+
await this.commit('nymph-delete-uid');
|
|
235
394
|
return true;
|
|
236
395
|
}
|
|
237
|
-
async
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
396
|
+
async getIndexes(etype) {
|
|
397
|
+
const indexes = [];
|
|
398
|
+
for (let [scope, suffix] of [
|
|
399
|
+
['data', '_json'],
|
|
400
|
+
['references', '_reference_guid'],
|
|
401
|
+
['tokens', '_token_position_stem'],
|
|
402
|
+
]) {
|
|
403
|
+
const indexDefinitions = this.queryArray(`SELECT "name", "sql" FROM "sqlite_master" WHERE "type"='index' AND "name" LIKE @pattern;`, {
|
|
404
|
+
params: {
|
|
405
|
+
pattern: `${this.prefix}${scope}_${etype}_id_custom_%${suffix}`,
|
|
406
|
+
},
|
|
407
|
+
});
|
|
408
|
+
for (const indexDefinition of indexDefinitions) {
|
|
409
|
+
indexes.push({
|
|
410
|
+
scope,
|
|
411
|
+
name: indexDefinition.name.substring(`${this.prefix}${scope}_${etype}_id_custom_`.length, indexDefinition.name.length - suffix.length),
|
|
412
|
+
property: (indexDefinition.sql.match(/WHERE\s+"name"\s*=\s*'(.*)'/) ?? [])[1] ?? '',
|
|
413
|
+
});
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
return indexes;
|
|
417
|
+
}
|
|
418
|
+
async addIndex(etype, definition) {
|
|
419
|
+
this.checkIndexName(definition.name);
|
|
420
|
+
await this.deleteIndex(etype, definition.scope, definition.name);
|
|
421
|
+
if (definition.scope === 'data') {
|
|
422
|
+
this.queryRun(`CREATE INDEX IF NOT EXISTS ${SQLite3Driver.escape(`${this.prefix}data_${etype}_id_custom_${definition.name}_json`)} ON ${SQLite3Driver.escape(`${this.prefix}data_${etype}`)} ("json") WHERE "name"=${SQLite3Driver.escapeValue(definition.property)};`);
|
|
423
|
+
this.queryRun(`CREATE INDEX IF NOT EXISTS ${SQLite3Driver.escape(`${this.prefix}data_${etype}_id_custom_${definition.name}_string`)} ON ${SQLite3Driver.escape(`${this.prefix}data_${etype}`)} ("string") WHERE "name"=${SQLite3Driver.escapeValue(definition.property)};`);
|
|
424
|
+
this.queryRun(`CREATE INDEX IF NOT EXISTS ${SQLite3Driver.escape(`${this.prefix}data_${etype}_id_custom_${definition.name}_number`)} ON ${SQLite3Driver.escape(`${this.prefix}data_${etype}`)} ("number") WHERE "name"=${SQLite3Driver.escapeValue(definition.property)};`);
|
|
425
|
+
this.queryRun(`CREATE INDEX IF NOT EXISTS ${SQLite3Driver.escape(`${this.prefix}data_${etype}_id_custom_${definition.name}_truthy`)} ON ${SQLite3Driver.escape(`${this.prefix}data_${etype}`)} ("truthy") WHERE "name"=${SQLite3Driver.escapeValue(definition.property)};`);
|
|
426
|
+
}
|
|
427
|
+
else if (definition.scope === 'references') {
|
|
428
|
+
this.queryRun(`CREATE INDEX IF NOT EXISTS ${SQLite3Driver.escape(`${this.prefix}references_${etype}_id_custom_${definition.name}_reference_guid`)} ON ${SQLite3Driver.escape(`${this.prefix}references_${etype}`)} ("reference", "guid") WHERE "name"=${SQLite3Driver.escapeValue(definition.property)};`);
|
|
429
|
+
}
|
|
430
|
+
else if (definition.scope === 'tokens') {
|
|
431
|
+
this.queryRun(`CREATE INDEX IF NOT EXISTS ${SQLite3Driver.escape(`${this.prefix}tokens_${etype}_id_custom_${definition.name}_token_position_stem`)} ON ${SQLite3Driver.escape(`${this.prefix}tokens_${etype}`)} ("token", "position", "stem") WHERE "name"=${SQLite3Driver.escapeValue(definition.property)};`);
|
|
432
|
+
}
|
|
433
|
+
return true;
|
|
434
|
+
}
|
|
435
|
+
async deleteIndex(etype, scope, name) {
|
|
436
|
+
this.checkIndexName(name);
|
|
437
|
+
if (scope === 'data') {
|
|
438
|
+
this.queryRun(`DROP INDEX IF EXISTS ${SQLite3Driver.escape(`${this.prefix}data_${etype}_id_custom_${name}_json`)};`);
|
|
439
|
+
this.queryRun(`DROP INDEX IF EXISTS ${SQLite3Driver.escape(`${this.prefix}data_${etype}_id_custom_${name}_string`)};`);
|
|
440
|
+
this.queryRun(`DROP INDEX IF EXISTS ${SQLite3Driver.escape(`${this.prefix}data_${etype}_id_custom_${name}_number`)};`);
|
|
441
|
+
this.queryRun(`DROP INDEX IF EXISTS ${SQLite3Driver.escape(`${this.prefix}data_${etype}_id_custom_${name}_truthy`)};`);
|
|
442
|
+
}
|
|
443
|
+
else if (scope === 'references') {
|
|
444
|
+
this.queryRun(`DROP INDEX IF EXISTS ${SQLite3Driver.escape(`${this.prefix}references_${etype}_id_custom_${name}_reference_guid`)};`);
|
|
445
|
+
}
|
|
446
|
+
else if (scope === 'tokens') {
|
|
447
|
+
this.queryRun(`DROP INDEX IF EXISTS ${SQLite3Driver.escape(`${this.prefix}tokens_${etype}_id_custom_${name}_token_position_stem`)};`);
|
|
448
|
+
}
|
|
449
|
+
return true;
|
|
450
|
+
}
|
|
451
|
+
async getEtypes() {
|
|
452
|
+
const tables = this.queryArray("SELECT `name` FROM `sqlite_master` WHERE `type`='table' AND `name` LIKE @prefix;", {
|
|
453
|
+
params: {
|
|
454
|
+
prefix: this.prefix + 'entities_' + '%',
|
|
455
|
+
},
|
|
456
|
+
});
|
|
258
457
|
const etypes = [];
|
|
259
458
|
for (const table of tables) {
|
|
260
|
-
|
|
261
|
-
|
|
459
|
+
etypes.push(table.name.substr((this.prefix + 'entities_').length));
|
|
460
|
+
}
|
|
461
|
+
return etypes;
|
|
462
|
+
}
|
|
463
|
+
async *exportDataIterator() {
|
|
464
|
+
if (yield {
|
|
465
|
+
type: 'comment',
|
|
466
|
+
content: `#nex2
|
|
467
|
+
# Nymph Entity Exchange v2
|
|
468
|
+
# http://nymph.io
|
|
469
|
+
#
|
|
470
|
+
# Generation Time: ${new Date().toLocaleString()}
|
|
471
|
+
`,
|
|
472
|
+
}) {
|
|
473
|
+
return;
|
|
474
|
+
}
|
|
475
|
+
if (yield {
|
|
476
|
+
type: 'comment',
|
|
477
|
+
content: `
|
|
478
|
+
|
|
479
|
+
#
|
|
480
|
+
# UIDs
|
|
481
|
+
#
|
|
482
|
+
|
|
483
|
+
`,
|
|
484
|
+
}) {
|
|
485
|
+
return;
|
|
486
|
+
}
|
|
487
|
+
// Export UIDs.
|
|
488
|
+
let uids = this.queryArray(`SELECT * FROM ${SQLite3Driver.escape(`${this.prefix}uids`)} ORDER BY "name";`);
|
|
489
|
+
for (const uid of uids) {
|
|
490
|
+
if (yield { type: 'uid', content: `<${uid.name}>[${uid.cur_uid}]\n` }) {
|
|
491
|
+
return;
|
|
262
492
|
}
|
|
263
493
|
}
|
|
494
|
+
if (yield {
|
|
495
|
+
type: 'comment',
|
|
496
|
+
content: `
|
|
497
|
+
|
|
498
|
+
#
|
|
499
|
+
# Entities
|
|
500
|
+
#
|
|
501
|
+
|
|
502
|
+
`,
|
|
503
|
+
}) {
|
|
504
|
+
return;
|
|
505
|
+
}
|
|
506
|
+
// Get the etypes.
|
|
507
|
+
const etypes = await this.getEtypes();
|
|
264
508
|
for (const etype of etypes) {
|
|
265
|
-
|
|
509
|
+
// Export entities.
|
|
510
|
+
const dataIterator = this.queryArray(`SELECT e."guid", e."tags", e."cdate", e."mdate", e."user", e."group", e."acUser", e."acGroup", e."acOther", e."acRead", e."acWrite", e."acFull", 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]();
|
|
266
511
|
let datum = dataIterator.next();
|
|
267
512
|
while (!datum.done) {
|
|
268
513
|
const guid = datum.value.guid;
|
|
269
514
|
const tags = datum.value.tags.slice(1, -1);
|
|
270
515
|
const cdate = datum.value.cdate;
|
|
271
516
|
const mdate = datum.value.mdate;
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
517
|
+
const user = datum.value.user;
|
|
518
|
+
const group = datum.value.group;
|
|
519
|
+
const acUser = datum.value.acUser;
|
|
520
|
+
const acGroup = datum.value.acGroup;
|
|
521
|
+
const acOther = datum.value.acOther;
|
|
522
|
+
const acRead = datum.value.acRead?.slice(1, -1).split(',');
|
|
523
|
+
const acWrite = datum.value.acWrite?.slice(1, -1).split(',');
|
|
524
|
+
const acFull = datum.value.acFull?.slice(1, -1).split(',');
|
|
525
|
+
let currentEntityExport = [];
|
|
526
|
+
currentEntityExport.push(`{${guid}}<${etype}>[${tags}]`);
|
|
527
|
+
currentEntityExport.push(`\tcdate=${JSON.stringify(cdate)}`);
|
|
528
|
+
currentEntityExport.push(`\tmdate=${JSON.stringify(mdate)}`);
|
|
529
|
+
if (this.nymph.tilmeld != null) {
|
|
530
|
+
if (user != null) {
|
|
531
|
+
currentEntityExport.push(`\tuser=${JSON.stringify(['nymph_entity_reference', user, 'User'])}`);
|
|
532
|
+
}
|
|
533
|
+
if (group != null) {
|
|
534
|
+
currentEntityExport.push(`\tgroup=${JSON.stringify(['nymph_entity_reference', group, 'Group'])}`);
|
|
535
|
+
}
|
|
536
|
+
if (acUser != null) {
|
|
537
|
+
currentEntityExport.push(`\tacUser=${JSON.stringify(acUser)}`);
|
|
538
|
+
}
|
|
539
|
+
if (acGroup != null) {
|
|
540
|
+
currentEntityExport.push(`\tacGroup=${JSON.stringify(acGroup)}`);
|
|
541
|
+
}
|
|
542
|
+
if (acOther != null) {
|
|
543
|
+
currentEntityExport.push(`\tacOther=${JSON.stringify(acOther)}`);
|
|
544
|
+
}
|
|
545
|
+
if (acRead != null) {
|
|
546
|
+
currentEntityExport.push(`\tacRead=${JSON.stringify(acRead)}`);
|
|
547
|
+
}
|
|
548
|
+
if (acWrite != null) {
|
|
549
|
+
currentEntityExport.push(`\tacWrite=${JSON.stringify(acWrite)}`);
|
|
550
|
+
}
|
|
551
|
+
if (acFull != null) {
|
|
552
|
+
currentEntityExport.push(`\tacFull=${JSON.stringify(acFull)}`);
|
|
553
|
+
}
|
|
554
|
+
}
|
|
555
|
+
if (datum.value.name != null) {
|
|
556
|
+
// This do will keep going and adding the data until the
|
|
557
|
+
// next entity is reached. datum will end on the next entity.
|
|
276
558
|
do {
|
|
277
|
-
const value = datum.value.
|
|
559
|
+
const value = datum.value.value === 'N'
|
|
278
560
|
? JSON.stringify(datum.value.number)
|
|
279
|
-
: datum.value.
|
|
561
|
+
: datum.value.value === 'S'
|
|
280
562
|
? JSON.stringify(datum.value.string)
|
|
281
|
-
: datum.value.
|
|
282
|
-
|
|
563
|
+
: datum.value.value === 'J'
|
|
564
|
+
? datum.value.json
|
|
565
|
+
: datum.value.value;
|
|
566
|
+
currentEntityExport.push(`\t${datum.value.name}=${value}`);
|
|
283
567
|
datum = dataIterator.next();
|
|
284
568
|
} while (!datum.done && datum.value.guid === guid);
|
|
285
569
|
}
|
|
286
570
|
else {
|
|
571
|
+
// Make sure that datum is incremented :)
|
|
287
572
|
datum = dataIterator.next();
|
|
288
573
|
}
|
|
574
|
+
currentEntityExport.push('');
|
|
575
|
+
if (yield { type: 'entity', content: currentEntityExport.join('\n') }) {
|
|
576
|
+
return;
|
|
577
|
+
}
|
|
289
578
|
}
|
|
290
579
|
}
|
|
291
|
-
return;
|
|
292
580
|
}
|
|
293
|
-
|
|
581
|
+
/**
|
|
582
|
+
* Generate the SQLite3 query.
|
|
583
|
+
* @param options The options array.
|
|
584
|
+
* @param formattedSelectors The formatted selector array.
|
|
585
|
+
* @param etype
|
|
586
|
+
* @param count Used to track internal params.
|
|
587
|
+
* @param params Used to store internal params.
|
|
588
|
+
* @param subquery Whether only a subquery should be returned.
|
|
589
|
+
* @returns The SQL query.
|
|
590
|
+
*/
|
|
591
|
+
makeEntityQuery(options, formattedSelectors, etype, count = { i: 0 }, params = {}, subquery = false, tableSuffix = '', etypes = [], guidSelector = undefined) {
|
|
294
592
|
if (typeof options.class?.alterOptions === 'function') {
|
|
295
593
|
options = options.class.alterOptions(options);
|
|
296
594
|
}
|
|
297
595
|
const eTable = `e${tableSuffix}`;
|
|
298
596
|
const dTable = `d${tableSuffix}`;
|
|
299
|
-
const cTable = `c${tableSuffix}`;
|
|
300
597
|
const fTable = `f${tableSuffix}`;
|
|
301
598
|
const ieTable = `ie${tableSuffix}`;
|
|
302
|
-
const
|
|
303
|
-
const
|
|
599
|
+
const sTable = `s${tableSuffix}`;
|
|
600
|
+
const sort = options.sort === undefined ? 'cdate' : options.sort;
|
|
601
|
+
const queryParts = this.iterateSelectorsForQuery(formattedSelectors, ({ key, value, typeIsOr, typeIsNot }) => {
|
|
304
602
|
const clauseNot = key.startsWith('!');
|
|
305
603
|
let curQuery = '';
|
|
306
604
|
for (const curValue of value) {
|
|
@@ -313,7 +611,7 @@ class SQLite3Driver extends nymph_1.NymphDriver {
|
|
|
313
611
|
}
|
|
314
612
|
const guid = `param${++count.i}`;
|
|
315
613
|
curQuery +=
|
|
316
|
-
(
|
|
614
|
+
(xor(typeIsNot, clauseNot) ? 'NOT ' : '') +
|
|
317
615
|
ieTable +
|
|
318
616
|
'."guid"=@' +
|
|
319
617
|
guid;
|
|
@@ -328,7 +626,7 @@ class SQLite3Driver extends nymph_1.NymphDriver {
|
|
|
328
626
|
}
|
|
329
627
|
const tag = `param${++count.i}`;
|
|
330
628
|
curQuery +=
|
|
331
|
-
(
|
|
629
|
+
(xor(typeIsNot, clauseNot) ? 'NOT ' : '') +
|
|
332
630
|
ieTable +
|
|
333
631
|
'."tags" LIKE @' +
|
|
334
632
|
tag +
|
|
@@ -348,17 +646,38 @@ class SQLite3Driver extends nymph_1.NymphDriver {
|
|
|
348
646
|
if (curQuery) {
|
|
349
647
|
curQuery += typeIsOr ? ' OR ' : ' AND ';
|
|
350
648
|
}
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
649
|
+
if (curVar === 'cdate' ||
|
|
650
|
+
curVar === 'mdate' ||
|
|
651
|
+
(this.nymph.tilmeld != null &&
|
|
652
|
+
(curVar === 'user' ||
|
|
653
|
+
curVar === 'group' ||
|
|
654
|
+
curVar === 'acUser' ||
|
|
655
|
+
curVar === 'acGroup' ||
|
|
656
|
+
curVar === 'acOther' ||
|
|
657
|
+
curVar === 'acRead' ||
|
|
658
|
+
curVar === 'acWrite' ||
|
|
659
|
+
curVar === 'acFull'))) {
|
|
660
|
+
curQuery +=
|
|
661
|
+
(xor(typeIsNot, clauseNot) ? 'NOT ' : '') +
|
|
662
|
+
'(' +
|
|
663
|
+
ieTable +
|
|
664
|
+
'.' +
|
|
665
|
+
SQLite3Driver.escape(curVar) +
|
|
666
|
+
' IS NOT NULL)';
|
|
667
|
+
}
|
|
668
|
+
else {
|
|
669
|
+
const name = `param${++count.i}`;
|
|
670
|
+
curQuery +=
|
|
671
|
+
ieTable +
|
|
672
|
+
'."guid" ' +
|
|
673
|
+
(xor(typeIsNot, clauseNot) ? 'NOT ' : '') +
|
|
674
|
+
'IN (SELECT "guid" FROM ' +
|
|
675
|
+
SQLite3Driver.escape(this.prefix + 'data_' + etype) +
|
|
676
|
+
' WHERE "name"=@' +
|
|
677
|
+
name +
|
|
678
|
+
')';
|
|
679
|
+
params[name] = curVar;
|
|
680
|
+
}
|
|
362
681
|
}
|
|
363
682
|
break;
|
|
364
683
|
case 'truthy':
|
|
@@ -367,30 +686,34 @@ class SQLite3Driver extends nymph_1.NymphDriver {
|
|
|
367
686
|
if (curQuery) {
|
|
368
687
|
curQuery += typeIsOr ? ' OR ' : ' AND ';
|
|
369
688
|
}
|
|
370
|
-
if (curVar === 'cdate'
|
|
689
|
+
if (curVar === 'cdate' ||
|
|
690
|
+
curVar === 'mdate' ||
|
|
691
|
+
(this.nymph.tilmeld != null &&
|
|
692
|
+
(curVar === 'user' ||
|
|
693
|
+
curVar === 'group' ||
|
|
694
|
+
curVar === 'acUser' ||
|
|
695
|
+
curVar === 'acGroup' ||
|
|
696
|
+
curVar === 'acOther' ||
|
|
697
|
+
curVar === 'acRead' ||
|
|
698
|
+
curVar === 'acWrite' ||
|
|
699
|
+
curVar === 'acFull'))) {
|
|
371
700
|
curQuery +=
|
|
372
|
-
(
|
|
701
|
+
(xor(typeIsNot, clauseNot) ? 'NOT ' : '') +
|
|
373
702
|
'(' +
|
|
374
703
|
ieTable +
|
|
375
|
-
'.
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
else if (curVar === 'mdate') {
|
|
379
|
-
curQuery +=
|
|
380
|
-
((0, nymph_1.xor)(typeIsNot, clauseNot) ? 'NOT ' : '') +
|
|
381
|
-
'(' +
|
|
382
|
-
ieTable +
|
|
383
|
-
'."mdate" NOT NULL)';
|
|
384
|
-
break;
|
|
704
|
+
'.' +
|
|
705
|
+
SQLite3Driver.escape(curVar) +
|
|
706
|
+
' IS NOT NULL)';
|
|
385
707
|
}
|
|
386
708
|
else {
|
|
387
709
|
const name = `param${++count.i}`;
|
|
388
710
|
curQuery +=
|
|
389
|
-
(
|
|
711
|
+
(xor(typeIsNot, clauseNot) ? 'NOT ' : '') +
|
|
712
|
+
'EXISTS (SELECT "guid" FROM ' +
|
|
713
|
+
SQLite3Driver.escape(this.prefix + 'data_' + etype) +
|
|
714
|
+
' WHERE "guid"=' +
|
|
390
715
|
ieTable +
|
|
391
|
-
'."guid"
|
|
392
|
-
SQLite3Driver.escape(this.prefix + 'comparisons_' + etype) +
|
|
393
|
-
' WHERE "name"=@' +
|
|
716
|
+
'."guid" AND "name"=@' +
|
|
394
717
|
name +
|
|
395
718
|
' AND "truthy"=1)';
|
|
396
719
|
params[name] = curVar;
|
|
@@ -399,31 +722,58 @@ class SQLite3Driver extends nymph_1.NymphDriver {
|
|
|
399
722
|
break;
|
|
400
723
|
case 'equal':
|
|
401
724
|
case '!equal':
|
|
402
|
-
if (curValue[0] === 'cdate'
|
|
725
|
+
if (curValue[0] === 'cdate' ||
|
|
726
|
+
curValue[0] === 'mdate' ||
|
|
727
|
+
(this.nymph.tilmeld != null &&
|
|
728
|
+
(curValue[0] === 'acUser' ||
|
|
729
|
+
curValue[0] === 'acGroup' ||
|
|
730
|
+
curValue[0] === 'acOther'))) {
|
|
403
731
|
if (curQuery) {
|
|
404
732
|
curQuery += typeIsOr ? ' OR ' : ' AND ';
|
|
405
733
|
}
|
|
406
|
-
const
|
|
734
|
+
const value = `param${++count.i}`;
|
|
407
735
|
curQuery +=
|
|
408
|
-
(
|
|
736
|
+
(xor(typeIsNot, clauseNot) ? 'NOT ' : '') +
|
|
409
737
|
ieTable +
|
|
410
|
-
'.
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
738
|
+
'.' +
|
|
739
|
+
SQLite3Driver.escape(curValue[0]) +
|
|
740
|
+
'=@' +
|
|
741
|
+
value;
|
|
742
|
+
params[value] = Number(curValue[1]);
|
|
414
743
|
}
|
|
415
|
-
else if (
|
|
744
|
+
else if (this.nymph.tilmeld != null &&
|
|
745
|
+
(curValue[0] === 'user' || curValue[0] === 'group')) {
|
|
416
746
|
if (curQuery) {
|
|
417
747
|
curQuery += typeIsOr ? ' OR ' : ' AND ';
|
|
418
748
|
}
|
|
419
|
-
const
|
|
749
|
+
const value = `param${++count.i}`;
|
|
420
750
|
curQuery +=
|
|
421
|
-
(
|
|
751
|
+
(xor(typeIsNot, clauseNot) ? 'NOT ' : '') +
|
|
422
752
|
ieTable +
|
|
423
|
-
'.
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
753
|
+
'.' +
|
|
754
|
+
SQLite3Driver.escape(curValue[0]) +
|
|
755
|
+
'=@' +
|
|
756
|
+
value;
|
|
757
|
+
params[value] = `${curValue[1]}`;
|
|
758
|
+
}
|
|
759
|
+
else if (this.nymph.tilmeld != null &&
|
|
760
|
+
(curValue[0] === 'acRead' ||
|
|
761
|
+
curValue[0] === 'acWrite' ||
|
|
762
|
+
curValue[0] === 'acFull')) {
|
|
763
|
+
if (curQuery) {
|
|
764
|
+
curQuery += typeIsOr ? ' OR ' : ' AND ';
|
|
765
|
+
}
|
|
766
|
+
const value = `param${++count.i}`;
|
|
767
|
+
curQuery +=
|
|
768
|
+
(xor(typeIsNot, clauseNot) ? 'NOT ' : '') +
|
|
769
|
+
ieTable +
|
|
770
|
+
'.' +
|
|
771
|
+
SQLite3Driver.escape(curValue[0]) +
|
|
772
|
+
'=@' +
|
|
773
|
+
value;
|
|
774
|
+
params[value] = Array.isArray(curValue[1])
|
|
775
|
+
? ',' + curValue[1].join(',') + ','
|
|
776
|
+
: '';
|
|
427
777
|
}
|
|
428
778
|
else if (typeof curValue[1] === 'number') {
|
|
429
779
|
if (curQuery) {
|
|
@@ -432,11 +782,12 @@ class SQLite3Driver extends nymph_1.NymphDriver {
|
|
|
432
782
|
const name = `param${++count.i}`;
|
|
433
783
|
const value = `param${++count.i}`;
|
|
434
784
|
curQuery +=
|
|
435
|
-
(
|
|
785
|
+
(xor(typeIsNot, clauseNot) ? 'NOT ' : '') +
|
|
786
|
+
'EXISTS (SELECT "guid" FROM ' +
|
|
787
|
+
SQLite3Driver.escape(this.prefix + 'data_' + etype) +
|
|
788
|
+
' WHERE "guid"=' +
|
|
436
789
|
ieTable +
|
|
437
|
-
'."guid"
|
|
438
|
-
SQLite3Driver.escape(this.prefix + 'comparisons_' + etype) +
|
|
439
|
-
' WHERE "name"=@' +
|
|
790
|
+
'."guid" AND "name"=@' +
|
|
440
791
|
name +
|
|
441
792
|
' AND "number"=@' +
|
|
442
793
|
value +
|
|
@@ -451,11 +802,12 @@ class SQLite3Driver extends nymph_1.NymphDriver {
|
|
|
451
802
|
const name = `param${++count.i}`;
|
|
452
803
|
const value = `param${++count.i}`;
|
|
453
804
|
curQuery +=
|
|
454
|
-
(
|
|
805
|
+
(xor(typeIsNot, clauseNot) ? 'NOT ' : '') +
|
|
806
|
+
'EXISTS (SELECT "guid" FROM ' +
|
|
807
|
+
SQLite3Driver.escape(this.prefix + 'data_' + etype) +
|
|
808
|
+
' WHERE "guid"=' +
|
|
455
809
|
ieTable +
|
|
456
|
-
'."guid"
|
|
457
|
-
SQLite3Driver.escape(this.prefix + 'comparisons_' + etype) +
|
|
458
|
-
' WHERE "name"=@' +
|
|
810
|
+
'."guid" AND "name"=@' +
|
|
459
811
|
name +
|
|
460
812
|
' AND "string"=@' +
|
|
461
813
|
value +
|
|
@@ -478,134 +830,273 @@ class SQLite3Driver extends nymph_1.NymphDriver {
|
|
|
478
830
|
const name = `param${++count.i}`;
|
|
479
831
|
const value = `param${++count.i}`;
|
|
480
832
|
curQuery +=
|
|
481
|
-
(
|
|
482
|
-
|
|
483
|
-
'."guid" IN (SELECT "guid" FROM ' +
|
|
833
|
+
(xor(typeIsNot, clauseNot) ? 'NOT ' : '') +
|
|
834
|
+
'EXISTS (SELECT "guid" FROM ' +
|
|
484
835
|
SQLite3Driver.escape(this.prefix + 'data_' + etype) +
|
|
485
|
-
' WHERE "
|
|
836
|
+
' WHERE "guid"=' +
|
|
837
|
+
ieTable +
|
|
838
|
+
'."guid" AND "name"=@' +
|
|
486
839
|
name +
|
|
487
|
-
' AND "
|
|
840
|
+
' AND "json"=jsonb(@' +
|
|
488
841
|
value +
|
|
489
|
-
')';
|
|
842
|
+
'))';
|
|
490
843
|
params[name] = curValue[0];
|
|
491
844
|
params[value] = svalue;
|
|
492
845
|
}
|
|
493
846
|
break;
|
|
494
847
|
case 'contain':
|
|
495
848
|
case '!contain':
|
|
496
|
-
if (curValue[0] === 'cdate'
|
|
849
|
+
if (curValue[0] === 'cdate' ||
|
|
850
|
+
curValue[0] === 'mdate' ||
|
|
851
|
+
(this.nymph.tilmeld != null &&
|
|
852
|
+
(curValue[0] === 'acUser' ||
|
|
853
|
+
curValue[0] === 'acGroup' ||
|
|
854
|
+
curValue[0] === 'acOther'))) {
|
|
497
855
|
if (curQuery) {
|
|
498
856
|
curQuery += typeIsOr ? ' OR ' : ' AND ';
|
|
499
857
|
}
|
|
500
|
-
const
|
|
858
|
+
const value = `param${++count.i}`;
|
|
501
859
|
curQuery +=
|
|
502
|
-
(
|
|
860
|
+
(xor(typeIsNot, clauseNot) ? 'NOT ' : '') +
|
|
503
861
|
ieTable +
|
|
504
|
-
'.
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
862
|
+
'.' +
|
|
863
|
+
SQLite3Driver.escape(curValue[0]) +
|
|
864
|
+
'=@' +
|
|
865
|
+
value;
|
|
866
|
+
params[value] = Number(curValue[1]);
|
|
508
867
|
}
|
|
509
|
-
else if (
|
|
868
|
+
else if (this.nymph.tilmeld != null &&
|
|
869
|
+
(curValue[0] === 'user' || curValue[0] === 'group')) {
|
|
510
870
|
if (curQuery) {
|
|
511
871
|
curQuery += typeIsOr ? ' OR ' : ' AND ';
|
|
512
872
|
}
|
|
513
|
-
const
|
|
873
|
+
const value = `param${++count.i}`;
|
|
514
874
|
curQuery +=
|
|
515
|
-
(
|
|
875
|
+
(xor(typeIsNot, clauseNot) ? 'NOT ' : '') +
|
|
516
876
|
ieTable +
|
|
517
|
-
'.
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
877
|
+
'.' +
|
|
878
|
+
SQLite3Driver.escape(curValue[0]) +
|
|
879
|
+
'=@' +
|
|
880
|
+
value;
|
|
881
|
+
params[value] = `${curValue[1]}`;
|
|
882
|
+
}
|
|
883
|
+
else if (this.nymph.tilmeld != null &&
|
|
884
|
+
(curValue[0] === 'acRead' ||
|
|
885
|
+
curValue[0] === 'acWrite' ||
|
|
886
|
+
curValue[0] === 'acFull')) {
|
|
887
|
+
if (curQuery) {
|
|
888
|
+
curQuery += typeIsOr ? ' OR ' : ' AND ';
|
|
889
|
+
}
|
|
890
|
+
const id = `param${++count.i}`;
|
|
891
|
+
curQuery +=
|
|
892
|
+
(xor(typeIsNot, clauseNot) ? 'NOT ' : '') +
|
|
893
|
+
ieTable +
|
|
894
|
+
'.' +
|
|
895
|
+
SQLite3Driver.escape(curValue[0]) +
|
|
896
|
+
' LIKE @' +
|
|
897
|
+
id +
|
|
898
|
+
" ESCAPE '\\'";
|
|
899
|
+
params[id] =
|
|
900
|
+
'%,' +
|
|
901
|
+
curValue[1]
|
|
902
|
+
.replace('\\', '\\\\')
|
|
903
|
+
.replace('%', '\\%')
|
|
904
|
+
.replace('_', '\\_') +
|
|
905
|
+
',%';
|
|
521
906
|
}
|
|
522
907
|
else {
|
|
908
|
+
const containTableSuffix = makeTableSuffix();
|
|
523
909
|
if (curQuery) {
|
|
524
910
|
curQuery += typeIsOr ? ' OR ' : ' AND ';
|
|
525
911
|
}
|
|
526
912
|
let svalue;
|
|
527
|
-
let stringValue;
|
|
528
913
|
if (curValue[1] instanceof Object &&
|
|
529
914
|
typeof curValue[1].toReference === 'function') {
|
|
530
915
|
svalue = JSON.stringify(curValue[1].toReference());
|
|
531
|
-
stringValue = `${curValue[1].toReference()}`;
|
|
532
916
|
}
|
|
533
917
|
else {
|
|
534
918
|
svalue = JSON.stringify(curValue[1]);
|
|
535
|
-
stringValue = `${curValue[1]}`;
|
|
536
919
|
}
|
|
537
920
|
const name = `param${++count.i}`;
|
|
538
921
|
const value = `param${++count.i}`;
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
(
|
|
543
|
-
|
|
922
|
+
curQuery +=
|
|
923
|
+
(xor(typeIsNot, clauseNot) ? 'NOT ' : '') +
|
|
924
|
+
'EXISTS (SELECT "guid" FROM ' +
|
|
925
|
+
SQLite3Driver.escape(this.prefix + 'data_' + etype) +
|
|
926
|
+
' d' +
|
|
927
|
+
containTableSuffix +
|
|
928
|
+
' WHERE "guid"=' +
|
|
929
|
+
ieTable +
|
|
930
|
+
'."guid" AND "name"=@' +
|
|
931
|
+
name +
|
|
932
|
+
' AND json(@' +
|
|
933
|
+
value +
|
|
934
|
+
') IN (SELECT json_quote("value") FROM json_each(d' +
|
|
935
|
+
containTableSuffix +
|
|
936
|
+
'."json")))';
|
|
937
|
+
params[name] = curValue[0];
|
|
938
|
+
params[value] = svalue;
|
|
939
|
+
}
|
|
940
|
+
break;
|
|
941
|
+
case 'search':
|
|
942
|
+
case '!search':
|
|
943
|
+
if (curValue[0] === 'cdate' ||
|
|
944
|
+
curValue[0] === 'mdate' ||
|
|
945
|
+
(this.nymph.tilmeld != null &&
|
|
946
|
+
(curValue[0] === 'user' ||
|
|
947
|
+
curValue[0] === 'group' ||
|
|
948
|
+
curValue[0] === 'acUser' ||
|
|
949
|
+
curValue[0] === 'acGroup' ||
|
|
950
|
+
curValue[0] === 'acOther' ||
|
|
951
|
+
curValue[0] === 'acRead' ||
|
|
952
|
+
curValue[0] === 'acWrite' ||
|
|
953
|
+
curValue[0] === 'acFull'))) {
|
|
954
|
+
if (curQuery) {
|
|
955
|
+
curQuery += typeIsOr ? ' OR ' : ' AND ';
|
|
956
|
+
}
|
|
957
|
+
curQuery += (xor(typeIsNot, clauseNot) ? 'NOT ' : '') + '(0)';
|
|
958
|
+
}
|
|
959
|
+
else {
|
|
960
|
+
if (curQuery) {
|
|
961
|
+
curQuery += typeIsOr ? ' OR ' : ' AND ';
|
|
962
|
+
}
|
|
963
|
+
const parsedFTSQuery = this.tokenizer.parseSearchQuery(curValue[1]);
|
|
964
|
+
if (!parsedFTSQuery.length) {
|
|
965
|
+
curQuery += (xor(typeIsNot, clauseNot) ? 'NOT ' : '') + '(0)';
|
|
966
|
+
}
|
|
967
|
+
else {
|
|
968
|
+
const name = `param${++count.i}`;
|
|
969
|
+
const queryPartToken = (term) => {
|
|
970
|
+
const value = `param${++count.i}`;
|
|
971
|
+
params[value] = term.token;
|
|
972
|
+
return ('EXISTS (SELECT "guid" FROM ' +
|
|
973
|
+
SQLite3Driver.escape(this.prefix + 'tokens_' + etype) +
|
|
974
|
+
' WHERE "guid"=' +
|
|
544
975
|
ieTable +
|
|
545
|
-
'."guid"
|
|
546
|
-
SQLite3Driver.escape(this.prefix + 'data_' + etype) +
|
|
547
|
-
' WHERE "name"=@' +
|
|
976
|
+
'."guid" AND "name"=@' +
|
|
548
977
|
name +
|
|
549
|
-
' AND
|
|
978
|
+
' AND "token"=@' +
|
|
550
979
|
value +
|
|
551
|
-
'
|
|
980
|
+
(term.nostemmed ? ' AND "stem"=0' : '') +
|
|
981
|
+
')');
|
|
982
|
+
};
|
|
983
|
+
const queryPartSeries = (series) => {
|
|
984
|
+
const tokenTableSuffix = makeTableSuffix();
|
|
985
|
+
const tokenParts = series.tokens.map((token, i) => {
|
|
986
|
+
const value = `param${++count.i}`;
|
|
987
|
+
params[value] = token.token;
|
|
988
|
+
return {
|
|
989
|
+
fromClause: i === 0
|
|
990
|
+
? 'FROM ' +
|
|
991
|
+
SQLite3Driver.escape(this.prefix + 'tokens_' + etype) +
|
|
992
|
+
' t' +
|
|
993
|
+
tokenTableSuffix +
|
|
994
|
+
'0'
|
|
995
|
+
: 'JOIN ' +
|
|
996
|
+
SQLite3Driver.escape(this.prefix + 'tokens_' + etype) +
|
|
997
|
+
' t' +
|
|
998
|
+
tokenTableSuffix +
|
|
999
|
+
i +
|
|
1000
|
+
' ON t' +
|
|
1001
|
+
tokenTableSuffix +
|
|
1002
|
+
i +
|
|
1003
|
+
'."guid" = t' +
|
|
1004
|
+
tokenTableSuffix +
|
|
1005
|
+
'0."guid" AND t' +
|
|
1006
|
+
tokenTableSuffix +
|
|
1007
|
+
i +
|
|
1008
|
+
'."name" = t' +
|
|
1009
|
+
tokenTableSuffix +
|
|
1010
|
+
'0."name" AND t' +
|
|
1011
|
+
tokenTableSuffix +
|
|
1012
|
+
i +
|
|
1013
|
+
'."position" = t' +
|
|
1014
|
+
tokenTableSuffix +
|
|
1015
|
+
'0."position" + ' +
|
|
1016
|
+
i,
|
|
1017
|
+
whereClause: 't' +
|
|
1018
|
+
tokenTableSuffix +
|
|
1019
|
+
i +
|
|
1020
|
+
'."token"=@' +
|
|
1021
|
+
value +
|
|
1022
|
+
(token.nostemmed
|
|
1023
|
+
? ' AND t' + tokenTableSuffix + i + '."stem"=0'
|
|
1024
|
+
: ''),
|
|
1025
|
+
};
|
|
1026
|
+
});
|
|
1027
|
+
return ('EXISTS (SELECT t' +
|
|
1028
|
+
tokenTableSuffix +
|
|
1029
|
+
'0."guid" ' +
|
|
1030
|
+
tokenParts.map((part) => part.fromClause).join(' ') +
|
|
1031
|
+
' WHERE t' +
|
|
1032
|
+
tokenTableSuffix +
|
|
1033
|
+
'0."guid"=' +
|
|
552
1034
|
ieTable +
|
|
553
|
-
'."guid"
|
|
554
|
-
|
|
555
|
-
'
|
|
1035
|
+
'."guid" AND t' +
|
|
1036
|
+
tokenTableSuffix +
|
|
1037
|
+
'0."name"=@' +
|
|
556
1038
|
name +
|
|
557
|
-
' AND
|
|
558
|
-
|
|
559
|
-
'))
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
1039
|
+
' AND ' +
|
|
1040
|
+
tokenParts.map((part) => part.whereClause).join(' AND ') +
|
|
1041
|
+
')');
|
|
1042
|
+
};
|
|
1043
|
+
const queryPartTerm = (term) => {
|
|
1044
|
+
if (term.type === 'series') {
|
|
1045
|
+
return queryPartSeries(term);
|
|
1046
|
+
}
|
|
1047
|
+
else if (term.type === 'not') {
|
|
1048
|
+
return 'NOT ' + queryPartTerm(term.operand);
|
|
1049
|
+
}
|
|
1050
|
+
else if (term.type === 'or') {
|
|
1051
|
+
let queryParts = [];
|
|
1052
|
+
for (let operand of term.operands) {
|
|
1053
|
+
queryParts.push(queryPartTerm(operand));
|
|
1054
|
+
}
|
|
1055
|
+
return '(' + queryParts.join(' OR ') + ')';
|
|
1056
|
+
}
|
|
1057
|
+
return queryPartToken(term);
|
|
1058
|
+
};
|
|
1059
|
+
// Run through the query and add terms.
|
|
1060
|
+
let termStrings = [];
|
|
1061
|
+
for (let term of parsedFTSQuery) {
|
|
1062
|
+
termStrings.push(queryPartTerm(term));
|
|
1063
|
+
}
|
|
563
1064
|
curQuery +=
|
|
564
|
-
(
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
name +
|
|
570
|
-
' AND instr("value", @' +
|
|
571
|
-
value +
|
|
572
|
-
'))';
|
|
1065
|
+
(xor(typeIsNot, clauseNot) ? 'NOT ' : '') +
|
|
1066
|
+
'(' +
|
|
1067
|
+
termStrings.join(' AND ') +
|
|
1068
|
+
')';
|
|
1069
|
+
params[name] = curValue[0];
|
|
573
1070
|
}
|
|
574
|
-
params[name] = curValue[0];
|
|
575
|
-
params[value] = svalue;
|
|
576
1071
|
}
|
|
577
1072
|
break;
|
|
578
1073
|
case 'match':
|
|
579
1074
|
case '!match':
|
|
580
|
-
if (curValue[0] === 'cdate'
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
'
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
')';
|
|
592
|
-
params[cdate] = curValue[1];
|
|
593
|
-
break;
|
|
594
|
-
}
|
|
595
|
-
else if (curValue[0] === 'mdate') {
|
|
1075
|
+
if (curValue[0] === 'cdate' ||
|
|
1076
|
+
curValue[0] === 'mdate' ||
|
|
1077
|
+
(this.nymph.tilmeld != null &&
|
|
1078
|
+
(curValue[0] === 'user' ||
|
|
1079
|
+
curValue[0] === 'group' ||
|
|
1080
|
+
curValue[0] === 'acUser' ||
|
|
1081
|
+
curValue[0] === 'acGroup' ||
|
|
1082
|
+
curValue[0] === 'acOther' ||
|
|
1083
|
+
curValue[0] === 'acRead' ||
|
|
1084
|
+
curValue[0] === 'acWrite' ||
|
|
1085
|
+
curValue[0] === 'acFull'))) {
|
|
596
1086
|
if (curQuery) {
|
|
597
1087
|
curQuery += typeIsOr ? ' OR ' : ' AND ';
|
|
598
1088
|
}
|
|
599
|
-
const
|
|
1089
|
+
const value = `param${++count.i}`;
|
|
600
1090
|
curQuery +=
|
|
601
|
-
(
|
|
1091
|
+
(xor(typeIsNot, clauseNot) ? 'NOT ' : '') +
|
|
602
1092
|
'(' +
|
|
603
1093
|
ieTable +
|
|
604
|
-
'.
|
|
605
|
-
|
|
1094
|
+
'.' +
|
|
1095
|
+
SQLite3Driver.escape(curValue[0]) +
|
|
1096
|
+
' REGEXP @' +
|
|
1097
|
+
value +
|
|
606
1098
|
')';
|
|
607
|
-
params[
|
|
608
|
-
break;
|
|
1099
|
+
params[value] = curValue[1];
|
|
609
1100
|
}
|
|
610
1101
|
else {
|
|
611
1102
|
if (curQuery) {
|
|
@@ -614,11 +1105,12 @@ class SQLite3Driver extends nymph_1.NymphDriver {
|
|
|
614
1105
|
const name = `param${++count.i}`;
|
|
615
1106
|
const value = `param${++count.i}`;
|
|
616
1107
|
curQuery +=
|
|
617
|
-
(
|
|
1108
|
+
(xor(typeIsNot, clauseNot) ? 'NOT ' : '') +
|
|
1109
|
+
'EXISTS (SELECT "guid" FROM ' +
|
|
1110
|
+
SQLite3Driver.escape(this.prefix + 'data_' + etype) +
|
|
1111
|
+
' WHERE "guid"=' +
|
|
618
1112
|
ieTable +
|
|
619
|
-
'."guid"
|
|
620
|
-
SQLite3Driver.escape(this.prefix + 'comparisons_' + etype) +
|
|
621
|
-
' WHERE "name"=@' +
|
|
1113
|
+
'."guid" AND "name"=@' +
|
|
622
1114
|
name +
|
|
623
1115
|
' AND "string" REGEXP @' +
|
|
624
1116
|
value +
|
|
@@ -629,35 +1121,31 @@ class SQLite3Driver extends nymph_1.NymphDriver {
|
|
|
629
1121
|
break;
|
|
630
1122
|
case 'imatch':
|
|
631
1123
|
case '!imatch':
|
|
632
|
-
if (curValue[0] === 'cdate'
|
|
1124
|
+
if (curValue[0] === 'cdate' ||
|
|
1125
|
+
curValue[0] === 'mdate' ||
|
|
1126
|
+
(this.nymph.tilmeld != null &&
|
|
1127
|
+
(curValue[0] === 'user' ||
|
|
1128
|
+
curValue[0] === 'group' ||
|
|
1129
|
+
curValue[0] === 'acUser' ||
|
|
1130
|
+
curValue[0] === 'acGroup' ||
|
|
1131
|
+
curValue[0] === 'acOther' ||
|
|
1132
|
+
curValue[0] === 'acRead' ||
|
|
1133
|
+
curValue[0] === 'acWrite' ||
|
|
1134
|
+
curValue[0] === 'acFull'))) {
|
|
633
1135
|
if (curQuery) {
|
|
634
1136
|
curQuery += typeIsOr ? ' OR ' : ' AND ';
|
|
635
1137
|
}
|
|
636
|
-
const
|
|
637
|
-
curQuery +=
|
|
638
|
-
((0, nymph_1.xor)(typeIsNot, clauseNot) ? 'NOT ' : '') +
|
|
639
|
-
'(' +
|
|
640
|
-
ieTable +
|
|
641
|
-
'."cdate" REGEXP @' +
|
|
642
|
-
cdate +
|
|
643
|
-
')';
|
|
644
|
-
params[cdate] = curValue[1];
|
|
645
|
-
break;
|
|
646
|
-
}
|
|
647
|
-
else if (curValue[0] === 'mdate') {
|
|
648
|
-
if (curQuery) {
|
|
649
|
-
curQuery += typeIsOr ? ' OR ' : ' AND ';
|
|
650
|
-
}
|
|
651
|
-
const mdate = `param${++count.i}`;
|
|
1138
|
+
const value = `param${++count.i}`;
|
|
652
1139
|
curQuery +=
|
|
653
|
-
(
|
|
654
|
-
'(' +
|
|
1140
|
+
(xor(typeIsNot, clauseNot) ? 'NOT ' : '') +
|
|
1141
|
+
'(lower(' +
|
|
655
1142
|
ieTable +
|
|
656
|
-
'.
|
|
657
|
-
|
|
658
|
-
')'
|
|
659
|
-
|
|
660
|
-
|
|
1143
|
+
'.' +
|
|
1144
|
+
SQLite3Driver.escape(curValue[0]) +
|
|
1145
|
+
') REGEXP lower(@' +
|
|
1146
|
+
value +
|
|
1147
|
+
'))';
|
|
1148
|
+
params[value] = curValue[1];
|
|
661
1149
|
}
|
|
662
1150
|
else {
|
|
663
1151
|
if (curQuery) {
|
|
@@ -666,11 +1154,12 @@ class SQLite3Driver extends nymph_1.NymphDriver {
|
|
|
666
1154
|
const name = `param${++count.i}`;
|
|
667
1155
|
const value = `param${++count.i}`;
|
|
668
1156
|
curQuery +=
|
|
669
|
-
(
|
|
1157
|
+
(xor(typeIsNot, clauseNot) ? 'NOT ' : '') +
|
|
1158
|
+
'EXISTS (SELECT "guid" FROM ' +
|
|
1159
|
+
SQLite3Driver.escape(this.prefix + 'data_' + etype) +
|
|
1160
|
+
' WHERE "guid"=' +
|
|
670
1161
|
ieTable +
|
|
671
|
-
'."guid"
|
|
672
|
-
SQLite3Driver.escape(this.prefix + 'comparisons_' + etype) +
|
|
673
|
-
' WHERE "name"=@' +
|
|
1162
|
+
'."guid" AND "name"=@' +
|
|
674
1163
|
name +
|
|
675
1164
|
' AND lower("string") REGEXP lower(@' +
|
|
676
1165
|
value +
|
|
@@ -681,35 +1170,31 @@ class SQLite3Driver extends nymph_1.NymphDriver {
|
|
|
681
1170
|
break;
|
|
682
1171
|
case 'like':
|
|
683
1172
|
case '!like':
|
|
684
|
-
if (curValue[0] === 'cdate'
|
|
1173
|
+
if (curValue[0] === 'cdate' ||
|
|
1174
|
+
curValue[0] === 'mdate' ||
|
|
1175
|
+
(this.nymph.tilmeld != null &&
|
|
1176
|
+
(curValue[0] === 'user' ||
|
|
1177
|
+
curValue[0] === 'group' ||
|
|
1178
|
+
curValue[0] === 'acUser' ||
|
|
1179
|
+
curValue[0] === 'acGroup' ||
|
|
1180
|
+
curValue[0] === 'acOther' ||
|
|
1181
|
+
curValue[0] === 'acRead' ||
|
|
1182
|
+
curValue[0] === 'acWrite' ||
|
|
1183
|
+
curValue[0] === 'acFull'))) {
|
|
685
1184
|
if (curQuery) {
|
|
686
1185
|
curQuery += typeIsOr ? ' OR ' : ' AND ';
|
|
687
1186
|
}
|
|
688
|
-
const
|
|
689
|
-
curQuery +=
|
|
690
|
-
((0, nymph_1.xor)(typeIsNot, clauseNot) ? 'NOT ' : '') +
|
|
691
|
-
'(' +
|
|
692
|
-
ieTable +
|
|
693
|
-
'."cdate" LIKE @' +
|
|
694
|
-
cdate +
|
|
695
|
-
" ESCAPE '\\')";
|
|
696
|
-
params[cdate] = curValue[1];
|
|
697
|
-
break;
|
|
698
|
-
}
|
|
699
|
-
else if (curValue[0] === 'mdate') {
|
|
700
|
-
if (curQuery) {
|
|
701
|
-
curQuery += typeIsOr ? ' OR ' : ' AND ';
|
|
702
|
-
}
|
|
703
|
-
const mdate = `param${++count.i}`;
|
|
1187
|
+
const value = `param${++count.i}`;
|
|
704
1188
|
curQuery +=
|
|
705
|
-
(
|
|
1189
|
+
(xor(typeIsNot, clauseNot) ? 'NOT ' : '') +
|
|
706
1190
|
'(' +
|
|
707
1191
|
ieTable +
|
|
708
|
-
'.
|
|
709
|
-
|
|
1192
|
+
'.' +
|
|
1193
|
+
SQLite3Driver.escape(curValue[0]) +
|
|
1194
|
+
' LIKE @' +
|
|
1195
|
+
value +
|
|
710
1196
|
" ESCAPE '\\')";
|
|
711
|
-
params[
|
|
712
|
-
break;
|
|
1197
|
+
params[value] = curValue[1];
|
|
713
1198
|
}
|
|
714
1199
|
else {
|
|
715
1200
|
if (curQuery) {
|
|
@@ -718,11 +1203,12 @@ class SQLite3Driver extends nymph_1.NymphDriver {
|
|
|
718
1203
|
const name = `param${++count.i}`;
|
|
719
1204
|
const value = `param${++count.i}`;
|
|
720
1205
|
curQuery +=
|
|
721
|
-
(
|
|
1206
|
+
(xor(typeIsNot, clauseNot) ? 'NOT ' : '') +
|
|
1207
|
+
'EXISTS (SELECT "guid" FROM ' +
|
|
1208
|
+
SQLite3Driver.escape(this.prefix + 'data_' + etype) +
|
|
1209
|
+
' WHERE "guid"=' +
|
|
722
1210
|
ieTable +
|
|
723
|
-
'."guid"
|
|
724
|
-
SQLite3Driver.escape(this.prefix + 'comparisons_' + etype) +
|
|
725
|
-
' WHERE "name"=@' +
|
|
1211
|
+
'."guid" AND "name"=@' +
|
|
726
1212
|
name +
|
|
727
1213
|
' AND "string" LIKE @' +
|
|
728
1214
|
value +
|
|
@@ -733,35 +1219,31 @@ class SQLite3Driver extends nymph_1.NymphDriver {
|
|
|
733
1219
|
break;
|
|
734
1220
|
case 'ilike':
|
|
735
1221
|
case '!ilike':
|
|
736
|
-
if (curValue[0] === 'cdate'
|
|
1222
|
+
if (curValue[0] === 'cdate' ||
|
|
1223
|
+
curValue[0] === 'mdate' ||
|
|
1224
|
+
(this.nymph.tilmeld != null &&
|
|
1225
|
+
(curValue[0] === 'user' ||
|
|
1226
|
+
curValue[0] === 'group' ||
|
|
1227
|
+
curValue[0] === 'acUser' ||
|
|
1228
|
+
curValue[0] === 'acGroup' ||
|
|
1229
|
+
curValue[0] === 'acOther' ||
|
|
1230
|
+
curValue[0] === 'acRead' ||
|
|
1231
|
+
curValue[0] === 'acWrite' ||
|
|
1232
|
+
curValue[0] === 'acFull'))) {
|
|
737
1233
|
if (curQuery) {
|
|
738
1234
|
curQuery += typeIsOr ? ' OR ' : ' AND ';
|
|
739
1235
|
}
|
|
740
|
-
const
|
|
741
|
-
curQuery +=
|
|
742
|
-
((0, nymph_1.xor)(typeIsNot, clauseNot) ? 'NOT ' : '') +
|
|
743
|
-
'(' +
|
|
744
|
-
ieTable +
|
|
745
|
-
'."cdate" LIKE @' +
|
|
746
|
-
cdate +
|
|
747
|
-
" ESCAPE '\\')";
|
|
748
|
-
params[cdate] = curValue[1];
|
|
749
|
-
break;
|
|
750
|
-
}
|
|
751
|
-
else if (curValue[0] === 'mdate') {
|
|
752
|
-
if (curQuery) {
|
|
753
|
-
curQuery += typeIsOr ? ' OR ' : ' AND ';
|
|
754
|
-
}
|
|
755
|
-
const mdate = `param${++count.i}`;
|
|
1236
|
+
const value = `param${++count.i}`;
|
|
756
1237
|
curQuery +=
|
|
757
|
-
(
|
|
758
|
-
'(' +
|
|
1238
|
+
(xor(typeIsNot, clauseNot) ? 'NOT ' : '') +
|
|
1239
|
+
'(lower(' +
|
|
759
1240
|
ieTable +
|
|
760
|
-
'.
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
1241
|
+
'.' +
|
|
1242
|
+
SQLite3Driver.escape(curValue[0]) +
|
|
1243
|
+
') LIKE lower(@' +
|
|
1244
|
+
value +
|
|
1245
|
+
") ESCAPE '\\')";
|
|
1246
|
+
params[value] = curValue[1];
|
|
765
1247
|
}
|
|
766
1248
|
else {
|
|
767
1249
|
if (curQuery) {
|
|
@@ -770,11 +1252,12 @@ class SQLite3Driver extends nymph_1.NymphDriver {
|
|
|
770
1252
|
const name = `param${++count.i}`;
|
|
771
1253
|
const value = `param${++count.i}`;
|
|
772
1254
|
curQuery +=
|
|
773
|
-
(
|
|
1255
|
+
(xor(typeIsNot, clauseNot) ? 'NOT ' : '') +
|
|
1256
|
+
'EXISTS (SELECT "guid" FROM ' +
|
|
1257
|
+
SQLite3Driver.escape(this.prefix + 'data_' + etype) +
|
|
1258
|
+
' WHERE "guid"=' +
|
|
774
1259
|
ieTable +
|
|
775
|
-
'."guid"
|
|
776
|
-
SQLite3Driver.escape(this.prefix + 'comparisons_' + etype) +
|
|
777
|
-
' WHERE "name"=@' +
|
|
1260
|
+
'."guid" AND "name"=@' +
|
|
778
1261
|
name +
|
|
779
1262
|
' AND lower("string") LIKE lower(@' +
|
|
780
1263
|
value +
|
|
@@ -785,31 +1268,29 @@ class SQLite3Driver extends nymph_1.NymphDriver {
|
|
|
785
1268
|
break;
|
|
786
1269
|
case 'gt':
|
|
787
1270
|
case '!gt':
|
|
788
|
-
if (curValue[0] === 'cdate'
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
'
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
break;
|
|
800
|
-
}
|
|
801
|
-
else if (curValue[0] === 'mdate') {
|
|
1271
|
+
if (curValue[0] === 'cdate' ||
|
|
1272
|
+
curValue[0] === 'mdate' ||
|
|
1273
|
+
(this.nymph.tilmeld != null &&
|
|
1274
|
+
(curValue[0] === 'user' ||
|
|
1275
|
+
curValue[0] === 'group' ||
|
|
1276
|
+
curValue[0] === 'acUser' ||
|
|
1277
|
+
curValue[0] === 'acGroup' ||
|
|
1278
|
+
curValue[0] === 'acOther' ||
|
|
1279
|
+
curValue[0] === 'acRead' ||
|
|
1280
|
+
curValue[0] === 'acWrite' ||
|
|
1281
|
+
curValue[0] === 'acFull'))) {
|
|
802
1282
|
if (curQuery) {
|
|
803
1283
|
curQuery += typeIsOr ? ' OR ' : ' AND ';
|
|
804
1284
|
}
|
|
805
|
-
const
|
|
1285
|
+
const value = `param${++count.i}`;
|
|
806
1286
|
curQuery +=
|
|
807
|
-
(
|
|
1287
|
+
(xor(typeIsNot, clauseNot) ? 'NOT ' : '') +
|
|
808
1288
|
ieTable +
|
|
809
|
-
'.
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
1289
|
+
'.' +
|
|
1290
|
+
SQLite3Driver.escape(curValue[0]) +
|
|
1291
|
+
'>@' +
|
|
1292
|
+
value;
|
|
1293
|
+
params[value] = Number(curValue[1]);
|
|
813
1294
|
}
|
|
814
1295
|
else {
|
|
815
1296
|
if (curQuery) {
|
|
@@ -818,11 +1299,12 @@ class SQLite3Driver extends nymph_1.NymphDriver {
|
|
|
818
1299
|
const name = `param${++count.i}`;
|
|
819
1300
|
const value = `param${++count.i}`;
|
|
820
1301
|
curQuery +=
|
|
821
|
-
(
|
|
1302
|
+
(xor(typeIsNot, clauseNot) ? 'NOT ' : '') +
|
|
1303
|
+
'EXISTS (SELECT "guid" FROM ' +
|
|
1304
|
+
SQLite3Driver.escape(this.prefix + 'data_' + etype) +
|
|
1305
|
+
' WHERE "guid"=' +
|
|
822
1306
|
ieTable +
|
|
823
|
-
'."guid"
|
|
824
|
-
SQLite3Driver.escape(this.prefix + 'comparisons_' + etype) +
|
|
825
|
-
' WHERE "name"=@' +
|
|
1307
|
+
'."guid" AND "name"=@' +
|
|
826
1308
|
name +
|
|
827
1309
|
' AND "number">@' +
|
|
828
1310
|
value +
|
|
@@ -833,31 +1315,29 @@ class SQLite3Driver extends nymph_1.NymphDriver {
|
|
|
833
1315
|
break;
|
|
834
1316
|
case 'gte':
|
|
835
1317
|
case '!gte':
|
|
836
|
-
if (curValue[0] === 'cdate'
|
|
1318
|
+
if (curValue[0] === 'cdate' ||
|
|
1319
|
+
curValue[0] === 'mdate' ||
|
|
1320
|
+
(this.nymph.tilmeld != null &&
|
|
1321
|
+
(curValue[0] === 'user' ||
|
|
1322
|
+
curValue[0] === 'group' ||
|
|
1323
|
+
curValue[0] === 'acUser' ||
|
|
1324
|
+
curValue[0] === 'acGroup' ||
|
|
1325
|
+
curValue[0] === 'acOther' ||
|
|
1326
|
+
curValue[0] === 'acRead' ||
|
|
1327
|
+
curValue[0] === 'acWrite' ||
|
|
1328
|
+
curValue[0] === 'acFull'))) {
|
|
837
1329
|
if (curQuery) {
|
|
838
1330
|
curQuery += typeIsOr ? ' OR ' : ' AND ';
|
|
839
1331
|
}
|
|
840
|
-
const
|
|
841
|
-
curQuery +=
|
|
842
|
-
((0, nymph_1.xor)(typeIsNot, clauseNot) ? 'NOT ' : '') +
|
|
843
|
-
ieTable +
|
|
844
|
-
'."cdate">=@' +
|
|
845
|
-
cdate;
|
|
846
|
-
params[cdate] = Number(curValue[1]);
|
|
847
|
-
break;
|
|
848
|
-
}
|
|
849
|
-
else if (curValue[0] === 'mdate') {
|
|
850
|
-
if (curQuery) {
|
|
851
|
-
curQuery += typeIsOr ? ' OR ' : ' AND ';
|
|
852
|
-
}
|
|
853
|
-
const mdate = `param${++count.i}`;
|
|
1332
|
+
const value = `param${++count.i}`;
|
|
854
1333
|
curQuery +=
|
|
855
|
-
(
|
|
1334
|
+
(xor(typeIsNot, clauseNot) ? 'NOT ' : '') +
|
|
856
1335
|
ieTable +
|
|
857
|
-
'.
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
1336
|
+
'.' +
|
|
1337
|
+
SQLite3Driver.escape(curValue[0]) +
|
|
1338
|
+
'>=@' +
|
|
1339
|
+
value;
|
|
1340
|
+
params[value] = Number(curValue[1]);
|
|
861
1341
|
}
|
|
862
1342
|
else {
|
|
863
1343
|
if (curQuery) {
|
|
@@ -866,11 +1346,12 @@ class SQLite3Driver extends nymph_1.NymphDriver {
|
|
|
866
1346
|
const name = `param${++count.i}`;
|
|
867
1347
|
const value = `param${++count.i}`;
|
|
868
1348
|
curQuery +=
|
|
869
|
-
(
|
|
1349
|
+
(xor(typeIsNot, clauseNot) ? 'NOT ' : '') +
|
|
1350
|
+
'EXISTS (SELECT "guid" FROM ' +
|
|
1351
|
+
SQLite3Driver.escape(this.prefix + 'data_' + etype) +
|
|
1352
|
+
' WHERE "guid"=' +
|
|
870
1353
|
ieTable +
|
|
871
|
-
'."guid"
|
|
872
|
-
SQLite3Driver.escape(this.prefix + 'comparisons_' + etype) +
|
|
873
|
-
' WHERE "name"=@' +
|
|
1354
|
+
'."guid" AND "name"=@' +
|
|
874
1355
|
name +
|
|
875
1356
|
' AND "number">=@' +
|
|
876
1357
|
value +
|
|
@@ -881,31 +1362,29 @@ class SQLite3Driver extends nymph_1.NymphDriver {
|
|
|
881
1362
|
break;
|
|
882
1363
|
case 'lt':
|
|
883
1364
|
case '!lt':
|
|
884
|
-
if (curValue[0] === 'cdate'
|
|
1365
|
+
if (curValue[0] === 'cdate' ||
|
|
1366
|
+
curValue[0] === 'mdate' ||
|
|
1367
|
+
(this.nymph.tilmeld != null &&
|
|
1368
|
+
(curValue[0] === 'user' ||
|
|
1369
|
+
curValue[0] === 'group' ||
|
|
1370
|
+
curValue[0] === 'acUser' ||
|
|
1371
|
+
curValue[0] === 'acGroup' ||
|
|
1372
|
+
curValue[0] === 'acOther' ||
|
|
1373
|
+
curValue[0] === 'acRead' ||
|
|
1374
|
+
curValue[0] === 'acWrite' ||
|
|
1375
|
+
curValue[0] === 'acFull'))) {
|
|
885
1376
|
if (curQuery) {
|
|
886
1377
|
curQuery += typeIsOr ? ' OR ' : ' AND ';
|
|
887
1378
|
}
|
|
888
|
-
const
|
|
889
|
-
curQuery +=
|
|
890
|
-
((0, nymph_1.xor)(typeIsNot, clauseNot) ? 'NOT ' : '') +
|
|
891
|
-
ieTable +
|
|
892
|
-
'."cdate"<@' +
|
|
893
|
-
cdate;
|
|
894
|
-
params[cdate] = Number(curValue[1]);
|
|
895
|
-
break;
|
|
896
|
-
}
|
|
897
|
-
else if (curValue[0] === 'mdate') {
|
|
898
|
-
if (curQuery) {
|
|
899
|
-
curQuery += typeIsOr ? ' OR ' : ' AND ';
|
|
900
|
-
}
|
|
901
|
-
const mdate = `param${++count.i}`;
|
|
1379
|
+
const value = `param${++count.i}`;
|
|
902
1380
|
curQuery +=
|
|
903
|
-
(
|
|
1381
|
+
(xor(typeIsNot, clauseNot) ? 'NOT ' : '') +
|
|
904
1382
|
ieTable +
|
|
905
|
-
'.
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
1383
|
+
'.' +
|
|
1384
|
+
SQLite3Driver.escape(curValue[0]) +
|
|
1385
|
+
'<@' +
|
|
1386
|
+
value;
|
|
1387
|
+
params[value] = Number(curValue[1]);
|
|
909
1388
|
}
|
|
910
1389
|
else {
|
|
911
1390
|
if (curQuery) {
|
|
@@ -914,11 +1393,12 @@ class SQLite3Driver extends nymph_1.NymphDriver {
|
|
|
914
1393
|
const name = `param${++count.i}`;
|
|
915
1394
|
const value = `param${++count.i}`;
|
|
916
1395
|
curQuery +=
|
|
917
|
-
(
|
|
1396
|
+
(xor(typeIsNot, clauseNot) ? 'NOT ' : '') +
|
|
1397
|
+
'EXISTS (SELECT "guid" FROM ' +
|
|
1398
|
+
SQLite3Driver.escape(this.prefix + 'data_' + etype) +
|
|
1399
|
+
' WHERE "guid"=' +
|
|
918
1400
|
ieTable +
|
|
919
|
-
'."guid"
|
|
920
|
-
SQLite3Driver.escape(this.prefix + 'comparisons_' + etype) +
|
|
921
|
-
' WHERE "name"=@' +
|
|
1401
|
+
'."guid" AND "name"=@' +
|
|
922
1402
|
name +
|
|
923
1403
|
' AND "number"<@' +
|
|
924
1404
|
value +
|
|
@@ -929,31 +1409,29 @@ class SQLite3Driver extends nymph_1.NymphDriver {
|
|
|
929
1409
|
break;
|
|
930
1410
|
case 'lte':
|
|
931
1411
|
case '!lte':
|
|
932
|
-
if (curValue[0] === 'cdate'
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
'
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
break;
|
|
944
|
-
}
|
|
945
|
-
else if (curValue[0] === 'mdate') {
|
|
1412
|
+
if (curValue[0] === 'cdate' ||
|
|
1413
|
+
curValue[0] === 'mdate' ||
|
|
1414
|
+
(this.nymph.tilmeld != null &&
|
|
1415
|
+
(curValue[0] === 'user' ||
|
|
1416
|
+
curValue[0] === 'group' ||
|
|
1417
|
+
curValue[0] === 'acUser' ||
|
|
1418
|
+
curValue[0] === 'acGroup' ||
|
|
1419
|
+
curValue[0] === 'acOther' ||
|
|
1420
|
+
curValue[0] === 'acRead' ||
|
|
1421
|
+
curValue[0] === 'acWrite' ||
|
|
1422
|
+
curValue[0] === 'acFull'))) {
|
|
946
1423
|
if (curQuery) {
|
|
947
1424
|
curQuery += typeIsOr ? ' OR ' : ' AND ';
|
|
948
1425
|
}
|
|
949
|
-
const
|
|
1426
|
+
const value = `param${++count.i}`;
|
|
950
1427
|
curQuery +=
|
|
951
|
-
(
|
|
1428
|
+
(xor(typeIsNot, clauseNot) ? 'NOT ' : '') +
|
|
952
1429
|
ieTable +
|
|
953
|
-
'.
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
1430
|
+
'.' +
|
|
1431
|
+
SQLite3Driver.escape(curValue[0]) +
|
|
1432
|
+
'<=@' +
|
|
1433
|
+
value;
|
|
1434
|
+
params[value] = Number(curValue[1]);
|
|
957
1435
|
}
|
|
958
1436
|
else {
|
|
959
1437
|
if (curQuery) {
|
|
@@ -962,11 +1440,12 @@ class SQLite3Driver extends nymph_1.NymphDriver {
|
|
|
962
1440
|
const name = `param${++count.i}`;
|
|
963
1441
|
const value = `param${++count.i}`;
|
|
964
1442
|
curQuery +=
|
|
965
|
-
(
|
|
1443
|
+
(xor(typeIsNot, clauseNot) ? 'NOT ' : '') +
|
|
1444
|
+
'EXISTS (SELECT "guid" FROM ' +
|
|
1445
|
+
SQLite3Driver.escape(this.prefix + 'data_' + etype) +
|
|
1446
|
+
' WHERE "guid"=' +
|
|
966
1447
|
ieTable +
|
|
967
|
-
'."guid"
|
|
968
|
-
SQLite3Driver.escape(this.prefix + 'comparisons_' + etype) +
|
|
969
|
-
' WHERE "name"=@' +
|
|
1448
|
+
'."guid" AND "name"=@' +
|
|
970
1449
|
name +
|
|
971
1450
|
' AND "number"<=@' +
|
|
972
1451
|
value +
|
|
@@ -990,71 +1469,205 @@ class SQLite3Driver extends nymph_1.NymphDriver {
|
|
|
990
1469
|
if (curQuery) {
|
|
991
1470
|
curQuery += typeIsOr ? ' OR ' : ' AND ';
|
|
992
1471
|
}
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1472
|
+
if (this.nymph.tilmeld != null &&
|
|
1473
|
+
(curValue[0] === 'user' || curValue[0] === 'group')) {
|
|
1474
|
+
const guid = `param${++count.i}`;
|
|
1475
|
+
curQuery +=
|
|
1476
|
+
(xor(typeIsNot, clauseNot) ? 'NOT ' : '') +
|
|
1477
|
+
ieTable +
|
|
1478
|
+
'.' +
|
|
1479
|
+
SQLite3Driver.escape(curValue[0]) +
|
|
1480
|
+
'=@' +
|
|
1481
|
+
guid;
|
|
1482
|
+
params[guid] = curQguid;
|
|
1483
|
+
}
|
|
1484
|
+
else if (this.nymph.tilmeld != null &&
|
|
1485
|
+
(curValue[0] === 'acRead' ||
|
|
1486
|
+
curValue[0] === 'acWrite' ||
|
|
1487
|
+
curValue[0] === 'acFull')) {
|
|
1488
|
+
const guid = `param${++count.i}`;
|
|
1489
|
+
curQuery +=
|
|
1490
|
+
(xor(typeIsNot, clauseNot) ? 'NOT ' : '') +
|
|
1491
|
+
ieTable +
|
|
1492
|
+
'.' +
|
|
1493
|
+
SQLite3Driver.escape(curValue[0]) +
|
|
1494
|
+
' LIKE @' +
|
|
1495
|
+
guid +
|
|
1496
|
+
" ESCAPE '\\'";
|
|
1497
|
+
params[guid] =
|
|
1498
|
+
'%,' +
|
|
1499
|
+
curQguid
|
|
1500
|
+
.replace('\\', '\\\\')
|
|
1501
|
+
.replace('%', '\\%')
|
|
1502
|
+
.replace('_', '\\_') +
|
|
1503
|
+
',%';
|
|
1504
|
+
}
|
|
1505
|
+
else {
|
|
1506
|
+
const name = `param${++count.i}`;
|
|
1507
|
+
const guid = `param${++count.i}`;
|
|
1508
|
+
curQuery +=
|
|
1509
|
+
(xor(typeIsNot, clauseNot) ? 'NOT ' : '') +
|
|
1510
|
+
'EXISTS (SELECT "guid" FROM ' +
|
|
1511
|
+
SQLite3Driver.escape(this.prefix + 'references_' + etype) +
|
|
1512
|
+
' WHERE "guid"=' +
|
|
1513
|
+
ieTable +
|
|
1514
|
+
'."guid" AND "name"=@' +
|
|
1515
|
+
name +
|
|
1516
|
+
' AND "reference"=@' +
|
|
1517
|
+
guid +
|
|
1518
|
+
')';
|
|
1519
|
+
params[name] = curValue[0];
|
|
1520
|
+
params[guid] = curQguid;
|
|
1521
|
+
}
|
|
1007
1522
|
break;
|
|
1008
1523
|
case 'selector':
|
|
1009
1524
|
case '!selector':
|
|
1010
|
-
const
|
|
1525
|
+
const innerquery = this.makeEntityQuery({ ...options, sort: null, limit: undefined }, [curValue], etype, count, params, true, tableSuffix, etypes);
|
|
1011
1526
|
if (curQuery) {
|
|
1012
1527
|
curQuery += typeIsOr ? ' OR ' : ' AND ';
|
|
1013
1528
|
}
|
|
1014
1529
|
curQuery +=
|
|
1015
|
-
(
|
|
1530
|
+
(xor(typeIsNot, clauseNot) ? 'NOT ' : '') +
|
|
1016
1531
|
'(' +
|
|
1017
|
-
|
|
1532
|
+
innerquery.query +
|
|
1018
1533
|
')';
|
|
1019
1534
|
break;
|
|
1020
1535
|
case 'qref':
|
|
1021
1536
|
case '!qref':
|
|
1537
|
+
const referenceTableSuffix = makeTableSuffix();
|
|
1022
1538
|
const [qrefOptions, ...qrefSelectors] = curValue[1];
|
|
1023
1539
|
const QrefEntityClass = qrefOptions.class;
|
|
1024
1540
|
etypes.push(QrefEntityClass.ETYPE);
|
|
1025
|
-
const qrefQuery = this.makeEntityQuery({ ...qrefOptions, return: 'guid', class: QrefEntityClass }, qrefSelectors, QrefEntityClass.ETYPE, count, params, false, (0, guid_1.makeTableSuffix)(), etypes);
|
|
1026
1541
|
if (curQuery) {
|
|
1027
1542
|
curQuery += typeIsOr ? ' OR ' : ' AND ';
|
|
1028
1543
|
}
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1544
|
+
if (this.nymph.tilmeld != null &&
|
|
1545
|
+
(curValue[0] === 'user' || curValue[0] === 'group')) {
|
|
1546
|
+
const qrefQuery = this.makeEntityQuery({
|
|
1547
|
+
...qrefOptions,
|
|
1548
|
+
sort: qrefOptions.sort ?? null,
|
|
1549
|
+
return: 'guid',
|
|
1550
|
+
class: QrefEntityClass,
|
|
1551
|
+
}, qrefSelectors, QrefEntityClass.ETYPE, count, params, false, makeTableSuffix(), etypes, 'r' +
|
|
1552
|
+
referenceTableSuffix +
|
|
1553
|
+
'.' +
|
|
1554
|
+
SQLite3Driver.escape(curValue[0]));
|
|
1555
|
+
curQuery +=
|
|
1556
|
+
(xor(typeIsNot, clauseNot) ? 'NOT ' : '') +
|
|
1557
|
+
'EXISTS (SELECT "guid" FROM ' +
|
|
1558
|
+
SQLite3Driver.escape(this.prefix + 'entities_' + etype) +
|
|
1559
|
+
' r' +
|
|
1560
|
+
referenceTableSuffix +
|
|
1561
|
+
' WHERE r' +
|
|
1562
|
+
referenceTableSuffix +
|
|
1563
|
+
'."guid"=' +
|
|
1564
|
+
ieTable +
|
|
1565
|
+
'."guid" AND EXISTS (' +
|
|
1566
|
+
qrefQuery.query +
|
|
1567
|
+
'))';
|
|
1568
|
+
}
|
|
1569
|
+
else if (this.nymph.tilmeld != null &&
|
|
1570
|
+
(curValue[0] === 'acRead' ||
|
|
1571
|
+
curValue[0] === 'acWrite' ||
|
|
1572
|
+
curValue[0] === 'acFull')) {
|
|
1573
|
+
const qrefQuery = this.makeEntityQuery({
|
|
1574
|
+
...qrefOptions,
|
|
1575
|
+
sort: qrefOptions.sort ?? null,
|
|
1576
|
+
return: 'guid',
|
|
1577
|
+
class: QrefEntityClass,
|
|
1578
|
+
}, qrefSelectors, QrefEntityClass.ETYPE, count, params, false, makeTableSuffix(), etypes, 'r' + referenceTableSuffix + '."ref"');
|
|
1579
|
+
const splitTableSuffix = makeTableSuffix();
|
|
1580
|
+
curQuery +=
|
|
1581
|
+
(xor(typeIsNot, clauseNot) ? 'NOT ' : '') +
|
|
1582
|
+
`EXISTS (SELECT "guid", "ref" FROM (
|
|
1583
|
+
WITH RECURSIVE "spl${splitTableSuffix}" AS (
|
|
1584
|
+
SELECT
|
|
1585
|
+
"guid",
|
|
1586
|
+
SUBSTR(${SQLite3Driver.escape(curValue[0])}, 1, INSTR(${SQLite3Driver.escape(curValue[0])}, ',') - 1) AS "ref",
|
|
1587
|
+
SUBSTR(${SQLite3Driver.escape(curValue[0])}, INSTR(${SQLite3Driver.escape(curValue[0])}, ',') + 1) AS "remainder"
|
|
1588
|
+
FROM ${SQLite3Driver.escape(this.prefix + 'entities_' + etype)}
|
|
1589
|
+
UNION ALL
|
|
1590
|
+
SELECT
|
|
1591
|
+
"guid",
|
|
1592
|
+
SUBSTR("remainder", 1, INSTR("remainder", ',') - 1) AS "ref",
|
|
1593
|
+
SUBSTR("remainder", INSTR("remainder", ',') + 1) AS "remainder"
|
|
1594
|
+
FROM "spl${splitTableSuffix}" WHERE "remainder" != ''
|
|
1595
|
+
)
|
|
1596
|
+
SELECT "guid", "ref" FROM "spl${splitTableSuffix}" WHERE "ref" != ''
|
|
1597
|
+
) ` +
|
|
1598
|
+
' r' +
|
|
1599
|
+
referenceTableSuffix +
|
|
1600
|
+
' WHERE r' +
|
|
1601
|
+
referenceTableSuffix +
|
|
1602
|
+
'."guid"=' +
|
|
1603
|
+
ieTable +
|
|
1604
|
+
'."guid" AND EXISTS (' +
|
|
1605
|
+
qrefQuery.query +
|
|
1606
|
+
'))';
|
|
1607
|
+
}
|
|
1608
|
+
else {
|
|
1609
|
+
const qrefQuery = this.makeEntityQuery({
|
|
1610
|
+
...qrefOptions,
|
|
1611
|
+
sort: qrefOptions.sort ?? null,
|
|
1612
|
+
return: 'guid',
|
|
1613
|
+
class: QrefEntityClass,
|
|
1614
|
+
}, qrefSelectors, QrefEntityClass.ETYPE, count, params, false, makeTableSuffix(), etypes, 'r' + referenceTableSuffix + '."reference"');
|
|
1615
|
+
const qrefName = `param${++count.i}`;
|
|
1616
|
+
curQuery +=
|
|
1617
|
+
(xor(typeIsNot, clauseNot) ? 'NOT ' : '') +
|
|
1618
|
+
'EXISTS (SELECT "guid" FROM ' +
|
|
1619
|
+
SQLite3Driver.escape(this.prefix + 'references_' + etype) +
|
|
1620
|
+
' r' +
|
|
1621
|
+
referenceTableSuffix +
|
|
1622
|
+
' WHERE r' +
|
|
1623
|
+
referenceTableSuffix +
|
|
1624
|
+
'."guid"=' +
|
|
1625
|
+
ieTable +
|
|
1626
|
+
'."guid" AND r' +
|
|
1627
|
+
referenceTableSuffix +
|
|
1628
|
+
'."name"=@' +
|
|
1629
|
+
qrefName +
|
|
1630
|
+
' AND EXISTS (' +
|
|
1631
|
+
qrefQuery.query +
|
|
1632
|
+
'))';
|
|
1633
|
+
params[qrefName] = curValue[0];
|
|
1634
|
+
}
|
|
1041
1635
|
break;
|
|
1042
1636
|
}
|
|
1043
1637
|
}
|
|
1044
1638
|
return curQuery;
|
|
1045
1639
|
});
|
|
1046
1640
|
let sortBy;
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1641
|
+
let sortByInner;
|
|
1642
|
+
let sortJoin = '';
|
|
1643
|
+
const order = options.reverse ? ' DESC' : '';
|
|
1644
|
+
if (sort == null) {
|
|
1645
|
+
sortBy = '';
|
|
1646
|
+
sortByInner = '';
|
|
1647
|
+
}
|
|
1648
|
+
else {
|
|
1649
|
+
switch (sort) {
|
|
1650
|
+
case 'mdate':
|
|
1651
|
+
sortBy = `ORDER BY ${eTable}."mdate"${order}`;
|
|
1652
|
+
sortByInner = `ORDER BY ${ieTable}."mdate"${order}`;
|
|
1653
|
+
break;
|
|
1654
|
+
case 'cdate':
|
|
1655
|
+
sortBy = `ORDER BY ${eTable}."cdate"${order}`;
|
|
1656
|
+
sortByInner = `ORDER BY ${ieTable}."cdate"${order}`;
|
|
1657
|
+
break;
|
|
1658
|
+
default:
|
|
1659
|
+
const name = `param${++count.i}`;
|
|
1660
|
+
sortJoin = `LEFT JOIN (
|
|
1661
|
+
SELECT "guid", "string", "number"
|
|
1662
|
+
FROM ${SQLite3Driver.escape(this.prefix + 'data_' + etype)}
|
|
1663
|
+
WHERE "name"=@${name}
|
|
1664
|
+
ORDER BY "number"${order}, "string"${order}
|
|
1665
|
+
) ${sTable} USING ("guid")`;
|
|
1666
|
+
sortBy = `ORDER BY ${sTable}."number"${order}, ${sTable}."string"${order}`;
|
|
1667
|
+
sortByInner = sortBy;
|
|
1668
|
+
params[name] = sort;
|
|
1669
|
+
break;
|
|
1670
|
+
}
|
|
1058
1671
|
}
|
|
1059
1672
|
let query;
|
|
1060
1673
|
if (queryParts.length) {
|
|
@@ -1071,25 +1684,29 @@ class SQLite3Driver extends nymph_1.NymphDriver {
|
|
|
1071
1684
|
offset = ` OFFSET ${Math.floor(Number(options.offset))}`;
|
|
1072
1685
|
}
|
|
1073
1686
|
const whereClause = queryParts.join(') AND (');
|
|
1687
|
+
const guidClause = guidSelector
|
|
1688
|
+
? `${ieTable}."guid"=${guidSelector} AND `
|
|
1689
|
+
: '';
|
|
1074
1690
|
if (options.return === 'count') {
|
|
1075
1691
|
if (limit || offset) {
|
|
1076
1692
|
query = `SELECT COUNT("guid") AS "count" FROM (
|
|
1077
1693
|
SELECT "guid"
|
|
1078
1694
|
FROM ${SQLite3Driver.escape(this.prefix + 'entities_' + etype)} ${ieTable}
|
|
1079
|
-
WHERE (${whereClause})${limit}${offset}
|
|
1695
|
+
WHERE ${guidClause}(${whereClause})${limit}${offset}
|
|
1080
1696
|
)`;
|
|
1081
1697
|
}
|
|
1082
1698
|
else {
|
|
1083
1699
|
query = `SELECT COUNT("guid") AS "count"
|
|
1084
1700
|
FROM ${SQLite3Driver.escape(this.prefix + 'entities_' + etype)} ${ieTable}
|
|
1085
|
-
WHERE (${whereClause})`;
|
|
1701
|
+
WHERE ${guidClause}(${whereClause})`;
|
|
1086
1702
|
}
|
|
1087
1703
|
}
|
|
1088
1704
|
else if (options.return === 'guid') {
|
|
1089
1705
|
query = `SELECT "guid"
|
|
1090
1706
|
FROM ${SQLite3Driver.escape(this.prefix + 'entities_' + etype)} ${ieTable}
|
|
1091
|
-
|
|
1092
|
-
|
|
1707
|
+
${sortJoin}
|
|
1708
|
+
WHERE ${guidClause}(${whereClause})
|
|
1709
|
+
${sortByInner ? sortByInner + ', ' : 'ORDER BY '}"guid"${limit}${offset}`;
|
|
1093
1710
|
}
|
|
1094
1711
|
else {
|
|
1095
1712
|
query = `SELECT
|
|
@@ -1097,20 +1714,30 @@ class SQLite3Driver extends nymph_1.NymphDriver {
|
|
|
1097
1714
|
${eTable}."tags",
|
|
1098
1715
|
${eTable}."cdate",
|
|
1099
1716
|
${eTable}."mdate",
|
|
1717
|
+
${eTable}."user",
|
|
1718
|
+
${eTable}."group",
|
|
1719
|
+
${eTable}."acUser",
|
|
1720
|
+
${eTable}."acGroup",
|
|
1721
|
+
${eTable}."acOther",
|
|
1722
|
+
${eTable}."acRead",
|
|
1723
|
+
${eTable}."acWrite",
|
|
1724
|
+
${eTable}."acFull",
|
|
1100
1725
|
${dTable}."name",
|
|
1101
1726
|
${dTable}."value",
|
|
1102
|
-
${
|
|
1103
|
-
${
|
|
1727
|
+
json(${dTable}."json") as "json",
|
|
1728
|
+
${dTable}."string",
|
|
1729
|
+
${dTable}."number"
|
|
1104
1730
|
FROM ${SQLite3Driver.escape(this.prefix + 'entities_' + etype)} ${eTable}
|
|
1105
1731
|
LEFT JOIN ${SQLite3Driver.escape(this.prefix + 'data_' + etype)} ${dTable} USING ("guid")
|
|
1106
|
-
|
|
1732
|
+
${sortJoin}
|
|
1107
1733
|
INNER JOIN (
|
|
1108
1734
|
SELECT "guid"
|
|
1109
1735
|
FROM ${SQLite3Driver.escape(this.prefix + 'entities_' + etype)} ${ieTable}
|
|
1110
|
-
|
|
1111
|
-
|
|
1736
|
+
${sortJoin}
|
|
1737
|
+
WHERE ${guidClause}(${whereClause})
|
|
1738
|
+
${sortByInner}${limit}${offset}
|
|
1112
1739
|
) ${fTable} USING ("guid")
|
|
1113
|
-
ORDER BY ${eTable}
|
|
1740
|
+
${sortBy ? sortBy + ', ' : 'ORDER BY '}${eTable}."guid"`;
|
|
1114
1741
|
}
|
|
1115
1742
|
}
|
|
1116
1743
|
}
|
|
@@ -1127,22 +1754,27 @@ class SQLite3Driver extends nymph_1.NymphDriver {
|
|
|
1127
1754
|
if ('offset' in options) {
|
|
1128
1755
|
offset = ` OFFSET ${Math.floor(Number(options.offset))}`;
|
|
1129
1756
|
}
|
|
1757
|
+
const guidClause = guidSelector
|
|
1758
|
+
? ` WHERE ${ieTable}."guid"=${guidSelector}`
|
|
1759
|
+
: '';
|
|
1130
1760
|
if (options.return === 'count') {
|
|
1131
1761
|
if (limit || offset) {
|
|
1132
1762
|
query = `SELECT COUNT("guid") AS "count" FROM (
|
|
1133
1763
|
SELECT "guid"
|
|
1134
|
-
FROM ${SQLite3Driver.escape(this.prefix + 'entities_' + etype)} ${ieTable}${limit}${offset}
|
|
1764
|
+
FROM ${SQLite3Driver.escape(this.prefix + 'entities_' + etype)} ${ieTable}${guidClause}${limit}${offset}
|
|
1135
1765
|
)`;
|
|
1136
1766
|
}
|
|
1137
1767
|
else {
|
|
1138
1768
|
query = `SELECT COUNT("guid") AS "count"
|
|
1139
|
-
FROM ${SQLite3Driver.escape(this.prefix + 'entities_' + etype)} ${ieTable}`;
|
|
1769
|
+
FROM ${SQLite3Driver.escape(this.prefix + 'entities_' + etype)} ${ieTable}${guidClause}`;
|
|
1140
1770
|
}
|
|
1141
1771
|
}
|
|
1142
1772
|
else if (options.return === 'guid') {
|
|
1143
1773
|
query = `SELECT "guid"
|
|
1144
1774
|
FROM ${SQLite3Driver.escape(this.prefix + 'entities_' + etype)} ${ieTable}
|
|
1145
|
-
|
|
1775
|
+
${sortJoin}
|
|
1776
|
+
${guidClause}
|
|
1777
|
+
${sortByInner ? sortByInner + ', ' : 'ORDER BY '}"guid"${limit}${offset}`;
|
|
1146
1778
|
}
|
|
1147
1779
|
else {
|
|
1148
1780
|
if (limit || offset) {
|
|
@@ -1151,19 +1783,30 @@ class SQLite3Driver extends nymph_1.NymphDriver {
|
|
|
1151
1783
|
${eTable}."tags",
|
|
1152
1784
|
${eTable}."cdate",
|
|
1153
1785
|
${eTable}."mdate",
|
|
1786
|
+
${eTable}."user",
|
|
1787
|
+
${eTable}."group",
|
|
1788
|
+
${eTable}."acUser",
|
|
1789
|
+
${eTable}."acGroup",
|
|
1790
|
+
${eTable}."acOther",
|
|
1791
|
+
${eTable}."acRead",
|
|
1792
|
+
${eTable}."acWrite",
|
|
1793
|
+
${eTable}."acFull",
|
|
1154
1794
|
${dTable}."name",
|
|
1155
1795
|
${dTable}."value",
|
|
1156
|
-
${
|
|
1157
|
-
${
|
|
1796
|
+
json(${dTable}."json") as "json",
|
|
1797
|
+
${dTable}."string",
|
|
1798
|
+
${dTable}."number"
|
|
1158
1799
|
FROM ${SQLite3Driver.escape(this.prefix + 'entities_' + etype)} ${eTable}
|
|
1159
1800
|
LEFT JOIN ${SQLite3Driver.escape(this.prefix + 'data_' + etype)} ${dTable} USING ("guid")
|
|
1160
|
-
|
|
1801
|
+
${sortJoin}
|
|
1161
1802
|
INNER JOIN (
|
|
1162
1803
|
SELECT "guid"
|
|
1163
1804
|
FROM ${SQLite3Driver.escape(this.prefix + 'entities_' + etype)} ${ieTable}
|
|
1164
|
-
|
|
1805
|
+
${sortJoin}
|
|
1806
|
+
${guidClause}
|
|
1807
|
+
${sortByInner}${limit}${offset}
|
|
1165
1808
|
) ${fTable} USING ("guid")
|
|
1166
|
-
ORDER BY ${eTable}
|
|
1809
|
+
${sortBy ? sortBy + ', ' : 'ORDER BY '}${eTable}."guid"`;
|
|
1167
1810
|
}
|
|
1168
1811
|
else {
|
|
1169
1812
|
query = `SELECT
|
|
@@ -1171,14 +1814,24 @@ class SQLite3Driver extends nymph_1.NymphDriver {
|
|
|
1171
1814
|
${eTable}."tags",
|
|
1172
1815
|
${eTable}."cdate",
|
|
1173
1816
|
${eTable}."mdate",
|
|
1817
|
+
${eTable}."user",
|
|
1818
|
+
${eTable}."group",
|
|
1819
|
+
${eTable}."acUser",
|
|
1820
|
+
${eTable}."acGroup",
|
|
1821
|
+
${eTable}."acOther",
|
|
1822
|
+
${eTable}."acRead",
|
|
1823
|
+
${eTable}."acWrite",
|
|
1824
|
+
${eTable}."acFull",
|
|
1174
1825
|
${dTable}."name",
|
|
1175
1826
|
${dTable}."value",
|
|
1176
|
-
${
|
|
1177
|
-
${
|
|
1827
|
+
json(${dTable}."json") as "json",
|
|
1828
|
+
${dTable}."string",
|
|
1829
|
+
${dTable}."number"
|
|
1178
1830
|
FROM ${SQLite3Driver.escape(this.prefix + 'entities_' + etype)} ${eTable}
|
|
1179
1831
|
LEFT JOIN ${SQLite3Driver.escape(this.prefix + 'data_' + etype)} ${dTable} USING ("guid")
|
|
1180
|
-
|
|
1181
|
-
|
|
1832
|
+
${sortJoin}
|
|
1833
|
+
${guidSelector ? `WHERE ${eTable}."guid"=${guidSelector}` : ''}
|
|
1834
|
+
${sortBy ? sortBy + ', ' : 'ORDER BY '}${eTable}."guid"`;
|
|
1182
1835
|
}
|
|
1183
1836
|
}
|
|
1184
1837
|
}
|
|
@@ -1194,29 +1847,41 @@ class SQLite3Driver extends nymph_1.NymphDriver {
|
|
|
1194
1847
|
}
|
|
1195
1848
|
performQuery(options, formattedSelectors, etype) {
|
|
1196
1849
|
const { query, params, etypes } = this.makeEntityQuery(options, formattedSelectors, etype);
|
|
1197
|
-
const result = this.
|
|
1850
|
+
const result = this.queryArray(query, { etypes, params })[Symbol.iterator]();
|
|
1198
1851
|
return {
|
|
1199
1852
|
result,
|
|
1200
1853
|
};
|
|
1201
1854
|
}
|
|
1202
1855
|
async getEntities(options = {}, ...selectors) {
|
|
1203
|
-
|
|
1204
|
-
}
|
|
1205
|
-
getEntitiesSync(options = {}, ...selectors) {
|
|
1206
|
-
const { result, process } = this.getEntitesRowLike(options, selectors, (options, formattedSelectors, etype) => this.performQuery(options, formattedSelectors, etype), () => {
|
|
1856
|
+
const { result, process } = this.getEntitiesRowLike(options, selectors, ({ options, selectors, etype }) => this.performQuery(options, selectors, etype), () => {
|
|
1207
1857
|
const next = result.next();
|
|
1208
1858
|
return next.done ? null : next.value;
|
|
1209
1859
|
}, () => undefined, (row) => Number(row.count), (row) => row.guid, (row) => ({
|
|
1210
|
-
tags: row.tags.length > 2
|
|
1860
|
+
tags: row.tags.length > 2
|
|
1861
|
+
? row.tags
|
|
1862
|
+
.slice(1, -1)
|
|
1863
|
+
.split(',')
|
|
1864
|
+
.filter((tag) => tag)
|
|
1865
|
+
: [],
|
|
1211
1866
|
cdate: Number(row.cdate),
|
|
1212
1867
|
mdate: Number(row.mdate),
|
|
1868
|
+
user: row.user,
|
|
1869
|
+
group: row.group,
|
|
1870
|
+
acUser: row.acUser,
|
|
1871
|
+
acGroup: row.acGroup,
|
|
1872
|
+
acOther: row.acOther,
|
|
1873
|
+
acRead: row.acRead?.slice(1, -1).split(',') ?? [],
|
|
1874
|
+
acWrite: row.acWrite?.slice(1, -1).split(',') ?? [],
|
|
1875
|
+
acFull: row.acFull?.slice(1, -1).split(',') ?? [],
|
|
1213
1876
|
}), (row) => ({
|
|
1214
1877
|
name: row.name,
|
|
1215
1878
|
svalue: row.value === 'N'
|
|
1216
1879
|
? JSON.stringify(row.number)
|
|
1217
1880
|
: row.value === 'S'
|
|
1218
1881
|
? JSON.stringify(row.string)
|
|
1219
|
-
: row.value
|
|
1882
|
+
: row.value === 'J'
|
|
1883
|
+
? row.json
|
|
1884
|
+
: row.value,
|
|
1220
1885
|
}));
|
|
1221
1886
|
const value = process();
|
|
1222
1887
|
if (value instanceof Error) {
|
|
@@ -1226,7 +1891,7 @@ class SQLite3Driver extends nymph_1.NymphDriver {
|
|
|
1226
1891
|
}
|
|
1227
1892
|
async getUID(name) {
|
|
1228
1893
|
if (name == null) {
|
|
1229
|
-
throw new
|
|
1894
|
+
throw new InvalidParametersError('Name not given for UID.');
|
|
1230
1895
|
}
|
|
1231
1896
|
const result = this.queryGet(`SELECT "cur_uid" FROM ${SQLite3Driver.escape(`${this.prefix}uids`)} WHERE "name"=@name;`, {
|
|
1232
1897
|
params: {
|
|
@@ -1235,10 +1900,18 @@ class SQLite3Driver extends nymph_1.NymphDriver {
|
|
|
1235
1900
|
});
|
|
1236
1901
|
return result?.cur_uid ?? null;
|
|
1237
1902
|
}
|
|
1238
|
-
async
|
|
1239
|
-
this.
|
|
1903
|
+
async importEntity(entity) {
|
|
1904
|
+
return await this.importEntityInternal(entity);
|
|
1905
|
+
}
|
|
1906
|
+
async importEntityTokens(entity) {
|
|
1907
|
+
return await this.importEntityInternal(entity, { only: 'tokens' });
|
|
1908
|
+
}
|
|
1909
|
+
async importEntityTilmeldAC(entity) {
|
|
1910
|
+
return await this.importEntityInternal(entity, { only: 'tilmeldAC' });
|
|
1911
|
+
}
|
|
1912
|
+
async importEntityInternal({ guid, cdate, mdate, tags, sdata, etype, }, { only = undefined } = {}) {
|
|
1240
1913
|
try {
|
|
1241
|
-
|
|
1914
|
+
if (only == null) {
|
|
1242
1915
|
this.queryRun(`DELETE FROM ${SQLite3Driver.escape(`${this.prefix}entities_${etype}`)} WHERE "guid"=@guid;`, {
|
|
1243
1916
|
etypes: [etype],
|
|
1244
1917
|
params: {
|
|
@@ -1251,29 +1924,48 @@ class SQLite3Driver extends nymph_1.NymphDriver {
|
|
|
1251
1924
|
guid,
|
|
1252
1925
|
},
|
|
1253
1926
|
});
|
|
1254
|
-
this.queryRun(`DELETE FROM ${SQLite3Driver.escape(`${this.prefix}
|
|
1927
|
+
this.queryRun(`DELETE FROM ${SQLite3Driver.escape(`${this.prefix}references_${etype}`)} WHERE "guid"=@guid;`, {
|
|
1255
1928
|
etypes: [etype],
|
|
1256
1929
|
params: {
|
|
1257
1930
|
guid,
|
|
1258
1931
|
},
|
|
1259
1932
|
});
|
|
1260
|
-
|
|
1933
|
+
}
|
|
1934
|
+
if (only == null || only === 'tokens') {
|
|
1935
|
+
this.queryRun(`DELETE FROM ${SQLite3Driver.escape(`${this.prefix}tokens_${etype}`)} WHERE "guid"=@guid;`, {
|
|
1936
|
+
etypes: [etype],
|
|
1937
|
+
params: {
|
|
1938
|
+
guid,
|
|
1939
|
+
},
|
|
1940
|
+
});
|
|
1941
|
+
}
|
|
1942
|
+
if (only == null) {
|
|
1943
|
+
this.queryRun(`DELETE FROM ${SQLite3Driver.escape(`${this.prefix}uniques_${etype}`)} WHERE "guid"=@guid;`, {
|
|
1261
1944
|
etypes: [etype],
|
|
1262
1945
|
params: {
|
|
1263
1946
|
guid,
|
|
1264
1947
|
},
|
|
1265
1948
|
});
|
|
1266
|
-
|
|
1949
|
+
}
|
|
1950
|
+
if (only == null) {
|
|
1951
|
+
let { user, group, acUser, acGroup, acOther, acRead, acWrite, acFull } = this.removeAndReturnACValues(etype, {}, sdata);
|
|
1952
|
+
this.queryRun(`INSERT INTO ${SQLite3Driver.escape(`${this.prefix}entities_${etype}`)} ("guid", "tags", "cdate", "mdate", "user", "group", "acUser", "acGroup", "acOther", "acRead", "acWrite", "acFull") VALUES (@guid, @tags, @cdate, @mdate, @user, @group, @acUser, @acGroup, @acOther, @acRead, @acWrite, @acFull);`, {
|
|
1267
1953
|
etypes: [etype],
|
|
1268
1954
|
params: {
|
|
1269
1955
|
guid,
|
|
1270
1956
|
tags: ',' + tags.join(',') + ',',
|
|
1271
|
-
cdate
|
|
1272
|
-
mdate
|
|
1957
|
+
cdate,
|
|
1958
|
+
mdate,
|
|
1959
|
+
user,
|
|
1960
|
+
group,
|
|
1961
|
+
acUser,
|
|
1962
|
+
acGroup,
|
|
1963
|
+
acOther,
|
|
1964
|
+
acRead: acRead && ',' + acRead.join(',') + ',',
|
|
1965
|
+
acWrite: acWrite && ',' + acWrite.join(',') + ',',
|
|
1966
|
+
acFull: acFull && ',' + acFull.join(',') + ',',
|
|
1273
1967
|
},
|
|
1274
1968
|
});
|
|
1275
|
-
delete sdata.cdate;
|
|
1276
|
-
delete sdata.mdate;
|
|
1277
1969
|
for (const name in sdata) {
|
|
1278
1970
|
const value = sdata[name];
|
|
1279
1971
|
const uvalue = JSON.parse(value);
|
|
@@ -1284,23 +1976,18 @@ class SQLite3Driver extends nymph_1.NymphDriver {
|
|
|
1284
1976
|
? 'N'
|
|
1285
1977
|
: typeof uvalue === 'string'
|
|
1286
1978
|
? 'S'
|
|
1287
|
-
:
|
|
1288
|
-
|
|
1979
|
+
: 'J';
|
|
1980
|
+
const jsonValue = storageValue === 'J' ? value : null;
|
|
1981
|
+
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);`, {
|
|
1289
1982
|
etypes: [etype],
|
|
1290
1983
|
params: {
|
|
1291
1984
|
guid,
|
|
1292
1985
|
name,
|
|
1293
1986
|
storageValue,
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
this.queryRun(`INSERT INTO ${SQLite3Driver.escape(`${this.prefix}comparisons_${etype}`)} ("guid", "name", "truthy", "string", "number") VALUES (@guid, @name, @truthy, @string, @number);`, {
|
|
1297
|
-
etypes: [etype],
|
|
1298
|
-
params: {
|
|
1299
|
-
guid,
|
|
1300
|
-
name,
|
|
1301
|
-
truthy: uvalue ? 1 : 0,
|
|
1302
|
-
string: `${uvalue}`,
|
|
1987
|
+
jsonValue,
|
|
1988
|
+
string: storageValue === 'J' ? null : `${uvalue}`,
|
|
1303
1989
|
number: Number(uvalue),
|
|
1990
|
+
truthy: uvalue ? 1 : 0,
|
|
1304
1991
|
},
|
|
1305
1992
|
});
|
|
1306
1993
|
const references = this.findReferences(value);
|
|
@@ -1315,41 +2002,132 @@ class SQLite3Driver extends nymph_1.NymphDriver {
|
|
|
1315
2002
|
});
|
|
1316
2003
|
}
|
|
1317
2004
|
}
|
|
1318
|
-
}
|
|
1319
|
-
|
|
2005
|
+
}
|
|
2006
|
+
if (only === 'tilmeldAC') {
|
|
2007
|
+
let { user, group, acUser, acGroup, acOther, acRead, acWrite, acFull } = this.removeAndReturnACValues(etype, {}, sdata);
|
|
2008
|
+
this.queryRun(`UPDATE OR IGNORE ${SQLite3Driver.escape(`${this.prefix}entities_${etype}`)} SET "user"=@user, "group"=@group, "acUser"=@acUser, "acGroup"=@acGroup, "acOther"=@acOther, "acRead"=@acRead, "acWrite"=@acWrite, "acFull"=@acFull WHERE "guid"=@guid;`, {
|
|
2009
|
+
etypes: [etype],
|
|
1320
2010
|
params: {
|
|
1321
|
-
|
|
2011
|
+
user,
|
|
2012
|
+
group,
|
|
2013
|
+
acUser,
|
|
2014
|
+
acGroup,
|
|
2015
|
+
acOther,
|
|
2016
|
+
acRead: acRead && ',' + acRead.join(',') + ',',
|
|
2017
|
+
acWrite: acWrite && ',' + acWrite.join(',') + ',',
|
|
2018
|
+
acFull: acFull && ',' + acFull.join(',') + ',',
|
|
2019
|
+
guid,
|
|
1322
2020
|
},
|
|
1323
2021
|
});
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
|
|
1328
|
-
|
|
2022
|
+
}
|
|
2023
|
+
const EntityClass = this.nymph.getEntityClassByEtype(etype);
|
|
2024
|
+
if (only == null || only === 'tokens') {
|
|
2025
|
+
for (let name in sdata) {
|
|
2026
|
+
let tokenString = null;
|
|
2027
|
+
try {
|
|
2028
|
+
tokenString = EntityClass.getFTSText(name, JSON.parse(sdata[name]));
|
|
2029
|
+
}
|
|
2030
|
+
catch (e) {
|
|
2031
|
+
// Ignore error.
|
|
2032
|
+
}
|
|
2033
|
+
if (tokenString != null) {
|
|
2034
|
+
const tokens = this.tokenizer.tokenize(tokenString);
|
|
2035
|
+
while (tokens.length) {
|
|
2036
|
+
const currentTokens = tokens.splice(0, 100);
|
|
2037
|
+
const params = {
|
|
2038
|
+
guid,
|
|
2039
|
+
name,
|
|
2040
|
+
};
|
|
2041
|
+
const values = [];
|
|
2042
|
+
for (let i = 0; i < currentTokens.length; i++) {
|
|
2043
|
+
const token = currentTokens[i];
|
|
2044
|
+
params['token' + i] = token.token;
|
|
2045
|
+
params['position' + i] = token.position;
|
|
2046
|
+
params['stem' + i] = token.stem ? 1 : 0;
|
|
2047
|
+
values.push('(@guid, @name, @token' +
|
|
2048
|
+
i +
|
|
2049
|
+
', @position' +
|
|
2050
|
+
i +
|
|
2051
|
+
', @stem' +
|
|
2052
|
+
i +
|
|
2053
|
+
')');
|
|
2054
|
+
}
|
|
2055
|
+
this.queryRun(`INSERT INTO ${SQLite3Driver.escape(`${this.prefix}tokens_${etype}`)} ("guid", "name", "token", "position", "stem") VALUES ${values.join(', ')};`, {
|
|
2056
|
+
etypes: [etype],
|
|
2057
|
+
params,
|
|
2058
|
+
});
|
|
2059
|
+
}
|
|
2060
|
+
}
|
|
2061
|
+
}
|
|
2062
|
+
}
|
|
2063
|
+
if (only == null) {
|
|
2064
|
+
const uniques = await EntityClass.getUniques({
|
|
2065
|
+
guid,
|
|
2066
|
+
cdate,
|
|
2067
|
+
mdate,
|
|
2068
|
+
tags,
|
|
2069
|
+
data: {},
|
|
2070
|
+
sdata,
|
|
1329
2071
|
});
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
|
|
1333
|
-
|
|
2072
|
+
for (const unique of uniques) {
|
|
2073
|
+
try {
|
|
2074
|
+
this.queryRun(`INSERT INTO ${SQLite3Driver.escape(`${this.prefix}uniques_${etype}`)} ("guid", "unique") VALUES (@guid, @unique);`, {
|
|
2075
|
+
etypes: [etype],
|
|
2076
|
+
params: {
|
|
2077
|
+
guid,
|
|
2078
|
+
unique,
|
|
2079
|
+
},
|
|
2080
|
+
});
|
|
2081
|
+
}
|
|
2082
|
+
catch (e) {
|
|
2083
|
+
if (e instanceof EntityUniqueConstraintError) {
|
|
2084
|
+
this.nymph.config.debugError('sqlite3', `Import entity unique constraint violation for GUID "${guid}" on etype "${etype}": "${unique}"`);
|
|
2085
|
+
}
|
|
2086
|
+
throw e;
|
|
2087
|
+
}
|
|
2088
|
+
}
|
|
2089
|
+
}
|
|
2090
|
+
}
|
|
2091
|
+
catch (e) {
|
|
2092
|
+
this.nymph.config.debugError('sqlite3', `Import entity error: "${e}"`);
|
|
2093
|
+
throw e;
|
|
2094
|
+
}
|
|
2095
|
+
}
|
|
2096
|
+
async importUID({ name, value }) {
|
|
2097
|
+
try {
|
|
2098
|
+
await this.startTransaction(`nymph-import-uid-${name}`);
|
|
2099
|
+
this.queryRun(`DELETE FROM ${SQLite3Driver.escape(`${this.prefix}uids`)} WHERE "name"=@name;`, {
|
|
2100
|
+
params: {
|
|
2101
|
+
name,
|
|
2102
|
+
},
|
|
2103
|
+
});
|
|
2104
|
+
this.queryRun(`INSERT INTO ${SQLite3Driver.escape(`${this.prefix}uids`)} ("name", "cur_uid") VALUES (@name, @value);`, {
|
|
2105
|
+
params: {
|
|
2106
|
+
name,
|
|
2107
|
+
value,
|
|
2108
|
+
},
|
|
1334
2109
|
});
|
|
2110
|
+
await this.commit(`nymph-import-uid-${name}`);
|
|
1335
2111
|
}
|
|
1336
2112
|
catch (e) {
|
|
1337
|
-
|
|
2113
|
+
this.nymph.config.debugError('sqlite3', `Import UID error: "${e}"`);
|
|
2114
|
+
await this.rollback(`nymph-import-uid-${name}`);
|
|
1338
2115
|
throw e;
|
|
1339
2116
|
}
|
|
1340
2117
|
}
|
|
1341
2118
|
async newUID(name) {
|
|
1342
2119
|
if (name == null) {
|
|
1343
|
-
throw new
|
|
2120
|
+
throw new InvalidParametersError('Name not given for UID.');
|
|
1344
2121
|
}
|
|
1345
|
-
this.checkReadOnlyMode();
|
|
1346
2122
|
await this.startTransaction('nymph-newuid');
|
|
2123
|
+
let curUid = undefined;
|
|
1347
2124
|
try {
|
|
1348
|
-
|
|
1349
|
-
|
|
1350
|
-
|
|
1351
|
-
|
|
1352
|
-
|
|
2125
|
+
curUid =
|
|
2126
|
+
this.queryGet(`SELECT "cur_uid" FROM ${SQLite3Driver.escape(`${this.prefix}uids`)} WHERE "name"=@name;`, {
|
|
2127
|
+
params: {
|
|
2128
|
+
name,
|
|
2129
|
+
},
|
|
2130
|
+
})?.cur_uid ?? null;
|
|
1353
2131
|
if (curUid == null) {
|
|
1354
2132
|
curUid = 1;
|
|
1355
2133
|
this.queryRun(`INSERT INTO ${SQLite3Driver.escape(`${this.prefix}uids`)} ("name", "cur_uid") VALUES (@name, @curUid);`, {
|
|
@@ -1368,41 +2146,50 @@ class SQLite3Driver extends nymph_1.NymphDriver {
|
|
|
1368
2146
|
},
|
|
1369
2147
|
});
|
|
1370
2148
|
}
|
|
1371
|
-
await this.commit('nymph-newuid');
|
|
1372
|
-
return curUid;
|
|
1373
2149
|
}
|
|
1374
2150
|
catch (e) {
|
|
2151
|
+
this.nymph.config.debugError('sqlite3', `New UID error: "${e}"`);
|
|
1375
2152
|
await this.rollback('nymph-newuid');
|
|
1376
2153
|
throw e;
|
|
1377
2154
|
}
|
|
2155
|
+
await this.commit('nymph-newuid');
|
|
2156
|
+
return curUid;
|
|
1378
2157
|
}
|
|
1379
2158
|
async renameUID(oldName, newName) {
|
|
1380
2159
|
if (oldName == null || newName == null) {
|
|
1381
|
-
throw new
|
|
2160
|
+
throw new InvalidParametersError('Name not given for UID.');
|
|
1382
2161
|
}
|
|
1383
|
-
this.
|
|
2162
|
+
await this.startTransaction('nymph-rename-uid');
|
|
1384
2163
|
this.queryRun(`UPDATE ${SQLite3Driver.escape(`${this.prefix}uids`)} SET "name"=@newName WHERE "name"=@oldName;`, {
|
|
1385
2164
|
params: {
|
|
1386
2165
|
newName,
|
|
1387
2166
|
oldName,
|
|
1388
2167
|
},
|
|
1389
2168
|
});
|
|
2169
|
+
await this.commit('nymph-rename-uid');
|
|
1390
2170
|
return true;
|
|
1391
2171
|
}
|
|
1392
2172
|
async rollback(name) {
|
|
1393
2173
|
if (name == null || typeof name !== 'string' || name.length === 0) {
|
|
1394
|
-
throw new
|
|
2174
|
+
throw new InvalidParametersError('Transaction rollback attempted without a name.');
|
|
1395
2175
|
}
|
|
1396
2176
|
if (this.store.transactionsStarted === 0) {
|
|
1397
2177
|
return true;
|
|
1398
2178
|
}
|
|
1399
2179
|
this.queryRun(`ROLLBACK TO SAVEPOINT ${SQLite3Driver.escape(name)};`);
|
|
1400
2180
|
this.store.transactionsStarted--;
|
|
2181
|
+
if (this.store.transactionsStarted === 0 &&
|
|
2182
|
+
this.store.linkWrite &&
|
|
2183
|
+
!this.config.explicitWrite) {
|
|
2184
|
+
this.store.linkWrite.exec('PRAGMA optimize;');
|
|
2185
|
+
this.store.linkWrite.close();
|
|
2186
|
+
this.store.linkWrite = undefined;
|
|
2187
|
+
}
|
|
1401
2188
|
return true;
|
|
1402
2189
|
}
|
|
1403
2190
|
async saveEntity(entity) {
|
|
1404
|
-
|
|
1405
|
-
|
|
2191
|
+
const insertData = (guid, data, sdata, uniques, etype) => {
|
|
2192
|
+
const EntityClass = this.nymph.getEntityClassByEtype(etype);
|
|
1406
2193
|
const runInsertQuery = (name, value, svalue) => {
|
|
1407
2194
|
if (value === undefined) {
|
|
1408
2195
|
return;
|
|
@@ -1411,23 +2198,18 @@ class SQLite3Driver extends nymph_1.NymphDriver {
|
|
|
1411
2198
|
? 'N'
|
|
1412
2199
|
: typeof value === 'string'
|
|
1413
2200
|
? 'S'
|
|
1414
|
-
:
|
|
1415
|
-
|
|
2201
|
+
: 'J';
|
|
2202
|
+
const jsonValue = storageValue === 'J' ? svalue : null;
|
|
2203
|
+
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);`, {
|
|
1416
2204
|
etypes: [etype],
|
|
1417
2205
|
params: {
|
|
1418
2206
|
guid,
|
|
1419
2207
|
name,
|
|
1420
2208
|
storageValue,
|
|
1421
|
-
|
|
1422
|
-
|
|
1423
|
-
this.queryRun(`INSERT INTO ${SQLite3Driver.escape(`${this.prefix}comparisons_${etype}`)} ("guid", "name", "truthy", "string", "number") VALUES (@guid, @name, @truthy, @string, @number);`, {
|
|
1424
|
-
etypes: [etype],
|
|
1425
|
-
params: {
|
|
1426
|
-
guid,
|
|
1427
|
-
name,
|
|
1428
|
-
truthy: value ? 1 : 0,
|
|
1429
|
-
string: `${value}`,
|
|
2209
|
+
jsonValue,
|
|
2210
|
+
string: storageValue === 'J' ? null : `${value}`,
|
|
1430
2211
|
number: Number(value),
|
|
2212
|
+
truthy: value ? 1 : 0,
|
|
1431
2213
|
},
|
|
1432
2214
|
});
|
|
1433
2215
|
const references = this.findReferences(svalue);
|
|
@@ -1441,7 +2223,59 @@ class SQLite3Driver extends nymph_1.NymphDriver {
|
|
|
1441
2223
|
},
|
|
1442
2224
|
});
|
|
1443
2225
|
}
|
|
2226
|
+
let tokenString = null;
|
|
2227
|
+
try {
|
|
2228
|
+
tokenString = EntityClass.getFTSText(name, value);
|
|
2229
|
+
}
|
|
2230
|
+
catch (e) {
|
|
2231
|
+
// Ignore error.
|
|
2232
|
+
}
|
|
2233
|
+
if (tokenString != null) {
|
|
2234
|
+
const tokens = this.tokenizer.tokenize(tokenString);
|
|
2235
|
+
while (tokens.length) {
|
|
2236
|
+
const currentTokens = tokens.splice(0, 100);
|
|
2237
|
+
const params = {
|
|
2238
|
+
guid,
|
|
2239
|
+
name,
|
|
2240
|
+
};
|
|
2241
|
+
const values = [];
|
|
2242
|
+
for (let i = 0; i < currentTokens.length; i++) {
|
|
2243
|
+
const token = currentTokens[i];
|
|
2244
|
+
params['token' + i] = token.token;
|
|
2245
|
+
params['position' + i] = token.position;
|
|
2246
|
+
params['stem' + i] = token.stem ? 1 : 0;
|
|
2247
|
+
values.push('(@guid, @name, @token' +
|
|
2248
|
+
i +
|
|
2249
|
+
', @position' +
|
|
2250
|
+
i +
|
|
2251
|
+
', @stem' +
|
|
2252
|
+
i +
|
|
2253
|
+
')');
|
|
2254
|
+
}
|
|
2255
|
+
this.queryRun(`INSERT INTO ${SQLite3Driver.escape(`${this.prefix}tokens_${etype}`)} ("guid", "name", "token", "position", "stem") VALUES ${values.join(', ')};`, {
|
|
2256
|
+
etypes: [etype],
|
|
2257
|
+
params,
|
|
2258
|
+
});
|
|
2259
|
+
}
|
|
2260
|
+
}
|
|
1444
2261
|
};
|
|
2262
|
+
for (const unique of uniques) {
|
|
2263
|
+
try {
|
|
2264
|
+
this.queryRun(`INSERT INTO ${SQLite3Driver.escape(`${this.prefix}uniques_${etype}`)} ("guid", "unique") VALUES (@guid, @unique);`, {
|
|
2265
|
+
etypes: [etype],
|
|
2266
|
+
params: {
|
|
2267
|
+
guid,
|
|
2268
|
+
unique,
|
|
2269
|
+
},
|
|
2270
|
+
});
|
|
2271
|
+
}
|
|
2272
|
+
catch (e) {
|
|
2273
|
+
if (e instanceof EntityUniqueConstraintError) {
|
|
2274
|
+
this.nymph.config.debugError('sqlite3', `Save entity unique constraint violation for GUID "${guid}" on etype "${etype}": "${unique}"`);
|
|
2275
|
+
}
|
|
2276
|
+
throw e;
|
|
2277
|
+
}
|
|
2278
|
+
}
|
|
1445
2279
|
for (const name in data) {
|
|
1446
2280
|
runInsertQuery(name, data[name], JSON.stringify(data[name]));
|
|
1447
2281
|
}
|
|
@@ -1449,24 +2283,51 @@ class SQLite3Driver extends nymph_1.NymphDriver {
|
|
|
1449
2283
|
runInsertQuery(name, JSON.parse(sdata[name]), sdata[name]);
|
|
1450
2284
|
}
|
|
1451
2285
|
};
|
|
2286
|
+
let inTransaction = false;
|
|
1452
2287
|
try {
|
|
1453
|
-
return this.saveEntityRowLike(entity, async (
|
|
1454
|
-
|
|
2288
|
+
return this.saveEntityRowLike(entity, async ({ guid, tags, data, sdata, uniques, cdate, etype }) => {
|
|
2289
|
+
if (Object.keys(data).length === 0 &&
|
|
2290
|
+
Object.keys(sdata).length === 0) {
|
|
2291
|
+
return false;
|
|
2292
|
+
}
|
|
2293
|
+
let { user, group, acUser, acGroup, acOther, acRead, acWrite, acFull, } = this.removeAndReturnACValues(etype, data, sdata);
|
|
2294
|
+
this.queryRun(`INSERT INTO ${SQLite3Driver.escape(`${this.prefix}entities_${etype}`)} ("guid", "tags", "cdate", "mdate", "user", "group", "acUser", "acGroup", "acOther", "acRead", "acWrite", "acFull") VALUES (@guid, @tags, @cdate, @cdate, @user, @group, @acUser, @acGroup, @acOther, @acRead, @acWrite, @acFull);`, {
|
|
1455
2295
|
etypes: [etype],
|
|
1456
2296
|
params: {
|
|
1457
2297
|
guid,
|
|
1458
2298
|
tags: ',' + tags.join(',') + ',',
|
|
1459
2299
|
cdate,
|
|
2300
|
+
user,
|
|
2301
|
+
group,
|
|
2302
|
+
acUser,
|
|
2303
|
+
acGroup,
|
|
2304
|
+
acOther,
|
|
2305
|
+
acRead: acRead && ',' + acRead.join(',') + ',',
|
|
2306
|
+
acWrite: acWrite && ',' + acWrite.join(',') + ',',
|
|
2307
|
+
acFull: acFull && ',' + acFull.join(',') + ',',
|
|
1460
2308
|
},
|
|
1461
2309
|
});
|
|
1462
|
-
insertData(guid, data, sdata, etype);
|
|
2310
|
+
insertData(guid, data, sdata, uniques, etype);
|
|
1463
2311
|
return true;
|
|
1464
|
-
}, async (entity, guid, tags, data, sdata, mdate, etype) => {
|
|
1465
|
-
|
|
2312
|
+
}, async ({ entity, guid, tags, data, sdata, uniques, mdate, etype }) => {
|
|
2313
|
+
if (Object.keys(data).length === 0 &&
|
|
2314
|
+
Object.keys(sdata).length === 0) {
|
|
2315
|
+
return false;
|
|
2316
|
+
}
|
|
2317
|
+
let { user, group, acUser, acGroup, acOther, acRead, acWrite, acFull, } = this.removeAndReturnACValues(etype, data, sdata);
|
|
2318
|
+
const info = this.queryRun(`UPDATE ${SQLite3Driver.escape(`${this.prefix}entities_${etype}`)} SET "tags"=@tags, "mdate"=@mdate, "user"=@user, "group"=@group, "acUser"=@acUser, "acGroup"=@acGroup, "acOther"=@acOther, "acRead"=@acRead, "acWrite"=@acWrite, "acFull"=@acFull WHERE "guid"=@guid AND "mdate" <= @emdate;`, {
|
|
1466
2319
|
etypes: [etype],
|
|
1467
2320
|
params: {
|
|
1468
2321
|
tags: ',' + tags.join(',') + ',',
|
|
1469
2322
|
mdate,
|
|
2323
|
+
user,
|
|
2324
|
+
group,
|
|
2325
|
+
acUser,
|
|
2326
|
+
acGroup,
|
|
2327
|
+
acOther,
|
|
2328
|
+
acRead: acRead && ',' + acRead.join(',') + ',',
|
|
2329
|
+
acWrite: acWrite && ',' + acWrite.join(',') + ',',
|
|
2330
|
+
acFull: acFull && ',' + acFull.join(',') + ',',
|
|
1470
2331
|
guid,
|
|
1471
2332
|
emdate: Number(entity.mdate),
|
|
1472
2333
|
},
|
|
@@ -1479,44 +2340,57 @@ class SQLite3Driver extends nymph_1.NymphDriver {
|
|
|
1479
2340
|
guid,
|
|
1480
2341
|
},
|
|
1481
2342
|
});
|
|
1482
|
-
this.queryRun(`DELETE FROM ${SQLite3Driver.escape(`${this.prefix}
|
|
2343
|
+
this.queryRun(`DELETE FROM ${SQLite3Driver.escape(`${this.prefix}references_${etype}`)} WHERE "guid"=@guid;`, {
|
|
1483
2344
|
etypes: [etype],
|
|
1484
2345
|
params: {
|
|
1485
2346
|
guid,
|
|
1486
2347
|
},
|
|
1487
2348
|
});
|
|
1488
|
-
this.queryRun(`DELETE FROM ${SQLite3Driver.escape(`${this.prefix}
|
|
2349
|
+
this.queryRun(`DELETE FROM ${SQLite3Driver.escape(`${this.prefix}tokens_${etype}`)} WHERE "guid"=@guid;`, {
|
|
2350
|
+
etypes: [etype],
|
|
2351
|
+
params: {
|
|
2352
|
+
guid,
|
|
2353
|
+
},
|
|
2354
|
+
});
|
|
2355
|
+
this.queryRun(`DELETE FROM ${SQLite3Driver.escape(`${this.prefix}uniques_${etype}`)} WHERE "guid"=@guid;`, {
|
|
1489
2356
|
etypes: [etype],
|
|
1490
2357
|
params: {
|
|
1491
2358
|
guid,
|
|
1492
2359
|
},
|
|
1493
2360
|
});
|
|
1494
|
-
insertData(guid, data, sdata, etype);
|
|
2361
|
+
insertData(guid, data, sdata, uniques, etype);
|
|
1495
2362
|
success = true;
|
|
1496
2363
|
}
|
|
1497
2364
|
return success;
|
|
1498
2365
|
}, async () => {
|
|
1499
2366
|
await this.startTransaction('nymph-save');
|
|
2367
|
+
inTransaction = true;
|
|
1500
2368
|
}, async (success) => {
|
|
1501
|
-
if (
|
|
1502
|
-
|
|
1503
|
-
|
|
1504
|
-
|
|
1505
|
-
|
|
2369
|
+
if (inTransaction) {
|
|
2370
|
+
inTransaction = false;
|
|
2371
|
+
if (success) {
|
|
2372
|
+
await this.commit('nymph-save');
|
|
2373
|
+
}
|
|
2374
|
+
else {
|
|
2375
|
+
await this.rollback('nymph-save');
|
|
2376
|
+
}
|
|
1506
2377
|
}
|
|
1507
2378
|
return success;
|
|
1508
2379
|
});
|
|
1509
2380
|
}
|
|
1510
2381
|
catch (e) {
|
|
1511
|
-
|
|
2382
|
+
this.nymph.config.debugError('sqlite3', `Save entity error: "${e}"`);
|
|
2383
|
+
if (inTransaction) {
|
|
2384
|
+
await this.rollback('nymph-save');
|
|
2385
|
+
}
|
|
1512
2386
|
throw e;
|
|
1513
2387
|
}
|
|
1514
2388
|
}
|
|
1515
2389
|
async setUID(name, curUid) {
|
|
1516
2390
|
if (name == null) {
|
|
1517
|
-
throw new
|
|
2391
|
+
throw new InvalidParametersError('Name not given for UID.');
|
|
1518
2392
|
}
|
|
1519
|
-
this.
|
|
2393
|
+
await this.startTransaction('nymph-set-uid');
|
|
1520
2394
|
this.queryRun(`DELETE FROM ${SQLite3Driver.escape(`${this.prefix}uids`)} WHERE "name"=@name;`, {
|
|
1521
2395
|
params: {
|
|
1522
2396
|
name,
|
|
@@ -1528,16 +2402,124 @@ class SQLite3Driver extends nymph_1.NymphDriver {
|
|
|
1528
2402
|
curUid,
|
|
1529
2403
|
},
|
|
1530
2404
|
});
|
|
2405
|
+
await this.commit('nymph-set-uid');
|
|
1531
2406
|
return true;
|
|
1532
2407
|
}
|
|
2408
|
+
async internalTransaction(name) {
|
|
2409
|
+
await this.startTransaction(name);
|
|
2410
|
+
}
|
|
1533
2411
|
async startTransaction(name) {
|
|
1534
2412
|
if (name == null || typeof name !== 'string' || name.length === 0) {
|
|
1535
|
-
throw new
|
|
2413
|
+
throw new InvalidParametersError('Transaction start attempted without a name.');
|
|
2414
|
+
}
|
|
2415
|
+
if (!this.config.explicitWrite && !this.store.linkWrite) {
|
|
2416
|
+
this._connect(true);
|
|
1536
2417
|
}
|
|
1537
2418
|
this.queryRun(`SAVEPOINT ${SQLite3Driver.escape(name)};`);
|
|
1538
2419
|
this.store.transactionsStarted++;
|
|
1539
2420
|
return this.nymph;
|
|
1540
2421
|
}
|
|
2422
|
+
async removeTilmeldOldRows(etype) {
|
|
2423
|
+
await this.startTransaction('nymph-remove-tilmeld-rows');
|
|
2424
|
+
try {
|
|
2425
|
+
for (let name of [
|
|
2426
|
+
'user',
|
|
2427
|
+
'group',
|
|
2428
|
+
'acUser',
|
|
2429
|
+
'acGroup',
|
|
2430
|
+
'acOther',
|
|
2431
|
+
'acRead',
|
|
2432
|
+
'acWrite',
|
|
2433
|
+
'acFull',
|
|
2434
|
+
]) {
|
|
2435
|
+
this.queryRun(`DELETE FROM ${SQLite3Driver.escape(`${this.prefix}data_${etype}`)} WHERE "name"=@name;`, {
|
|
2436
|
+
etypes: [etype],
|
|
2437
|
+
params: {
|
|
2438
|
+
name,
|
|
2439
|
+
},
|
|
2440
|
+
});
|
|
2441
|
+
this.queryRun(`DELETE FROM ${SQLite3Driver.escape(`${this.prefix}references_${etype}`)} WHERE "name"=@name;`, {
|
|
2442
|
+
etypes: [etype],
|
|
2443
|
+
params: {
|
|
2444
|
+
name,
|
|
2445
|
+
},
|
|
2446
|
+
});
|
|
2447
|
+
this.queryRun(`DELETE FROM ${SQLite3Driver.escape(`${this.prefix}tokens_${etype}`)} WHERE "name"=@name;`, {
|
|
2448
|
+
etypes: [etype],
|
|
2449
|
+
params: {
|
|
2450
|
+
name,
|
|
2451
|
+
},
|
|
2452
|
+
});
|
|
2453
|
+
}
|
|
2454
|
+
}
|
|
2455
|
+
catch (e) {
|
|
2456
|
+
this.nymph.config.debugError('sqlite3', `Remove tilmeld rows error: "${e}"`);
|
|
2457
|
+
await this.rollback('nymph-remove-tilmeld-rows');
|
|
2458
|
+
throw e;
|
|
2459
|
+
}
|
|
2460
|
+
await this.commit('nymph-remove-tilmeld-rows');
|
|
2461
|
+
return true;
|
|
2462
|
+
}
|
|
2463
|
+
async needsMigration() {
|
|
2464
|
+
const table = this.queryGet("SELECT `name` FROM `sqlite_master` WHERE `type`='table' AND `name` LIKE @prefix LIMIT 1;", {
|
|
2465
|
+
params: {
|
|
2466
|
+
prefix: this.prefix + 'data_' + '%',
|
|
2467
|
+
},
|
|
2468
|
+
});
|
|
2469
|
+
if (table?.name) {
|
|
2470
|
+
const result = this.queryGet("SELECT 1 AS `exists` FROM pragma_table_info(@table) WHERE `name`='json';", {
|
|
2471
|
+
params: {
|
|
2472
|
+
table: table.name,
|
|
2473
|
+
},
|
|
2474
|
+
});
|
|
2475
|
+
if (!result?.exists) {
|
|
2476
|
+
return 'json';
|
|
2477
|
+
}
|
|
2478
|
+
}
|
|
2479
|
+
const table2 = this.queryGet("SELECT `name` FROM `sqlite_master` WHERE `type`='table' AND `name` LIKE @tokenTable LIMIT 1;", {
|
|
2480
|
+
params: {
|
|
2481
|
+
tokenTable: this.prefix + 'tokens_' + '%',
|
|
2482
|
+
},
|
|
2483
|
+
});
|
|
2484
|
+
if (!table2 || !table2.name) {
|
|
2485
|
+
return 'tokens';
|
|
2486
|
+
}
|
|
2487
|
+
const table3 = this.queryGet("SELECT `name` FROM `sqlite_master` WHERE `type`='table' AND `name` LIKE @prefix LIMIT 1;", {
|
|
2488
|
+
params: {
|
|
2489
|
+
prefix: this.prefix + 'entities_' + '%',
|
|
2490
|
+
},
|
|
2491
|
+
});
|
|
2492
|
+
if (table3?.name) {
|
|
2493
|
+
const result = this.queryGet("SELECT 1 AS `exists` FROM pragma_table_info(@table) WHERE `name`='user';", {
|
|
2494
|
+
params: {
|
|
2495
|
+
table: table3.name,
|
|
2496
|
+
},
|
|
2497
|
+
});
|
|
2498
|
+
if (!result?.exists) {
|
|
2499
|
+
return 'tilmeldColumns';
|
|
2500
|
+
}
|
|
2501
|
+
}
|
|
2502
|
+
return false;
|
|
2503
|
+
}
|
|
2504
|
+
async liveMigration(migrationType) {
|
|
2505
|
+
if (migrationType === 'tokenTables') {
|
|
2506
|
+
const etypes = await this.getEtypes();
|
|
2507
|
+
for (let etype of etypes) {
|
|
2508
|
+
this.createTokensTable(etype);
|
|
2509
|
+
}
|
|
2510
|
+
}
|
|
2511
|
+
else if (migrationType === 'tilmeldColumns') {
|
|
2512
|
+
const etypes = await this.getEtypes();
|
|
2513
|
+
for (let etype of etypes) {
|
|
2514
|
+
this.addTilmeldColumnsAndIndexes(etype);
|
|
2515
|
+
}
|
|
2516
|
+
}
|
|
2517
|
+
else if (migrationType === 'tilmeldRemoveOldRows') {
|
|
2518
|
+
const etypes = await this.getEtypes();
|
|
2519
|
+
for (let etype of etypes) {
|
|
2520
|
+
await this.removeTilmeldOldRows(etype);
|
|
2521
|
+
}
|
|
2522
|
+
}
|
|
2523
|
+
}
|
|
1541
2524
|
}
|
|
1542
|
-
exports.default = SQLite3Driver;
|
|
1543
2525
|
//# sourceMappingURL=SQLite3Driver.js.map
|