prostgles-server 3.0.70 → 3.0.72
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/PubSubManager/PubSubManager.d.ts +4 -4
- package/dist/PubSubManager/PubSubManager.d.ts.map +1 -1
- package/dist/PubSubManager/PubSubManager.js.map +1 -1
- package/dist/PubSubManager/initPubSubManager.d.ts.map +1 -1
- package/dist/PubSubManager/initPubSubManager.js +52 -36
- package/dist/PubSubManager/initPubSubManager.js.map +1 -1
- package/lib/AuthHandler.js +213 -209
- package/lib/DBEventsManager.js +34 -31
- package/lib/DboBuilder/QueryBuilder/QueryBuilder.js +163 -155
- package/lib/DboBuilder/TableHandler.js +21 -20
- package/lib/DboBuilder/ViewHandler.js +23 -8
- package/lib/DboBuilder/runSQL.js +5 -5
- package/lib/DboBuilder.js +85 -65
- package/lib/FileManager.js +369 -364
- package/lib/PostgresNotifListenManager.js +26 -20
- package/lib/Prostgles.js +194 -177
- package/lib/PubSubManager/PubSubManager.d.ts +4 -4
- package/lib/PubSubManager/PubSubManager.d.ts.map +1 -1
- package/lib/PubSubManager/PubSubManager.js +249 -239
- package/lib/PubSubManager/PubSubManager.ts +1 -1
- package/lib/PubSubManager/initPubSubManager.d.ts.map +1 -1
- package/lib/PubSubManager/initPubSubManager.js +52 -36
- package/lib/PubSubManager/initPubSubManager.ts +53 -37
- package/lib/PublishParser.js +7 -2
- package/lib/SchemaWatch.js +2 -1
- package/lib/TableConfig.js +94 -91
- package/package.json +2 -2
- package/tests/client/PID.txt +1 -1
- package/tests/client/tsconfig.json +2 -2
- package/tests/server/package-lock.json +3 -3
- package/tests/server/tsconfig.json +2 -2
|
@@ -32,162 +32,16 @@ const parseFunctionObject = (funcData) => {
|
|
|
32
32
|
};
|
|
33
33
|
exports.parseFunctionObject = parseFunctionObject;
|
|
34
34
|
class SelectItemBuilder {
|
|
35
|
+
select = [];
|
|
36
|
+
allFields;
|
|
37
|
+
allowedFields;
|
|
38
|
+
allowedOrderByFields;
|
|
39
|
+
computedFields;
|
|
40
|
+
functions;
|
|
41
|
+
allowedFieldsIncludingComputed;
|
|
42
|
+
isView;
|
|
43
|
+
columns;
|
|
35
44
|
constructor(params) {
|
|
36
|
-
this.select = [];
|
|
37
|
-
this.checkField = (f, isSelected) => {
|
|
38
|
-
const allowedSelectedFields = this.allowedFieldsIncludingComputed;
|
|
39
|
-
const allowedNonSelectedFields = [...this.allowedFieldsIncludingComputed, ...this.allowedOrderByFields];
|
|
40
|
-
/** Not selected items can be part of the orderBy fields */
|
|
41
|
-
if (!(isSelected ? allowedSelectedFields : allowedNonSelectedFields).includes(f)) {
|
|
42
|
-
throw "Field " + f + " is invalid or dissallowed";
|
|
43
|
-
}
|
|
44
|
-
return f;
|
|
45
|
-
};
|
|
46
|
-
this.addItem = (item) => {
|
|
47
|
-
let fields = item.getFields();
|
|
48
|
-
// console.trace(fields)
|
|
49
|
-
if (fields === "*")
|
|
50
|
-
fields = this.allowedFields.slice(0);
|
|
51
|
-
fields.map(f => this.checkField(f, item.selected));
|
|
52
|
-
if (this.select.find(s => s.alias === item.alias)) {
|
|
53
|
-
throw `Cannot specify duplicate columns ( ${item.alias} ). Perhaps you're using "*" with column names?`;
|
|
54
|
-
}
|
|
55
|
-
this.select.push({ ...item, fields });
|
|
56
|
-
};
|
|
57
|
-
this.addFunction = (func, args, alias) => {
|
|
58
|
-
const funcDef = (0, Functions_1.parseFunction)({
|
|
59
|
-
func, args, functions: this.functions,
|
|
60
|
-
allowedFields: this.allowedFieldsIncludingComputed,
|
|
61
|
-
});
|
|
62
|
-
this.addItem({
|
|
63
|
-
type: funcDef.type,
|
|
64
|
-
alias,
|
|
65
|
-
getFields: () => funcDef.getFields(args),
|
|
66
|
-
getQuery: (tableAlias) => funcDef.getQuery({ allColumns: this.columns, allowedFields: this.allowedFields, args, tableAlias,
|
|
67
|
-
ctidField: undefined,
|
|
68
|
-
/* CTID not available in AFTER trigger */
|
|
69
|
-
// ctidField: this.isView? undefined : "ctid"
|
|
70
|
-
}),
|
|
71
|
-
selected: true
|
|
72
|
-
});
|
|
73
|
-
};
|
|
74
|
-
this.addColumn = (fieldName, selected) => {
|
|
75
|
-
/* Check if computed col */
|
|
76
|
-
if (selected) {
|
|
77
|
-
const compCol = Functions_1.COMPUTED_FIELDS.find(cf => cf.name === fieldName);
|
|
78
|
-
if (compCol && !this.select.find(s => s.alias === fieldName)) {
|
|
79
|
-
const cf = {
|
|
80
|
-
...compCol,
|
|
81
|
-
type: "computed",
|
|
82
|
-
numArgs: 0,
|
|
83
|
-
singleColArg: false,
|
|
84
|
-
getFields: (args) => []
|
|
85
|
-
};
|
|
86
|
-
this.addFunction(cf, [], compCol.name);
|
|
87
|
-
return;
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
const colDef = this.columns.find(c => c.name === fieldName);
|
|
91
|
-
let alias = selected ? fieldName : ("not_selected_" + fieldName);
|
|
92
|
-
this.addItem({
|
|
93
|
-
type: "column",
|
|
94
|
-
columnPGDataType: colDef?.data_type,
|
|
95
|
-
column_udt_type: colDef?.udt_name,
|
|
96
|
-
alias,
|
|
97
|
-
getQuery: () => (0, prostgles_types_1.asName)(fieldName),
|
|
98
|
-
getFields: () => [fieldName],
|
|
99
|
-
selected
|
|
100
|
-
});
|
|
101
|
-
};
|
|
102
|
-
this.parseUserSelect = async (userSelect, joinParse) => {
|
|
103
|
-
/* Array select */
|
|
104
|
-
if (Array.isArray(userSelect)) {
|
|
105
|
-
if (userSelect.find(key => typeof key !== "string"))
|
|
106
|
-
throw "Invalid array select. Expecting an array of strings";
|
|
107
|
-
userSelect.map(key => this.addColumn(key, true));
|
|
108
|
-
/* Empty select */
|
|
109
|
-
}
|
|
110
|
-
else if (userSelect === "") {
|
|
111
|
-
// select.push({
|
|
112
|
-
// type: "function",
|
|
113
|
-
// alias: "",
|
|
114
|
-
// getFields: () => [],
|
|
115
|
-
// getQuery: () => ""
|
|
116
|
-
// })
|
|
117
|
-
return [];
|
|
118
|
-
}
|
|
119
|
-
else if (userSelect === "*") {
|
|
120
|
-
this.allowedFields.map(key => this.addColumn(key, true));
|
|
121
|
-
}
|
|
122
|
-
else if ((0, DboBuilder_1.isPlainObject)(userSelect) && !(0, prostgles_types_1.isEmpty)(userSelect)) {
|
|
123
|
-
const selectKeys = Object.keys(userSelect), selectValues = Object.values(userSelect);
|
|
124
|
-
/* Cannot include and exclude at the same time */
|
|
125
|
-
if (selectValues.filter(v => [0, false].includes(v)).length) {
|
|
126
|
-
if (selectValues.filter(v => ![0, false].includes(v)).length) {
|
|
127
|
-
throw "\nCannot include and exclude fields at the same time";
|
|
128
|
-
}
|
|
129
|
-
/* Exclude only */
|
|
130
|
-
this.allowedFields.filter(f => !selectKeys.includes(f)).map(key => this.addColumn(key, true));
|
|
131
|
-
}
|
|
132
|
-
else {
|
|
133
|
-
await Promise.all(selectKeys.map(async (key) => {
|
|
134
|
-
const val = userSelect[key], throwErr = (extraErr = "") => {
|
|
135
|
-
console.trace(extraErr);
|
|
136
|
-
throw "Unexpected select -> " + JSON.stringify({ [key]: val }) + "\n" + extraErr;
|
|
137
|
-
};
|
|
138
|
-
/* Included fields */
|
|
139
|
-
if ([1, true].includes(val)) {
|
|
140
|
-
if (key === "*") {
|
|
141
|
-
this.allowedFields.map(key => this.addColumn(key, true));
|
|
142
|
-
}
|
|
143
|
-
else {
|
|
144
|
-
this.addColumn(key, true);
|
|
145
|
-
}
|
|
146
|
-
/* Aggs and functions */
|
|
147
|
-
}
|
|
148
|
-
else if (typeof val === "string" || (0, DboBuilder_1.isPlainObject)(val)) {
|
|
149
|
-
/* Function shorthand notation
|
|
150
|
-
{ id: "$max" } === { id: { $max: ["id"] } } === SELECT MAX(id) AS id
|
|
151
|
-
*/
|
|
152
|
-
if ((typeof val === "string" && val !== "*") ||
|
|
153
|
-
(0, DboBuilder_1.isPlainObject)(val) && Object.keys(val).length === 1 && Array.isArray(Object.values(val)[0]) // !isPlainObject(Object.values(val)[0])
|
|
154
|
-
) {
|
|
155
|
-
// if(!Array.isArray(Object.values(val)[0])){
|
|
156
|
-
// throw `Could not parse selected item: ${JSON.stringify(val)}\nFunction arguments must be in an array`;
|
|
157
|
-
// }
|
|
158
|
-
let funcName, args;
|
|
159
|
-
if (typeof val === "string") {
|
|
160
|
-
/* Shorthand notation -> it is expected that the key is the column name used as the only argument */
|
|
161
|
-
try {
|
|
162
|
-
this.checkField(key, true);
|
|
163
|
-
}
|
|
164
|
-
catch (err) {
|
|
165
|
-
throwErr(` Shorthand function notation error: the specifield column ( ${key} ) is invalid or dissallowed. \n Use correct column name or full aliased function notation, e.g.: -> { alias: { $func_name: ["column_name"] } } `);
|
|
166
|
-
}
|
|
167
|
-
funcName = val;
|
|
168
|
-
args = [key];
|
|
169
|
-
/** Function full notation { $funcName: ["colName", ...args] } */
|
|
170
|
-
}
|
|
171
|
-
else {
|
|
172
|
-
({ funcName, args } = (0, exports.parseFunctionObject)(val));
|
|
173
|
-
}
|
|
174
|
-
this.addFunction(funcName, args, key);
|
|
175
|
-
/* Join */
|
|
176
|
-
}
|
|
177
|
-
else {
|
|
178
|
-
if (!joinParse)
|
|
179
|
-
throw "Joins dissalowed";
|
|
180
|
-
await joinParse(key, val, throwErr);
|
|
181
|
-
}
|
|
182
|
-
}
|
|
183
|
-
else
|
|
184
|
-
throwErr();
|
|
185
|
-
}));
|
|
186
|
-
}
|
|
187
|
-
}
|
|
188
|
-
else
|
|
189
|
-
throw "Unexpected select -> " + JSON.stringify(userSelect);
|
|
190
|
-
};
|
|
191
45
|
this.allFields = params.allFields;
|
|
192
46
|
this.allowedFields = params.allowedFields;
|
|
193
47
|
this.allowedOrderByFields = params.allowedOrderByFields;
|
|
@@ -205,6 +59,160 @@ class SelectItemBuilder {
|
|
|
205
59
|
throw "INTERNAL ERROR: Cannot have duplicate column names ( " + conflictingCol + " ). One or more computed column names are colliding with table columns ones";
|
|
206
60
|
}
|
|
207
61
|
}
|
|
62
|
+
checkField = (f, isSelected) => {
|
|
63
|
+
const allowedSelectedFields = this.allowedFieldsIncludingComputed;
|
|
64
|
+
const allowedNonSelectedFields = [...this.allowedFieldsIncludingComputed, ...this.allowedOrderByFields];
|
|
65
|
+
/** Not selected items can be part of the orderBy fields */
|
|
66
|
+
if (!(isSelected ? allowedSelectedFields : allowedNonSelectedFields).includes(f)) {
|
|
67
|
+
throw "Field " + f + " is invalid or dissallowed";
|
|
68
|
+
}
|
|
69
|
+
return f;
|
|
70
|
+
};
|
|
71
|
+
addItem = (item) => {
|
|
72
|
+
let fields = item.getFields();
|
|
73
|
+
// console.trace(fields)
|
|
74
|
+
if (fields === "*")
|
|
75
|
+
fields = this.allowedFields.slice(0);
|
|
76
|
+
fields.map(f => this.checkField(f, item.selected));
|
|
77
|
+
if (this.select.find(s => s.alias === item.alias)) {
|
|
78
|
+
throw `Cannot specify duplicate columns ( ${item.alias} ). Perhaps you're using "*" with column names?`;
|
|
79
|
+
}
|
|
80
|
+
this.select.push({ ...item, fields });
|
|
81
|
+
};
|
|
82
|
+
addFunction = (func, args, alias) => {
|
|
83
|
+
const funcDef = (0, Functions_1.parseFunction)({
|
|
84
|
+
func, args, functions: this.functions,
|
|
85
|
+
allowedFields: this.allowedFieldsIncludingComputed,
|
|
86
|
+
});
|
|
87
|
+
this.addItem({
|
|
88
|
+
type: funcDef.type,
|
|
89
|
+
alias,
|
|
90
|
+
getFields: () => funcDef.getFields(args),
|
|
91
|
+
getQuery: (tableAlias) => funcDef.getQuery({ allColumns: this.columns, allowedFields: this.allowedFields, args, tableAlias,
|
|
92
|
+
ctidField: undefined,
|
|
93
|
+
/* CTID not available in AFTER trigger */
|
|
94
|
+
// ctidField: this.isView? undefined : "ctid"
|
|
95
|
+
}),
|
|
96
|
+
selected: true
|
|
97
|
+
});
|
|
98
|
+
};
|
|
99
|
+
addColumn = (fieldName, selected) => {
|
|
100
|
+
/* Check if computed col */
|
|
101
|
+
if (selected) {
|
|
102
|
+
const compCol = Functions_1.COMPUTED_FIELDS.find(cf => cf.name === fieldName);
|
|
103
|
+
if (compCol && !this.select.find(s => s.alias === fieldName)) {
|
|
104
|
+
const cf = {
|
|
105
|
+
...compCol,
|
|
106
|
+
type: "computed",
|
|
107
|
+
numArgs: 0,
|
|
108
|
+
singleColArg: false,
|
|
109
|
+
getFields: (args) => []
|
|
110
|
+
};
|
|
111
|
+
this.addFunction(cf, [], compCol.name);
|
|
112
|
+
return;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
const colDef = this.columns.find(c => c.name === fieldName);
|
|
116
|
+
let alias = selected ? fieldName : ("not_selected_" + fieldName);
|
|
117
|
+
this.addItem({
|
|
118
|
+
type: "column",
|
|
119
|
+
columnPGDataType: colDef?.data_type,
|
|
120
|
+
column_udt_type: colDef?.udt_name,
|
|
121
|
+
alias,
|
|
122
|
+
getQuery: () => (0, prostgles_types_1.asName)(fieldName),
|
|
123
|
+
getFields: () => [fieldName],
|
|
124
|
+
selected
|
|
125
|
+
});
|
|
126
|
+
};
|
|
127
|
+
parseUserSelect = async (userSelect, joinParse) => {
|
|
128
|
+
/* Array select */
|
|
129
|
+
if (Array.isArray(userSelect)) {
|
|
130
|
+
if (userSelect.find(key => typeof key !== "string"))
|
|
131
|
+
throw "Invalid array select. Expecting an array of strings";
|
|
132
|
+
userSelect.map(key => this.addColumn(key, true));
|
|
133
|
+
/* Empty select */
|
|
134
|
+
}
|
|
135
|
+
else if (userSelect === "") {
|
|
136
|
+
// select.push({
|
|
137
|
+
// type: "function",
|
|
138
|
+
// alias: "",
|
|
139
|
+
// getFields: () => [],
|
|
140
|
+
// getQuery: () => ""
|
|
141
|
+
// })
|
|
142
|
+
return [];
|
|
143
|
+
}
|
|
144
|
+
else if (userSelect === "*") {
|
|
145
|
+
this.allowedFields.map(key => this.addColumn(key, true));
|
|
146
|
+
}
|
|
147
|
+
else if ((0, DboBuilder_1.isPlainObject)(userSelect) && !(0, prostgles_types_1.isEmpty)(userSelect)) {
|
|
148
|
+
const selectKeys = Object.keys(userSelect), selectValues = Object.values(userSelect);
|
|
149
|
+
/* Cannot include and exclude at the same time */
|
|
150
|
+
if (selectValues.filter(v => [0, false].includes(v)).length) {
|
|
151
|
+
if (selectValues.filter(v => ![0, false].includes(v)).length) {
|
|
152
|
+
throw "\nCannot include and exclude fields at the same time";
|
|
153
|
+
}
|
|
154
|
+
/* Exclude only */
|
|
155
|
+
this.allowedFields.filter(f => !selectKeys.includes(f)).map(key => this.addColumn(key, true));
|
|
156
|
+
}
|
|
157
|
+
else {
|
|
158
|
+
await Promise.all(selectKeys.map(async (key) => {
|
|
159
|
+
const val = userSelect[key], throwErr = (extraErr = "") => {
|
|
160
|
+
console.trace(extraErr);
|
|
161
|
+
throw "Unexpected select -> " + JSON.stringify({ [key]: val }) + "\n" + extraErr;
|
|
162
|
+
};
|
|
163
|
+
/* Included fields */
|
|
164
|
+
if ([1, true].includes(val)) {
|
|
165
|
+
if (key === "*") {
|
|
166
|
+
this.allowedFields.map(key => this.addColumn(key, true));
|
|
167
|
+
}
|
|
168
|
+
else {
|
|
169
|
+
this.addColumn(key, true);
|
|
170
|
+
}
|
|
171
|
+
/* Aggs and functions */
|
|
172
|
+
}
|
|
173
|
+
else if (typeof val === "string" || (0, DboBuilder_1.isPlainObject)(val)) {
|
|
174
|
+
/* Function shorthand notation
|
|
175
|
+
{ id: "$max" } === { id: { $max: ["id"] } } === SELECT MAX(id) AS id
|
|
176
|
+
*/
|
|
177
|
+
if ((typeof val === "string" && val !== "*") ||
|
|
178
|
+
(0, DboBuilder_1.isPlainObject)(val) && Object.keys(val).length === 1 && Array.isArray(Object.values(val)[0]) // !isPlainObject(Object.values(val)[0])
|
|
179
|
+
) {
|
|
180
|
+
// if(!Array.isArray(Object.values(val)[0])){
|
|
181
|
+
// throw `Could not parse selected item: ${JSON.stringify(val)}\nFunction arguments must be in an array`;
|
|
182
|
+
// }
|
|
183
|
+
let funcName, args;
|
|
184
|
+
if (typeof val === "string") {
|
|
185
|
+
/* Shorthand notation -> it is expected that the key is the column name used as the only argument */
|
|
186
|
+
try {
|
|
187
|
+
this.checkField(key, true);
|
|
188
|
+
}
|
|
189
|
+
catch (err) {
|
|
190
|
+
throwErr(` Shorthand function notation error: the specifield column ( ${key} ) is invalid or dissallowed. \n Use correct column name or full aliased function notation, e.g.: -> { alias: { $func_name: ["column_name"] } } `);
|
|
191
|
+
}
|
|
192
|
+
funcName = val;
|
|
193
|
+
args = [key];
|
|
194
|
+
/** Function full notation { $funcName: ["colName", ...args] } */
|
|
195
|
+
}
|
|
196
|
+
else {
|
|
197
|
+
({ funcName, args } = (0, exports.parseFunctionObject)(val));
|
|
198
|
+
}
|
|
199
|
+
this.addFunction(funcName, args, key);
|
|
200
|
+
/* Join */
|
|
201
|
+
}
|
|
202
|
+
else {
|
|
203
|
+
if (!joinParse)
|
|
204
|
+
throw "Joins dissalowed";
|
|
205
|
+
await joinParse(key, val, throwErr);
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
else
|
|
209
|
+
throwErr();
|
|
210
|
+
}));
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
else
|
|
214
|
+
throw "Unexpected select -> " + JSON.stringify(userSelect);
|
|
215
|
+
};
|
|
208
216
|
}
|
|
209
217
|
exports.SelectItemBuilder = SelectItemBuilder;
|
|
210
218
|
async function getNewQuery(_this, filter, selectParams = {}, param3_unused = null, tableRules, localParams, columns) {
|
|
@@ -12,28 +12,9 @@ const ViewHandler_1 = require("./ViewHandler");
|
|
|
12
12
|
const parseUpdateRules_1 = require("./parseUpdateRules");
|
|
13
13
|
const Functions_1 = require("./QueryBuilder/Functions");
|
|
14
14
|
class TableHandler extends ViewHandler_1.ViewHandler {
|
|
15
|
+
io_stats;
|
|
15
16
|
constructor(db, tableOrViewInfo, dboBuilder, t, dbTX, joinPaths) {
|
|
16
17
|
super(db, tableOrViewInfo, dboBuilder, t, dbTX, joinPaths);
|
|
17
|
-
this.parseUpdateRules = parseUpdateRules_1.parseUpdateRules.bind(this);
|
|
18
|
-
this.update = update_1.update.bind(this);
|
|
19
|
-
this.insertDataParse = insertDataParse_1.insertDataParse;
|
|
20
|
-
this.prepareReturning = async (returning, allowedFields) => {
|
|
21
|
-
let result = [];
|
|
22
|
-
if (returning) {
|
|
23
|
-
let sBuilder = new QueryBuilder_1.SelectItemBuilder({
|
|
24
|
-
allFields: this.column_names.slice(0),
|
|
25
|
-
allowedFields,
|
|
26
|
-
allowedOrderByFields: allowedFields,
|
|
27
|
-
computedFields: Functions_1.COMPUTED_FIELDS,
|
|
28
|
-
functions: Functions_1.FUNCTIONS.filter(f => f.type === "function" && f.singleColArg),
|
|
29
|
-
isView: this.is_view,
|
|
30
|
-
columns: this.columns,
|
|
31
|
-
});
|
|
32
|
-
await sBuilder.parseUserSelect(returning);
|
|
33
|
-
return sBuilder.select;
|
|
34
|
-
}
|
|
35
|
-
return result;
|
|
36
|
-
};
|
|
37
18
|
this.remove = this.delete;
|
|
38
19
|
this.io_stats = {
|
|
39
20
|
since: Date.now(),
|
|
@@ -73,6 +54,8 @@ class TableHandler extends ViewHandler_1.ViewHandler {
|
|
|
73
54
|
throw (0, DboBuilder_1.parseError)(e, `dbo.${this.name}.update()`);
|
|
74
55
|
}
|
|
75
56
|
}
|
|
57
|
+
parseUpdateRules = parseUpdateRules_1.parseUpdateRules.bind(this);
|
|
58
|
+
update = update_1.update.bind(this);
|
|
76
59
|
validateNewData({ row, forcedData, allowedFields, tableRules, fixIssues = false }) {
|
|
77
60
|
const synced_field = (tableRules ?? {})?.sync?.synced_field;
|
|
78
61
|
/* Update synced_field if sync is on and missing */
|
|
@@ -95,9 +78,27 @@ class TableHandler extends ViewHandler_1.ViewHandler {
|
|
|
95
78
|
});
|
|
96
79
|
return { data, allowedCols: this.columns.filter(c => dataKeys.includes(c.name)).map(c => c.name) };
|
|
97
80
|
}
|
|
81
|
+
insertDataParse = insertDataParse_1.insertDataParse;
|
|
98
82
|
async insert(rowOrRows, param2, param3_unused, tableRules, _localParams) {
|
|
99
83
|
return insert_1.insert.bind(this)(rowOrRows, param2, param3_unused, tableRules, _localParams);
|
|
100
84
|
}
|
|
85
|
+
prepareReturning = async (returning, allowedFields) => {
|
|
86
|
+
let result = [];
|
|
87
|
+
if (returning) {
|
|
88
|
+
let sBuilder = new QueryBuilder_1.SelectItemBuilder({
|
|
89
|
+
allFields: this.column_names.slice(0),
|
|
90
|
+
allowedFields,
|
|
91
|
+
allowedOrderByFields: allowedFields,
|
|
92
|
+
computedFields: Functions_1.COMPUTED_FIELDS,
|
|
93
|
+
functions: Functions_1.FUNCTIONS.filter(f => f.type === "function" && f.singleColArg),
|
|
94
|
+
isView: this.is_view,
|
|
95
|
+
columns: this.columns,
|
|
96
|
+
});
|
|
97
|
+
await sBuilder.parseUserSelect(returning);
|
|
98
|
+
return sBuilder.select;
|
|
99
|
+
}
|
|
100
|
+
return result;
|
|
101
|
+
};
|
|
101
102
|
makeReturnQuery(items) {
|
|
102
103
|
if (items?.length)
|
|
103
104
|
return " RETURNING " + items.map(s => s.getQuery() + " AS " + (0, prostgles_types_1.asName)(s.alias)).join(", ");
|
|
@@ -13,6 +13,7 @@ const getColumns_1 = require("./getColumns");
|
|
|
13
13
|
const subscribe_1 = require("./subscribe");
|
|
14
14
|
const FILTER_FUNCS = Functions_1.FUNCTIONS.filter(f => f.canBeUsedForFilter);
|
|
15
15
|
class ColSet {
|
|
16
|
+
opts;
|
|
16
17
|
constructor(columns, tableName) {
|
|
17
18
|
this.opts = { columns, tableName, colNames: columns.map(c => c.name) };
|
|
18
19
|
}
|
|
@@ -99,14 +100,26 @@ class ColSet {
|
|
|
99
100
|
}
|
|
100
101
|
}
|
|
101
102
|
class ViewHandler {
|
|
103
|
+
db;
|
|
104
|
+
name;
|
|
105
|
+
escapedName;
|
|
106
|
+
columns;
|
|
107
|
+
columnsForTypes;
|
|
108
|
+
column_names;
|
|
109
|
+
tableOrViewInfo; // TableOrViewInfo;
|
|
110
|
+
colSet;
|
|
111
|
+
tsColumnDefs = [];
|
|
112
|
+
joins;
|
|
113
|
+
joinGraph;
|
|
114
|
+
joinPaths;
|
|
115
|
+
dboBuilder;
|
|
116
|
+
t;
|
|
117
|
+
dbTX;
|
|
118
|
+
is_view = true;
|
|
119
|
+
filterDef = "";
|
|
120
|
+
// pubSubManager: PubSubManager;
|
|
121
|
+
is_media = false;
|
|
102
122
|
constructor(db, tableOrViewInfo, dboBuilder, t, dbTX, joinPaths) {
|
|
103
|
-
this.tsColumnDefs = [];
|
|
104
|
-
this.is_view = true;
|
|
105
|
-
this.filterDef = "";
|
|
106
|
-
// pubSubManager: PubSubManager;
|
|
107
|
-
this.is_media = false;
|
|
108
|
-
// TODO: fix renamed table trigger problem
|
|
109
|
-
this.getColumns = getColumns_1.getColumns.bind(this);
|
|
110
123
|
if (!db || !tableOrViewInfo)
|
|
111
124
|
throw "";
|
|
112
125
|
this.db = db;
|
|
@@ -282,7 +295,7 @@ class ViewHandler {
|
|
|
282
295
|
/* Make the join chain info excluding root table */
|
|
283
296
|
paths = (path || jp.path).slice(1).map((t2, i, arr) => {
|
|
284
297
|
const t1 = i === 0 ? source : arr[i - 1];
|
|
285
|
-
this.joins
|
|
298
|
+
this.joins ??= this.dboBuilder.joins;
|
|
286
299
|
/* Get join options */
|
|
287
300
|
const jo = this.joins.find(j => j.tables.includes(t1) && j.tables.includes(t2));
|
|
288
301
|
if (!jo)
|
|
@@ -378,6 +391,8 @@ class ViewHandler {
|
|
|
378
391
|
}
|
|
379
392
|
};
|
|
380
393
|
}
|
|
394
|
+
// TODO: fix renamed table trigger problem
|
|
395
|
+
getColumns = getColumns_1.getColumns.bind(this);
|
|
381
396
|
getValidatedRules(tableRules, localParams) {
|
|
382
397
|
if (localParams?.socket && !tableRules) {
|
|
383
398
|
throw "INTERNAL ERROR: Unexpected case -> localParams && !tableRules";
|
package/lib/DboBuilder/runSQL.js
CHANGED
|
@@ -13,8 +13,8 @@ async function runSQL(query, params, options, localParams) {
|
|
|
13
13
|
}
|
|
14
14
|
}
|
|
15
15
|
/** Cache types */
|
|
16
|
-
this.DATA_TYPES
|
|
17
|
-
this.USER_TABLES
|
|
16
|
+
this.DATA_TYPES ??= await this.db.any("SELECT oid, typname FROM pg_type") ?? [];
|
|
17
|
+
this.USER_TABLES ??= await this.db.any(`
|
|
18
18
|
SELECT relid, relname, schemaname, array_to_json(array_agg(c.column_name) FILTER (WHERE c.column_name IS NOT NULL)) as pkey_columns
|
|
19
19
|
FROM pg_catalog.pg_statio_user_tables t
|
|
20
20
|
LEFT JOIN (
|
|
@@ -26,13 +26,13 @@ async function runSQL(query, params, options, localParams) {
|
|
|
26
26
|
) c
|
|
27
27
|
ON t.relid = c.table_oid
|
|
28
28
|
GROUP BY relid, relname, schemaname
|
|
29
|
-
`) ?? []
|
|
30
|
-
this.USER_TABLE_COLUMNS
|
|
29
|
+
`) ?? [];
|
|
30
|
+
this.USER_TABLE_COLUMNS ??= await this.db.any(`
|
|
31
31
|
SELECT t.relid, t.schemaname,t.relname, c.column_name, c.udt_name, c.ordinal_position
|
|
32
32
|
FROM information_schema.columns c
|
|
33
33
|
INNER JOIN pg_catalog.pg_statio_user_tables t
|
|
34
34
|
ON c.table_schema = t.schemaname AND c.table_name = t.relname
|
|
35
|
-
`)
|
|
35
|
+
`);
|
|
36
36
|
if (!(await (0, exports.canRunSQL)(this.prostgles, localParams)))
|
|
37
37
|
throw "Not allowed to run SQL";
|
|
38
38
|
const { returnType, allowListen, hasParams = true } = options || {};
|