@saltcorn/data 0.6.2-beta.3 → 0.6.3-beta.0
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/dist/base-plugin/fileviews.d.ts +2 -2
- package/dist/base-plugin/index.d.ts +41 -36
- package/dist/base-plugin/index.d.ts.map +1 -1
- package/dist/base-plugin/types.d.ts +8 -8
- package/dist/base-plugin/types.d.ts.map +1 -1
- package/dist/base-plugin/viewtemplates/edit.d.ts +1 -1
- package/dist/base-plugin/viewtemplates/edit.d.ts.map +1 -1
- package/dist/base-plugin/viewtemplates/edit.js +25 -2
- package/dist/base-plugin/viewtemplates/edit.js.map +1 -1
- package/dist/base-plugin/viewtemplates/feed.d.ts +1 -1
- package/dist/base-plugin/viewtemplates/feed.d.ts.map +1 -1
- package/dist/base-plugin/viewtemplates/feed.js +11 -1
- package/dist/base-plugin/viewtemplates/feed.js.map +1 -1
- package/dist/base-plugin/viewtemplates/list.d.ts +1 -1
- package/dist/base-plugin/viewtemplates/list.d.ts.map +1 -1
- package/dist/base-plugin/viewtemplates/list.js +23 -11
- package/dist/base-plugin/viewtemplates/list.js.map +1 -1
- package/dist/base-plugin/viewtemplates/show.d.ts +5 -0
- package/dist/base-plugin/viewtemplates/show.d.ts.map +1 -1
- package/dist/base-plugin/viewtemplates/show.js +34 -4
- package/dist/base-plugin/viewtemplates/show.js.map +1 -1
- package/dist/common_types.d.ts +28 -0
- package/dist/common_types.d.ts.map +1 -0
- package/dist/common_types.js +16 -0
- package/dist/common_types.js.map +1 -0
- package/dist/db/index.d.ts.map +1 -1
- package/dist/db/index.js.map +1 -1
- package/dist/db/state.d.ts.map +1 -1
- package/dist/db/state.js +2 -0
- package/dist/db/state.js.map +1 -1
- package/dist/models/backup.d.ts +6 -21
- package/dist/models/backup.d.ts.map +1 -1
- package/dist/models/backup.js +48 -44
- package/dist/models/backup.js.map +1 -1
- package/dist/models/config.d.ts.map +1 -1
- package/dist/models/config.js +3 -1
- package/dist/models/config.js.map +1 -1
- package/dist/models/eventlog.d.ts +39 -38
- package/dist/models/eventlog.d.ts.map +1 -1
- package/dist/models/eventlog.js +14 -29
- package/dist/models/eventlog.js.map +1 -1
- package/dist/models/expression.d.ts.map +1 -1
- package/dist/models/expression.js +14 -3
- package/dist/models/expression.js.map +1 -1
- package/dist/models/field.d.ts +123 -120
- package/dist/models/field.d.ts.map +1 -1
- package/dist/models/field.js +129 -147
- package/dist/models/field.js.map +1 -1
- package/dist/models/form.d.ts.map +1 -1
- package/dist/models/form.js +2 -0
- package/dist/models/form.js.map +1 -1
- package/dist/models/library.d.ts +29 -19
- package/dist/models/library.d.ts.map +1 -1
- package/dist/models/library.js +10 -8
- package/dist/models/library.js.map +1 -1
- package/dist/models/role.d.ts +13 -9
- package/dist/models/role.d.ts.map +1 -1
- package/dist/models/role.js +10 -7
- package/dist/models/role.js.map +1 -1
- package/dist/models/table.d.ts +85 -132
- package/dist/models/table.d.ts.map +1 -1
- package/dist/models/table.js +172 -177
- package/dist/models/table.js.map +1 -1
- package/dist/models/tenant.d.ts +6 -0
- package/dist/models/tenant.d.ts.map +1 -1
- package/dist/models/tenant.js +9 -0
- package/dist/models/tenant.js.map +1 -1
- package/dist/models/trigger.d.ts +62 -66
- package/dist/models/trigger.d.ts.map +1 -1
- package/dist/models/trigger.js +7 -33
- package/dist/models/trigger.js.map +1 -1
- package/dist/tests/calc.test.js +13 -0
- package/dist/tests/calc.test.js.map +1 -1
- package/dist/tests/exact_views.test.js +214 -0
- package/dist/tests/exact_views.test.js.map +1 -1
- package/dist/tests/table.test.js +7 -0
- package/dist/tests/table.test.js.map +1 -1
- package/dist/tsconfig.ref.tsbuildinfo +1 -1
- package/dist/utils.d.ts +2 -0
- package/dist/utils.d.ts.map +1 -1
- package/dist/utils.js +26 -0
- package/dist/utils.js.map +1 -1
- package/package.json +11 -6
package/dist/models/table.js
CHANGED
|
@@ -1,20 +1,24 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
2
5
|
/**
|
|
3
6
|
* Table Database Access Layer
|
|
4
7
|
* @category saltcorn-data
|
|
5
8
|
* @module models/table
|
|
6
9
|
* @subcategory models
|
|
7
10
|
*/
|
|
8
|
-
const
|
|
9
|
-
const
|
|
10
|
-
const
|
|
11
|
-
const
|
|
11
|
+
const db_1 = __importDefault(require("../db"));
|
|
12
|
+
const internal_1 = require("@saltcorn/db-common/internal");
|
|
13
|
+
const field_1 = __importDefault(require("./field"));
|
|
14
|
+
const common_types_1 = require("../common_types");
|
|
15
|
+
const trigger_1 = __importDefault(require("./trigger"));
|
|
12
16
|
const { apply_calculated_fields, apply_calculated_fields_stored, recalculate_for_stored, get_expression_function, } = require("./expression");
|
|
13
|
-
const
|
|
14
|
-
const
|
|
15
|
-
const
|
|
16
|
-
const
|
|
17
|
-
const
|
|
17
|
+
const csvtojson_1 = __importDefault(require("csvtojson"));
|
|
18
|
+
const moment_1 = __importDefault(require("moment"));
|
|
19
|
+
const fs_1 = require("fs");
|
|
20
|
+
const promises_1 = require("fs/promises");
|
|
21
|
+
const utils_1 = require("../utils");
|
|
18
22
|
const { InvalidConfiguration, InvalidAdminAction, satisfies, structuredClone, getLines, } = require("../utils");
|
|
19
23
|
/**
|
|
20
24
|
* Transponce Objects
|
|
@@ -40,7 +44,7 @@ const transposeObjects = (objs) => {
|
|
|
40
44
|
return res;
|
|
41
45
|
};
|
|
42
46
|
// todo support also other date formats https://momentjs.com/docs/
|
|
43
|
-
const dateFormats = [
|
|
47
|
+
const dateFormats = [moment_1.default.ISO_8601];
|
|
44
48
|
// todo refactor - move to separated data utils module?
|
|
45
49
|
/**
|
|
46
50
|
* Is Valid Date of format moment.ISO_8601,
|
|
@@ -50,7 +54,7 @@ const dateFormats = [moment.ISO_8601];
|
|
|
50
54
|
* @returns {boolean}
|
|
51
55
|
*/
|
|
52
56
|
const isDate = function (date) {
|
|
53
|
-
return
|
|
57
|
+
return (0, moment_1.default)(date, dateFormats, true).isValid();
|
|
54
58
|
};
|
|
55
59
|
// todo resolve database specific
|
|
56
60
|
/**
|
|
@@ -59,7 +63,7 @@ const isDate = function (date) {
|
|
|
59
63
|
* @returns {string}
|
|
60
64
|
*/
|
|
61
65
|
// todo refactor
|
|
62
|
-
const normalise_error_message = (msg) =>
|
|
66
|
+
const normalise_error_message = (msg) => db_1.default.isSQLite
|
|
63
67
|
? msg.replace(/SQLITE_CONSTRAINT: UNIQUE constraint failed: (.*?)\.(.*?)/, "Duplicate value for unique field: $2")
|
|
64
68
|
: msg.replace(/duplicate key value violates unique constraint "(.*?)_(.*?)_unique"/, "Duplicate value for unique field: $2");
|
|
65
69
|
/**
|
|
@@ -82,8 +86,7 @@ class Table {
|
|
|
82
86
|
this.external = false;
|
|
83
87
|
this.description = o.description;
|
|
84
88
|
if (o.fields)
|
|
85
|
-
this.fields = o.fields.map((f) => new
|
|
86
|
-
contract.class(this);
|
|
89
|
+
this.fields = o.fields.map((f) => new field_1.default(f));
|
|
87
90
|
}
|
|
88
91
|
/**
|
|
89
92
|
*
|
|
@@ -125,7 +128,7 @@ class Table {
|
|
|
125
128
|
const { getState } = require("../db/state");
|
|
126
129
|
return getState().tables.map((t) => new Table(t));
|
|
127
130
|
}
|
|
128
|
-
const tbls = await
|
|
131
|
+
const tbls = await db_1.default.select("_sc_tables", where, selectopts);
|
|
129
132
|
return tbls.map((t) => new Table(t));
|
|
130
133
|
}
|
|
131
134
|
/**
|
|
@@ -144,7 +147,7 @@ class Table {
|
|
|
144
147
|
}
|
|
145
148
|
if (external !== true) {
|
|
146
149
|
//do include db tables
|
|
147
|
-
const tbls = await
|
|
150
|
+
const tbls = await db_1.default.select("_sc_tables", where, selectopts);
|
|
148
151
|
dbs = tbls.map((t) => new Table(t));
|
|
149
152
|
}
|
|
150
153
|
return [...dbs, ...externals];
|
|
@@ -155,10 +158,10 @@ class Table {
|
|
|
155
158
|
* @returns {null|*} null or owner column name
|
|
156
159
|
*/
|
|
157
160
|
owner_fieldname_from_fields(fields) {
|
|
158
|
-
if (!this.ownership_field_id)
|
|
161
|
+
if (!this.ownership_field_id || !fields)
|
|
159
162
|
return null;
|
|
160
163
|
const field = fields.find((f) => f.id === this.ownership_field_id);
|
|
161
|
-
return field
|
|
164
|
+
return field?.name;
|
|
162
165
|
}
|
|
163
166
|
/**
|
|
164
167
|
* Get owner column name
|
|
@@ -185,7 +188,9 @@ class Table {
|
|
|
185
188
|
return f(row, user);
|
|
186
189
|
}
|
|
187
190
|
const field_name = this.owner_fieldname();
|
|
188
|
-
|
|
191
|
+
if (!field_name && this.name === "users")
|
|
192
|
+
return user && user.id && row && `${row.id}` === `${user.id}`;
|
|
193
|
+
return typeof field_name === "string" && row[field_name] === user.id;
|
|
189
194
|
}
|
|
190
195
|
/**
|
|
191
196
|
* Create table
|
|
@@ -194,9 +199,9 @@ class Table {
|
|
|
194
199
|
* @returns {Promise<Table>} table
|
|
195
200
|
*/
|
|
196
201
|
static async create(name, options = {}) {
|
|
197
|
-
const schema =
|
|
202
|
+
const schema = db_1.default.getTenantSchemaPrefix();
|
|
198
203
|
// create table in database
|
|
199
|
-
await
|
|
204
|
+
await db_1.default.query(`create table ${schema}"${(0, internal_1.sqlsanitize)(name)}" (id ${db_1.default.isSQLite ? "integer" : "serial"} primary key)`);
|
|
200
205
|
// populate table definition row
|
|
201
206
|
const tblrow = {
|
|
202
207
|
name,
|
|
@@ -208,9 +213,9 @@ class Table {
|
|
|
208
213
|
description: options.description || "",
|
|
209
214
|
};
|
|
210
215
|
// insert table defintion into _sc_tables
|
|
211
|
-
const id = await
|
|
216
|
+
const id = await db_1.default.insert("_sc_tables", tblrow);
|
|
212
217
|
// add primary key columnt ID
|
|
213
|
-
await
|
|
218
|
+
await db_1.default.query(`insert into ${schema}_sc_fields(table_id, name, label, type, attributes, required, is_unique,primary_key)
|
|
214
219
|
values($1,'id','ID','Integer', '{}', true, true, true)`, [id]);
|
|
215
220
|
// create table
|
|
216
221
|
const table = new Table({ ...tblrow, id });
|
|
@@ -226,20 +231,20 @@ class Table {
|
|
|
226
231
|
* @returns {Promise<void>}
|
|
227
232
|
*/
|
|
228
233
|
async delete(only_forget = false) {
|
|
229
|
-
const schema =
|
|
230
|
-
const is_sqlite =
|
|
234
|
+
const schema = db_1.default.getTenantSchemaPrefix();
|
|
235
|
+
const is_sqlite = db_1.default.isSQLite;
|
|
231
236
|
await this.update({ ownership_field_id: null });
|
|
232
|
-
const client = is_sqlite ?
|
|
237
|
+
const client = is_sqlite ? db_1.default : await db_1.default.getClient();
|
|
233
238
|
await client.query(`BEGIN`);
|
|
234
239
|
try {
|
|
235
240
|
if (!only_forget)
|
|
236
|
-
await client.query(`drop table if exists ${schema}"${sqlsanitize(this.name)}"`);
|
|
241
|
+
await client.query(`drop table if exists ${schema}"${(0, internal_1.sqlsanitize)(this.name)}"`);
|
|
237
242
|
await client.query(`delete FROM ${schema}_sc_fields WHERE table_id = $1`, [this.id]);
|
|
238
243
|
await client.query(`delete FROM ${schema}_sc_tables WHERE id = $1`, [
|
|
239
244
|
this.id,
|
|
240
245
|
]);
|
|
241
246
|
if (this.versioned)
|
|
242
|
-
await client.query(`drop table if exists ${schema}"${sqlsanitize(this.name)}__history"`);
|
|
247
|
+
await client.query(`drop table if exists ${schema}"${(0, internal_1.sqlsanitize)(this.name)}__history"`);
|
|
243
248
|
await client.query(`COMMIT`);
|
|
244
249
|
}
|
|
245
250
|
catch (e) {
|
|
@@ -257,7 +262,7 @@ class Table {
|
|
|
257
262
|
* @type {string}
|
|
258
263
|
*/
|
|
259
264
|
get sql_name() {
|
|
260
|
-
return `${
|
|
265
|
+
return `${db_1.default.getTenantSchemaPrefix()}"${(0, internal_1.sqlsanitize)(this.name)}"`;
|
|
261
266
|
}
|
|
262
267
|
/**
|
|
263
268
|
* Delete rows from table
|
|
@@ -266,7 +271,7 @@ class Table {
|
|
|
266
271
|
*/
|
|
267
272
|
async deleteRows(where) {
|
|
268
273
|
// get triggers on delete
|
|
269
|
-
const triggers = await
|
|
274
|
+
const triggers = await trigger_1.default.getTableTriggers("Delete", this);
|
|
270
275
|
if (triggers.length > 0) {
|
|
271
276
|
const rows = await this.getRows(where);
|
|
272
277
|
for (const trigger of triggers) {
|
|
@@ -276,7 +281,7 @@ class Table {
|
|
|
276
281
|
}
|
|
277
282
|
}
|
|
278
283
|
}
|
|
279
|
-
await
|
|
284
|
+
await db_1.default.deleteWhere(this.name, where);
|
|
280
285
|
}
|
|
281
286
|
/**
|
|
282
287
|
* Returns row with only fields that can be read from db (readFromDB flag)
|
|
@@ -284,9 +289,11 @@ class Table {
|
|
|
284
289
|
* @returns {*}
|
|
285
290
|
*/
|
|
286
291
|
readFromDB(row) {
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
292
|
+
if (this.fields) {
|
|
293
|
+
for (const f of this.fields) {
|
|
294
|
+
if (f.type && (0, common_types_1.instanceOfTypeObj)(f.type) && f.type.readFromDB)
|
|
295
|
+
row[f.name] = f.type.readFromDB(row[f.name]);
|
|
296
|
+
}
|
|
290
297
|
}
|
|
291
298
|
return row;
|
|
292
299
|
}
|
|
@@ -297,7 +304,7 @@ class Table {
|
|
|
297
304
|
*/
|
|
298
305
|
async getRow(where = {}) {
|
|
299
306
|
await this.getFields();
|
|
300
|
-
const row = await
|
|
307
|
+
const row = await db_1.default.selectMaybeOne(this.name, where);
|
|
301
308
|
if (!row)
|
|
302
309
|
return null;
|
|
303
310
|
return apply_calculated_fields([this.readFromDB(row)], this.fields)[0];
|
|
@@ -310,7 +317,7 @@ class Table {
|
|
|
310
317
|
*/
|
|
311
318
|
async getRows(where = {}, selopts) {
|
|
312
319
|
await this.getFields();
|
|
313
|
-
const rows = await
|
|
320
|
+
const rows = await db_1.default.select(this.name, where, selopts);
|
|
314
321
|
return apply_calculated_fields(rows.map((r) => this.readFromDB(r)), this.fields);
|
|
315
322
|
}
|
|
316
323
|
/**
|
|
@@ -319,7 +326,7 @@ class Table {
|
|
|
319
326
|
* @returns {Promise<number>}
|
|
320
327
|
*/
|
|
321
328
|
async countRows(where) {
|
|
322
|
-
return await
|
|
329
|
+
return await db_1.default.count(this.name, where);
|
|
323
330
|
}
|
|
324
331
|
/**
|
|
325
332
|
* Return distinct Values for column in table
|
|
@@ -328,7 +335,7 @@ class Table {
|
|
|
328
335
|
* @returns {Promise<Object[]>}
|
|
329
336
|
*/
|
|
330
337
|
async distinctValues(fieldnm) {
|
|
331
|
-
const res = await
|
|
338
|
+
const res = await db_1.default.query(`select distinct "${db_1.default.sqlsanitize(fieldnm)}" from ${this.sql_name}`);
|
|
332
339
|
return res.rows.map((r) => r[fieldnm]);
|
|
333
340
|
}
|
|
334
341
|
/**
|
|
@@ -344,15 +351,15 @@ class Table {
|
|
|
344
351
|
const fields = await this.getFields();
|
|
345
352
|
const pk_name = this.pk_name;
|
|
346
353
|
if (fields.some((f) => f.calculated && f.stored)) {
|
|
347
|
-
existing = await
|
|
354
|
+
existing = await db_1.default.selectOne(this.name, { [pk_name]: id });
|
|
348
355
|
v = await apply_calculated_fields_stored({ ...existing, ...v_in }, this.fields);
|
|
349
356
|
}
|
|
350
357
|
else
|
|
351
358
|
v = v_in;
|
|
352
359
|
if (this.versioned) {
|
|
353
360
|
if (!existing)
|
|
354
|
-
existing = await
|
|
355
|
-
await
|
|
361
|
+
existing = await db_1.default.selectOne(this.name, { [pk_name]: id });
|
|
362
|
+
await db_1.default.insert(this.name + "__history", {
|
|
356
363
|
...existing,
|
|
357
364
|
...v,
|
|
358
365
|
[pk_name]: id,
|
|
@@ -363,14 +370,14 @@ class Table {
|
|
|
363
370
|
_userid,
|
|
364
371
|
});
|
|
365
372
|
}
|
|
366
|
-
await
|
|
373
|
+
await db_1.default.update(this.name, v, id, { pk_name });
|
|
367
374
|
if (typeof existing === "undefined") {
|
|
368
|
-
const triggers = await
|
|
375
|
+
const triggers = await trigger_1.default.getTableTriggers("Update", this);
|
|
369
376
|
if (triggers.length > 0)
|
|
370
|
-
existing = await
|
|
377
|
+
existing = await db_1.default.selectOne(this.name, { [pk_name]: id });
|
|
371
378
|
}
|
|
372
379
|
const newRow = { ...existing, ...v, [pk_name]: id };
|
|
373
|
-
await
|
|
380
|
+
await trigger_1.default.runTableTriggers("Update", this, newRow);
|
|
374
381
|
}
|
|
375
382
|
/**
|
|
376
383
|
* Try to Update row
|
|
@@ -395,11 +402,13 @@ class Table {
|
|
|
395
402
|
* @returns {Promise<void>}
|
|
396
403
|
*/
|
|
397
404
|
async toggleBool(id, field_name) {
|
|
398
|
-
const schema =
|
|
399
|
-
await
|
|
400
|
-
const triggers = await
|
|
405
|
+
const schema = db_1.default.getTenantSchemaPrefix();
|
|
406
|
+
await db_1.default.query(`update ${schema}"${(0, internal_1.sqlsanitize)(this.name)}" set "${(0, internal_1.sqlsanitize)(field_name)}"=NOT coalesce("${(0, internal_1.sqlsanitize)(field_name)}", false) where id=$1`, [id]);
|
|
407
|
+
const triggers = await trigger_1.default.getTableTriggers("Update", this);
|
|
401
408
|
if (triggers.length > 0) {
|
|
402
409
|
const row = await this.getRow({ id });
|
|
410
|
+
if (!row)
|
|
411
|
+
throw new Error(`Unable to find row with id: ${id}`);
|
|
403
412
|
for (const trigger of triggers) {
|
|
404
413
|
await trigger.run(row);
|
|
405
414
|
}
|
|
@@ -410,7 +419,11 @@ class Table {
|
|
|
410
419
|
* @type {string}
|
|
411
420
|
*/
|
|
412
421
|
get pk_name() {
|
|
413
|
-
|
|
422
|
+
const pkField = this.fields?.find((f) => f.primary_key)?.name;
|
|
423
|
+
if (!pkField) {
|
|
424
|
+
throw new Error("A primary key field is mandatory");
|
|
425
|
+
}
|
|
426
|
+
return pkField;
|
|
414
427
|
}
|
|
415
428
|
/**
|
|
416
429
|
* Insert row
|
|
@@ -422,16 +435,16 @@ class Table {
|
|
|
422
435
|
await this.getFields();
|
|
423
436
|
const v = await apply_calculated_fields_stored(v_in, this.fields);
|
|
424
437
|
const pk_name = this.pk_name;
|
|
425
|
-
const id = await
|
|
438
|
+
const id = await db_1.default.insert(this.name, v, { pk_name });
|
|
426
439
|
if (this.versioned)
|
|
427
|
-
await
|
|
440
|
+
await db_1.default.insert(this.name + "__history", {
|
|
428
441
|
...v,
|
|
429
442
|
[pk_name]: id,
|
|
430
443
|
_version: 1,
|
|
431
444
|
_userid,
|
|
432
445
|
_time: new Date(),
|
|
433
446
|
});
|
|
434
|
-
|
|
447
|
+
trigger_1.default.runTableTriggers("Insert", this, { [pk_name]: id, ...v });
|
|
435
448
|
return id;
|
|
436
449
|
}
|
|
437
450
|
/**
|
|
@@ -455,7 +468,10 @@ class Table {
|
|
|
455
468
|
*/
|
|
456
469
|
async getFields() {
|
|
457
470
|
if (!this.fields) {
|
|
458
|
-
this.fields = await
|
|
471
|
+
this.fields = await field_1.default.find({ table_id: this.id }, { orderBy: "id" });
|
|
472
|
+
for (let field of this.fields) {
|
|
473
|
+
field.table = this;
|
|
474
|
+
}
|
|
459
475
|
}
|
|
460
476
|
return this.fields;
|
|
461
477
|
}
|
|
@@ -465,12 +481,15 @@ class Table {
|
|
|
465
481
|
*/
|
|
466
482
|
// todo create function that returns history table name for table
|
|
467
483
|
async create_history_table() {
|
|
468
|
-
const schemaPrefix =
|
|
484
|
+
const schemaPrefix = db_1.default.getTenantSchemaPrefix();
|
|
469
485
|
const fields = await this.getFields();
|
|
470
|
-
const flds = fields.map((f) => `,"${sqlsanitize(f.name)}" ${f.sql_bare_type}`);
|
|
471
|
-
const pk = fields.find((f) => f.primary_key)
|
|
486
|
+
const flds = fields.map((f) => `,"${(0, internal_1.sqlsanitize)(f.name)}" ${f.sql_bare_type}`);
|
|
487
|
+
const pk = fields.find((f) => f.primary_key)?.name;
|
|
488
|
+
if (!pk) {
|
|
489
|
+
throw new Error("Unable to find a field with a primary key.");
|
|
490
|
+
}
|
|
472
491
|
// create history table
|
|
473
|
-
await
|
|
492
|
+
await db_1.default.query(`create table ${schemaPrefix}"${(0, internal_1.sqlsanitize)(this.name)}__history" (
|
|
474
493
|
_version integer,
|
|
475
494
|
_time timestamp,
|
|
476
495
|
_userid integer
|
|
@@ -483,9 +502,9 @@ class Table {
|
|
|
483
502
|
* @returns {Promise<void>}
|
|
484
503
|
*/
|
|
485
504
|
async drop_history_table() {
|
|
486
|
-
const schemaPrefix =
|
|
487
|
-
await
|
|
488
|
-
drop table ${schemaPrefix}"${sqlsanitize(this.name)}__history";`);
|
|
505
|
+
const schemaPrefix = db_1.default.getTenantSchemaPrefix();
|
|
506
|
+
await db_1.default.query(`
|
|
507
|
+
drop table ${schemaPrefix}"${(0, internal_1.sqlsanitize)(this.name)}__history";`);
|
|
489
508
|
}
|
|
490
509
|
/**
|
|
491
510
|
* Rename table
|
|
@@ -494,19 +513,19 @@ class Table {
|
|
|
494
513
|
*/
|
|
495
514
|
async rename(new_name) {
|
|
496
515
|
//in transaction
|
|
497
|
-
if (
|
|
516
|
+
if (db_1.default.isSQLite)
|
|
498
517
|
throw new InvalidAdminAction("Cannot rename table on SQLite");
|
|
499
|
-
const schemaPrefix =
|
|
500
|
-
const client = await
|
|
518
|
+
const schemaPrefix = db_1.default.getTenantSchemaPrefix();
|
|
519
|
+
const client = await db_1.default.getClient();
|
|
501
520
|
await client.query(`BEGIN`);
|
|
502
521
|
try {
|
|
503
522
|
//rename table
|
|
504
|
-
await
|
|
523
|
+
await db_1.default.query(`alter table ${schemaPrefix}"${(0, internal_1.sqlsanitize)(this.name)}" rename to "${(0, internal_1.sqlsanitize)(new_name)}";`);
|
|
505
524
|
//change refs
|
|
506
|
-
await
|
|
525
|
+
await db_1.default.query(`update ${schemaPrefix}_sc_fields set reftable_name=$1 where reftable_name=$2`, [(0, internal_1.sqlsanitize)(new_name), (0, internal_1.sqlsanitize)(this.name)]);
|
|
507
526
|
//rename history
|
|
508
527
|
if (this.versioned)
|
|
509
|
-
await
|
|
528
|
+
await db_1.default.query(`alter table ${schemaPrefix}"${(0, internal_1.sqlsanitize)(this.name)}__history" rename to "${(0, internal_1.sqlsanitize)(new_name)}__history";`);
|
|
510
529
|
//1. change record
|
|
511
530
|
await this.update({ name: new_name });
|
|
512
531
|
await client.query(`COMMIT`);
|
|
@@ -529,17 +548,25 @@ class Table {
|
|
|
529
548
|
if (new_table_rec.ownership_field_id === "")
|
|
530
549
|
delete new_table_rec.ownership_field_id;
|
|
531
550
|
const existing = await Table.findOne({ id: this.id });
|
|
551
|
+
if (!existing) {
|
|
552
|
+
throw new Error(`Unable to find table with id: ${this.id}`);
|
|
553
|
+
}
|
|
532
554
|
const { external, fields, ...upd_rec } = new_table_rec;
|
|
533
|
-
await
|
|
555
|
+
await db_1.default.update("_sc_tables", upd_rec, this.id);
|
|
534
556
|
await require("../db/state").getState().refresh_tables();
|
|
535
557
|
const new_table = await Table.findOne({ id: this.id });
|
|
536
|
-
if (new_table
|
|
537
|
-
|
|
558
|
+
if (!new_table) {
|
|
559
|
+
throw new Error(`Unable to find table with id: ${this.id}`);
|
|
538
560
|
}
|
|
539
|
-
else
|
|
540
|
-
|
|
561
|
+
else {
|
|
562
|
+
if (new_table.versioned && !existing.versioned) {
|
|
563
|
+
await new_table.create_history_table();
|
|
564
|
+
}
|
|
565
|
+
else if (!new_table.versioned && existing.versioned) {
|
|
566
|
+
await new_table.drop_history_table();
|
|
567
|
+
}
|
|
568
|
+
Object.assign(this, new_table_rec);
|
|
541
569
|
}
|
|
542
|
-
Object.assign(this, new_table_rec);
|
|
543
570
|
}
|
|
544
571
|
/**
|
|
545
572
|
* Get table history data
|
|
@@ -547,7 +574,7 @@ class Table {
|
|
|
547
574
|
* @returns {Promise<*>}
|
|
548
575
|
*/
|
|
549
576
|
async get_history(id) {
|
|
550
|
-
return await
|
|
577
|
+
return await db_1.default.select(`${(0, internal_1.sqlsanitize)(this.name)}__history`, { id }, { orderBy: "_version" });
|
|
551
578
|
}
|
|
552
579
|
/**
|
|
553
580
|
* Enable constraints
|
|
@@ -568,7 +595,7 @@ class Table {
|
|
|
568
595
|
let rows;
|
|
569
596
|
try {
|
|
570
597
|
const s = await getLines(filePath, 500);
|
|
571
|
-
rows = await
|
|
598
|
+
rows = await (0, csvtojson_1.default)().fromString(s); // todo agrument type unknown
|
|
572
599
|
}
|
|
573
600
|
catch (e) {
|
|
574
601
|
return { error: `Error processing CSV file` };
|
|
@@ -595,14 +622,14 @@ class Table {
|
|
|
595
622
|
type = "String";
|
|
596
623
|
const label = (k.charAt(0).toUpperCase() + k.slice(1)).replace(/_/g, " ");
|
|
597
624
|
//can fail here if: non integer i d, duplicate headers, invalid name
|
|
598
|
-
const fld = new
|
|
599
|
-
name:
|
|
625
|
+
const fld = new field_1.default({
|
|
626
|
+
name: field_1.default.labelToName(k),
|
|
600
627
|
required,
|
|
601
628
|
type,
|
|
602
629
|
table,
|
|
603
630
|
label,
|
|
604
631
|
});
|
|
605
|
-
if (
|
|
632
|
+
if (db_1.default.sqlsanitize(k.toLowerCase()) === "id") {
|
|
606
633
|
if (type !== "Integer") {
|
|
607
634
|
await table.delete();
|
|
608
635
|
return { error: `Columns named "id" must have only integers` };
|
|
@@ -613,14 +640,14 @@ class Table {
|
|
|
613
640
|
}
|
|
614
641
|
continue;
|
|
615
642
|
}
|
|
616
|
-
if (
|
|
643
|
+
if (db_1.default.sqlsanitize(fld.name) === "") {
|
|
617
644
|
await table.delete();
|
|
618
645
|
return {
|
|
619
646
|
error: `Invalid column name ${k} - Use A-Z, a-z, 0-9, _ only`,
|
|
620
647
|
};
|
|
621
648
|
}
|
|
622
649
|
try {
|
|
623
|
-
await
|
|
650
|
+
await field_1.default.create(fld);
|
|
624
651
|
}
|
|
625
652
|
catch (e) {
|
|
626
653
|
await table.delete();
|
|
@@ -628,7 +655,7 @@ class Table {
|
|
|
628
655
|
}
|
|
629
656
|
}
|
|
630
657
|
const parse_res = await table.import_csv_file(filePath);
|
|
631
|
-
if (
|
|
658
|
+
if ((0, common_types_1.instanceOfErrorMsg)(parse_res)) {
|
|
632
659
|
await table.delete();
|
|
633
660
|
return { error: parse_res.error };
|
|
634
661
|
}
|
|
@@ -648,7 +675,7 @@ class Table {
|
|
|
648
675
|
const { readStateStrict } = require("../plugin-helper");
|
|
649
676
|
try {
|
|
650
677
|
const s = await getLines(filePath, 1);
|
|
651
|
-
[headers] = await
|
|
678
|
+
[headers] = await (0, csvtojson_1.default)({
|
|
652
679
|
output: "csv",
|
|
653
680
|
noheader: true,
|
|
654
681
|
}).fromString(s); // todo agrument type unknown
|
|
@@ -680,15 +707,15 @@ class Table {
|
|
|
680
707
|
const colRe = new RegExp(`(${Object.keys(okHeaders).join("|")})`);
|
|
681
708
|
let i = 1;
|
|
682
709
|
let rejects = 0;
|
|
683
|
-
const client =
|
|
684
|
-
const stats = await
|
|
710
|
+
const client = db_1.default.isSQLite ? db_1.default : await db_1.default.getClient();
|
|
711
|
+
const stats = await (0, promises_1.stat)(filePath);
|
|
685
712
|
const fileSizeInMegabytes = stats.size / (1024 * 1024);
|
|
686
713
|
await client.query("BEGIN");
|
|
687
|
-
const readStream =
|
|
714
|
+
const readStream = (0, fs_1.createReadStream)(filePath);
|
|
688
715
|
try {
|
|
689
|
-
if (
|
|
716
|
+
if (db_1.default.copyFrom && fileSizeInMegabytes > 1) {
|
|
690
717
|
let theError;
|
|
691
|
-
const copyres = await
|
|
718
|
+
const copyres = await db_1.default
|
|
692
719
|
.copyFrom(readStream, this.name, fieldNames, client)
|
|
693
720
|
.catch((cate) => {
|
|
694
721
|
theError = cate;
|
|
@@ -704,7 +731,7 @@ class Table {
|
|
|
704
731
|
}
|
|
705
732
|
else {
|
|
706
733
|
await new Promise((resolve, reject) => {
|
|
707
|
-
|
|
734
|
+
(0, csvtojson_1.default)({
|
|
708
735
|
includeColumns: colRe,
|
|
709
736
|
})
|
|
710
737
|
.fromStream(readStream)
|
|
@@ -719,7 +746,7 @@ class Table {
|
|
|
719
746
|
});
|
|
720
747
|
const rowOk = readStateStrict(rec, fields);
|
|
721
748
|
if (rowOk)
|
|
722
|
-
await
|
|
749
|
+
await db_1.default.insert(this.name, rec, {
|
|
723
750
|
noid: true,
|
|
724
751
|
client,
|
|
725
752
|
pk_name,
|
|
@@ -729,7 +756,7 @@ class Table {
|
|
|
729
756
|
}
|
|
730
757
|
catch (e) {
|
|
731
758
|
await client.query("ROLLBACK");
|
|
732
|
-
if (!
|
|
759
|
+
if (!db_1.default.isSQLite)
|
|
733
760
|
await client.release(true);
|
|
734
761
|
reject({ error: `${e.message} in row ${i}` });
|
|
735
762
|
}
|
|
@@ -748,12 +775,19 @@ class Table {
|
|
|
748
775
|
};
|
|
749
776
|
}
|
|
750
777
|
await client.query("COMMIT");
|
|
751
|
-
if (!
|
|
778
|
+
if (!db_1.default.isSQLite)
|
|
752
779
|
await client.release(true);
|
|
753
780
|
const pk = fields.find((f) => f.primary_key);
|
|
754
|
-
if (
|
|
755
|
-
|
|
756
|
-
|
|
781
|
+
if (!pk) {
|
|
782
|
+
throw new Error("Unable to find a field with a primary key.");
|
|
783
|
+
}
|
|
784
|
+
if (db_1.default.reset_sequence &&
|
|
785
|
+
(0, common_types_1.instanceOfTypeObj)(pk.type) &&
|
|
786
|
+
pk.type.name === "Integer")
|
|
787
|
+
await db_1.default.reset_sequence(this.name);
|
|
788
|
+
if (recalc_stored &&
|
|
789
|
+
this.fields &&
|
|
790
|
+
this.fields.some((f) => f.calculated && f.stored)) {
|
|
757
791
|
await recalculate_for_stored(this);
|
|
758
792
|
}
|
|
759
793
|
return {
|
|
@@ -768,12 +802,12 @@ class Table {
|
|
|
768
802
|
*/
|
|
769
803
|
async import_json_file(filePath, skip_first_data_row) {
|
|
770
804
|
// todo argument type buffer is not assignable for type String...
|
|
771
|
-
const file_rows = JSON.parse(await
|
|
805
|
+
const file_rows = JSON.parse(await (await (0, promises_1.readFile)(filePath)).toString());
|
|
772
806
|
const fields = await this.getFields();
|
|
773
807
|
const pk_name = this.pk_name;
|
|
774
808
|
const { readState } = require("../plugin-helper");
|
|
775
809
|
let i = 1;
|
|
776
|
-
const client =
|
|
810
|
+
const client = db_1.default.isSQLite ? db_1.default : await db_1.default.getClient();
|
|
777
811
|
await client.query("BEGIN");
|
|
778
812
|
for (const rec of file_rows) {
|
|
779
813
|
i += 1;
|
|
@@ -788,21 +822,25 @@ class Table {
|
|
|
788
822
|
});
|
|
789
823
|
try {
|
|
790
824
|
readState(rec, fields);
|
|
791
|
-
await
|
|
825
|
+
await db_1.default.insert(this.name, rec, { noid: true, client, pk_name });
|
|
792
826
|
}
|
|
793
827
|
catch (e) {
|
|
794
828
|
await client.query("ROLLBACK");
|
|
795
|
-
if (!
|
|
829
|
+
if (!db_1.default.isSQLite)
|
|
796
830
|
await client.release(true);
|
|
797
831
|
return { error: `${e.message} in row ${i}` };
|
|
798
832
|
}
|
|
799
833
|
}
|
|
800
834
|
await client.query("COMMIT");
|
|
801
|
-
if (!
|
|
835
|
+
if (!db_1.default.isSQLite)
|
|
802
836
|
await client.release(true);
|
|
803
837
|
const pk = fields.find((f) => f.primary_key);
|
|
804
|
-
if (
|
|
805
|
-
|
|
838
|
+
if (!pk)
|
|
839
|
+
throw new Error("Unable to find a primary key field.");
|
|
840
|
+
if (db_1.default.reset_sequence &&
|
|
841
|
+
(0, common_types_1.instanceOfTypeObj)(pk.type) &&
|
|
842
|
+
pk.type.name === "Integer")
|
|
843
|
+
await db_1.default.reset_sequence(this.name);
|
|
806
844
|
return {
|
|
807
845
|
success: `Imported ${file_rows.length} rows into table ${this.name}`,
|
|
808
846
|
};
|
|
@@ -819,15 +857,24 @@ class Table {
|
|
|
819
857
|
for (const f of fields) {
|
|
820
858
|
if (f.is_fkey && f.type !== "File") {
|
|
821
859
|
const table = await Table.findOne({ name: f.reftable_name });
|
|
860
|
+
if (!table)
|
|
861
|
+
throw new Error(`Unable to find table '${f.reftable_name}`);
|
|
822
862
|
await table.getFields();
|
|
863
|
+
if (!table.fields)
|
|
864
|
+
throw new Error(`The table '${f.reftable_name} has no fields.`);
|
|
823
865
|
for (const pf of table.fields.filter((f) => !f.calculated || f.stored)) {
|
|
824
866
|
parent_field_list.push(`${f.name}.${pf.name}`);
|
|
825
867
|
if (pf.is_fkey && pf.type !== "File" && allow_double) {
|
|
826
868
|
const table1 = await Table.findOne({ name: pf.reftable_name });
|
|
869
|
+
if (!table1)
|
|
870
|
+
throw new Error(`Unable to find table '${pf.reftable_name}`);
|
|
827
871
|
await table1.getFields();
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
872
|
+
if (!table1.fields)
|
|
873
|
+
throw new Error(`The table '${pf.reftable_name} has no fields.`);
|
|
874
|
+
if (table1.fields)
|
|
875
|
+
for (const gpf of table1.fields.filter((f) => !f.calculated || f.stored)) {
|
|
876
|
+
parent_field_list.push(`${f.name}.${pf.name}.${gpf.name}`);
|
|
877
|
+
}
|
|
831
878
|
parent_relations.push({ key_field: pf, through: f, table: table1 });
|
|
832
879
|
}
|
|
833
880
|
}
|
|
@@ -841,12 +888,15 @@ class Table {
|
|
|
841
888
|
* @returns {Promise<{child_relations: object[], child_field_list: object[]}>}
|
|
842
889
|
*/
|
|
843
890
|
async get_child_relations() {
|
|
844
|
-
const cfields = await
|
|
891
|
+
const cfields = await field_1.default.find({ reftable_name: this.name });
|
|
845
892
|
let child_relations = [];
|
|
846
893
|
let child_field_list = [];
|
|
847
894
|
for (const f of cfields) {
|
|
848
895
|
if (f.is_fkey) {
|
|
849
896
|
const table = await Table.findOne({ id: f.table_id });
|
|
897
|
+
if (!table) {
|
|
898
|
+
throw new Error(`Unable to find table with id: ${f.table_id}`);
|
|
899
|
+
}
|
|
850
900
|
child_field_list.push(`${table.name}.${f.name}`);
|
|
851
901
|
await table.getFields();
|
|
852
902
|
child_relations.push({ key_field: f, table });
|
|
@@ -865,7 +915,7 @@ class Table {
|
|
|
865
915
|
let joinq = "";
|
|
866
916
|
let joinTables = [];
|
|
867
917
|
let joinFields = opts.joinFields || [];
|
|
868
|
-
const schema =
|
|
918
|
+
const schema = db_1.default.getTenantSchemaPrefix();
|
|
869
919
|
fields
|
|
870
920
|
.filter((f) => f.type === "File")
|
|
871
921
|
.forEach((f) => {
|
|
@@ -882,10 +932,10 @@ class Table {
|
|
|
882
932
|
const reftable = reffield.reftable_name;
|
|
883
933
|
if (!reftable)
|
|
884
934
|
throw new InvalidConfiguration(`Field ${ref} is not a key field`);
|
|
885
|
-
const jtNm = `${sqlsanitize(reftable)}_jt_${sqlsanitize(ref)}`;
|
|
935
|
+
const jtNm = `${(0, internal_1.sqlsanitize)(reftable)}_jt_${(0, internal_1.sqlsanitize)(ref)}`;
|
|
886
936
|
if (!joinTables.includes(jtNm)) {
|
|
887
937
|
joinTables.push(jtNm);
|
|
888
|
-
joinq += ` left join ${schema}"${sqlsanitize(reftable)}" ${jtNm} on ${jtNm}."${reffield.refname}"=a."${sqlsanitize(ref)}"`;
|
|
938
|
+
joinq += ` left join ${schema}"${(0, internal_1.sqlsanitize)(reftable)}" ${jtNm} on ${jtNm}."${reffield.refname}"=a."${(0, internal_1.sqlsanitize)(ref)}"`;
|
|
889
939
|
}
|
|
890
940
|
if (through) {
|
|
891
941
|
const throughTable = await Table.findOne({
|
|
@@ -898,48 +948,42 @@ class Table {
|
|
|
898
948
|
if (!throughRefField)
|
|
899
949
|
throw new InvalidConfiguration(`Reference field field ${through} not found in table ${throughTable.name}`);
|
|
900
950
|
const finalTable = throughRefField.reftable_name;
|
|
901
|
-
const jtNm1 = `${sqlsanitize(reftable)}_jt_${sqlsanitize(through)}_jt_${sqlsanitize(ref)}`;
|
|
951
|
+
const jtNm1 = `${(0, internal_1.sqlsanitize)(reftable)}_jt_${(0, internal_1.sqlsanitize)(through)}_jt_${(0, internal_1.sqlsanitize)(ref)}`;
|
|
902
952
|
if (!joinTables.includes(jtNm1)) {
|
|
953
|
+
if (!finalTable)
|
|
954
|
+
throw new Error("Unable to build a joind without a reftable_name.");
|
|
903
955
|
joinTables.push(jtNm1);
|
|
904
|
-
joinq += ` left join ${schema}"${sqlsanitize(finalTable)}" ${jtNm1} on ${jtNm1}.id=${jtNm}."${sqlsanitize(through)}"`;
|
|
956
|
+
joinq += ` left join ${schema}"${(0, internal_1.sqlsanitize)(finalTable)}" ${jtNm1} on ${jtNm1}.id=${jtNm}."${(0, internal_1.sqlsanitize)(through)}"`;
|
|
905
957
|
}
|
|
906
|
-
fldNms.push(`${jtNm1}.${sqlsanitize(target)} as ${sqlsanitize(fldnm)}`);
|
|
958
|
+
fldNms.push(`${jtNm1}.${(0, internal_1.sqlsanitize)(target)} as ${(0, internal_1.sqlsanitize)(fldnm)}`);
|
|
907
959
|
}
|
|
908
960
|
else {
|
|
909
|
-
fldNms.push(`${jtNm}.${sqlsanitize(target)} as ${sqlsanitize(fldnm)}`);
|
|
961
|
+
fldNms.push(`${jtNm}.${(0, internal_1.sqlsanitize)(target)} as ${(0, internal_1.sqlsanitize)(fldnm)}`);
|
|
910
962
|
}
|
|
911
963
|
}
|
|
912
964
|
for (const f of fields.filter((f) => !f.calculated || f.stored)) {
|
|
913
|
-
fldNms.push(`a."${sqlsanitize(f.name)}"`);
|
|
965
|
+
fldNms.push(`a."${(0, internal_1.sqlsanitize)(f.name)}"`);
|
|
914
966
|
}
|
|
915
967
|
Object.entries(opts.aggregations || {}).forEach(([fldnm, { table, ref, field, where, aggregate, subselect }]) => {
|
|
916
968
|
if (aggregate.startsWith("Latest ")) {
|
|
917
969
|
const dateField = aggregate.replace("Latest ", "");
|
|
918
|
-
fldNms.push(`(select "${sqlsanitize(field)}" from ${schema}"${sqlsanitize(table)}" where ${dateField}=(select max(${dateField}) from ${schema}"${sqlsanitize(table)}" where "${sqlsanitize(ref)}"=a.id${where ? ` and ${where}` : ""}) and "${sqlsanitize(ref)}"=a.id) ${sqlsanitize(fldnm)}`);
|
|
970
|
+
fldNms.push(`(select "${(0, internal_1.sqlsanitize)(field)}" from ${schema}"${(0, internal_1.sqlsanitize)(table)}" where ${dateField}=(select max(${dateField}) from ${schema}"${(0, internal_1.sqlsanitize)(table)}" where "${(0, internal_1.sqlsanitize)(ref)}"=a.id${where ? ` and ${where}` : ""}) and "${(0, internal_1.sqlsanitize)(ref)}"=a.id) ${(0, internal_1.sqlsanitize)(fldnm)}`);
|
|
919
971
|
}
|
|
920
972
|
else if (subselect)
|
|
921
|
-
fldNms.push(`(select ${sqlsanitize(aggregate)}(${field ? `"${sqlsanitize(field)}"` : "*"}) from ${schema}"${sqlsanitize(table)}" where ${sqlsanitize(ref)} in (select "${subselect.field}" from ${schema}"${subselect.table.name}" where "${subselect.whereField}"=a.id)) ${sqlsanitize(fldnm)}`);
|
|
973
|
+
fldNms.push(`(select ${(0, internal_1.sqlsanitize)(aggregate)}(${field ? `"${(0, internal_1.sqlsanitize)(field)}"` : "*"}) from ${schema}"${(0, internal_1.sqlsanitize)(table)}" where ${(0, internal_1.sqlsanitize)(ref)} in (select "${subselect.field}" from ${schema}"${subselect.table.name}" where "${subselect.whereField}"=a.id)) ${(0, internal_1.sqlsanitize)(fldnm)}`);
|
|
922
974
|
else
|
|
923
|
-
fldNms.push(`(select ${sqlsanitize(aggregate)}(${field ? `"${sqlsanitize(field)}"` : "*"}) from ${schema}"${sqlsanitize(table)}" where "${sqlsanitize(ref)}"=a.id${where ? ` and ${where}` : ""}) ${sqlsanitize(fldnm)}`);
|
|
975
|
+
fldNms.push(`(select ${(0, internal_1.sqlsanitize)(aggregate)}(${field ? `"${(0, internal_1.sqlsanitize)(field)}"` : "*"}) from ${schema}"${(0, internal_1.sqlsanitize)(table)}" where "${(0, internal_1.sqlsanitize)(ref)}"=a.id${where ? ` and ${where}` : ""}) ${(0, internal_1.sqlsanitize)(fldnm)}`);
|
|
924
976
|
});
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
Object.keys(opts.where).forEach((k) => {
|
|
928
|
-
if (k === "_fts")
|
|
929
|
-
whereObj[k] = { table: "a", ...opts.where[k] };
|
|
930
|
-
else
|
|
931
|
-
whereObj[`a."${k}"`] = opts.where[k];
|
|
932
|
-
});
|
|
933
|
-
}
|
|
934
|
-
const { where, values } = mkWhere(whereObj, db.isSQLite);
|
|
977
|
+
const whereObj = (0, utils_1.prefixFieldsInWhere)(opts.where, "a");
|
|
978
|
+
const { where, values } = (0, internal_1.mkWhere)(whereObj, db_1.default.isSQLite);
|
|
935
979
|
const selectopts = {
|
|
936
980
|
limit: opts.limit,
|
|
937
981
|
orderBy: opts.orderBy &&
|
|
938
|
-
(opts.orderBy
|
|
982
|
+
((0, internal_1.orderByIsObject)(opts.orderBy) ? opts.orderBy : "a." + opts.orderBy),
|
|
939
983
|
orderDesc: opts.orderDesc,
|
|
940
984
|
offset: opts.offset,
|
|
941
985
|
};
|
|
942
|
-
const sql = `SELECT ${fldNms.join()} FROM ${schema}"${sqlsanitize(this.name)}" a ${joinq} ${where} ${mkSelectOptions(selectopts)}`;
|
|
986
|
+
const sql = `SELECT ${fldNms.join()} FROM ${schema}"${(0, internal_1.sqlsanitize)(this.name)}" a ${joinq} ${where} ${(0, internal_1.mkSelectOptions)(selectopts)}`;
|
|
943
987
|
return { sql, values };
|
|
944
988
|
}
|
|
945
989
|
/**
|
|
@@ -949,58 +993,9 @@ class Table {
|
|
|
949
993
|
async getJoinedRows(opts = {}) {
|
|
950
994
|
const fields = await this.getFields();
|
|
951
995
|
const { sql, values } = await this.getJoinedQuery(opts);
|
|
952
|
-
const res = await
|
|
996
|
+
const res = await db_1.default.query(sql, values);
|
|
953
997
|
return apply_calculated_fields(res.rows, fields);
|
|
954
998
|
}
|
|
955
999
|
}
|
|
956
|
-
/**
|
|
957
|
-
* Table contract
|
|
958
|
-
* @type {{variables: {name: ((function(*=): *)|*)}, methods: {updateRow: ((function(*=): *)|*), get_history: ((function(*=): *)|*), tryUpdateRow: ((function(*=): *)|*), deleteRows: ((function(*=): *)|*), update: ((function(*=): *)|*), getRows: ((function(*=): *)|*), getRow: ((function(*=): *)|*), delete: ((function(*=): *)|*), get_parent_relations: ((function(*=): *)|*), get_child_relations: ((function(*=): *)|*), tryInsertRow: ((function(*=): *)|*), getFields: ((function(*=): *)|*), insertRow: ((function(*=): *)|*), toggleBool: ((function(*=): *)|*), getJoinedRows: ((function(*=): *)|*), countRows: ((function(*=): *)|*), distinctValues: ((function(*=): *)|*), sql_name: ((function(*=): *)|*), import_csv_file: ((function(*=): *)|*)}, static_methods: {find: ((function(*=): *)|*), create_from_csv: ((function(*=): *)|*), findOne: ((function(*=): *)|*), find_with_external: ((function(*=): *)|*), create: ((function(*=): *)|*)}, constructs: {name: ((function(*=): *)|*)}}}
|
|
959
|
-
*/
|
|
960
|
-
Table.contract = {
|
|
961
|
-
constructs: { name: is.str },
|
|
962
|
-
variables: { name: is.str },
|
|
963
|
-
methods: {
|
|
964
|
-
delete: is.fun([], is.promise(is.eq(undefined))),
|
|
965
|
-
update: is.fun(is.obj(), is.promise(is.eq(undefined))),
|
|
966
|
-
deleteRows: is.fun(is.obj(), is.promise(is.eq(undefined))),
|
|
967
|
-
getRow: is.fun(is.maybe(is.obj()), is.promise(is.maybe(is.obj()))),
|
|
968
|
-
getRows: is.fun(is.maybe(is.obj()), is.promise(is.array(is.obj()))),
|
|
969
|
-
countRows: is.fun(is.maybe(is.obj()), is.promise(is.posint)),
|
|
970
|
-
updateRow: is.fun([is.obj(), is.any], is.promise(is.eq(undefined))),
|
|
971
|
-
toggleBool: is.fun([is.any, is.str], is.promise(is.eq(undefined))),
|
|
972
|
-
insertRow: is.fun(is.obj(), is.promise(is.any)),
|
|
973
|
-
get_history: is.fun(is.posint, is.promise(is.array(is.obj()))),
|
|
974
|
-
distinctValues: is.fun(is.str, is.promise(is.array(is.any))),
|
|
975
|
-
tryInsertRow: is.fun([is.obj(), is.maybe(is.posint)], is.promise(is.or(is.obj({ error: is.str }), is.obj({ success: is.any })))),
|
|
976
|
-
tryUpdateRow: is.fun([is.obj(), is.any, is.maybe(is.posint)], is.promise(is.or(is.obj({ error: is.str }), is.obj({ success: is.eq(true) })))),
|
|
977
|
-
sql_name: is.getter(is.str),
|
|
978
|
-
getFields: is.fun([], is.promise(is.array(is.class("Field")))),
|
|
979
|
-
get_parent_relations: is.fun([], is.promise(is.obj({
|
|
980
|
-
parent_relations: is.array(is.obj({
|
|
981
|
-
key_field: is.class("Field"),
|
|
982
|
-
table: is.class("Table"),
|
|
983
|
-
})),
|
|
984
|
-
parent_field_list: is.array(is.str),
|
|
985
|
-
}))),
|
|
986
|
-
get_child_relations: is.fun([], is.promise(is.obj({
|
|
987
|
-
child_relations: is.array(is.obj({
|
|
988
|
-
key_field: is.class("Field"),
|
|
989
|
-
table: is.class("Table"),
|
|
990
|
-
})),
|
|
991
|
-
child_field_list: is.array(is.str),
|
|
992
|
-
}))),
|
|
993
|
-
import_csv_file: is.fun(is.str, is.promise(is.or(is.obj({ success: is.str }), is.obj({ error: is.str })))),
|
|
994
|
-
getJoinedRows: is.fun(is.maybe(is_table_query), is.promise(is.array(is.obj({})))),
|
|
995
|
-
},
|
|
996
|
-
static_methods: {
|
|
997
|
-
find: is.fun([is.maybe(is.obj()), is.maybe(is.obj())], is.promise(is.array(is.class("Table")))),
|
|
998
|
-
find_with_external: is.fun([is.maybe(is.obj()), is.maybe(is.obj())], is.promise(is.array(is.or(is.class("Table"), is.obj({ external: is.eq(true) }))))),
|
|
999
|
-
findOne: is.fun(is.or(is.obj(), is.str, is.posint), is.maybe(is.or(is.class("Table"), is.obj({ external: is.eq(true) })))),
|
|
1000
|
-
create: is.fun(is.str, is.promise(is.class("Table"))),
|
|
1001
|
-
create_from_csv: is.fun([is.str, is.str], is.promise(is.or(is.obj({ success: is.str, table: is.class("Table") }), is.obj({ error: is.str })))),
|
|
1002
|
-
//update: is.fun([is.posint, is.obj({})], is.promise(is.eq(undefined)))
|
|
1003
|
-
},
|
|
1004
|
-
};
|
|
1005
1000
|
module.exports = Table;
|
|
1006
1001
|
//# sourceMappingURL=table.js.map
|