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.
Files changed (49) hide show
  1. package/dist/DboBuilder/TableHandler.d.ts +3 -11
  2. package/dist/DboBuilder/TableHandler.d.ts.map +1 -1
  3. package/dist/DboBuilder/TableHandler.js +0 -74
  4. package/dist/DboBuilder/TableHandler.js.map +1 -1
  5. package/dist/DboBuilder/ViewHandler.d.ts +9 -1
  6. package/dist/DboBuilder/ViewHandler.d.ts.map +1 -1
  7. package/dist/DboBuilder/ViewHandler.js +127 -0
  8. package/dist/DboBuilder/ViewHandler.js.map +1 -1
  9. package/dist/DboBuilder/runSQL.d.ts.map +1 -1
  10. package/dist/DboBuilder/runSQL.js +23 -3
  11. package/dist/DboBuilder/runSQL.js.map +1 -1
  12. package/dist/DboBuilder.d.ts +10 -0
  13. package/dist/DboBuilder.d.ts.map +1 -1
  14. package/dist/DboBuilder.js.map +1 -1
  15. package/dist/Prostgles.d.ts.map +1 -1
  16. package/dist/Prostgles.js +3 -2
  17. package/dist/Prostgles.js.map +1 -1
  18. package/dist/PubSubManager.d.ts +10 -2
  19. package/dist/PubSubManager.d.ts.map +1 -1
  20. package/dist/PubSubManager.js +83 -75
  21. package/dist/PubSubManager.js.map +1 -1
  22. package/dist/PublishParser.js +1 -1
  23. package/dist/PublishParser.js.map +1 -1
  24. package/lib/DboBuilder/TableHandler.d.ts +1 -9
  25. package/lib/DboBuilder/TableHandler.d.ts.map +1 -1
  26. package/lib/DboBuilder/TableHandler.js +0 -74
  27. package/lib/DboBuilder/TableHandler.ts +2 -86
  28. package/lib/DboBuilder/ViewHandler.d.ts +9 -1
  29. package/lib/DboBuilder/ViewHandler.d.ts.map +1 -1
  30. package/lib/DboBuilder/ViewHandler.js +127 -0
  31. package/lib/DboBuilder/ViewHandler.ts +157 -2
  32. package/lib/DboBuilder/runSQL.d.ts.map +1 -1
  33. package/lib/DboBuilder/runSQL.js +23 -3
  34. package/lib/DboBuilder/runSQL.ts +24 -3
  35. package/lib/DboBuilder.d.ts +10 -0
  36. package/lib/DboBuilder.d.ts.map +1 -1
  37. package/lib/DboBuilder.ts +15 -2
  38. package/lib/Prostgles.d.ts.map +1 -1
  39. package/lib/Prostgles.js +3 -2
  40. package/lib/Prostgles.ts +3 -2
  41. package/lib/PubSubManager.d.ts +10 -2
  42. package/lib/PubSubManager.d.ts.map +1 -1
  43. package/lib/PubSubManager.js +83 -75
  44. package/lib/PubSubManager.ts +104 -82
  45. package/lib/PublishParser.js +1 -1
  46. package/lib/PublishParser.ts +1 -1
  47. package/package.json +2 -2
  48. package/tests/client/PID.txt +1 -1
  49. package/tests/server/package-lock.json +3 -3
@@ -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
- CREATE EXTENSION IF NOT EXISTS pg_prewarm;
228
- PERFORM pg_prewarm('prostgles.app_triggers');
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
- 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
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$ SELECT CASE WHEN EXISTS( SELECT 1 FROM $z$ AS p1,
264
+ $z$
265
+ SELECT CASE WHEN EXISTS( SELECT 1 FROM
266
+ $z$ AS p1,
265
267
  format(
266
- $c$ as %I WHERE %s ) THEN %s::text END AS t_ids $c$
267
- , table_name, condition, id
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
- ${(0, exports.asValue)(this.NOTIF_CHANNEL.preffix)} || (SELECT id FROM prostgles.apps LIMIT 1) ,
276
- concat_ws(
277
- ${(0, exports.asValue)(PubSubManager.DELIMITER)},
278
-
279
- ${(0, exports.asValue)(this.NOTIF_TYPE.data)},
280
- COALESCE(TG_TABLE_NAME, 'MISSING'),
281
- COALESCE(TG_OP, 'MISSING'),
282
- unions
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
- SELECT ARRAY_AGG(DISTINCT t.t_ids)
292
- FROM ( %s ) t
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
- EXECUTE query INTO t_ids;
302
+ EXECUTE query INTO t_ids;
299
303
 
300
- --RAISE NOTICE 'trigger fired ok';
304
+ --RAISE NOTICE 'trigger fired ok';
301
305
 
302
306
  EXCEPTION WHEN OTHERS THEN
303
-
304
- has_errors := TRUE;
307
+
308
+ has_errors := TRUE;
305
309
 
306
- GET STACKED DIAGNOSTICS
307
- err_text = MESSAGE_TEXT,
308
- err_detail = PG_EXCEPTION_DETAIL,
309
- err_hint = PG_EXCEPTION_HINT;
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
- SELECT * --, ROW_NUMBER() OVER(PARTITION BY table_name ORDER BY table_name, condition ) - 1 as id
972
- FROM prostgles.v_triggers
973
- WHERE app_id = $1
974
- ORDER BY table_name, condition
975
- `, [this.appID]);
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 (0, utils_1.get)(this.subs, [table_name, condition, "subs"]);
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 = this.parseCondition(condition);
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
- } = subscriptionParams || {};
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
- let channel_name = `${this.socketChannelPreffix}.${table_info.name}.${JSON.stringify(filter)}.${JSON.stringify(params)}.${"m"}.sub`; //.${subOne? "o" : "m"}.sub`;
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 = this.parseCondition(_cond), newSub = {
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
- func: func ? func : undefined,
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] || { subs: [] };
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 && table_info.parent_tables) {
1216
- if (table_info.parent_tables.length) {
1217
- let _condition = "TRUE";
1218
- table_info.parent_tables.map(async (table_name) => {
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
- table_name,
1221
- condition: _condition,
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
- table_name,
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: this.parseCondition(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: this.parseCondition(condition),
1257
+ condition: parseCondition(condition),
1252
1258
  });
1253
1259
  upsertSub({
1254
1260
  table_name: table_info.name,
1255
- condition: this.parseCondition(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 = this.parseCondition(condition);
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
- const app_id = this.appID;
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
- BEGIN WORK;
1339
- LOCK TABLE prostgles.app_triggers IN ACCESS EXCLUSIVE MODE;
1340
-
1341
- INSERT INTO prostgles.app_triggers (table_name, condition, app_id)
1342
- VALUES (${trgVals.tbl}, ${trgVals.cond}, ${(0, exports.asValue)(this.appID)})
1343
- ON CONFLICT DO NOTHING;
1344
-
1345
- COMMIT WORK;
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
  }
@@ -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
- CREATE EXTENSION IF NOT EXISTS pg_prewarm;
346
- PERFORM pg_prewarm('prostgles.app_triggers');
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
- concat_ws(
373
- E' UNION \n ',
374
- CASE WHEN (TG_OP = 'DELETE' OR TG_OP = 'UPDATE') THEN (p1 || ' old_table ' || p2) END,
375
- CASE WHEN (TG_OP = 'INSERT' OR TG_OP = 'UPDATE') THEN (p1 || ' new_table ' || p2) END
376
- ),
377
- E' UNION \n '::text
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$ SELECT CASE WHEN EXISTS( SELECT 1 FROM $z$ AS p1,
393
+ $z$
394
+ SELECT CASE WHEN EXISTS( SELECT 1 FROM
395
+ $z$ AS p1,
383
396
  format(
384
- $c$ as %I WHERE %s ) THEN %s::text END AS t_ids $c$
385
- , table_name, condition, id
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
- ${asValue(this.NOTIF_CHANNEL.preffix)} || (SELECT id FROM prostgles.apps LIMIT 1) ,
394
- concat_ws(
395
- ${asValue(PubSubManager.DELIMITER)},
396
-
397
- ${asValue(this.NOTIF_TYPE.data)},
398
- COALESCE(TG_TABLE_NAME, 'MISSING'),
399
- COALESCE(TG_OP, 'MISSING'),
400
- unions
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
- SELECT ARRAY_AGG(DISTINCT t.t_ids)
410
- FROM ( %s ) t
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
- EXECUTE query INTO t_ids;
431
+ EXECUTE query INTO t_ids;
417
432
 
418
- --RAISE NOTICE 'trigger fired ok';
433
+ --RAISE NOTICE 'trigger fired ok';
419
434
 
420
435
  EXCEPTION WHEN OTHERS THEN
421
-
422
- has_errors := TRUE;
436
+
437
+ has_errors := TRUE;
423
438
 
424
- GET STACKED DIAGNOSTICS
425
- err_text = MESSAGE_TEXT,
426
- err_detail = PG_EXCEPTION_DETAIL,
427
- err_hint = PG_EXCEPTION_HINT;
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 get(this.subs, [table_name, condition, "subs"])
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 = this.parseCondition(condition);
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
- let channel_name = `${this.socketChannelPreffix}.${table_info.name}.${JSON.stringify(filter)}.${JSON.stringify(params)}.${"m"}.sub`; //.${subOne? "o" : "m"}.sub`;
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, condition: string, is_ready: boolean }) => {
1320
- const { table_name, condition: _cond, is_ready = false } = newSubData,
1321
- condition = this.parseCondition(_cond),
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
- func: func ? func : undefined,
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] || { subs: [] };
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 && table_info.parent_tables) {
1372
- if (table_info.parent_tables.length) {
1373
-
1374
- let _condition = "TRUE";
1375
- table_info.parent_tables.map(async table_name => {
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
- table_name,
1379
- condition: _condition,
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
- table_name,
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: this.parseCondition(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: this.parseCondition(condition),
1429
+ condition: parseCondition(condition),
1412
1430
  });
1413
1431
  upsertSub({
1414
1432
  table_name: table_info.name,
1415
- condition: this.parseCondition(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 = this.parseCondition(condition);
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
- SELECT * --, ROW_NUMBER() OVER(PARTITION BY table_name ORDER BY table_name, condition ) - 1 as id
1542
- FROM prostgles.v_triggers
1543
- WHERE app_id = $1
1544
- ORDER BY table_name, condition
1545
- `, [this.appID]
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) condition = "TRUE";
1560
-
1561
- const app_id = this.appID;
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
- BEGIN WORK;
1574
- LOCK TABLE prostgles.app_triggers IN ACCESS EXCLUSIVE MODE;
1592
+ BEGIN WORK;
1593
+ LOCK TABLE prostgles.app_triggers IN ACCESS EXCLUSIVE MODE;
1575
1594
 
1576
- INSERT INTO prostgles.app_triggers (table_name, condition, app_id)
1577
- VALUES (${trgVals.tbl}, ${trgVals.cond}, ${asValue(this.appID)})
1578
- ON CONFLICT DO NOTHING;
1579
-
1580
- COMMIT WORK;
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
  }
@@ -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: true,
76
+ table_only: false,
77
77
  allowed_params: ["throttle"],
78
78
  hint: ` expecting "*" | true | { throttle: number } \n Will use "select" rules`
79
79
  }