prostgles-server 3.0.50 → 3.0.52
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.d.ts +3 -11
- package/dist/DboBuilder/TableHandler.d.ts.map +1 -1
- package/dist/DboBuilder/TableHandler.js +0 -74
- package/dist/DboBuilder/TableHandler.js.map +1 -1
- package/dist/DboBuilder/ViewHandler.d.ts +9 -1
- package/dist/DboBuilder/ViewHandler.d.ts.map +1 -1
- package/dist/DboBuilder/ViewHandler.js +127 -0
- package/dist/DboBuilder/ViewHandler.js.map +1 -1
- package/dist/DboBuilder/runSQL.d.ts.map +1 -1
- package/dist/DboBuilder/runSQL.js +23 -3
- package/dist/DboBuilder/runSQL.js.map +1 -1
- package/dist/DboBuilder.d.ts +10 -0
- package/dist/DboBuilder.d.ts.map +1 -1
- package/dist/DboBuilder.js.map +1 -1
- package/dist/Prostgles.d.ts.map +1 -1
- package/dist/Prostgles.js +3 -2
- package/dist/Prostgles.js.map +1 -1
- package/dist/PubSubManager.d.ts +10 -2
- package/dist/PubSubManager.d.ts.map +1 -1
- package/dist/PubSubManager.js +83 -75
- package/dist/PubSubManager.js.map +1 -1
- package/dist/PublishParser.js +1 -1
- package/dist/PublishParser.js.map +1 -1
- package/lib/DboBuilder/TableHandler.d.ts +1 -9
- package/lib/DboBuilder/TableHandler.d.ts.map +1 -1
- package/lib/DboBuilder/TableHandler.js +0 -74
- package/lib/DboBuilder/TableHandler.ts +2 -86
- package/lib/DboBuilder/ViewHandler.d.ts +9 -1
- package/lib/DboBuilder/ViewHandler.d.ts.map +1 -1
- package/lib/DboBuilder/ViewHandler.js +127 -0
- package/lib/DboBuilder/ViewHandler.ts +157 -2
- package/lib/DboBuilder/runSQL.d.ts.map +1 -1
- package/lib/DboBuilder/runSQL.js +23 -3
- package/lib/DboBuilder/runSQL.ts +24 -3
- package/lib/DboBuilder.d.ts +10 -0
- package/lib/DboBuilder.d.ts.map +1 -1
- package/lib/DboBuilder.ts +15 -2
- package/lib/Prostgles.d.ts.map +1 -1
- package/lib/Prostgles.js +3 -2
- package/lib/Prostgles.ts +3 -2
- package/lib/PubSubManager.d.ts +10 -2
- package/lib/PubSubManager.d.ts.map +1 -1
- package/lib/PubSubManager.js +83 -75
- package/lib/PubSubManager.ts +104 -82
- package/lib/PublishParser.js +1 -1
- package/lib/PublishParser.ts +1 -1
- package/package.json +2 -2
- package/tests/client/PID.txt +1 -1
- package/tests/server/package-lock.json +3 -3
package/lib/PubSubManager.js
CHANGED
|
@@ -224,8 +224,8 @@ class PubSubManager {
|
|
|
224
224
|
|
|
225
225
|
-- Force table into cache
|
|
226
226
|
IF EXISTS (select * from pg_extension where extname = 'pg_prewarm') THEN
|
|
227
|
-
|
|
228
|
-
|
|
227
|
+
CREATE EXTENSION IF NOT EXISTS pg_prewarm;
|
|
228
|
+
PERFORM pg_prewarm('prostgles.app_triggers');
|
|
229
229
|
END IF;
|
|
230
230
|
*/
|
|
231
231
|
|
|
@@ -251,20 +251,24 @@ class PubSubManager {
|
|
|
251
251
|
-- PERFORM pg_notify('debug', concat_ws(' ', 'TABLE', TG_TABLE_NAME, TG_OP));
|
|
252
252
|
|
|
253
253
|
SELECT string_agg(
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
254
|
+
concat_ws(
|
|
255
|
+
E' UNION \n ',
|
|
256
|
+
CASE WHEN (TG_OP = 'DELETE' OR TG_OP = 'UPDATE') THEN (p1 || ' old_table ' || p2) END,
|
|
257
|
+
CASE WHEN (TG_OP = 'INSERT' OR TG_OP = 'UPDATE') THEN (p1 || ' new_table ' || p2) END
|
|
258
|
+
),
|
|
259
|
+
E' UNION \n '::text
|
|
260
260
|
)
|
|
261
261
|
INTO unions
|
|
262
262
|
FROM (
|
|
263
263
|
SELECT
|
|
264
|
-
$z$
|
|
264
|
+
$z$
|
|
265
|
+
SELECT CASE WHEN EXISTS( SELECT 1 FROM
|
|
266
|
+
$z$ AS p1,
|
|
265
267
|
format(
|
|
266
|
-
|
|
267
|
-
|
|
268
|
+
$c$
|
|
269
|
+
as %I WHERE %s ) THEN %s::text END AS t_ids
|
|
270
|
+
$c$,
|
|
271
|
+
table_name, condition, id
|
|
268
272
|
) AS p2
|
|
269
273
|
FROM prostgles.v_triggers
|
|
270
274
|
WHERE table_name = TG_TABLE_NAME
|
|
@@ -272,15 +276,15 @@ class PubSubManager {
|
|
|
272
276
|
|
|
273
277
|
/*
|
|
274
278
|
PERFORM pg_notify(
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
279
|
+
${(0, exports.asValue)(this.NOTIF_CHANNEL.preffix)} || (SELECT id FROM prostgles.apps LIMIT 1) ,
|
|
280
|
+
concat_ws(
|
|
281
|
+
${(0, exports.asValue)(PubSubManager.DELIMITER)},
|
|
282
|
+
|
|
283
|
+
${(0, exports.asValue)(this.NOTIF_TYPE.data)},
|
|
284
|
+
COALESCE(TG_TABLE_NAME, 'MISSING'),
|
|
285
|
+
COALESCE(TG_OP, 'MISSING'),
|
|
286
|
+
unions
|
|
287
|
+
)
|
|
284
288
|
);
|
|
285
289
|
RAISE 'unions: % , cids: %', unions, c_ids;
|
|
286
290
|
*/
|
|
@@ -288,25 +292,25 @@ class PubSubManager {
|
|
|
288
292
|
IF unions IS NOT NULL THEN
|
|
289
293
|
query = format(
|
|
290
294
|
$s$
|
|
291
|
-
|
|
292
|
-
|
|
295
|
+
SELECT ARRAY_AGG(DISTINCT t.t_ids)
|
|
296
|
+
FROM ( %s ) t
|
|
293
297
|
$s$,
|
|
294
298
|
unions
|
|
295
299
|
);
|
|
296
300
|
|
|
297
301
|
BEGIN
|
|
298
|
-
|
|
302
|
+
EXECUTE query INTO t_ids;
|
|
299
303
|
|
|
300
|
-
|
|
304
|
+
--RAISE NOTICE 'trigger fired ok';
|
|
301
305
|
|
|
302
306
|
EXCEPTION WHEN OTHERS THEN
|
|
303
|
-
|
|
304
|
-
|
|
307
|
+
|
|
308
|
+
has_errors := TRUE;
|
|
305
309
|
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
+
GET STACKED DIAGNOSTICS
|
|
311
|
+
err_text = MESSAGE_TEXT,
|
|
312
|
+
err_detail = PG_EXCEPTION_DETAIL,
|
|
313
|
+
err_hint = PG_EXCEPTION_HINT;
|
|
310
314
|
|
|
311
315
|
|
|
312
316
|
END;
|
|
@@ -925,7 +929,6 @@ class PubSubManager {
|
|
|
925
929
|
console.warn(190, "Trigger sub issue: ", table_name, condition_ids_str, this._triggers);
|
|
926
930
|
}
|
|
927
931
|
};
|
|
928
|
-
this.parseCondition = (condition) => Boolean(condition && condition.trim().length) ? condition : "TRUE";
|
|
929
932
|
this.getActiveListeners = () => {
|
|
930
933
|
let result = [];
|
|
931
934
|
const upsert = (t, c) => {
|
|
@@ -968,11 +971,11 @@ class PubSubManager {
|
|
|
968
971
|
*/
|
|
969
972
|
this.getMyTriggerQuery = async () => {
|
|
970
973
|
return pgp.as.format(`
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
974
|
+
SELECT * --, ROW_NUMBER() OVER(PARTITION BY table_name ORDER BY table_name, condition ) - 1 as id
|
|
975
|
+
FROM prostgles.v_triggers
|
|
976
|
+
WHERE app_id = $1
|
|
977
|
+
ORDER BY table_name, condition
|
|
978
|
+
`, [this.appID]);
|
|
976
979
|
};
|
|
977
980
|
this.addTriggerPool = undefined;
|
|
978
981
|
const { wsChannelNamePrefix, pgChannelName, onSchemaChange, dboBuilder } = options;
|
|
@@ -999,7 +1002,7 @@ class PubSubManager {
|
|
|
999
1002
|
return this.postgresNotifListenManager.isListening();
|
|
1000
1003
|
}
|
|
1001
1004
|
getSubs(table_name, condition) {
|
|
1002
|
-
return
|
|
1005
|
+
return this.subs?.[table_name]?.[condition]?.subs;
|
|
1003
1006
|
}
|
|
1004
1007
|
getSyncs(table_name, condition) {
|
|
1005
1008
|
return (this.syncs || [])
|
|
@@ -1065,7 +1068,7 @@ class PubSubManager {
|
|
|
1065
1068
|
*/
|
|
1066
1069
|
async addSync(syncParams) {
|
|
1067
1070
|
const { socket = null, table_info = null, table_rules, synced_field = null, allow_delete = false, id_fields = [], filter = {}, params, condition = "", throttle = 0 } = syncParams || {};
|
|
1068
|
-
let conditionParsed =
|
|
1071
|
+
let conditionParsed = parseCondition(condition);
|
|
1069
1072
|
if (!socket || !table_info)
|
|
1070
1073
|
throw "socket or table_info missing";
|
|
1071
1074
|
const { name: table_name } = table_info, channel_name = `${this.socketChannelPreffix}.${table_name}.${JSON.stringify(filter)}.sync`;
|
|
@@ -1156,8 +1159,8 @@ class PubSubManager {
|
|
|
1156
1159
|
/* Must return a channel for socket */
|
|
1157
1160
|
/* The distinct list of channel names must have a corresponding trigger in the database */
|
|
1158
1161
|
async addSub(subscriptionParams) {
|
|
1159
|
-
const { socket, func = null, table_info = null, table_rules, filter = {}, params = {}, condition = "", throttle = 0 //subOne = false,
|
|
1160
|
-
|
|
1162
|
+
const { socket, func = null, table_info = null, table_rules, filter = {}, params = {}, condition = "", throttle = 0, //subOne = false,
|
|
1163
|
+
relatedTableSubscriptions } = subscriptionParams || {};
|
|
1161
1164
|
let validated_throttle = subscriptionParams.throttle || 10;
|
|
1162
1165
|
if ((!socket && !func) || !table_info)
|
|
1163
1166
|
throw "socket/func or table_info missing";
|
|
@@ -1168,10 +1171,10 @@ class PubSubManager {
|
|
|
1168
1171
|
if (throttle && Number.isInteger(throttle) && throttle >= pubThrottle) {
|
|
1169
1172
|
validated_throttle = throttle;
|
|
1170
1173
|
}
|
|
1171
|
-
|
|
1174
|
+
const channel_name = `${this.socketChannelPreffix}.${table_info.name}.${JSON.stringify(filter)}.${JSON.stringify(params)}.${"m"}.sub`;
|
|
1172
1175
|
this.upsertSocket(socket, channel_name);
|
|
1173
1176
|
const upsertSub = (newSubData) => {
|
|
1174
|
-
const { table_name, condition: _cond, is_ready = false } = newSubData, condition =
|
|
1177
|
+
const { table_name, condition: _cond, is_ready = false, parentSubParams } = newSubData, condition = parseCondition(_cond), newSub = {
|
|
1175
1178
|
socket,
|
|
1176
1179
|
table_name: table_info.name,
|
|
1177
1180
|
table_info,
|
|
@@ -1179,17 +1182,17 @@ class PubSubManager {
|
|
|
1179
1182
|
params,
|
|
1180
1183
|
table_rules,
|
|
1181
1184
|
channel_name,
|
|
1182
|
-
|
|
1185
|
+
parentSubParams,
|
|
1186
|
+
func: func ?? undefined,
|
|
1183
1187
|
socket_id: socket?.id,
|
|
1184
1188
|
throttle: validated_throttle,
|
|
1185
1189
|
is_throttling: null,
|
|
1186
1190
|
last_throttled: 0,
|
|
1187
1191
|
is_ready,
|
|
1188
|
-
// subOne
|
|
1189
1192
|
};
|
|
1190
|
-
this.subs[table_name] = this.subs[table_name]
|
|
1191
|
-
this.subs[table_name][condition] = this.subs[table_name][condition]
|
|
1192
|
-
this.subs[table_name][condition].subs = this.subs[table_name][condition].subs
|
|
1193
|
+
this.subs[table_name] = this.subs[table_name] ?? {};
|
|
1194
|
+
this.subs[table_name][condition] = this.subs[table_name][condition] ?? { subs: [] };
|
|
1195
|
+
this.subs[table_name][condition].subs = this.subs[table_name][condition].subs ?? [];
|
|
1193
1196
|
// console.log("1034 upsertSub", this.subs)
|
|
1194
1197
|
const sub_idx = this.subs[table_name][condition].subs.findIndex(s => s.channel_name === channel_name &&
|
|
1195
1198
|
(socket && s.socket_id === socket.id ||
|
|
@@ -1212,22 +1215,24 @@ class PubSubManager {
|
|
|
1212
1215
|
this.pushSubData(newSub);
|
|
1213
1216
|
}
|
|
1214
1217
|
};
|
|
1215
|
-
if (table_info.is_view &&
|
|
1216
|
-
if (
|
|
1217
|
-
|
|
1218
|
-
|
|
1218
|
+
if (table_info.is_view && relatedTableSubscriptions) {
|
|
1219
|
+
if (relatedTableSubscriptions.length) {
|
|
1220
|
+
relatedTableSubscriptions.map(async (relatedTable) => {
|
|
1221
|
+
const params = {
|
|
1222
|
+
table_name: relatedTable.tableNameEscaped,
|
|
1223
|
+
condition: relatedTable.condition,
|
|
1224
|
+
parentSubParams: {
|
|
1225
|
+
...subscriptionParams,
|
|
1226
|
+
channel_name
|
|
1227
|
+
},
|
|
1228
|
+
};
|
|
1219
1229
|
upsertSub({
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
is_ready: true
|
|
1223
|
-
});
|
|
1224
|
-
await this.addTrigger({
|
|
1225
|
-
table_name,
|
|
1226
|
-
condition: _condition
|
|
1230
|
+
...params,
|
|
1231
|
+
is_ready: false
|
|
1227
1232
|
});
|
|
1233
|
+
await this.addTrigger(params);
|
|
1228
1234
|
upsertSub({
|
|
1229
|
-
|
|
1230
|
-
condition: _condition,
|
|
1235
|
+
...params,
|
|
1231
1236
|
is_ready: true
|
|
1232
1237
|
});
|
|
1233
1238
|
});
|
|
@@ -1243,23 +1248,25 @@ class PubSubManager {
|
|
|
1243
1248
|
// console.log(table_info, 202);
|
|
1244
1249
|
upsertSub({
|
|
1245
1250
|
table_name: table_info.name,
|
|
1246
|
-
condition:
|
|
1251
|
+
condition: parseCondition(condition),
|
|
1252
|
+
parentSubParams: undefined,
|
|
1247
1253
|
is_ready: false
|
|
1248
1254
|
});
|
|
1249
1255
|
await this.addTrigger({
|
|
1250
1256
|
table_name: table_info.name,
|
|
1251
|
-
condition:
|
|
1257
|
+
condition: parseCondition(condition),
|
|
1252
1258
|
});
|
|
1253
1259
|
upsertSub({
|
|
1254
1260
|
table_name: table_info.name,
|
|
1255
|
-
condition:
|
|
1261
|
+
condition: parseCondition(condition),
|
|
1262
|
+
parentSubParams: undefined,
|
|
1256
1263
|
is_ready: true
|
|
1257
1264
|
});
|
|
1258
1265
|
return channel_name;
|
|
1259
1266
|
}
|
|
1260
1267
|
}
|
|
1261
1268
|
removeLocalSub(table_name, condition, func) {
|
|
1262
|
-
let cond =
|
|
1269
|
+
let cond = parseCondition(condition);
|
|
1263
1270
|
if ((0, utils_1.get)(this.subs, [table_name, cond, "subs"])) {
|
|
1264
1271
|
this.subs[table_name][cond].subs.map((sub, i) => {
|
|
1265
1272
|
if (sub.func && sub.func === func) {
|
|
@@ -1325,9 +1332,9 @@ class PubSubManager {
|
|
|
1325
1332
|
throw "MISSING table_name";
|
|
1326
1333
|
if (!this.appID)
|
|
1327
1334
|
throw "MISSING appID";
|
|
1328
|
-
if (!condition || !condition.trim().length)
|
|
1335
|
+
if (!condition || !condition.trim().length) {
|
|
1329
1336
|
condition = "TRUE";
|
|
1330
|
-
|
|
1337
|
+
}
|
|
1331
1338
|
// console.log(1623, { app_id, addTrigger: { table_name, condition } });
|
|
1332
1339
|
await this.checkIfTimescaleBug(table_name);
|
|
1333
1340
|
const trgVals = {
|
|
@@ -1335,15 +1342,15 @@ class PubSubManager {
|
|
|
1335
1342
|
cond: (0, exports.asValue)(condition),
|
|
1336
1343
|
};
|
|
1337
1344
|
await this.db.any(`
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
|
|
1342
|
-
|
|
1343
|
-
|
|
1344
|
-
|
|
1345
|
-
|
|
1346
|
-
|
|
1345
|
+
BEGIN WORK;
|
|
1346
|
+
LOCK TABLE prostgles.app_triggers IN ACCESS EXCLUSIVE MODE;
|
|
1347
|
+
|
|
1348
|
+
INSERT INTO prostgles.app_triggers (table_name, condition, app_id)
|
|
1349
|
+
VALUES (${trgVals.tbl}, ${trgVals.cond}, ${(0, exports.asValue)(this.appID)})
|
|
1350
|
+
ON CONFLICT DO NOTHING;
|
|
1351
|
+
|
|
1352
|
+
COMMIT WORK;
|
|
1353
|
+
`);
|
|
1347
1354
|
(0, exports.log)("addTrigger.. ", { table_name, condition });
|
|
1348
1355
|
const triggers = await this.db.any(await this.getMyTriggerQuery());
|
|
1349
1356
|
this._triggers = {};
|
|
@@ -1392,6 +1399,7 @@ PubSubManager.create = async (options) => {
|
|
|
1392
1399
|
};
|
|
1393
1400
|
PubSubManager.SCHEMA_ALTERING_QUERIES = ['CREATE TABLE', 'ALTER TABLE', 'DROP TABLE', 'CREATE VIEW', 'DROP VIEW', 'ALTER VIEW', 'CREATE TABLE AS', 'SELECT INTO'];
|
|
1394
1401
|
PubSubManager.EXCLUDE_QUERY_FROM_SCHEMA_WATCH_ID = "prostgles internal query that should be excluded from ";
|
|
1402
|
+
const parseCondition = (condition) => Boolean(condition && condition.trim().length) ? condition : "TRUE";
|
|
1395
1403
|
function omitKeys(obj, exclude) {
|
|
1396
1404
|
return pickKeys(obj, (0, prostgles_types_1.getKeys)(obj).filter(k => !exclude.includes(k)));
|
|
1397
1405
|
}
|
package/lib/PubSubManager.ts
CHANGED
|
@@ -75,6 +75,17 @@ type SubscriptionParams = {
|
|
|
75
75
|
channel_name: string;
|
|
76
76
|
table_name: string;
|
|
77
77
|
socket: PRGLIOSocket | undefined;
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* If this is a view then an array with all related tables will be
|
|
81
|
+
* */
|
|
82
|
+
relatedTableSubscriptions?: {
|
|
83
|
+
tableName: string;
|
|
84
|
+
tableNameEscaped: string;
|
|
85
|
+
condition: string;
|
|
86
|
+
}[];
|
|
87
|
+
parentSubParams: Omit<SubscriptionParams, "parentSubParams"> | undefined;
|
|
88
|
+
|
|
78
89
|
table_info: TableOrViewInfo;
|
|
79
90
|
table_rules?: TableRule;
|
|
80
91
|
filter: object;
|
|
@@ -342,8 +353,8 @@ export class PubSubManager {
|
|
|
342
353
|
|
|
343
354
|
-- Force table into cache
|
|
344
355
|
IF EXISTS (select * from pg_extension where extname = 'pg_prewarm') THEN
|
|
345
|
-
|
|
346
|
-
|
|
356
|
+
CREATE EXTENSION IF NOT EXISTS pg_prewarm;
|
|
357
|
+
PERFORM pg_prewarm('prostgles.app_triggers');
|
|
347
358
|
END IF;
|
|
348
359
|
*/
|
|
349
360
|
|
|
@@ -369,20 +380,24 @@ export class PubSubManager {
|
|
|
369
380
|
-- PERFORM pg_notify('debug', concat_ws(' ', 'TABLE', TG_TABLE_NAME, TG_OP));
|
|
370
381
|
|
|
371
382
|
SELECT string_agg(
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
383
|
+
concat_ws(
|
|
384
|
+
E' UNION \n ',
|
|
385
|
+
CASE WHEN (TG_OP = 'DELETE' OR TG_OP = 'UPDATE') THEN (p1 || ' old_table ' || p2) END,
|
|
386
|
+
CASE WHEN (TG_OP = 'INSERT' OR TG_OP = 'UPDATE') THEN (p1 || ' new_table ' || p2) END
|
|
387
|
+
),
|
|
388
|
+
E' UNION \n '::text
|
|
378
389
|
)
|
|
379
390
|
INTO unions
|
|
380
391
|
FROM (
|
|
381
392
|
SELECT
|
|
382
|
-
$z$
|
|
393
|
+
$z$
|
|
394
|
+
SELECT CASE WHEN EXISTS( SELECT 1 FROM
|
|
395
|
+
$z$ AS p1,
|
|
383
396
|
format(
|
|
384
|
-
|
|
385
|
-
|
|
397
|
+
$c$
|
|
398
|
+
as %I WHERE %s ) THEN %s::text END AS t_ids
|
|
399
|
+
$c$,
|
|
400
|
+
table_name, condition, id
|
|
386
401
|
) AS p2
|
|
387
402
|
FROM prostgles.v_triggers
|
|
388
403
|
WHERE table_name = TG_TABLE_NAME
|
|
@@ -390,15 +405,15 @@ export class PubSubManager {
|
|
|
390
405
|
|
|
391
406
|
/*
|
|
392
407
|
PERFORM pg_notify(
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
408
|
+
${asValue(this.NOTIF_CHANNEL.preffix)} || (SELECT id FROM prostgles.apps LIMIT 1) ,
|
|
409
|
+
concat_ws(
|
|
410
|
+
${asValue(PubSubManager.DELIMITER)},
|
|
411
|
+
|
|
412
|
+
${asValue(this.NOTIF_TYPE.data)},
|
|
413
|
+
COALESCE(TG_TABLE_NAME, 'MISSING'),
|
|
414
|
+
COALESCE(TG_OP, 'MISSING'),
|
|
415
|
+
unions
|
|
416
|
+
)
|
|
402
417
|
);
|
|
403
418
|
RAISE 'unions: % , cids: %', unions, c_ids;
|
|
404
419
|
*/
|
|
@@ -406,25 +421,25 @@ export class PubSubManager {
|
|
|
406
421
|
IF unions IS NOT NULL THEN
|
|
407
422
|
query = format(
|
|
408
423
|
$s$
|
|
409
|
-
|
|
410
|
-
|
|
424
|
+
SELECT ARRAY_AGG(DISTINCT t.t_ids)
|
|
425
|
+
FROM ( %s ) t
|
|
411
426
|
$s$,
|
|
412
427
|
unions
|
|
413
428
|
);
|
|
414
429
|
|
|
415
430
|
BEGIN
|
|
416
|
-
|
|
431
|
+
EXECUTE query INTO t_ids;
|
|
417
432
|
|
|
418
|
-
|
|
433
|
+
--RAISE NOTICE 'trigger fired ok';
|
|
419
434
|
|
|
420
435
|
EXCEPTION WHEN OTHERS THEN
|
|
421
|
-
|
|
422
|
-
|
|
436
|
+
|
|
437
|
+
has_errors := TRUE;
|
|
423
438
|
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
439
|
+
GET STACKED DIAGNOSTICS
|
|
440
|
+
err_text = MESSAGE_TEXT,
|
|
441
|
+
err_detail = PG_EXCEPTION_DETAIL,
|
|
442
|
+
err_hint = PG_EXCEPTION_HINT;
|
|
428
443
|
|
|
429
444
|
|
|
430
445
|
END;
|
|
@@ -986,7 +1001,7 @@ export class PubSubManager {
|
|
|
986
1001
|
}
|
|
987
1002
|
|
|
988
1003
|
getSubs(table_name: string, condition: string): SubscriptionParams[] {
|
|
989
|
-
return
|
|
1004
|
+
return this.subs?.[table_name]?.[condition]?.subs
|
|
990
1005
|
}
|
|
991
1006
|
|
|
992
1007
|
getSyncs(table_name: string, condition: string) {
|
|
@@ -1185,7 +1200,7 @@ export class PubSubManager {
|
|
|
1185
1200
|
params, condition = "", throttle = 0
|
|
1186
1201
|
} = syncParams || {};
|
|
1187
1202
|
|
|
1188
|
-
let conditionParsed =
|
|
1203
|
+
let conditionParsed = parseCondition(condition);
|
|
1189
1204
|
if (!socket || !table_info) throw "socket or table_info missing";
|
|
1190
1205
|
|
|
1191
1206
|
|
|
@@ -1289,16 +1304,16 @@ export class PubSubManager {
|
|
|
1289
1304
|
await this.addTrigger({ table_name, condition: conditionParsed });
|
|
1290
1305
|
|
|
1291
1306
|
return channel_name;
|
|
1292
|
-
}
|
|
1293
|
-
|
|
1294
|
-
parseCondition = (condition: string): string => Boolean(condition && condition.trim().length) ? condition : "TRUE"
|
|
1307
|
+
}
|
|
1308
|
+
|
|
1295
1309
|
|
|
1296
1310
|
/* Must return a channel for socket */
|
|
1297
1311
|
/* The distinct list of channel names must have a corresponding trigger in the database */
|
|
1298
|
-
async addSub(subscriptionParams: Omit<AddSubscriptionParams, "channel_name">) {
|
|
1312
|
+
async addSub(subscriptionParams: Omit<AddSubscriptionParams, "channel_name" | "parentSubParams">) {
|
|
1299
1313
|
const {
|
|
1300
1314
|
socket, func = null, table_info = null, table_rules, filter = {},
|
|
1301
|
-
params = {}, condition = "", throttle = 0 //subOne = false,
|
|
1315
|
+
params = {}, condition = "", throttle = 0, //subOne = false,
|
|
1316
|
+
relatedTableSubscriptions
|
|
1302
1317
|
} = subscriptionParams || {};
|
|
1303
1318
|
|
|
1304
1319
|
let validated_throttle = subscriptionParams.throttle || 10;
|
|
@@ -1312,13 +1327,13 @@ export class PubSubManager {
|
|
|
1312
1327
|
validated_throttle = throttle;
|
|
1313
1328
|
}
|
|
1314
1329
|
|
|
1315
|
-
|
|
1330
|
+
const channel_name = `${this.socketChannelPreffix}.${table_info.name}.${JSON.stringify(filter)}.${JSON.stringify(params)}.${"m"}.sub`;
|
|
1316
1331
|
|
|
1317
1332
|
this.upsertSocket(socket, channel_name);
|
|
1318
1333
|
|
|
1319
|
-
const upsertSub = (newSubData: { table_name: string
|
|
1320
|
-
const { table_name, condition: _cond, is_ready = false } = newSubData,
|
|
1321
|
-
condition =
|
|
1334
|
+
const upsertSub = (newSubData: { table_name: string; condition: string; is_ready: boolean; parentSubParams: SubscriptionParams["parentSubParams"] }) => {
|
|
1335
|
+
const { table_name, condition: _cond, is_ready = false, parentSubParams } = newSubData,
|
|
1336
|
+
condition = parseCondition(_cond),
|
|
1322
1337
|
newSub: SubscriptionParams = {
|
|
1323
1338
|
socket,
|
|
1324
1339
|
table_name: table_info.name,
|
|
@@ -1327,18 +1342,18 @@ export class PubSubManager {
|
|
|
1327
1342
|
params,
|
|
1328
1343
|
table_rules,
|
|
1329
1344
|
channel_name,
|
|
1330
|
-
|
|
1345
|
+
parentSubParams,
|
|
1346
|
+
func: func ?? undefined,
|
|
1331
1347
|
socket_id: socket?.id,
|
|
1332
1348
|
throttle: validated_throttle,
|
|
1333
1349
|
is_throttling: null,
|
|
1334
1350
|
last_throttled: 0,
|
|
1335
1351
|
is_ready,
|
|
1336
|
-
// subOne
|
|
1337
1352
|
};
|
|
1338
1353
|
|
|
1339
|
-
this.subs[table_name] = this.subs[table_name]
|
|
1340
|
-
this.subs[table_name][condition] = this.subs[table_name][condition]
|
|
1341
|
-
this.subs[table_name][condition].subs = this.subs[table_name][condition].subs
|
|
1354
|
+
this.subs[table_name] = this.subs[table_name] ?? {};
|
|
1355
|
+
this.subs[table_name][condition] = this.subs[table_name][condition] ?? { subs: [] };
|
|
1356
|
+
this.subs[table_name][condition].subs = this.subs[table_name][condition].subs ?? [];
|
|
1342
1357
|
|
|
1343
1358
|
// console.log("1034 upsertSub", this.subs)
|
|
1344
1359
|
const sub_idx = this.subs[table_name][condition].subs.findIndex(s =>
|
|
@@ -1368,26 +1383,28 @@ export class PubSubManager {
|
|
|
1368
1383
|
};
|
|
1369
1384
|
|
|
1370
1385
|
|
|
1371
|
-
if (table_info.is_view &&
|
|
1372
|
-
if (
|
|
1373
|
-
|
|
1374
|
-
|
|
1375
|
-
|
|
1376
|
-
|
|
1386
|
+
if (table_info.is_view && relatedTableSubscriptions) {
|
|
1387
|
+
if (relatedTableSubscriptions.length) {
|
|
1388
|
+
|
|
1389
|
+
relatedTableSubscriptions.map(async relatedTable => {
|
|
1390
|
+
const params: Omit<Parameters<typeof upsertSub>[0], "is_ready"> = {
|
|
1391
|
+
table_name: relatedTable.tableNameEscaped,
|
|
1392
|
+
condition: relatedTable.condition,
|
|
1393
|
+
parentSubParams: {
|
|
1394
|
+
...subscriptionParams,
|
|
1395
|
+
channel_name
|
|
1396
|
+
},
|
|
1397
|
+
}
|
|
1398
|
+
|
|
1377
1399
|
upsertSub({
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
is_ready: true
|
|
1400
|
+
...params,
|
|
1401
|
+
is_ready: false
|
|
1381
1402
|
});
|
|
1382
1403
|
|
|
1383
|
-
await this.addTrigger(
|
|
1384
|
-
table_name,
|
|
1385
|
-
condition: _condition
|
|
1386
|
-
});
|
|
1404
|
+
await this.addTrigger(params);
|
|
1387
1405
|
|
|
1388
1406
|
upsertSub({
|
|
1389
|
-
|
|
1390
|
-
condition: _condition,
|
|
1407
|
+
...params,
|
|
1391
1408
|
is_ready: true
|
|
1392
1409
|
});
|
|
1393
1410
|
});
|
|
@@ -1403,16 +1420,18 @@ export class PubSubManager {
|
|
|
1403
1420
|
|
|
1404
1421
|
upsertSub({
|
|
1405
1422
|
table_name: table_info.name,
|
|
1406
|
-
condition:
|
|
1423
|
+
condition: parseCondition(condition),
|
|
1424
|
+
parentSubParams: undefined,
|
|
1407
1425
|
is_ready: false
|
|
1408
1426
|
});
|
|
1409
1427
|
await this.addTrigger({
|
|
1410
1428
|
table_name: table_info.name,
|
|
1411
|
-
condition:
|
|
1429
|
+
condition: parseCondition(condition),
|
|
1412
1430
|
});
|
|
1413
1431
|
upsertSub({
|
|
1414
1432
|
table_name: table_info.name,
|
|
1415
|
-
condition:
|
|
1433
|
+
condition: parseCondition(condition),
|
|
1434
|
+
parentSubParams: undefined,
|
|
1416
1435
|
is_ready: true
|
|
1417
1436
|
});
|
|
1418
1437
|
|
|
@@ -1421,7 +1440,7 @@ export class PubSubManager {
|
|
|
1421
1440
|
}
|
|
1422
1441
|
|
|
1423
1442
|
removeLocalSub(table_name: string, condition: string, func: (items: object[]) => any) {
|
|
1424
|
-
let cond =
|
|
1443
|
+
let cond = parseCondition(condition);
|
|
1425
1444
|
if (get(this.subs, [table_name, cond, "subs"])) {
|
|
1426
1445
|
this.subs[table_name][cond].subs.map((sub, i) => {
|
|
1427
1446
|
if (
|
|
@@ -1538,11 +1557,11 @@ export class PubSubManager {
|
|
|
1538
1557
|
|
|
1539
1558
|
getMyTriggerQuery = async () => {
|
|
1540
1559
|
return pgp.as.format(`
|
|
1541
|
-
|
|
1542
|
-
|
|
1543
|
-
|
|
1544
|
-
|
|
1545
|
-
|
|
1560
|
+
SELECT * --, ROW_NUMBER() OVER(PARTITION BY table_name ORDER BY table_name, condition ) - 1 as id
|
|
1561
|
+
FROM prostgles.v_triggers
|
|
1562
|
+
WHERE app_id = $1
|
|
1563
|
+
ORDER BY table_name, condition
|
|
1564
|
+
`, [this.appID]
|
|
1546
1565
|
)
|
|
1547
1566
|
}
|
|
1548
1567
|
|
|
@@ -1556,9 +1575,9 @@ export class PubSubManager {
|
|
|
1556
1575
|
if (!table_name) throw "MISSING table_name";
|
|
1557
1576
|
if (!this.appID) throw "MISSING appID";
|
|
1558
1577
|
|
|
1559
|
-
if (!condition || !condition.trim().length)
|
|
1560
|
-
|
|
1561
|
-
|
|
1578
|
+
if (!condition || !condition.trim().length) {
|
|
1579
|
+
condition = "TRUE";
|
|
1580
|
+
}
|
|
1562
1581
|
|
|
1563
1582
|
// console.log(1623, { app_id, addTrigger: { table_name, condition } });
|
|
1564
1583
|
|
|
@@ -1567,18 +1586,18 @@ export class PubSubManager {
|
|
|
1567
1586
|
const trgVals = {
|
|
1568
1587
|
tbl: asValue(table_name),
|
|
1569
1588
|
cond: asValue(condition),
|
|
1570
|
-
}
|
|
1589
|
+
};
|
|
1571
1590
|
|
|
1572
1591
|
await this.db.any(`
|
|
1573
|
-
|
|
1574
|
-
|
|
1592
|
+
BEGIN WORK;
|
|
1593
|
+
LOCK TABLE prostgles.app_triggers IN ACCESS EXCLUSIVE MODE;
|
|
1575
1594
|
|
|
1576
|
-
|
|
1577
|
-
|
|
1578
|
-
|
|
1579
|
-
|
|
1580
|
-
|
|
1581
|
-
|
|
1595
|
+
INSERT INTO prostgles.app_triggers (table_name, condition, app_id)
|
|
1596
|
+
VALUES (${trgVals.tbl}, ${trgVals.cond}, ${asValue(this.appID)})
|
|
1597
|
+
ON CONFLICT DO NOTHING;
|
|
1598
|
+
|
|
1599
|
+
COMMIT WORK;
|
|
1600
|
+
`);
|
|
1582
1601
|
|
|
1583
1602
|
log("addTrigger.. ", { table_name, condition });
|
|
1584
1603
|
|
|
@@ -1611,6 +1630,9 @@ export class PubSubManager {
|
|
|
1611
1630
|
}
|
|
1612
1631
|
}
|
|
1613
1632
|
|
|
1633
|
+
|
|
1634
|
+
const parseCondition = (condition: string): string => Boolean(condition && condition.trim().length) ? condition : "TRUE"
|
|
1635
|
+
|
|
1614
1636
|
export function omitKeys<T extends AnyObject, Exclude extends keyof T>(obj: T, exclude: Exclude[]): Omit<T, Exclude> {
|
|
1615
1637
|
return pickKeys(obj, getKeys(obj).filter(k => !exclude.includes(k as any)))
|
|
1616
1638
|
}
|
package/lib/PublishParser.js
CHANGED
|
@@ -73,7 +73,7 @@ const RULE_TO_METHODS = [
|
|
|
73
73
|
sqlRule: "select",
|
|
74
74
|
methods: prostgles_types_1.RULE_METHODS.subscribe,
|
|
75
75
|
no_limits: { throttle: 0 },
|
|
76
|
-
table_only:
|
|
76
|
+
table_only: false,
|
|
77
77
|
allowed_params: ["throttle"],
|
|
78
78
|
hint: ` expecting "*" | true | { throttle: number } \n Will use "select" rules`
|
|
79
79
|
}
|