prostgles-server 4.2.549 → 4.2.551
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/DboBuilder/TableHandler/TableHandler.d.ts +14 -6
- package/dist/DboBuilder/TableHandler/TableHandler.d.ts.map +1 -1
- package/dist/DboBuilder/TableHandler/TableHandler.js +9 -9
- package/dist/DboBuilder/TableHandler/TableHandler.js.map +1 -1
- package/dist/DboBuilder/TableHandler/delete.d.ts +1 -1
- package/dist/DboBuilder/TableHandler/delete.d.ts.map +1 -1
- package/dist/DboBuilder/TableHandler/delete.js +56 -13
- package/dist/DboBuilder/TableHandler/delete.js.map +1 -1
- package/dist/DboBuilder/TableHandler/executeHooksCheckAndPostValidation.d.ts +21 -0
- package/dist/DboBuilder/TableHandler/executeHooksCheckAndPostValidation.d.ts.map +1 -0
- package/dist/DboBuilder/TableHandler/executeHooksCheckAndPostValidation.js +69 -0
- package/dist/DboBuilder/TableHandler/executeHooksCheckAndPostValidation.js.map +1 -0
- package/dist/DboBuilder/TableHandler/insert/insert.d.ts.map +1 -1
- package/dist/DboBuilder/TableHandler/insert/insert.js +30 -17
- package/dist/DboBuilder/TableHandler/insert/insert.js.map +1 -1
- package/dist/DboBuilder/TableHandler/insert/insertNestedRecords.d.ts.map +1 -1
- package/dist/DboBuilder/TableHandler/insert/insertNestedRecords.js +1 -2
- package/dist/DboBuilder/TableHandler/insert/insertNestedRecords.js.map +1 -1
- package/dist/DboBuilder/TableHandler/onDeleteFromFileTable.d.ts.map +1 -1
- package/dist/DboBuilder/TableHandler/onDeleteFromFileTable.js +2 -1
- package/dist/DboBuilder/TableHandler/onDeleteFromFileTable.js.map +1 -1
- package/dist/DboBuilder/TableHandler/runInsertUpdateQuery.d.ts.map +1 -1
- package/dist/DboBuilder/TableHandler/runInsertUpdateQuery.js +24 -95
- 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 +21 -13
- package/dist/DboBuilder/TableHandler/update.js.map +1 -1
- package/dist/DboBuilder/TableHandler/updateBatch.d.ts.map +1 -1
- package/dist/DboBuilder/TableHandler/updateBatch.js +13 -1
- package/dist/DboBuilder/TableHandler/updateBatch.js.map +1 -1
- package/dist/DboBuilder/TableHandler/upsert.js +2 -2
- package/dist/DboBuilder/TableHandler/upsert.js.map +1 -1
- package/dist/DboBuilder/ViewHandler/ViewHandler.d.ts +6 -1
- package/dist/DboBuilder/ViewHandler/ViewHandler.d.ts.map +1 -1
- package/dist/DboBuilder/ViewHandler/ViewHandler.js +11 -5
- package/dist/DboBuilder/ViewHandler/ViewHandler.js.map +1 -1
- package/dist/DboBuilder/ViewHandler/count.d.ts.map +1 -1
- package/dist/DboBuilder/ViewHandler/count.js +20 -8
- package/dist/DboBuilder/ViewHandler/count.js.map +1 -1
- package/dist/DboBuilder/ViewHandler/find.d.ts +0 -12
- package/dist/DboBuilder/ViewHandler/find.d.ts.map +1 -1
- package/dist/DboBuilder/ViewHandler/find.js +28 -75
- package/dist/DboBuilder/ViewHandler/find.js.map +1 -1
- package/dist/DboBuilder/ViewHandler/getReturnTypeQuery.d.ts +14 -0
- package/dist/DboBuilder/ViewHandler/getReturnTypeQuery.d.ts.map +1 -0
- package/dist/DboBuilder/ViewHandler/getReturnTypeQuery.js +32 -0
- package/dist/DboBuilder/ViewHandler/getReturnTypeQuery.js.map +1 -0
- package/dist/DboBuilder/ViewHandler/size.d.ts.map +1 -1
- package/dist/DboBuilder/ViewHandler/size.js +23 -8
- package/dist/DboBuilder/ViewHandler/size.js.map +1 -1
- package/dist/DboBuilder/dboBuilderUtils.d.ts +1 -1
- package/dist/DboBuilder/dboBuilderUtils.d.ts.map +1 -1
- package/dist/DboBuilder/dboBuilderUtils.js +2 -2
- package/dist/DboBuilder/dboBuilderUtils.js.map +1 -1
- package/dist/DboBuilder/parseUpdateRules.js +1 -1
- package/dist/DboBuilder/parseUpdateRules.js.map +1 -1
- package/dist/PublishParser/publishTypesAndUtils.d.ts +34 -1
- package/dist/PublishParser/publishTypesAndUtils.d.ts.map +1 -1
- package/dist/PublishParser/publishTypesAndUtils.js.map +1 -1
- package/dist/TableConfig/TableConfig.d.ts +3 -15
- package/dist/TableConfig/TableConfig.d.ts.map +1 -1
- package/dist/TableConfig/TableConfig.js.map +1 -1
- package/dist/TableConfig/getCreateSchemaQueries.d.ts +4 -28
- package/dist/TableConfig/getCreateSchemaQueries.d.ts.map +1 -1
- package/dist/TableConfig/getTableConfigSchemaQueries.d.ts +4 -28
- package/dist/TableConfig/getTableConfigSchemaQueries.d.ts.map +1 -1
- package/dist/utils/utils.d.ts +1 -0
- package/dist/utils/utils.d.ts.map +1 -1
- package/dist/utils/utils.js +3 -1
- package/dist/utils/utils.js.map +1 -1
- package/lib/DboBuilder/TableHandler/TableHandler.ts +17 -10
- package/lib/DboBuilder/TableHandler/delete.ts +83 -15
- package/lib/DboBuilder/TableHandler/executeHooksCheckAndPostValidation.ts +88 -0
- package/lib/DboBuilder/TableHandler/insert/insert.ts +36 -17
- package/lib/DboBuilder/TableHandler/insert/insertNestedRecords.ts +1 -2
- package/lib/DboBuilder/TableHandler/onDeleteFromFileTable.ts +7 -5
- package/lib/DboBuilder/TableHandler/runInsertUpdateQuery.ts +34 -110
- package/lib/DboBuilder/TableHandler/update.ts +28 -13
- package/lib/DboBuilder/TableHandler/updateBatch.ts +15 -2
- package/lib/DboBuilder/TableHandler/upsert.ts +2 -2
- package/lib/DboBuilder/ViewHandler/ViewHandler.ts +13 -5
- package/lib/DboBuilder/ViewHandler/count.ts +24 -9
- package/lib/DboBuilder/ViewHandler/find.ts +36 -96
- package/lib/DboBuilder/ViewHandler/getReturnTypeQuery.ts +50 -0
- package/lib/DboBuilder/ViewHandler/size.ts +26 -12
- package/lib/DboBuilder/dboBuilderUtils.ts +1 -1
- package/lib/DboBuilder/parseUpdateRules.ts +1 -1
- package/lib/PublishParser/publishTypesAndUtils.ts +42 -1
- package/lib/TableConfig/TableConfig.ts +4 -18
- package/lib/utils/utils.ts +2 -0
- package/package.json +1 -1
|
@@ -2,9 +2,10 @@ import type { AnyObject, FieldFilter, InsertParams, UpdateParams } from "prostgl
|
|
|
2
2
|
import { asName } from "prostgles-types";
|
|
3
3
|
import type { InsertRule, UpdateRule } from "../../PublishParser/PublishParser";
|
|
4
4
|
import type { LocalParams } from "../DboBuilder";
|
|
5
|
-
import {
|
|
5
|
+
import { rejectWithPGClientError, withUserRLS } from "../DboBuilder";
|
|
6
6
|
import type { TableHandler } from "./TableHandler";
|
|
7
7
|
import { getSelectItemQuery } from "./TableHandler";
|
|
8
|
+
import { executeHooksCheckAndPostValidation } from "./executeHooksCheckAndPostValidation";
|
|
8
9
|
|
|
9
10
|
type RunInsertUpdateQueryArgs = {
|
|
10
11
|
tableHandler: TableHandler;
|
|
@@ -71,7 +72,12 @@ export const runInsertUpdateQuery = async (args: RunInsertUpdateQueryArgs) => {
|
|
|
71
72
|
RETURNING *
|
|
72
73
|
)
|
|
73
74
|
SELECT
|
|
74
|
-
count(*) as row_count,
|
|
75
|
+
count(*) as row_count,
|
|
76
|
+
EXISTS (
|
|
77
|
+
SELECT *
|
|
78
|
+
FROM ${escapedTableName}
|
|
79
|
+
${checkCondition}
|
|
80
|
+
) AS failed_check,
|
|
75
81
|
(
|
|
76
82
|
SELECT json_agg(item)
|
|
77
83
|
FROM (
|
|
@@ -86,127 +92,47 @@ export const runInsertUpdateQuery = async (args: RunInsertUpdateQueryArgs) => {
|
|
|
86
92
|
FROM ${escapedTableName}
|
|
87
93
|
WHERE ${hasReturning ? "TRUE" : "FALSE"}
|
|
88
94
|
) item
|
|
89
|
-
) as modified_returning
|
|
90
|
-
(
|
|
91
|
-
SELECT json_agg(item)
|
|
92
|
-
FROM (
|
|
93
|
-
SELECT *
|
|
94
|
-
FROM ${escapedTableName}
|
|
95
|
-
${checkCondition}
|
|
96
|
-
LIMIT 5
|
|
97
|
-
) item
|
|
98
|
-
) AS failed_check
|
|
95
|
+
) as modified_returning
|
|
99
96
|
FROM ${escapedTableName}
|
|
100
97
|
`;
|
|
101
98
|
|
|
102
99
|
const allowedFieldKeys = tableHandler.parseFieldFilter(fields);
|
|
103
|
-
let result: {
|
|
104
|
-
row_count: number | null;
|
|
105
|
-
modified: AnyObject[] | null;
|
|
106
|
-
failed_check: AnyObject[] | null;
|
|
107
|
-
modified_returning: AnyObject[] | null;
|
|
108
|
-
};
|
|
109
100
|
|
|
110
101
|
const queryType = "one";
|
|
111
102
|
|
|
112
|
-
const tx =
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
.
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
localParams,
|
|
130
|
-
view: tableHandler,
|
|
131
|
-
allowedKeys: allowedFieldKeys,
|
|
132
|
-
prostgles: tableHandler.dboBuilder.prostgles,
|
|
133
|
-
}),
|
|
134
|
-
);
|
|
135
|
-
}
|
|
103
|
+
const tx = tableHandler.getTransaction(localParams)?.t;
|
|
104
|
+
const queryPromise: Promise<{
|
|
105
|
+
row_count: number | null;
|
|
106
|
+
modified: AnyObject[] | null;
|
|
107
|
+
failed_check: boolean | null;
|
|
108
|
+
modified_returning: AnyObject[] | null;
|
|
109
|
+
}> = tx ? tx[queryType](query) : tableHandler.db.tx((t) => t[queryType](query));
|
|
110
|
+
|
|
111
|
+
const result = await queryPromise.catch((err: unknown) =>
|
|
112
|
+
rejectWithPGClientError(err, {
|
|
113
|
+
type: "tableMethod",
|
|
114
|
+
localParams,
|
|
115
|
+
view: tableHandler,
|
|
116
|
+
allowedKeys: allowedFieldKeys,
|
|
117
|
+
prostgles: tableHandler.dboBuilder.prostgles,
|
|
118
|
+
}),
|
|
119
|
+
);
|
|
136
120
|
|
|
137
|
-
if (checkFilter && result.failed_check
|
|
121
|
+
if (checkFilter && result.failed_check) {
|
|
138
122
|
throw new Error(
|
|
139
123
|
`Insert ${name} records failed the check condition: ${JSON.stringify(checkFilter, null, 2)}`,
|
|
140
124
|
);
|
|
141
125
|
}
|
|
142
126
|
|
|
143
127
|
const rows = result.modified ?? [];
|
|
144
|
-
const finalDBtx = tableHandler.getFinalDBtx(localParams);
|
|
145
|
-
const { postValidate } = rule ?? {};
|
|
146
|
-
const hooks = tableHandler.getHooksAndChecks(
|
|
147
|
-
command === "insert" ? { name: command, rule } : { name: command, rule },
|
|
148
|
-
);
|
|
149
|
-
let changedFieldsSet = undefined as undefined | Set<string>;
|
|
150
|
-
const getChangedFieldsSet = () => {
|
|
151
|
-
changedFieldsSet ??= new Set<string>(
|
|
152
|
-
(isArray(data) ? data : [data]).map((row) => Object.keys(row)).flat(),
|
|
153
|
-
);
|
|
154
|
-
return changedFieldsSet;
|
|
155
|
-
};
|
|
156
|
-
const applicableHooks = hooks.filter((hook) => {
|
|
157
|
-
if (hook.type === "checkFilter") return;
|
|
158
|
-
if (hook.type === "postValidate") return true;
|
|
159
|
-
const { commands, changedFields } = hook;
|
|
160
|
-
return (
|
|
161
|
-
commands[command] &&
|
|
162
|
-
(!changedFields || changedFields.some((f) => getChangedFieldsSet().has(f)))
|
|
163
|
-
);
|
|
164
|
-
});
|
|
165
|
-
|
|
166
|
-
if (postValidate && !localParams) {
|
|
167
|
-
throw new Error("Unexpected: no localParams for postValidate");
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
if (applicableHooks.length) {
|
|
171
|
-
if (!finalDBtx) throw new Error("Unexpected: no dbTX for hooks/postValidate");
|
|
172
|
-
|
|
173
|
-
for (const row of rows) {
|
|
174
|
-
const commonParams = {
|
|
175
|
-
row: row,
|
|
176
|
-
tx: tx || tableHandler.db,
|
|
177
|
-
dbx: finalDBtx,
|
|
178
|
-
command,
|
|
179
|
-
data,
|
|
180
|
-
} as const;
|
|
181
|
-
for (const hook of applicableHooks) {
|
|
182
|
-
if (hook.type === "afterEach") {
|
|
183
|
-
await hook.validate({
|
|
184
|
-
...commonParams,
|
|
185
|
-
localParams,
|
|
186
|
-
});
|
|
187
|
-
} else if (hook.type === "postValidate") {
|
|
188
|
-
if (!localParams) throw new Error("Unexpected: no localParams for postValidate");
|
|
189
|
-
await hook.validate({
|
|
190
|
-
...commonParams,
|
|
191
|
-
localParams,
|
|
192
|
-
});
|
|
193
|
-
}
|
|
194
|
-
}
|
|
195
|
-
}
|
|
196
128
|
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
rows,
|
|
205
|
-
localParams,
|
|
206
|
-
});
|
|
207
|
-
}
|
|
208
|
-
}
|
|
209
|
-
}
|
|
129
|
+
await executeHooksCheckAndPostValidation({
|
|
130
|
+
tableHandler,
|
|
131
|
+
operation: command === "insert" ? { name: "insert", rule } : { name: "update", rule },
|
|
132
|
+
localParams,
|
|
133
|
+
rows,
|
|
134
|
+
data,
|
|
135
|
+
});
|
|
210
136
|
|
|
211
137
|
let returnMany = false;
|
|
212
138
|
if (args.command === "update") {
|
|
@@ -231,5 +157,3 @@ export const runInsertUpdateQuery = async (args: RunInsertUpdateQueryArgs) => {
|
|
|
231
157
|
|
|
232
158
|
return returnMany ? modified_returning : modified_returning?.[0];
|
|
233
159
|
};
|
|
234
|
-
|
|
235
|
-
const isArray = <T>(data: T): data is Extract<T, readonly unknown[]> => Array.isArray(data);
|
|
@@ -8,6 +8,7 @@ import { runInsertUpdateQuery } from "./runInsertUpdateQuery";
|
|
|
8
8
|
import type { TableHandler } from "./TableHandler";
|
|
9
9
|
import { updateFile } from "./updateFile";
|
|
10
10
|
import { getInsertTableRules } from "./insert/getInsertTableRules";
|
|
11
|
+
import { getReturnTypeQuery } from "../ViewHandler/getReturnTypeQuery";
|
|
11
12
|
|
|
12
13
|
export async function update(
|
|
13
14
|
this: TableHandler,
|
|
@@ -20,11 +21,10 @@ export async function update(
|
|
|
20
21
|
const ACTION = "update";
|
|
21
22
|
const start = Date.now();
|
|
22
23
|
try {
|
|
23
|
-
|
|
24
|
-
const finalDBtx = this.getFinalDBtx(localParams);
|
|
24
|
+
const transaction = this.getTransaction(localParams);
|
|
25
25
|
const wrapInTx = () =>
|
|
26
|
-
this.dboBuilder.getTX((
|
|
27
|
-
(
|
|
26
|
+
this.dboBuilder.getTX((th) =>
|
|
27
|
+
(th[this.name] as Partial<typeof this> | undefined)?.[ACTION]?.(
|
|
28
28
|
filter,
|
|
29
29
|
_newData,
|
|
30
30
|
params,
|
|
@@ -33,7 +33,7 @@ export async function update(
|
|
|
33
33
|
),
|
|
34
34
|
);
|
|
35
35
|
const rule = tableRules?.[ACTION];
|
|
36
|
-
if (this.shouldWrapInTx({ name: ACTION, rule }, localParams)) {
|
|
36
|
+
if (this.shouldWrapInTx({ name: ACTION, rule }, localParams).shouldWrap) {
|
|
37
37
|
return wrapInTx();
|
|
38
38
|
}
|
|
39
39
|
|
|
@@ -60,7 +60,6 @@ export async function update(
|
|
|
60
60
|
const { fields, validateRow, forcedData, returningFields, forcedFilter, filterFields } =
|
|
61
61
|
parsedRules;
|
|
62
62
|
const { removeDisallowedFields = false } = params || {};
|
|
63
|
-
const { returnQuery = false } = localParams ?? {};
|
|
64
63
|
|
|
65
64
|
if (params) {
|
|
66
65
|
const good_paramsObj: Record<keyof UpdateParams, 1> = {
|
|
@@ -103,18 +102,24 @@ export async function update(
|
|
|
103
102
|
const nestedInserts = getReferenceColumnInserts(this, nData, true);
|
|
104
103
|
const nestedInsertsResultsObj: Record<string, any> = {};
|
|
105
104
|
if (nestedInserts.length) {
|
|
106
|
-
const updateCount = await this.count(
|
|
105
|
+
const updateCount = await this.count(
|
|
106
|
+
updateFilter.filter,
|
|
107
|
+
undefined,
|
|
108
|
+
undefined,
|
|
109
|
+
tableRules,
|
|
110
|
+
localParams,
|
|
111
|
+
);
|
|
107
112
|
if (+updateCount > 1) {
|
|
108
113
|
throw "Cannot do a nestedInsert from an update that targets more than 1 row";
|
|
109
114
|
}
|
|
110
|
-
if (!
|
|
115
|
+
if (!transaction) {
|
|
111
116
|
return wrapInTx();
|
|
112
117
|
}
|
|
113
118
|
await Promise.all(
|
|
114
119
|
nestedInserts.map(async (nestedInsert) => {
|
|
115
|
-
const
|
|
116
|
-
if (!
|
|
117
|
-
throw `nestedInsert
|
|
120
|
+
const nestedTableHandler = transaction.dbTX[nestedInsert.tableName];
|
|
121
|
+
if (!nestedTableHandler)
|
|
122
|
+
throw `nestedInsert TableHandler not found for ${nestedInsert.tableName}`;
|
|
118
123
|
const refTableRules =
|
|
119
124
|
!localParams ? undefined : (
|
|
120
125
|
await getInsertTableRules(
|
|
@@ -133,7 +138,7 @@ export async function update(
|
|
|
133
138
|
referencingColumn: nestedInsert.insertedFieldName,
|
|
134
139
|
},
|
|
135
140
|
};
|
|
136
|
-
const nestedInsertResult = (await
|
|
141
|
+
const nestedInsertResult = (await nestedTableHandler.insert(
|
|
137
142
|
nestedInsert.data,
|
|
138
143
|
{ returning: "*" },
|
|
139
144
|
undefined,
|
|
@@ -170,7 +175,17 @@ export async function update(
|
|
|
170
175
|
const queryWithoutUserRLS = query;
|
|
171
176
|
query = withUserRLS(localParams, query);
|
|
172
177
|
|
|
173
|
-
|
|
178
|
+
const queryToReturn = await getReturnTypeQuery({
|
|
179
|
+
handler: this,
|
|
180
|
+
localParams,
|
|
181
|
+
queryWithoutRLS: queryWithoutUserRLS,
|
|
182
|
+
queryWithRLS: query,
|
|
183
|
+
returnType: params?.returnType,
|
|
184
|
+
newQuery: undefined,
|
|
185
|
+
});
|
|
186
|
+
if (queryToReturn) {
|
|
187
|
+
return queryToReturn;
|
|
188
|
+
}
|
|
174
189
|
|
|
175
190
|
const result = await runInsertUpdateQuery({
|
|
176
191
|
tableHandler: this,
|
|
@@ -2,12 +2,13 @@ import type { AnyObject, UpdateParams } from "prostgles-types";
|
|
|
2
2
|
import type { ParsedTableRule } from "../../PublishParser/PublishParser";
|
|
3
3
|
import type { Filter, LocalParams } from "../DboBuilder";
|
|
4
4
|
import {
|
|
5
|
-
|
|
5
|
+
rejectWithPGClientError,
|
|
6
6
|
getErrorAsObject,
|
|
7
7
|
getSerializedClientErrorFromPGError,
|
|
8
8
|
withUserRLS,
|
|
9
9
|
} from "../DboBuilder";
|
|
10
10
|
import type { TableHandler } from "./TableHandler";
|
|
11
|
+
import { getReturnTypeQuery } from "../ViewHandler/getReturnTypeQuery";
|
|
11
12
|
|
|
12
13
|
export async function updateBatch(
|
|
13
14
|
this: TableHandler,
|
|
@@ -38,6 +39,18 @@ export async function updateBatch(
|
|
|
38
39
|
);
|
|
39
40
|
const queries = [withUserRLS(localParams, ""), ...updateQueries];
|
|
40
41
|
|
|
42
|
+
const queryToReturn = await getReturnTypeQuery({
|
|
43
|
+
handler: this,
|
|
44
|
+
localParams,
|
|
45
|
+
queryWithoutRLS: queries.slice(1).join(";\n"),
|
|
46
|
+
queryWithRLS: queries.join(";\n"),
|
|
47
|
+
returnType: params?.returnType,
|
|
48
|
+
newQuery: undefined,
|
|
49
|
+
});
|
|
50
|
+
if (queryToReturn) {
|
|
51
|
+
return queryToReturn as unknown[];
|
|
52
|
+
}
|
|
53
|
+
|
|
41
54
|
const t = localParams?.tx?.t ?? this.tx?.t;
|
|
42
55
|
if (t) {
|
|
43
56
|
const result = await t.none(queries.join(";\n"));
|
|
@@ -54,7 +67,7 @@ export async function updateBatch(
|
|
|
54
67
|
return t.none(queries.join(";\n"));
|
|
55
68
|
})
|
|
56
69
|
.catch((err) =>
|
|
57
|
-
|
|
70
|
+
rejectWithPGClientError(err, {
|
|
58
71
|
type: "tableMethod",
|
|
59
72
|
localParams,
|
|
60
73
|
view: this,
|
|
@@ -32,8 +32,8 @@ export const upsert = async function (
|
|
|
32
32
|
});
|
|
33
33
|
};
|
|
34
34
|
|
|
35
|
-
/* Do it within a transaction to ensure
|
|
36
|
-
if (!this.
|
|
35
|
+
/* Do it within a transaction to ensure consistency */
|
|
36
|
+
if (!this.getTransaction(localParams)) {
|
|
37
37
|
return this.dboBuilder.getTX((dbTX) => _upsert(dbTX[this.name] as TableHandler));
|
|
38
38
|
}
|
|
39
39
|
const result = await _upsert(this);
|
|
@@ -104,6 +104,14 @@ export class ViewHandler {
|
|
|
104
104
|
});
|
|
105
105
|
}
|
|
106
106
|
|
|
107
|
+
getFinalDBtx = (localParams: LocalParams | undefined) => {
|
|
108
|
+
return localParams?.tx?.dbTX ?? this.tx?.dbTX;
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
getTransaction = (localParams: LocalParams | undefined) => {
|
|
112
|
+
return localParams?.tx || this.tx;
|
|
113
|
+
};
|
|
114
|
+
|
|
107
115
|
_log = ({
|
|
108
116
|
command,
|
|
109
117
|
data,
|
|
@@ -298,20 +306,20 @@ export class ViewHandler {
|
|
|
298
306
|
|
|
299
307
|
intersectColumns(
|
|
300
308
|
allowedFields: FieldFilter,
|
|
301
|
-
|
|
309
|
+
disallowedFields: FieldFilter,
|
|
302
310
|
removeDisallowedFields = false,
|
|
303
311
|
): string[] {
|
|
304
312
|
let result: string[] = [];
|
|
305
313
|
if (allowedFields) {
|
|
306
314
|
result = this.parseFieldFilter(allowedFields);
|
|
307
315
|
}
|
|
308
|
-
if (
|
|
309
|
-
const
|
|
316
|
+
if (disallowedFields) {
|
|
317
|
+
const excludedFields = this.parseFieldFilter(disallowedFields);
|
|
310
318
|
|
|
311
319
|
if (!removeDisallowedFields) {
|
|
312
|
-
throw `
|
|
320
|
+
throw `disallowed/invalid field found for ${this.name}: `;
|
|
313
321
|
}
|
|
314
|
-
result = result.filter((key) => !
|
|
322
|
+
result = result.filter((key) => !excludedFields.includes(key));
|
|
315
323
|
}
|
|
316
324
|
|
|
317
325
|
return result;
|
|
@@ -7,6 +7,7 @@ import {
|
|
|
7
7
|
withUserRLS,
|
|
8
8
|
} from "../dboBuilderUtils";
|
|
9
9
|
import type { ViewHandler } from "./ViewHandler";
|
|
10
|
+
import { getReturnTypeQuery } from "./getReturnTypeQuery";
|
|
10
11
|
|
|
11
12
|
export async function count(
|
|
12
13
|
this: ViewHandler,
|
|
@@ -32,15 +33,29 @@ export async function count(
|
|
|
32
33
|
returnQuery: "noRLS",
|
|
33
34
|
bypassLimit: true,
|
|
34
35
|
})) as unknown as string;
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
findQuery
|
|
40
|
-
|
|
41
|
-
|
|
36
|
+
|
|
37
|
+
const queryWithoutUserRLS = `
|
|
38
|
+
SELECT COUNT(*)
|
|
39
|
+
FROM (
|
|
40
|
+
${findQuery}
|
|
41
|
+
) t
|
|
42
|
+
`;
|
|
43
|
+
const queryWithRLS = withUserRLS(localParams, queryWithoutUserRLS);
|
|
44
|
+
|
|
45
|
+
const queryToReturn = await getReturnTypeQuery({
|
|
46
|
+
handler: this,
|
|
47
|
+
localParams,
|
|
48
|
+
queryWithoutRLS: queryWithoutUserRLS,
|
|
49
|
+
queryWithRLS,
|
|
50
|
+
returnType: selectParams?.returnType,
|
|
51
|
+
newQuery: undefined,
|
|
52
|
+
});
|
|
53
|
+
if (queryToReturn) {
|
|
54
|
+
return queryToReturn as unknown[];
|
|
55
|
+
}
|
|
56
|
+
|
|
42
57
|
const handler = this.tx?.t ?? this.db;
|
|
43
|
-
return handler.one(
|
|
58
|
+
return handler.one(queryWithRLS).then(({ count }) => +count);
|
|
44
59
|
});
|
|
45
60
|
|
|
46
61
|
await this._log({
|
|
@@ -49,7 +64,7 @@ export async function count(
|
|
|
49
64
|
data: { filter },
|
|
50
65
|
duration: Date.now() - start,
|
|
51
66
|
});
|
|
52
|
-
return result;
|
|
67
|
+
return result as number;
|
|
53
68
|
} catch (e) {
|
|
54
69
|
await this._log({
|
|
55
70
|
command: "count",
|
|
@@ -1,18 +1,16 @@
|
|
|
1
|
-
import type { SelectParams } from "prostgles-types";
|
|
1
|
+
import type { AnyObject, SelectParams } from "prostgles-types";
|
|
2
2
|
import { isObject } from "prostgles-types";
|
|
3
3
|
import type { ParsedTableRule } from "../../PublishParser/PublishParser";
|
|
4
4
|
import type { Filter, LocalParams } from "../DboBuilder";
|
|
5
5
|
import {
|
|
6
|
-
getClientErrorFromPGError,
|
|
7
6
|
getErrorAsObject,
|
|
8
7
|
getSerializedClientErrorFromPGError,
|
|
8
|
+
rejectWithPGClientError,
|
|
9
9
|
withUserRLS,
|
|
10
10
|
} from "../DboBuilder";
|
|
11
11
|
import { getNewQuery } from "../QueryBuilder/getNewQuery";
|
|
12
12
|
import { getSelectQuery } from "../QueryBuilder/getSelectQuery";
|
|
13
|
-
import
|
|
14
|
-
import { canRunSQL } from "../runSql/runSQL";
|
|
15
|
-
import type { TableHandler } from "../TableHandler/TableHandler";
|
|
13
|
+
import { getReturnTypeQuery } from "./getReturnTypeQuery";
|
|
16
14
|
import type { ViewHandler } from "./ViewHandler";
|
|
17
15
|
|
|
18
16
|
export const find = async function (
|
|
@@ -111,36 +109,42 @@ export const find = async function (
|
|
|
111
109
|
);
|
|
112
110
|
|
|
113
111
|
const queryWithRLS = withUserRLS(localParams, queryWithoutRLS);
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
// await this.db.any(withUserRLS(localParams, "EXPLAIN " + queryWithRLS));
|
|
118
|
-
// return [];
|
|
119
|
-
// } catch (e) {
|
|
120
|
-
// console.error(e);
|
|
121
|
-
// throw `Internal error: publish config is not valid for publish.${this.name}.select `;
|
|
122
|
-
// }
|
|
123
|
-
// }
|
|
124
|
-
|
|
125
|
-
/** Used for subscribe */
|
|
126
|
-
if (localParams?.returnNewQuery) return newQuery as unknown as any;
|
|
127
|
-
if (localParams?.returnQuery) {
|
|
128
|
-
if (localParams.returnQuery === "where-condition") {
|
|
129
|
-
return newQuery.whereOpts.condition as any;
|
|
130
|
-
}
|
|
131
|
-
return (localParams.returnQuery === "noRLS" ?
|
|
132
|
-
queryWithoutRLS
|
|
133
|
-
: queryWithRLS) as unknown as any[];
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
const result = await runQueryReturnType({
|
|
112
|
+
const queryToReturn = await getReturnTypeQuery({
|
|
113
|
+
handler: this,
|
|
114
|
+
localParams,
|
|
137
115
|
queryWithoutRLS,
|
|
138
116
|
queryWithRLS,
|
|
139
117
|
returnType,
|
|
140
|
-
handler: this,
|
|
141
|
-
localParams,
|
|
142
118
|
newQuery,
|
|
143
119
|
});
|
|
120
|
+
if (queryToReturn) {
|
|
121
|
+
return queryToReturn as unknown[];
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
const query = queryWithRLS;
|
|
125
|
+
const isOneOrNone = returnType === "row" || returnType === "value";
|
|
126
|
+
const dbHandler = this.getTransaction(localParams)?.t ?? this.db;
|
|
127
|
+
const queryPromise =
|
|
128
|
+
isOneOrNone ?
|
|
129
|
+
dbHandler.oneOrNone<AnyObject>(query).then((data) => (data ? [data] : []))
|
|
130
|
+
: dbHandler.any<AnyObject>(query);
|
|
131
|
+
|
|
132
|
+
const parsedResult = await queryPromise
|
|
133
|
+
.then((rows) => {
|
|
134
|
+
if (returnType === "values" || returnType === "value") {
|
|
135
|
+
return rows.map((d) => Object.values(d)[0]);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
return rows;
|
|
139
|
+
})
|
|
140
|
+
.catch((err) =>
|
|
141
|
+
rejectWithPGClientError(err, {
|
|
142
|
+
type: "tableMethod",
|
|
143
|
+
localParams,
|
|
144
|
+
view: this,
|
|
145
|
+
prostgles: this.dboBuilder.prostgles,
|
|
146
|
+
}),
|
|
147
|
+
);
|
|
144
148
|
|
|
145
149
|
await this._log({
|
|
146
150
|
command,
|
|
@@ -148,7 +152,8 @@ export const find = async function (
|
|
|
148
152
|
data: { filter, selectParams },
|
|
149
153
|
duration: Date.now() - start,
|
|
150
154
|
});
|
|
151
|
-
|
|
155
|
+
|
|
156
|
+
return isOneOrNone ? parsedResult[0] : parsedResult;
|
|
152
157
|
} catch (e) {
|
|
153
158
|
await this._log({
|
|
154
159
|
command,
|
|
@@ -165,68 +170,3 @@ export const find = async function (
|
|
|
165
170
|
});
|
|
166
171
|
}
|
|
167
172
|
};
|
|
168
|
-
|
|
169
|
-
type RunQueryReturnTypeArgs = {
|
|
170
|
-
queryWithRLS: string;
|
|
171
|
-
queryWithoutRLS: string;
|
|
172
|
-
returnType: SelectParams["returnType"];
|
|
173
|
-
handler: ViewHandler | TableHandler;
|
|
174
|
-
localParams: LocalParams | undefined;
|
|
175
|
-
newQuery: NewQuery | undefined;
|
|
176
|
-
};
|
|
177
|
-
|
|
178
|
-
export const runQueryReturnType = async ({
|
|
179
|
-
newQuery,
|
|
180
|
-
handler,
|
|
181
|
-
localParams,
|
|
182
|
-
queryWithRLS,
|
|
183
|
-
queryWithoutRLS,
|
|
184
|
-
returnType,
|
|
185
|
-
}: RunQueryReturnTypeArgs) => {
|
|
186
|
-
const query = queryWithRLS;
|
|
187
|
-
const sqlTypes = ["statement", "statement-no-rls", "statement-where"] as const;
|
|
188
|
-
if (!returnType || returnType === "values") {
|
|
189
|
-
return handler.dbHandler
|
|
190
|
-
.any(query)
|
|
191
|
-
.then((data) => {
|
|
192
|
-
if (returnType === "values") {
|
|
193
|
-
return data.map((d) => Object.values(d)[0]);
|
|
194
|
-
}
|
|
195
|
-
return data;
|
|
196
|
-
})
|
|
197
|
-
.catch((err) =>
|
|
198
|
-
getClientErrorFromPGError(err, {
|
|
199
|
-
type: "tableMethod",
|
|
200
|
-
localParams,
|
|
201
|
-
view: handler,
|
|
202
|
-
prostgles: handler.dboBuilder.prostgles,
|
|
203
|
-
}),
|
|
204
|
-
);
|
|
205
|
-
} else if (sqlTypes.some((v) => v === returnType)) {
|
|
206
|
-
if (!(await canRunSQL(handler.dboBuilder.prostgles, localParams?.clientReq))) {
|
|
207
|
-
throw `Not allowed: { returnType: ${JSON.stringify(returnType)} } requires execute sql privileges `;
|
|
208
|
-
}
|
|
209
|
-
if (returnType === "statement-no-rls") {
|
|
210
|
-
return queryWithoutRLS as unknown;
|
|
211
|
-
}
|
|
212
|
-
if (returnType === "statement-where") {
|
|
213
|
-
if (!newQuery) throw `returnType ${returnType} not possible for this command type`;
|
|
214
|
-
return newQuery.whereOpts.condition as unknown;
|
|
215
|
-
}
|
|
216
|
-
return query as unknown as unknown[];
|
|
217
|
-
} else if (["row", "value"].includes(returnType)) {
|
|
218
|
-
return handler.dbHandler
|
|
219
|
-
.oneOrNone(query)
|
|
220
|
-
.then((data) => {
|
|
221
|
-
return data && returnType === "value" ? Object.values(data)[0] : data;
|
|
222
|
-
})
|
|
223
|
-
.catch((err) =>
|
|
224
|
-
getClientErrorFromPGError(err, {
|
|
225
|
-
type: "tableMethod",
|
|
226
|
-
localParams,
|
|
227
|
-
view: handler,
|
|
228
|
-
prostgles: handler.dboBuilder.prostgles,
|
|
229
|
-
}),
|
|
230
|
-
);
|
|
231
|
-
}
|
|
232
|
-
};
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import type { SelectParams } from "prostgles-types";
|
|
2
|
+
import type { LocalParams } from "../DboBuilder";
|
|
3
|
+
import type { NewQuery } from "../QueryBuilder/QueryBuilder";
|
|
4
|
+
import { canRunSQL } from "../runSql/runSQL";
|
|
5
|
+
import type { TableHandler } from "../TableHandler/TableHandler";
|
|
6
|
+
import type { ViewHandler } from "./ViewHandler";
|
|
7
|
+
|
|
8
|
+
const sqlTypes = ["statement", "statement-no-rls", "statement-where"] as const;
|
|
9
|
+
|
|
10
|
+
export const getReturnTypeQuery = async ({
|
|
11
|
+
handler,
|
|
12
|
+
returnType,
|
|
13
|
+
localParams,
|
|
14
|
+
queryWithRLS,
|
|
15
|
+
queryWithoutRLS,
|
|
16
|
+
newQuery,
|
|
17
|
+
}: {
|
|
18
|
+
handler: TableHandler | ViewHandler;
|
|
19
|
+
returnType: SelectParams["returnType"];
|
|
20
|
+
localParams: LocalParams | undefined;
|
|
21
|
+
queryWithRLS: string;
|
|
22
|
+
queryWithoutRLS: string;
|
|
23
|
+
newQuery: NewQuery | undefined;
|
|
24
|
+
}) => {
|
|
25
|
+
/** Used for subscribe */
|
|
26
|
+
if (localParams?.returnNewQuery) {
|
|
27
|
+
return newQuery;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
if (returnType === "statement-where" || localParams?.returnQuery === "where-condition") {
|
|
31
|
+
if (!newQuery) {
|
|
32
|
+
throw `returnType ${returnType} not possible for this command type`;
|
|
33
|
+
}
|
|
34
|
+
return newQuery.whereOpts.condition as unknown;
|
|
35
|
+
}
|
|
36
|
+
if (localParams?.returnQuery) {
|
|
37
|
+
return localParams.returnQuery === "noRLS" ? queryWithoutRLS : queryWithRLS;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
if (!sqlTypes.some((v) => v === returnType)) {
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
if (!(await canRunSQL(handler.dboBuilder.prostgles, localParams?.clientReq))) {
|
|
44
|
+
throw `Not allowed: { returnType: ${JSON.stringify(returnType)} } requires execute sql privileges `;
|
|
45
|
+
}
|
|
46
|
+
if (returnType === "statement-no-rls") {
|
|
47
|
+
return queryWithoutRLS as unknown;
|
|
48
|
+
}
|
|
49
|
+
return queryWithRLS as unknown as unknown[];
|
|
50
|
+
};
|