prostgles-server 2.0.146 → 2.0.147
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/AuthHandler.d.ts +15 -13
- package/dist/AuthHandler.d.ts.map +1 -1
- package/dist/AuthHandler.js +41 -43
- package/dist/AuthHandler.js.map +1 -1
- package/dist/DBEventsManager.d.ts +6 -5
- package/dist/DBEventsManager.d.ts.map +1 -1
- package/dist/DBEventsManager.js +8 -2
- package/dist/DBEventsManager.js.map +1 -1
- package/dist/DboBuilder.d.ts +62 -50
- package/dist/DboBuilder.d.ts.map +1 -1
- package/dist/DboBuilder.js +193 -167
- package/dist/DboBuilder.js.map +1 -1
- package/dist/FileManager.d.ts +5 -5
- package/dist/FileManager.d.ts.map +1 -1
- package/dist/FileManager.js +48 -21
- package/dist/FileManager.js.map +1 -1
- package/dist/Filtering.d.ts.map +1 -1
- package/dist/Filtering.js +11 -9
- package/dist/Filtering.js.map +1 -1
- package/dist/PostgresNotifListenManager.d.ts +3 -3
- package/dist/PostgresNotifListenManager.d.ts.map +1 -1
- package/dist/PostgresNotifListenManager.js +7 -5
- package/dist/PostgresNotifListenManager.js.map +1 -1
- package/dist/Prostgles.d.ts +6 -9
- package/dist/Prostgles.d.ts.map +1 -1
- package/dist/Prostgles.js +122 -83
- package/dist/Prostgles.js.map +1 -1
- package/dist/PubSubManager.d.ts +9 -9
- package/dist/PubSubManager.d.ts.map +1 -1
- package/dist/PubSubManager.js +10 -9
- package/dist/PubSubManager.js.map +1 -1
- package/dist/QueryBuilder.d.ts +7 -6
- package/dist/QueryBuilder.d.ts.map +1 -1
- package/dist/QueryBuilder.js +53 -23
- package/dist/QueryBuilder.js.map +1 -1
- package/dist/SyncReplication.d.ts +1 -1
- package/dist/SyncReplication.d.ts.map +1 -1
- package/dist/SyncReplication.js +31 -29
- package/dist/SyncReplication.js.map +1 -1
- package/dist/TableConfig.d.ts +0 -1
- package/dist/TableConfig.d.ts.map +1 -1
- package/dist/TableConfig.js +25 -17
- package/dist/TableConfig.js.map +1 -1
- package/dist/shortestPath.d.ts.map +1 -1
- package/dist/shortestPath.js.map +1 -1
- package/dist/utils.d.ts +2 -1
- package/dist/utils.d.ts.map +1 -1
- package/dist/utils.js +2 -1
- package/dist/utils.js.map +1 -1
- package/lib/AuthHandler.ts +50 -40
- package/lib/DBEventsManager.ts +14 -7
- package/lib/DboBuilder.ts +231 -195
- package/lib/FileManager.ts +30 -21
- package/lib/Filtering.ts +19 -16
- package/lib/PostgresNotifListenManager.ts +11 -10
- package/lib/Prostgles.ts +89 -73
- package/lib/PubSubManager.ts +13 -11
- package/lib/QueryBuilder.ts +53 -29
- package/lib/SyncReplication.ts +10 -10
- package/lib/TableConfig.ts +23 -15
- package/lib/shortestPath.ts +6 -4
- package/lib/utils.ts +3 -2
- package/package.json +3 -2
- package/tests/client/PID.txt +1 -1
- package/tests/client/index.js +10 -7
- package/tests/client/index.ts +12 -8
- package/tests/client/package-lock.json +14 -14
- package/tests/client/package.json +2 -2
- package/tests/client/tsconfig.json +2 -2
- package/tests/client_only_queries.js +127 -104
- package/tests/client_only_queries.ts +43 -17
- package/tests/isomorphic_queries.js +22 -6
- package/tests/isomorphic_queries.ts +18 -6
- package/tests/server/package-lock.json +19 -17
- package/tests/server/package.json +2 -2
- package/tests/server/tsconfig.json +2 -2
- package/tsconfig.json +3 -2
package/dist/DboBuilder.js
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* Licensed under the MIT License. See LICENSE in the project root for license information.
|
|
5
5
|
*--------------------------------------------------------------------------------------------*/
|
|
6
6
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
-
exports.postgresToTsType = exports.isPlainObject = exports.DboBuilder = exports.TableHandler = exports.ViewHandler = exports.EXISTS_KEYS = exports.pgp = void 0;
|
|
7
|
+
exports.postgresToTsType = exports.getKeys = exports.isPlainObject = exports.DboBuilder = exports.TableHandler = exports.ViewHandler = exports.EXISTS_KEYS = exports.pgp = void 0;
|
|
8
8
|
const Bluebird = require("bluebird");
|
|
9
9
|
// declare global { export interface Promise<T> extends Bluebird<T> {} }
|
|
10
10
|
const pgPromise = require("pg-promise");
|
|
@@ -23,7 +23,6 @@ const prostgles_types_1 = require("prostgles-types");
|
|
|
23
23
|
// }>
|
|
24
24
|
const utils_1 = require("./utils");
|
|
25
25
|
const QueryBuilder_1 = require("./QueryBuilder");
|
|
26
|
-
const Prostgles_1 = require("./Prostgles");
|
|
27
26
|
const PubSubManager_1 = require("./PubSubManager");
|
|
28
27
|
const Filtering_1 = require("./Filtering");
|
|
29
28
|
exports.pgp = pgPromise({
|
|
@@ -62,13 +61,17 @@ function escapeTSNames(str, capitalize = true) {
|
|
|
62
61
|
const shortestPath_1 = require("./shortestPath");
|
|
63
62
|
/* DEBUG CLIENT ERRORS HERE */
|
|
64
63
|
function makeErr(err, localParams, view, allowedKeys) {
|
|
65
|
-
var _a;
|
|
66
64
|
// console.trace(err)
|
|
67
65
|
if (process.env.TEST_TYPE || process.env.PRGL_DEBUG) {
|
|
68
66
|
console.trace(err);
|
|
69
67
|
}
|
|
70
|
-
const errObject =
|
|
71
|
-
|
|
68
|
+
const errObject = {
|
|
69
|
+
...((!localParams || !localParams.socket) ? err : {}),
|
|
70
|
+
...PubSubManager_1.filterObj(err, ["column", "code", "table", "constraint"]),
|
|
71
|
+
...(err && err.toString ? { txt: err.toString() } : {}),
|
|
72
|
+
code_info: sqlErrCodeToMsg(err.code)
|
|
73
|
+
};
|
|
74
|
+
if (view?.dboBuilder?.constraints && errObject.constraint && !errObject.column) {
|
|
72
75
|
const constraint = view.dboBuilder.constraints
|
|
73
76
|
.find(c => c.conname === errObject.constraint && c.relname === view.name);
|
|
74
77
|
if (constraint) {
|
|
@@ -108,7 +111,6 @@ class ColSet {
|
|
|
108
111
|
}
|
|
109
112
|
const rowKeys = Object.keys(row);
|
|
110
113
|
return rowKeys.map(key => {
|
|
111
|
-
var _a;
|
|
112
114
|
const col = this.opts.columns.find(c => c.name === key);
|
|
113
115
|
if (!col)
|
|
114
116
|
throw "Unexpected missing col name";
|
|
@@ -126,7 +128,7 @@ class ColSet {
|
|
|
126
128
|
const dataKeys = Object.keys(row[key]);
|
|
127
129
|
const funcName = dataKeys[0];
|
|
128
130
|
const funcExists = basicFuncNames.includes(funcName);
|
|
129
|
-
const funcArgs =
|
|
131
|
+
const funcArgs = row[key]?.[funcName];
|
|
130
132
|
if (dataKeys.length !== 1 || !funcExists || !Array.isArray(funcArgs)) {
|
|
131
133
|
throw `Expecting only one function key (${basicFuncNames.join(", ")}) \nwith an array of arguments \n within column (${key}) data but got: ${JSON.stringify(row[key])} \nExample: { geo_col: { ST_GeomFromText: ["POINT(-71.064544 42.28787)", 4326] } }`;
|
|
132
134
|
}
|
|
@@ -179,7 +181,7 @@ class ViewHandler {
|
|
|
179
181
|
this.column_names = tableOrViewInfo.columns.map(c => c.name);
|
|
180
182
|
// this.pubSubManager = pubSubManager;
|
|
181
183
|
this.dboBuilder = dboBuilder;
|
|
182
|
-
this.joins = this.dboBuilder.joins;
|
|
184
|
+
this.joins = this.dboBuilder.joins ?? [];
|
|
183
185
|
// fix this
|
|
184
186
|
// and also make hot schema reload over ws
|
|
185
187
|
this.colSet = new ColSet(this.columns, this.name);
|
|
@@ -276,7 +278,6 @@ class ViewHandler {
|
|
|
276
278
|
return { query, toOne: false };
|
|
277
279
|
}
|
|
278
280
|
getJoins(source, target, path, checkTableConfig) {
|
|
279
|
-
var _a, _b, _e;
|
|
280
281
|
let paths = [];
|
|
281
282
|
if (!this.joinPaths)
|
|
282
283
|
throw `${source} - ${target} Join info missing or dissallowed`;
|
|
@@ -284,7 +285,7 @@ class ViewHandler {
|
|
|
284
285
|
throw `Empty join path ( $path ) specified for ${source} <-> ${target}`;
|
|
285
286
|
/* Find the join path between tables */
|
|
286
287
|
if (checkTableConfig) {
|
|
287
|
-
const tableConfigJoinInfo =
|
|
288
|
+
const tableConfigJoinInfo = this.dboBuilder?.prostgles?.tableConfigurator?.getJoinInfo(source, target);
|
|
288
289
|
if (tableConfigJoinInfo)
|
|
289
290
|
return tableConfigJoinInfo;
|
|
290
291
|
}
|
|
@@ -351,7 +352,6 @@ class ViewHandler {
|
|
|
351
352
|
throw `invalid filter -> ${JSON.stringify(filter)} \nExpecting: undefined | {} | { field_name: "value" } | { field: { $gt: 22 } } ... `;
|
|
352
353
|
}
|
|
353
354
|
async getInfo(param1, param2, param3, tableRules, localParams) {
|
|
354
|
-
var _a, _b, _e, _f, _g, _h, _j, _k, _l, _m, _o;
|
|
355
355
|
const p = this.getValidatedRules(tableRules, localParams);
|
|
356
356
|
if (!p.getInfo)
|
|
357
357
|
throw "Not allowed";
|
|
@@ -360,18 +360,17 @@ class ViewHandler {
|
|
|
360
360
|
* Media is directly related to this table (does not come from a deeply joined table)
|
|
361
361
|
*/
|
|
362
362
|
let has_direct_media = false;
|
|
363
|
-
const mediaTable =
|
|
363
|
+
const mediaTable = this.dboBuilder.prostgles?.opts?.fileTable?.tableName;
|
|
364
364
|
if (!this.is_media && mediaTable) {
|
|
365
|
-
if (
|
|
366
|
-
has_media =
|
|
365
|
+
if (this.dboBuilder.prostgles?.opts?.fileTable?.referencedTables?.[this.name]) {
|
|
366
|
+
has_media = this.dboBuilder.prostgles?.opts?.fileTable?.referencedTables?.[this.name];
|
|
367
367
|
has_direct_media = true;
|
|
368
368
|
}
|
|
369
369
|
else {
|
|
370
370
|
const jp = this.dboBuilder.joinPaths.find(jp => jp.t1 === this.name && jp.t2 === mediaTable);
|
|
371
371
|
if (jp && jp.path.length <= 3) {
|
|
372
372
|
await Promise.all(jp.path.map(async (tableName) => {
|
|
373
|
-
|
|
374
|
-
const cols = (_g = (await ((_f = (_e = (_b = (_a = this === null || this === void 0 ? void 0 : this.dboBuilder) === null || _a === void 0 ? void 0 : _a.dbo) === null || _b === void 0 ? void 0 : _b[tableName]) === null || _e === void 0 ? void 0 : _e.getColumns) === null || _f === void 0 ? void 0 : _f.call(_e)))) === null || _g === void 0 ? void 0 : _g.filter(c => { var _a; return jp.path.includes((_a = c === null || c === void 0 ? void 0 : c.references) === null || _a === void 0 ? void 0 : _a.ftable); });
|
|
373
|
+
const cols = (await this?.dboBuilder?.dbo?.[tableName]?.getColumns?.())?.filter(c => jp.path.includes(c?.references?.ftable));
|
|
375
374
|
if (cols && cols.length && has_media !== "many") {
|
|
376
375
|
if (cols.find(c => !c.is_pkey)) {
|
|
377
376
|
has_media = "many";
|
|
@@ -406,30 +405,39 @@ class ViewHandler {
|
|
|
406
405
|
.filter(c => {
|
|
407
406
|
const { insert, select, update } = p || {};
|
|
408
407
|
return [
|
|
409
|
-
...(
|
|
410
|
-
...(
|
|
411
|
-
...(
|
|
408
|
+
...(insert?.fields || []),
|
|
409
|
+
...(select?.fields || []),
|
|
410
|
+
...(update?.fields || []),
|
|
412
411
|
].includes(c.name);
|
|
413
412
|
})
|
|
414
413
|
.map(_c => {
|
|
415
|
-
|
|
416
|
-
let c = Object.assign({}, _c);
|
|
414
|
+
let c = { ..._c };
|
|
417
415
|
let label = c.comment || capitalizeFirstLetter(c.name, " ");
|
|
418
|
-
const tblConfig =
|
|
416
|
+
const tblConfig = this.dboBuilder.prostgles?.opts?.tableConfig?.[this.name];
|
|
419
417
|
if (tblConfig && "columns" in tblConfig) {
|
|
420
|
-
const lbl =
|
|
418
|
+
const lbl = tblConfig?.columns[c.name]?.label;
|
|
421
419
|
if (["string", "object"].includes(typeof lbl)) {
|
|
422
420
|
if (typeof lbl === "string") {
|
|
423
421
|
label = lbl;
|
|
424
422
|
}
|
|
425
423
|
else if (lang) {
|
|
426
|
-
label = (lbl
|
|
424
|
+
label = (lbl?.[lang]) || lbl?.en || label;
|
|
427
425
|
}
|
|
428
426
|
}
|
|
429
427
|
}
|
|
430
428
|
const select = c.privileges.some(p => p.privilege_type === "SELECT"), insert = c.privileges.some(p => p.privilege_type === "INSERT"), update = c.privileges.some(p => p.privilege_type === "UPDATE"), _delete = this.tableOrViewInfo.privileges.delete; // c.privileges.some(p => p.privilege_type === "DELETE");
|
|
431
429
|
delete c.privileges;
|
|
432
|
-
return
|
|
430
|
+
return {
|
|
431
|
+
...c,
|
|
432
|
+
label,
|
|
433
|
+
tsDataType: postgresToTsType(c.udt_name),
|
|
434
|
+
insert: insert && Boolean(p.insert && p.insert.fields && p.insert.fields.includes(c.name)),
|
|
435
|
+
select: select && Boolean(p.select && p.select.fields && p.select.fields.includes(c.name)),
|
|
436
|
+
filter: Boolean(p.select && p.select.filterFields && p.select.filterFields.includes(c.name)),
|
|
437
|
+
update: update && Boolean(p.update && p.update.fields && p.update.fields.includes(c.name)),
|
|
438
|
+
delete: _delete && Boolean(p.delete && p.delete.filterFields && p.delete.filterFields.includes(c.name)),
|
|
439
|
+
...(this.dboBuilder?.prostgles?.tableConfigurator?.getColInfo({ table: this.name, col: c.name }) || {})
|
|
440
|
+
};
|
|
433
441
|
}).filter(c => c.select || c.update || c.delete || c.insert);
|
|
434
442
|
//.sort((a, b) => a.ordinal_position - b.ordinal_position);
|
|
435
443
|
// const tblInfo = await this.getInfo();
|
|
@@ -449,7 +457,6 @@ class ViewHandler {
|
|
|
449
457
|
}
|
|
450
458
|
}
|
|
451
459
|
getValidatedRules(tableRules, localParams) {
|
|
452
|
-
var _a, _b, _e, _f, _g, _h;
|
|
453
460
|
if (utils_1.get(localParams, "socket") && !tableRules) {
|
|
454
461
|
throw "INTERNAL ERROR: Unexpected case -> localParams && !tableRules";
|
|
455
462
|
}
|
|
@@ -483,8 +490,8 @@ class ViewHandler {
|
|
|
483
490
|
};
|
|
484
491
|
let res = {
|
|
485
492
|
allColumns,
|
|
486
|
-
getColumns:
|
|
487
|
-
getInfo:
|
|
493
|
+
getColumns: tableRules?.getColumns ?? true,
|
|
494
|
+
getInfo: tableRules?.getColumns ?? true,
|
|
488
495
|
};
|
|
489
496
|
/* SELECT */
|
|
490
497
|
if (tableRules.select) {
|
|
@@ -499,7 +506,7 @@ class ViewHandler {
|
|
|
499
506
|
}
|
|
500
507
|
res.select = {
|
|
501
508
|
fields: this.parseFieldFilter(tableRules.select.fields),
|
|
502
|
-
forcedFilter:
|
|
509
|
+
forcedFilter: { ...tableRules.select.forcedFilter },
|
|
503
510
|
filterFields: this.parseFieldFilter(tableRules.select.filterFields),
|
|
504
511
|
maxLimit
|
|
505
512
|
};
|
|
@@ -510,9 +517,9 @@ class ViewHandler {
|
|
|
510
517
|
return throwFieldsErr("update");
|
|
511
518
|
res.update = {
|
|
512
519
|
fields: this.parseFieldFilter(tableRules.update.fields),
|
|
513
|
-
forcedData:
|
|
514
|
-
forcedFilter:
|
|
515
|
-
returningFields: getFirstSpecified(
|
|
520
|
+
forcedData: { ...tableRules.update.forcedData },
|
|
521
|
+
forcedFilter: { ...tableRules.update.forcedFilter },
|
|
522
|
+
returningFields: getFirstSpecified(tableRules.update?.returningFields, tableRules?.select?.fields, tableRules.update.fields),
|
|
516
523
|
filterFields: this.parseFieldFilter(tableRules.update.filterFields)
|
|
517
524
|
};
|
|
518
525
|
}
|
|
@@ -522,8 +529,8 @@ class ViewHandler {
|
|
|
522
529
|
return throwFieldsErr("insert");
|
|
523
530
|
res.insert = {
|
|
524
531
|
fields: this.parseFieldFilter(tableRules.insert.fields),
|
|
525
|
-
forcedData:
|
|
526
|
-
returningFields: getFirstSpecified(tableRules.insert.returningFields,
|
|
532
|
+
forcedData: { ...tableRules.insert.forcedData },
|
|
533
|
+
returningFields: getFirstSpecified(tableRules.insert.returningFields, tableRules?.select?.fields, tableRules.insert.fields)
|
|
527
534
|
};
|
|
528
535
|
}
|
|
529
536
|
/* DELETE */
|
|
@@ -531,9 +538,9 @@ class ViewHandler {
|
|
|
531
538
|
if (!tableRules.delete.filterFields)
|
|
532
539
|
return throwFieldsErr("delete", "filterFields");
|
|
533
540
|
res.delete = {
|
|
534
|
-
forcedFilter:
|
|
541
|
+
forcedFilter: { ...tableRules.delete.forcedFilter },
|
|
535
542
|
filterFields: this.parseFieldFilter(tableRules.delete.filterFields),
|
|
536
|
-
returningFields: getFirstSpecified(tableRules.delete.returningFields,
|
|
543
|
+
returningFields: getFirstSpecified(tableRules.delete.returningFields, tableRules?.select?.fields, tableRules.delete.filterFields)
|
|
537
544
|
};
|
|
538
545
|
}
|
|
539
546
|
if (!tableRules.select && !tableRules.update && !tableRules.delete && !tableRules.insert) {
|
|
@@ -576,7 +583,7 @@ class ViewHandler {
|
|
|
576
583
|
};
|
|
577
584
|
}
|
|
578
585
|
}
|
|
579
|
-
async find(filter, selectParams, param3_unused
|
|
586
|
+
async find(filter, selectParams, param3_unused, tableRules, localParams) {
|
|
580
587
|
try {
|
|
581
588
|
filter = filter || {};
|
|
582
589
|
const allowedReturnTypes = ["row", "value", "values"];
|
|
@@ -646,14 +653,14 @@ class ViewHandler {
|
|
|
646
653
|
}
|
|
647
654
|
findOne(filter, selectParams, param3_unused, table_rules, localParams) {
|
|
648
655
|
try {
|
|
649
|
-
const { select = "*", orderBy
|
|
656
|
+
const { select = "*", orderBy, offset = 0 } = selectParams || {};
|
|
650
657
|
if (selectParams) {
|
|
651
658
|
const good_params = ["select", "orderBy", "offset"];
|
|
652
659
|
const bad_params = Object.keys(selectParams).filter(k => !good_params.includes(k));
|
|
653
660
|
if (bad_params && bad_params.length)
|
|
654
661
|
throw "Invalid params: " + bad_params.join(", ") + " \n Expecting: " + good_params.join(", ");
|
|
655
662
|
}
|
|
656
|
-
return this.find(filter, { select, orderBy, limit: 1, offset, returnType: "row" },
|
|
663
|
+
return this.find(filter, { select, orderBy, limit: 1, offset, returnType: "row" }, undefined, table_rules, localParams);
|
|
657
664
|
}
|
|
658
665
|
catch (e) {
|
|
659
666
|
if (localParams && localParams.testRule)
|
|
@@ -664,7 +671,7 @@ class ViewHandler {
|
|
|
664
671
|
async count(filter, param2_unused, param3_unused, table_rules, localParams = {}) {
|
|
665
672
|
filter = filter || {};
|
|
666
673
|
try {
|
|
667
|
-
return await this.find(filter, { select: "", limit: 0 },
|
|
674
|
+
return await this.find(filter, { select: "", limit: 0 }, undefined, table_rules, localParams)
|
|
668
675
|
.then(async (allowed) => {
|
|
669
676
|
const { filterFields, forcedFilter } = utils_1.get(table_rules, "select") || {};
|
|
670
677
|
const where = (await this.prepareWhere({ filter, forcedFilter, filterFields, addKeywords: true, localParams, tableRule: table_rules }));
|
|
@@ -681,13 +688,12 @@ class ViewHandler {
|
|
|
681
688
|
async size(filter, selectParams, param3_unused, table_rules, localParams = {}) {
|
|
682
689
|
filter = filter || {};
|
|
683
690
|
try {
|
|
684
|
-
return await this.find(filter,
|
|
691
|
+
return await this.find(filter, { ...selectParams, limit: 2 }, undefined, table_rules, localParams)
|
|
685
692
|
.then(async (_allowed) => {
|
|
686
693
|
// let rules: TableRule = table_rules || {};
|
|
687
694
|
// rules.select.maxLimit = Number.MAX_SAFE_INTEGER;
|
|
688
695
|
// rules.select.fields = rules.select.fields || "*";
|
|
689
|
-
|
|
690
|
-
const q = await this.find(filter, Object.assign(Object.assign({}, selectParams), { limit: (_a = selectParams === null || selectParams === void 0 ? void 0 : selectParams.limit) !== null && _a !== void 0 ? _a : Number.MAX_SAFE_INTEGER }), null, table_rules, Object.assign(Object.assign({}, localParams), { returnQuery: true }));
|
|
696
|
+
const q = await this.find(filter, { ...selectParams, limit: selectParams?.limit ?? Number.MAX_SAFE_INTEGER }, undefined, table_rules, { ...localParams, returnQuery: true });
|
|
691
697
|
const query = `
|
|
692
698
|
SELECT sum(pg_column_size((prgl_size_query.*))) as size
|
|
693
699
|
FROM (
|
|
@@ -744,7 +750,7 @@ class ViewHandler {
|
|
|
744
750
|
* Parses group or simple filter
|
|
745
751
|
*/
|
|
746
752
|
async prepareWhere(params) {
|
|
747
|
-
const { filter, select, forcedFilter, filterFields: ff, addKeywords = true, tableAlias
|
|
753
|
+
const { filter, select, forcedFilter, filterFields: ff, addKeywords = true, tableAlias, localParams, tableRule } = params;
|
|
748
754
|
const { $and: $and_key, $or: $or_key } = this.dboBuilder.prostgles.keywords;
|
|
749
755
|
let filterFields = ff;
|
|
750
756
|
/* Local update allow all. TODO -> FIX THIS */
|
|
@@ -754,7 +760,7 @@ class ViewHandler {
|
|
|
754
760
|
if (!f)
|
|
755
761
|
throw "Invalid/missing group filter provided";
|
|
756
762
|
let result = "";
|
|
757
|
-
let keys =
|
|
763
|
+
let keys = getKeys(f);
|
|
758
764
|
if (!keys.length)
|
|
759
765
|
return result;
|
|
760
766
|
if ((keys.includes($and_key) || keys.includes($or_key))) {
|
|
@@ -776,7 +782,7 @@ class ViewHandler {
|
|
|
776
782
|
}
|
|
777
783
|
else if (!group) {
|
|
778
784
|
result = await this.getCondition({
|
|
779
|
-
filter:
|
|
785
|
+
filter: { ...f },
|
|
780
786
|
select,
|
|
781
787
|
allowed_colnames: this.parseFieldFilter(filterFields),
|
|
782
788
|
tableAlias,
|
|
@@ -788,7 +794,7 @@ class ViewHandler {
|
|
|
788
794
|
};
|
|
789
795
|
if (!isPlainObject(filter))
|
|
790
796
|
throw "\nInvalid filter\nExpecting an object but got -> " + JSON.stringify(filter);
|
|
791
|
-
let _filter =
|
|
797
|
+
let _filter = { ...filter };
|
|
792
798
|
if (forcedFilter) {
|
|
793
799
|
_filter = {
|
|
794
800
|
[$and_key]: [forcedFilter, _filter].filter(f => f)
|
|
@@ -801,7 +807,7 @@ class ViewHandler {
|
|
|
801
807
|
cond = "WHERE " + cond;
|
|
802
808
|
return cond || "";
|
|
803
809
|
}
|
|
804
|
-
async prepareExistCondition(eConfig, localParams
|
|
810
|
+
async prepareExistCondition(eConfig, localParams) {
|
|
805
811
|
let res = "";
|
|
806
812
|
const thisTable = this.name;
|
|
807
813
|
const isNotExists = ["$notExists", "$notExistsJoined"].includes(eConfig.existType);
|
|
@@ -824,7 +830,7 @@ class ViewHandler {
|
|
|
824
830
|
if (!depth && eConfig.shortestJoin)
|
|
825
831
|
exactPaths = undefined;
|
|
826
832
|
const jinf = this.getJoins(t1, t2, exactPaths, true);
|
|
827
|
-
expectOne = expectOne && jinf.expectOne;
|
|
833
|
+
expectOne = Boolean(expectOne && jinf.expectOne);
|
|
828
834
|
joinPaths = joinPaths.concat(jinf.paths);
|
|
829
835
|
});
|
|
830
836
|
let r = makeJoin({ paths: joinPaths, expectOne }, 0);
|
|
@@ -832,7 +838,7 @@ class ViewHandler {
|
|
|
832
838
|
function makeJoin(joinInfo, ji) {
|
|
833
839
|
const { paths } = joinInfo;
|
|
834
840
|
const jp = paths[ji];
|
|
835
|
-
let prevTable = ji
|
|
841
|
+
// let prevTable = ji? paths[ji - 1].table : jp.source;
|
|
836
842
|
let table = paths[ji].table;
|
|
837
843
|
let tableAlias = prostgles_types_1.asName(ji < paths.length - 1 ? `jd${ji}` : table);
|
|
838
844
|
let prevTableAlias = prostgles_types_1.asName(ji ? `jd${ji - 1}` : thisTable);
|
|
@@ -896,7 +902,7 @@ class ViewHandler {
|
|
|
896
902
|
*/
|
|
897
903
|
async getCondition(params) {
|
|
898
904
|
const { filter, select, allowed_colnames, tableAlias, localParams, tableRules } = params;
|
|
899
|
-
let data =
|
|
905
|
+
let data = { ...filter };
|
|
900
906
|
/* Exists join filter */
|
|
901
907
|
const ERR = "Invalid exists filter. \nExpecting somethibng like: { $exists: { tableName.tableName2: Filter } } | { $exists: { \"**.tableName3\": Filter } }\n";
|
|
902
908
|
const SP_WILDCARD = "**";
|
|
@@ -955,7 +961,7 @@ class ViewHandler {
|
|
|
955
961
|
});
|
|
956
962
|
let existsCond = "";
|
|
957
963
|
if (existsKeys.length) {
|
|
958
|
-
existsCond = (await Promise.all(existsKeys.map(async (k) => await this.prepareExistCondition(k, localParams
|
|
964
|
+
existsCond = (await Promise.all(existsKeys.map(async (k) => await this.prepareExistCondition(k, localParams)))).join(" AND ");
|
|
959
965
|
}
|
|
960
966
|
/* Computed field queries */
|
|
961
967
|
const p = this.getValidatedRules(tableRules, localParams);
|
|
@@ -1034,6 +1040,10 @@ class ViewHandler {
|
|
|
1034
1040
|
}
|
|
1035
1041
|
complexFilters.push(result);
|
|
1036
1042
|
}
|
|
1043
|
+
/* Parse join filters
|
|
1044
|
+
{ $joinFilter: { $ST_DWithin: [table.col, foreignTable.col, distance] }
|
|
1045
|
+
will make an exists filter
|
|
1046
|
+
*/
|
|
1037
1047
|
let filterKeys = Object.keys(data).filter(k => k !== complexFilterKey && !funcFilterkeys.find(ek => ek.name === k) && !computedFields.find(cf => cf.name === k) && !existsKeys.find(ek => ek.key === k));
|
|
1038
1048
|
// if(allowed_colnames){
|
|
1039
1049
|
// const aliasedColumns = (select || []).filter(s =>
|
|
@@ -1168,7 +1178,7 @@ class ViewHandler {
|
|
|
1168
1178
|
const orderType = asc ? " ASC " : " DESC ";
|
|
1169
1179
|
const index = selectedAliases.indexOf(key) + 1;
|
|
1170
1180
|
const nullOrder = nulls ? ` NULLS ${nulls === "first" ? " FIRST " : " LAST "}` : "";
|
|
1171
|
-
let colKey = (index > 0 && !nullEmpty) ? index : [tableAlias, key].filter(
|
|
1181
|
+
let colKey = (index > 0 && !nullEmpty) ? index : [tableAlias, key].filter(utils_1.isDefined).map(prostgles_types_1.asName).join(".");
|
|
1172
1182
|
if (nullEmpty) {
|
|
1173
1183
|
colKey = `nullif(trim(${colKey}::text), '')`;
|
|
1174
1184
|
}
|
|
@@ -1236,11 +1246,11 @@ class ViewHandler {
|
|
|
1236
1246
|
if (!column_names || !column_names.length)
|
|
1237
1247
|
throw "table column_names mising";
|
|
1238
1248
|
let _allowed_cols = column_names.slice(0);
|
|
1239
|
-
let _obj =
|
|
1249
|
+
let _obj = { ...obj };
|
|
1240
1250
|
if (allowed_cols) {
|
|
1241
1251
|
_allowed_cols = this.parseFieldFilter(allowed_cols, false);
|
|
1242
1252
|
}
|
|
1243
|
-
let final_filter =
|
|
1253
|
+
let final_filter = { ..._obj }, filter_keys = Object.keys(final_filter);
|
|
1244
1254
|
if (fixIssues && filter_keys.length) {
|
|
1245
1255
|
final_filter = {};
|
|
1246
1256
|
filter_keys
|
|
@@ -1254,7 +1264,7 @@ class ViewHandler {
|
|
|
1254
1264
|
validateObj(final_filter, _allowed_cols);
|
|
1255
1265
|
}
|
|
1256
1266
|
if (forcedData && Object.keys(forcedData).length) {
|
|
1257
|
-
final_filter =
|
|
1267
|
+
final_filter = { ...final_filter, ...forcedData };
|
|
1258
1268
|
}
|
|
1259
1269
|
validateObj(final_filter, column_names.slice(0));
|
|
1260
1270
|
return final_filter;
|
|
@@ -1271,7 +1281,7 @@ class ViewHandler {
|
|
|
1271
1281
|
if (!all_cols)
|
|
1272
1282
|
throw "all_cols missing";
|
|
1273
1283
|
const all_fields = all_cols; // || this.column_names.slice(0);
|
|
1274
|
-
let colNames =
|
|
1284
|
+
let colNames = [], initialParams = JSON.stringify(fieldParams);
|
|
1275
1285
|
if (fieldParams) {
|
|
1276
1286
|
/*
|
|
1277
1287
|
"field1, field2, field4" | "*"
|
|
@@ -1414,7 +1424,7 @@ class TableHandler extends ViewHandler {
|
|
|
1414
1424
|
console.error({ localParams, localFunc });
|
|
1415
1425
|
throw " Cannot have localFunc AND socket ";
|
|
1416
1426
|
}
|
|
1417
|
-
const { filterFields, forcedFilter } = utils_1.get(table_rules, "select") || {}, condition = await this.prepareWhere({ filter, forcedFilter, addKeywords: false, filterFields, tableAlias:
|
|
1427
|
+
const { filterFields, forcedFilter } = utils_1.get(table_rules, "select") || {}, condition = await this.prepareWhere({ filter, forcedFilter, addKeywords: false, filterFields, tableAlias: undefined, localParams, tableRule: table_rules }), throttle = utils_1.get(params, "throttle") || 0, selectParams = PubSubManager_1.filterObj(params || {}, [], ["throttle"]);
|
|
1418
1428
|
// const { subOne = false } = localParams || {};
|
|
1419
1429
|
const filterSize = JSON.stringify(filter || {}).length;
|
|
1420
1430
|
if (filterSize * 4 > 2704) {
|
|
@@ -1423,20 +1433,19 @@ class TableHandler extends ViewHandler {
|
|
|
1423
1433
|
if (!localFunc) {
|
|
1424
1434
|
if (!this.dboBuilder.prostgles.isSuperUser)
|
|
1425
1435
|
throw "Subscribe not possible. Must be superuser to add triggers 1856";
|
|
1426
|
-
return await this.find(filter,
|
|
1436
|
+
return await this.find(filter, { ...selectParams, limit: 0 }, undefined, table_rules, localParams)
|
|
1427
1437
|
.then(async (isValid) => {
|
|
1428
|
-
const { socket
|
|
1438
|
+
const { socket } = localParams ?? {};
|
|
1429
1439
|
const pubSubManager = await this.dboBuilder.getPubSubManager();
|
|
1430
1440
|
return pubSubManager.addSub({
|
|
1431
1441
|
table_info: this.tableOrViewInfo,
|
|
1432
1442
|
socket,
|
|
1433
1443
|
table_rules,
|
|
1434
1444
|
condition: condition,
|
|
1435
|
-
func:
|
|
1436
|
-
filter:
|
|
1437
|
-
params:
|
|
1438
|
-
|
|
1439
|
-
socket_id: socket.id,
|
|
1445
|
+
func: undefined,
|
|
1446
|
+
filter: { ...filter },
|
|
1447
|
+
params: { ...selectParams },
|
|
1448
|
+
socket_id: socket?.id,
|
|
1440
1449
|
table_name: this.name,
|
|
1441
1450
|
throttle,
|
|
1442
1451
|
last_throttled: 0,
|
|
@@ -1447,14 +1456,13 @@ class TableHandler extends ViewHandler {
|
|
|
1447
1456
|
const pubSubManager = await this.dboBuilder.getPubSubManager();
|
|
1448
1457
|
pubSubManager.addSub({
|
|
1449
1458
|
table_info: this.tableOrViewInfo,
|
|
1450
|
-
socket:
|
|
1459
|
+
socket: undefined,
|
|
1451
1460
|
table_rules,
|
|
1452
1461
|
condition,
|
|
1453
1462
|
func: localFunc,
|
|
1454
|
-
filter:
|
|
1455
|
-
params:
|
|
1456
|
-
|
|
1457
|
-
socket_id: null,
|
|
1463
|
+
filter: { ...filter },
|
|
1464
|
+
params: { ...selectParams },
|
|
1465
|
+
socket_id: undefined,
|
|
1458
1466
|
table_name: this.name,
|
|
1459
1467
|
throttle,
|
|
1460
1468
|
last_throttled: 0,
|
|
@@ -1475,11 +1483,11 @@ class TableHandler extends ViewHandler {
|
|
|
1475
1483
|
}
|
|
1476
1484
|
subscribeOne(filter, params = {}, localFunc, table_rules, localParams) {
|
|
1477
1485
|
let func = localParams ? undefined : (rows) => localFunc(rows[0]);
|
|
1478
|
-
return this.subscribe(filter,
|
|
1486
|
+
return this.subscribe(filter, { ...params, limit: 2 }, func, table_rules, localParams);
|
|
1479
1487
|
}
|
|
1480
|
-
async updateBatch(data, params, tableRules, localParams
|
|
1488
|
+
async updateBatch(data, params, tableRules, localParams) {
|
|
1481
1489
|
try {
|
|
1482
|
-
const queries = await Promise.all(data.map(async ([filter, data]) => await this.update(filter, data,
|
|
1490
|
+
const queries = await Promise.all(data.map(async ([filter, data]) => await this.update(filter, data, { ...(params || {}), returning: undefined }, tableRules, { ...(localParams || {}), returnQuery: true })));
|
|
1483
1491
|
const keys = (data && data.length) ? Object.keys(data[0]) : [];
|
|
1484
1492
|
return this.db.tx(t => {
|
|
1485
1493
|
const _queries = queries.map(q => t.none(q));
|
|
@@ -1492,10 +1500,9 @@ class TableHandler extends ViewHandler {
|
|
|
1492
1500
|
throw { err: parseError(e), msg: `Issue with dbo.${this.name}.update()` };
|
|
1493
1501
|
}
|
|
1494
1502
|
}
|
|
1495
|
-
async update(filter, newData, params, tableRules, localParams
|
|
1496
|
-
var _a;
|
|
1503
|
+
async update(filter, newData, params, tableRules, localParams) {
|
|
1497
1504
|
try {
|
|
1498
|
-
const { testRule = false, returnQuery = false } = localParams
|
|
1505
|
+
const { testRule = false, returnQuery = false } = localParams ?? {};
|
|
1499
1506
|
if (!testRule) {
|
|
1500
1507
|
if (!newData || !Object.keys(newData).length)
|
|
1501
1508
|
throw "no update data provided\nEXPECTING db.table.update(filter, updateData, options)";
|
|
@@ -1515,7 +1522,7 @@ class TableHandler extends ViewHandler {
|
|
|
1515
1522
|
await this.validateViewRules(fields, filterFields, returningFields, forcedFilter, "update");
|
|
1516
1523
|
if (forcedData) {
|
|
1517
1524
|
try {
|
|
1518
|
-
const { data, allowedCols } = this.validateNewData({ row: forcedData, forcedData:
|
|
1525
|
+
const { data, allowedCols } = this.validateNewData({ row: forcedData, forcedData: undefined, allowedFields: "*", tableRules, fixIssues: false });
|
|
1519
1526
|
const updateQ = await this.colSet.getUpdateQuery(data, allowedCols, validate); //pgp.helpers.update(data, columnSet)
|
|
1520
1527
|
let query = updateQ + " WHERE FALSE ";
|
|
1521
1528
|
await this.db.any("EXPLAIN " + query);
|
|
@@ -1549,13 +1556,13 @@ class TableHandler extends ViewHandler {
|
|
|
1549
1556
|
const unrecProps = Object.keys(d).filter(k => !["from", "to", "text", "md5"].includes(k));
|
|
1550
1557
|
if (unrecProps.length)
|
|
1551
1558
|
throw "Unrecognised params in textPatch field: " + unrecProps.join(", ");
|
|
1552
|
-
patchedTextData.push(
|
|
1559
|
+
patchedTextData.push({ ...d, fieldName: c.name });
|
|
1553
1560
|
}
|
|
1554
1561
|
});
|
|
1555
1562
|
if (patchedTextData && patchedTextData.length) {
|
|
1556
1563
|
if (tableRules && !tableRules.select)
|
|
1557
1564
|
throw "Select needs to be permitted to patch data";
|
|
1558
|
-
const rows = await this.find(filter, { select: patchedTextData.reduce((a, v) => (
|
|
1565
|
+
const rows = await this.find(filter, { select: patchedTextData.reduce((a, v) => ({ ...a, [v.fieldName]: 1 }), {}) }, undefined, tableRules);
|
|
1559
1566
|
if (rows.length !== 1) {
|
|
1560
1567
|
throw "Cannot patch data within a filter that affects more/less than 1 row";
|
|
1561
1568
|
}
|
|
@@ -1565,11 +1572,11 @@ class TableHandler extends ViewHandler {
|
|
|
1565
1572
|
// https://w3resource.com/PostgreSQL/overlay-function.p hp
|
|
1566
1573
|
// overlay(coalesce(status, '') placing 'hom' from 2 for 0)
|
|
1567
1574
|
}
|
|
1568
|
-
let nData =
|
|
1575
|
+
let nData = { ...data };
|
|
1569
1576
|
// if(tableRules && tableRules.update && tableRules?.update?.validate){
|
|
1570
1577
|
// nData = await tableRules.update.validate(nData);
|
|
1571
1578
|
// }
|
|
1572
|
-
let query = await this.colSet.getUpdateQuery(nData, allowedCols,
|
|
1579
|
+
let query = await this.colSet.getUpdateQuery(nData, allowedCols, tableRules?.update?.validate); //pgp.helpers.update(nData, columnSet) + " ";
|
|
1573
1580
|
query += (await this.prepareWhere({
|
|
1574
1581
|
filter,
|
|
1575
1582
|
forcedFilter,
|
|
@@ -1587,7 +1594,7 @@ class TableHandler extends ViewHandler {
|
|
|
1587
1594
|
if (returnQuery)
|
|
1588
1595
|
return query;
|
|
1589
1596
|
if (this.t) {
|
|
1590
|
-
return this.t[qType](query).catch(err => makeErr(err, localParams, this, _fields));
|
|
1597
|
+
return this.t[qType](query).catch((err) => makeErr(err, localParams, this, _fields));
|
|
1591
1598
|
}
|
|
1592
1599
|
return this.db.tx(t => t[qType](query)).catch(err => makeErr(err, localParams, this, _fields));
|
|
1593
1600
|
}
|
|
@@ -1599,17 +1606,16 @@ class TableHandler extends ViewHandler {
|
|
|
1599
1606
|
}
|
|
1600
1607
|
;
|
|
1601
1608
|
validateNewData({ row, forcedData, allowedFields, tableRules, fixIssues = false }) {
|
|
1602
|
-
const synced_field = utils_1.get(tableRules
|
|
1609
|
+
const synced_field = utils_1.get(tableRules ?? {}, "sync.synced_field");
|
|
1603
1610
|
/* Update synced_field if sync is on and missing */
|
|
1604
1611
|
if (synced_field && !row[synced_field]) {
|
|
1605
1612
|
row[synced_field] = Date.now();
|
|
1606
1613
|
}
|
|
1607
1614
|
let data = this.prepareFieldValues(row, forcedData, allowedFields, fixIssues);
|
|
1608
|
-
const dataKeys =
|
|
1615
|
+
const dataKeys = getKeys(data);
|
|
1609
1616
|
dataKeys.map(col => {
|
|
1610
|
-
|
|
1611
|
-
|
|
1612
|
-
const colConfig = (_f = (_e = this.dboBuilder.prostgles) === null || _e === void 0 ? void 0 : _e.tableConfigurator) === null || _f === void 0 ? void 0 : _f.getColumnConfig(this.name, col);
|
|
1617
|
+
this.dboBuilder.prostgles?.tableConfigurator?.checkColVal({ table: this.name, col, value: data[col] });
|
|
1618
|
+
const colConfig = this.dboBuilder.prostgles?.tableConfigurator?.getColumnConfig(this.name, col);
|
|
1613
1619
|
if (colConfig && "isText" in colConfig && data[col]) {
|
|
1614
1620
|
if (colConfig.lowerCased) {
|
|
1615
1621
|
data[col] = data[col].toString().toLowerCase();
|
|
@@ -1621,12 +1627,11 @@ class TableHandler extends ViewHandler {
|
|
|
1621
1627
|
});
|
|
1622
1628
|
return { data, allowedCols: this.columns.filter(c => dataKeys.includes(c.name)).map(c => c.name) };
|
|
1623
1629
|
}
|
|
1624
|
-
async insertDataParse(data, param2, param3_unused, tableRules, _localParams
|
|
1625
|
-
var _a, _b;
|
|
1630
|
+
async insertDataParse(data, param2, param3_unused, tableRules, _localParams) {
|
|
1626
1631
|
const localParams = _localParams || {};
|
|
1627
|
-
let dbTX =
|
|
1632
|
+
let dbTX = localParams?.dbTX || this.dbTX;
|
|
1628
1633
|
const isMultiInsert = Array.isArray(data);
|
|
1629
|
-
const getExtraKeys = d => Object.keys(d).filter(k => !this.columns.find(c => c.name === k));
|
|
1634
|
+
const getExtraKeys = (d) => Object.keys(d).filter(k => !this.columns.find(c => c.name === k));
|
|
1630
1635
|
/* Nested insert is not allowed for the file table */
|
|
1631
1636
|
const isNestedInsert = this.is_media ? false : (Array.isArray(data) ? data : [data]).some(d => getExtraKeys(d).length);
|
|
1632
1637
|
/**
|
|
@@ -1634,13 +1639,12 @@ class TableHandler extends ViewHandler {
|
|
|
1634
1639
|
*/
|
|
1635
1640
|
if (isNestedInsert && !dbTX) {
|
|
1636
1641
|
return {
|
|
1637
|
-
insertResult: await this.dboBuilder.getTX((dbTX) => dbTX[this.name].insert(data, param2, param3_unused, tableRules,
|
|
1642
|
+
insertResult: await this.dboBuilder.getTX((dbTX) => dbTX[this.name].insert(data, param2, param3_unused, tableRules, { dbTX, ...localParams }))
|
|
1638
1643
|
};
|
|
1639
1644
|
}
|
|
1640
1645
|
// if(!dbTX && this.t) dbTX = this.d;
|
|
1641
|
-
const preValidate =
|
|
1646
|
+
const preValidate = tableRules?.insert?.preValidate, validate = tableRules?.insert?.validate;
|
|
1642
1647
|
let _data = await Promise.all((Array.isArray(data) ? data : [data]).map(async (row) => {
|
|
1643
|
-
var _a, _b;
|
|
1644
1648
|
if (preValidate) {
|
|
1645
1649
|
row = await preValidate(row);
|
|
1646
1650
|
}
|
|
@@ -1648,7 +1652,7 @@ class TableHandler extends ViewHandler {
|
|
|
1648
1652
|
const extraKeys = getExtraKeys(row);
|
|
1649
1653
|
/* Upload file then continue insert */
|
|
1650
1654
|
if (this.is_media) {
|
|
1651
|
-
if (!
|
|
1655
|
+
if (!this.dboBuilder.prostgles?.fileManager)
|
|
1652
1656
|
throw "fileManager not set up";
|
|
1653
1657
|
const { data, name } = row;
|
|
1654
1658
|
if (dataKeys.length !== 2)
|
|
@@ -1675,35 +1679,37 @@ class TableHandler extends ViewHandler {
|
|
|
1675
1679
|
const _media = await this.dboBuilder.prostgles.fileManager.uploadAsMedia({
|
|
1676
1680
|
item: {
|
|
1677
1681
|
data,
|
|
1678
|
-
name: media.name,
|
|
1682
|
+
name: media.name ?? "????",
|
|
1679
1683
|
content_type: media.content_type
|
|
1680
1684
|
},
|
|
1681
1685
|
});
|
|
1682
|
-
return
|
|
1686
|
+
return {
|
|
1687
|
+
...media,
|
|
1688
|
+
..._media,
|
|
1689
|
+
};
|
|
1683
1690
|
/* Potentially a nested join */
|
|
1684
1691
|
}
|
|
1685
1692
|
else if (extraKeys.length) {
|
|
1686
1693
|
/* Ensure we're using the same transaction */
|
|
1687
1694
|
const _this = this.t ? this : dbTX[this.name];
|
|
1688
|
-
let rootData = PubSubManager_1.filterObj(data,
|
|
1695
|
+
let rootData = PubSubManager_1.filterObj(data, undefined, extraKeys);
|
|
1689
1696
|
let insertedChildren;
|
|
1690
1697
|
let targetTableRules;
|
|
1691
|
-
const fullRootResult = await _this.insert(rootData, { returning: "*" },
|
|
1698
|
+
const fullRootResult = await _this.insert(rootData, { returning: "*" }, undefined, tableRules, localParams);
|
|
1692
1699
|
let returnData;
|
|
1693
|
-
const returning = param2
|
|
1700
|
+
const returning = param2?.returning;
|
|
1694
1701
|
if (returning) {
|
|
1695
1702
|
returnData = {};
|
|
1696
|
-
const returningItems = await this.prepareReturning(returning, this.parseFieldFilter(
|
|
1703
|
+
const returningItems = await this.prepareReturning(returning, this.parseFieldFilter(tableRules?.insert?.returningFields));
|
|
1697
1704
|
returningItems.filter(s => s.selected).map(rs => {
|
|
1698
1705
|
returnData[rs.alias] = fullRootResult[rs.alias];
|
|
1699
1706
|
});
|
|
1700
1707
|
}
|
|
1701
1708
|
await Promise.all(extraKeys.map(async (targetTable) => {
|
|
1702
|
-
var _a;
|
|
1703
1709
|
const childDataItems = Array.isArray(row[targetTable]) ? row[targetTable] : [row[targetTable]];
|
|
1704
1710
|
/* Must be allowed to insert into media table */
|
|
1705
1711
|
const canInsert = async (tbl) => {
|
|
1706
|
-
const childRules = await this.dboBuilder.publishParser
|
|
1712
|
+
const childRules = await this.dboBuilder.publishParser?.getValidatedRequestRuleWusr({ tableName: tbl, command: "insert", localParams });
|
|
1707
1713
|
if (!childRules || !childRules.insert)
|
|
1708
1714
|
throw "Dissallowed nested insert into table " + childRules;
|
|
1709
1715
|
return childRules;
|
|
@@ -1715,7 +1721,7 @@ class TableHandler extends ViewHandler {
|
|
|
1715
1721
|
const thisInfo = await this.getInfo();
|
|
1716
1722
|
const childInsert = async (cdata, tableName) => {
|
|
1717
1723
|
// console.log("childInsert", {data, tableName})
|
|
1718
|
-
if (!cdata || !dbTX[tableName] || !("insert" in dbTX[tableName]))
|
|
1724
|
+
if (!cdata || !dbTX?.[tableName] || !("insert" in dbTX[tableName]))
|
|
1719
1725
|
throw "childInsertErr: Child table handler missing for: " + tableName;
|
|
1720
1726
|
const tableRules = await canInsert(tableName);
|
|
1721
1727
|
if (thisInfo.has_media === "one" && thisInfo.media_table_name === tableName && Array.isArray(cdata) && cdata.length > 1) {
|
|
@@ -1723,7 +1729,7 @@ class TableHandler extends ViewHandler {
|
|
|
1723
1729
|
}
|
|
1724
1730
|
return Promise.all((Array.isArray(cdata) ? cdata : [cdata])
|
|
1725
1731
|
.map(m => dbTX[tableName]
|
|
1726
|
-
.insert(m, { returning: "*" },
|
|
1732
|
+
.insert(m, { returning: "*" }, undefined, tableRules, localParams)
|
|
1727
1733
|
.catch(e => {
|
|
1728
1734
|
console.trace({ childInsertErr: e });
|
|
1729
1735
|
return Promise.reject({ childInsertErr: e });
|
|
@@ -1735,7 +1741,7 @@ class TableHandler extends ViewHandler {
|
|
|
1735
1741
|
const cols2 = this.dboBuilder.dbo[tbl2].columns || [];
|
|
1736
1742
|
if (!this.dboBuilder.dbo[tbl2])
|
|
1737
1743
|
throw "Invalid/disallowed table: " + tbl2;
|
|
1738
|
-
const colsRefT1 = cols2
|
|
1744
|
+
const colsRefT1 = cols2?.filter(c => c.references?.cols.length === 1 && c.references?.ftable === tbl1);
|
|
1739
1745
|
if (!path.length) {
|
|
1740
1746
|
throw "Nested inserts join path not found for " + [this.name, targetTable];
|
|
1741
1747
|
}
|
|
@@ -1745,8 +1751,8 @@ class TableHandler extends ViewHandler {
|
|
|
1745
1751
|
if (!colsRefT1.length)
|
|
1746
1752
|
throw `Target table ${tbl2} does not reference any columns from the root table ${this.name}. Cannot do nested insert`;
|
|
1747
1753
|
// console.log(childDataItems, JSON.stringify(colsRefT1, null, 2))
|
|
1748
|
-
insertedChildren = await childInsert(childDataItems.map(d => {
|
|
1749
|
-
let result =
|
|
1754
|
+
insertedChildren = await childInsert(childDataItems.map((d) => {
|
|
1755
|
+
let result = { ...d };
|
|
1750
1756
|
colsRefT1.map(col => {
|
|
1751
1757
|
result[col.references.cols[0]] = fullRootResult[col.references.fcols[0]];
|
|
1752
1758
|
});
|
|
@@ -1757,10 +1763,10 @@ class TableHandler extends ViewHandler {
|
|
|
1757
1763
|
else if (path.length === 3) {
|
|
1758
1764
|
if (targetTable !== tbl3)
|
|
1759
1765
|
throw "Did not expect this";
|
|
1760
|
-
const colsRefT3 = cols2
|
|
1766
|
+
const colsRefT3 = cols2?.filter(c => c.references?.cols.length === 1 && c.references?.ftable === tbl3);
|
|
1761
1767
|
if (!colsRefT1.length || !colsRefT3.length)
|
|
1762
1768
|
throw "Incorrectly referenced or missing columns for nested insert";
|
|
1763
|
-
if (targetTable !== this.dboBuilder.prostgles.fileManager
|
|
1769
|
+
if (targetTable !== this.dboBuilder.prostgles.fileManager?.tableName) {
|
|
1764
1770
|
throw "Only media allowed to have nested inserts more than 2 tables apart";
|
|
1765
1771
|
}
|
|
1766
1772
|
/* We expect tbl2 to have only 2 columns (media_id and foreign_id) */
|
|
@@ -1786,11 +1792,11 @@ class TableHandler extends ViewHandler {
|
|
|
1786
1792
|
throw "Unexpected path for Nested inserts";
|
|
1787
1793
|
}
|
|
1788
1794
|
/* Return also the nested inserted data */
|
|
1789
|
-
if (targetTableRules &&
|
|
1795
|
+
if (targetTableRules && insertedChildren?.length && returning) {
|
|
1790
1796
|
const targetTableHandler = dbTX[targetTable];
|
|
1791
|
-
const targetReturning = await targetTableHandler.prepareReturning("*", targetTableHandler.parseFieldFilter(
|
|
1797
|
+
const targetReturning = await targetTableHandler.prepareReturning("*", targetTableHandler.parseFieldFilter(targetTableRules?.insert?.returningFields));
|
|
1792
1798
|
let clientTargetInserts = insertedChildren.map(d => {
|
|
1793
|
-
let _d =
|
|
1799
|
+
let _d = { ...d };
|
|
1794
1800
|
let res = {};
|
|
1795
1801
|
targetReturning.map(r => {
|
|
1796
1802
|
res[r.alias] = _d[r.alias];
|
|
@@ -1813,8 +1819,7 @@ class TableHandler extends ViewHandler {
|
|
|
1813
1819
|
{ data: result };
|
|
1814
1820
|
return res;
|
|
1815
1821
|
}
|
|
1816
|
-
async insert(rowOrRows, param2, param3_unused, tableRules, _localParams
|
|
1817
|
-
var _a, _b, _e;
|
|
1822
|
+
async insert(rowOrRows, param2, param3_unused, tableRules, _localParams) {
|
|
1818
1823
|
const localParams = _localParams || {};
|
|
1819
1824
|
const { dbTX } = localParams;
|
|
1820
1825
|
try {
|
|
@@ -1835,7 +1840,7 @@ class TableHandler extends ViewHandler {
|
|
|
1835
1840
|
/* Safely test publish rules */
|
|
1836
1841
|
if (testRule) {
|
|
1837
1842
|
// if(this.is_media && tableRules.insert.preValidate) throw "Media table cannot have a preValidate. It already is used internally by prostgles for file upload";
|
|
1838
|
-
await this.validateViewRules(fields,
|
|
1843
|
+
await this.validateViewRules(fields, undefined, returningFields, undefined, "insert");
|
|
1839
1844
|
if (forcedData) {
|
|
1840
1845
|
const keys = Object.keys(forcedData);
|
|
1841
1846
|
if (keys.length) {
|
|
@@ -1865,19 +1870,18 @@ class TableHandler extends ViewHandler {
|
|
|
1865
1870
|
rowOrRows = {}; //throw "Provide data in param1";
|
|
1866
1871
|
let returningSelect = this.makeReturnQuery(await this.prepareReturning(returning, this.parseFieldFilter(returningFields)));
|
|
1867
1872
|
const makeQuery = async (_row, isOne = false) => {
|
|
1868
|
-
|
|
1869
|
-
let row = Object.assign({}, _row);
|
|
1873
|
+
let row = { ..._row };
|
|
1870
1874
|
if (!isPojoObject(row)) {
|
|
1871
1875
|
console.trace(row);
|
|
1872
1876
|
throw "\ninvalid insert data provided -> " + JSON.stringify(row);
|
|
1873
1877
|
}
|
|
1874
1878
|
const { data, allowedCols } = this.validateNewData({ row, forcedData, allowedFields: fields, tableRules, fixIssues });
|
|
1875
|
-
let _data =
|
|
1879
|
+
let _data = { ...data };
|
|
1876
1880
|
let insertQ = "";
|
|
1877
1881
|
if (!Object.keys(_data).length)
|
|
1878
1882
|
insertQ = `INSERT INTO ${prostgles_types_1.asName(this.name)} DEFAULT VALUES `;
|
|
1879
1883
|
else
|
|
1880
|
-
insertQ = await this.colSet.getInsertQuery(_data, allowedCols,
|
|
1884
|
+
insertQ = await this.colSet.getInsertQuery(_data, allowedCols, tableRules?.insert?.validate); // pgp.helpers.insert(_data, columnSet);
|
|
1881
1885
|
return insertQ + conflict_query + returningSelect;
|
|
1882
1886
|
};
|
|
1883
1887
|
let query = "";
|
|
@@ -1910,12 +1914,12 @@ class TableHandler extends ViewHandler {
|
|
|
1910
1914
|
return query;
|
|
1911
1915
|
let result;
|
|
1912
1916
|
if (this.dboBuilder.prostgles.opts.DEBUG_MODE) {
|
|
1913
|
-
console.log(
|
|
1917
|
+
console.log(this.t?.ctx?.start, "insert in " + this.name, data);
|
|
1914
1918
|
}
|
|
1915
|
-
const tx =
|
|
1919
|
+
const tx = dbTX?.[this.name]?.t || this.t;
|
|
1916
1920
|
const allowedFieldKeys = this.parseFieldFilter(fields);
|
|
1917
1921
|
if (tx) {
|
|
1918
|
-
result = tx[queryType](query).catch(err => makeErr(err, localParams, this, allowedFieldKeys));
|
|
1922
|
+
result = tx[queryType](query).catch((err) => makeErr(err, localParams, this, allowedFieldKeys));
|
|
1919
1923
|
}
|
|
1920
1924
|
else {
|
|
1921
1925
|
result = this.db.tx(t => t[queryType](query)).catch(err => makeErr(err, localParams, this, allowedFieldKeys));
|
|
@@ -1933,11 +1937,11 @@ class TableHandler extends ViewHandler {
|
|
|
1933
1937
|
}
|
|
1934
1938
|
;
|
|
1935
1939
|
makeReturnQuery(items) {
|
|
1936
|
-
if (items
|
|
1940
|
+
if (items?.length)
|
|
1937
1941
|
return " RETURNING " + items.map(s => s.getQuery() + " AS " + prostgles_types_1.asName(s.alias)).join(", ");
|
|
1938
1942
|
return "";
|
|
1939
1943
|
}
|
|
1940
|
-
async delete(filter, params, param3_unused, table_rules, localParams
|
|
1944
|
+
async delete(filter, params, param3_unused, table_rules, localParams) {
|
|
1941
1945
|
try {
|
|
1942
1946
|
const { returning } = params || {};
|
|
1943
1947
|
filter = filter || {};
|
|
@@ -1959,7 +1963,7 @@ class TableHandler extends ViewHandler {
|
|
|
1959
1963
|
throw ` Invalid delete rule for ${this.name}. filterFields missing `;
|
|
1960
1964
|
/* Safely test publish rules */
|
|
1961
1965
|
if (testRule) {
|
|
1962
|
-
await this.validateViewRules(
|
|
1966
|
+
await this.validateViewRules(undefined, filterFields, returningFields, forcedFilter, "delete");
|
|
1963
1967
|
return true;
|
|
1964
1968
|
}
|
|
1965
1969
|
}
|
|
@@ -1987,7 +1991,7 @@ class TableHandler extends ViewHandler {
|
|
|
1987
1991
|
}
|
|
1988
1992
|
if (returnQuery)
|
|
1989
1993
|
return _query;
|
|
1990
|
-
return (this.t || this.db)[queryType](_query).catch(err => makeErr(err, localParams));
|
|
1994
|
+
return (this.t || this.db)[queryType](_query).catch((err) => makeErr(err, localParams));
|
|
1991
1995
|
}
|
|
1992
1996
|
catch (e) {
|
|
1993
1997
|
// console.trace(e)
|
|
@@ -1997,10 +2001,10 @@ class TableHandler extends ViewHandler {
|
|
|
1997
2001
|
}
|
|
1998
2002
|
}
|
|
1999
2003
|
;
|
|
2000
|
-
remove(filter, params, param3_unused, tableRules, localParams
|
|
2004
|
+
remove(filter, params, param3_unused, tableRules, localParams) {
|
|
2001
2005
|
return this.delete(filter, params, param3_unused, tableRules, localParams);
|
|
2002
2006
|
}
|
|
2003
|
-
async upsert(filter, newData, params, table_rules, localParams
|
|
2007
|
+
async upsert(filter, newData, params, table_rules, localParams) {
|
|
2004
2008
|
try {
|
|
2005
2009
|
/* Do it within a transaction to ensure consisency */
|
|
2006
2010
|
if (!this.t) {
|
|
@@ -2010,13 +2014,13 @@ class TableHandler extends ViewHandler {
|
|
|
2010
2014
|
return _upsert(this);
|
|
2011
2015
|
}
|
|
2012
2016
|
async function _upsert(tblH) {
|
|
2013
|
-
return tblH.find(filter, { select: "", limit: 1 },
|
|
2017
|
+
return tblH.find(filter, { select: "", limit: 1 }, undefined, table_rules, localParams)
|
|
2014
2018
|
.then(exists => {
|
|
2015
2019
|
if (exists && exists.length) {
|
|
2016
2020
|
return tblH.update(filter, newData, params, table_rules, localParams);
|
|
2017
2021
|
}
|
|
2018
2022
|
else {
|
|
2019
|
-
return tblH.insert(
|
|
2023
|
+
return tblH.insert({ ...newData, ...filter }, params, undefined, table_rules, localParams);
|
|
2020
2024
|
}
|
|
2021
2025
|
});
|
|
2022
2026
|
}
|
|
@@ -2065,7 +2069,7 @@ class TableHandler extends ViewHandler {
|
|
|
2065
2069
|
select.push(sf);
|
|
2066
2070
|
});
|
|
2067
2071
|
/* Step 1: parse command and params */
|
|
2068
|
-
return this.find(filter, { select, limit: 0 },
|
|
2072
|
+
return this.find(filter, { select, limit: 0 }, undefined, table_rules, localParams)
|
|
2069
2073
|
.then(async (isValid) => {
|
|
2070
2074
|
const { filterFields, forcedFilter } = utils_1.get(table_rules, "select") || {};
|
|
2071
2075
|
const condition = await this.prepareWhere({ filter, forcedFilter, filterFields, addKeywords: false, localParams, tableRule: table_rules });
|
|
@@ -2074,10 +2078,11 @@ class TableHandler extends ViewHandler {
|
|
|
2074
2078
|
return pubSubManager.addSync({
|
|
2075
2079
|
table_info: this.tableOrViewInfo,
|
|
2076
2080
|
condition,
|
|
2077
|
-
id_fields, synced_field,
|
|
2081
|
+
id_fields, synced_field,
|
|
2082
|
+
allow_delete,
|
|
2078
2083
|
socket,
|
|
2079
2084
|
table_rules,
|
|
2080
|
-
filter:
|
|
2085
|
+
filter: { ...filter },
|
|
2081
2086
|
params: { select }
|
|
2082
2087
|
}).then(channelName => ({ channelName, id_fields, synced_field }));
|
|
2083
2088
|
});
|
|
@@ -2115,7 +2120,7 @@ class TableHandler extends ViewHandler {
|
|
|
2115
2120
|
}
|
|
2116
2121
|
}
|
|
2117
2122
|
exports.TableHandler = TableHandler;
|
|
2118
|
-
const
|
|
2123
|
+
const Prostgles_1 = require("./Prostgles");
|
|
2119
2124
|
class DboBuilder {
|
|
2120
2125
|
constructor(prostgles) {
|
|
2121
2126
|
this.schema = "public";
|
|
@@ -2144,8 +2149,11 @@ class DboBuilder {
|
|
|
2144
2149
|
console.warn(`subscribe and sync cannot be used because db user is not a superuser `);
|
|
2145
2150
|
}
|
|
2146
2151
|
}
|
|
2152
|
+
if (!this._pubSubManager)
|
|
2153
|
+
throw "Could not create this._pubSubManager";
|
|
2147
2154
|
return this._pubSubManager;
|
|
2148
2155
|
};
|
|
2156
|
+
this.joinPaths = [];
|
|
2149
2157
|
this.init = async () => {
|
|
2150
2158
|
/* If watchSchema then PubSubManager must be created */
|
|
2151
2159
|
await this.build();
|
|
@@ -2157,7 +2165,7 @@ class DboBuilder {
|
|
|
2157
2165
|
this.getTX = (cb) => {
|
|
2158
2166
|
return this.db.tx((t) => {
|
|
2159
2167
|
let dbTX = {};
|
|
2160
|
-
this.tablesOrViews
|
|
2168
|
+
this.tablesOrViews?.map(tov => {
|
|
2161
2169
|
if (tov.is_view) {
|
|
2162
2170
|
dbTX[tov.name] = new ViewHandler(this.db, tov, this, t, dbTX, this.joinPaths);
|
|
2163
2171
|
}
|
|
@@ -2178,14 +2186,15 @@ class DboBuilder {
|
|
|
2178
2186
|
});
|
|
2179
2187
|
};
|
|
2180
2188
|
this.prostgles = prostgles;
|
|
2189
|
+
if (!this.prostgles.db)
|
|
2190
|
+
throw "db missing";
|
|
2181
2191
|
this.db = this.prostgles.db;
|
|
2182
2192
|
this.schema = this.prostgles.opts.schema || "public";
|
|
2183
2193
|
this.dbo = {};
|
|
2184
2194
|
// this.joins = this.prostgles.joins;
|
|
2185
2195
|
}
|
|
2186
2196
|
destroy() {
|
|
2187
|
-
|
|
2188
|
-
(_a = this._pubSubManager) === null || _a === void 0 ? void 0 : _a.destroy();
|
|
2197
|
+
this._pubSubManager?.destroy();
|
|
2189
2198
|
}
|
|
2190
2199
|
getJoins() {
|
|
2191
2200
|
return this.joins;
|
|
@@ -2218,7 +2227,7 @@ class DboBuilder {
|
|
|
2218
2227
|
}
|
|
2219
2228
|
const tovNames = this.tablesOrViews.map(t => t.name);
|
|
2220
2229
|
// 2 find incorrect tables
|
|
2221
|
-
const missing =
|
|
2230
|
+
const missing = joins.flatMap(j => j.tables).find(t => !tovNames.includes(t));
|
|
2222
2231
|
if (missing) {
|
|
2223
2232
|
throw "Table not found: " + missing;
|
|
2224
2233
|
}
|
|
@@ -2237,11 +2246,11 @@ class DboBuilder {
|
|
|
2237
2246
|
});
|
|
2238
2247
|
});
|
|
2239
2248
|
// 4 find incorrect/missing join types
|
|
2240
|
-
const expected_types = " \n\n-> Expecting: " +
|
|
2249
|
+
const expected_types = " \n\n-> Expecting: " + Prostgles_1.JOIN_TYPES.map(t => JSON.stringify(t)).join(` | `);
|
|
2241
2250
|
const mt = joins.find(j => !j.type);
|
|
2242
2251
|
if (mt)
|
|
2243
2252
|
throw "Join type missing for: " + JSON.stringify(mt, null, 2) + expected_types;
|
|
2244
|
-
const it = joins.find(j => !
|
|
2253
|
+
const it = joins.find(j => !Prostgles_1.JOIN_TYPES.includes(j.type));
|
|
2245
2254
|
if (it)
|
|
2246
2255
|
throw "Incorrect join type for: " + JSON.stringify(it, null, 2) + expected_types;
|
|
2247
2256
|
}
|
|
@@ -2257,7 +2266,7 @@ class DboBuilder {
|
|
|
2257
2266
|
this.joinGraph[t2] = this.joinGraph[t2] || {};
|
|
2258
2267
|
this.joinGraph[t2][t1] = 1;
|
|
2259
2268
|
});
|
|
2260
|
-
const tables =
|
|
2269
|
+
const tables = this.joins.flatMap(t => t.tables);
|
|
2261
2270
|
this.joinPaths = [];
|
|
2262
2271
|
tables.map(t1 => {
|
|
2263
2272
|
tables.map(t2 => {
|
|
@@ -2316,11 +2325,11 @@ export type TxCB = {
|
|
|
2316
2325
|
const TSTableDataName = snakify(tov.name, true);
|
|
2317
2326
|
const TSTableHandlerName = JSON.stringify(tov.name);
|
|
2318
2327
|
if (tov.is_view) {
|
|
2319
|
-
this.dbo[tov.name] = new ViewHandler(this.db, tov, this,
|
|
2328
|
+
this.dbo[tov.name] = new ViewHandler(this.db, tov, this, undefined, undefined, this.joinPaths);
|
|
2320
2329
|
this.dboDefinition += ` ${TSTableHandlerName}: ViewHandler<${TSTableDataName}> \n`;
|
|
2321
2330
|
}
|
|
2322
2331
|
else {
|
|
2323
|
-
this.dbo[tov.name] = new TableHandler(this.db, tov, this,
|
|
2332
|
+
this.dbo[tov.name] = new TableHandler(this.db, tov, this, undefined, undefined, this.joinPaths);
|
|
2324
2333
|
this.dboDefinition += ` ${TSTableHandlerName}: TableHandler<${TSTableDataName}> \n`;
|
|
2325
2334
|
}
|
|
2326
2335
|
allDataDefs += `export type ${TSTableDataName} = { \n` +
|
|
@@ -2330,6 +2339,14 @@ export type TxCB = {
|
|
|
2330
2339
|
if (this.joinPaths && this.joinPaths.find(jp => [jp.t1, jp.t2].includes(tov.name))) {
|
|
2331
2340
|
let table = tov.name;
|
|
2332
2341
|
joinTableNames.push(table);
|
|
2342
|
+
const makeJoin = (isLeft = true, filter, select, options) => {
|
|
2343
|
+
return {
|
|
2344
|
+
[isLeft ? "$leftJoin" : "$innerJoin"]: table,
|
|
2345
|
+
filter,
|
|
2346
|
+
select,
|
|
2347
|
+
...options
|
|
2348
|
+
};
|
|
2349
|
+
};
|
|
2333
2350
|
this.dbo.innerJoin = this.dbo.innerJoin || {};
|
|
2334
2351
|
this.dbo.leftJoin = this.dbo.leftJoin || {};
|
|
2335
2352
|
this.dbo.innerJoinOne = this.dbo.innerJoinOne || {};
|
|
@@ -2341,15 +2358,11 @@ export type TxCB = {
|
|
|
2341
2358
|
return makeJoin(false, filter, select, options);
|
|
2342
2359
|
};
|
|
2343
2360
|
this.dbo.leftJoinOne[table] = (filter, select, options = {}) => {
|
|
2344
|
-
return makeJoin(true, filter, select,
|
|
2361
|
+
return makeJoin(true, filter, select, { ...options, limit: 1 });
|
|
2345
2362
|
};
|
|
2346
2363
|
this.dbo.innerJoinOne[table] = (filter, select, options = {}) => {
|
|
2347
|
-
return makeJoin(false, filter, select,
|
|
2364
|
+
return makeJoin(false, filter, select, { ...options, limit: 1 });
|
|
2348
2365
|
};
|
|
2349
|
-
function makeJoin(isLeft = true, filter, select, options) {
|
|
2350
|
-
return Object.assign({ [isLeft ? "$leftJoin" : "$innerJoin"]: table, filter,
|
|
2351
|
-
select }, options);
|
|
2352
|
-
}
|
|
2353
2366
|
}
|
|
2354
2367
|
});
|
|
2355
2368
|
i18nDef += " }> \n";
|
|
@@ -2377,13 +2390,12 @@ export type TxCB = {
|
|
|
2377
2390
|
let DATA_TYPES = !needType ? [] : await this.db.any("SELECT oid, typname FROM pg_type");
|
|
2378
2391
|
let USER_TABLES = !needType ? [] : await this.db.any("SELECT relid, relname FROM pg_catalog.pg_statio_user_tables");
|
|
2379
2392
|
this.dbo.sql = async (query, params, options, localParams) => {
|
|
2380
|
-
var _a, _b;
|
|
2381
2393
|
const canRunSQL = async (localParams) => {
|
|
2382
2394
|
if (!localParams)
|
|
2383
2395
|
return true;
|
|
2384
2396
|
const { socket } = localParams;
|
|
2385
2397
|
const publishParams = await this.prostgles.publishParser.getPublishParams({ socket });
|
|
2386
|
-
let res = await this.prostgles.opts.publishRawSQL(publishParams);
|
|
2398
|
+
let res = await this.prostgles.opts.publishRawSQL?.(publishParams);
|
|
2387
2399
|
return Boolean(res && typeof res === "boolean" || res === "*");
|
|
2388
2400
|
};
|
|
2389
2401
|
if (!(await canRunSQL(localParams)))
|
|
@@ -2393,7 +2405,7 @@ export type TxCB = {
|
|
|
2393
2405
|
if (returnType === "noticeSubscription") {
|
|
2394
2406
|
if (!socket)
|
|
2395
2407
|
throw "Only allowed with client socket";
|
|
2396
|
-
return await this.prostgles.dbEventsManager
|
|
2408
|
+
return await this.prostgles.dbEventsManager?.addNotice(socket);
|
|
2397
2409
|
}
|
|
2398
2410
|
else if (returnType === "statement") {
|
|
2399
2411
|
try {
|
|
@@ -2408,12 +2420,12 @@ export type TxCB = {
|
|
|
2408
2420
|
if (returnType === "arrayMode") {
|
|
2409
2421
|
finalQuery = new PQ({ text: exports.pgp.as.format(query, params), rowMode: "array" });
|
|
2410
2422
|
}
|
|
2411
|
-
let
|
|
2412
|
-
const {
|
|
2423
|
+
let _qres = await this.db.result(finalQuery, params);
|
|
2424
|
+
const { fields, rows, command } = _qres;
|
|
2413
2425
|
/**
|
|
2414
2426
|
* Fallback for watchSchema in case not superuser and cannot add db event listener
|
|
2415
2427
|
*/
|
|
2416
|
-
const { watchSchema, watchSchemaType } =
|
|
2428
|
+
const { watchSchema, watchSchemaType } = this.prostgles?.opts || {};
|
|
2417
2429
|
if (watchSchema &&
|
|
2418
2430
|
(!this.prostgles.isSuperUser || watchSchemaType === "queries") &&
|
|
2419
2431
|
(["CREATE", "ALTER", "DROP"].includes(command) ||
|
|
@@ -2424,7 +2436,7 @@ export type TxCB = {
|
|
|
2424
2436
|
if (command === "LISTEN") {
|
|
2425
2437
|
if (!socket)
|
|
2426
2438
|
throw "Only allowed with client socket";
|
|
2427
|
-
return await this.prostgles.dbEventsManager
|
|
2439
|
+
return await this.prostgles.dbEventsManager?.addNotify(query, socket);
|
|
2428
2440
|
}
|
|
2429
2441
|
else if (returnType === "rows") {
|
|
2430
2442
|
return rows;
|
|
@@ -2433,18 +2445,26 @@ export type TxCB = {
|
|
|
2433
2445
|
return rows[0];
|
|
2434
2446
|
}
|
|
2435
2447
|
else if (returnType === "value") {
|
|
2436
|
-
return
|
|
2448
|
+
return Object.values(rows?.[0] || {})?.[0];
|
|
2437
2449
|
}
|
|
2438
2450
|
else if (returnType === "values") {
|
|
2439
2451
|
return rows.map(r => Object.values(r[0]));
|
|
2440
2452
|
}
|
|
2441
2453
|
else {
|
|
2442
|
-
|
|
2443
|
-
|
|
2444
|
-
|
|
2445
|
-
|
|
2446
|
-
|
|
2447
|
-
|
|
2454
|
+
let qres = {
|
|
2455
|
+
duration: 0,
|
|
2456
|
+
..._qres,
|
|
2457
|
+
fields: fields?.map(f => {
|
|
2458
|
+
const dataType = DATA_TYPES.find(dt => +dt.oid === +f.dataTypeID)?.typname ?? "text", tableName = USER_TABLES.find(t => +t.relid === +f.tableID), tsDataType = postgresToTsType(dataType);
|
|
2459
|
+
return {
|
|
2460
|
+
...f,
|
|
2461
|
+
tsDataType,
|
|
2462
|
+
dataType,
|
|
2463
|
+
udt_name: dataType,
|
|
2464
|
+
tableName: tableName?.relname
|
|
2465
|
+
};
|
|
2466
|
+
}) ?? []
|
|
2467
|
+
};
|
|
2448
2468
|
return qres;
|
|
2449
2469
|
}
|
|
2450
2470
|
}
|
|
@@ -2641,8 +2661,13 @@ function isPlainObject(o) {
|
|
|
2641
2661
|
return Object(o) === o && Object.getPrototypeOf(o) === Object.prototype;
|
|
2642
2662
|
}
|
|
2643
2663
|
exports.isPlainObject = isPlainObject;
|
|
2664
|
+
function getKeys(o) {
|
|
2665
|
+
return Object.keys(o);
|
|
2666
|
+
}
|
|
2667
|
+
exports.getKeys = getKeys;
|
|
2644
2668
|
function postgresToTsType(udt_data_type) {
|
|
2645
|
-
return
|
|
2669
|
+
return getKeys(prostgles_types_1.TS_PG_Types).find(k => {
|
|
2670
|
+
// @ts-ignore
|
|
2646
2671
|
return prostgles_types_1.TS_PG_Types[k].includes(udt_data_type) || !prostgles_types_1.TS_PG_Types[k].length;
|
|
2647
2672
|
});
|
|
2648
2673
|
}
|
|
@@ -2890,6 +2915,7 @@ function sqlErrCodeToMsg(code) {
|
|
|
2890
2915
|
"XX001": "data_corrupted",
|
|
2891
2916
|
"XX002": "index_corrupted"
|
|
2892
2917
|
}, c2 = { "20000": "case_not_found", "21000": "cardinality_violation", "22000": "data_exception", "22001": "string_data_right_truncation", "22002": "null_value_no_indicator_parameter", "22003": "numeric_value_out_of_range", "22004": "null_value_not_allowed", "22005": "error_in_assignment", "22007": "invalid_datetime_format", "22008": "datetime_field_overflow", "22009": "invalid_time_zone_displacement_value", "22010": "invalid_indicator_parameter_value", "22011": "substring_error", "22012": "division_by_zero", "22013": "invalid_preceding_or_following_size", "22014": "invalid_argument_for_ntile_function", "22015": "interval_field_overflow", "22016": "invalid_argument_for_nth_value_function", "22018": "invalid_character_value_for_cast", "22019": "invalid_escape_character", "22021": "character_not_in_repertoire", "22022": "indicator_overflow", "22023": "invalid_parameter_value", "22024": "unterminated_c_string", "22025": "invalid_escape_sequence", "22026": "string_data_length_mismatch", "22027": "trim_error", "22030": "duplicate_json_object_key_value", "22031": "invalid_argument_for_sql_json_datetime_function", "22032": "invalid_json_text", "22033": "invalid_sql_json_subscript", "22034": "more_than_one_sql_json_item", "22035": "no_sql_json_item", "22036": "non_numeric_sql_json_item", "22037": "non_unique_keys_in_a_json_object", "22038": "singleton_sql_json_item_required", "22039": "sql_json_array_not_found", "23000": "integrity_constraint_violation", "23001": "restrict_violation", "23502": "not_null_violation", "23503": "foreign_key_violation", "23505": "unique_violation", "23514": "check_violation", "24000": "invalid_cursor_state", "25000": "invalid_transaction_state", "25001": "active_sql_transaction", "25002": "branch_transaction_already_active", "25003": "inappropriate_access_mode_for_branch_transaction", "25004": "inappropriate_isolation_level_for_branch_transaction", "25005": "no_active_sql_transaction_for_branch_transaction", "25006": "read_only_sql_transaction", "25007": "schema_and_data_statement_mixing_not_supported", "25008": "held_cursor_requires_same_isolation_level", "26000": "invalid_sql_statement_name", "27000": "triggered_data_change_violation", "28000": "invalid_authorization_specification", "34000": "invalid_cursor_name", "38000": "external_routine_exception", "38001": "containing_sql_not_permitted", "38002": "modifying_sql_data_not_permitted", "38003": "prohibited_sql_statement_attempted", "38004": "reading_sql_data_not_permitted", "39000": "external_routine_invocation_exception", "39001": "invalid_sqlstate_returned", "39004": "null_value_not_allowed", "40000": "transaction_rollback", "40001": "serialization_failure", "40002": "transaction_integrity_constraint_violation", "40003": "statement_completion_unknown", "42000": "syntax_error_or_access_rule_violation", "42501": "insufficient_privilege", "42601": "syntax_error", "42602": "invalid_name", "42611": "invalid_column_definition", "42622": "name_too_long", "42701": "duplicate_column", "42702": "ambiguous_column", "42703": "undefined_column", "42704": "undefined_object", "42710": "duplicate_object", "42712": "duplicate_alias", "42723": "duplicate_function", "42725": "ambiguous_function", "42803": "grouping_error", "42804": "datatype_mismatch", "42809": "wrong_object_type", "42830": "invalid_foreign_key", "42846": "cannot_coerce", "42883": "undefined_function", "42939": "reserved_name", "44000": "with_check_option_violation", "53000": "insufficient_resources", "53100": "disk_full", "53200": "out_of_memory", "53300": "too_many_connections", "53400": "configuration_limit_exceeded", "54000": "program_limit_exceeded", "54001": "statement_too_complex", "54011": "too_many_columns", "54023": "too_many_arguments", "55000": "object_not_in_prerequisite_state", "55006": "object_in_use", "57000": "operator_intervention", "57014": "query_canceled", "58000": "system_error", "58030": "io_error", "72000": "snapshot_too_old", "00000": "successful_completion", "01000": "warning", "0100C": "dynamic_result_sets_returned", "01008": "implicit_zero_bit_padding", "01003": "null_value_eliminated_in_set_function", "01007": "privilege_not_granted", "01006": "privilege_not_revoked", "01004": "string_data_right_truncation", "01P01": "deprecated_feature", "02000": "no_data", "02001": "no_additional_dynamic_result_sets_returned", "03000": "sql_statement_not_yet_complete", "08000": "connection_exception", "08003": "connection_does_not_exist", "08006": "connection_failure", "08001": "sqlclient_unable_to_establish_sqlconnection", "08004": "sqlserver_rejected_establishment_of_sqlconnection", "08007": "transaction_resolution_unknown", "08P01": "protocol_violation", "09000": "triggered_action_exception", "0A000": "feature_not_supported", "0B000": "invalid_transaction_initiation", "0F000": "locator_exception", "0F001": "invalid_locator_specification", "0L000": "invalid_grantor", "0LP01": "invalid_grant_operation", "0P000": "invalid_role_specification", "0Z000": "diagnostics_exception", "0Z002": "stacked_diagnostics_accessed_without_active_handler", "2202E": "array_subscript_error", "2200B": "escape_character_conflict", "2201E": "invalid_argument_for_logarithm", "2201F": "invalid_argument_for_power_function", "2201G": "invalid_argument_for_width_bucket_function", "2200D": "invalid_escape_octet", "22P06": "nonstandard_use_of_escape_character", "2201B": "invalid_regular_expression", "2201W": "invalid_row_count_in_limit_clause", "2201X": "invalid_row_count_in_result_offset_clause", "2202H": "invalid_tablesample_argument", "2202G": "invalid_tablesample_repeat", "2200C": "invalid_use_of_escape_character", "2200G": "most_specific_type_mismatch", "2200H": "sequence_generator_limit_exceeded", "2200F": "zero_length_character_string", "22P01": "floating_point_exception", "22P02": "invalid_text_representation", "22P03": "invalid_binary_representation", "22P04": "bad_copy_file_format", "22P05": "untranslatable_character", "2200L": "not_an_xml_document", "2200M": "invalid_xml_document", "2200N": "invalid_xml_content", "2200S": "invalid_xml_comment", "2200T": "invalid_xml_processing_instruction", "2203A": "sql_json_member_not_found", "2203B": "sql_json_number_not_found", "2203C": "sql_json_object_not_found", "2203D": "too_many_json_array_elements", "2203E": "too_many_json_object_members", "2203F": "sql_json_scalar_required", "23P01": "exclusion_violation", "25P01": "no_active_sql_transaction", "25P02": "in_failed_sql_transaction", "25P03": "idle_in_transaction_session_timeout", "28P01": "invalid_password", "2B000": "dependent_privilege_descriptors_still_exist", "2BP01": "dependent_objects_still_exist", "2D000": "invalid_transaction_termination", "2F000": "sql_routine_exception", "2F005": "function_executed_no_return_statement", "2F002": "modifying_sql_data_not_permitted", "2F003": "prohibited_sql_statement_attempted", "2F004": "reading_sql_data_not_permitted", "39P01": "trigger_protocol_violated", "39P02": "srf_protocol_violated", "39P03": "event_trigger_protocol_violated", "3B000": "savepoint_exception", "3B001": "invalid_savepoint_specification", "3D000": "invalid_catalog_name", "3F000": "invalid_schema_name", "40P01": "deadlock_detected", "42P20": "windowing_error", "42P19": "invalid_recursion", "42P18": "indeterminate_datatype", "42P21": "collation_mismatch", "42P22": "indeterminate_collation", "428C9": "generated_always", "42P01": "undefined_table", "42P02": "undefined_parameter", "42P03": "duplicate_cursor", "42P04": "duplicate_database", "42P05": "duplicate_prepared_statement", "42P06": "duplicate_schema", "42P07": "duplicate_table", "42P08": "ambiguous_parameter", "42P09": "ambiguous_alias", "42P10": "invalid_column_reference", "42P11": "invalid_cursor_definition", "42P12": "invalid_database_definition", "42P13": "invalid_function_definition", "42P14": "invalid_prepared_statement_definition", "42P15": "invalid_schema_definition", "42P16": "invalid_table_definition", "42P17": "invalid_object_definition", "55P02": "cant_change_runtime_param", "55P03": "lock_not_available", "55P04": "unsafe_new_enum_value_usage", "57P01": "admin_shutdown", "57P02": "crash_shutdown", "57P03": "cannot_connect_now", "57P04": "database_dropped", "58P01": "undefined_file", "58P02": "duplicate_file", "F0000": "config_file_error", "F0001": "lock_file_exists", "HV000": "fdw_error", "HV005": "fdw_column_name_not_found", "HV002": "fdw_dynamic_parameter_value_needed", "HV010": "fdw_function_sequence_error", "HV021": "fdw_inconsistent_descriptor_information", "HV024": "fdw_invalid_attribute_value", "HV007": "fdw_invalid_column_name", "HV008": "fdw_invalid_column_number", "HV004": "fdw_invalid_data_type", "HV006": "fdw_invalid_data_type_descriptors", "HV091": "fdw_invalid_descriptor_field_identifier", "HV00B": "fdw_invalid_handle", "HV00C": "fdw_invalid_option_index", "HV00D": "fdw_invalid_option_name", "HV090": "fdw_invalid_string_length_or_buffer_length", "HV00A": "fdw_invalid_string_format", "HV009": "fdw_invalid_use_of_null_pointer", "HV014": "fdw_too_many_handles", "HV001": "fdw_out_of_memory", "HV00P": "fdw_no_schemas", "HV00J": "fdw_option_name_not_found", "HV00K": "fdw_reply_handle", "HV00Q": "fdw_schema_not_found", "HV00R": "fdw_table_not_found", "HV00L": "fdw_unable_to_create_execution", "HV00M": "fdw_unable_to_create_reply", "HV00N": "fdw_unable_to_establish_connection", "P0000": "plpgsql_error", "P0001": "raise_exception", "P0002": "no_data_found", "P0003": "too_many_rows", "P0004": "assert_failure", "XX000": "internal_error", "XX001": "data_corrupted", "XX002": "index_corrupted" };
|
|
2918
|
+
//@ts-ignore
|
|
2893
2919
|
return c2[code] || errs[code] || code;
|
|
2894
2920
|
/*
|
|
2895
2921
|
https://www.postgresql.org/docs/13/errcodes-appendix.html
|
|
@@ -2924,10 +2950,10 @@ async function getInferredJoins(db, schema = "public") {
|
|
|
2924
2950
|
let existing = joins[eIdx];
|
|
2925
2951
|
if (existing) {
|
|
2926
2952
|
if (existing.tables[0] === d.table_name) {
|
|
2927
|
-
existing.on =
|
|
2953
|
+
existing.on = { ...existing.on, [d.column_name]: d.foreign_column_name };
|
|
2928
2954
|
}
|
|
2929
2955
|
else {
|
|
2930
|
-
existing.on =
|
|
2956
|
+
existing.on = { ...existing.on, [d.foreign_column_name]: d.column_name };
|
|
2931
2957
|
}
|
|
2932
2958
|
joins[eIdx] = existing;
|
|
2933
2959
|
}
|