prostgles-server 4.2.296 → 4.2.298
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/DboBuilder.d.ts.map +1 -1
- package/dist/DboBuilder/DboBuilder.js +5 -3
- package/dist/DboBuilder/DboBuilder.js.map +1 -1
- package/dist/DboBuilder/TableHandler/update.d.ts.map +1 -1
- package/dist/DboBuilder/TableHandler/update.js +2 -2
- package/dist/DboBuilder/TableHandler/update.js.map +1 -1
- package/dist/DboBuilder/ViewHandler/getValidatedSubscribeOptions.d.ts.map +1 -1
- package/dist/DboBuilder/ViewHandler/getValidatedSubscribeOptions.js +3 -1
- package/dist/DboBuilder/ViewHandler/getValidatedSubscribeOptions.js.map +1 -1
- package/dist/DboBuilder/ViewHandler/subscribe.d.ts.map +1 -1
- package/dist/DboBuilder/ViewHandler/subscribe.js +4 -3
- package/dist/DboBuilder/ViewHandler/subscribe.js.map +1 -1
- package/dist/DboBuilder/getSubscribeRelatedTables.d.ts.map +1 -1
- package/dist/DboBuilder/getSubscribeRelatedTables.js +5 -5
- package/dist/DboBuilder/getSubscribeRelatedTables.js.map +1 -1
- package/dist/PubSubManager/PubSubManager.d.ts +6 -13
- package/dist/PubSubManager/PubSubManager.d.ts.map +1 -1
- package/dist/PubSubManager/PubSubManager.js +2 -2
- package/dist/PubSubManager/PubSubManager.js.map +1 -1
- package/dist/PubSubManager/addSub.d.ts.map +1 -1
- package/dist/PubSubManager/addSub.js +7 -7
- package/dist/PubSubManager/addSub.js.map +1 -1
- package/dist/PubSubManager/addSync.d.ts.map +1 -1
- package/dist/PubSubManager/addSync.js +1 -1
- package/dist/PubSubManager/addSync.js.map +1 -1
- package/dist/PubSubManager/addTrigger.d.ts +4 -2
- package/dist/PubSubManager/addTrigger.d.ts.map +1 -1
- package/dist/PubSubManager/addTrigger.js +55 -3
- package/dist/PubSubManager/addTrigger.js.map +1 -1
- package/dist/PubSubManager/getCreatePubSubManagerError.js +1 -1
- package/dist/PubSubManager/getCreatePubSubManagerError.js.map +1 -1
- package/dist/PubSubManager/init/getDataWatchFunctionQuery.d.ts +5 -0
- package/dist/PubSubManager/init/getDataWatchFunctionQuery.d.ts.map +1 -1
- package/dist/PubSubManager/init/getDataWatchFunctionQuery.js +80 -51
- package/dist/PubSubManager/init/getDataWatchFunctionQuery.js.map +1 -1
- package/dist/PubSubManager/{getPubSubManagerInitQuery.d.ts → init/getPubSubManagerInitQuery.d.ts} +1 -1
- package/dist/PubSubManager/init/getPubSubManagerInitQuery.d.ts.map +1 -0
- package/dist/PubSubManager/{getPubSubManagerInitQuery.js → init/getPubSubManagerInitQuery.js} +22 -19
- package/dist/PubSubManager/init/getPubSubManagerInitQuery.js.map +1 -0
- package/dist/PubSubManager/{initPubSubManager.d.ts → init/initPubSubManager.d.ts} +1 -1
- package/dist/PubSubManager/init/initPubSubManager.d.ts.map +1 -0
- package/dist/PubSubManager/{initPubSubManager.js → init/initPubSubManager.js} +3 -3
- package/dist/PubSubManager/init/initPubSubManager.js.map +1 -0
- package/dist/PubSubManager/initialiseEventTriggers.js +1 -1
- package/dist/PubSubManager/initialiseEventTriggers.js.map +1 -1
- package/dist/PubSubManager/notifListener.d.ts.map +1 -1
- package/dist/PubSubManager/notifListener.js +15 -15
- package/dist/PubSubManager/notifListener.js.map +1 -1
- package/dist/PubSubManager/orphanTriggerCheck.js +1 -1
- package/dist/PubSubManager/orphanTriggerCheck.js.map +1 -1
- package/dist/TableConfig/runSQLFile.d.ts +3 -0
- package/dist/TableConfig/runSQLFile.d.ts.map +1 -1
- package/dist/TableConfig/runSQLFile.js +11 -1
- package/dist/TableConfig/runSQLFile.js.map +1 -1
- package/lib/DboBuilder/DboBuilder.ts +13 -3
- package/lib/DboBuilder/TableHandler/update.ts +2 -3
- package/lib/DboBuilder/ViewHandler/getValidatedSubscribeOptions.ts +9 -1
- package/lib/DboBuilder/ViewHandler/subscribe.ts +5 -3
- package/lib/DboBuilder/getSubscribeRelatedTables.ts +8 -5
- package/lib/PubSubManager/PubSubManager.ts +7 -12
- package/lib/PubSubManager/addSub.ts +10 -9
- package/lib/PubSubManager/addSync.ts +5 -1
- package/lib/PubSubManager/addTrigger.ts +77 -6
- package/lib/PubSubManager/getCreatePubSubManagerError.ts +1 -1
- package/lib/PubSubManager/init/getDataWatchFunctionQuery.ts +80 -50
- package/lib/PubSubManager/{getPubSubManagerInitQuery.ts → init/getPubSubManagerInitQuery.ts} +23 -20
- package/lib/PubSubManager/{initPubSubManager.ts → init/initPubSubManager.ts} +4 -4
- package/lib/PubSubManager/initialiseEventTriggers.ts +1 -1
- package/lib/PubSubManager/notifListener.ts +19 -28
- package/lib/PubSubManager/orphanTriggerCheck.ts +1 -1
- package/lib/TableConfig/runSQLFile.ts +19 -2
- package/package.json +2 -2
- package/dist/PubSubManager/getPubSubManagerInitQuery.d.ts.map +0 -1
- package/dist/PubSubManager/getPubSubManagerInitQuery.js.map +0 -1
- package/dist/PubSubManager/initPubSubManager.d.ts.map +0 -1
- package/dist/PubSubManager/initPubSubManager.js.map +0 -1
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
import { type Prostgles } from "../Prostgles";
|
|
2
2
|
export declare const runSQLFile: (prostgles: Prostgles) => Promise<number | undefined>;
|
|
3
|
+
/**
|
|
4
|
+
* Given an sql error, return the lines of the query that caused the error.
|
|
5
|
+
*/
|
|
3
6
|
export declare const getQueryErrorPositionInfo: (err: any, _fileContent?: string) => string | undefined;
|
|
4
7
|
//# sourceMappingURL=runSQLFile.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"runSQLFile.d.ts","sourceRoot":"","sources":["../../lib/TableConfig/runSQLFile.ts"],"names":[],"mappings":"AACA,OAAO,EAAe,KAAK,SAAS,EAAE,MAAM,cAAc,CAAC;AAE3D,eAAO,MAAM,UAAU,cAAqB,SAAS,gCAyBpD,CAAC;AAEF,eAAO,MAAM,yBAAyB,QAAS,GAAG,iBAAiB,MAAM,
|
|
1
|
+
{"version":3,"file":"runSQLFile.d.ts","sourceRoot":"","sources":["../../lib/TableConfig/runSQLFile.ts"],"names":[],"mappings":"AACA,OAAO,EAAe,KAAK,SAAS,EAAE,MAAM,cAAc,CAAC;AAE3D,eAAO,MAAM,UAAU,cAAqB,SAAS,gCAyBpD,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,yBAAyB,QAAS,GAAG,iBAAiB,MAAM,KAAG,MAAM,GAAG,SA4BpF,CAAC"}
|
|
@@ -28,8 +28,11 @@ const runSQLFile = async (prostgles) => {
|
|
|
28
28
|
return res.data?.success;
|
|
29
29
|
};
|
|
30
30
|
exports.runSQLFile = runSQLFile;
|
|
31
|
+
/**
|
|
32
|
+
* Given an sql error, return the lines of the query that caused the error.
|
|
33
|
+
*/
|
|
31
34
|
const getQueryErrorPositionInfo = (err, _fileContent) => {
|
|
32
|
-
const { position, length, query } = err, fileContent = _fileContent || query, lines = fileContent.split("\n");
|
|
35
|
+
const { position, length, query, internalPosition, internalQuery } = err, fileContent = _fileContent || query, lines = fileContent.split("\n");
|
|
33
36
|
if (position && length && fileContent) {
|
|
34
37
|
const startLine = Math.max(0, fileContent.substring(0, position).split("\n").length - 2), endLine = startLine + 3;
|
|
35
38
|
return lines
|
|
@@ -37,6 +40,13 @@ const getQueryErrorPositionInfo = (err, _fileContent) => {
|
|
|
37
40
|
.map((txt, i) => `${startLine + i + 1} ${i === 1 ? "->" : " "} ${txt}`)
|
|
38
41
|
.join("\n");
|
|
39
42
|
}
|
|
43
|
+
if (internalPosition && internalQuery) {
|
|
44
|
+
return (0, exports.getQueryErrorPositionInfo)({
|
|
45
|
+
query: internalQuery,
|
|
46
|
+
position: parseInt(internalPosition),
|
|
47
|
+
length: internalQuery.length,
|
|
48
|
+
});
|
|
49
|
+
}
|
|
40
50
|
};
|
|
41
51
|
exports.getQueryErrorPositionInfo = getQueryErrorPositionInfo;
|
|
42
52
|
//# sourceMappingURL=runSQLFile.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"runSQLFile.js","sourceRoot":"","sources":["../../lib/TableConfig/runSQLFile.ts"],"names":[],"mappings":";;;AAAA,qDAA6C;AAC7C,4CAA2D;AAEpD,MAAM,UAAU,GAAG,KAAK,EAAE,SAAoB,EAAE,EAAE;IACvD,MAAM,EACJ,EAAE,EACF,IAAI,EAAE,EAAE,WAAW,EAAE,KAAK,EAAE,GAC7B,GAAG,SAAS,CAAC;IACd,IAAI,CAAC,WAAW;QAAE,OAAO;IACzB,IAAI,CAAC,EAAE;QAAE,MAAM,YAAY,CAAC;IAC5B,MAAM,GAAG,GAAG,MAAM,IAAA,4BAAU,EAAC,KAAK,IAAI,EAAE;QACtC,MAAM,WAAW,GAAG,MAAM,IAAA,uBAAW,EAAC,WAAW,CAAC,CAAC;QAEnD,MAAM,MAAM,GAAG,MAAM,EAAE,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;YACvD,MAAM,OAAO,GAAG,IAAA,iCAAyB,EAAC,GAAG,EAAE,WAAW,CAAC,CAAC;YAC5D,OAAO,CAAC,KAAK,CAAC,oCAAoC,EAAE,WAAW,EAAE,OAAO,CAAC,CAAC;YAC1E,OAAO,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QAC7B,CAAC,CAAC,CAAC;QACH,OAAO,EAAE,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC;IACpC,CAAC,CAAC,CAAC;IAEH,MAAM,KAAK,EAAE,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,YAAY,EAAE,GAAG,GAAG,EAAE,CAAC,CAAC;IAChE,IAAI,GAAG,CAAC,KAAK,KAAK,SAAS,EAAE,CAAC;QAC5B,MAAM,GAAG,CAAC,KAAK,CAAC;IAClB,CAAC;SAAM,CAAC;QACN,OAAO,CAAC,GAAG,CAAC,2CAA2C,EAAE,WAAW,CAAC,CAAC;IACxE,CAAC;IACD,OAAO,GAAG,CAAC,IAAI,EAAE,OAAO,CAAC;AAC3B,CAAC,CAAC;AAzBW,QAAA,UAAU,cAyBrB;
|
|
1
|
+
{"version":3,"file":"runSQLFile.js","sourceRoot":"","sources":["../../lib/TableConfig/runSQLFile.ts"],"names":[],"mappings":";;;AAAA,qDAA6C;AAC7C,4CAA2D;AAEpD,MAAM,UAAU,GAAG,KAAK,EAAE,SAAoB,EAAE,EAAE;IACvD,MAAM,EACJ,EAAE,EACF,IAAI,EAAE,EAAE,WAAW,EAAE,KAAK,EAAE,GAC7B,GAAG,SAAS,CAAC;IACd,IAAI,CAAC,WAAW;QAAE,OAAO;IACzB,IAAI,CAAC,EAAE;QAAE,MAAM,YAAY,CAAC;IAC5B,MAAM,GAAG,GAAG,MAAM,IAAA,4BAAU,EAAC,KAAK,IAAI,EAAE;QACtC,MAAM,WAAW,GAAG,MAAM,IAAA,uBAAW,EAAC,WAAW,CAAC,CAAC;QAEnD,MAAM,MAAM,GAAG,MAAM,EAAE,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;YACvD,MAAM,OAAO,GAAG,IAAA,iCAAyB,EAAC,GAAG,EAAE,WAAW,CAAC,CAAC;YAC5D,OAAO,CAAC,KAAK,CAAC,oCAAoC,EAAE,WAAW,EAAE,OAAO,CAAC,CAAC;YAC1E,OAAO,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QAC7B,CAAC,CAAC,CAAC;QACH,OAAO,EAAE,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC;IACpC,CAAC,CAAC,CAAC;IAEH,MAAM,KAAK,EAAE,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,YAAY,EAAE,GAAG,GAAG,EAAE,CAAC,CAAC;IAChE,IAAI,GAAG,CAAC,KAAK,KAAK,SAAS,EAAE,CAAC;QAC5B,MAAM,GAAG,CAAC,KAAK,CAAC;IAClB,CAAC;SAAM,CAAC;QACN,OAAO,CAAC,GAAG,CAAC,2CAA2C,EAAE,WAAW,CAAC,CAAC;IACxE,CAAC;IACD,OAAO,GAAG,CAAC,IAAI,EAAE,OAAO,CAAC;AAC3B,CAAC,CAAC;AAzBW,QAAA,UAAU,cAyBrB;AAEF;;GAEG;AACI,MAAM,yBAAyB,GAAG,CAAC,GAAQ,EAAE,YAAqB,EAAsB,EAAE;IAC/F,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,gBAAgB,EAAE,aAAa,EAAE,GAAG,GAMlE,EACD,WAAW,GAAG,YAAY,IAAI,KAAK,EACnC,KAAK,GAAG,WAAW,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAElC,IAAI,QAAQ,IAAI,MAAM,IAAI,WAAW,EAAE,CAAC;QACtC,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,WAAW,CAAC,SAAS,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,EACtF,OAAO,GAAG,SAAS,GAAG,CAAC,CAAC;QAE1B,OAAO,KAAK;aACT,KAAK,CAAC,SAAS,EAAE,OAAO,CAAC;aACzB,GAAG,CAAC,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,GAAG,SAAS,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,IAAI,GAAG,EAAE,CAAC;aACvE,IAAI,CAAC,IAAI,CAAC,CAAC;IAChB,CAAC;IAED,IAAI,gBAAgB,IAAI,aAAa,EAAE,CAAC;QACtC,OAAO,IAAA,iCAAyB,EAAC;YAC/B,KAAK,EAAE,aAAa;YACpB,QAAQ,EAAE,QAAQ,CAAC,gBAAgB,CAAC;YACpC,MAAM,EAAE,aAAa,CAAC,MAAM;SAC7B,CAAC,CAAC;IACL,CAAC;AACH,CAAC,CAAC;AA5BW,QAAA,yBAAyB,6BA4BpC"}
|
|
@@ -7,8 +7,12 @@ import {
|
|
|
7
7
|
PG_COLUMN_UDT_DATA_TYPE,
|
|
8
8
|
SQLOptions,
|
|
9
9
|
getJoinHandlers,
|
|
10
|
+
getSerialisableError,
|
|
10
11
|
isDefined,
|
|
12
|
+
omitKeys,
|
|
11
13
|
tryCatch,
|
|
14
|
+
tryCatchV2,
|
|
15
|
+
type AnyObject,
|
|
12
16
|
} from "prostgles-types";
|
|
13
17
|
import { getDBSchema } from "../DBSchemaBuilder";
|
|
14
18
|
import { DB, Prostgles } from "../Prostgles";
|
|
@@ -40,6 +44,7 @@ import {
|
|
|
40
44
|
import { getTablesForSchemaPostgresSQL } from "./getTablesForSchemaPostgresSQL";
|
|
41
45
|
import { prepareShortestJoinPaths } from "./prepareShortestJoinPaths";
|
|
42
46
|
import { cacheDBTypes, runSQL } from "./runSQL";
|
|
47
|
+
import { getQueryErrorPositionInfo } from "../TableConfig/runSQLFile";
|
|
43
48
|
|
|
44
49
|
export * from "./DboBuilderTypes";
|
|
45
50
|
export * from "./dboBuilderUtils";
|
|
@@ -109,9 +114,13 @@ export class DboBuilder {
|
|
|
109
114
|
if (!canExecute)
|
|
110
115
|
throw "PubSubManager based subscriptions not possible: Cannot run EXECUTE statements on this connection";
|
|
111
116
|
|
|
112
|
-
const {
|
|
117
|
+
const {
|
|
118
|
+
data: pubSubManager,
|
|
119
|
+
error,
|
|
120
|
+
hasError,
|
|
121
|
+
} = await tryCatchV2(async () => {
|
|
113
122
|
const pubSubManager = await PubSubManager.create(this);
|
|
114
|
-
return
|
|
123
|
+
return pubSubManager;
|
|
115
124
|
});
|
|
116
125
|
this._pubSubManager = pubSubManager;
|
|
117
126
|
if (hasError || !this._pubSubManager) {
|
|
@@ -119,8 +128,9 @@ export class DboBuilder {
|
|
|
119
128
|
type: "debug",
|
|
120
129
|
command: "PubSubManager.create",
|
|
121
130
|
duration: 0,
|
|
122
|
-
error:
|
|
131
|
+
error: getSerialisableError(error),
|
|
123
132
|
});
|
|
133
|
+
console.error("Could not create PubSubManager", getQueryErrorPositionInfo(error));
|
|
124
134
|
throw "Could not create this._pubSubManager check logs";
|
|
125
135
|
}
|
|
126
136
|
}
|
|
@@ -6,10 +6,9 @@ import {
|
|
|
6
6
|
getErrorAsObject,
|
|
7
7
|
getSerializedClientErrorFromPGError,
|
|
8
8
|
withUserRLS,
|
|
9
|
-
type TableHandlers,
|
|
10
9
|
} from "../DboBuilder";
|
|
11
|
-
import { getInsertTableRules, getReferenceColumnInserts } from "./insert/insertNestedRecords";
|
|
12
10
|
import { prepareNewData } from "./DataValidator";
|
|
11
|
+
import { getInsertTableRules, getReferenceColumnInserts } from "./insert/insertNestedRecords";
|
|
13
12
|
import { runInsertUpdateQuery } from "./runInsertUpdateQuery";
|
|
14
13
|
import { TableHandler } from "./TableHandler";
|
|
15
14
|
import { updateFile } from "./updateFile";
|
|
@@ -82,7 +81,7 @@ export async function update(
|
|
|
82
81
|
);
|
|
83
82
|
}
|
|
84
83
|
|
|
85
|
-
const { data, allowedCols } =
|
|
84
|
+
const { data, allowedCols } = prepareNewData({
|
|
86
85
|
row: newData,
|
|
87
86
|
forcedData,
|
|
88
87
|
allowedFields: fields,
|
|
@@ -16,6 +16,7 @@ export const getValidatedSubscribeOptions = (
|
|
|
16
16
|
optional: true,
|
|
17
17
|
},
|
|
18
18
|
skipFirst: { type: "boolean", optional: true },
|
|
19
|
+
skipChangedColumnsCheck: { type: "boolean", optional: true },
|
|
19
20
|
actions: {
|
|
20
21
|
oneOf: [
|
|
21
22
|
{
|
|
@@ -48,7 +49,13 @@ export const getValidatedSubscribeOptions = (
|
|
|
48
49
|
}
|
|
49
50
|
|
|
50
51
|
const publishedThrottle = subscribeRule?.throttle || 0;
|
|
51
|
-
const {
|
|
52
|
+
const {
|
|
53
|
+
actions,
|
|
54
|
+
throttleOpts,
|
|
55
|
+
skipFirst,
|
|
56
|
+
throttle = publishedThrottle,
|
|
57
|
+
skipChangedColumnsCheck,
|
|
58
|
+
} = data;
|
|
52
59
|
if (actions && isEmpty(actions)) {
|
|
53
60
|
throw `addSub: actions cannot be empty`;
|
|
54
61
|
}
|
|
@@ -68,5 +75,6 @@ export const getValidatedSubscribeOptions = (
|
|
|
68
75
|
skipFirst,
|
|
69
76
|
throttle,
|
|
70
77
|
throttleOpts,
|
|
78
|
+
skipChangedColumnsCheck,
|
|
71
79
|
};
|
|
72
80
|
};
|
|
@@ -81,7 +81,8 @@ async function subscribe(
|
|
|
81
81
|
throw " Cannot have localFunc AND socket ";
|
|
82
82
|
}
|
|
83
83
|
|
|
84
|
-
const { throttle, throttleOpts, skipFirst, actions, ...selectParams } =
|
|
84
|
+
const { throttle, throttleOpts, skipFirst, actions, skipChangedColumnsCheck, ...selectParams } =
|
|
85
|
+
params;
|
|
85
86
|
|
|
86
87
|
/** Ensure request is valid */
|
|
87
88
|
await this.find(filter, { ...selectParams, limit: 0 }, undefined, table_rules, localParams);
|
|
@@ -101,6 +102,7 @@ async function subscribe(
|
|
|
101
102
|
newQuery,
|
|
102
103
|
});
|
|
103
104
|
|
|
105
|
+
const tracked_columns = newQuery.select.filter((s) => s.selected).flatMap((c) => c.fields);
|
|
104
106
|
const commonSubOpts = {
|
|
105
107
|
table_info: this.tableOrViewInfo,
|
|
106
108
|
viewOptions,
|
|
@@ -110,11 +112,11 @@ async function subscribe(
|
|
|
110
112
|
filter: { ...filter },
|
|
111
113
|
selectParams: { ...selectParams },
|
|
112
114
|
subscribeOptions: getValidatedSubscribeOptions(
|
|
113
|
-
{ actions, skipFirst, throttle, throttleOpts },
|
|
115
|
+
{ actions, skipFirst, throttle, throttleOpts, skipChangedColumnsCheck },
|
|
114
116
|
table_rules?.subscribe
|
|
115
117
|
),
|
|
116
118
|
lastPushed: 0,
|
|
117
|
-
|
|
119
|
+
tracked_columns,
|
|
118
120
|
} as const;
|
|
119
121
|
|
|
120
122
|
const pubSubManager = await this.dboBuilder.getPubSubManager();
|
|
@@ -34,12 +34,14 @@ export async function getSubscribeRelatedTables(
|
|
|
34
34
|
/** TODO: this needs to be memoized on schema fetch */
|
|
35
35
|
const viewName = this.name;
|
|
36
36
|
const viewNameEscaped = this.escapedName;
|
|
37
|
-
const { current_schema } = await this.db.
|
|
37
|
+
const { current_schema } = await this.db.one<{ current_schema: string }>(
|
|
38
|
+
"SELECT current_schema"
|
|
39
|
+
);
|
|
38
40
|
|
|
39
41
|
/** Get list of used columns and their parent tables */
|
|
40
|
-
let { def } =
|
|
42
|
+
let { def } = await this.db.one<{ def: string }>("SELECT pg_get_viewdef(${viewName}) as def", {
|
|
41
43
|
viewName,
|
|
42
|
-
})
|
|
44
|
+
});
|
|
43
45
|
def = def.trim();
|
|
44
46
|
if (def.endsWith(";")) {
|
|
45
47
|
def = def.slice(0, -1);
|
|
@@ -53,7 +55,8 @@ export async function getSubscribeRelatedTables(
|
|
|
53
55
|
}
|
|
54
56
|
const { fields } = await this.dboBuilder.dbo.sql!(
|
|
55
57
|
`SELECT * FROM ( \n ${def} \n ) prostgles_subscribe_view_definition LIMIT 0`,
|
|
56
|
-
{}
|
|
58
|
+
{},
|
|
59
|
+
{ returnType: "default-with-rollback" }
|
|
57
60
|
);
|
|
58
61
|
const tableColumns = fields.filter((f) => f.tableName && f.columnName);
|
|
59
62
|
|
|
@@ -96,7 +99,7 @@ export async function getSubscribeRelatedTables(
|
|
|
96
99
|
)`;
|
|
97
100
|
|
|
98
101
|
try {
|
|
99
|
-
const { count } = await this.db.
|
|
102
|
+
const { count } = await this.db.one<{ count: number }>(`
|
|
100
103
|
WITH ${asName(tableName)} AS (
|
|
101
104
|
SELECT *
|
|
102
105
|
FROM ${asName(tableName)}
|
|
@@ -13,10 +13,10 @@ import {
|
|
|
13
13
|
import { PostgresNotifListenManager } from "../PostgresNotifListenManager";
|
|
14
14
|
import { DB } from "../Prostgles";
|
|
15
15
|
import { addSync } from "./addSync";
|
|
16
|
-
import { addTrigger } from "./addTrigger";
|
|
16
|
+
import { addTrigger, type AddTriggerParams } from "./addTrigger";
|
|
17
17
|
import { deleteOrphanedTriggers } from "./deleteOrphanedTriggers";
|
|
18
|
+
import { initPubSubManager } from "./init/initPubSubManager";
|
|
18
19
|
import { initialiseEventTriggers } from "./initialiseEventTriggers";
|
|
19
|
-
import { initPubSubManager } from "./initPubSubManager";
|
|
20
20
|
import { refreshTriggers } from "./refreshTriggers";
|
|
21
21
|
|
|
22
22
|
import {
|
|
@@ -35,9 +35,8 @@ import { ParsedTableRule } from "../PublishParser/PublishParser";
|
|
|
35
35
|
import { syncData } from "../SyncReplication";
|
|
36
36
|
import { addSub } from "./addSub";
|
|
37
37
|
import { notifListener } from "./notifListener";
|
|
38
|
-
import { pushSubData } from "./pushSubData";
|
|
39
38
|
import { log } from "./PubSubManagerUtils";
|
|
40
|
-
import
|
|
39
|
+
import { pushSubData } from "./pushSubData";
|
|
41
40
|
|
|
42
41
|
export type BasicCallback = (err?: any, res?: any) => void;
|
|
43
42
|
|
|
@@ -101,7 +100,7 @@ export type SubscriptionParams = {
|
|
|
101
100
|
channel_name: string;
|
|
102
101
|
|
|
103
102
|
/**
|
|
104
|
-
* If this is a view then
|
|
103
|
+
* If this is a view then all related tables will be added triggers
|
|
105
104
|
* */
|
|
106
105
|
viewOptions?: ViewSubscriptionOptions;
|
|
107
106
|
parentSubParams: Omit<SubscriptionParams, "parentSubParams"> | undefined;
|
|
@@ -113,7 +112,7 @@ export type SubscriptionParams = {
|
|
|
113
112
|
filter: object;
|
|
114
113
|
selectParams: SelectParams;
|
|
115
114
|
subscribeOptions: SubscribeOptions;
|
|
116
|
-
|
|
115
|
+
tracked_columns: string[] | undefined;
|
|
117
116
|
|
|
118
117
|
localFuncs?: LocalFuncs;
|
|
119
118
|
socket: PRGLIOSocket | undefined;
|
|
@@ -137,13 +136,9 @@ export type Subscription = Pick<
|
|
|
137
136
|
| "table_info"
|
|
138
137
|
| "filter"
|
|
139
138
|
| "table_rules"
|
|
140
|
-
| "
|
|
139
|
+
| "tracked_columns"
|
|
141
140
|
> & {
|
|
142
|
-
triggers:
|
|
143
|
-
table_name: string;
|
|
144
|
-
condition: string;
|
|
145
|
-
is_related: boolean;
|
|
146
|
-
}[];
|
|
141
|
+
triggers: AddTriggerParams[];
|
|
147
142
|
};
|
|
148
143
|
|
|
149
144
|
export type PubSubManagerTriggers = Record<string, { condition: string; hash: string }[]>;
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { SubscriptionChannels } from "prostgles-types";
|
|
2
2
|
import { VoidFunction } from "../SchemaWatch/SchemaWatch";
|
|
3
|
-
import { tout } from "./initPubSubManager";
|
|
3
|
+
import { tout } from "./init/initPubSubManager";
|
|
4
4
|
import { BasicCallback, PubSubManager, Subscription, SubscriptionParams } from "./PubSubManager";
|
|
5
5
|
import { parseCondition } from "./PubSubManagerUtils";
|
|
6
|
+
import type { AddTriggerParams } from "./addTrigger";
|
|
6
7
|
|
|
7
8
|
type AddSubscriptionParams = SubscriptionParams & {
|
|
8
9
|
condition: string;
|
|
@@ -28,7 +29,7 @@ export async function addSub(
|
|
|
28
29
|
viewOptions,
|
|
29
30
|
table_info,
|
|
30
31
|
subscribeOptions,
|
|
31
|
-
|
|
32
|
+
tracked_columns,
|
|
32
33
|
} = subscriptionParams;
|
|
33
34
|
const table_name = table_info.name;
|
|
34
35
|
|
|
@@ -39,12 +40,12 @@ export async function addSub(
|
|
|
39
40
|
throw "addSub: cannot have socket AND func";
|
|
40
41
|
}
|
|
41
42
|
|
|
42
|
-
const channel_name = `${this.socketChannelPreffix}.${table_name}.${JSON.stringify(filter)}.${JSON.stringify(selectParams)}
|
|
43
|
+
const channel_name = `${this.socketChannelPreffix}.${table_name}.${JSON.stringify(filter)}.${JSON.stringify(selectParams)}.m.sub`;
|
|
43
44
|
const mainTrigger = {
|
|
44
45
|
table_name: table_name,
|
|
45
46
|
condition: parseCondition(condition),
|
|
46
|
-
|
|
47
|
-
}
|
|
47
|
+
tracked_columns,
|
|
48
|
+
} satisfies AddTriggerParams;
|
|
48
49
|
|
|
49
50
|
const newSub: Subscription = {
|
|
50
51
|
channel_name,
|
|
@@ -59,7 +60,7 @@ export async function addSub(
|
|
|
59
60
|
is_throttling: false,
|
|
60
61
|
socket_id: socket?.id,
|
|
61
62
|
table_rules,
|
|
62
|
-
|
|
63
|
+
tracked_columns,
|
|
63
64
|
triggers: [mainTrigger],
|
|
64
65
|
};
|
|
65
66
|
|
|
@@ -85,8 +86,8 @@ export async function addSub(
|
|
|
85
86
|
const relatedSub = {
|
|
86
87
|
table_name: relatedTable.tableName,
|
|
87
88
|
condition: parseCondition(relatedTable.condition),
|
|
88
|
-
|
|
89
|
-
}
|
|
89
|
+
tracked_columns: undefined,
|
|
90
|
+
} satisfies AddTriggerParams;
|
|
90
91
|
|
|
91
92
|
newSub.triggers.push(relatedSub);
|
|
92
93
|
|
|
@@ -142,7 +143,7 @@ export async function addSub(
|
|
|
142
143
|
|
|
143
144
|
this.subs.push(newSub);
|
|
144
145
|
|
|
145
|
-
/** A view
|
|
146
|
+
/** A view will not have triggers. Related tables are added triggers instead */
|
|
146
147
|
if (table_info.is_view) {
|
|
147
148
|
if (!viewOptions?.relatedTables.length) {
|
|
148
149
|
throw "PubSubManager: view parent_tables missing";
|
|
@@ -122,7 +122,11 @@ export async function addSync(
|
|
|
122
122
|
|
|
123
123
|
upsertSync();
|
|
124
124
|
|
|
125
|
-
await this.addTrigger(
|
|
125
|
+
await this.addTrigger(
|
|
126
|
+
{ table_name, condition: conditionParsed, tracked_columns: undefined },
|
|
127
|
+
undefined,
|
|
128
|
+
socket
|
|
129
|
+
);
|
|
126
130
|
|
|
127
131
|
return { channelName };
|
|
128
132
|
});
|
|
@@ -1,12 +1,19 @@
|
|
|
1
|
-
import { tryCatchV2 } from "prostgles-types";
|
|
1
|
+
import { asName, pickKeys, tryCatchV2 } from "prostgles-types";
|
|
2
2
|
import { type PubSubManager, ViewSubscriptionOptions } from "./PubSubManager";
|
|
3
3
|
import * as crypto from "crypto";
|
|
4
4
|
import { PRGLIOSocket } from "../DboBuilder/DboBuilderTypes";
|
|
5
5
|
import { asValue, EXCLUDE_QUERY_FROM_SCHEMA_WATCH_ID } from "./PubSubManagerUtils";
|
|
6
|
+
import { udtNamesWithoutEqualityComparison } from "./init/getDataWatchFunctionQuery";
|
|
7
|
+
import type { TableHandler } from "../DboBuilder/TableHandler/TableHandler";
|
|
6
8
|
|
|
9
|
+
export type AddTriggerParams = {
|
|
10
|
+
table_name: string;
|
|
11
|
+
condition: string;
|
|
12
|
+
tracked_columns: string[] | undefined;
|
|
13
|
+
};
|
|
7
14
|
export async function addTrigger(
|
|
8
15
|
this: PubSubManager,
|
|
9
|
-
params:
|
|
16
|
+
params: AddTriggerParams,
|
|
10
17
|
viewOptions: ViewSubscriptionOptions | undefined,
|
|
11
18
|
socket: PRGLIOSocket | undefined
|
|
12
19
|
) {
|
|
@@ -14,7 +21,6 @@ export async function addTrigger(
|
|
|
14
21
|
const { table_name } = { ...params };
|
|
15
22
|
let { condition } = { ...params };
|
|
16
23
|
if (!table_name) throw "MISSING table_name";
|
|
17
|
-
|
|
18
24
|
if (!condition || !condition.trim().length) {
|
|
19
25
|
condition = "TRUE";
|
|
20
26
|
}
|
|
@@ -29,6 +35,11 @@ export async function addTrigger(
|
|
|
29
35
|
condHash: asValue(crypto.createHash("md5").update(condition).digest("hex")),
|
|
30
36
|
};
|
|
31
37
|
|
|
38
|
+
const tableHandler = this.dbo[table_name];
|
|
39
|
+
if (!tableHandler) {
|
|
40
|
+
throw `Cannot add trigger. Tablehandler for ${table_name} not found`;
|
|
41
|
+
}
|
|
42
|
+
|
|
32
43
|
await this.db.tx((t) =>
|
|
33
44
|
t.any(`
|
|
34
45
|
BEGIN WORK;
|
|
@@ -52,7 +63,8 @@ export async function addTrigger(
|
|
|
52
63
|
condition_hash,
|
|
53
64
|
app_id,
|
|
54
65
|
related_view_name,
|
|
55
|
-
related_view_def
|
|
66
|
+
related_view_def,
|
|
67
|
+
columns_info
|
|
56
68
|
)
|
|
57
69
|
VALUES (
|
|
58
70
|
${trgVals.tbl},
|
|
@@ -60,9 +72,20 @@ export async function addTrigger(
|
|
|
60
72
|
${trgVals.condHash},
|
|
61
73
|
${asValue(this.appId)},
|
|
62
74
|
${asValue(viewOptions?.viewName ?? null)},
|
|
63
|
-
${asValue(viewOptions?.definition ?? null)}
|
|
75
|
+
${asValue(viewOptions?.definition ?? null)},
|
|
76
|
+
${asValue(getColumnsInfo(params, tableHandler))}
|
|
64
77
|
)
|
|
65
|
-
ON CONFLICT
|
|
78
|
+
ON CONFLICT (app_id, table_name, condition_hash)
|
|
79
|
+
DO UPDATE /* upsert tracked_columns where necessary */
|
|
80
|
+
SET columns_info = CASE WHEN EXCLUDED.columns_info IS NOT NULL THEN
|
|
81
|
+
jsonb_set(
|
|
82
|
+
prostgles.app_triggers.columns_info,
|
|
83
|
+
'{tracked_columns}',
|
|
84
|
+
prostgles.app_triggers.columns_info->'tracked_columns' || EXCLUDED.columns_info->'tracked_columns'
|
|
85
|
+
)
|
|
86
|
+
END
|
|
87
|
+
WHERE prostgles.app_triggers.columns_info IS NOT NULL
|
|
88
|
+
;
|
|
66
89
|
|
|
67
90
|
COMMIT WORK;
|
|
68
91
|
`)
|
|
@@ -93,3 +116,51 @@ export async function addTrigger(
|
|
|
93
116
|
|
|
94
117
|
return addedTrigger;
|
|
95
118
|
}
|
|
119
|
+
|
|
120
|
+
const getColumnsInfo = (
|
|
121
|
+
{ tracked_columns, table_name }: AddTriggerParams,
|
|
122
|
+
tableHandler: Partial<TableHandler>
|
|
123
|
+
) => {
|
|
124
|
+
if (tracked_columns && !tracked_columns.length) {
|
|
125
|
+
throw "tracked_columns cannot be defined and empty";
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
let hasPkey = false as boolean;
|
|
129
|
+
const cols = tableHandler.columns?.map((c) => {
|
|
130
|
+
hasPkey = hasPkey || c.is_pkey;
|
|
131
|
+
return {
|
|
132
|
+
...pickKeys(c, ["name", "is_pkey"]),
|
|
133
|
+
cast_to: udtNamesWithoutEqualityComparison.includes(c.udt_name) ? "::TEXT" : "",
|
|
134
|
+
};
|
|
135
|
+
});
|
|
136
|
+
tracked_columns?.forEach((colName) => {
|
|
137
|
+
if (!cols?.some((c) => c.name === colName)) {
|
|
138
|
+
throw `tracked_columns ${colName} not found in table ${table_name}`;
|
|
139
|
+
}
|
|
140
|
+
});
|
|
141
|
+
const columns_info =
|
|
142
|
+
!hasPkey || !cols || !tracked_columns?.length || tracked_columns.length === cols.length ?
|
|
143
|
+
null
|
|
144
|
+
: {
|
|
145
|
+
join_condition: cols
|
|
146
|
+
.filter((c) => c.is_pkey)
|
|
147
|
+
.map((c) => `n.${asName(c.name)} = o.${asName(c.name)}`)
|
|
148
|
+
.join(" AND "),
|
|
149
|
+
tracked_columns: tracked_columns.reduce(
|
|
150
|
+
(acc, colName) => ({
|
|
151
|
+
...acc,
|
|
152
|
+
[colName]: 1,
|
|
153
|
+
}),
|
|
154
|
+
{} as Record<string, number>
|
|
155
|
+
),
|
|
156
|
+
where_statement: cols
|
|
157
|
+
.filter((c) => !c.is_pkey && tracked_columns.includes(c.name))
|
|
158
|
+
.map(
|
|
159
|
+
(c) =>
|
|
160
|
+
`column_name = ${asValue(c.name)} AND n.${asName(c.name)}${c.cast_to} IS DISTINCT FROM o.${asName(c.name)}${c.cast_to}`
|
|
161
|
+
)
|
|
162
|
+
.join(" OR \n"),
|
|
163
|
+
};
|
|
164
|
+
|
|
165
|
+
return columns_info;
|
|
166
|
+
};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { tryCatch, tryCatchV2 } from "prostgles-types";
|
|
2
|
-
import { getPubSubManagerInitQuery } from "./getPubSubManagerInitQuery";
|
|
2
|
+
import { getPubSubManagerInitQuery } from "./init/getPubSubManagerInitQuery";
|
|
3
3
|
import { getCanExecute } from "../DboBuilder/dboBuilderUtils";
|
|
4
4
|
import { DboBuilder } from "../DboBuilder/DboBuilder";
|
|
5
5
|
|