prostgles-server 4.2.603 → 4.2.605
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/Auth/utils/getSessionUser.d.ts +4 -0
- package/dist/Auth/utils/getSessionUser.d.ts.map +1 -0
- package/dist/Auth/utils/getSessionUser.js +17 -0
- package/dist/Auth/utils/getSessionUser.js.map +1 -0
- package/dist/Auth/utils/getSessionUser.spec.d.ts +2 -0
- package/dist/Auth/utils/getSessionUser.spec.d.ts.map +1 -0
- package/dist/Auth/utils/getSessionUser.spec.js +42 -0
- package/dist/Auth/utils/getSessionUser.spec.js.map +1 -0
- package/dist/DBSchemaBuilder/getColumnTypescriptDefinition.js +2 -2
- package/dist/DBSchemaBuilder/getColumnTypescriptDefinition.js.map +1 -1
- package/dist/DboBuilder/TableHandler/TableHandler.d.ts.map +1 -1
- package/dist/DboBuilder/TableHandler/TableHandler.js +4 -0
- 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 +4 -1
- package/dist/DboBuilder/TableHandler/delete.js.map +1 -1
- package/dist/DboBuilder/TableHandler/insert/insert.js +1 -1
- package/dist/DboBuilder/TableHandler/insert/insert.js.map +1 -1
- package/dist/DboBuilder/TableHandler/runInsertUpdateQuery.js +1 -1
- package/dist/DboBuilder/TableHandler/runInsertUpdateQuery.js.map +1 -1
- package/dist/DboBuilder/TableHandler/update.js +1 -1
- 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 +4 -1
- package/dist/DboBuilder/TableHandler/updateBatch.js.map +1 -1
- package/dist/DboBuilder/ViewHandler/count.d.ts.map +1 -1
- package/dist/DboBuilder/ViewHandler/count.js +1 -1
- package/dist/DboBuilder/ViewHandler/count.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/size.d.ts.map +1 -1
- package/dist/DboBuilder/ViewHandler/size.js +1 -1
- package/dist/DboBuilder/ViewHandler/size.js.map +1 -1
- package/dist/DboBuilder/ViewHandler/subscribe.d.ts.map +1 -1
- package/dist/DboBuilder/ViewHandler/subscribe.js +1 -0
- package/dist/DboBuilder/ViewHandler/subscribe.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 +7 -2
- package/dist/DboBuilder/dboBuilderUtils.js.map +1 -1
- package/dist/PubSubManager/PubSubManager.d.ts +5 -2
- package/dist/PubSubManager/PubSubManager.d.ts.map +1 -1
- package/dist/PubSubManager/PubSubManager.js +2 -4
- package/dist/PubSubManager/PubSubManager.js.map +1 -1
- package/dist/PubSubManager/SyncReplication/fetchSyncServerData.d.ts +3 -3
- package/dist/PubSubManager/SyncReplication/fetchSyncServerData.d.ts.map +1 -1
- package/dist/PubSubManager/SyncReplication/fetchSyncServerData.js +2 -2
- package/dist/PubSubManager/SyncReplication/fetchSyncServerData.js.map +1 -1
- package/dist/PubSubManager/SyncReplication/getSyncUtilFunctions.d.ts +3 -2
- package/dist/PubSubManager/SyncReplication/getSyncUtilFunctions.d.ts.map +1 -1
- package/dist/PubSubManager/SyncReplication/getSyncUtilFunctions.js +8 -8
- package/dist/PubSubManager/SyncReplication/getSyncUtilFunctions.js.map +1 -1
- package/dist/PubSubManager/SyncReplication/syncData.js +1 -0
- package/dist/PubSubManager/SyncReplication/syncData.js.map +1 -1
- package/dist/PubSubManager/addSub.d.ts.map +1 -1
- package/dist/PubSubManager/addSub.js +2 -1
- package/dist/PubSubManager/addSub.js.map +1 -1
- package/dist/PubSubManager/addSync.d.ts.map +1 -1
- package/dist/PubSubManager/addSync.js +2 -0
- package/dist/PubSubManager/addSync.js.map +1 -1
- package/dist/PubSubManager/init/getPubSubManagerInitQuery.js +4 -4
- package/dist/TableConfig/getTableConfigSchemaQueries.js +2 -2
- package/dist/TableConfig/getTableConfigSchemaQueries.js.map +1 -1
- package/dist/TableConfig/getTableTriggerQueries.d.ts +5 -0
- package/dist/TableConfig/getTableTriggerQueries.d.ts.map +1 -0
- package/dist/TableConfig/getTableTriggerQueries.js +61 -0
- package/dist/TableConfig/getTableTriggerQueries.js.map +1 -0
- package/dist/TableConfig/getTableTriggerQueries.spec.d.ts +2 -0
- package/dist/TableConfig/getTableTriggerQueries.spec.d.ts.map +1 -0
- package/dist/TableConfig/getTableTriggerQueries.spec.js +56 -0
- package/dist/TableConfig/getTableTriggerQueries.spec.js.map +1 -0
- package/dist/TableConfig/initTableConfig.d.ts.map +1 -1
- package/dist/TableConfig/initTableConfig.js +8 -63
- package/dist/TableConfig/initTableConfig.js.map +1 -1
- package/dist/runClientRequest.d.ts.map +1 -1
- package/dist/runClientRequest.js +2 -7
- package/dist/runClientRequest.js.map +1 -1
- package/lib/Auth/utils/getSessionUser.spec.ts +41 -0
- package/lib/Auth/utils/getSessionUser.ts +19 -0
- package/lib/DBSchemaBuilder/getColumnTypescriptDefinition.ts +2 -2
- package/lib/DboBuilder/TableHandler/TableHandler.ts +9 -1
- package/lib/DboBuilder/TableHandler/delete.ts +8 -1
- package/lib/DboBuilder/TableHandler/insert/insert.ts +1 -1
- package/lib/DboBuilder/TableHandler/runInsertUpdateQuery.ts +1 -1
- package/lib/DboBuilder/TableHandler/update.ts +1 -1
- package/lib/DboBuilder/TableHandler/updateBatch.ts +4 -1
- package/lib/DboBuilder/ViewHandler/count.ts +5 -1
- package/lib/DboBuilder/ViewHandler/find.ts +5 -1
- package/lib/DboBuilder/ViewHandler/size.ts +5 -1
- package/lib/DboBuilder/ViewHandler/subscribe.ts +1 -0
- package/lib/DboBuilder/dboBuilderUtils.ts +11 -2
- package/lib/PubSubManager/PubSubManager.ts +20 -5
- package/lib/PubSubManager/SyncReplication/fetchSyncServerData.ts +4 -4
- package/lib/PubSubManager/SyncReplication/getSyncUtilFunctions.ts +16 -8
- package/lib/PubSubManager/SyncReplication/syncData.ts +1 -1
- package/lib/PubSubManager/addSub.ts +2 -0
- package/lib/PubSubManager/addSync.ts +2 -0
- package/lib/PubSubManager/init/getPubSubManagerInitQuery.ts +4 -4
- package/lib/TableConfig/getTableConfigSchemaQueries.ts +2 -2
- package/lib/TableConfig/getTableTriggerQueries.spec.ts +77 -0
- package/lib/TableConfig/getTableTriggerQueries.ts +74 -0
- package/lib/TableConfig/initTableConfig.ts +8 -73
- package/lib/runClientRequest.ts +3 -15
- package/package.json +1 -1
|
@@ -3,7 +3,12 @@
|
|
|
3
3
|
* Licensed under the MIT License. See LICENSE in the project root for license information.
|
|
4
4
|
*--------------------------------------------------------------------------------------------*/
|
|
5
5
|
|
|
6
|
-
import type {
|
|
6
|
+
import type {
|
|
7
|
+
DBHandlerServer,
|
|
8
|
+
DboBuilder,
|
|
9
|
+
LocalParams,
|
|
10
|
+
PRGLIOSocket,
|
|
11
|
+
} from "../DboBuilder/DboBuilder";
|
|
7
12
|
import type { PostgresNotifListenManager } from "../PostgresNotifListenManager";
|
|
8
13
|
import type { DB } from "../Prostgles";
|
|
9
14
|
import { addSync } from "./addSync";
|
|
@@ -56,6 +61,7 @@ export type SyncParams = {
|
|
|
56
61
|
lr?: AnyObject;
|
|
57
62
|
is_syncing: boolean;
|
|
58
63
|
handlers: ReturnType<(typeof ReplicationProtocol)["getServerHandlers"]>;
|
|
64
|
+
localParams: LocalParams;
|
|
59
65
|
};
|
|
60
66
|
|
|
61
67
|
export type AddSyncParams = SyncTableInfo & {
|
|
@@ -74,6 +80,7 @@ export type AddSyncParams = SyncTableInfo & {
|
|
|
74
80
|
};
|
|
75
81
|
condition: string;
|
|
76
82
|
throttle?: number;
|
|
83
|
+
localParams: LocalParams;
|
|
77
84
|
};
|
|
78
85
|
|
|
79
86
|
export type ViewSubscriptionOptions = (
|
|
@@ -114,6 +121,7 @@ export type SubscriptionParams = {
|
|
|
114
121
|
|
|
115
122
|
onData?: OnData;
|
|
116
123
|
socket: PRGLIOSocket | undefined;
|
|
124
|
+
localParams?: LocalParams;
|
|
117
125
|
|
|
118
126
|
lastPushed: number;
|
|
119
127
|
/**
|
|
@@ -143,6 +151,7 @@ export type Subscription = Pick<
|
|
|
143
151
|
| "table_info"
|
|
144
152
|
| "filter"
|
|
145
153
|
| "table_rules"
|
|
154
|
+
| "localParams"
|
|
146
155
|
> & {
|
|
147
156
|
triggers: [AddTriggerParams, ...AddTriggerParams[]];
|
|
148
157
|
};
|
|
@@ -321,7 +330,15 @@ export class PubSubManager {
|
|
|
321
330
|
};
|
|
322
331
|
|
|
323
332
|
getSubData = async (sub: Subscription) => {
|
|
324
|
-
const {
|
|
333
|
+
const {
|
|
334
|
+
table_info,
|
|
335
|
+
filter,
|
|
336
|
+
selectParams: params,
|
|
337
|
+
table_rules,
|
|
338
|
+
localParams,
|
|
339
|
+
socket,
|
|
340
|
+
onData,
|
|
341
|
+
} = sub; //, subOne = false
|
|
325
342
|
const { name: table_name } = table_info;
|
|
326
343
|
const tableHandler = this.dbo[table_name];
|
|
327
344
|
if (!onData && !socket) {
|
|
@@ -337,9 +354,7 @@ export class PubSubManager {
|
|
|
337
354
|
params,
|
|
338
355
|
undefined,
|
|
339
356
|
table_rules,
|
|
340
|
-
|
|
341
|
-
clientReq: { socket },
|
|
342
|
-
},
|
|
357
|
+
localParams,
|
|
343
358
|
)) as AnyObject[];
|
|
344
359
|
return { data };
|
|
345
360
|
} catch (err) {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { AnyObject } from "prostgles-types";
|
|
2
|
-
import type {
|
|
2
|
+
import type { LocalParams } from "../../DboBuilder/DboBuilder";
|
|
3
3
|
import type { TableHandler } from "../../DboBuilder/TableHandler/TableHandler";
|
|
4
4
|
import type { SyncParams } from "../PubSubManager";
|
|
5
5
|
import { getSyncOrderByAndFields } from "./getSyncOrderByAndFields";
|
|
@@ -8,12 +8,12 @@ import { getSyncBatchOptions } from "./getSyncBatchOptions";
|
|
|
8
8
|
export const fetchSyncServerData = async (
|
|
9
9
|
{
|
|
10
10
|
tableHandler,
|
|
11
|
-
|
|
11
|
+
localParams,
|
|
12
12
|
from_synced,
|
|
13
13
|
offset,
|
|
14
14
|
}: {
|
|
15
15
|
tableHandler: TableHandler;
|
|
16
|
-
|
|
16
|
+
localParams: LocalParams;
|
|
17
17
|
from_synced: number | undefined;
|
|
18
18
|
offset: number | undefined;
|
|
19
19
|
},
|
|
@@ -48,7 +48,7 @@ export const fetchSyncServerData = async (
|
|
|
48
48
|
},
|
|
49
49
|
undefined,
|
|
50
50
|
table_rules,
|
|
51
|
-
|
|
51
|
+
localParams,
|
|
52
52
|
);
|
|
53
53
|
|
|
54
54
|
return batchRows as AnyObject[];
|
|
@@ -6,7 +6,7 @@ import {
|
|
|
6
6
|
type AnyObject,
|
|
7
7
|
type SyncBatchParams,
|
|
8
8
|
} from "prostgles-types";
|
|
9
|
-
import type { PRGLIOSocket } from "../../DboBuilder/DboBuilder";
|
|
9
|
+
import type { LocalParams, PRGLIOSocket } from "../../DboBuilder/DboBuilder";
|
|
10
10
|
import type { TableHandler } from "../../DboBuilder/TableHandler/TableHandler";
|
|
11
11
|
import { getSyncOrderByAndFields } from "./getSyncOrderByAndFields";
|
|
12
12
|
import type { PubSubManager, SyncParams } from "../PubSubManager";
|
|
@@ -26,6 +26,7 @@ type Args = {
|
|
|
26
26
|
sync: SyncParams;
|
|
27
27
|
pubSubManager: PubSubManager;
|
|
28
28
|
logSyncData: (state: Extract<EventTypes.Sync, { command: "syncData" }>["state"]) => void;
|
|
29
|
+
localParams: LocalParams;
|
|
29
30
|
};
|
|
30
31
|
|
|
31
32
|
export const getSyncUtilFunctions = ({
|
|
@@ -34,6 +35,7 @@ export const getSyncUtilFunctions = ({
|
|
|
34
35
|
sync,
|
|
35
36
|
pubSubManager,
|
|
36
37
|
logSyncData,
|
|
38
|
+
localParams,
|
|
37
39
|
}: Args) => {
|
|
38
40
|
const {
|
|
39
41
|
synced_field,
|
|
@@ -71,12 +73,18 @@ export const getSyncUtilFunctions = ({
|
|
|
71
73
|
{ orderBy: orderByAsc, select: sync_fields, limit, offset },
|
|
72
74
|
undefined,
|
|
73
75
|
table_rules,
|
|
74
|
-
|
|
76
|
+
localParams,
|
|
75
77
|
)) as AnyObject[];
|
|
76
78
|
|
|
77
79
|
const last_rows = first_rows.slice(-1); // Why not logic below?
|
|
78
80
|
// const last_rows = await _this?.dbo[table_name]?.find?.(_filter, { orderBy: (orderByDesc as OrderBy), select: sync_fields, limit: 1, offset: -offset || 0 }, null, table_rules);
|
|
79
|
-
const count = await tableHandler.count(
|
|
81
|
+
const count = await tableHandler.count(
|
|
82
|
+
batchFilter,
|
|
83
|
+
undefined,
|
|
84
|
+
undefined,
|
|
85
|
+
table_rules,
|
|
86
|
+
localParams,
|
|
87
|
+
);
|
|
80
88
|
|
|
81
89
|
return {
|
|
82
90
|
s_fr: first_rows[0],
|
|
@@ -128,7 +136,7 @@ export const getSyncUtilFunctions = ({
|
|
|
128
136
|
},
|
|
129
137
|
getServerData = async (from_synced: number | undefined, offset = 0): Promise<AnyObject[]> => {
|
|
130
138
|
return fetchSyncServerData(
|
|
131
|
-
{ tableHandler,
|
|
139
|
+
{ tableHandler, localParams, from_synced, offset },
|
|
132
140
|
{ filter, id_fields, params, synced_field, batch_size, table_rules },
|
|
133
141
|
);
|
|
134
142
|
},
|
|
@@ -173,7 +181,7 @@ export const getSyncUtilFunctions = ({
|
|
|
173
181
|
},
|
|
174
182
|
undefined,
|
|
175
183
|
table_rules,
|
|
176
|
-
|
|
184
|
+
localParams,
|
|
177
185
|
)) as AnyObject[];
|
|
178
186
|
let rowsToInsert = data.filter(
|
|
179
187
|
(incomingRow) =>
|
|
@@ -201,7 +209,7 @@ export const getSyncUtilFunctions = ({
|
|
|
201
209
|
{ removeDisallowedFields: true },
|
|
202
210
|
undefined,
|
|
203
211
|
table_rules,
|
|
204
|
-
|
|
212
|
+
localParams,
|
|
205
213
|
);
|
|
206
214
|
} else {
|
|
207
215
|
rowsToUpdate = [];
|
|
@@ -213,7 +221,7 @@ export const getSyncUtilFunctions = ({
|
|
|
213
221
|
{ removeDisallowedFields: true },
|
|
214
222
|
undefined,
|
|
215
223
|
table_rules,
|
|
216
|
-
|
|
224
|
+
localParams,
|
|
217
225
|
);
|
|
218
226
|
} else {
|
|
219
227
|
rowsToInsert = [];
|
|
@@ -355,7 +363,7 @@ export const getSyncUtilFunctions = ({
|
|
|
355
363
|
{ select: sync_fields, limit: 1 },
|
|
356
364
|
undefined,
|
|
357
365
|
table_rules,
|
|
358
|
-
|
|
366
|
+
localParams,
|
|
359
367
|
);
|
|
360
368
|
}
|
|
361
369
|
|
|
@@ -82,7 +82,6 @@ export async function syncData(
|
|
|
82
82
|
if (!tableHandler?.find) {
|
|
83
83
|
throw `dbo.${table_name}.find missing or not allowed`;
|
|
84
84
|
}
|
|
85
|
-
|
|
86
85
|
const {
|
|
87
86
|
upsertData,
|
|
88
87
|
updateSyncLR,
|
|
@@ -98,6 +97,7 @@ export async function syncData(
|
|
|
98
97
|
sync,
|
|
99
98
|
pubSubManager: this,
|
|
100
99
|
logSyncData,
|
|
100
|
+
localParams: sync.localParams,
|
|
101
101
|
});
|
|
102
102
|
|
|
103
103
|
/* Used to throttle and merge incoming updates */
|
|
@@ -34,6 +34,7 @@ export async function addSub(
|
|
|
34
34
|
table_info,
|
|
35
35
|
subscribeOptions,
|
|
36
36
|
tracked_columns,
|
|
37
|
+
localParams,
|
|
37
38
|
} = subscriptionParams;
|
|
38
39
|
const table_name = table_info.name;
|
|
39
40
|
|
|
@@ -65,6 +66,7 @@ export async function addSub(
|
|
|
65
66
|
is_throttling: false,
|
|
66
67
|
socket_id: socket?.id,
|
|
67
68
|
table_rules,
|
|
69
|
+
localParams,
|
|
68
70
|
triggers: [mainTrigger],
|
|
69
71
|
};
|
|
70
72
|
|
|
@@ -20,6 +20,7 @@ export async function addSync(
|
|
|
20
20
|
const res = await tryCatchV2(async () => {
|
|
21
21
|
const { socket, rawSelect, table_info, table_rules, filter, params, condition, initialData } =
|
|
22
22
|
syncParams;
|
|
23
|
+
const { localParams } = syncParams;
|
|
23
24
|
const conditionParsed = parseCondition(condition);
|
|
24
25
|
|
|
25
26
|
const { name: table_name } = table_info;
|
|
@@ -84,6 +85,7 @@ export async function addSync(
|
|
|
84
85
|
socket,
|
|
85
86
|
params,
|
|
86
87
|
handlers,
|
|
88
|
+
localParams,
|
|
87
89
|
};
|
|
88
90
|
const unsyncChn = channelName + "unsync";
|
|
89
91
|
socket.removeAllListeners(unsyncChn);
|
|
@@ -162,11 +162,11 @@ BEGIN
|
|
|
162
162
|
END IF;
|
|
163
163
|
|
|
164
164
|
IF length(key) > 0 THEN
|
|
165
|
-
RETURN
|
|
165
|
+
RETURN jsonb_extract_path_text(user_jsonb, key);
|
|
166
166
|
END IF;
|
|
167
167
|
RETURN user_jsonb;
|
|
168
168
|
END;
|
|
169
|
-
$$ LANGUAGE plpgsql;
|
|
169
|
+
$$ LANGUAGE plpgsql STABLE PARALLEL SAFE;
|
|
170
170
|
COMMENT ON FUNCTION prostgles."user" IS 'Used for row level security';
|
|
171
171
|
|
|
172
172
|
CREATE OR REPLACE FUNCTION prostgles.user_id()
|
|
@@ -174,7 +174,7 @@ BEGIN
|
|
|
174
174
|
BEGIN
|
|
175
175
|
RETURN prostgles.user('id')::UUID;
|
|
176
176
|
END;
|
|
177
|
-
$$ LANGUAGE plpgsql;
|
|
177
|
+
$$ LANGUAGE plpgsql STABLE PARALLEL SAFE;
|
|
178
178
|
COMMENT ON FUNCTION prostgles.user_id IS 'Session user id';
|
|
179
179
|
|
|
180
180
|
CREATE OR REPLACE FUNCTION prostgles.user_type()
|
|
@@ -182,7 +182,7 @@ BEGIN
|
|
|
182
182
|
BEGIN
|
|
183
183
|
RETURN prostgles.user('type')::TEXT;
|
|
184
184
|
END;
|
|
185
|
-
$$ LANGUAGE plpgsql;
|
|
185
|
+
$$ LANGUAGE plpgsql STABLE PARALLEL SAFE;
|
|
186
186
|
COMMENT ON FUNCTION prostgles.user_type IS 'Session user type';
|
|
187
187
|
|
|
188
188
|
CREATE TABLE IF NOT EXISTS prostgles.apps (
|
|
@@ -115,7 +115,7 @@ const getTableQueries = async (
|
|
|
115
115
|
`);`,
|
|
116
116
|
].join("\n");
|
|
117
117
|
|
|
118
|
-
const
|
|
118
|
+
const insertQueries = rows.map((row) => {
|
|
119
119
|
const values = allColumns.map((key) => row[key]);
|
|
120
120
|
return as.format(
|
|
121
121
|
`INSERT INTO ${tableName} (${allColumns.map((t) => asName(t)).join(", ")}) ` +
|
|
@@ -123,7 +123,7 @@ const getTableQueries = async (
|
|
|
123
123
|
{ values },
|
|
124
124
|
);
|
|
125
125
|
});
|
|
126
|
-
const queries = [createQuery, ...
|
|
126
|
+
const queries = [createQuery, ...insertQueries];
|
|
127
127
|
return {
|
|
128
128
|
queries,
|
|
129
129
|
colDefs,
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import assert from "node:assert/strict";
|
|
2
|
+
import test from "node:test";
|
|
3
|
+
import { asName } from "prostgles-types";
|
|
4
|
+
import type { DB } from "../initProstgles";
|
|
5
|
+
import { getTableTriggerQueries } from "./getTableTriggerQueries";
|
|
6
|
+
|
|
7
|
+
void test("trigger configuration quotes names and bodies and preserves unmanaged triggers", async () => {
|
|
8
|
+
const db = {
|
|
9
|
+
any: () =>
|
|
10
|
+
Promise.resolve([
|
|
11
|
+
{ name: "manual", comment: null },
|
|
12
|
+
{ name: "old_insert", comment: "prostgles.tableConfig:old" },
|
|
13
|
+
]),
|
|
14
|
+
} as unknown as DB;
|
|
15
|
+
const queries = await getTableTriggerQueries(
|
|
16
|
+
db,
|
|
17
|
+
"Odd ' table",
|
|
18
|
+
{
|
|
19
|
+
triggers: {
|
|
20
|
+
audit: {
|
|
21
|
+
type: "after",
|
|
22
|
+
actions: ["insert"],
|
|
23
|
+
forEach: "row",
|
|
24
|
+
query: "BEGIN RAISE NOTICE '$$'; RETURN NULL; END;",
|
|
25
|
+
},
|
|
26
|
+
},
|
|
27
|
+
},
|
|
28
|
+
asName,
|
|
29
|
+
);
|
|
30
|
+
assert.ok(queries.some((query) => query.includes('ON "Odd \' table"')));
|
|
31
|
+
assert.ok(
|
|
32
|
+
queries.some((query) =>
|
|
33
|
+
query.includes("AS 'BEGIN RAISE NOTICE ''$$''; RETURN NULL; END;';"),
|
|
34
|
+
),
|
|
35
|
+
);
|
|
36
|
+
assert.ok(
|
|
37
|
+
queries.some((query) => query.includes('DROP TRIGGER "old_insert"')),
|
|
38
|
+
);
|
|
39
|
+
assert.ok(!queries.some((query) => query.includes('DROP TRIGGER "manual"')));
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
void test("unchanged triggers do not produce DDL; changed bodies replace them", async () => {
|
|
43
|
+
const trigger = {
|
|
44
|
+
type: "after",
|
|
45
|
+
actions: ["update"],
|
|
46
|
+
forEach: "row",
|
|
47
|
+
query: "BEGIN RETURN NULL; END;" as string,
|
|
48
|
+
} as const;
|
|
49
|
+
const config = {
|
|
50
|
+
triggers: { audit: { ...trigger, actions: [...trigger.actions] } },
|
|
51
|
+
};
|
|
52
|
+
const first = await getTableTriggerQueries(
|
|
53
|
+
{ any: () => Promise.resolve([]) } as unknown as DB,
|
|
54
|
+
"records",
|
|
55
|
+
config,
|
|
56
|
+
asName,
|
|
57
|
+
);
|
|
58
|
+
const commentQuery = first.find((query) => query.startsWith("COMMENT ON"))!;
|
|
59
|
+
const comment = commentQuery.split(" IS '")[1]!.slice(0, -2);
|
|
60
|
+
const db = {
|
|
61
|
+
any: () => Promise.resolve([{ name: "audit_update", comment }]),
|
|
62
|
+
} as unknown as DB;
|
|
63
|
+
assert.deepEqual(
|
|
64
|
+
await getTableTriggerQueries(db, "records", config, asName),
|
|
65
|
+
[],
|
|
66
|
+
);
|
|
67
|
+
config.triggers.audit.query =
|
|
68
|
+
"BEGIN RAISE NOTICE 'changed'; RETURN NULL; END;";
|
|
69
|
+
assert.ok(
|
|
70
|
+
(await getTableTriggerQueries(db, "records", config, asName)).some(
|
|
71
|
+
(query) => query.startsWith("CREATE OR REPLACE FUNCTION"),
|
|
72
|
+
),
|
|
73
|
+
);
|
|
74
|
+
assert.deepEqual(await getTableTriggerQueries(db, "records", {}, asName), [
|
|
75
|
+
'DROP TRIGGER "audit_update" ON "records";',
|
|
76
|
+
]);
|
|
77
|
+
});
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { as } from "pg-promise";
|
|
2
|
+
import { md5 } from "prostgles-types/dist/md5";
|
|
3
|
+
import type { DB } from "../initProstgles";
|
|
4
|
+
import type { TableConfig } from "./TableConfigTypes";
|
|
5
|
+
|
|
6
|
+
const MANAGED_TRIGGER_PREFIX = "prostgles.tableConfig:";
|
|
7
|
+
|
|
8
|
+
/** Reconcile only triggers owned by tableConfig; preserve manually created triggers. */
|
|
9
|
+
export const getTableTriggerQueries = async (
|
|
10
|
+
db: DB,
|
|
11
|
+
tableName: string,
|
|
12
|
+
tableConfig: TableConfig[string],
|
|
13
|
+
asName: (name: string) => string,
|
|
14
|
+
): Promise<string[]> => {
|
|
15
|
+
const tableIdent = asName(tableName);
|
|
16
|
+
const existing = await db.any<{ name: string; comment: string | null }>(
|
|
17
|
+
`
|
|
18
|
+
SELECT t.tgname AS name, obj_description(t.oid, 'pg_trigger') AS comment
|
|
19
|
+
FROM pg_trigger t
|
|
20
|
+
WHERE t.tgrelid = to_regclass($1) AND NOT t.tgisinternal
|
|
21
|
+
`,
|
|
22
|
+
[tableIdent],
|
|
23
|
+
);
|
|
24
|
+
const queries: string[] = [];
|
|
25
|
+
const desired = new Set<string>();
|
|
26
|
+
const isDropped = tableConfig.dropIfExists || tableConfig.dropIfExistsCascade;
|
|
27
|
+
for (const [functionName, trigger] of Object.entries(
|
|
28
|
+
tableConfig.triggers ?? {},
|
|
29
|
+
)) {
|
|
30
|
+
const functionIdent = asName(functionName);
|
|
31
|
+
let functionAdded = false;
|
|
32
|
+
for (const action of trigger.actions) {
|
|
33
|
+
const name = `${functionName}_${action}`;
|
|
34
|
+
desired.add(name);
|
|
35
|
+
const triggerIdent = asName(name);
|
|
36
|
+
const transitionTables =
|
|
37
|
+
trigger.forEach === "row"
|
|
38
|
+
? ""
|
|
39
|
+
: [
|
|
40
|
+
"REFERENCING",
|
|
41
|
+
action !== "delete" ? "NEW TABLE AS new_table" : "",
|
|
42
|
+
action !== "insert" ? "OLD TABLE AS old_table" : "",
|
|
43
|
+
].join(" ");
|
|
44
|
+
const definition = `CREATE TRIGGER ${triggerIdent}
|
|
45
|
+
${trigger.type} ${action} ON ${tableIdent}
|
|
46
|
+
${transitionTables} FOR EACH ${trigger.forEach}
|
|
47
|
+
EXECUTE FUNCTION ${functionIdent}();`;
|
|
48
|
+
const comment = MANAGED_TRIGGER_PREFIX + md5(definition + trigger.query);
|
|
49
|
+
const previous = existing.find((entry) => entry.name === name);
|
|
50
|
+
if (!isDropped && previous?.comment === comment) continue;
|
|
51
|
+
if (!functionAdded) {
|
|
52
|
+
queries.push(`CREATE OR REPLACE FUNCTION ${functionIdent}()
|
|
53
|
+
RETURNS trigger LANGUAGE plpgsql AS ${as.text(trigger.query)};`);
|
|
54
|
+
functionAdded = true;
|
|
55
|
+
}
|
|
56
|
+
queries.push(`DROP TRIGGER IF EXISTS ${triggerIdent} ON ${tableIdent};`);
|
|
57
|
+
queries.push(definition);
|
|
58
|
+
queries.push(
|
|
59
|
+
`COMMENT ON TRIGGER ${triggerIdent} ON ${tableIdent} IS ${as.text(comment)};`,
|
|
60
|
+
);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
if (!isDropped) {
|
|
64
|
+
for (const trigger of existing) {
|
|
65
|
+
if (
|
|
66
|
+
trigger.comment?.startsWith(MANAGED_TRIGGER_PREFIX) &&
|
|
67
|
+
!desired.has(trigger.name)
|
|
68
|
+
) {
|
|
69
|
+
queries.push(`DROP TRIGGER ${asName(trigger.name)} ON ${tableIdent};`);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
return queries;
|
|
74
|
+
};
|
|
@@ -9,6 +9,7 @@ import { fetchTableConstraints } from "./fetchTableConstraints";
|
|
|
9
9
|
import { getConstraintDefinitionQueries } from "./getConstraintDefinitionQueries";
|
|
10
10
|
import { getFutureTableSchema } from "./getFutureTableSchema";
|
|
11
11
|
import { getTableColumnQueries } from "./getTableColumnQueries";
|
|
12
|
+
import { getTableTriggerQueries } from "./getTableTriggerQueries";
|
|
12
13
|
import { getIndexesQueries } from "./indexes/getIndexesQueries";
|
|
13
14
|
import { runMigrations } from "./runMigrations";
|
|
14
15
|
import type { TableConfigurator } from "./TableConfigurator";
|
|
@@ -162,7 +163,7 @@ export const initTableConfig = async function (this: TableConfigurator) {
|
|
|
162
163
|
const ALTER_TABLE_Q = `ALTER TABLE ${asName(tableName)}`;
|
|
163
164
|
|
|
164
165
|
/* isLookupTable table has already been created */
|
|
165
|
-
const
|
|
166
|
+
const tableColumnDefinition =
|
|
166
167
|
"isLookupTable" in tableConf ? undefined : (
|
|
167
168
|
await getTableColumnQueries({
|
|
168
169
|
db: this.db,
|
|
@@ -172,8 +173,8 @@ export const initTableConfig = async function (this: TableConfigurator) {
|
|
|
172
173
|
})
|
|
173
174
|
);
|
|
174
175
|
|
|
175
|
-
if (
|
|
176
|
-
queries.push(
|
|
176
|
+
if (tableColumnDefinition) {
|
|
177
|
+
queries.push(tableColumnDefinition.fullQuery);
|
|
177
178
|
}
|
|
178
179
|
|
|
179
180
|
/** CONSTRAINTS */
|
|
@@ -181,13 +182,13 @@ export const initTableConfig = async function (this: TableConfigurator) {
|
|
|
181
182
|
tableName,
|
|
182
183
|
tableConf,
|
|
183
184
|
});
|
|
184
|
-
if (
|
|
185
|
+
if (tableColumnDefinition?.isCreate) {
|
|
185
186
|
queries.push(...(constraintDefs?.map((c) => c.alterQuery) ?? []));
|
|
186
|
-
} else if (
|
|
187
|
+
} else if (tableColumnDefinition) {
|
|
187
188
|
const fullSchema = await getFutureTableSchema({
|
|
188
189
|
db: this.db,
|
|
189
190
|
tableName,
|
|
190
|
-
columnDefs:
|
|
191
|
+
columnDefs: tableColumnDefinition.columnDefs,
|
|
191
192
|
constraintDefs,
|
|
192
193
|
});
|
|
193
194
|
const futureCons = fullSchema.constraints.map((nc) => ({
|
|
@@ -234,73 +235,7 @@ export const initTableConfig = async function (this: TableConfigurator) {
|
|
|
234
235
|
const indexQueries = await getIndexesQueries(this.db, tableName, tableConf);
|
|
235
236
|
queries.push(...indexQueries);
|
|
236
237
|
|
|
237
|
-
|
|
238
|
-
if (triggers) {
|
|
239
|
-
const isDropped = dropIfExists || dropIfExistsCascade;
|
|
240
|
-
|
|
241
|
-
const existingTriggers = await this.db.any<{ trigger_name: string }>(
|
|
242
|
-
`
|
|
243
|
-
SELECT event_object_table
|
|
244
|
-
,trigger_name
|
|
245
|
-
FROM information_schema.triggers
|
|
246
|
-
WHERE event_object_table = \${tableName}
|
|
247
|
-
ORDER BY event_object_table
|
|
248
|
-
`,
|
|
249
|
-
{ tableName },
|
|
250
|
-
);
|
|
251
|
-
|
|
252
|
-
// const existingTriggerFuncs = await this.dbo.sql!(`
|
|
253
|
-
// SELECT p.oid,proname,prosrc,u.usename
|
|
254
|
-
// FROM pg_proc p
|
|
255
|
-
// JOIN pg_user u ON u.usesysid = p.proowner
|
|
256
|
-
// WHERE prorettype = 2279;
|
|
257
|
-
// `, {}, { returnType: "rows" }) as { proname: string }[];
|
|
258
|
-
|
|
259
|
-
Object.entries(triggers).forEach(([triggerFuncName, trigger]) => {
|
|
260
|
-
const funcNameParsed = asName(triggerFuncName);
|
|
261
|
-
|
|
262
|
-
let addedFunc = false;
|
|
263
|
-
const addFuncDef = () => {
|
|
264
|
-
if (addedFunc) return;
|
|
265
|
-
addedFunc = true;
|
|
266
|
-
queries.push(`
|
|
267
|
-
CREATE OR REPLACE FUNCTION ${funcNameParsed}()
|
|
268
|
-
RETURNS trigger
|
|
269
|
-
LANGUAGE plpgsql
|
|
270
|
-
AS
|
|
271
|
-
$$
|
|
272
|
-
|
|
273
|
-
${trigger.query}
|
|
274
|
-
|
|
275
|
-
$$;
|
|
276
|
-
`);
|
|
277
|
-
};
|
|
278
|
-
|
|
279
|
-
trigger.actions.forEach((action) => {
|
|
280
|
-
const triggerActionName = triggerFuncName + "_" + action;
|
|
281
|
-
|
|
282
|
-
const triggerActionNameParsed = asName(triggerActionName);
|
|
283
|
-
if (isDropped) {
|
|
284
|
-
queries.push(`DROP TRIGGER IF EXISTS ${triggerActionNameParsed} ON ${tableName};`);
|
|
285
|
-
}
|
|
286
|
-
|
|
287
|
-
if (isDropped || !existingTriggers.some((t) => t.trigger_name === triggerActionName)) {
|
|
288
|
-
addFuncDef();
|
|
289
|
-
const newTableName = action !== "delete" ? "NEW TABLE AS new_table" : "";
|
|
290
|
-
const oldTableName = action !== "insert" ? "OLD TABLE AS old_table" : "";
|
|
291
|
-
const transitionTables =
|
|
292
|
-
trigger.forEach === "row" ? "" : `REFERENCING ${newTableName} ${oldTableName}`;
|
|
293
|
-
queries.push(`
|
|
294
|
-
CREATE TRIGGER ${triggerActionNameParsed}
|
|
295
|
-
${trigger.type} ${action} ON ${tableName}
|
|
296
|
-
${transitionTables}
|
|
297
|
-
FOR EACH ${trigger.forEach}
|
|
298
|
-
EXECUTE PROCEDURE ${funcNameParsed}();
|
|
299
|
-
`);
|
|
300
|
-
}
|
|
301
|
-
});
|
|
302
|
-
});
|
|
303
|
-
}
|
|
238
|
+
queries.push(...(await getTableTriggerQueries(this.db, tableName, tableConf, asName)));
|
|
304
239
|
}
|
|
305
240
|
|
|
306
241
|
if (queries.length) {
|
package/lib/runClientRequest.ts
CHANGED
|
@@ -1,16 +1,15 @@
|
|
|
1
|
-
import type { SQLRequest, TableHandler
|
|
1
|
+
import type { SQLRequest, TableHandler } from "prostgles-types";
|
|
2
2
|
import {
|
|
3
3
|
ABORTABLE_METHODS,
|
|
4
4
|
getJSONBObjectSchemaValidationError,
|
|
5
5
|
getJSONBSchemaValidationErrorAsync,
|
|
6
6
|
getKeys,
|
|
7
|
-
pickKeys,
|
|
8
7
|
type AnyObject,
|
|
9
8
|
} from "prostgles-types";
|
|
10
9
|
import type { AuthClientRequest } from "./Auth/AuthTypes";
|
|
10
|
+
import { getSessionUser } from "./Auth/utils/getSessionUser";
|
|
11
11
|
import type { LocalParams } from "./DboBuilder/DboBuilder";
|
|
12
12
|
import type { TableHandler as TableHandlerServer } from "./DboBuilder/TableHandler/TableHandler";
|
|
13
|
-
import { parseFieldFilter } from "./DboBuilder/ViewHandler/parseFieldFilter";
|
|
14
13
|
import { canRunSQL } from "./DboBuilder/runSql/runSQL";
|
|
15
14
|
import type { Prostgles } from "./Prostgles";
|
|
16
15
|
import type { ParsedTableRule } from "./PublishParser/publishTypesAndUtils";
|
|
@@ -118,18 +117,7 @@ export const runClientRequest = async function (
|
|
|
118
117
|
scope,
|
|
119
118
|
);
|
|
120
119
|
|
|
121
|
-
const sessionUser
|
|
122
|
-
!clientInfo.user ? undefined : (
|
|
123
|
-
{
|
|
124
|
-
...parseFieldFilter(
|
|
125
|
-
//@ts-ignore
|
|
126
|
-
clientInfo.sessionFields ?? [],
|
|
127
|
-
false,
|
|
128
|
-
getKeys(clientInfo.user),
|
|
129
|
-
),
|
|
130
|
-
...(pickKeys(clientInfo.user, ["id", "type"]) as UserLike),
|
|
131
|
-
}
|
|
132
|
-
);
|
|
120
|
+
const sessionUser = getSessionUser(clientInfo);
|
|
133
121
|
const localParams: LocalParams = {
|
|
134
122
|
clientReq,
|
|
135
123
|
isRemoteRequest: { user: sessionUser, clientInfo },
|