prostgles-server 2.0.146 → 2.0.149
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 +43 -44
- 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 +54 -50
- package/dist/DboBuilder.d.ts.map +1 -1
- package/dist/DboBuilder.js +242 -206
- 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 +59 -31
- package/dist/FileManager.js.map +1 -1
- package/dist/Filtering.d.ts.map +1 -1
- package/dist/Filtering.js +17 -14
- 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 +125 -86
- package/dist/Prostgles.js.map +1 -1
- package/dist/PubSubManager.d.ts +8 -8
- package/dist/PubSubManager.d.ts.map +1 -1
- package/dist/PubSubManager.js +58 -52
- package/dist/PubSubManager.js.map +1 -1
- package/dist/QueryBuilder.d.ts +6 -5
- package/dist/QueryBuilder.d.ts.map +1 -1
- package/dist/QueryBuilder.js +124 -89
- package/dist/QueryBuilder.js.map +1 -1
- package/dist/SyncReplication.js +38 -35
- 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 +36 -28
- package/dist/TableConfig.js.map +1 -1
- package/dist/shortestPath.d.ts.map +1 -1
- package/dist/shortestPath.js +2 -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 +3 -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 +4 -3
- 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 +21 -19
- package/tests/server/package.json +2 -2
- package/tests/server/tsconfig.json +2 -2
- package/tsconfig.json +3 -2
package/dist/DboBuilder.js
CHANGED
|
@@ -3,8 +3,9 @@
|
|
|
3
3
|
* Copyright (c) Stefan L. All rights reserved.
|
|
4
4
|
* Licensed under the MIT License. See LICENSE in the project root for license information.
|
|
5
5
|
*--------------------------------------------------------------------------------------------*/
|
|
6
|
+
var _a;
|
|
6
7
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
-
exports.postgresToTsType = exports.isPlainObject = exports.DboBuilder = exports.TableHandler = exports.ViewHandler = exports.EXISTS_KEYS = exports.pgp = void 0;
|
|
8
|
+
exports.postgresToTsType = exports.getKeys = exports.isPlainObject = exports.DboBuilder = exports.TableHandler = exports.ViewHandler = exports.EXISTS_KEYS = exports.pgp = void 0;
|
|
8
9
|
const Bluebird = require("bluebird");
|
|
9
10
|
// declare global { export interface Promise<T> extends Bluebird<T> {} }
|
|
10
11
|
const pgPromise = require("pg-promise");
|
|
@@ -23,7 +24,6 @@ const prostgles_types_1 = require("prostgles-types");
|
|
|
23
24
|
// }>
|
|
24
25
|
const utils_1 = require("./utils");
|
|
25
26
|
const QueryBuilder_1 = require("./QueryBuilder");
|
|
26
|
-
const Prostgles_1 = require("./Prostgles");
|
|
27
27
|
const PubSubManager_1 = require("./PubSubManager");
|
|
28
28
|
const Filtering_1 = require("./Filtering");
|
|
29
29
|
exports.pgp = pgPromise({
|
|
@@ -62,13 +62,17 @@ function escapeTSNames(str, capitalize = true) {
|
|
|
62
62
|
const shortestPath_1 = require("./shortestPath");
|
|
63
63
|
/* DEBUG CLIENT ERRORS HERE */
|
|
64
64
|
function makeErr(err, localParams, view, allowedKeys) {
|
|
65
|
-
var _a;
|
|
66
65
|
// console.trace(err)
|
|
67
66
|
if (process.env.TEST_TYPE || process.env.PRGL_DEBUG) {
|
|
68
67
|
console.trace(err);
|
|
69
68
|
}
|
|
70
|
-
const errObject =
|
|
71
|
-
|
|
69
|
+
const errObject = {
|
|
70
|
+
...((!localParams || !localParams.socket) ? err : {}),
|
|
71
|
+
...(0, PubSubManager_1.filterObj)(err, ["column", "code", "table", "constraint"]),
|
|
72
|
+
...(err && err.toString ? { txt: err.toString() } : {}),
|
|
73
|
+
code_info: sqlErrCodeToMsg(err.code)
|
|
74
|
+
};
|
|
75
|
+
if (view?.dboBuilder?.constraints && errObject.constraint && !errObject.column) {
|
|
72
76
|
const constraint = view.dboBuilder.constraints
|
|
73
77
|
.find(c => c.conname === errObject.constraint && c.relname === view.name);
|
|
74
78
|
if (constraint) {
|
|
@@ -100,15 +104,14 @@ class ColSet {
|
|
|
100
104
|
if (!allowedCols || badCol) {
|
|
101
105
|
throw "Missing or unexpected columns: " + badCol;
|
|
102
106
|
}
|
|
103
|
-
if (prostgles_types_1.isEmpty(data))
|
|
107
|
+
if ((0, prostgles_types_1.isEmpty)(data))
|
|
104
108
|
throw "No data";
|
|
105
|
-
let row = PubSubManager_1.filterObj(data, allowedCols);
|
|
109
|
+
let row = (0, PubSubManager_1.filterObj)(data, allowedCols);
|
|
106
110
|
if (validate) {
|
|
107
111
|
row = await validate(row);
|
|
108
112
|
}
|
|
109
113
|
const rowKeys = Object.keys(row);
|
|
110
114
|
return rowKeys.map(key => {
|
|
111
|
-
var _a;
|
|
112
115
|
const col = this.opts.columns.find(c => c.name === key);
|
|
113
116
|
if (!col)
|
|
114
117
|
throw "Unexpected missing col name";
|
|
@@ -120,13 +123,13 @@ class ColSet {
|
|
|
120
123
|
let escapedVal;
|
|
121
124
|
if (["geometry", "geography"].includes(col.udt_name) && row[key] && isPlainObject(row[key])) {
|
|
122
125
|
const basicFunc = (args) => {
|
|
123
|
-
return args.map(arg => PubSubManager_1.asValue(arg)).join(", ");
|
|
126
|
+
return args.map(arg => (0, PubSubManager_1.asValue)(arg)).join(", ");
|
|
124
127
|
};
|
|
125
128
|
const basicFuncNames = ["ST_GeomFromText", "ST_Point", "ST_MakePoint", "ST_MakePointM", "ST_PointFromText", "ST_GeomFromEWKT", "ST_GeomFromGeoJSON"];
|
|
126
129
|
const dataKeys = Object.keys(row[key]);
|
|
127
130
|
const funcName = dataKeys[0];
|
|
128
131
|
const funcExists = basicFuncNames.includes(funcName);
|
|
129
|
-
const funcArgs =
|
|
132
|
+
const funcArgs = row[key]?.[funcName];
|
|
130
133
|
if (dataKeys.length !== 1 || !funcExists || !Array.isArray(funcArgs)) {
|
|
131
134
|
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
135
|
}
|
|
@@ -136,7 +139,7 @@ class ColSet {
|
|
|
136
139
|
escapedVal = exports.pgp.as.format(colIsUUID ? "$1::uuid" : colIsJSON ? "$1:json" : "$1", [row[key]]);
|
|
137
140
|
}
|
|
138
141
|
return {
|
|
139
|
-
escapedCol: prostgles_types_1.asName(key),
|
|
142
|
+
escapedCol: (0, prostgles_types_1.asName)(key),
|
|
140
143
|
escapedVal
|
|
141
144
|
};
|
|
142
145
|
});
|
|
@@ -145,14 +148,14 @@ class ColSet {
|
|
|
145
148
|
const res = (await Promise.all((Array.isArray(data) ? data : [data]).map(async (d) => {
|
|
146
149
|
const rowParts = await this.getRow(d, allowedCols, validate);
|
|
147
150
|
const select = rowParts.map(r => r.escapedCol).join(", "), values = rowParts.map(r => r.escapedVal).join(", ");
|
|
148
|
-
return `INSERT INTO ${prostgles_types_1.asName(this.opts.tableName)} (${select}) VALUES (${values})`;
|
|
151
|
+
return `INSERT INTO ${(0, prostgles_types_1.asName)(this.opts.tableName)} (${select}) VALUES (${values})`;
|
|
149
152
|
}))).join(";\n") + " ";
|
|
150
153
|
return res;
|
|
151
154
|
}
|
|
152
155
|
async getUpdateQuery(data, allowedCols, validate) {
|
|
153
156
|
const res = (await Promise.all((Array.isArray(data) ? data : [data]).map(async (d) => {
|
|
154
157
|
const rowParts = await this.getRow(d, allowedCols, validate);
|
|
155
|
-
return `UPDATE ${prostgles_types_1.asName(this.opts.tableName)} SET ` + rowParts.map(r => `${r.escapedCol} = ${r.escapedVal} `).join(",\n");
|
|
158
|
+
return `UPDATE ${(0, prostgles_types_1.asName)(this.opts.tableName)} SET ` + rowParts.map(r => `${r.escapedCol} = ${r.escapedVal} `).join(",\n");
|
|
156
159
|
}))).join(";\n") + " ";
|
|
157
160
|
return res;
|
|
158
161
|
}
|
|
@@ -172,14 +175,14 @@ class ViewHandler {
|
|
|
172
175
|
this.joinPaths = joinPaths;
|
|
173
176
|
this.tableOrViewInfo = tableOrViewInfo;
|
|
174
177
|
this.name = tableOrViewInfo.name;
|
|
175
|
-
this.escapedName = prostgles_types_1.asName(this.name);
|
|
178
|
+
this.escapedName = (0, prostgles_types_1.asName)(this.name);
|
|
176
179
|
this.columns = tableOrViewInfo.columns;
|
|
177
180
|
/* cols are sorted by name to reduce .d.ts schema rewrites */
|
|
178
181
|
this.columnsForTypes = tableOrViewInfo.columns.slice(0).sort((a, b) => a.name.localeCompare(b.name));
|
|
179
182
|
this.column_names = tableOrViewInfo.columns.map(c => c.name);
|
|
180
183
|
// this.pubSubManager = pubSubManager;
|
|
181
184
|
this.dboBuilder = dboBuilder;
|
|
182
|
-
this.joins = this.dboBuilder.joins;
|
|
185
|
+
this.joins = this.dboBuilder.joins ?? [];
|
|
183
186
|
// fix this
|
|
184
187
|
// and also make hot schema reload over ws
|
|
185
188
|
this.colSet = new ColSet(this.columns, this.name);
|
|
@@ -218,10 +221,10 @@ class ViewHandler {
|
|
|
218
221
|
/* CTID not available in AFTER trigger */
|
|
219
222
|
// .concat(this.is_view? [] : ["ctid"])
|
|
220
223
|
.sort()
|
|
221
|
-
.map(f => (tableAlias ? (prostgles_types_1.asName(tableAlias) + ".") : "") + prostgles_types_1.asName(f))
|
|
224
|
+
.map(f => (tableAlias ? ((0, prostgles_types_1.asName)(tableAlias) + ".") : "") + (0, prostgles_types_1.asName)(f))
|
|
222
225
|
.map(f => `md5(coalesce(${f}::text, 'dd'))`)
|
|
223
226
|
.join(" || ") +
|
|
224
|
-
`)` + (alias ? ` as ${prostgles_types_1.asName(alias)}` : "");
|
|
227
|
+
`)` + (alias ? ` as ${(0, prostgles_types_1.asName)(alias)}` : "");
|
|
225
228
|
}
|
|
226
229
|
async validateViewRules(fields, filterFields, returningFields, forcedFilter, rule) {
|
|
227
230
|
/* Safely test publish rules */
|
|
@@ -276,7 +279,6 @@ class ViewHandler {
|
|
|
276
279
|
return { query, toOne: false };
|
|
277
280
|
}
|
|
278
281
|
getJoins(source, target, path, checkTableConfig) {
|
|
279
|
-
var _a, _b, _e;
|
|
280
282
|
let paths = [];
|
|
281
283
|
if (!this.joinPaths)
|
|
282
284
|
throw `${source} - ${target} Join info missing or dissallowed`;
|
|
@@ -284,7 +286,7 @@ class ViewHandler {
|
|
|
284
286
|
throw `Empty join path ( $path ) specified for ${source} <-> ${target}`;
|
|
285
287
|
/* Find the join path between tables */
|
|
286
288
|
if (checkTableConfig) {
|
|
287
|
-
const tableConfigJoinInfo =
|
|
289
|
+
const tableConfigJoinInfo = this.dboBuilder?.prostgles?.tableConfigurator?.getJoinInfo(source, target);
|
|
288
290
|
if (tableConfigJoinInfo)
|
|
289
291
|
return tableConfigJoinInfo;
|
|
290
292
|
}
|
|
@@ -351,7 +353,6 @@ class ViewHandler {
|
|
|
351
353
|
throw `invalid filter -> ${JSON.stringify(filter)} \nExpecting: undefined | {} | { field_name: "value" } | { field: { $gt: 22 } } ... `;
|
|
352
354
|
}
|
|
353
355
|
async getInfo(param1, param2, param3, tableRules, localParams) {
|
|
354
|
-
var _a, _b, _e, _f, _g, _h, _j, _k, _l, _m, _o;
|
|
355
356
|
const p = this.getValidatedRules(tableRules, localParams);
|
|
356
357
|
if (!p.getInfo)
|
|
357
358
|
throw "Not allowed";
|
|
@@ -360,18 +361,17 @@ class ViewHandler {
|
|
|
360
361
|
* Media is directly related to this table (does not come from a deeply joined table)
|
|
361
362
|
*/
|
|
362
363
|
let has_direct_media = false;
|
|
363
|
-
const mediaTable =
|
|
364
|
+
const mediaTable = this.dboBuilder.prostgles?.opts?.fileTable?.tableName;
|
|
364
365
|
if (!this.is_media && mediaTable) {
|
|
365
|
-
if (
|
|
366
|
-
has_media =
|
|
366
|
+
if (this.dboBuilder.prostgles?.opts?.fileTable?.referencedTables?.[this.name]) {
|
|
367
|
+
has_media = this.dboBuilder.prostgles?.opts?.fileTable?.referencedTables?.[this.name];
|
|
367
368
|
has_direct_media = true;
|
|
368
369
|
}
|
|
369
370
|
else {
|
|
370
371
|
const jp = this.dboBuilder.joinPaths.find(jp => jp.t1 === this.name && jp.t2 === mediaTable);
|
|
371
372
|
if (jp && jp.path.length <= 3) {
|
|
372
373
|
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); });
|
|
374
|
+
const cols = (await this?.dboBuilder?.dbo?.[tableName]?.getColumns?.())?.filter(c => jp.path.includes(c?.references?.ftable));
|
|
375
375
|
if (cols && cols.length && has_media !== "many") {
|
|
376
376
|
if (cols.find(c => !c.is_pkey)) {
|
|
377
377
|
has_media = "many";
|
|
@@ -406,30 +406,39 @@ class ViewHandler {
|
|
|
406
406
|
.filter(c => {
|
|
407
407
|
const { insert, select, update } = p || {};
|
|
408
408
|
return [
|
|
409
|
-
...(
|
|
410
|
-
...(
|
|
411
|
-
...(
|
|
409
|
+
...(insert?.fields || []),
|
|
410
|
+
...(select?.fields || []),
|
|
411
|
+
...(update?.fields || []),
|
|
412
412
|
].includes(c.name);
|
|
413
413
|
})
|
|
414
414
|
.map(_c => {
|
|
415
|
-
|
|
416
|
-
let c = Object.assign({}, _c);
|
|
415
|
+
let c = { ..._c };
|
|
417
416
|
let label = c.comment || capitalizeFirstLetter(c.name, " ");
|
|
418
|
-
const tblConfig =
|
|
417
|
+
const tblConfig = this.dboBuilder.prostgles?.opts?.tableConfig?.[this.name];
|
|
419
418
|
if (tblConfig && "columns" in tblConfig) {
|
|
420
|
-
const lbl =
|
|
419
|
+
const lbl = tblConfig?.columns[c.name]?.label;
|
|
421
420
|
if (["string", "object"].includes(typeof lbl)) {
|
|
422
421
|
if (typeof lbl === "string") {
|
|
423
422
|
label = lbl;
|
|
424
423
|
}
|
|
425
424
|
else if (lang) {
|
|
426
|
-
label = (lbl
|
|
425
|
+
label = (lbl?.[lang]) || lbl?.en || label;
|
|
427
426
|
}
|
|
428
427
|
}
|
|
429
428
|
}
|
|
430
429
|
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
430
|
delete c.privileges;
|
|
432
|
-
return
|
|
431
|
+
return {
|
|
432
|
+
...c,
|
|
433
|
+
label,
|
|
434
|
+
tsDataType: postgresToTsType(c.udt_name),
|
|
435
|
+
insert: insert && Boolean(p.insert && p.insert.fields && p.insert.fields.includes(c.name)),
|
|
436
|
+
select: select && Boolean(p.select && p.select.fields && p.select.fields.includes(c.name)),
|
|
437
|
+
filter: Boolean(p.select && p.select.filterFields && p.select.filterFields.includes(c.name)),
|
|
438
|
+
update: update && Boolean(p.update && p.update.fields && p.update.fields.includes(c.name)),
|
|
439
|
+
delete: _delete && Boolean(p.delete && p.delete.filterFields && p.delete.filterFields.includes(c.name)),
|
|
440
|
+
...(this.dboBuilder?.prostgles?.tableConfigurator?.getColInfo({ table: this.name, col: c.name }) || {})
|
|
441
|
+
};
|
|
433
442
|
}).filter(c => c.select || c.update || c.delete || c.insert);
|
|
434
443
|
//.sort((a, b) => a.ordinal_position - b.ordinal_position);
|
|
435
444
|
// const tblInfo = await this.getInfo();
|
|
@@ -449,15 +458,14 @@ class ViewHandler {
|
|
|
449
458
|
}
|
|
450
459
|
}
|
|
451
460
|
getValidatedRules(tableRules, localParams) {
|
|
452
|
-
|
|
453
|
-
if (utils_1.get(localParams, "socket") && !tableRules) {
|
|
461
|
+
if ((0, utils_1.get)(localParams, "socket") && !tableRules) {
|
|
454
462
|
throw "INTERNAL ERROR: Unexpected case -> localParams && !tableRules";
|
|
455
463
|
}
|
|
456
464
|
/* Computed fields are allowed only if select is allowed */
|
|
457
465
|
const allColumns = this.column_names.slice(0).map(fieldName => ({
|
|
458
466
|
type: "column",
|
|
459
467
|
name: fieldName,
|
|
460
|
-
getQuery: ({ tableAlias }) => QueryBuilder_1.asNameAlias(fieldName, tableAlias),
|
|
468
|
+
getQuery: ({ tableAlias }) => (0, QueryBuilder_1.asNameAlias)(fieldName, tableAlias),
|
|
461
469
|
selected: false
|
|
462
470
|
})).concat(QueryBuilder_1.COMPUTED_FIELDS.map(c => ({
|
|
463
471
|
type: c.type,
|
|
@@ -473,7 +481,7 @@ class ViewHandler {
|
|
|
473
481
|
selected: false
|
|
474
482
|
})));
|
|
475
483
|
if (tableRules) {
|
|
476
|
-
if (prostgles_types_1.isEmpty(tableRules))
|
|
484
|
+
if ((0, prostgles_types_1.isEmpty)(tableRules))
|
|
477
485
|
throw "INTERNAL ERROR: Unexpected case -> Empty table rules for " + this.name;
|
|
478
486
|
const throwFieldsErr = (command, fieldType = "fields") => {
|
|
479
487
|
throw `Invalid publish.${this.name}.${command} rule -> ${fieldType} setting is missing.\nPlease specify allowed ${fieldType} in this format: "*" | { col_name: false } | { col1: true, col2: true }`;
|
|
@@ -483,8 +491,8 @@ class ViewHandler {
|
|
|
483
491
|
};
|
|
484
492
|
let res = {
|
|
485
493
|
allColumns,
|
|
486
|
-
getColumns:
|
|
487
|
-
getInfo:
|
|
494
|
+
getColumns: tableRules?.getColumns ?? true,
|
|
495
|
+
getInfo: tableRules?.getColumns ?? true,
|
|
488
496
|
};
|
|
489
497
|
/* SELECT */
|
|
490
498
|
if (tableRules.select) {
|
|
@@ -499,7 +507,7 @@ class ViewHandler {
|
|
|
499
507
|
}
|
|
500
508
|
res.select = {
|
|
501
509
|
fields: this.parseFieldFilter(tableRules.select.fields),
|
|
502
|
-
forcedFilter:
|
|
510
|
+
forcedFilter: { ...tableRules.select.forcedFilter },
|
|
503
511
|
filterFields: this.parseFieldFilter(tableRules.select.filterFields),
|
|
504
512
|
maxLimit
|
|
505
513
|
};
|
|
@@ -510,9 +518,9 @@ class ViewHandler {
|
|
|
510
518
|
return throwFieldsErr("update");
|
|
511
519
|
res.update = {
|
|
512
520
|
fields: this.parseFieldFilter(tableRules.update.fields),
|
|
513
|
-
forcedData:
|
|
514
|
-
forcedFilter:
|
|
515
|
-
returningFields: getFirstSpecified(
|
|
521
|
+
forcedData: { ...tableRules.update.forcedData },
|
|
522
|
+
forcedFilter: { ...tableRules.update.forcedFilter },
|
|
523
|
+
returningFields: getFirstSpecified(tableRules.update?.returningFields, tableRules?.select?.fields, tableRules.update.fields),
|
|
516
524
|
filterFields: this.parseFieldFilter(tableRules.update.filterFields)
|
|
517
525
|
};
|
|
518
526
|
}
|
|
@@ -522,8 +530,8 @@ class ViewHandler {
|
|
|
522
530
|
return throwFieldsErr("insert");
|
|
523
531
|
res.insert = {
|
|
524
532
|
fields: this.parseFieldFilter(tableRules.insert.fields),
|
|
525
|
-
forcedData:
|
|
526
|
-
returningFields: getFirstSpecified(tableRules.insert.returningFields,
|
|
533
|
+
forcedData: { ...tableRules.insert.forcedData },
|
|
534
|
+
returningFields: getFirstSpecified(tableRules.insert.returningFields, tableRules?.select?.fields, tableRules.insert.fields)
|
|
527
535
|
};
|
|
528
536
|
}
|
|
529
537
|
/* DELETE */
|
|
@@ -531,9 +539,9 @@ class ViewHandler {
|
|
|
531
539
|
if (!tableRules.delete.filterFields)
|
|
532
540
|
return throwFieldsErr("delete", "filterFields");
|
|
533
541
|
res.delete = {
|
|
534
|
-
forcedFilter:
|
|
542
|
+
forcedFilter: { ...tableRules.delete.forcedFilter },
|
|
535
543
|
filterFields: this.parseFieldFilter(tableRules.delete.filterFields),
|
|
536
|
-
returningFields: getFirstSpecified(tableRules.delete.returningFields,
|
|
544
|
+
returningFields: getFirstSpecified(tableRules.delete.returningFields, tableRules?.select?.fields, tableRules.delete.filterFields)
|
|
537
545
|
};
|
|
538
546
|
}
|
|
539
547
|
if (!tableRules.select && !tableRules.update && !tableRules.delete && !tableRules.insert) {
|
|
@@ -576,7 +584,7 @@ class ViewHandler {
|
|
|
576
584
|
};
|
|
577
585
|
}
|
|
578
586
|
}
|
|
579
|
-
async find(filter, selectParams, param3_unused
|
|
587
|
+
async find(filter, selectParams, param3_unused, tableRules, localParams) {
|
|
580
588
|
try {
|
|
581
589
|
filter = filter || {};
|
|
582
590
|
const allowedReturnTypes = ["row", "value", "values"];
|
|
@@ -609,7 +617,7 @@ class ViewHandler {
|
|
|
609
617
|
if (maxLimit && !Number.isInteger(maxLimit))
|
|
610
618
|
throw ` invalid publish.${this.name}.select.maxLimit -> expecting integer but got ` + maxLimit;
|
|
611
619
|
}
|
|
612
|
-
let q = await QueryBuilder_1.getNewQuery(this, filter, selectParams, param3_unused, tableRules, localParams, this.columns), _query = QueryBuilder_1.makeQuery(this, q, undefined, undefined, selectParams);
|
|
620
|
+
let q = await (0, QueryBuilder_1.getNewQuery)(this, filter, selectParams, param3_unused, tableRules, localParams, this.columns), _query = (0, QueryBuilder_1.makeQuery)(this, q, undefined, undefined, selectParams);
|
|
613
621
|
// console.log(_query, JSON.stringify(q, null, 2))
|
|
614
622
|
if (testRule) {
|
|
615
623
|
try {
|
|
@@ -646,14 +654,14 @@ class ViewHandler {
|
|
|
646
654
|
}
|
|
647
655
|
findOne(filter, selectParams, param3_unused, table_rules, localParams) {
|
|
648
656
|
try {
|
|
649
|
-
const { select = "*", orderBy
|
|
657
|
+
const { select = "*", orderBy, offset = 0 } = selectParams || {};
|
|
650
658
|
if (selectParams) {
|
|
651
659
|
const good_params = ["select", "orderBy", "offset"];
|
|
652
660
|
const bad_params = Object.keys(selectParams).filter(k => !good_params.includes(k));
|
|
653
661
|
if (bad_params && bad_params.length)
|
|
654
662
|
throw "Invalid params: " + bad_params.join(", ") + " \n Expecting: " + good_params.join(", ");
|
|
655
663
|
}
|
|
656
|
-
return this.find(filter, { select, orderBy, limit: 1, offset, returnType: "row" },
|
|
664
|
+
return this.find(filter, { select, orderBy, limit: 1, offset, returnType: "row" }, undefined, table_rules, localParams);
|
|
657
665
|
}
|
|
658
666
|
catch (e) {
|
|
659
667
|
if (localParams && localParams.testRule)
|
|
@@ -664,9 +672,9 @@ class ViewHandler {
|
|
|
664
672
|
async count(filter, param2_unused, param3_unused, table_rules, localParams = {}) {
|
|
665
673
|
filter = filter || {};
|
|
666
674
|
try {
|
|
667
|
-
return await this.find(filter, { select: "", limit: 0 },
|
|
675
|
+
return await this.find(filter, { select: "", limit: 0 }, undefined, table_rules, localParams)
|
|
668
676
|
.then(async (allowed) => {
|
|
669
|
-
const { filterFields, forcedFilter } = utils_1.get(table_rules, "select") || {};
|
|
677
|
+
const { filterFields, forcedFilter } = (0, utils_1.get)(table_rules, "select") || {};
|
|
670
678
|
const where = (await this.prepareWhere({ filter, forcedFilter, filterFields, addKeywords: true, localParams, tableRule: table_rules }));
|
|
671
679
|
let query = "SELECT COUNT(*) FROM " + this.escapedName + " " + where;
|
|
672
680
|
return (this.t || this.db).one(query, { _psqlWS_tableName: this.name }).then(({ count }) => +count);
|
|
@@ -681,13 +689,12 @@ class ViewHandler {
|
|
|
681
689
|
async size(filter, selectParams, param3_unused, table_rules, localParams = {}) {
|
|
682
690
|
filter = filter || {};
|
|
683
691
|
try {
|
|
684
|
-
return await this.find(filter,
|
|
692
|
+
return await this.find(filter, { ...selectParams, limit: 2 }, undefined, table_rules, localParams)
|
|
685
693
|
.then(async (_allowed) => {
|
|
686
694
|
// let rules: TableRule = table_rules || {};
|
|
687
695
|
// rules.select.maxLimit = Number.MAX_SAFE_INTEGER;
|
|
688
696
|
// 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 }));
|
|
697
|
+
const q = await this.find(filter, { ...selectParams, limit: selectParams?.limit ?? Number.MAX_SAFE_INTEGER }, undefined, table_rules, { ...localParams, returnQuery: true });
|
|
691
698
|
const query = `
|
|
692
699
|
SELECT sum(pg_column_size((prgl_size_query.*))) as size
|
|
693
700
|
FROM (
|
|
@@ -731,7 +738,7 @@ class ViewHandler {
|
|
|
731
738
|
prepareSelect(selectParams = "*", allowed_cols, allow_empty = true, tableAlias) {
|
|
732
739
|
if (tableAlias) {
|
|
733
740
|
let cs = this.prepareColumnSet(selectParams, allowed_cols, true, false);
|
|
734
|
-
return cs.columns.map(col => `${this.escapedName}.${prostgles_types_1.asName(col.name)}`).join(", ");
|
|
741
|
+
return cs.columns.map(col => `${this.escapedName}.${(0, prostgles_types_1.asName)(col.name)}`).join(", ");
|
|
735
742
|
}
|
|
736
743
|
else {
|
|
737
744
|
return this.prepareColumnSet(selectParams, allowed_cols, true, true);
|
|
@@ -744,7 +751,7 @@ class ViewHandler {
|
|
|
744
751
|
* Parses group or simple filter
|
|
745
752
|
*/
|
|
746
753
|
async prepareWhere(params) {
|
|
747
|
-
const { filter, select, forcedFilter, filterFields: ff, addKeywords = true, tableAlias
|
|
754
|
+
const { filter, select, forcedFilter, filterFields: ff, addKeywords = true, tableAlias, localParams, tableRule } = params;
|
|
748
755
|
const { $and: $and_key, $or: $or_key } = this.dboBuilder.prostgles.keywords;
|
|
749
756
|
let filterFields = ff;
|
|
750
757
|
/* Local update allow all. TODO -> FIX THIS */
|
|
@@ -754,7 +761,7 @@ class ViewHandler {
|
|
|
754
761
|
if (!f)
|
|
755
762
|
throw "Invalid/missing group filter provided";
|
|
756
763
|
let result = "";
|
|
757
|
-
let keys =
|
|
764
|
+
let keys = getKeys(f);
|
|
758
765
|
if (!keys.length)
|
|
759
766
|
return result;
|
|
760
767
|
if ((keys.includes($and_key) || keys.includes($or_key))) {
|
|
@@ -776,7 +783,7 @@ class ViewHandler {
|
|
|
776
783
|
}
|
|
777
784
|
else if (!group) {
|
|
778
785
|
result = await this.getCondition({
|
|
779
|
-
filter:
|
|
786
|
+
filter: { ...f },
|
|
780
787
|
select,
|
|
781
788
|
allowed_colnames: this.parseFieldFilter(filterFields),
|
|
782
789
|
tableAlias,
|
|
@@ -788,7 +795,7 @@ class ViewHandler {
|
|
|
788
795
|
};
|
|
789
796
|
if (!isPlainObject(filter))
|
|
790
797
|
throw "\nInvalid filter\nExpecting an object but got -> " + JSON.stringify(filter);
|
|
791
|
-
let _filter =
|
|
798
|
+
let _filter = { ...filter };
|
|
792
799
|
if (forcedFilter) {
|
|
793
800
|
_filter = {
|
|
794
801
|
[$and_key]: [forcedFilter, _filter].filter(f => f)
|
|
@@ -801,7 +808,7 @@ class ViewHandler {
|
|
|
801
808
|
cond = "WHERE " + cond;
|
|
802
809
|
return cond || "";
|
|
803
810
|
}
|
|
804
|
-
async prepareExistCondition(eConfig, localParams
|
|
811
|
+
async prepareExistCondition(eConfig, localParams) {
|
|
805
812
|
let res = "";
|
|
806
813
|
const thisTable = this.name;
|
|
807
814
|
const isNotExists = ["$notExists", "$notExistsJoined"].includes(eConfig.existType);
|
|
@@ -824,7 +831,7 @@ class ViewHandler {
|
|
|
824
831
|
if (!depth && eConfig.shortestJoin)
|
|
825
832
|
exactPaths = undefined;
|
|
826
833
|
const jinf = this.getJoins(t1, t2, exactPaths, true);
|
|
827
|
-
expectOne = expectOne && jinf.expectOne;
|
|
834
|
+
expectOne = Boolean(expectOne && jinf.expectOne);
|
|
828
835
|
joinPaths = joinPaths.concat(jinf.paths);
|
|
829
836
|
});
|
|
830
837
|
let r = makeJoin({ paths: joinPaths, expectOne }, 0);
|
|
@@ -832,13 +839,13 @@ class ViewHandler {
|
|
|
832
839
|
function makeJoin(joinInfo, ji) {
|
|
833
840
|
const { paths } = joinInfo;
|
|
834
841
|
const jp = paths[ji];
|
|
835
|
-
let prevTable = ji
|
|
842
|
+
// let prevTable = ji? paths[ji - 1].table : jp.source;
|
|
836
843
|
let table = paths[ji].table;
|
|
837
|
-
let tableAlias = prostgles_types_1.asName(ji < paths.length - 1 ? `jd${ji}` : table);
|
|
838
|
-
let prevTableAlias = prostgles_types_1.asName(ji ? `jd${ji - 1}` : thisTable);
|
|
839
|
-
let cond = `${jp.on.map(([c1, c2]) => `${prevTableAlias}.${prostgles_types_1.asName(c1)} = ${tableAlias}.${prostgles_types_1.asName(c2)}`).join("\n AND ")}`;
|
|
844
|
+
let tableAlias = (0, prostgles_types_1.asName)(ji < paths.length - 1 ? `jd${ji}` : table);
|
|
845
|
+
let prevTableAlias = (0, prostgles_types_1.asName)(ji ? `jd${ji - 1}` : thisTable);
|
|
846
|
+
let cond = `${jp.on.map(([c1, c2]) => `${prevTableAlias}.${(0, prostgles_types_1.asName)(c1)} = ${tableAlias}.${(0, prostgles_types_1.asName)(c2)}`).join("\n AND ")}`;
|
|
840
847
|
let j = `SELECT 1 \n` +
|
|
841
|
-
`FROM ${prostgles_types_1.asName(table)} ${tableAlias} \n` +
|
|
848
|
+
`FROM ${(0, prostgles_types_1.asName)(table)} ${tableAlias} \n` +
|
|
842
849
|
`WHERE ${cond} \n`; //
|
|
843
850
|
if (ji === paths.length - 1 &&
|
|
844
851
|
finalFilter) {
|
|
@@ -881,7 +888,7 @@ class ViewHandler {
|
|
|
881
888
|
throw "Issue with preparing $exists query for table " + t2 + "\n->" + JSON.stringify(err);
|
|
882
889
|
}
|
|
883
890
|
if (!isJoined) {
|
|
884
|
-
res = `${isNotExists ? " NOT " : " "} EXISTS (SELECT 1 \nFROM ${prostgles_types_1.asName(t2)} \n${finalWhere ? `WHERE ${finalWhere}` : ""}) `;
|
|
891
|
+
res = `${isNotExists ? " NOT " : " "} EXISTS (SELECT 1 \nFROM ${(0, prostgles_types_1.asName)(t2)} \n${finalWhere ? `WHERE ${finalWhere}` : ""}) `;
|
|
885
892
|
}
|
|
886
893
|
else {
|
|
887
894
|
res = makeTableChain(finalWhere);
|
|
@@ -896,7 +903,7 @@ class ViewHandler {
|
|
|
896
903
|
*/
|
|
897
904
|
async getCondition(params) {
|
|
898
905
|
const { filter, select, allowed_colnames, tableAlias, localParams, tableRules } = params;
|
|
899
|
-
let data =
|
|
906
|
+
let data = { ...filter };
|
|
900
907
|
/* Exists join filter */
|
|
901
908
|
const ERR = "Invalid exists filter. \nExpecting somethibng like: { $exists: { tableName.tableName2: Filter } } | { $exists: { \"**.tableName3\": Filter } }\n";
|
|
902
909
|
const SP_WILDCARD = "**";
|
|
@@ -945,7 +952,7 @@ class ViewHandler {
|
|
|
945
952
|
funcFilterkeys.map(f => {
|
|
946
953
|
const funcArgs = data[f.name];
|
|
947
954
|
if (!Array.isArray(funcArgs))
|
|
948
|
-
throw `A function filter must contain an array. E.g: { $funcFilterName: ["col1"] } \n but got: ${JSON.stringify(PubSubManager_1.filterObj(data, [f.name]))} `;
|
|
955
|
+
throw `A function filter must contain an array. E.g: { $funcFilterName: ["col1"] } \n but got: ${JSON.stringify((0, PubSubManager_1.filterObj)(data, [f.name]))} `;
|
|
949
956
|
const fields = this.parseFieldFilter(f.getFields(funcArgs), true, allowed_colnames);
|
|
950
957
|
const dissallowedCols = fields.filter(fname => !allowed_colnames.includes(fname));
|
|
951
958
|
if (dissallowedCols.length) {
|
|
@@ -955,7 +962,7 @@ class ViewHandler {
|
|
|
955
962
|
});
|
|
956
963
|
let existsCond = "";
|
|
957
964
|
if (existsKeys.length) {
|
|
958
|
-
existsCond = (await Promise.all(existsKeys.map(async (k) => await this.prepareExistCondition(k, localParams
|
|
965
|
+
existsCond = (await Promise.all(existsKeys.map(async (k) => await this.prepareExistCondition(k, localParams)))).join(" AND ");
|
|
959
966
|
}
|
|
960
967
|
/* Computed field queries */
|
|
961
968
|
const p = this.getValidatedRules(tableRules, localParams);
|
|
@@ -1010,8 +1017,8 @@ class ViewHandler {
|
|
|
1010
1017
|
const allowedComparators = [">", "<", "=", "<=", ">=", "<>", "!="];
|
|
1011
1018
|
if (complexFilterKey in data) {
|
|
1012
1019
|
const getFuncQuery = (funcData) => {
|
|
1013
|
-
const { funcName, args } = QueryBuilder_1.parseFunctionObject(funcData);
|
|
1014
|
-
const funcDef = QueryBuilder_1.parseFunction({ func: funcName, args, functions: QueryBuilder_1.FUNCTIONS, allowedFields: allowed_colnames });
|
|
1020
|
+
const { funcName, args } = (0, QueryBuilder_1.parseFunctionObject)(funcData);
|
|
1021
|
+
const funcDef = (0, QueryBuilder_1.parseFunction)({ func: funcName, args, functions: QueryBuilder_1.FUNCTIONS, allowedFields: allowed_colnames });
|
|
1015
1022
|
return funcDef.getQuery({ args, tableAlias, allColumns: this.columns, allowedFields: allowed_colnames });
|
|
1016
1023
|
};
|
|
1017
1024
|
const complexFilter = data[complexFilterKey];
|
|
@@ -1027,13 +1034,17 @@ class ViewHandler {
|
|
|
1027
1034
|
throw `Invalid $filter. comparator ${JSON.stringify(comparator)} is not valid. Expecting one of: ${allowedComparators}`;
|
|
1028
1035
|
if (!rightFilterOrValue)
|
|
1029
1036
|
throw "Invalid $filter. Expecting a value or function after the comparator";
|
|
1030
|
-
const rightVal = utils_1.isObject(rightFilterOrValue) ? getFuncQuery(rightFilterOrValue) : PubSubManager_1.asValue(rightFilterOrValue);
|
|
1037
|
+
const rightVal = (0, utils_1.isObject)(rightFilterOrValue) ? getFuncQuery(rightFilterOrValue) : (0, PubSubManager_1.asValue)(rightFilterOrValue);
|
|
1031
1038
|
if (leftVal === rightVal)
|
|
1032
1039
|
throw "Invalid $filter. Cannot compare two identical function signatures: " + JSON.stringify(leftFilter);
|
|
1033
1040
|
result += ` ${comparator} ${rightVal}`;
|
|
1034
1041
|
}
|
|
1035
1042
|
complexFilters.push(result);
|
|
1036
1043
|
}
|
|
1044
|
+
/* Parse join filters
|
|
1045
|
+
{ $joinFilter: { $ST_DWithin: [table.col, foreignTable.col, distance] }
|
|
1046
|
+
will make an exists filter
|
|
1047
|
+
*/
|
|
1037
1048
|
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
1049
|
// if(allowed_colnames){
|
|
1039
1050
|
// const aliasedColumns = (select || []).filter(s =>
|
|
@@ -1052,8 +1063,8 @@ class ViewHandler {
|
|
|
1052
1063
|
}
|
|
1053
1064
|
/* TODO: Allow filter funcs */
|
|
1054
1065
|
// const singleFuncs = FUNCTIONS.filter(f => f.singleColArg);
|
|
1055
|
-
const f = PubSubManager_1.filterObj(data, filterKeys);
|
|
1056
|
-
const q = Filtering_1.parseFilterItem({
|
|
1066
|
+
const f = (0, PubSubManager_1.filterObj)(data, filterKeys);
|
|
1067
|
+
const q = (0, Filtering_1.parseFilterItem)({
|
|
1057
1068
|
filter: f,
|
|
1058
1069
|
tableAlias,
|
|
1059
1070
|
pgp: exports.pgp,
|
|
@@ -1168,7 +1179,7 @@ class ViewHandler {
|
|
|
1168
1179
|
const orderType = asc ? " ASC " : " DESC ";
|
|
1169
1180
|
const index = selectedAliases.indexOf(key) + 1;
|
|
1170
1181
|
const nullOrder = nulls ? ` NULLS ${nulls === "first" ? " FIRST " : " LAST "}` : "";
|
|
1171
|
-
let colKey = (index > 0 && !nullEmpty) ? index : [tableAlias, key].filter(
|
|
1182
|
+
let colKey = (index > 0 && !nullEmpty) ? index : [tableAlias, key].filter(utils_1.isDefined).map(prostgles_types_1.asName).join(".");
|
|
1172
1183
|
if (nullEmpty) {
|
|
1173
1184
|
colKey = `nullif(trim(${colKey}::text), '')`;
|
|
1174
1185
|
}
|
|
@@ -1236,11 +1247,11 @@ class ViewHandler {
|
|
|
1236
1247
|
if (!column_names || !column_names.length)
|
|
1237
1248
|
throw "table column_names mising";
|
|
1238
1249
|
let _allowed_cols = column_names.slice(0);
|
|
1239
|
-
let _obj =
|
|
1250
|
+
let _obj = { ...obj };
|
|
1240
1251
|
if (allowed_cols) {
|
|
1241
1252
|
_allowed_cols = this.parseFieldFilter(allowed_cols, false);
|
|
1242
1253
|
}
|
|
1243
|
-
let final_filter =
|
|
1254
|
+
let final_filter = { ..._obj }, filter_keys = Object.keys(final_filter);
|
|
1244
1255
|
if (fixIssues && filter_keys.length) {
|
|
1245
1256
|
final_filter = {};
|
|
1246
1257
|
filter_keys
|
|
@@ -1254,7 +1265,7 @@ class ViewHandler {
|
|
|
1254
1265
|
validateObj(final_filter, _allowed_cols);
|
|
1255
1266
|
}
|
|
1256
1267
|
if (forcedData && Object.keys(forcedData).length) {
|
|
1257
|
-
final_filter =
|
|
1268
|
+
final_filter = { ...final_filter, ...forcedData };
|
|
1258
1269
|
}
|
|
1259
1270
|
validateObj(final_filter, column_names.slice(0));
|
|
1260
1271
|
return final_filter;
|
|
@@ -1271,7 +1282,7 @@ class ViewHandler {
|
|
|
1271
1282
|
if (!all_cols)
|
|
1272
1283
|
throw "all_cols missing";
|
|
1273
1284
|
const all_fields = all_cols; // || this.column_names.slice(0);
|
|
1274
|
-
let colNames =
|
|
1285
|
+
let colNames = [], initialParams = JSON.stringify(fieldParams);
|
|
1275
1286
|
if (fieldParams) {
|
|
1276
1287
|
/*
|
|
1277
1288
|
"field1, field2, field4" | "*"
|
|
@@ -1414,7 +1425,7 @@ class TableHandler extends ViewHandler {
|
|
|
1414
1425
|
console.error({ localParams, localFunc });
|
|
1415
1426
|
throw " Cannot have localFunc AND socket ";
|
|
1416
1427
|
}
|
|
1417
|
-
const { filterFields, forcedFilter } = utils_1.get(table_rules, "select") || {}, condition = await this.prepareWhere({ filter, forcedFilter, addKeywords: false, filterFields, tableAlias:
|
|
1428
|
+
const { filterFields, forcedFilter } = (0, utils_1.get)(table_rules, "select") || {}, condition = await this.prepareWhere({ filter, forcedFilter, addKeywords: false, filterFields, tableAlias: undefined, localParams, tableRule: table_rules }), throttle = (0, utils_1.get)(params, "throttle") || 0, selectParams = (0, PubSubManager_1.filterObj)(params || {}, [], ["throttle"]);
|
|
1418
1429
|
// const { subOne = false } = localParams || {};
|
|
1419
1430
|
const filterSize = JSON.stringify(filter || {}).length;
|
|
1420
1431
|
if (filterSize * 4 > 2704) {
|
|
@@ -1423,23 +1434,23 @@ class TableHandler extends ViewHandler {
|
|
|
1423
1434
|
if (!localFunc) {
|
|
1424
1435
|
if (!this.dboBuilder.prostgles.isSuperUser)
|
|
1425
1436
|
throw "Subscribe not possible. Must be superuser to add triggers 1856";
|
|
1426
|
-
return await this.find(filter,
|
|
1437
|
+
return await this.find(filter, { ...selectParams, limit: 0 }, undefined, table_rules, localParams)
|
|
1427
1438
|
.then(async (isValid) => {
|
|
1428
|
-
const { socket
|
|
1439
|
+
const { socket } = localParams ?? {};
|
|
1429
1440
|
const pubSubManager = await this.dboBuilder.getPubSubManager();
|
|
1430
1441
|
return pubSubManager.addSub({
|
|
1431
1442
|
table_info: this.tableOrViewInfo,
|
|
1432
1443
|
socket,
|
|
1433
1444
|
table_rules,
|
|
1434
1445
|
condition: condition,
|
|
1435
|
-
func:
|
|
1436
|
-
filter:
|
|
1437
|
-
params:
|
|
1438
|
-
|
|
1439
|
-
socket_id: socket.id,
|
|
1446
|
+
func: undefined,
|
|
1447
|
+
filter: { ...filter },
|
|
1448
|
+
params: { ...selectParams },
|
|
1449
|
+
socket_id: socket?.id,
|
|
1440
1450
|
table_name: this.name,
|
|
1441
1451
|
throttle,
|
|
1442
1452
|
last_throttled: 0,
|
|
1453
|
+
// subOne
|
|
1443
1454
|
}).then(channelName => ({ channelName }));
|
|
1444
1455
|
});
|
|
1445
1456
|
}
|
|
@@ -1447,17 +1458,17 @@ class TableHandler extends ViewHandler {
|
|
|
1447
1458
|
const pubSubManager = await this.dboBuilder.getPubSubManager();
|
|
1448
1459
|
pubSubManager.addSub({
|
|
1449
1460
|
table_info: this.tableOrViewInfo,
|
|
1450
|
-
socket:
|
|
1461
|
+
socket: undefined,
|
|
1451
1462
|
table_rules,
|
|
1452
1463
|
condition,
|
|
1453
1464
|
func: localFunc,
|
|
1454
|
-
filter:
|
|
1455
|
-
params:
|
|
1456
|
-
|
|
1457
|
-
socket_id: null,
|
|
1465
|
+
filter: { ...filter },
|
|
1466
|
+
params: { ...selectParams },
|
|
1467
|
+
socket_id: undefined,
|
|
1458
1468
|
table_name: this.name,
|
|
1459
1469
|
throttle,
|
|
1460
1470
|
last_throttled: 0,
|
|
1471
|
+
// subOne
|
|
1461
1472
|
}).then(channelName => ({ channelName }));
|
|
1462
1473
|
const unsubscribe = async () => {
|
|
1463
1474
|
const pubSubManager = await this.dboBuilder.getPubSubManager();
|
|
@@ -1475,11 +1486,11 @@ class TableHandler extends ViewHandler {
|
|
|
1475
1486
|
}
|
|
1476
1487
|
subscribeOne(filter, params = {}, localFunc, table_rules, localParams) {
|
|
1477
1488
|
let func = localParams ? undefined : (rows) => localFunc(rows[0]);
|
|
1478
|
-
return this.subscribe(filter,
|
|
1489
|
+
return this.subscribe(filter, { ...params, limit: 2 }, func, table_rules, localParams);
|
|
1479
1490
|
}
|
|
1480
|
-
async updateBatch(data, params, tableRules, localParams
|
|
1491
|
+
async updateBatch(data, params, tableRules, localParams) {
|
|
1481
1492
|
try {
|
|
1482
|
-
const queries = await Promise.all(data.map(async ([filter, data]) => await this.update(filter, data,
|
|
1493
|
+
const queries = await Promise.all(data.map(async ([filter, data]) => await this.update(filter, data, { ...(params || {}), returning: undefined }, tableRules, { ...(localParams || {}), returnQuery: true })));
|
|
1483
1494
|
const keys = (data && data.length) ? Object.keys(data[0]) : [];
|
|
1484
1495
|
return this.db.tx(t => {
|
|
1485
1496
|
const _queries = queries.map(q => t.none(q));
|
|
@@ -1492,10 +1503,9 @@ class TableHandler extends ViewHandler {
|
|
|
1492
1503
|
throw { err: parseError(e), msg: `Issue with dbo.${this.name}.update()` };
|
|
1493
1504
|
}
|
|
1494
1505
|
}
|
|
1495
|
-
async update(filter, newData, params, tableRules, localParams
|
|
1496
|
-
var _a;
|
|
1506
|
+
async update(filter, newData, params, tableRules, localParams) {
|
|
1497
1507
|
try {
|
|
1498
|
-
const { testRule = false, returnQuery = false } = localParams
|
|
1508
|
+
const { testRule = false, returnQuery = false } = localParams ?? {};
|
|
1499
1509
|
if (!testRule) {
|
|
1500
1510
|
if (!newData || !Object.keys(newData).length)
|
|
1501
1511
|
throw "no update data provided\nEXPECTING db.table.update(filter, updateData, options)";
|
|
@@ -1507,7 +1517,7 @@ class TableHandler extends ViewHandler {
|
|
|
1507
1517
|
throw "update rules missing for " + this.name;
|
|
1508
1518
|
({ forcedFilter, forcedData, returningFields, fields, filterFields, validate } = tableRules.update);
|
|
1509
1519
|
if (!returningFields)
|
|
1510
|
-
returningFields = utils_1.get(tableRules, "select.fields");
|
|
1520
|
+
returningFields = (0, utils_1.get)(tableRules, "select.fields");
|
|
1511
1521
|
if (!fields)
|
|
1512
1522
|
throw ` Invalid update rule for ${this.name}. fields missing `;
|
|
1513
1523
|
/* Safely test publish rules */
|
|
@@ -1515,7 +1525,7 @@ class TableHandler extends ViewHandler {
|
|
|
1515
1525
|
await this.validateViewRules(fields, filterFields, returningFields, forcedFilter, "update");
|
|
1516
1526
|
if (forcedData) {
|
|
1517
1527
|
try {
|
|
1518
|
-
const { data, allowedCols } = this.validateNewData({ row: forcedData, forcedData:
|
|
1528
|
+
const { data, allowedCols } = this.validateNewData({ row: forcedData, forcedData: undefined, allowedFields: "*", tableRules, fixIssues: false });
|
|
1519
1529
|
const updateQ = await this.colSet.getUpdateQuery(data, allowedCols, validate); //pgp.helpers.update(data, columnSet)
|
|
1520
1530
|
let query = updateQ + " WHERE FALSE ";
|
|
1521
1531
|
await this.db.any("EXPLAIN " + query);
|
|
@@ -1549,27 +1559,27 @@ class TableHandler extends ViewHandler {
|
|
|
1549
1559
|
const unrecProps = Object.keys(d).filter(k => !["from", "to", "text", "md5"].includes(k));
|
|
1550
1560
|
if (unrecProps.length)
|
|
1551
1561
|
throw "Unrecognised params in textPatch field: " + unrecProps.join(", ");
|
|
1552
|
-
patchedTextData.push(
|
|
1562
|
+
patchedTextData.push({ ...d, fieldName: c.name });
|
|
1553
1563
|
}
|
|
1554
1564
|
});
|
|
1555
1565
|
if (patchedTextData && patchedTextData.length) {
|
|
1556
1566
|
if (tableRules && !tableRules.select)
|
|
1557
1567
|
throw "Select needs to be permitted to patch data";
|
|
1558
|
-
const rows = await this.find(filter, { select: patchedTextData.reduce((a, v) => (
|
|
1568
|
+
const rows = await this.find(filter, { select: patchedTextData.reduce((a, v) => ({ ...a, [v.fieldName]: 1 }), {}) }, undefined, tableRules);
|
|
1559
1569
|
if (rows.length !== 1) {
|
|
1560
1570
|
throw "Cannot patch data within a filter that affects more/less than 1 row";
|
|
1561
1571
|
}
|
|
1562
1572
|
patchedTextData.map(p => {
|
|
1563
|
-
data[p.fieldName] = prostgles_types_1.unpatchText(rows[0][p.fieldName], p);
|
|
1573
|
+
data[p.fieldName] = (0, prostgles_types_1.unpatchText)(rows[0][p.fieldName], p);
|
|
1564
1574
|
});
|
|
1565
1575
|
// https://w3resource.com/PostgreSQL/overlay-function.p hp
|
|
1566
1576
|
// overlay(coalesce(status, '') placing 'hom' from 2 for 0)
|
|
1567
1577
|
}
|
|
1568
|
-
let nData =
|
|
1578
|
+
let nData = { ...data };
|
|
1569
1579
|
// if(tableRules && tableRules.update && tableRules?.update?.validate){
|
|
1570
1580
|
// nData = await tableRules.update.validate(nData);
|
|
1571
1581
|
// }
|
|
1572
|
-
let query = await this.colSet.getUpdateQuery(nData, allowedCols,
|
|
1582
|
+
let query = await this.colSet.getUpdateQuery(nData, allowedCols, tableRules?.update?.validate); //pgp.helpers.update(nData, columnSet) + " ";
|
|
1573
1583
|
query += (await this.prepareWhere({
|
|
1574
1584
|
filter,
|
|
1575
1585
|
forcedFilter,
|
|
@@ -1587,7 +1597,7 @@ class TableHandler extends ViewHandler {
|
|
|
1587
1597
|
if (returnQuery)
|
|
1588
1598
|
return query;
|
|
1589
1599
|
if (this.t) {
|
|
1590
|
-
return this.t[qType](query).catch(err => makeErr(err, localParams, this, _fields));
|
|
1600
|
+
return this.t[qType](query).catch((err) => makeErr(err, localParams, this, _fields));
|
|
1591
1601
|
}
|
|
1592
1602
|
return this.db.tx(t => t[qType](query)).catch(err => makeErr(err, localParams, this, _fields));
|
|
1593
1603
|
}
|
|
@@ -1599,17 +1609,16 @@ class TableHandler extends ViewHandler {
|
|
|
1599
1609
|
}
|
|
1600
1610
|
;
|
|
1601
1611
|
validateNewData({ row, forcedData, allowedFields, tableRules, fixIssues = false }) {
|
|
1602
|
-
const synced_field = utils_1.get(tableRules
|
|
1612
|
+
const synced_field = (0, utils_1.get)(tableRules ?? {}, "sync.synced_field");
|
|
1603
1613
|
/* Update synced_field if sync is on and missing */
|
|
1604
1614
|
if (synced_field && !row[synced_field]) {
|
|
1605
1615
|
row[synced_field] = Date.now();
|
|
1606
1616
|
}
|
|
1607
1617
|
let data = this.prepareFieldValues(row, forcedData, allowedFields, fixIssues);
|
|
1608
|
-
const dataKeys =
|
|
1618
|
+
const dataKeys = getKeys(data);
|
|
1609
1619
|
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);
|
|
1620
|
+
this.dboBuilder.prostgles?.tableConfigurator?.checkColVal({ table: this.name, col, value: data[col] });
|
|
1621
|
+
const colConfig = this.dboBuilder.prostgles?.tableConfigurator?.getColumnConfig(this.name, col);
|
|
1613
1622
|
if (colConfig && "isText" in colConfig && data[col]) {
|
|
1614
1623
|
if (colConfig.lowerCased) {
|
|
1615
1624
|
data[col] = data[col].toString().toLowerCase();
|
|
@@ -1621,12 +1630,11 @@ class TableHandler extends ViewHandler {
|
|
|
1621
1630
|
});
|
|
1622
1631
|
return { data, allowedCols: this.columns.filter(c => dataKeys.includes(c.name)).map(c => c.name) };
|
|
1623
1632
|
}
|
|
1624
|
-
async insertDataParse(data, param2, param3_unused, tableRules, _localParams
|
|
1625
|
-
var _a, _b;
|
|
1633
|
+
async insertDataParse(data, param2, param3_unused, tableRules, _localParams) {
|
|
1626
1634
|
const localParams = _localParams || {};
|
|
1627
|
-
let dbTX =
|
|
1635
|
+
let dbTX = localParams?.dbTX || this.dbTX;
|
|
1628
1636
|
const isMultiInsert = Array.isArray(data);
|
|
1629
|
-
const getExtraKeys = d => Object.keys(d).filter(k => !this.columns.find(c => c.name === k));
|
|
1637
|
+
const getExtraKeys = (d) => Object.keys(d).filter(k => !this.columns.find(c => c.name === k));
|
|
1630
1638
|
/* Nested insert is not allowed for the file table */
|
|
1631
1639
|
const isNestedInsert = this.is_media ? false : (Array.isArray(data) ? data : [data]).some(d => getExtraKeys(d).length);
|
|
1632
1640
|
/**
|
|
@@ -1634,13 +1642,12 @@ class TableHandler extends ViewHandler {
|
|
|
1634
1642
|
*/
|
|
1635
1643
|
if (isNestedInsert && !dbTX) {
|
|
1636
1644
|
return {
|
|
1637
|
-
insertResult: await this.dboBuilder.getTX((dbTX) => dbTX[this.name].insert(data, param2, param3_unused, tableRules,
|
|
1645
|
+
insertResult: await this.dboBuilder.getTX((dbTX) => dbTX[this.name].insert(data, param2, param3_unused, tableRules, { dbTX, ...localParams }))
|
|
1638
1646
|
};
|
|
1639
1647
|
}
|
|
1640
1648
|
// if(!dbTX && this.t) dbTX = this.d;
|
|
1641
|
-
const preValidate =
|
|
1649
|
+
const preValidate = tableRules?.insert?.preValidate, validate = tableRules?.insert?.validate;
|
|
1642
1650
|
let _data = await Promise.all((Array.isArray(data) ? data : [data]).map(async (row) => {
|
|
1643
|
-
var _a, _b;
|
|
1644
1651
|
if (preValidate) {
|
|
1645
1652
|
row = await preValidate(row);
|
|
1646
1653
|
}
|
|
@@ -1648,7 +1655,7 @@ class TableHandler extends ViewHandler {
|
|
|
1648
1655
|
const extraKeys = getExtraKeys(row);
|
|
1649
1656
|
/* Upload file then continue insert */
|
|
1650
1657
|
if (this.is_media) {
|
|
1651
|
-
if (!
|
|
1658
|
+
if (!this.dboBuilder.prostgles?.fileManager)
|
|
1652
1659
|
throw "fileManager not set up";
|
|
1653
1660
|
const { data, name } = row;
|
|
1654
1661
|
if (dataKeys.length !== 2)
|
|
@@ -1675,35 +1682,43 @@ class TableHandler extends ViewHandler {
|
|
|
1675
1682
|
const _media = await this.dboBuilder.prostgles.fileManager.uploadAsMedia({
|
|
1676
1683
|
item: {
|
|
1677
1684
|
data,
|
|
1678
|
-
name: media.name,
|
|
1685
|
+
name: media.name ?? "????",
|
|
1679
1686
|
content_type: media.content_type
|
|
1680
1687
|
},
|
|
1688
|
+
// imageCompression: {
|
|
1689
|
+
// inside: {
|
|
1690
|
+
// width: 1100,
|
|
1691
|
+
// height: 630
|
|
1692
|
+
// }
|
|
1693
|
+
// }
|
|
1681
1694
|
});
|
|
1682
|
-
return
|
|
1695
|
+
return {
|
|
1696
|
+
...media,
|
|
1697
|
+
..._media,
|
|
1698
|
+
};
|
|
1683
1699
|
/* Potentially a nested join */
|
|
1684
1700
|
}
|
|
1685
1701
|
else if (extraKeys.length) {
|
|
1686
1702
|
/* Ensure we're using the same transaction */
|
|
1687
1703
|
const _this = this.t ? this : dbTX[this.name];
|
|
1688
|
-
let rootData = PubSubManager_1.filterObj(data,
|
|
1704
|
+
let rootData = (0, PubSubManager_1.filterObj)(data, undefined, extraKeys);
|
|
1689
1705
|
let insertedChildren;
|
|
1690
1706
|
let targetTableRules;
|
|
1691
|
-
const fullRootResult = await _this.insert(rootData, { returning: "*" },
|
|
1707
|
+
const fullRootResult = await _this.insert(rootData, { returning: "*" }, undefined, tableRules, localParams);
|
|
1692
1708
|
let returnData;
|
|
1693
|
-
const returning = param2
|
|
1709
|
+
const returning = param2?.returning;
|
|
1694
1710
|
if (returning) {
|
|
1695
1711
|
returnData = {};
|
|
1696
|
-
const returningItems = await this.prepareReturning(returning, this.parseFieldFilter(
|
|
1712
|
+
const returningItems = await this.prepareReturning(returning, this.parseFieldFilter(tableRules?.insert?.returningFields));
|
|
1697
1713
|
returningItems.filter(s => s.selected).map(rs => {
|
|
1698
1714
|
returnData[rs.alias] = fullRootResult[rs.alias];
|
|
1699
1715
|
});
|
|
1700
1716
|
}
|
|
1701
1717
|
await Promise.all(extraKeys.map(async (targetTable) => {
|
|
1702
|
-
var _a;
|
|
1703
1718
|
const childDataItems = Array.isArray(row[targetTable]) ? row[targetTable] : [row[targetTable]];
|
|
1704
1719
|
/* Must be allowed to insert into media table */
|
|
1705
1720
|
const canInsert = async (tbl) => {
|
|
1706
|
-
const childRules = await this.dboBuilder.publishParser
|
|
1721
|
+
const childRules = await this.dboBuilder.publishParser?.getValidatedRequestRuleWusr({ tableName: tbl, command: "insert", localParams });
|
|
1707
1722
|
if (!childRules || !childRules.insert)
|
|
1708
1723
|
throw "Dissallowed nested insert into table " + childRules;
|
|
1709
1724
|
return childRules;
|
|
@@ -1715,7 +1730,7 @@ class TableHandler extends ViewHandler {
|
|
|
1715
1730
|
const thisInfo = await this.getInfo();
|
|
1716
1731
|
const childInsert = async (cdata, tableName) => {
|
|
1717
1732
|
// console.log("childInsert", {data, tableName})
|
|
1718
|
-
if (!cdata || !dbTX[tableName] || !("insert" in dbTX[tableName]))
|
|
1733
|
+
if (!cdata || !dbTX?.[tableName] || !("insert" in dbTX[tableName]))
|
|
1719
1734
|
throw "childInsertErr: Child table handler missing for: " + tableName;
|
|
1720
1735
|
const tableRules = await canInsert(tableName);
|
|
1721
1736
|
if (thisInfo.has_media === "one" && thisInfo.media_table_name === tableName && Array.isArray(cdata) && cdata.length > 1) {
|
|
@@ -1723,7 +1738,7 @@ class TableHandler extends ViewHandler {
|
|
|
1723
1738
|
}
|
|
1724
1739
|
return Promise.all((Array.isArray(cdata) ? cdata : [cdata])
|
|
1725
1740
|
.map(m => dbTX[tableName]
|
|
1726
|
-
.insert(m, { returning: "*" },
|
|
1741
|
+
.insert(m, { returning: "*" }, undefined, tableRules, localParams)
|
|
1727
1742
|
.catch(e => {
|
|
1728
1743
|
console.trace({ childInsertErr: e });
|
|
1729
1744
|
return Promise.reject({ childInsertErr: e });
|
|
@@ -1735,7 +1750,7 @@ class TableHandler extends ViewHandler {
|
|
|
1735
1750
|
const cols2 = this.dboBuilder.dbo[tbl2].columns || [];
|
|
1736
1751
|
if (!this.dboBuilder.dbo[tbl2])
|
|
1737
1752
|
throw "Invalid/disallowed table: " + tbl2;
|
|
1738
|
-
const colsRefT1 = cols2
|
|
1753
|
+
const colsRefT1 = cols2?.filter(c => c.references?.cols.length === 1 && c.references?.ftable === tbl1);
|
|
1739
1754
|
if (!path.length) {
|
|
1740
1755
|
throw "Nested inserts join path not found for " + [this.name, targetTable];
|
|
1741
1756
|
}
|
|
@@ -1745,8 +1760,8 @@ class TableHandler extends ViewHandler {
|
|
|
1745
1760
|
if (!colsRefT1.length)
|
|
1746
1761
|
throw `Target table ${tbl2} does not reference any columns from the root table ${this.name}. Cannot do nested insert`;
|
|
1747
1762
|
// console.log(childDataItems, JSON.stringify(colsRefT1, null, 2))
|
|
1748
|
-
insertedChildren = await childInsert(childDataItems.map(d => {
|
|
1749
|
-
let result =
|
|
1763
|
+
insertedChildren = await childInsert(childDataItems.map((d) => {
|
|
1764
|
+
let result = { ...d };
|
|
1750
1765
|
colsRefT1.map(col => {
|
|
1751
1766
|
result[col.references.cols[0]] = fullRootResult[col.references.fcols[0]];
|
|
1752
1767
|
});
|
|
@@ -1757,10 +1772,10 @@ class TableHandler extends ViewHandler {
|
|
|
1757
1772
|
else if (path.length === 3) {
|
|
1758
1773
|
if (targetTable !== tbl3)
|
|
1759
1774
|
throw "Did not expect this";
|
|
1760
|
-
const colsRefT3 = cols2
|
|
1775
|
+
const colsRefT3 = cols2?.filter(c => c.references?.cols.length === 1 && c.references?.ftable === tbl3);
|
|
1761
1776
|
if (!colsRefT1.length || !colsRefT3.length)
|
|
1762
1777
|
throw "Incorrectly referenced or missing columns for nested insert";
|
|
1763
|
-
if (targetTable !== this.dboBuilder.prostgles.fileManager
|
|
1778
|
+
if (targetTable !== this.dboBuilder.prostgles.fileManager?.tableName) {
|
|
1764
1779
|
throw "Only media allowed to have nested inserts more than 2 tables apart";
|
|
1765
1780
|
}
|
|
1766
1781
|
/* We expect tbl2 to have only 2 columns (media_id and foreign_id) */
|
|
@@ -1786,11 +1801,11 @@ class TableHandler extends ViewHandler {
|
|
|
1786
1801
|
throw "Unexpected path for Nested inserts";
|
|
1787
1802
|
}
|
|
1788
1803
|
/* Return also the nested inserted data */
|
|
1789
|
-
if (targetTableRules &&
|
|
1804
|
+
if (targetTableRules && insertedChildren?.length && returning) {
|
|
1790
1805
|
const targetTableHandler = dbTX[targetTable];
|
|
1791
|
-
const targetReturning = await targetTableHandler.prepareReturning("*", targetTableHandler.parseFieldFilter(
|
|
1806
|
+
const targetReturning = await targetTableHandler.prepareReturning("*", targetTableHandler.parseFieldFilter(targetTableRules?.insert?.returningFields));
|
|
1792
1807
|
let clientTargetInserts = insertedChildren.map(d => {
|
|
1793
|
-
let _d =
|
|
1808
|
+
let _d = { ...d };
|
|
1794
1809
|
let res = {};
|
|
1795
1810
|
targetReturning.map(r => {
|
|
1796
1811
|
res[r.alias] = _d[r.alias];
|
|
@@ -1813,8 +1828,7 @@ class TableHandler extends ViewHandler {
|
|
|
1813
1828
|
{ data: result };
|
|
1814
1829
|
return res;
|
|
1815
1830
|
}
|
|
1816
|
-
async insert(rowOrRows, param2, param3_unused, tableRules, _localParams
|
|
1817
|
-
var _a, _b, _e;
|
|
1831
|
+
async insert(rowOrRows, param2, param3_unused, tableRules, _localParams) {
|
|
1818
1832
|
const localParams = _localParams || {};
|
|
1819
1833
|
const { dbTX } = localParams;
|
|
1820
1834
|
try {
|
|
@@ -1829,13 +1843,13 @@ class TableHandler extends ViewHandler {
|
|
|
1829
1843
|
fields = tableRules.insert.fields;
|
|
1830
1844
|
/* If no returning fields specified then take select fields as returning */
|
|
1831
1845
|
if (!returningFields)
|
|
1832
|
-
returningFields = utils_1.get(tableRules, "select.fields") || utils_1.get(tableRules, "insert.fields");
|
|
1846
|
+
returningFields = (0, utils_1.get)(tableRules, "select.fields") || (0, utils_1.get)(tableRules, "insert.fields");
|
|
1833
1847
|
if (!fields)
|
|
1834
1848
|
throw ` invalid insert rule for ${this.name} -> fields missing `;
|
|
1835
1849
|
/* Safely test publish rules */
|
|
1836
1850
|
if (testRule) {
|
|
1837
1851
|
// 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,
|
|
1852
|
+
await this.validateViewRules(fields, undefined, returningFields, undefined, "insert");
|
|
1839
1853
|
if (forcedData) {
|
|
1840
1854
|
const keys = Object.keys(forcedData);
|
|
1841
1855
|
if (keys.length) {
|
|
@@ -1865,19 +1879,18 @@ class TableHandler extends ViewHandler {
|
|
|
1865
1879
|
rowOrRows = {}; //throw "Provide data in param1";
|
|
1866
1880
|
let returningSelect = this.makeReturnQuery(await this.prepareReturning(returning, this.parseFieldFilter(returningFields)));
|
|
1867
1881
|
const makeQuery = async (_row, isOne = false) => {
|
|
1868
|
-
|
|
1869
|
-
let row = Object.assign({}, _row);
|
|
1882
|
+
let row = { ..._row };
|
|
1870
1883
|
if (!isPojoObject(row)) {
|
|
1871
1884
|
console.trace(row);
|
|
1872
1885
|
throw "\ninvalid insert data provided -> " + JSON.stringify(row);
|
|
1873
1886
|
}
|
|
1874
1887
|
const { data, allowedCols } = this.validateNewData({ row, forcedData, allowedFields: fields, tableRules, fixIssues });
|
|
1875
|
-
let _data =
|
|
1888
|
+
let _data = { ...data };
|
|
1876
1889
|
let insertQ = "";
|
|
1877
1890
|
if (!Object.keys(_data).length)
|
|
1878
|
-
insertQ = `INSERT INTO ${prostgles_types_1.asName(this.name)} DEFAULT VALUES `;
|
|
1891
|
+
insertQ = `INSERT INTO ${(0, prostgles_types_1.asName)(this.name)} DEFAULT VALUES `;
|
|
1879
1892
|
else
|
|
1880
|
-
insertQ = await this.colSet.getInsertQuery(_data, allowedCols,
|
|
1893
|
+
insertQ = await this.colSet.getInsertQuery(_data, allowedCols, tableRules?.insert?.validate); // pgp.helpers.insert(_data, columnSet);
|
|
1881
1894
|
return insertQ + conflict_query + returningSelect;
|
|
1882
1895
|
};
|
|
1883
1896
|
let query = "";
|
|
@@ -1910,12 +1923,12 @@ class TableHandler extends ViewHandler {
|
|
|
1910
1923
|
return query;
|
|
1911
1924
|
let result;
|
|
1912
1925
|
if (this.dboBuilder.prostgles.opts.DEBUG_MODE) {
|
|
1913
|
-
console.log(
|
|
1926
|
+
console.log(this.t?.ctx?.start, "insert in " + this.name, data);
|
|
1914
1927
|
}
|
|
1915
|
-
const tx =
|
|
1928
|
+
const tx = dbTX?.[this.name]?.t || this.t;
|
|
1916
1929
|
const allowedFieldKeys = this.parseFieldFilter(fields);
|
|
1917
1930
|
if (tx) {
|
|
1918
|
-
result = tx[queryType](query).catch(err => makeErr(err, localParams, this, allowedFieldKeys));
|
|
1931
|
+
result = tx[queryType](query).catch((err) => makeErr(err, localParams, this, allowedFieldKeys));
|
|
1919
1932
|
}
|
|
1920
1933
|
else {
|
|
1921
1934
|
result = this.db.tx(t => t[queryType](query)).catch(err => makeErr(err, localParams, this, allowedFieldKeys));
|
|
@@ -1933,11 +1946,11 @@ class TableHandler extends ViewHandler {
|
|
|
1933
1946
|
}
|
|
1934
1947
|
;
|
|
1935
1948
|
makeReturnQuery(items) {
|
|
1936
|
-
if (items
|
|
1937
|
-
return " RETURNING " + items.map(s => s.getQuery() + " AS " + prostgles_types_1.asName(s.alias)).join(", ");
|
|
1949
|
+
if (items?.length)
|
|
1950
|
+
return " RETURNING " + items.map(s => s.getQuery() + " AS " + (0, prostgles_types_1.asName)(s.alias)).join(", ");
|
|
1938
1951
|
return "";
|
|
1939
1952
|
}
|
|
1940
|
-
async delete(filter, params, param3_unused, table_rules, localParams
|
|
1953
|
+
async delete(filter, params, param3_unused, table_rules, localParams) {
|
|
1941
1954
|
try {
|
|
1942
1955
|
const { returning } = params || {};
|
|
1943
1956
|
filter = filter || {};
|
|
@@ -1952,14 +1965,14 @@ class TableHandler extends ViewHandler {
|
|
|
1952
1965
|
filterFields = table_rules.delete.filterFields;
|
|
1953
1966
|
returningFields = table_rules.delete.returningFields;
|
|
1954
1967
|
if (!returningFields)
|
|
1955
|
-
returningFields = utils_1.get(table_rules, "select.fields");
|
|
1968
|
+
returningFields = (0, utils_1.get)(table_rules, "select.fields");
|
|
1956
1969
|
if (!returningFields)
|
|
1957
|
-
returningFields = utils_1.get(table_rules, "delete.filterFields");
|
|
1970
|
+
returningFields = (0, utils_1.get)(table_rules, "delete.filterFields");
|
|
1958
1971
|
if (!filterFields)
|
|
1959
1972
|
throw ` Invalid delete rule for ${this.name}. filterFields missing `;
|
|
1960
1973
|
/* Safely test publish rules */
|
|
1961
1974
|
if (testRule) {
|
|
1962
|
-
await this.validateViewRules(
|
|
1975
|
+
await this.validateViewRules(undefined, filterFields, returningFields, forcedFilter, "delete");
|
|
1963
1976
|
return true;
|
|
1964
1977
|
}
|
|
1965
1978
|
}
|
|
@@ -1987,7 +2000,7 @@ class TableHandler extends ViewHandler {
|
|
|
1987
2000
|
}
|
|
1988
2001
|
if (returnQuery)
|
|
1989
2002
|
return _query;
|
|
1990
|
-
return (this.t || this.db)[queryType](_query).catch(err => makeErr(err, localParams));
|
|
2003
|
+
return (this.t || this.db)[queryType](_query).catch((err) => makeErr(err, localParams));
|
|
1991
2004
|
}
|
|
1992
2005
|
catch (e) {
|
|
1993
2006
|
// console.trace(e)
|
|
@@ -1997,10 +2010,10 @@ class TableHandler extends ViewHandler {
|
|
|
1997
2010
|
}
|
|
1998
2011
|
}
|
|
1999
2012
|
;
|
|
2000
|
-
remove(filter, params, param3_unused, tableRules, localParams
|
|
2013
|
+
remove(filter, params, param3_unused, tableRules, localParams) {
|
|
2001
2014
|
return this.delete(filter, params, param3_unused, tableRules, localParams);
|
|
2002
2015
|
}
|
|
2003
|
-
async upsert(filter, newData, params, table_rules, localParams
|
|
2016
|
+
async upsert(filter, newData, params, table_rules, localParams) {
|
|
2004
2017
|
try {
|
|
2005
2018
|
/* Do it within a transaction to ensure consisency */
|
|
2006
2019
|
if (!this.t) {
|
|
@@ -2010,13 +2023,13 @@ class TableHandler extends ViewHandler {
|
|
|
2010
2023
|
return _upsert(this);
|
|
2011
2024
|
}
|
|
2012
2025
|
async function _upsert(tblH) {
|
|
2013
|
-
return tblH.find(filter, { select: "", limit: 1 },
|
|
2026
|
+
return tblH.find(filter, { select: "", limit: 1 }, undefined, table_rules, localParams)
|
|
2014
2027
|
.then(exists => {
|
|
2015
2028
|
if (exists && exists.length) {
|
|
2016
2029
|
return tblH.update(filter, newData, params, table_rules, localParams);
|
|
2017
2030
|
}
|
|
2018
2031
|
else {
|
|
2019
|
-
return tblH.insert(
|
|
2032
|
+
return tblH.insert({ ...newData, ...filter }, params, undefined, table_rules, localParams);
|
|
2020
2033
|
}
|
|
2021
2034
|
});
|
|
2022
2035
|
}
|
|
@@ -2052,11 +2065,11 @@ class TableHandler extends ViewHandler {
|
|
|
2052
2065
|
throw err;
|
|
2053
2066
|
}
|
|
2054
2067
|
id_fields = this.parseFieldFilter(id_fields, false);
|
|
2055
|
-
let allowedSelect = this.parseFieldFilter(utils_1.get(table_rules, "select.fields"), false);
|
|
2068
|
+
let allowedSelect = this.parseFieldFilter((0, utils_1.get)(table_rules, "select.fields"), false);
|
|
2056
2069
|
if (syncFields.find(f => !allowedSelect.includes(f))) {
|
|
2057
2070
|
throw `INTERNAL ERROR: sync field missing from publish.${this.name}.select.fields`;
|
|
2058
2071
|
}
|
|
2059
|
-
let select = this.getAllowedSelectFields(utils_1.get(params || {}, "select") || "*", allowedSelect, false);
|
|
2072
|
+
let select = this.getAllowedSelectFields((0, utils_1.get)(params || {}, "select") || "*", allowedSelect, false);
|
|
2060
2073
|
if (!select.length)
|
|
2061
2074
|
throw "Empty select not allowed";
|
|
2062
2075
|
/* Add sync fields if missing */
|
|
@@ -2065,19 +2078,20 @@ class TableHandler extends ViewHandler {
|
|
|
2065
2078
|
select.push(sf);
|
|
2066
2079
|
});
|
|
2067
2080
|
/* Step 1: parse command and params */
|
|
2068
|
-
return this.find(filter, { select, limit: 0 },
|
|
2081
|
+
return this.find(filter, { select, limit: 0 }, undefined, table_rules, localParams)
|
|
2069
2082
|
.then(async (isValid) => {
|
|
2070
|
-
const { filterFields, forcedFilter } = utils_1.get(table_rules, "select") || {};
|
|
2083
|
+
const { filterFields, forcedFilter } = (0, utils_1.get)(table_rules, "select") || {};
|
|
2071
2084
|
const condition = await this.prepareWhere({ filter, forcedFilter, filterFields, addKeywords: false, localParams, tableRule: table_rules });
|
|
2072
2085
|
// let final_filter = getFindFilter(filter, table_rules);
|
|
2073
2086
|
const pubSubManager = await this.dboBuilder.getPubSubManager();
|
|
2074
2087
|
return pubSubManager.addSync({
|
|
2075
2088
|
table_info: this.tableOrViewInfo,
|
|
2076
2089
|
condition,
|
|
2077
|
-
id_fields, synced_field,
|
|
2090
|
+
id_fields, synced_field,
|
|
2091
|
+
allow_delete,
|
|
2078
2092
|
socket,
|
|
2079
2093
|
table_rules,
|
|
2080
|
-
filter:
|
|
2094
|
+
filter: { ...filter },
|
|
2081
2095
|
params: { select }
|
|
2082
2096
|
}).then(channelName => ({ channelName, id_fields, synced_field }));
|
|
2083
2097
|
});
|
|
@@ -2115,7 +2129,7 @@ class TableHandler extends ViewHandler {
|
|
|
2115
2129
|
}
|
|
2116
2130
|
}
|
|
2117
2131
|
exports.TableHandler = TableHandler;
|
|
2118
|
-
const
|
|
2132
|
+
const Prostgles_1 = require("./Prostgles");
|
|
2119
2133
|
class DboBuilder {
|
|
2120
2134
|
constructor(prostgles) {
|
|
2121
2135
|
this.schema = "public";
|
|
@@ -2144,8 +2158,11 @@ class DboBuilder {
|
|
|
2144
2158
|
console.warn(`subscribe and sync cannot be used because db user is not a superuser `);
|
|
2145
2159
|
}
|
|
2146
2160
|
}
|
|
2161
|
+
if (!this._pubSubManager)
|
|
2162
|
+
throw "Could not create this._pubSubManager";
|
|
2147
2163
|
return this._pubSubManager;
|
|
2148
2164
|
};
|
|
2165
|
+
this.joinPaths = [];
|
|
2149
2166
|
this.init = async () => {
|
|
2150
2167
|
/* If watchSchema then PubSubManager must be created */
|
|
2151
2168
|
await this.build();
|
|
@@ -2157,7 +2174,7 @@ class DboBuilder {
|
|
|
2157
2174
|
this.getTX = (cb) => {
|
|
2158
2175
|
return this.db.tx((t) => {
|
|
2159
2176
|
let dbTX = {};
|
|
2160
|
-
this.tablesOrViews
|
|
2177
|
+
this.tablesOrViews?.map(tov => {
|
|
2161
2178
|
if (tov.is_view) {
|
|
2162
2179
|
dbTX[tov.name] = new ViewHandler(this.db, tov, this, t, dbTX, this.joinPaths);
|
|
2163
2180
|
}
|
|
@@ -2178,14 +2195,15 @@ class DboBuilder {
|
|
|
2178
2195
|
});
|
|
2179
2196
|
};
|
|
2180
2197
|
this.prostgles = prostgles;
|
|
2198
|
+
if (!this.prostgles.db)
|
|
2199
|
+
throw "db missing";
|
|
2181
2200
|
this.db = this.prostgles.db;
|
|
2182
2201
|
this.schema = this.prostgles.opts.schema || "public";
|
|
2183
2202
|
this.dbo = {};
|
|
2184
2203
|
// this.joins = this.prostgles.joins;
|
|
2185
2204
|
}
|
|
2186
2205
|
destroy() {
|
|
2187
|
-
|
|
2188
|
-
(_a = this._pubSubManager) === null || _a === void 0 ? void 0 : _a.destroy();
|
|
2206
|
+
this._pubSubManager?.destroy();
|
|
2189
2207
|
}
|
|
2190
2208
|
getJoins() {
|
|
2191
2209
|
return this.joins;
|
|
@@ -2218,7 +2236,7 @@ class DboBuilder {
|
|
|
2218
2236
|
}
|
|
2219
2237
|
const tovNames = this.tablesOrViews.map(t => t.name);
|
|
2220
2238
|
// 2 find incorrect tables
|
|
2221
|
-
const missing =
|
|
2239
|
+
const missing = joins.flatMap(j => j.tables).find(t => !tovNames.includes(t));
|
|
2222
2240
|
if (missing) {
|
|
2223
2241
|
throw "Table not found: " + missing;
|
|
2224
2242
|
}
|
|
@@ -2237,11 +2255,11 @@ class DboBuilder {
|
|
|
2237
2255
|
});
|
|
2238
2256
|
});
|
|
2239
2257
|
// 4 find incorrect/missing join types
|
|
2240
|
-
const expected_types = " \n\n-> Expecting: " +
|
|
2258
|
+
const expected_types = " \n\n-> Expecting: " + Prostgles_1.JOIN_TYPES.map(t => JSON.stringify(t)).join(` | `);
|
|
2241
2259
|
const mt = joins.find(j => !j.type);
|
|
2242
2260
|
if (mt)
|
|
2243
2261
|
throw "Join type missing for: " + JSON.stringify(mt, null, 2) + expected_types;
|
|
2244
|
-
const it = joins.find(j => !
|
|
2262
|
+
const it = joins.find(j => !Prostgles_1.JOIN_TYPES.includes(j.type));
|
|
2245
2263
|
if (it)
|
|
2246
2264
|
throw "Incorrect join type for: " + JSON.stringify(it, null, 2) + expected_types;
|
|
2247
2265
|
}
|
|
@@ -2257,11 +2275,11 @@ class DboBuilder {
|
|
|
2257
2275
|
this.joinGraph[t2] = this.joinGraph[t2] || {};
|
|
2258
2276
|
this.joinGraph[t2][t1] = 1;
|
|
2259
2277
|
});
|
|
2260
|
-
const tables =
|
|
2278
|
+
const tables = this.joins.flatMap(t => t.tables);
|
|
2261
2279
|
this.joinPaths = [];
|
|
2262
2280
|
tables.map(t1 => {
|
|
2263
2281
|
tables.map(t2 => {
|
|
2264
|
-
const spath = shortestPath_1.findShortestPath(this.joinGraph, t1, t2);
|
|
2282
|
+
const spath = (0, shortestPath_1.findShortestPath)(this.joinGraph, t1, t2);
|
|
2265
2283
|
if (spath && spath.distance < Infinity) {
|
|
2266
2284
|
const existing1 = this.joinPaths.find(j => j.t1 === t1 && j.t2 === t2);
|
|
2267
2285
|
if (!existing1) {
|
|
@@ -2316,11 +2334,11 @@ export type TxCB = {
|
|
|
2316
2334
|
const TSTableDataName = snakify(tov.name, true);
|
|
2317
2335
|
const TSTableHandlerName = JSON.stringify(tov.name);
|
|
2318
2336
|
if (tov.is_view) {
|
|
2319
|
-
this.dbo[tov.name] = new ViewHandler(this.db, tov, this,
|
|
2337
|
+
this.dbo[tov.name] = new ViewHandler(this.db, tov, this, undefined, undefined, this.joinPaths);
|
|
2320
2338
|
this.dboDefinition += ` ${TSTableHandlerName}: ViewHandler<${TSTableDataName}> \n`;
|
|
2321
2339
|
}
|
|
2322
2340
|
else {
|
|
2323
|
-
this.dbo[tov.name] = new TableHandler(this.db, tov, this,
|
|
2341
|
+
this.dbo[tov.name] = new TableHandler(this.db, tov, this, undefined, undefined, this.joinPaths);
|
|
2324
2342
|
this.dboDefinition += ` ${TSTableHandlerName}: TableHandler<${TSTableDataName}> \n`;
|
|
2325
2343
|
}
|
|
2326
2344
|
allDataDefs += `export type ${TSTableDataName} = { \n` +
|
|
@@ -2330,6 +2348,14 @@ export type TxCB = {
|
|
|
2330
2348
|
if (this.joinPaths && this.joinPaths.find(jp => [jp.t1, jp.t2].includes(tov.name))) {
|
|
2331
2349
|
let table = tov.name;
|
|
2332
2350
|
joinTableNames.push(table);
|
|
2351
|
+
const makeJoin = (isLeft = true, filter, select, options) => {
|
|
2352
|
+
return {
|
|
2353
|
+
[isLeft ? "$leftJoin" : "$innerJoin"]: table,
|
|
2354
|
+
filter,
|
|
2355
|
+
select,
|
|
2356
|
+
...options
|
|
2357
|
+
};
|
|
2358
|
+
};
|
|
2333
2359
|
this.dbo.innerJoin = this.dbo.innerJoin || {};
|
|
2334
2360
|
this.dbo.leftJoin = this.dbo.leftJoin || {};
|
|
2335
2361
|
this.dbo.innerJoinOne = this.dbo.innerJoinOne || {};
|
|
@@ -2341,15 +2367,11 @@ export type TxCB = {
|
|
|
2341
2367
|
return makeJoin(false, filter, select, options);
|
|
2342
2368
|
};
|
|
2343
2369
|
this.dbo.leftJoinOne[table] = (filter, select, options = {}) => {
|
|
2344
|
-
return makeJoin(true, filter, select,
|
|
2370
|
+
return makeJoin(true, filter, select, { ...options, limit: 1 });
|
|
2345
2371
|
};
|
|
2346
2372
|
this.dbo.innerJoinOne[table] = (filter, select, options = {}) => {
|
|
2347
|
-
return makeJoin(false, filter, select,
|
|
2373
|
+
return makeJoin(false, filter, select, { ...options, limit: 1 });
|
|
2348
2374
|
};
|
|
2349
|
-
function makeJoin(isLeft = true, filter, select, options) {
|
|
2350
|
-
return Object.assign({ [isLeft ? "$leftJoin" : "$innerJoin"]: table, filter,
|
|
2351
|
-
select }, options);
|
|
2352
|
-
}
|
|
2353
2375
|
}
|
|
2354
2376
|
});
|
|
2355
2377
|
i18nDef += " }> \n";
|
|
@@ -2377,13 +2399,12 @@ export type TxCB = {
|
|
|
2377
2399
|
let DATA_TYPES = !needType ? [] : await this.db.any("SELECT oid, typname FROM pg_type");
|
|
2378
2400
|
let USER_TABLES = !needType ? [] : await this.db.any("SELECT relid, relname FROM pg_catalog.pg_statio_user_tables");
|
|
2379
2401
|
this.dbo.sql = async (query, params, options, localParams) => {
|
|
2380
|
-
var _a, _b;
|
|
2381
2402
|
const canRunSQL = async (localParams) => {
|
|
2382
2403
|
if (!localParams)
|
|
2383
2404
|
return true;
|
|
2384
2405
|
const { socket } = localParams;
|
|
2385
2406
|
const publishParams = await this.prostgles.publishParser.getPublishParams({ socket });
|
|
2386
|
-
let res = await this.prostgles.opts.publishRawSQL(publishParams);
|
|
2407
|
+
let res = await this.prostgles.opts.publishRawSQL?.(publishParams);
|
|
2387
2408
|
return Boolean(res && typeof res === "boolean" || res === "*");
|
|
2388
2409
|
};
|
|
2389
2410
|
if (!(await canRunSQL(localParams)))
|
|
@@ -2393,7 +2414,7 @@ export type TxCB = {
|
|
|
2393
2414
|
if (returnType === "noticeSubscription") {
|
|
2394
2415
|
if (!socket)
|
|
2395
2416
|
throw "Only allowed with client socket";
|
|
2396
|
-
return await this.prostgles.dbEventsManager
|
|
2417
|
+
return await this.prostgles.dbEventsManager?.addNotice(socket);
|
|
2397
2418
|
}
|
|
2398
2419
|
else if (returnType === "statement") {
|
|
2399
2420
|
try {
|
|
@@ -2408,12 +2429,12 @@ export type TxCB = {
|
|
|
2408
2429
|
if (returnType === "arrayMode") {
|
|
2409
2430
|
finalQuery = new PQ({ text: exports.pgp.as.format(query, params), rowMode: "array" });
|
|
2410
2431
|
}
|
|
2411
|
-
let
|
|
2412
|
-
const {
|
|
2432
|
+
let _qres = await this.db.result(finalQuery, params);
|
|
2433
|
+
const { fields, rows, command } = _qres;
|
|
2413
2434
|
/**
|
|
2414
2435
|
* Fallback for watchSchema in case not superuser and cannot add db event listener
|
|
2415
2436
|
*/
|
|
2416
|
-
const { watchSchema, watchSchemaType } =
|
|
2437
|
+
const { watchSchema, watchSchemaType } = this.prostgles?.opts || {};
|
|
2417
2438
|
if (watchSchema &&
|
|
2418
2439
|
(!this.prostgles.isSuperUser || watchSchemaType === "queries") &&
|
|
2419
2440
|
(["CREATE", "ALTER", "DROP"].includes(command) ||
|
|
@@ -2424,7 +2445,7 @@ export type TxCB = {
|
|
|
2424
2445
|
if (command === "LISTEN") {
|
|
2425
2446
|
if (!socket)
|
|
2426
2447
|
throw "Only allowed with client socket";
|
|
2427
|
-
return await this.prostgles.dbEventsManager
|
|
2448
|
+
return await this.prostgles.dbEventsManager?.addNotify(query, socket);
|
|
2428
2449
|
}
|
|
2429
2450
|
else if (returnType === "rows") {
|
|
2430
2451
|
return rows;
|
|
@@ -2433,18 +2454,26 @@ export type TxCB = {
|
|
|
2433
2454
|
return rows[0];
|
|
2434
2455
|
}
|
|
2435
2456
|
else if (returnType === "value") {
|
|
2436
|
-
return
|
|
2457
|
+
return Object.values(rows?.[0] || {})?.[0];
|
|
2437
2458
|
}
|
|
2438
2459
|
else if (returnType === "values") {
|
|
2439
2460
|
return rows.map(r => Object.values(r[0]));
|
|
2440
2461
|
}
|
|
2441
2462
|
else {
|
|
2442
|
-
|
|
2443
|
-
|
|
2444
|
-
|
|
2445
|
-
|
|
2446
|
-
|
|
2447
|
-
|
|
2463
|
+
let qres = {
|
|
2464
|
+
duration: 0,
|
|
2465
|
+
..._qres,
|
|
2466
|
+
fields: fields?.map(f => {
|
|
2467
|
+
const dataType = DATA_TYPES.find(dt => +dt.oid === +f.dataTypeID)?.typname ?? "text", tableName = USER_TABLES.find(t => +t.relid === +f.tableID), tsDataType = postgresToTsType(dataType);
|
|
2468
|
+
return {
|
|
2469
|
+
...f,
|
|
2470
|
+
tsDataType,
|
|
2471
|
+
dataType,
|
|
2472
|
+
udt_name: dataType,
|
|
2473
|
+
tableName: tableName?.relname
|
|
2474
|
+
};
|
|
2475
|
+
}) ?? []
|
|
2476
|
+
};
|
|
2448
2477
|
return qres;
|
|
2449
2478
|
}
|
|
2450
2479
|
}
|
|
@@ -2470,6 +2499,7 @@ export type TxCB = {
|
|
|
2470
2499
|
}
|
|
2471
2500
|
}
|
|
2472
2501
|
exports.DboBuilder = DboBuilder;
|
|
2502
|
+
_a = DboBuilder;
|
|
2473
2503
|
DboBuilder.create = async (prostgles) => {
|
|
2474
2504
|
let res = new DboBuilder(prostgles);
|
|
2475
2505
|
return await res.init();
|
|
@@ -2482,7 +2512,7 @@ async function getConstraints(db, schema = "public") {
|
|
|
2482
2512
|
ON rel.oid = con.conrelid
|
|
2483
2513
|
INNER JOIN pg_catalog.pg_namespace nsp
|
|
2484
2514
|
ON nsp.oid = connamespace
|
|
2485
|
-
WHERE nsp.nspname = ${PubSubManager_1.asValue(schema)}
|
|
2515
|
+
WHERE nsp.nspname = ${(0, PubSubManager_1.asValue)(schema)}
|
|
2486
2516
|
`);
|
|
2487
2517
|
}
|
|
2488
2518
|
async function getTablesForSchemaPostgresSQL(db, schema = "public") {
|
|
@@ -2596,7 +2626,7 @@ async function getTablesForSchemaPostgresSQL(db, schema = "public") {
|
|
|
2596
2626
|
GROUP BY cl_r.relname
|
|
2597
2627
|
) vr
|
|
2598
2628
|
ON t.table_name = vr.view_name
|
|
2599
|
-
WHERE t.table_schema = ${PubSubManager_1.asValue(schema)}
|
|
2629
|
+
WHERE t.table_schema = ${(0, PubSubManager_1.asValue)(schema)}
|
|
2600
2630
|
GROUP BY t.table_schema, t.table_name, t.table_type, vr.table_names , cc.table_oid
|
|
2601
2631
|
ORDER BY schema, name
|
|
2602
2632
|
`;
|
|
@@ -2641,8 +2671,13 @@ function isPlainObject(o) {
|
|
|
2641
2671
|
return Object(o) === o && Object.getPrototypeOf(o) === Object.prototype;
|
|
2642
2672
|
}
|
|
2643
2673
|
exports.isPlainObject = isPlainObject;
|
|
2674
|
+
function getKeys(o) {
|
|
2675
|
+
return Object.keys(o);
|
|
2676
|
+
}
|
|
2677
|
+
exports.getKeys = getKeys;
|
|
2644
2678
|
function postgresToTsType(udt_data_type) {
|
|
2645
|
-
return
|
|
2679
|
+
return getKeys(prostgles_types_1.TS_PG_Types).find(k => {
|
|
2680
|
+
// @ts-ignore
|
|
2646
2681
|
return prostgles_types_1.TS_PG_Types[k].includes(udt_data_type) || !prostgles_types_1.TS_PG_Types[k].length;
|
|
2647
2682
|
});
|
|
2648
2683
|
}
|
|
@@ -2890,6 +2925,7 @@ function sqlErrCodeToMsg(code) {
|
|
|
2890
2925
|
"XX001": "data_corrupted",
|
|
2891
2926
|
"XX002": "index_corrupted"
|
|
2892
2927
|
}, 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" };
|
|
2928
|
+
//@ts-ignore
|
|
2893
2929
|
return c2[code] || errs[code] || code;
|
|
2894
2930
|
/*
|
|
2895
2931
|
https://www.postgresql.org/docs/13/errcodes-appendix.html
|
|
@@ -2924,10 +2960,10 @@ async function getInferredJoins(db, schema = "public") {
|
|
|
2924
2960
|
let existing = joins[eIdx];
|
|
2925
2961
|
if (existing) {
|
|
2926
2962
|
if (existing.tables[0] === d.table_name) {
|
|
2927
|
-
existing.on =
|
|
2963
|
+
existing.on = { ...existing.on, [d.column_name]: d.foreign_column_name };
|
|
2928
2964
|
}
|
|
2929
2965
|
else {
|
|
2930
|
-
existing.on =
|
|
2966
|
+
existing.on = { ...existing.on, [d.foreign_column_name]: d.column_name };
|
|
2931
2967
|
}
|
|
2932
2968
|
joins[eIdx] = existing;
|
|
2933
2969
|
}
|