prostgles-server 2.0.145 → 2.0.148
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 +275 -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 +21 -8
- package/dist/QueryBuilder.d.ts.map +1 -1
- package/dist/QueryBuilder.js +179 -107
- 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 -0
- package/dist/utils.d.ts.map +1 -1
- package/dist/utils.js +7 -0
- package/dist/utils.js.map +1 -1
- package/lib/AuthHandler.ts +50 -40
- package/lib/DBEventsManager.ts +14 -7
- package/lib/DboBuilder.ts +265 -199
- 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 +128 -55
- package/lib/SyncReplication.ts +10 -10
- package/lib/TableConfig.ts +23 -15
- package/lib/shortestPath.ts +6 -4
- package/lib/utils.ts +7 -1
- package/package.json +8 -9
- 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 +43 -6
- package/tests/isomorphic_queries.ts +41 -6
- package/tests/server/package-lock.json +29 -31
- package/tests/server/package.json +2 -2
- package/tests/server/tsconfig.json +2 -2
- package/tsconfig.json +3 -2
package/dist/QueryBuilder.js
CHANGED
|
@@ -4,17 +4,70 @@
|
|
|
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.makeQuery = exports.getNewQuery = exports.SelectItemBuilder = exports.COMPUTED_FIELDS = exports.FUNCTIONS = exports.asNameAlias = void 0;
|
|
7
|
+
exports.makeQuery = exports.getNewQuery = exports.SelectItemBuilder = exports.COMPUTED_FIELDS = exports.FUNCTIONS = exports.parseFunction = exports.parseFunctionObject = exports.asNameAlias = void 0;
|
|
8
8
|
const DboBuilder_1 = require("./DboBuilder");
|
|
9
|
-
const Prostgles_1 = require("./Prostgles");
|
|
10
9
|
const prostgles_types_1 = require("prostgles-types");
|
|
11
10
|
const utils_1 = require("./utils");
|
|
12
|
-
|
|
13
|
-
let result = prostgles_types_1.asName(field);
|
|
11
|
+
const asNameAlias = (field, tableAlias) => {
|
|
12
|
+
let result = (0, prostgles_types_1.asName)(field);
|
|
14
13
|
if (tableAlias)
|
|
15
|
-
return prostgles_types_1.asName(tableAlias) + "." + result;
|
|
14
|
+
return (0, prostgles_types_1.asName)(tableAlias) + "." + result;
|
|
16
15
|
return result;
|
|
17
16
|
};
|
|
17
|
+
exports.asNameAlias = asNameAlias;
|
|
18
|
+
const parseFunctionObject = (funcData) => {
|
|
19
|
+
const makeErr = (msg) => `Function not specified correctly. Expecting { $funcName: ["columnName",...] } object but got: ${JSON.stringify(funcData)} \n ${msg}`;
|
|
20
|
+
if (!(0, utils_1.isObject)(funcData))
|
|
21
|
+
throw makeErr("");
|
|
22
|
+
const keys = Object.keys(funcData);
|
|
23
|
+
if (keys.length !== 1)
|
|
24
|
+
throw makeErr("");
|
|
25
|
+
const funcName = keys[0];
|
|
26
|
+
const args = funcData[funcName];
|
|
27
|
+
if (!args || !Array.isArray(args)) {
|
|
28
|
+
throw makeErr("Arguments missing or invalid");
|
|
29
|
+
}
|
|
30
|
+
return { funcName, args };
|
|
31
|
+
};
|
|
32
|
+
exports.parseFunctionObject = parseFunctionObject;
|
|
33
|
+
const parseFunction = (funcData) => {
|
|
34
|
+
const { func, args, functions, allowedFields } = funcData;
|
|
35
|
+
/* Function is computed column. No checks needed */
|
|
36
|
+
if (typeof func !== "string") {
|
|
37
|
+
const computedCol = exports.COMPUTED_FIELDS.find(c => c.name === func.name);
|
|
38
|
+
if (!computedCol)
|
|
39
|
+
throw `Unexpected function: computed column spec not found for ${JSON.stringify(func.name)}`;
|
|
40
|
+
return func;
|
|
41
|
+
}
|
|
42
|
+
const funcName = func;
|
|
43
|
+
const makeErr = (msg) => {
|
|
44
|
+
return `Issue with function ${JSON.stringify({ [funcName]: args })}: \n${msg}`;
|
|
45
|
+
};
|
|
46
|
+
/* Find function */
|
|
47
|
+
const funcDef = functions.find(f => f.name === funcName);
|
|
48
|
+
if (!funcDef) {
|
|
49
|
+
const sf = functions.filter(f => f.name.toLowerCase().slice(1).startsWith(funcName.toLowerCase())).sort((a, b) => (a.name.length - b.name.length));
|
|
50
|
+
const hint = (sf.length ? `. \n Maybe you meant: \n | ${sf.map(s => s.name + " " + (s.description || "")).join(" \n | ")} ?` : "");
|
|
51
|
+
throw "\n Function " + funcName + " does not exist or is not allowed " + hint;
|
|
52
|
+
}
|
|
53
|
+
/* Validate fields */
|
|
54
|
+
const fields = funcDef.getFields(args);
|
|
55
|
+
if (fields !== "*") {
|
|
56
|
+
fields.forEach(fieldKey => {
|
|
57
|
+
if (typeof fieldKey !== "string" || !allowedFields.includes(fieldKey)) {
|
|
58
|
+
throw makeErr(`getFields() => field name ${JSON.stringify(fieldKey)} is invalid or disallowed`);
|
|
59
|
+
}
|
|
60
|
+
});
|
|
61
|
+
if ((funcDef.minCols ?? 0) > fields.length) {
|
|
62
|
+
throw makeErr(`Less columns provided than necessary (minCols=${funcDef.minCols})`);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
if (funcDef.numArgs && funcDef.minCols !== 0 && fields !== "*" && Array.isArray(fields) && !fields.length) {
|
|
66
|
+
throw `\n Function "${funcDef.name}" expects at least a field name but has not been provided with one`;
|
|
67
|
+
}
|
|
68
|
+
return funcDef;
|
|
69
|
+
};
|
|
70
|
+
exports.parseFunction = parseFunction;
|
|
18
71
|
const MAX_COL_NUM = 1600;
|
|
19
72
|
const asValue = (v, castAs = "") => DboBuilder_1.pgp.as.format("$1" + castAs, [v]);
|
|
20
73
|
const FTS_Funcs =
|
|
@@ -36,12 +89,12 @@ const FTS_Funcs =
|
|
|
36
89
|
numArgs: 2,
|
|
37
90
|
getFields: (args) => [args[0]],
|
|
38
91
|
getQuery: ({ allColumns, args, tableAlias }) => {
|
|
39
|
-
const col = prostgles_types_1.asName(args[0]);
|
|
92
|
+
const col = (0, prostgles_types_1.asName)(args[0]);
|
|
40
93
|
let qVal = args[1], qType = "to_tsquery";
|
|
41
94
|
let _type = type ? (asValue(type) + ",") : "";
|
|
42
95
|
const searchTypes = prostgles_types_1.TextFilter_FullTextSearchFilterKeys;
|
|
43
96
|
/* { to_tsquery: 'search term' } */
|
|
44
|
-
if (DboBuilder_1.isPlainObject(qVal)) {
|
|
97
|
+
if ((0, DboBuilder_1.isPlainObject)(qVal)) {
|
|
45
98
|
const keys = Object.keys(qVal);
|
|
46
99
|
if (!keys.length)
|
|
47
100
|
throw "Bad arg";
|
|
@@ -99,9 +152,11 @@ let PostGIS_Funcs = [
|
|
|
99
152
|
getFields: (args) => [args[0]],
|
|
100
153
|
getQuery: ({ allColumns, args, tableAlias }) => {
|
|
101
154
|
const arg2 = args[1], mErr = () => { throw `${fname}: Expecting a second argument like: { lat?: number; lng?: number; geojson?: object; srid?: number; use_spheroid?: boolean }`; };
|
|
102
|
-
if (!DboBuilder_1.isPlainObject(arg2))
|
|
155
|
+
if (!(0, DboBuilder_1.isPlainObject)(arg2))
|
|
103
156
|
mErr();
|
|
104
157
|
const col = allColumns.find(c => c.name === args[0]);
|
|
158
|
+
if (!col)
|
|
159
|
+
throw new Error("Col not found: " + args[0]);
|
|
105
160
|
const { lat, lng, srid = 4326, geojson, text, use_spheroid, distance, spheroid = 'SPHEROID["WGS 84",6378137,298.257223563]', debug } = arg2;
|
|
106
161
|
let geomQ = "", extraParams = "";
|
|
107
162
|
if (typeof text === "string") {
|
|
@@ -110,7 +165,7 @@ let PostGIS_Funcs = [
|
|
|
110
165
|
else if ([lat, lng].every(v => Number.isFinite(v))) {
|
|
111
166
|
geomQ = `ST_Point(${asValue(lng)}, ${asValue(lat)})`;
|
|
112
167
|
}
|
|
113
|
-
else if (DboBuilder_1.isPlainObject(geojson)) {
|
|
168
|
+
else if ((0, DboBuilder_1.isPlainObject)(geojson)) {
|
|
114
169
|
geomQ = `ST_GeomFromGeoJSON(${geojson})`;
|
|
115
170
|
}
|
|
116
171
|
else
|
|
@@ -168,12 +223,12 @@ let PostGIS_Funcs = [
|
|
|
168
223
|
else if (fname === "<->") {
|
|
169
224
|
colCast = colIsGeog ? "::geography" : "::geometry";
|
|
170
225
|
geomQCast = colIsGeog ? "::geography" : "::geometry";
|
|
171
|
-
const q = DboBuilder_1.pgp.as.format(`${exports.asNameAlias(args[0], tableAlias)}${colCast} <-> ${geomQ}${geomQCast}`);
|
|
226
|
+
const q = DboBuilder_1.pgp.as.format(`${(0, exports.asNameAlias)(args[0], tableAlias)}${colCast} <-> ${geomQ}${geomQCast}`);
|
|
172
227
|
if (debug)
|
|
173
228
|
throw q;
|
|
174
229
|
return q;
|
|
175
230
|
}
|
|
176
|
-
const q = DboBuilder_1.pgp.as.format(`${fname}(${exports.asNameAlias(args[0], tableAlias)}${colCast} , ${geomQ}${geomQCast} ${extraParams})`);
|
|
231
|
+
const q = DboBuilder_1.pgp.as.format(`${fname}(${(0, exports.asNameAlias)(args[0], tableAlias)}${colCast} , ${geomQ}${geomQCast} ${extraParams})`);
|
|
177
232
|
if (debug)
|
|
178
233
|
throw q;
|
|
179
234
|
return q;
|
|
@@ -197,7 +252,7 @@ PostGIS_Funcs = PostGIS_Funcs.concat([
|
|
|
197
252
|
const otherArgs = args.slice(1);
|
|
198
253
|
if (otherArgs.length)
|
|
199
254
|
secondArg = ", " + otherArgs.map(arg => asValue(arg)).join(", ");
|
|
200
|
-
const escTabelName = exports.asNameAlias(args[0], tableAlias) + "::geometry";
|
|
255
|
+
const escTabelName = (0, exports.asNameAlias)(args[0], tableAlias) + "::geometry";
|
|
201
256
|
let result = DboBuilder_1.pgp.as.format(fname + "(" + escTabelName + secondArg + (fname === "ST_AsGeoJSON" ? ")::jsonb" : ")"));
|
|
202
257
|
if (fname.startsWith("ST_SnapToGrid") || fname.startsWith("ST_Simplify")) {
|
|
203
258
|
let r = `ST_AsGeoJSON(${result})::jsonb`;
|
|
@@ -220,7 +275,7 @@ PostGIS_Funcs = PostGIS_Funcs.concat(["ST_Extent", "ST_3DExtent", "ST_XMin_Agg",
|
|
|
220
275
|
numArgs: 1,
|
|
221
276
|
getFields: (args) => [args[0]],
|
|
222
277
|
getQuery: ({ allowedFields, args, tableAlias }) => {
|
|
223
|
-
const escTabelName = exports.asNameAlias(args[0], tableAlias) + "::geometry";
|
|
278
|
+
const escTabelName = (0, exports.asNameAlias)(args[0], tableAlias) + "::geometry";
|
|
224
279
|
if (fname.includes("Extent")) {
|
|
225
280
|
return `${fname}(${escTabelName})`;
|
|
226
281
|
}
|
|
@@ -242,7 +297,7 @@ exports.FUNCTIONS = [
|
|
|
242
297
|
numArgs: MAX_COL_NUM,
|
|
243
298
|
getFields: (args) => args,
|
|
244
299
|
getQuery: ({ allowedFields, args, tableAlias }) => {
|
|
245
|
-
const q = DboBuilder_1.pgp.as.format("md5(" + args.map(fname => "COALESCE( " + exports.asNameAlias(fname, tableAlias) + "::text, '' )").join(" || ") + ")");
|
|
300
|
+
const q = DboBuilder_1.pgp.as.format("md5(" + args.map(fname => "COALESCE( " + (0, exports.asNameAlias)(fname, tableAlias) + "::text, '' )").join(" || ") + ")");
|
|
246
301
|
return q;
|
|
247
302
|
}
|
|
248
303
|
},
|
|
@@ -254,7 +309,7 @@ exports.FUNCTIONS = [
|
|
|
254
309
|
numArgs: MAX_COL_NUM,
|
|
255
310
|
getFields: (args) => args,
|
|
256
311
|
getQuery: ({ allowedFields, args, tableAlias }) => {
|
|
257
|
-
const q = DboBuilder_1.pgp.as.format("md5(string_agg(" + args.map(fname => "COALESCE( " + exports.asNameAlias(fname, tableAlias) + "::text, '' )").join(" || ") + ", ','))");
|
|
312
|
+
const q = DboBuilder_1.pgp.as.format("md5(string_agg(" + args.map(fname => "COALESCE( " + (0, exports.asNameAlias)(fname, tableAlias) + "::text, '' )").join(" || ") + ", ','))");
|
|
258
313
|
return q;
|
|
259
314
|
}
|
|
260
315
|
},
|
|
@@ -266,7 +321,7 @@ exports.FUNCTIONS = [
|
|
|
266
321
|
numArgs: MAX_COL_NUM,
|
|
267
322
|
getFields: (args) => args,
|
|
268
323
|
getQuery: ({ allowedFields, args, tableAlias }) => {
|
|
269
|
-
const q = DboBuilder_1.pgp.as.format("encode(sha256((" + args.map(fname => "COALESCE( " + exports.asNameAlias(fname, tableAlias) + ", '' )").join(" || ") + ")::text::bytea), 'hex')");
|
|
324
|
+
const q = DboBuilder_1.pgp.as.format("encode(sha256((" + args.map(fname => "COALESCE( " + (0, exports.asNameAlias)(fname, tableAlias) + ", '' )").join(" || ") + ")::text::bytea), 'hex')");
|
|
270
325
|
return q;
|
|
271
326
|
}
|
|
272
327
|
},
|
|
@@ -278,7 +333,7 @@ exports.FUNCTIONS = [
|
|
|
278
333
|
numArgs: MAX_COL_NUM,
|
|
279
334
|
getFields: (args) => args,
|
|
280
335
|
getQuery: ({ allowedFields, args, tableAlias }) => {
|
|
281
|
-
const q = DboBuilder_1.pgp.as.format("encode(sha256(string_agg(" + args.map(fname => "COALESCE( " + exports.asNameAlias(fname, tableAlias) + ", '' )").join(" || ") + ", ',')::text::bytea), 'hex')");
|
|
336
|
+
const q = DboBuilder_1.pgp.as.format("encode(sha256(string_agg(" + args.map(fname => "COALESCE( " + (0, exports.asNameAlias)(fname, tableAlias) + ", '' )").join(" || ") + ", ',')::text::bytea), 'hex')");
|
|
282
337
|
return q;
|
|
283
338
|
}
|
|
284
339
|
},
|
|
@@ -290,7 +345,7 @@ exports.FUNCTIONS = [
|
|
|
290
345
|
numArgs: MAX_COL_NUM,
|
|
291
346
|
getFields: (args) => args,
|
|
292
347
|
getQuery: ({ allowedFields, args, tableAlias }) => {
|
|
293
|
-
const q = DboBuilder_1.pgp.as.format("encode(sha512((" + args.map(fname => "COALESCE( " + exports.asNameAlias(fname, tableAlias) + ", '' )").join(" || ") + ")::text::bytea), 'hex')");
|
|
348
|
+
const q = DboBuilder_1.pgp.as.format("encode(sha512((" + args.map(fname => "COALESCE( " + (0, exports.asNameAlias)(fname, tableAlias) + ", '' )").join(" || ") + ")::text::bytea), 'hex')");
|
|
294
349
|
return q;
|
|
295
350
|
}
|
|
296
351
|
},
|
|
@@ -302,7 +357,7 @@ exports.FUNCTIONS = [
|
|
|
302
357
|
numArgs: MAX_COL_NUM,
|
|
303
358
|
getFields: (args) => args,
|
|
304
359
|
getQuery: ({ allowedFields, args, tableAlias }) => {
|
|
305
|
-
const q = DboBuilder_1.pgp.as.format("encode(sha512(string_agg(" + args.map(fname => "COALESCE( " + exports.asNameAlias(fname, tableAlias) + ", '' )").join(" || ") + ", ',')::text::bytea), 'hex')");
|
|
360
|
+
const q = DboBuilder_1.pgp.as.format("encode(sha512(string_agg(" + args.map(fname => "COALESCE( " + (0, exports.asNameAlias)(fname, tableAlias) + ", '' )").join(" || ") + ", ',')::text::bytea), 'hex')");
|
|
306
361
|
return q;
|
|
307
362
|
}
|
|
308
363
|
},
|
|
@@ -316,7 +371,7 @@ exports.FUNCTIONS = [
|
|
|
316
371
|
singleColArg: false,
|
|
317
372
|
getFields: (args) => [args[0]],
|
|
318
373
|
getQuery: ({ allowedFields, args, tableAlias }) => {
|
|
319
|
-
return DboBuilder_1.pgp.as.format("LEFT(" + exports.asNameAlias(args[0], tableAlias) + ", $1)", [args[1]]);
|
|
374
|
+
return DboBuilder_1.pgp.as.format("LEFT(" + (0, exports.asNameAlias)(args[0], tableAlias) + ", $1)", [args[1]]);
|
|
320
375
|
}
|
|
321
376
|
},
|
|
322
377
|
{
|
|
@@ -327,7 +382,7 @@ exports.FUNCTIONS = [
|
|
|
327
382
|
singleColArg: true,
|
|
328
383
|
getFields: (args) => [args[0]],
|
|
329
384
|
getQuery: ({ allowedFields, args, tableAlias }) => {
|
|
330
|
-
return DboBuilder_1.pgp.as.format("unnest(string_to_array(" + exports.asNameAlias(args[0], tableAlias) + "::TEXT , ' '))"); //, [args[1]]
|
|
385
|
+
return DboBuilder_1.pgp.as.format("unnest(string_to_array(" + (0, exports.asNameAlias)(args[0], tableAlias) + "::TEXT , ' '))"); //, [args[1]]
|
|
331
386
|
}
|
|
332
387
|
},
|
|
333
388
|
{
|
|
@@ -338,7 +393,7 @@ exports.FUNCTIONS = [
|
|
|
338
393
|
singleColArg: false,
|
|
339
394
|
getFields: (args) => [args[0]],
|
|
340
395
|
getQuery: ({ allowedFields, args, tableAlias }) => {
|
|
341
|
-
return DboBuilder_1.pgp.as.format("RIGHT(" + exports.asNameAlias(args[0], tableAlias) + ", $1)", [args[1]]);
|
|
396
|
+
return DboBuilder_1.pgp.as.format("RIGHT(" + (0, exports.asNameAlias)(args[0], tableAlias) + ", $1)", [args[1]]);
|
|
342
397
|
}
|
|
343
398
|
},
|
|
344
399
|
{
|
|
@@ -350,9 +405,9 @@ exports.FUNCTIONS = [
|
|
|
350
405
|
getFields: (args) => [args[0]],
|
|
351
406
|
getQuery: ({ allowedFields, args, tableAlias }) => {
|
|
352
407
|
if (args.length === 3) {
|
|
353
|
-
return DboBuilder_1.pgp.as.format("to_char(" + exports.asNameAlias(args[0], tableAlias) + ", $2, $3)", [args[0], args[1], args[2]]);
|
|
408
|
+
return DboBuilder_1.pgp.as.format("to_char(" + (0, exports.asNameAlias)(args[0], tableAlias) + ", $2, $3)", [args[0], args[1], args[2]]);
|
|
354
409
|
}
|
|
355
|
-
return DboBuilder_1.pgp.as.format("to_char(" + exports.asNameAlias(args[0], tableAlias) + ", $2)", [args[0], args[1]]);
|
|
410
|
+
return DboBuilder_1.pgp.as.format("to_char(" + (0, exports.asNameAlias)(args[0], tableAlias) + ", $2)", [args[0], args[1]]);
|
|
356
411
|
}
|
|
357
412
|
},
|
|
358
413
|
/**
|
|
@@ -412,7 +467,7 @@ exports.FUNCTIONS = [
|
|
|
412
467
|
numArgs: 1,
|
|
413
468
|
getFields: (args) => [args[0]],
|
|
414
469
|
getQuery: ({ allowedFields, args, tableAlias }) => {
|
|
415
|
-
const col = exports.asNameAlias(args[0], tableAlias);
|
|
470
|
+
const col = (0, exports.asNameAlias)(args[0], tableAlias);
|
|
416
471
|
if (!val)
|
|
417
472
|
return `date_trunc(${asValue(unit)}, ${col})`;
|
|
418
473
|
const prevInt = {
|
|
@@ -435,7 +490,7 @@ exports.FUNCTIONS = [
|
|
|
435
490
|
singleColArg: false,
|
|
436
491
|
getFields: (args) => [args[1]],
|
|
437
492
|
getQuery: ({ allowedFields, args, tableAlias }) => {
|
|
438
|
-
return `${funcName}(${asValue(args[0])}, ${exports.asNameAlias(args[1], tableAlias)})`;
|
|
493
|
+
return `${funcName}(${asValue(args[0])}, ${(0, exports.asNameAlias)(args[1], tableAlias)})`;
|
|
439
494
|
}
|
|
440
495
|
})),
|
|
441
496
|
/* Handy date funcs */
|
|
@@ -474,18 +529,42 @@ exports.FUNCTIONS = [
|
|
|
474
529
|
numArgs: 1,
|
|
475
530
|
getFields: (args) => [args[0]],
|
|
476
531
|
getQuery: ({ allowedFields, args, tableAlias }) => {
|
|
477
|
-
return DboBuilder_1.pgp.as.format("trim(to_char(" + exports.asNameAlias(args[0], tableAlias) + ", $2))", [args[0], txt]);
|
|
532
|
+
return DboBuilder_1.pgp.as.format("trim(to_char(" + (0, exports.asNameAlias)(args[0], tableAlias) + ", $2))", [args[0], txt]);
|
|
478
533
|
}
|
|
479
534
|
})),
|
|
480
535
|
/* Basic 1 arg col funcs */
|
|
481
|
-
...["upper", "lower", "length", "reverse", "trim", "initcap", "round", "ceil", "floor", "sign", "
|
|
536
|
+
...["upper", "lower", "length", "reverse", "trim", "initcap", "round", "ceil", "floor", "sign", "md5"].map(funcName => ({
|
|
482
537
|
name: "$" + funcName,
|
|
483
538
|
type: "function",
|
|
484
539
|
numArgs: 1,
|
|
485
540
|
singleColArg: true,
|
|
486
541
|
getFields: (args) => [args[0]],
|
|
487
542
|
getQuery: ({ allowedFields, args, tableAlias }) => {
|
|
488
|
-
return funcName + "(" + exports.asNameAlias(args[0], tableAlias) + ")";
|
|
543
|
+
return funcName + "(" + (0, exports.asNameAlias)(args[0], tableAlias) + ")";
|
|
544
|
+
}
|
|
545
|
+
})),
|
|
546
|
+
/* Interval funcs */
|
|
547
|
+
...["age", "difference"].map(funcName => ({
|
|
548
|
+
name: "$" + funcName,
|
|
549
|
+
type: "function",
|
|
550
|
+
numArgs: 1,
|
|
551
|
+
singleColArg: true,
|
|
552
|
+
getFields: (args) => args,
|
|
553
|
+
getQuery: ({ allowedFields, args, tableAlias }) => {
|
|
554
|
+
const validCols = args.filter(a => typeof a === "string").length;
|
|
555
|
+
if (funcName === "difference" && validCols !== 2)
|
|
556
|
+
throw new Error("Must have two column names");
|
|
557
|
+
if (![1, 2].includes(validCols))
|
|
558
|
+
throw new Error("Must have one or two column names");
|
|
559
|
+
const [leftField, rightField] = args;
|
|
560
|
+
const leftQ = (0, exports.asNameAlias)(leftField, tableAlias);
|
|
561
|
+
const rightQ = rightField ? ("," + (0, exports.asNameAlias)(rightField, tableAlias)) : "";
|
|
562
|
+
if (funcName === "age") {
|
|
563
|
+
return `${funcName}(${leftQ}, ${rightQ})`;
|
|
564
|
+
}
|
|
565
|
+
else {
|
|
566
|
+
return `${leftQ} - ${rightQ}`;
|
|
567
|
+
}
|
|
489
568
|
}
|
|
490
569
|
})),
|
|
491
570
|
/* pgcrypto funcs */
|
|
@@ -496,7 +575,7 @@ exports.FUNCTIONS = [
|
|
|
496
575
|
singleColArg: false,
|
|
497
576
|
getFields: (args) => [args[1]],
|
|
498
577
|
getQuery: ({ allowedFields, args, tableAlias }) => {
|
|
499
|
-
const value = asValue(args[0]) + "", seedColumnName = exports.asNameAlias(args[1], tableAlias);
|
|
578
|
+
const value = asValue(args[0]) + "", seedColumnName = (0, exports.asNameAlias)(args[1], tableAlias);
|
|
500
579
|
return `crypt(${value}, ${seedColumnName}::text)`;
|
|
501
580
|
}
|
|
502
581
|
})),
|
|
@@ -508,7 +587,7 @@ exports.FUNCTIONS = [
|
|
|
508
587
|
singleColArg: false,
|
|
509
588
|
getFields: (args) => [args[1]],
|
|
510
589
|
getQuery: ({ allowedFields, args, tableAlias }) => {
|
|
511
|
-
let a1 = asValue(args[0]), a2 = exports.asNameAlias(args[1], tableAlias);
|
|
590
|
+
let a1 = asValue(args[0]), a2 = (0, exports.asNameAlias)(args[1], tableAlias);
|
|
512
591
|
if (funcName === "position_lower") {
|
|
513
592
|
a1 = `LOWER(${a1}::text)`;
|
|
514
593
|
a2 = `LOWER(${a2}::text)`;
|
|
@@ -522,7 +601,7 @@ exports.FUNCTIONS = [
|
|
|
522
601
|
numArgs: 1,
|
|
523
602
|
minCols: 0,
|
|
524
603
|
singleColArg: false,
|
|
525
|
-
getFields: (args
|
|
604
|
+
getFields: (args) => [],
|
|
526
605
|
getQuery: ({ allowedFields, args, tableAlias }) => {
|
|
527
606
|
let value = asValue(args[0]);
|
|
528
607
|
if (typeof value !== "string")
|
|
@@ -533,7 +612,7 @@ exports.FUNCTIONS = [
|
|
|
533
612
|
});
|
|
534
613
|
value = asValue(value);
|
|
535
614
|
if (usedColumns.length) {
|
|
536
|
-
return `format(${value}, ${usedColumns.map(c => `${exports.asNameAlias(c, tableAlias)}::TEXT`).join(", ")})`;
|
|
615
|
+
return `format(${value}, ${usedColumns.map(c => `${(0, exports.asNameAlias)(c, tableAlias)}::TEXT`).join(", ")})`;
|
|
537
616
|
}
|
|
538
617
|
return `format(${value})`;
|
|
539
618
|
}
|
|
@@ -556,7 +635,7 @@ exports.FUNCTIONS = [
|
|
|
556
635
|
let term = args[1];
|
|
557
636
|
const rawTerm = args[1];
|
|
558
637
|
let { edgeTruncate, noFields = false, returnType, matchCase = false } = args[2] || {};
|
|
559
|
-
if (!prostgles_types_1.isEmpty(args[2])) {
|
|
638
|
+
if (!(0, prostgles_types_1.isEmpty)(args[2])) {
|
|
560
639
|
const keys = Object.keys(args[2]);
|
|
561
640
|
const validKeys = ["edgeTruncate", "noFields", "returnType", "matchCase"];
|
|
562
641
|
const bad_keys = keys.filter(k => !validKeys.includes(k));
|
|
@@ -600,7 +679,7 @@ exports.FUNCTIONS = [
|
|
|
600
679
|
END
|
|
601
680
|
`;
|
|
602
681
|
};
|
|
603
|
-
let colRaw = "( " + cols.map(c => `${noFields ? "" : (asValue(c + ": ") + " || ")} COALESCE(${exports.asNameAlias(c, tableAlias)}::TEXT, '')`).join(" || ', ' || ") + " )";
|
|
682
|
+
let colRaw = "( " + cols.map(c => `${noFields ? "" : (asValue(c + ": ") + " || ")} COALESCE(${(0, exports.asNameAlias)(c, tableAlias)}::TEXT, '')`).join(" || ', ' || ") + " )";
|
|
604
683
|
let col = colRaw;
|
|
605
684
|
term = asValue(term);
|
|
606
685
|
if (!matchCase) {
|
|
@@ -632,7 +711,7 @@ exports.FUNCTIONS = [
|
|
|
632
711
|
let _cols = validCols.filter(c =>
|
|
633
712
|
/** Exclude numeric columns when the search tern contains a character */
|
|
634
713
|
!hasChars ||
|
|
635
|
-
DboBuilder_1.postgresToTsType(c.colInfo.udt_name) !== "number");
|
|
714
|
+
(0, DboBuilder_1.postgresToTsType)(c.colInfo.udt_name) !== "number");
|
|
636
715
|
/** This will break GROUP BY (non-integer constant in GROUP BY) */
|
|
637
716
|
if (!_cols.length) {
|
|
638
717
|
if (validCols.length && hasChars)
|
|
@@ -642,11 +721,10 @@ exports.FUNCTIONS = [
|
|
|
642
721
|
res = `CASE
|
|
643
722
|
${_cols
|
|
644
723
|
.map(c => {
|
|
645
|
-
|
|
646
|
-
const colNameEscaped = exports.asNameAlias(c.key, tableAlias);
|
|
724
|
+
const colNameEscaped = (0, exports.asNameAlias)(c.key, tableAlias);
|
|
647
725
|
let colSelect = `${colNameEscaped}::TEXT`;
|
|
648
|
-
const isTstamp =
|
|
649
|
-
if (isTstamp ||
|
|
726
|
+
const isTstamp = c.colInfo?.udt_name.startsWith("timestamp");
|
|
727
|
+
if (isTstamp || c.colInfo?.udt_name === "date") {
|
|
650
728
|
colSelect = `( CASE WHEN ${colNameEscaped} IS NULL THEN ''
|
|
651
729
|
ELSE concat_ws(' ',
|
|
652
730
|
${colNameEscaped}::TEXT,
|
|
@@ -701,7 +779,7 @@ exports.FUNCTIONS = [
|
|
|
701
779
|
if (args.length > 1) {
|
|
702
780
|
extraArgs = DboBuilder_1.pgp.as.format(", $1:csv", args.slice(1));
|
|
703
781
|
}
|
|
704
|
-
return aggName + "(" + exports.asNameAlias(args[0], tableAlias) + `${extraArgs})`;
|
|
782
|
+
return aggName + "(" + (0, exports.asNameAlias)(args[0], tableAlias) + `${extraArgs})`;
|
|
705
783
|
}
|
|
706
784
|
})),
|
|
707
785
|
/* More aggs */
|
|
@@ -723,7 +801,7 @@ exports.FUNCTIONS = [
|
|
|
723
801
|
singleColArg: true,
|
|
724
802
|
getFields: (args) => [args[0]],
|
|
725
803
|
getQuery: ({ allowedFields, args, tableAlias }) => {
|
|
726
|
-
const col = exports.asNameAlias(args[0], tableAlias);
|
|
804
|
+
const col = (0, exports.asNameAlias)(args[0], tableAlias);
|
|
727
805
|
return `round( ( ( MAX(${col}) - MIN(${col}) )::float/MIN(${col}) ) * 100, 2)`;
|
|
728
806
|
}
|
|
729
807
|
}
|
|
@@ -743,7 +821,7 @@ exports.COMPUTED_FIELDS = [
|
|
|
743
821
|
/* CTID not available in AFTER trigger */
|
|
744
822
|
// .concat(ctidField? [ctidField] : [])
|
|
745
823
|
.sort()
|
|
746
|
-
.map(f => exports.asNameAlias(f, tableAlias))
|
|
824
|
+
.map(f => (0, exports.asNameAlias)(f, tableAlias))
|
|
747
825
|
.map(f => `md5(coalesce(${f}::text, 'dd'))`)
|
|
748
826
|
.join(" || ") +
|
|
749
827
|
`)`;
|
|
@@ -778,29 +856,19 @@ class SelectItemBuilder {
|
|
|
778
856
|
throw `Cannot specify duplicate columns ( ${item.alias} ). Perhaps you're using "*" with column names?`;
|
|
779
857
|
this.select.push(item);
|
|
780
858
|
};
|
|
781
|
-
this.
|
|
782
|
-
const funcDef =
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
throw "\n Function " + funcName + " does not exist or is not allowed " + hint;
|
|
787
|
-
}
|
|
788
|
-
this.addFunction(funcDef, args, alias);
|
|
789
|
-
};
|
|
790
|
-
this.addFunction = (funcDef, args, alias) => {
|
|
791
|
-
if (funcDef.numArgs) {
|
|
792
|
-
const fields = funcDef.getFields(args, this.allowedFields);
|
|
793
|
-
if (funcDef.minCols !== 0 && fields !== "*" && Array.isArray(fields) && !fields.length) {
|
|
794
|
-
console.log(fields);
|
|
795
|
-
throw `\n Function "${funcDef.name}" expects at least a field name but has not been provided with one`;
|
|
796
|
-
}
|
|
797
|
-
}
|
|
859
|
+
this.addFunction = (func, args, alias) => {
|
|
860
|
+
const funcDef = (0, exports.parseFunction)({
|
|
861
|
+
func, args, functions: this.functions,
|
|
862
|
+
allowedFields: this.allowedFieldsIncludingComputed,
|
|
863
|
+
});
|
|
798
864
|
this.addItem({
|
|
799
865
|
type: funcDef.type,
|
|
800
866
|
alias,
|
|
801
|
-
getFields: () => funcDef.getFields(args
|
|
867
|
+
getFields: () => funcDef.getFields(args),
|
|
802
868
|
getQuery: (tableAlias) => funcDef.getQuery({ allColumns: this.columns, allowedFields: this.allowedFields, args, tableAlias,
|
|
803
869
|
ctidField: undefined,
|
|
870
|
+
/* CTID not available in AFTER trigger */
|
|
871
|
+
// ctidField: this.isView? undefined : "ctid"
|
|
804
872
|
}),
|
|
805
873
|
selected: true
|
|
806
874
|
});
|
|
@@ -810,7 +878,13 @@ class SelectItemBuilder {
|
|
|
810
878
|
if (selected) {
|
|
811
879
|
const compCol = exports.COMPUTED_FIELDS.find(cf => cf.name === fieldName);
|
|
812
880
|
if (compCol && !this.select.find(s => s.alias === fieldName)) {
|
|
813
|
-
const cf =
|
|
881
|
+
const cf = {
|
|
882
|
+
...compCol,
|
|
883
|
+
type: "computed",
|
|
884
|
+
numArgs: 0,
|
|
885
|
+
singleColArg: false,
|
|
886
|
+
getFields: (args) => []
|
|
887
|
+
};
|
|
814
888
|
this.addFunction(cf, [], compCol.name);
|
|
815
889
|
return;
|
|
816
890
|
}
|
|
@@ -819,10 +893,10 @@ class SelectItemBuilder {
|
|
|
819
893
|
let alias = selected ? fieldName : ("not_selected_" + fieldName);
|
|
820
894
|
this.addItem({
|
|
821
895
|
type: "column",
|
|
822
|
-
columnPGDataType: colDef
|
|
823
|
-
column_udt_type: colDef
|
|
896
|
+
columnPGDataType: colDef?.data_type,
|
|
897
|
+
column_udt_type: colDef?.udt_name,
|
|
824
898
|
alias,
|
|
825
|
-
getQuery: () => prostgles_types_1.asName(fieldName),
|
|
899
|
+
getQuery: () => (0, prostgles_types_1.asName)(fieldName),
|
|
826
900
|
getFields: () => [fieldName],
|
|
827
901
|
selected
|
|
828
902
|
});
|
|
@@ -847,7 +921,7 @@ class SelectItemBuilder {
|
|
|
847
921
|
else if (userSelect === "*") {
|
|
848
922
|
this.allowedFields.map(key => this.addColumn(key, true));
|
|
849
923
|
}
|
|
850
|
-
else if (DboBuilder_1.isPlainObject(userSelect) && !prostgles_types_1.isEmpty(userSelect)) {
|
|
924
|
+
else if ((0, DboBuilder_1.isPlainObject)(userSelect) && !(0, prostgles_types_1.isEmpty)(userSelect)) {
|
|
851
925
|
const selectKeys = Object.keys(userSelect), selectValues = Object.values(userSelect);
|
|
852
926
|
/* Cannot include and exclude at the same time */
|
|
853
927
|
if (selectValues.filter(v => [0, false].includes(v)).length) {
|
|
@@ -873,12 +947,12 @@ class SelectItemBuilder {
|
|
|
873
947
|
}
|
|
874
948
|
/* Aggs and functions */
|
|
875
949
|
}
|
|
876
|
-
else if (typeof val === "string" || DboBuilder_1.isPlainObject(val)) {
|
|
950
|
+
else if (typeof val === "string" || (0, DboBuilder_1.isPlainObject)(val)) {
|
|
877
951
|
/* Function shorthand notation
|
|
878
952
|
{ id: "$max" } === { id: { $max: ["id"] } } === SELECT MAX(id) AS id
|
|
879
953
|
*/
|
|
880
954
|
if ((typeof val === "string" && val !== "*") ||
|
|
881
|
-
DboBuilder_1.isPlainObject(val) && Object.keys(val).length === 1 && Array.isArray(Object.values(val)[0]) // !isPlainObject(Object.values(val)[0])
|
|
955
|
+
(0, DboBuilder_1.isPlainObject)(val) && Object.keys(val).length === 1 && Array.isArray(Object.values(val)[0]) // !isPlainObject(Object.values(val)[0])
|
|
882
956
|
) {
|
|
883
957
|
// if(!Array.isArray(Object.values(val)[0])){
|
|
884
958
|
// throw `Could not parse selected item: ${JSON.stringify(val)}\nFunction arguments must be in an array`;
|
|
@@ -894,15 +968,12 @@ class SelectItemBuilder {
|
|
|
894
968
|
}
|
|
895
969
|
funcName = val;
|
|
896
970
|
args = [key];
|
|
971
|
+
/** Function full notation { $funcName: ["colName", ...args] } */
|
|
897
972
|
}
|
|
898
973
|
else {
|
|
899
|
-
|
|
900
|
-
if (callKeys.length !== 1 || !Array.isArray(val[callKeys[0]]))
|
|
901
|
-
throw "\nIssue with select. \nUnexpected function definition. \nExpecting { field_name: func_name } OR { result_key: { func_name: [arg1, arg2 ...] } } \nBut got -> " + JSON.stringify({ [key]: val });
|
|
902
|
-
funcName = callKeys[0];
|
|
903
|
-
args = val[funcName];
|
|
974
|
+
({ funcName, args } = (0, exports.parseFunctionObject)(val));
|
|
904
975
|
}
|
|
905
|
-
this.
|
|
976
|
+
this.addFunction(funcName, args, key);
|
|
906
977
|
/* Join */
|
|
907
978
|
}
|
|
908
979
|
else {
|
|
@@ -937,8 +1008,8 @@ class SelectItemBuilder {
|
|
|
937
1008
|
}
|
|
938
1009
|
}
|
|
939
1010
|
exports.SelectItemBuilder = SelectItemBuilder;
|
|
940
|
-
async function getNewQuery(_this, filter, selectParams, param3_unused = null, tableRules, localParams, columns) {
|
|
941
|
-
if ((
|
|
1011
|
+
async function getNewQuery(_this, filter, selectParams = {}, param3_unused = null, tableRules, localParams, columns) {
|
|
1012
|
+
if ((localParams?.socket || localParams?.httpReq) && !(0, utils_1.get)(tableRules, "select.fields")) {
|
|
942
1013
|
throw `INTERNAL ERROR: publish.${_this.name}.select.fields rule missing`;
|
|
943
1014
|
}
|
|
944
1015
|
// const all_columns: SelectItem[] = _this.column_names.slice(0).map(fieldName => ({
|
|
@@ -958,11 +1029,10 @@ async function getNewQuery(_this, filter, selectParams, param3_unused = null, ta
|
|
|
958
1029
|
// let select: SelectItem[] = [],
|
|
959
1030
|
let joinQueries = [];
|
|
960
1031
|
// const all_colnames = _this.column_names.slice(0).concat(COMPUTED_FIELDS.map(c => c.name));
|
|
961
|
-
selectParams = selectParams || {};
|
|
962
1032
|
const { select: userSelect = "*" } = selectParams,
|
|
963
1033
|
// allCols = _this.column_names.slice(0),
|
|
964
1034
|
// allFieldsIncludingComputed = allCols.concat(COMPUTED_FIELDS.map(c => c.name)),
|
|
965
|
-
allowedFields = _this.parseFieldFilter(utils_1.get(tableRules, "select.fields")) || _this.column_names.slice(0),
|
|
1035
|
+
allowedFields = _this.parseFieldFilter((0, utils_1.get)(tableRules, "select.fields")) || _this.column_names.slice(0),
|
|
966
1036
|
// allowedFieldsIncludingComputed = _this.parseFieldFilter(get(tableRules, "select.fields"), true, allFieldsIncludingComputed) || allFieldsIncludingComputed,
|
|
967
1037
|
sBuilder = new SelectItemBuilder({ allowedFields, computedFields: exports.COMPUTED_FIELDS, isView: _this.is_view, functions: exports.FUNCTIONS, allFields: _this.column_names.slice(0), columns });
|
|
968
1038
|
await sBuilder.parseUserSelect(userSelect, async (key, val, throwErr) => {
|
|
@@ -1003,6 +1073,8 @@ async function getNewQuery(_this, filter, selectParams, param3_unused = null, ta
|
|
|
1003
1073
|
j_table = key;
|
|
1004
1074
|
}
|
|
1005
1075
|
}
|
|
1076
|
+
if (!j_table)
|
|
1077
|
+
throw "j_table missing";
|
|
1006
1078
|
const _thisJoinedTable = _this.dboBuilder.dbo[j_table];
|
|
1007
1079
|
if (!_thisJoinedTable) {
|
|
1008
1080
|
throw `Joined table ${JSON.stringify(j_table)} is disallowed or inexistent \nOr you've forgot to put the function arguments into an array`;
|
|
@@ -1010,10 +1082,10 @@ async function getNewQuery(_this, filter, selectParams, param3_unused = null, ta
|
|
|
1010
1082
|
let isLocal = true;
|
|
1011
1083
|
if (localParams && (localParams.socket || localParams.httpReq)) {
|
|
1012
1084
|
isLocal = false;
|
|
1013
|
-
j_tableRules = await _this.dboBuilder.publishParser
|
|
1085
|
+
j_tableRules = await _this.dboBuilder.publishParser?.getValidatedRequestRuleWusr({ tableName: j_table, command: "find", localParams });
|
|
1014
1086
|
}
|
|
1015
1087
|
if (isLocal || j_tableRules) {
|
|
1016
|
-
const joinQuery = await getNewQuery(_thisJoinedTable, j_filter,
|
|
1088
|
+
const joinQuery = await getNewQuery(_thisJoinedTable, j_filter, { ...j_selectParams, alias: j_alias }, param3_unused, j_tableRules, localParams, columns);
|
|
1017
1089
|
joinQuery.isLeftJoin = j_isLeftJoin;
|
|
1018
1090
|
joinQuery.tableAlias = j_alias;
|
|
1019
1091
|
joinQuery.$path = j_path;
|
|
@@ -1035,8 +1107,8 @@ async function getNewQuery(_this, filter, selectParams, param3_unused = null, ta
|
|
|
1035
1107
|
const where = await _this.prepareWhere({
|
|
1036
1108
|
filter,
|
|
1037
1109
|
select,
|
|
1038
|
-
forcedFilter: utils_1.get(tableRules, "select.forcedFilter"),
|
|
1039
|
-
filterFields: utils_1.get(tableRules, "select.filterFields"),
|
|
1110
|
+
forcedFilter: (0, utils_1.get)(tableRules, "select.forcedFilter"),
|
|
1111
|
+
filterFields: (0, utils_1.get)(tableRules, "select.filterFields"),
|
|
1040
1112
|
tableAlias: selectParams.alias,
|
|
1041
1113
|
localParams,
|
|
1042
1114
|
tableRule: tableRules
|
|
@@ -1050,7 +1122,7 @@ async function getNewQuery(_this, filter, selectParams, param3_unused = null, ta
|
|
|
1050
1122
|
where,
|
|
1051
1123
|
// having: cond.having,
|
|
1052
1124
|
limit: _this.prepareLimitQuery(selectParams.limit, p),
|
|
1053
|
-
orderBy: [_this.prepareSort(selectParams.orderBy, allowedFields, selectParams.alias,
|
|
1125
|
+
orderBy: [_this.prepareSort(selectParams.orderBy, allowedFields, selectParams.alias, undefined, select)],
|
|
1054
1126
|
offset: _this.prepareOffsetQuery(selectParams.offset)
|
|
1055
1127
|
};
|
|
1056
1128
|
// console.log(resQuery);
|
|
@@ -1059,24 +1131,24 @@ async function getNewQuery(_this, filter, selectParams, param3_unused = null, ta
|
|
|
1059
1131
|
}
|
|
1060
1132
|
exports.getNewQuery = getNewQuery;
|
|
1061
1133
|
/* No validation/authorisation at this point */
|
|
1062
|
-
function makeQuery(_this, q, depth = 0, joinFields = [], selectParams) {
|
|
1134
|
+
function makeQuery(_this, q, depth = 0, joinFields = [], selectParams = {}) {
|
|
1063
1135
|
const PREF = `prostgles`, joins = q.joins || [],
|
|
1064
1136
|
// aggs = q.aggs || [],
|
|
1065
|
-
makePref = (q) => !q.tableAlias ? q.table : `${q.tableAlias || ""}_${q.table}`, makePrefANON = (joinAlias, table) => prostgles_types_1.asName(!joinAlias ? table : `${joinAlias || ""}_${table}`), makePrefAN = (q) => prostgles_types_1.asName(makePref(q));
|
|
1137
|
+
makePref = (q) => !q.tableAlias ? q.table : `${q.tableAlias || ""}_${q.table}`, makePrefANON = (joinAlias, table) => (0, prostgles_types_1.asName)(!joinAlias ? table : `${joinAlias || ""}_${table}`), makePrefAN = (q) => (0, prostgles_types_1.asName)(makePref(q));
|
|
1066
1138
|
const indentLine = (numInd, str, indentStr = " ") => new Array(numInd).fill(indentStr).join("") + str;
|
|
1067
1139
|
const indStr = (numInd, str) => str.split("\n").map(s => indentLine(numInd, s)).join("\n");
|
|
1068
1140
|
const indjArr = (numInd, strArr, indentStr = " ") => strArr.map(str => indentLine(numInd, str));
|
|
1069
1141
|
const indJ = (numInd, strArr, separator = " \n ", indentStr = " ") => indjArr(numInd, strArr, indentStr).join(separator);
|
|
1070
1142
|
const selectArrComma = (strArr) => strArr.map((s, i, arr) => s + (i < arr.length - 1 ? " , " : " "));
|
|
1071
|
-
const prefJCAN = (q, str) => prostgles_types_1.asName(`${q.tableAlias || q.table}_${PREF}_${str}`);
|
|
1143
|
+
const prefJCAN = (q, str) => (0, prostgles_types_1.asName)(`${q.tableAlias || q.table}_${PREF}_${str}`);
|
|
1072
1144
|
// const indent = (a, b) => a;
|
|
1073
1145
|
const joinTables = (q1, q2) => {
|
|
1074
1146
|
const joinInfo = _this.getJoins(q1.table, q2.table, q2.$path, true);
|
|
1075
1147
|
const paths = joinInfo.paths;
|
|
1076
|
-
return
|
|
1148
|
+
return paths.flatMap(({ table, on }, i) => {
|
|
1077
1149
|
const getColName = (col, q) => {
|
|
1078
1150
|
if (table === q.table) {
|
|
1079
|
-
const colFromSelect = q.select.find(s => s.getQuery() === prostgles_types_1.asName(col));
|
|
1151
|
+
const colFromSelect = q.select.find(s => s.getQuery() === (0, prostgles_types_1.asName)(col));
|
|
1080
1152
|
if (!colFromSelect) {
|
|
1081
1153
|
console.error(`${col} column might be missing in user publish `);
|
|
1082
1154
|
throw `Could not find join column (${col}) in allowe select. Some join tables and columns might be invalid/dissallowed`;
|
|
@@ -1098,7 +1170,7 @@ function makeQuery(_this, q, depth = 0, joinFields = [], selectParams) {
|
|
|
1098
1170
|
const prevAlias = i === 0 ? makePrefAN(q1) : makePrefANON(q2.tableAlias, prevTable);
|
|
1099
1171
|
// If root then prev table is aliased from root query. Alias from join otherwise
|
|
1100
1172
|
let iQ = [
|
|
1101
|
-
prostgles_types_1.asName(table) + ` ${thisAlias}`
|
|
1173
|
+
(0, prostgles_types_1.asName)(table) + ` ${thisAlias}`
|
|
1102
1174
|
];
|
|
1103
1175
|
/* If target table then add filters, options, etc */
|
|
1104
1176
|
if (i === paths.length - 1) {
|
|
@@ -1112,10 +1184,10 @@ function makeQuery(_this, q, depth = 0, joinFields = [], selectParams) {
|
|
|
1112
1184
|
const targetSelect = q2.select.filter(s => s.selected).map(s => {
|
|
1113
1185
|
/* Rename aggs to avoid collision with join cols */
|
|
1114
1186
|
if (s.type === "aggregation")
|
|
1115
|
-
return prostgles_types_1.asName(`agg_${s.alias}`) + " AS " + prostgles_types_1.asName(s.alias);
|
|
1116
|
-
return prostgles_types_1.asName(s.alias);
|
|
1117
|
-
}).concat(q2.joins
|
|
1118
|
-
const _iiQ = makeQuery(_this, q2, depth + 1, on.map(([c1, c2]) => prostgles_types_1.asName(c2)), selectParams);
|
|
1187
|
+
return (0, prostgles_types_1.asName)(`agg_${s.alias}`) + " AS " + (0, prostgles_types_1.asName)(s.alias);
|
|
1188
|
+
return (0, prostgles_types_1.asName)(s.alias);
|
|
1189
|
+
}).concat(q2.joins?.map(j => (0, prostgles_types_1.asName)(j.table)) ?? []).join(", ");
|
|
1190
|
+
const _iiQ = makeQuery(_this, q2, depth + 1, on.map(([c1, c2]) => (0, prostgles_types_1.asName)(c2)), selectParams);
|
|
1119
1191
|
// const iiQ = flat(_iiQ.split("\n")); // prettify for debugging
|
|
1120
1192
|
// console.log(_iiQ)
|
|
1121
1193
|
const iiQ = [_iiQ];
|
|
@@ -1128,7 +1200,7 @@ function makeQuery(_this, q, depth = 0, joinFields = [], selectParams) {
|
|
|
1128
1200
|
`row_to_json((select x from (SELECT ${targetSelect}) as x)) AS ${prefJCAN(q2, `json`)}`,
|
|
1129
1201
|
`FROM (`,
|
|
1130
1202
|
...iiQ,
|
|
1131
|
-
`) ${prostgles_types_1.asName(q2.table)} `
|
|
1203
|
+
`) ${(0, prostgles_types_1.asName)(q2.table)} `
|
|
1132
1204
|
]),
|
|
1133
1205
|
`) ${thisAlias}`
|
|
1134
1206
|
];
|
|
@@ -1136,10 +1208,10 @@ function makeQuery(_this, q, depth = 0, joinFields = [], selectParams) {
|
|
|
1136
1208
|
let jres = [
|
|
1137
1209
|
`${q2.isLeftJoin ? "LEFT" : "INNER"} JOIN `,
|
|
1138
1210
|
...iQ,
|
|
1139
|
-
`ON ${on.map(([c1, c2]) => `${prevAlias}.${prostgles_types_1.asName(getPrevColName(c1))} = ${thisAlias}.${prostgles_types_1.asName(getThisColName(c2))} `).join(" AND ")}`
|
|
1211
|
+
`ON ${on.map(([c1, c2]) => `${prevAlias}.${(0, prostgles_types_1.asName)(getPrevColName(c1))} = ${thisAlias}.${(0, prostgles_types_1.asName)(getThisColName(c2))} `).join(" AND ")}`
|
|
1140
1212
|
];
|
|
1141
1213
|
return jres;
|
|
1142
|
-
})
|
|
1214
|
+
});
|
|
1143
1215
|
};
|
|
1144
1216
|
const getGroupBy = (rootSelectItems, groupByItems) => {
|
|
1145
1217
|
if (groupByItems.length) {
|
|
@@ -1161,7 +1233,7 @@ function makeQuery(_this, q, depth = 0, joinFields = [], selectParams) {
|
|
|
1161
1233
|
let groupBy = "";
|
|
1162
1234
|
const rootSelectItems = q.select.filter(s => joinFields.includes(s.getQuery()) || s.selected);
|
|
1163
1235
|
/* If aggs exist need to set groupBy add joinFields into select */
|
|
1164
|
-
if (aggs.length ||
|
|
1236
|
+
if (aggs.length || selectParams?.groupBy) {
|
|
1165
1237
|
// const missingFields = joinFields.filter(jf => !q.select.find(s => s.type === "column" && s.alias === jf));
|
|
1166
1238
|
// if(depth && missingFields.length){
|
|
1167
1239
|
// // select = Array.from(new Set(missingFields.concat(select)));
|
|
@@ -1183,11 +1255,11 @@ function makeQuery(_this, q, depth = 0, joinFields = [], selectParams) {
|
|
|
1183
1255
|
// return s.getQuery() + ((s.type !== "column")? (" AS " + s.alias) : "")
|
|
1184
1256
|
if (s.type === "aggregation") {
|
|
1185
1257
|
/* Rename aggs to avoid collision with join cols */
|
|
1186
|
-
return s.getQuery() + " AS " + prostgles_types_1.asName((depth ? "agg_" : "") + s.alias);
|
|
1258
|
+
return s.getQuery() + " AS " + (0, prostgles_types_1.asName)((depth ? "agg_" : "") + s.alias);
|
|
1187
1259
|
}
|
|
1188
|
-
return s.getQuery() + " AS " + prostgles_types_1.asName(s.alias);
|
|
1260
|
+
return s.getQuery() + " AS " + (0, prostgles_types_1.asName)(s.alias);
|
|
1189
1261
|
}).join(", "),
|
|
1190
|
-
`FROM ${prostgles_types_1.asName(q.table)} `,
|
|
1262
|
+
`FROM ${(0, prostgles_types_1.asName)(q.table)} `,
|
|
1191
1263
|
q.where,
|
|
1192
1264
|
groupBy //!aggs.length? "" : `GROUP BY ${nonAggs.map(sf => asName(sf.alias)).join(", ")}`,
|
|
1193
1265
|
,
|
|
@@ -1214,8 +1286,8 @@ function makeQuery(_this, q, depth = 0, joinFields = [], selectParams) {
|
|
|
1214
1286
|
// console.log({ aggs, nonAggs, joins: q.joins })
|
|
1215
1287
|
// rootGroupBy = getGroupBy(rootSelectItems, depth? rootSelectItems : nonAggs) + (aggs?.length? "" : ", ctid")
|
|
1216
1288
|
rootGroupBy = `GROUP BY ${(depth ?
|
|
1217
|
-
q.allFields.map(f => prostgles_types_1.asName(f)) :
|
|
1218
|
-
nonAggs.map(s => s.type === "function" ? s.getQuery() : prostgles_types_1.asName(s.alias))).concat((aggs && aggs.length) ?
|
|
1289
|
+
q.allFields.map(f => (0, prostgles_types_1.asName)(f)) :
|
|
1290
|
+
nonAggs.map(s => s.type === "function" ? s.getQuery() : (0, prostgles_types_1.asName)(s.alias))).concat((aggs && aggs.length) ?
|
|
1219
1291
|
[] :
|
|
1220
1292
|
[`ctid`]).filter(s => s).join(", ")} `;
|
|
1221
1293
|
}
|
|
@@ -1224,10 +1296,10 @@ function makeQuery(_this, q, depth = 0, joinFields = [], selectParams) {
|
|
|
1224
1296
|
" \n",
|
|
1225
1297
|
`-- 0. [joined root] `,
|
|
1226
1298
|
"SELECT ",
|
|
1227
|
-
...selectArrComma(rootSelectItems.map(s => s.getQuery() + " AS " + prostgles_types_1.asName(s.alias)).concat(joins.map((j, i) => {
|
|
1299
|
+
...selectArrComma(rootSelectItems.map(s => s.getQuery() + " AS " + (0, prostgles_types_1.asName)(s.alias)).concat(joins.map((j, i) => {
|
|
1228
1300
|
/** Apply LIMIT to joined items */
|
|
1229
1301
|
const jsq = `json_agg(${prefJCAN(j, `json`)}::jsonb ORDER BY ${prefJCAN(j, `rowid_sorted`)}) FILTER (WHERE ${prefJCAN(j, `limit`)} <= ${j.limit} AND ${prefJCAN(j, `dupes_rowid`)} = 1 AND ${prefJCAN(j, `json`)} IS NOT NULL)`;
|
|
1230
|
-
const resAlias = prostgles_types_1.asName(j.tableAlias || j.table);
|
|
1302
|
+
const resAlias = (0, prostgles_types_1.asName)(j.tableAlias || j.table);
|
|
1231
1303
|
// If limit = 1 then return a single json object (first one)
|
|
1232
1304
|
return (j.limit === 1 ? `${jsq}->0 ` : `COALESCE(${jsq}, '[]') `) + ` AS ${resAlias}`;
|
|
1233
1305
|
}))),
|
|
@@ -1244,18 +1316,18 @@ function makeQuery(_this, q, depth = 0, joinFields = [], selectParams) {
|
|
|
1244
1316
|
"-- 2. [source full select + ctid to group by] ",
|
|
1245
1317
|
"SELECT ",
|
|
1246
1318
|
...selectArrComma(q.allFields.concat(["ctid"])
|
|
1247
|
-
.map(field => `${makePrefAN(q)}.${prostgles_types_1.asName(field)} `)
|
|
1319
|
+
.map(field => `${makePrefAN(q)}.${(0, prostgles_types_1.asName)(field)} `)
|
|
1248
1320
|
.concat(joins.map((j, i) => makePrefAN(j) + "." + prefJCAN(j, `json`) + ", " + makePrefAN(j) + "." + prefJCAN(j, `rowid_sorted`)).concat(joins.map(j => `row_number() over(partition by ${makePrefAN(j)}.${prefJCAN(j, `rowid_sorted`)}, ${makePrefAN(q)}.ctid ) AS ${prefJCAN(j, `dupes_rowid`)}`)))),
|
|
1249
1321
|
`FROM ( `,
|
|
1250
1322
|
...indjArr(depth + 1, [
|
|
1251
1323
|
"-- 3. [source table] ",
|
|
1252
1324
|
"SELECT ",
|
|
1253
1325
|
"*, row_number() over() as ctid ",
|
|
1254
|
-
`FROM ${prostgles_types_1.asName(q.table)} `,
|
|
1326
|
+
`FROM ${(0, prostgles_types_1.asName)(q.table)} `,
|
|
1255
1327
|
`${q.where} `
|
|
1256
1328
|
]),
|
|
1257
1329
|
`) ${makePrefAN(q)} `,
|
|
1258
|
-
...
|
|
1330
|
+
...joins.flatMap((j, i) => joinTables(q, j))
|
|
1259
1331
|
]),
|
|
1260
1332
|
") t1"
|
|
1261
1333
|
]),
|