prostgles-server 4.2.623 → 4.2.625
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/debug/client-schema-types/DBGeneratedSchema.ts +13 -1
- package/dist/Audit/AuditTable.d.ts +2 -1
- package/dist/Audit/AuditTable.d.ts.map +1 -1
- package/dist/Audit/AuditTable.js +3 -2
- package/dist/Audit/AuditTable.js.map +1 -1
- package/dist/Audit/getAuditTableRules.d.ts +7 -0
- package/dist/Audit/getAuditTableRules.d.ts.map +1 -0
- package/dist/Audit/getAuditTableRules.js +191 -0
- package/dist/Audit/getAuditTableRules.js.map +1 -0
- package/dist/Audit/getAuditTriggerConfig.d.ts.map +1 -1
- package/dist/Audit/getAuditTriggerConfig.js +14 -1
- package/dist/Audit/getAuditTriggerConfig.js.map +1 -1
- package/dist/DBSchemaBuilder/getDBGeneratedSchema.d.ts.map +1 -1
- package/dist/DBSchemaBuilder/getDBGeneratedSchema.js +1 -2
- package/dist/DBSchemaBuilder/getDBGeneratedSchema.js.map +1 -1
- package/dist/DboBuilder/DboBuilder.js +1 -1
- package/dist/DboBuilder/DboBuilder.js.map +1 -1
- package/dist/DboBuilder/QueryBuilder/QueryBuilder.d.ts +10 -5
- package/dist/DboBuilder/QueryBuilder/QueryBuilder.d.ts.map +1 -1
- package/dist/DboBuilder/QueryBuilder/QueryBuilder.js +90 -71
- package/dist/DboBuilder/QueryBuilder/QueryBuilder.js.map +1 -1
- package/dist/DboBuilder/QueryBuilder/getJoinQuery.d.ts.map +1 -1
- package/dist/DboBuilder/QueryBuilder/getJoinQuery.js +3 -2
- package/dist/DboBuilder/QueryBuilder/getJoinQuery.js.map +1 -1
- package/dist/DboBuilder/QueryBuilder/getNewQuery.d.ts +2 -2
- package/dist/DboBuilder/QueryBuilder/getNewQuery.d.ts.map +1 -1
- package/dist/DboBuilder/QueryBuilder/getNewQuery.js +53 -116
- package/dist/DboBuilder/QueryBuilder/getNewQuery.js.map +1 -1
- package/dist/DboBuilder/QueryBuilder/getQuerySource.d.ts +18 -0
- package/dist/DboBuilder/QueryBuilder/getQuerySource.d.ts.map +1 -0
- package/dist/DboBuilder/QueryBuilder/getQuerySource.js +29 -0
- package/dist/DboBuilder/QueryBuilder/getQuerySource.js.map +1 -0
- package/dist/DboBuilder/QueryBuilder/getSelectQuery.d.ts.map +1 -1
- package/dist/DboBuilder/QueryBuilder/getSelectQuery.js +6 -2
- package/dist/DboBuilder/QueryBuilder/getSelectQuery.js.map +1 -1
- package/dist/DboBuilder/QueryBuilder/parseJoinSelect.d.ts +13 -0
- package/dist/DboBuilder/QueryBuilder/parseJoinSelect.d.ts.map +1 -0
- package/dist/DboBuilder/QueryBuilder/parseJoinSelect.js +57 -0
- package/dist/DboBuilder/QueryBuilder/parseJoinSelect.js.map +1 -0
- package/dist/DboBuilder/TableHandler/TableHandler.d.ts.map +1 -1
- package/dist/DboBuilder/TableHandler/TableHandler.js +2 -1
- package/dist/DboBuilder/TableHandler/TableHandler.js.map +1 -1
- package/dist/DboBuilder/TableHandler/delete.d.ts.map +1 -1
- package/dist/DboBuilder/TableHandler/delete.js +2 -1
- package/dist/DboBuilder/TableHandler/delete.js.map +1 -1
- package/dist/DboBuilder/TableHandler/runInsertUpdateQuery.d.ts.map +1 -1
- package/dist/DboBuilder/TableHandler/runInsertUpdateQuery.js +2 -1
- package/dist/DboBuilder/TableHandler/runInsertUpdateQuery.js.map +1 -1
- package/dist/DboBuilder/TableHandler/update.d.ts.map +1 -1
- package/dist/DboBuilder/TableHandler/update.js +2 -1
- package/dist/DboBuilder/TableHandler/update.js.map +1 -1
- package/dist/DboBuilder/ViewHandler/ViewHandler.d.ts +6 -16
- package/dist/DboBuilder/ViewHandler/ViewHandler.d.ts.map +1 -1
- package/dist/DboBuilder/ViewHandler/ViewHandler.js +2 -7
- package/dist/DboBuilder/ViewHandler/ViewHandler.js.map +1 -1
- package/dist/DboBuilder/ViewHandler/find.d.ts.map +1 -1
- package/dist/DboBuilder/ViewHandler/find.js +1 -1
- package/dist/DboBuilder/ViewHandler/find.js.map +1 -1
- package/dist/DboBuilder/ViewHandler/getExistsCondition.d.ts +1 -1
- package/dist/DboBuilder/ViewHandler/getExistsCondition.d.ts.map +1 -1
- package/dist/DboBuilder/ViewHandler/getExistsCondition.js +24 -13
- package/dist/DboBuilder/ViewHandler/getExistsCondition.js.map +1 -1
- package/dist/DboBuilder/ViewHandler/getTableJoinQuery.d.ts +4 -1
- package/dist/DboBuilder/ViewHandler/getTableJoinQuery.d.ts.map +1 -1
- package/dist/DboBuilder/ViewHandler/getTableJoinQuery.js +20 -14
- package/dist/DboBuilder/ViewHandler/getTableJoinQuery.js.map +1 -1
- package/dist/DboBuilder/ViewHandler/prepareWhere.d.ts +7 -3
- package/dist/DboBuilder/ViewHandler/prepareWhere.d.ts.map +1 -1
- package/dist/DboBuilder/ViewHandler/prepareWhere.js +30 -23
- package/dist/DboBuilder/ViewHandler/prepareWhere.js.map +1 -1
- package/dist/DboBuilder/getCondition.d.ts +2 -1
- package/dist/DboBuilder/getCondition.d.ts.map +1 -1
- package/dist/DboBuilder/getCondition.js +9 -8
- package/dist/DboBuilder/getCondition.js.map +1 -1
- package/dist/DboBuilder/getSubscribeRelatedTables.d.ts.map +1 -1
- package/dist/DboBuilder/getSubscribeRelatedTables.js +3 -2
- package/dist/DboBuilder/getSubscribeRelatedTables.js.map +1 -1
- package/dist/DboBuilder/parseUpdateRules.d.ts.map +1 -1
- package/dist/DboBuilder/parseUpdateRules.js +3 -2
- package/dist/DboBuilder/parseUpdateRules.js.map +1 -1
- package/dist/DboBuilder/schema/getTablesForSchemaPostgresSQL.d.ts +2 -2
- package/dist/Prostgles.d.ts.map +1 -1
- package/dist/Prostgles.js +2 -0
- package/dist/Prostgles.js.map +1 -1
- package/dist/ProstglesContext.spec.js +25 -0
- package/dist/ProstglesContext.spec.js.map +1 -1
- package/dist/PubSubManager/PubSubManager.d.ts +1 -1
- package/dist/PublishParser/PublishParser.d.ts +17 -8
- package/dist/PublishParser/PublishParser.d.ts.map +1 -1
- package/dist/PublishParser/PublishParser.js +59 -28
- package/dist/PublishParser/PublishParser.js.map +1 -1
- package/dist/PublishParser/applyScopeToTableRules.d.ts +0 -1
- package/dist/PublishParser/applyScopeToTableRules.d.ts.map +1 -1
- package/dist/PublishParser/applyScopeToTableRules.js +3 -7
- package/dist/PublishParser/applyScopeToTableRules.js.map +1 -1
- package/dist/PublishParser/getFileTableRules.d.ts +1 -1
- package/dist/PublishParser/getFileTableRules.d.ts.map +1 -1
- package/dist/PublishParser/getFileTableRules.js +52 -41
- package/dist/PublishParser/getFileTableRules.js.map +1 -1
- package/dist/PublishParser/getParsedPublishTable.d.ts +4 -0
- package/dist/PublishParser/getParsedPublishTable.d.ts.map +1 -0
- package/dist/PublishParser/{getTableRulesWithoutFileTable.js → getParsedPublishTable.js} +13 -7
- package/dist/PublishParser/getParsedPublishTable.js.map +1 -0
- package/dist/PublishParser/getPublishSchemas.d.ts +4 -0
- package/dist/PublishParser/getPublishSchemas.d.ts.map +1 -0
- package/dist/PublishParser/getPublishSchemas.js +42 -0
- package/dist/PublishParser/getPublishSchemas.js.map +1 -0
- package/dist/PublishParser/getPublishedObjectFromResult.d.ts +4 -0
- package/dist/PublishParser/getPublishedObjectFromResult.d.ts.map +1 -0
- package/dist/PublishParser/getPublishedObjectFromResult.js +77 -0
- package/dist/PublishParser/getPublishedObjectFromResult.js.map +1 -0
- package/dist/PublishParser/getPublishedTableNames.d.ts.map +1 -1
- package/dist/PublishParser/getPublishedTableNames.js +20 -1
- package/dist/PublishParser/getPublishedTableNames.js.map +1 -1
- package/dist/PublishParser/getSchemaFromPublish.d.ts.map +1 -1
- package/dist/PublishParser/getSchemaFromPublish.js +11 -5
- package/dist/PublishParser/getSchemaFromPublish.js.map +1 -1
- package/dist/PublishParser/publishTypesAndUtils.d.ts +28 -7
- package/dist/PublishParser/publishTypesAndUtils.d.ts.map +1 -1
- package/dist/PublishParser/publishTypesAndUtils.js +6 -1
- package/dist/PublishParser/publishTypesAndUtils.js.map +1 -1
- package/dist/PublishParser/validatePublishProfiles.d.ts +2 -2
- package/dist/PublishParser/validatePublishProfiles.d.ts.map +1 -1
- package/dist/PublishParser/validatePublishProfiles.js.map +1 -1
- package/dist/TableConfig/getColumnSQLDefinitionQuery.d.ts.map +1 -1
- package/dist/TableConfig/getColumnSQLDefinitionQuery.js +1 -2
- package/dist/TableConfig/getColumnSQLDefinitionQuery.js.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -1
- package/dist/index.js.map +1 -1
- package/dist/runClientRequest.d.ts.map +1 -1
- package/dist/runClientRequest.js +6 -1
- package/dist/runClientRequest.js.map +1 -1
- package/lib/Audit/AuditTable.ts +4 -3
- package/lib/Audit/getAuditTableRules.ts +288 -0
- package/lib/Audit/getAuditTriggerConfig.ts +14 -1
- package/lib/DBSchemaBuilder/getDBGeneratedSchema.ts +1 -2
- package/lib/DboBuilder/DboBuilder.ts +1 -1
- package/lib/DboBuilder/QueryBuilder/QueryBuilder.ts +118 -90
- package/lib/DboBuilder/QueryBuilder/getJoinQuery.ts +3 -2
- package/lib/DboBuilder/QueryBuilder/getNewQuery.ts +111 -194
- package/lib/DboBuilder/QueryBuilder/getQuerySource.ts +55 -0
- package/lib/DboBuilder/QueryBuilder/getSelectQuery.ts +8 -2
- package/lib/DboBuilder/QueryBuilder/parseJoinSelect.ts +73 -0
- package/lib/DboBuilder/TableHandler/TableHandler.ts +3 -6
- package/lib/DboBuilder/TableHandler/delete.ts +2 -1
- package/lib/DboBuilder/TableHandler/runInsertUpdateQuery.ts +2 -1
- package/lib/DboBuilder/TableHandler/update.ts +2 -1
- package/lib/DboBuilder/ViewHandler/ViewHandler.ts +6 -12
- package/lib/DboBuilder/ViewHandler/find.ts +0 -1
- package/lib/DboBuilder/ViewHandler/getExistsCondition.ts +35 -28
- package/lib/DboBuilder/ViewHandler/getTableJoinQuery.ts +22 -14
- package/lib/DboBuilder/ViewHandler/prepareWhere.ts +48 -27
- package/lib/DboBuilder/getCondition.ts +11 -10
- package/lib/DboBuilder/getSubscribeRelatedTables.ts +3 -2
- package/lib/DboBuilder/parseUpdateRules.ts +3 -2
- package/lib/Prostgles.ts +1 -0
- package/lib/ProstglesContext.spec.ts +30 -0
- package/lib/PublishParser/PublishParser.ts +108 -51
- package/lib/PublishParser/applyScopeToTableRules.ts +1 -7
- package/lib/PublishParser/getFileTableRules.ts +52 -45
- package/lib/PublishParser/{getTableRulesWithoutFileTable.ts → getParsedPublishTable.ts} +16 -12
- package/lib/PublishParser/getPublishSchemas.ts +49 -0
- package/lib/PublishParser/getPublishedObjectFromResult.ts +104 -0
- package/lib/PublishParser/getPublishedTableNames.ts +28 -1
- package/lib/PublishParser/getSchemaFromPublish.ts +9 -7
- package/lib/PublishParser/publishTypesAndUtils.ts +31 -11
- package/lib/PublishParser/validatePublishProfiles.ts +1 -1
- package/lib/TableConfig/getColumnSQLDefinitionQuery.ts +8 -2
- package/lib/index.ts +14 -1
- package/lib/runClientRequest.ts +4 -3
- package/package.json +1 -1
- package/dist/DBSchemaBuilder/getPublishSchemas.d.ts +0 -4
- package/dist/DBSchemaBuilder/getPublishSchemas.d.ts.map +0 -1
- package/dist/DBSchemaBuilder/getPublishSchemas.js +0 -34
- package/dist/DBSchemaBuilder/getPublishSchemas.js.map +0 -1
- package/dist/PublishParser/getTableRulesWithoutFileTable.d.ts +0 -6
- package/dist/PublishParser/getTableRulesWithoutFileTable.d.ts.map +0 -1
- package/dist/PublishParser/getTableRulesWithoutFileTable.js.map +0 -1
- package/lib/DBSchemaBuilder/getPublishSchemas.ts +0 -41
|
@@ -5,7 +5,6 @@
|
|
|
5
5
|
|
|
6
6
|
import type {
|
|
7
7
|
ColumnInfo,
|
|
8
|
-
JoinSelect,
|
|
9
8
|
PG_COLUMN_UDT_DATA_TYPE,
|
|
10
9
|
Select,
|
|
11
10
|
ValidatedColumnInfo,
|
|
@@ -13,12 +12,15 @@ import type {
|
|
|
13
12
|
import { getKeys, isEmpty, isObject, postgresToTsType } from "prostgles-types";
|
|
14
13
|
import type { PGIdentifier, SortItem } from "../DboBuilder";
|
|
15
14
|
|
|
15
|
+
import type { Awaitable } from "../../PublishParser/publishTypesAndUtils";
|
|
16
|
+
import { asNameAlias } from "../../utils/asNameAlias";
|
|
16
17
|
import type { ParsedJoinPath } from "../ViewHandler/parseJoinPath";
|
|
17
|
-
import type {
|
|
18
|
-
import type { FieldSpec, FunctionSpec } from "./Functions/Functions";
|
|
18
|
+
import type { WhereOptions } from "../ViewHandler/prepareWhere";
|
|
19
19
|
import { COMPUTED_FIELDS } from "./Functions/COMPUTED_FIELDS";
|
|
20
|
+
import type { FieldSpec, FunctionSpec } from "./Functions/Functions";
|
|
20
21
|
import { parseFunction } from "./Functions/parseFunction";
|
|
21
|
-
import {
|
|
22
|
+
import { parseJoinSelect, type ParsedJoin } from "./parseJoinSelect";
|
|
23
|
+
import type { QuerySource } from "./getQuerySource";
|
|
22
24
|
|
|
23
25
|
export type SelectItem = {
|
|
24
26
|
getFields: (args: any[]) => string[] | "*";
|
|
@@ -36,13 +38,9 @@ export type SelectItem = {
|
|
|
36
38
|
| {
|
|
37
39
|
type: "function" | "aggregation" | "joinedColumn" | "computed";
|
|
38
40
|
columnName?: undefined;
|
|
39
|
-
// args: any[];
|
|
40
|
-
// getFields: (args: any[]) => string[] | "*";
|
|
41
|
-
// columnNames: string[];
|
|
42
41
|
}
|
|
43
42
|
);
|
|
44
43
|
export type SelectItemValidated = Omit<SelectItem, "getFields"> & { fields: string[] };
|
|
45
|
-
export type WhereOptions = Awaited<ReturnType<ViewHandler["prepareWhere"]>>;
|
|
46
44
|
export type NewQueryRoot = {
|
|
47
45
|
/**
|
|
48
46
|
* All fields from the table will be in nested SELECT and GROUP BY to allow order/filter by fields not in select
|
|
@@ -55,6 +53,7 @@ export type NewQueryRoot = {
|
|
|
55
53
|
select: SelectItemValidated[];
|
|
56
54
|
|
|
57
55
|
table: PGIdentifier;
|
|
56
|
+
source: QuerySource;
|
|
58
57
|
where: string;
|
|
59
58
|
whereOpts: WhereOptions;
|
|
60
59
|
orderByItems: SortItem[];
|
|
@@ -148,7 +147,7 @@ export class SelectItemBuilder {
|
|
|
148
147
|
const allowedFields = isSelected ? allowedSelectedFields : allowedNonSelectedFields;
|
|
149
148
|
if (!allowedFields.includes(f)) {
|
|
150
149
|
throw (
|
|
151
|
-
"Field " + f + " is invalid or
|
|
150
|
+
"Field " + f + " is invalid or disallowed. \nAllowed fields: " + allowedFields.join(", ")
|
|
152
151
|
);
|
|
153
152
|
}
|
|
154
153
|
return f;
|
|
@@ -193,7 +192,7 @@ export class SelectItemBuilder {
|
|
|
193
192
|
});
|
|
194
193
|
};
|
|
195
194
|
|
|
196
|
-
addColumn = (fieldName: string, selected: boolean) => {
|
|
195
|
+
private addColumn = (fieldName: string, selected: boolean) => {
|
|
197
196
|
/* Check if computed col */
|
|
198
197
|
if (selected) {
|
|
199
198
|
const compCol = COMPUTED_FIELDS.find((cf) => cf.name === fieldName);
|
|
@@ -225,10 +224,19 @@ export class SelectItemBuilder {
|
|
|
225
224
|
});
|
|
226
225
|
};
|
|
227
226
|
|
|
228
|
-
|
|
227
|
+
parse = async (
|
|
229
228
|
userSelect: Select,
|
|
230
|
-
joinParse?: (key: string,
|
|
231
|
-
) => {
|
|
229
|
+
joinParse?: (key: string, parsedJoin: ParsedJoin) => Awaitable<void>,
|
|
230
|
+
): Promise<void> => {
|
|
231
|
+
if (userSelect === "") {
|
|
232
|
+
return;
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
if (userSelect === "*") {
|
|
236
|
+
this.allowedFields.map((key) => this.addColumn(key, true));
|
|
237
|
+
return;
|
|
238
|
+
}
|
|
239
|
+
|
|
232
240
|
/* [col1, col2, col3] */
|
|
233
241
|
if (Array.isArray(userSelect)) {
|
|
234
242
|
if (userSelect.find((key) => typeof (key as unknown) !== "string")) {
|
|
@@ -236,90 +244,110 @@ export class SelectItemBuilder {
|
|
|
236
244
|
}
|
|
237
245
|
|
|
238
246
|
userSelect.map((key) => this.addColumn(key, true));
|
|
247
|
+
return;
|
|
248
|
+
}
|
|
239
249
|
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
this.allowedFields
|
|
257
|
-
.filter((f) => !selectKeys.includes(f))
|
|
258
|
-
.map((key) => this.addColumn(key, true));
|
|
259
|
-
} else {
|
|
260
|
-
await Promise.all(
|
|
261
|
-
selectKeys.map(async (key) => {
|
|
262
|
-
const val: unknown = userSelect[key as keyof typeof userSelect];
|
|
263
|
-
const throwErr = (extraErr = "") => {
|
|
264
|
-
console.trace(extraErr);
|
|
265
|
-
throw "Unexpected select -> " + JSON.stringify({ [key]: val }) + "\n" + extraErr;
|
|
266
|
-
};
|
|
267
|
-
|
|
268
|
-
/* Included fields */
|
|
269
|
-
if ([1, true].includes(val as number | boolean)) {
|
|
270
|
-
if (key === "*") {
|
|
271
|
-
this.allowedFields.map((key) => this.addColumn(key, true));
|
|
272
|
-
} else {
|
|
273
|
-
this.addColumn(key, true);
|
|
274
|
-
}
|
|
250
|
+
if (!isObject(userSelect)) {
|
|
251
|
+
throw "Unexpected select -> " + JSON.stringify(userSelect);
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
if (isEmpty(userSelect)) {
|
|
255
|
+
throw "Unexpected empty object select";
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
const selectKeys = Object.keys(userSelect),
|
|
259
|
+
selectValues = Object.values(userSelect);
|
|
260
|
+
|
|
261
|
+
/* Cannot include and exclude at the same time */
|
|
262
|
+
if (selectValues.filter((v) => [0, false].includes(v as number)).length) {
|
|
263
|
+
if (selectValues.filter((v) => ![0, false].includes(v as number)).length) {
|
|
264
|
+
throw "\nCannot include and exclude fields at the same time";
|
|
265
|
+
}
|
|
275
266
|
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
267
|
+
/* Exclude only */
|
|
268
|
+
this.allowedFields
|
|
269
|
+
.filter((f) => !selectKeys.includes(f))
|
|
270
|
+
.map((key) => this.addColumn(key, true));
|
|
271
|
+
} else {
|
|
272
|
+
await Promise.all(
|
|
273
|
+
selectKeys.map(async (key) => {
|
|
274
|
+
const val: unknown = userSelect[key as keyof typeof userSelect];
|
|
275
|
+
const throwErr: (message: string) => never = (message) => {
|
|
276
|
+
console.trace(message);
|
|
277
|
+
throw "Unexpected select -> " + JSON.stringify({ [key]: val }) + "\n" + message;
|
|
278
|
+
};
|
|
279
|
+
|
|
280
|
+
/* Included fields */
|
|
281
|
+
if ([1, true].includes(val as number | boolean)) {
|
|
282
|
+
if (key === "*") {
|
|
283
|
+
this.allowedFields.map((key) => this.addColumn(key, true));
|
|
284
|
+
} else {
|
|
285
|
+
this.addColumn(key, true);
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
/* Aggregations and functions */
|
|
289
|
+
} else if (typeof val === "string" || isObject(val)) {
|
|
290
|
+
/* Function shorthand notation
|
|
279
291
|
{ id: "$max" } === { id: { $max: ["id"] } } === SELECT MAX(id) AS id
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
}
|
|
297
|
-
funcName = val;
|
|
298
|
-
args = [key];
|
|
299
|
-
|
|
300
|
-
/** Function full notation { $funcName: ["colName", ...args] } */
|
|
301
|
-
} else {
|
|
302
|
-
({ funcName, args } = parseFunctionObject(val));
|
|
292
|
+
*/
|
|
293
|
+
if (
|
|
294
|
+
(typeof val === "string" && val !== "*") ||
|
|
295
|
+
(isObject(val) &&
|
|
296
|
+
Object.keys(val).length === 1 &&
|
|
297
|
+
Array.isArray(Object.values(val)[0]))
|
|
298
|
+
) {
|
|
299
|
+
let funcName: string | undefined, args: any[] | undefined;
|
|
300
|
+
if (typeof val === "string") {
|
|
301
|
+
/* Shorthand notation -> it is expected that the key is the column name used as the only argument */
|
|
302
|
+
try {
|
|
303
|
+
this.checkField(key, true);
|
|
304
|
+
} catch {
|
|
305
|
+
throwErr(
|
|
306
|
+
` Shorthand function notation error: the specified column ( ${key} ) is invalid or disallowed. \n Use correct column name or full aliased function notation, e.g.: -> { alias: { $func_name: ["column_name"] } } `,
|
|
307
|
+
);
|
|
303
308
|
}
|
|
309
|
+
funcName = val;
|
|
310
|
+
args = [key];
|
|
304
311
|
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
/* Join */
|
|
312
|
+
/** Function full notation { $funcName: ["colName", ...args] } */
|
|
308
313
|
} else {
|
|
309
|
-
|
|
310
|
-
throw "Joins disallowed";
|
|
311
|
-
}
|
|
312
|
-
await joinParse(key, val as JoinSelect, throwErr);
|
|
314
|
+
({ funcName, args } = parseFunctionObject(val));
|
|
313
315
|
}
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
316
|
+
|
|
317
|
+
this.addFunction(funcName, args, key);
|
|
318
|
+
|
|
319
|
+
/* Join */
|
|
320
|
+
} else {
|
|
321
|
+
if (!joinParse) {
|
|
322
|
+
throw "Joins disallowed";
|
|
323
|
+
}
|
|
324
|
+
const joinSelect = val;
|
|
325
|
+
|
|
326
|
+
const parsedJoin = parseJoinSelect(joinSelect);
|
|
327
|
+
|
|
328
|
+
if (typeof parsedJoin === "string") {
|
|
329
|
+
throwErr(parsedJoin);
|
|
330
|
+
}
|
|
331
|
+
await joinParse(key, parsedJoin);
|
|
332
|
+
}
|
|
333
|
+
} else throwErr("Invalid select value");
|
|
334
|
+
}),
|
|
335
|
+
);
|
|
323
336
|
}
|
|
337
|
+
|
|
338
|
+
if (!joinParse) return;
|
|
339
|
+
/**
|
|
340
|
+
* Is this still needed?!!!
|
|
341
|
+
* Add non selected columns
|
|
342
|
+
* This ensures all fields are available for orderBy in case of nested select
|
|
343
|
+
* */
|
|
344
|
+
Array.from(new Set([...this.allowedFields, ...this.allowedOrderByFields])).map((columnName) => {
|
|
345
|
+
if (!this.select.find((s) => s.alias === columnName && s.type === "column")) {
|
|
346
|
+
this.addColumn(columnName, false);
|
|
347
|
+
}
|
|
348
|
+
});
|
|
324
349
|
};
|
|
350
|
+
|
|
351
|
+
parseUserSelect = (userSelect: Select) => this.parse(userSelect);
|
|
352
|
+
parseUserSelectWithJoins = this.parse;
|
|
325
353
|
}
|
|
@@ -255,6 +255,7 @@ const getInnerJoinQuery = ({
|
|
|
255
255
|
|
|
256
256
|
const isFirst = !i;
|
|
257
257
|
if (isFirst) {
|
|
258
|
+
const tableExpression = isLast ? q2.source.expression : table.name;
|
|
258
259
|
return [
|
|
259
260
|
`SELECT `,
|
|
260
261
|
` /* Join fields + select */`,
|
|
@@ -262,13 +263,13 @@ const getInnerJoinQuery = ({
|
|
|
262
263
|
rootSelectItems.map((s) => s.query),
|
|
263
264
|
{ appendCommas: true },
|
|
264
265
|
),
|
|
265
|
-
`FROM ${
|
|
266
|
+
`FROM ${tableExpression} ${table.alias}`,
|
|
266
267
|
...targetQueryExtraQueries,
|
|
267
268
|
];
|
|
268
269
|
}
|
|
269
270
|
|
|
270
271
|
return [
|
|
271
|
-
`INNER JOIN ${table.name} ${table.alias}`,
|
|
272
|
+
`INNER JOIN ${isLast ? q2.source.expression : table.name} ${table.alias}`,
|
|
272
273
|
`ON ${getJoinOnCondition({
|
|
273
274
|
on: path.on,
|
|
274
275
|
leftAlias: prevTable.alias,
|
|
@@ -1,255 +1,172 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
|
|
3
|
-
JoinPath,
|
|
4
|
-
JoinSelect,
|
|
5
|
-
RawJoinPath,
|
|
6
|
-
SelectParams,
|
|
7
|
-
SimpleJoinSelect,
|
|
8
|
-
} from "prostgles-types";
|
|
9
|
-
import { asName, getKeys, includes, isEmpty, omitKeys } from "prostgles-types";
|
|
1
|
+
import type { SelectParams } from "prostgles-types";
|
|
2
|
+
import { asName, isEmpty, omitKeys } from "prostgles-types";
|
|
10
3
|
import type { ParsedTableRule } from "../../PublishParser/PublishParser";
|
|
11
4
|
import type { Filter, LocalParams, PGIdentifier, ValidatedTableRules } from "../DboBuilder";
|
|
12
5
|
import type { ViewHandler } from "../ViewHandler/ViewHandler";
|
|
13
6
|
import { parseJoinPath } from "../ViewHandler/parseJoinPath";
|
|
14
7
|
import { prepareSortItems } from "../ViewHandler/prepareSortItems";
|
|
15
|
-
import type
|
|
8
|
+
import { prepareWhere, type PrepareWhereParams } from "../ViewHandler/prepareWhere";
|
|
16
9
|
import { COMPUTED_FIELDS } from "./Functions/COMPUTED_FIELDS";
|
|
17
10
|
import { FUNCTIONS } from "./Functions/Functions";
|
|
18
11
|
import type { NewQuery, NewQueryJoin } from "./QueryBuilder";
|
|
19
12
|
import { SelectItemBuilder } from "./QueryBuilder";
|
|
13
|
+
import { ROOT_TABLE_ALIAS } from "./getSelectQuery";
|
|
20
14
|
|
|
21
|
-
const
|
|
22
|
-
|
|
23
|
-
$condition: 1,
|
|
24
|
-
filter: 1,
|
|
25
|
-
having: 1,
|
|
26
|
-
limit: 1,
|
|
27
|
-
offset: 1,
|
|
28
|
-
orderBy: 1,
|
|
29
|
-
select: 1,
|
|
30
|
-
} satisfies Record<keyof Omit<DetailedJoinSelect, (typeof JOIN_KEYS)[number]>, 1>);
|
|
31
|
-
|
|
32
|
-
type ParsedJoin =
|
|
33
|
-
| {
|
|
34
|
-
type: "detailed";
|
|
35
|
-
params: DetailedJoinSelect & {
|
|
36
|
-
table: DetailedJoinSelect["$leftJoin"];
|
|
37
|
-
path: RawJoinPath;
|
|
38
|
-
};
|
|
39
|
-
}
|
|
40
|
-
| { type: "simple"; params: SimpleJoinSelect }
|
|
41
|
-
| { type?: undefined; error: string };
|
|
42
|
-
|
|
43
|
-
const parseJoinSelect = (joinParams: JoinSelect): ParsedJoin => {
|
|
44
|
-
if (!(joinParams as string)) {
|
|
45
|
-
return {
|
|
46
|
-
error: "Empty join params",
|
|
47
|
-
};
|
|
48
|
-
}
|
|
49
|
-
if (typeof joinParams === "string") {
|
|
50
|
-
if ((joinParams as string) !== "*") {
|
|
51
|
-
throw "Join select can be * or { field: 1 }";
|
|
52
|
-
}
|
|
53
|
-
return {
|
|
54
|
-
type: "simple",
|
|
55
|
-
params: joinParams,
|
|
56
|
-
};
|
|
57
|
-
}
|
|
58
|
-
const [joinKey, ...otherKeys] = getKeys(joinParams).filter((k) => includes(JOIN_KEYS, k));
|
|
59
|
-
if (otherKeys.length) {
|
|
60
|
-
return {
|
|
61
|
-
error: "Cannot specify more than one join type ( $innerJoin OR $leftJoin )",
|
|
62
|
-
};
|
|
63
|
-
} else if (joinKey) {
|
|
64
|
-
/* Full option join { field_name: db.innerJoin.table_name(filter, select) } */
|
|
65
|
-
const invalidParams = Object.keys(joinParams).filter(
|
|
66
|
-
(k) => !includes([...JOIN_PARAM_KEYS, ...JOIN_KEYS], k),
|
|
67
|
-
);
|
|
68
|
-
if (invalidParams.length) {
|
|
69
|
-
throw "Invalid join params: " + invalidParams.join(", ");
|
|
70
|
-
}
|
|
71
|
-
const path = joinParams[joinKey] as string | JoinPath[];
|
|
72
|
-
if (Array.isArray(path) && !path.length) {
|
|
73
|
-
throw `Cannot have an empty join path/tableName ${joinKey}`;
|
|
74
|
-
}
|
|
75
|
-
return {
|
|
76
|
-
type: "detailed",
|
|
77
|
-
params: {
|
|
78
|
-
...(joinParams as DetailedJoinSelect),
|
|
79
|
-
path,
|
|
80
|
-
table: typeof path === "string" ? path : path.at(-1)!.table,
|
|
81
|
-
},
|
|
82
|
-
};
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
return {
|
|
86
|
-
type: "simple",
|
|
87
|
-
params: joinParams as SimpleJoinSelect,
|
|
88
|
-
};
|
|
89
|
-
};
|
|
90
|
-
|
|
91
|
-
export async function getNewQuery(
|
|
92
|
-
_this: ViewHandler,
|
|
15
|
+
export const getNewQuery = async (
|
|
16
|
+
viewHandler: ViewHandler,
|
|
93
17
|
filter: Filter,
|
|
94
18
|
selectParams: SelectParams & { joinExpressionAlias?: PGIdentifier } = {},
|
|
95
|
-
param3_unused = null,
|
|
96
19
|
tableRules: ParsedTableRule | undefined,
|
|
97
20
|
localParams: LocalParams | undefined,
|
|
98
|
-
): Promise<NewQuery> {
|
|
99
|
-
const { columns } =
|
|
21
|
+
): Promise<NewQuery> => {
|
|
22
|
+
const { columns } = viewHandler;
|
|
100
23
|
|
|
101
24
|
if (localParams?.isRemoteRequest && !tableRules?.select?.fields) {
|
|
102
|
-
throw `INTERNAL ERROR: publish.${
|
|
25
|
+
throw `INTERNAL ERROR: publish.${viewHandler.name}.select.fields rule missing`;
|
|
103
26
|
}
|
|
104
27
|
|
|
105
28
|
const allowedOrderByFields =
|
|
106
29
|
!tableRules ?
|
|
107
|
-
|
|
108
|
-
:
|
|
30
|
+
viewHandler.column_names.slice(0)
|
|
31
|
+
: viewHandler.parseFieldFilter(tableRules.select?.orderByFields ?? tableRules.select?.fields);
|
|
109
32
|
const allowedSelectFields =
|
|
110
|
-
!tableRules ?
|
|
33
|
+
!tableRules ?
|
|
34
|
+
viewHandler.column_names.slice(0)
|
|
35
|
+
: viewHandler.parseFieldFilter(tableRules.select?.fields);
|
|
111
36
|
|
|
112
37
|
const joinQueries: NewQueryJoin[] = [];
|
|
113
38
|
|
|
114
|
-
const { select: userSelect = "*" } = selectParams
|
|
115
|
-
sBuilder = new SelectItemBuilder({
|
|
116
|
-
allowedFields: allowedSelectFields,
|
|
117
|
-
allowedOrderByFields,
|
|
118
|
-
computedFields: COMPUTED_FIELDS,
|
|
119
|
-
isView: _this.isView,
|
|
120
|
-
functions: FUNCTIONS,
|
|
121
|
-
allFields: _this.column_names.slice(0),
|
|
122
|
-
columns,
|
|
123
|
-
});
|
|
124
|
-
|
|
125
|
-
await sBuilder.parseUserSelect(userSelect, async (joinColumnName, _joinParams, throwErr) => {
|
|
126
|
-
const j_selectParams: SelectParams = {};
|
|
127
|
-
let j_filter: Filter = {},
|
|
128
|
-
j_isLeftJoin = true;
|
|
39
|
+
const { select: userSelect = "*" } = selectParams;
|
|
129
40
|
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
rootTable: _this.name,
|
|
140
|
-
viewHandler: _this,
|
|
141
|
-
allowMultiOrJoin: true,
|
|
142
|
-
addShortestJoinIfMissing: true,
|
|
143
|
-
});
|
|
144
|
-
|
|
145
|
-
if (parsedJoin.params === "*") {
|
|
146
|
-
j_selectParams.select = "*";
|
|
147
|
-
} else if (parsedJoin.type === "detailed") {
|
|
148
|
-
const joinParams = parsedJoin.params;
|
|
149
|
-
|
|
150
|
-
j_isLeftJoin = !!joinParams.$leftJoin;
|
|
151
|
-
|
|
152
|
-
j_selectParams.select = joinParams.select || "*";
|
|
153
|
-
j_filter = joinParams.filter || {};
|
|
154
|
-
j_selectParams.limit = joinParams.limit;
|
|
155
|
-
j_selectParams.offset = joinParams.offset;
|
|
156
|
-
j_selectParams.orderBy = joinParams.orderBy;
|
|
157
|
-
j_selectParams.having = joinParams.having;
|
|
158
|
-
} else {
|
|
159
|
-
j_selectParams.select = parsedJoin.params;
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
const joinTableName =
|
|
163
|
-
parsedJoin.type === "simple" ? joinColumnName
|
|
164
|
-
: typeof j_path === "string" ? j_path
|
|
165
|
-
: j_path.at(-1)?.table;
|
|
166
|
-
if (!joinTableName) {
|
|
167
|
-
throw "jTable missing";
|
|
168
|
-
}
|
|
169
|
-
const joinTableHandler = _this.dboBuilder.dbo[joinTableName] as ViewHandler | undefined;
|
|
170
|
-
if (!joinTableHandler) {
|
|
171
|
-
throw `Joined table ${JSON.stringify(joinTableName)} is disallowed or inexistent \nOr you forgot to put the function arguments into an array`;
|
|
172
|
-
}
|
|
41
|
+
const selectItemBuilder = new SelectItemBuilder({
|
|
42
|
+
allowedFields: allowedSelectFields,
|
|
43
|
+
allowedOrderByFields,
|
|
44
|
+
computedFields: COMPUTED_FIELDS,
|
|
45
|
+
isView: viewHandler.isView,
|
|
46
|
+
functions: FUNCTIONS,
|
|
47
|
+
allFields: viewHandler.column_names.slice(0),
|
|
48
|
+
columns,
|
|
49
|
+
});
|
|
173
50
|
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
51
|
+
await selectItemBuilder.parseUserSelectWithJoins(
|
|
52
|
+
userSelect,
|
|
53
|
+
async (joinColumnName, parsedJoin) => {
|
|
54
|
+
const j_selectParams: SelectParams = {};
|
|
55
|
+
let j_filter: Filter = {},
|
|
56
|
+
j_isLeftJoin = true;
|
|
57
|
+
|
|
58
|
+
const joinExpressionAlias = { raw: joinColumnName, escaped: asName(joinColumnName) };
|
|
59
|
+
const j_path = parseJoinPath({
|
|
60
|
+
rawPath: parsedJoin.type === "simple" ? joinColumnName : parsedJoin.params.path,
|
|
61
|
+
rootTable: viewHandler.name,
|
|
62
|
+
viewHandler: viewHandler,
|
|
63
|
+
allowMultiOrJoin: true,
|
|
64
|
+
addShortestJoinIfMissing: true,
|
|
65
|
+
});
|
|
187
66
|
|
|
188
|
-
|
|
189
|
-
|
|
67
|
+
if (parsedJoin.params === "*") {
|
|
68
|
+
j_selectParams.select = "*";
|
|
69
|
+
} else if (parsedJoin.type === "detailed") {
|
|
70
|
+
const joinParams = parsedJoin.params;
|
|
71
|
+
|
|
72
|
+
j_isLeftJoin = !!joinParams.$leftJoin;
|
|
73
|
+
|
|
74
|
+
j_filter = joinParams.filter || {};
|
|
75
|
+
j_selectParams.select = joinParams.select || "*";
|
|
76
|
+
j_selectParams.limit = joinParams.limit;
|
|
77
|
+
j_selectParams.offset = joinParams.offset;
|
|
78
|
+
j_selectParams.orderBy = joinParams.orderBy;
|
|
79
|
+
j_selectParams.having = joinParams.having;
|
|
80
|
+
} else {
|
|
81
|
+
j_selectParams.select = parsedJoin.params;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
const joinTableName =
|
|
85
|
+
parsedJoin.type === "simple" ? joinColumnName
|
|
86
|
+
: typeof j_path === "string" ? j_path
|
|
87
|
+
: j_path.at(-1)?.table;
|
|
88
|
+
if (!joinTableName) {
|
|
89
|
+
throw "jTable missing";
|
|
90
|
+
}
|
|
91
|
+
const joinTableHandler = viewHandler.dboBuilder.dboMap.get(joinTableName);
|
|
92
|
+
if (!joinTableHandler) {
|
|
93
|
+
throw `Joined table ${JSON.stringify(joinTableName)} is disallowed or inexistent \nOr you forgot to put the function arguments into an array`;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
let joinTableRules: ParsedTableRule | undefined;
|
|
97
|
+
let isLocal = true;
|
|
98
|
+
if (localParams && localParams.clientReq) {
|
|
99
|
+
isLocal = false;
|
|
100
|
+
joinTableRules = await viewHandler.dboBuilder.publishParser?.getValidatedRequestRuleWusr(
|
|
101
|
+
{
|
|
102
|
+
tableName: joinTableName,
|
|
103
|
+
command: "find",
|
|
104
|
+
clientReq: localParams.clientReq,
|
|
105
|
+
},
|
|
106
|
+
localParams.scope,
|
|
107
|
+
);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
const isAllowedAccessToTable = isLocal || joinTableRules?.select;
|
|
111
|
+
if (!isAllowedAccessToTable) {
|
|
112
|
+
throw `Join select for ${JSON.stringify(joinTableName)} is invalid or not allowed`;
|
|
113
|
+
}
|
|
190
114
|
const joinQuery: NewQuery = await getNewQuery(
|
|
191
115
|
joinTableHandler,
|
|
192
116
|
j_filter,
|
|
193
117
|
{ ...j_selectParams, joinExpressionAlias },
|
|
194
|
-
param3_unused,
|
|
195
118
|
joinTableRules,
|
|
196
119
|
localParams,
|
|
197
120
|
);
|
|
198
121
|
joinQuery.isLeftJoin = j_isLeftJoin;
|
|
199
|
-
joinQuery.tableAlias = joinExpressionAlias;
|
|
200
122
|
joinQueries.push({
|
|
201
123
|
...joinQuery,
|
|
202
124
|
joinPath: j_path,
|
|
203
125
|
joinAlias: joinQuery.tableAlias ?? joinQuery.table,
|
|
204
126
|
});
|
|
205
|
-
}
|
|
206
|
-
|
|
127
|
+
},
|
|
128
|
+
);
|
|
207
129
|
|
|
208
|
-
|
|
209
|
-
* Is this still needed?!!!
|
|
210
|
-
* Add non selected columns
|
|
211
|
-
* This ensures all fields are available for orderBy in case of nested select
|
|
212
|
-
* */
|
|
213
|
-
Array.from(new Set([...allowedSelectFields, ...allowedOrderByFields])).map((key) => {
|
|
214
|
-
if (!sBuilder.select.find((s) => s.alias === key && s.type === "column")) {
|
|
215
|
-
sBuilder.addColumn(key, false);
|
|
216
|
-
}
|
|
217
|
-
});
|
|
218
|
-
|
|
219
|
-
const select = sBuilder.select;
|
|
130
|
+
const select = selectItemBuilder.select;
|
|
220
131
|
|
|
221
|
-
const tableAlias = selectParams.joinExpressionAlias;
|
|
222
132
|
const commonWhereParams: PrepareWhereParams = {
|
|
223
133
|
filter,
|
|
224
134
|
select,
|
|
225
135
|
forcedFilter: tableRules?.select?.forcedFilter,
|
|
226
136
|
filterFields: tableRules?.select?.filterFields,
|
|
227
|
-
tableAlias,
|
|
137
|
+
tableAlias: selectParams.joinExpressionAlias,
|
|
228
138
|
localParams,
|
|
229
139
|
tableRule: tableRules,
|
|
230
140
|
isHaving: false,
|
|
141
|
+
selectParams,
|
|
231
142
|
};
|
|
232
|
-
const filterOpts = await
|
|
143
|
+
const filterOpts = await prepareWhere(viewHandler, {
|
|
233
144
|
...commonWhereParams,
|
|
234
145
|
isHaving: false,
|
|
235
146
|
});
|
|
147
|
+
const { source } = filterOpts;
|
|
236
148
|
const havingOpts =
|
|
237
|
-
|
|
238
|
-
await
|
|
239
|
-
...omitKeys(commonWhereParams, ["forcedFilter"]),
|
|
149
|
+
isEmpty(selectParams.having) ? undefined : (
|
|
150
|
+
await prepareWhere(viewHandler, {
|
|
151
|
+
...omitKeys(commonWhereParams, ["forcedFilter", "selectParams"]),
|
|
240
152
|
filter: selectParams.having,
|
|
153
|
+
tableAlias:
|
|
154
|
+
selectParams.joinExpressionAlias ? source.alias : (
|
|
155
|
+
{ raw: ROOT_TABLE_ALIAS, escaped: ROOT_TABLE_ALIAS }
|
|
156
|
+
),
|
|
241
157
|
isHaving: true,
|
|
242
158
|
})
|
|
243
|
-
|
|
244
|
-
const
|
|
245
|
-
const validatedRules = _this.getValidatedRules(tableRules, localParams);
|
|
159
|
+
);
|
|
160
|
+
const validatedRules = viewHandler.getValidatedRules(tableRules, localParams);
|
|
246
161
|
|
|
247
|
-
const
|
|
248
|
-
allFields:
|
|
162
|
+
const newQuery: NewQuery = {
|
|
163
|
+
allFields: viewHandler.column_names.slice(0),
|
|
249
164
|
select,
|
|
250
|
-
table: { raw:
|
|
165
|
+
table: { raw: viewHandler.name, escaped: viewHandler.name },
|
|
166
|
+
tableAlias: selectParams.joinExpressionAlias,
|
|
167
|
+
source,
|
|
251
168
|
joins: joinQueries,
|
|
252
|
-
where,
|
|
169
|
+
where: filterOpts.where,
|
|
253
170
|
whereOpts: filterOpts,
|
|
254
171
|
having: havingOpts?.condition ?? "",
|
|
255
172
|
isLeftJoin: false,
|
|
@@ -264,12 +181,12 @@ export async function getNewQuery(
|
|
|
264
181
|
offset: prepareOffsetQuery(selectParams.offset),
|
|
265
182
|
};
|
|
266
183
|
|
|
267
|
-
if (
|
|
184
|
+
if (newQuery.select.some((s) => s.type === "aggregation") && newQuery.joins?.length) {
|
|
268
185
|
throw new Error(`Root query aggregation AND nested joins not allowed`);
|
|
269
186
|
}
|
|
270
187
|
|
|
271
|
-
return
|
|
272
|
-
}
|
|
188
|
+
return newQuery;
|
|
189
|
+
};
|
|
273
190
|
|
|
274
191
|
const prepareOffsetQuery = (offset?: number) => {
|
|
275
192
|
if (Number.isInteger(offset)) {
|