prostgles-server 2.0.146 → 2.0.149
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/AuthHandler.d.ts +15 -13
- package/dist/AuthHandler.d.ts.map +1 -1
- package/dist/AuthHandler.js +43 -44
- package/dist/AuthHandler.js.map +1 -1
- package/dist/DBEventsManager.d.ts +6 -5
- package/dist/DBEventsManager.d.ts.map +1 -1
- package/dist/DBEventsManager.js +8 -2
- package/dist/DBEventsManager.js.map +1 -1
- package/dist/DboBuilder.d.ts +54 -50
- package/dist/DboBuilder.d.ts.map +1 -1
- package/dist/DboBuilder.js +242 -206
- package/dist/DboBuilder.js.map +1 -1
- package/dist/FileManager.d.ts +5 -5
- package/dist/FileManager.d.ts.map +1 -1
- package/dist/FileManager.js +59 -31
- package/dist/FileManager.js.map +1 -1
- package/dist/Filtering.d.ts.map +1 -1
- package/dist/Filtering.js +17 -14
- package/dist/Filtering.js.map +1 -1
- package/dist/PostgresNotifListenManager.d.ts +3 -3
- package/dist/PostgresNotifListenManager.d.ts.map +1 -1
- package/dist/PostgresNotifListenManager.js +7 -5
- package/dist/PostgresNotifListenManager.js.map +1 -1
- package/dist/Prostgles.d.ts +6 -9
- package/dist/Prostgles.d.ts.map +1 -1
- package/dist/Prostgles.js +125 -86
- package/dist/Prostgles.js.map +1 -1
- package/dist/PubSubManager.d.ts +8 -8
- package/dist/PubSubManager.d.ts.map +1 -1
- package/dist/PubSubManager.js +58 -52
- package/dist/PubSubManager.js.map +1 -1
- package/dist/QueryBuilder.d.ts +6 -5
- package/dist/QueryBuilder.d.ts.map +1 -1
- package/dist/QueryBuilder.js +124 -89
- package/dist/QueryBuilder.js.map +1 -1
- package/dist/SyncReplication.js +38 -35
- package/dist/SyncReplication.js.map +1 -1
- package/dist/TableConfig.d.ts +0 -1
- package/dist/TableConfig.d.ts.map +1 -1
- package/dist/TableConfig.js +36 -28
- package/dist/TableConfig.js.map +1 -1
- package/dist/shortestPath.d.ts.map +1 -1
- package/dist/shortestPath.js +2 -1
- package/dist/shortestPath.js.map +1 -1
- package/dist/utils.d.ts +2 -1
- package/dist/utils.d.ts.map +1 -1
- package/dist/utils.js +3 -1
- package/dist/utils.js.map +1 -1
- package/lib/AuthHandler.ts +50 -40
- package/lib/DBEventsManager.ts +14 -7
- package/lib/DboBuilder.ts +231 -195
- package/lib/FileManager.ts +30 -21
- package/lib/Filtering.ts +19 -16
- package/lib/PostgresNotifListenManager.ts +11 -10
- package/lib/Prostgles.ts +89 -73
- package/lib/PubSubManager.ts +13 -11
- package/lib/QueryBuilder.ts +53 -29
- package/lib/SyncReplication.ts +10 -10
- package/lib/TableConfig.ts +23 -15
- package/lib/shortestPath.ts +6 -4
- package/lib/utils.ts +3 -2
- package/package.json +4 -3
- package/tests/client/PID.txt +1 -1
- package/tests/client/index.js +10 -7
- package/tests/client/index.ts +12 -8
- package/tests/client/package-lock.json +14 -14
- package/tests/client/package.json +2 -2
- package/tests/client/tsconfig.json +2 -2
- package/tests/client_only_queries.js +127 -104
- package/tests/client_only_queries.ts +43 -17
- package/tests/isomorphic_queries.js +22 -6
- package/tests/isomorphic_queries.ts +18 -6
- package/tests/server/package-lock.json +21 -19
- package/tests/server/package.json +2 -2
- package/tests/server/tsconfig.json +2 -2
- package/tsconfig.json +3 -2
package/lib/DboBuilder.ts
CHANGED
|
@@ -11,7 +11,8 @@ import * as pgPromise from 'pg-promise';
|
|
|
11
11
|
const {ParameterizedQuery: PQ} = require('pg-promise');
|
|
12
12
|
import pg = require('pg-promise/typescript/pg-subset');
|
|
13
13
|
import {
|
|
14
|
-
ColumnInfo, ValidatedColumnInfo, FieldFilter, SelectParams, SubscribeParams,
|
|
14
|
+
ColumnInfo, ValidatedColumnInfo, FieldFilter, SelectParams, SubscribeParams,
|
|
15
|
+
OrderBy, InsertParams, UpdateParams, DeleteParams, SQLOptions,
|
|
15
16
|
DbJoinMaker,
|
|
16
17
|
unpatchText,
|
|
17
18
|
isEmpty,
|
|
@@ -21,6 +22,9 @@ import {
|
|
|
21
22
|
TableInfo as TInfo,
|
|
22
23
|
SQLHandler,
|
|
23
24
|
AnyObject,
|
|
25
|
+
SQLResult,
|
|
26
|
+
Select,
|
|
27
|
+
JoinMaker,
|
|
24
28
|
} from "prostgles-types";
|
|
25
29
|
|
|
26
30
|
export type Media = {
|
|
@@ -69,10 +73,10 @@ export type DbHandler = {
|
|
|
69
73
|
// [key: string]: TX
|
|
70
74
|
// }>
|
|
71
75
|
|
|
72
|
-
import { get, isObject } from "./utils";
|
|
76
|
+
import { get, isDefined, isObject } from "./utils";
|
|
73
77
|
import { getNewQuery, makeQuery, COMPUTED_FIELDS, SelectItem, FieldSpec, asNameAlias, SelectItemBuilder, FUNCTIONS, parseFunction, parseFunctionObject } from "./QueryBuilder";
|
|
74
78
|
import {
|
|
75
|
-
DB, TableRule, SelectRule, InsertRule, UpdateRule, DeleteRule, SyncRule, Joins, Join, Prostgles, PublishParser,
|
|
79
|
+
DB, TableRule, SelectRule, InsertRule, UpdateRule, DeleteRule, SyncRule, Joins, Join, Prostgles, PublishParser, ValidateRow
|
|
76
80
|
} from "./Prostgles";
|
|
77
81
|
import { PubSubManager, filterObj, asValue, BasicCallback } from "./PubSubManager";
|
|
78
82
|
|
|
@@ -108,8 +112,16 @@ export type PRGLIOSocket = {
|
|
|
108
112
|
headers?: { cookie?: string; } // e.g.: "some_arg=dwdaw; otherarg=23232"
|
|
109
113
|
}
|
|
110
114
|
|
|
115
|
+
readonly on: (channel: string, params: any, cb?: (err: any, res?: any) => void) => Promise<void>;
|
|
116
|
+
|
|
111
117
|
readonly emit: (channel: string, message: any, cb?: BasicCallback) => any;
|
|
112
118
|
|
|
119
|
+
readonly once: (channel: string, cb: (_data: any, cb: BasicCallback) => void) => void;
|
|
120
|
+
|
|
121
|
+
readonly removeAllListeners: (channel: string) => void;
|
|
122
|
+
|
|
123
|
+
readonly disconnect: () => void;
|
|
124
|
+
|
|
113
125
|
/** Used for session caching */
|
|
114
126
|
__prglCache?: {
|
|
115
127
|
session: BasicSession;
|
|
@@ -117,6 +129,8 @@ export type PRGLIOSocket = {
|
|
|
117
129
|
clientUser: AnyObject;
|
|
118
130
|
}
|
|
119
131
|
|
|
132
|
+
_user?: AnyObject
|
|
133
|
+
|
|
120
134
|
/** Used for publish error caching */
|
|
121
135
|
prostgles?: AnyObject;
|
|
122
136
|
};
|
|
@@ -361,7 +375,7 @@ class ColSet {
|
|
|
361
375
|
this.opts = { columns, tableName, colNames: columns.map(c => c.name) }
|
|
362
376
|
}
|
|
363
377
|
|
|
364
|
-
private async getRow(data: any, allowedCols: string[], validate
|
|
378
|
+
private async getRow(data: any, allowedCols: string[], validate?: ValidateRow): Promise<{ escapedCol: string; escapedVal: string }[]> {
|
|
365
379
|
const badCol = allowedCols.find(c => !this.opts.colNames.includes(c))
|
|
366
380
|
if(!allowedCols || badCol){
|
|
367
381
|
throw "Missing or unexpected columns: " + badCol;
|
|
@@ -387,7 +401,7 @@ class ColSet {
|
|
|
387
401
|
let escapedVal: string;
|
|
388
402
|
if(["geometry", "geography"].includes(col.udt_name) && row[key] && isPlainObject(row[key])){
|
|
389
403
|
|
|
390
|
-
const basicFunc = (args) => {
|
|
404
|
+
const basicFunc = (args: any[]) => {
|
|
391
405
|
return args.map(arg => asValue(arg)).join(", ")
|
|
392
406
|
}
|
|
393
407
|
const basicFuncNames = ["ST_GeomFromText", "ST_Point", "ST_MakePoint", "ST_MakePointM", "ST_PointFromText", "ST_GeomFromEWKT", "ST_GeomFromGeoJSON"]
|
|
@@ -413,7 +427,7 @@ class ColSet {
|
|
|
413
427
|
|
|
414
428
|
}
|
|
415
429
|
|
|
416
|
-
async getInsertQuery(data: any[], allowedCols: string[], validate: ValidateRow): Promise<string> {
|
|
430
|
+
async getInsertQuery(data: any[], allowedCols: string[], validate: ValidateRow | undefined): Promise<string> {
|
|
417
431
|
const res = (await Promise.all((Array.isArray(data)? data : [data]).map(async d => {
|
|
418
432
|
const rowParts = await this.getRow(d, allowedCols, validate);
|
|
419
433
|
const select = rowParts.map(r => r.escapedCol).join(", "),
|
|
@@ -423,7 +437,7 @@ class ColSet {
|
|
|
423
437
|
}))).join(";\n") + " ";
|
|
424
438
|
return res;
|
|
425
439
|
}
|
|
426
|
-
async getUpdateQuery(data: any[], allowedCols: string[], validate: ValidateRow): Promise<string> {
|
|
440
|
+
async getUpdateQuery(data: any[], allowedCols: string[], validate: ValidateRow | undefined): Promise<string> {
|
|
427
441
|
const res = (await Promise.all((Array.isArray(data)? data : [data]).map(async d => {
|
|
428
442
|
const rowParts = await this.getRow(d, allowedCols, validate);
|
|
429
443
|
return `UPDATE ${asName(this.opts.tableName)} SET ` + rowParts.map(r => `${r.escapedCol} = ${r.escapedVal} `).join(",\n")
|
|
@@ -483,7 +497,7 @@ export class ViewHandler {
|
|
|
483
497
|
|
|
484
498
|
// this.pubSubManager = pubSubManager;
|
|
485
499
|
this.dboBuilder = dboBuilder;
|
|
486
|
-
this.joins = this.dboBuilder.joins;
|
|
500
|
+
this.joins = this.dboBuilder.joins ?? [];
|
|
487
501
|
|
|
488
502
|
// fix this
|
|
489
503
|
// and also make hot schema reload over ws
|
|
@@ -533,7 +547,7 @@ export class ViewHandler {
|
|
|
533
547
|
`)` + (alias? ` as ${asName(alias)}` : "");
|
|
534
548
|
}
|
|
535
549
|
|
|
536
|
-
async validateViewRules(fields: FieldFilter, filterFields: FieldFilter, returningFields: FieldFilter, forcedFilter:
|
|
550
|
+
async validateViewRules(fields: FieldFilter | undefined, filterFields: FieldFilter | undefined, returningFields: FieldFilter | undefined, forcedFilter: AnyObject | undefined, rule: "update" | "select" | "insert" | "delete"){
|
|
537
551
|
|
|
538
552
|
/* Safely test publish rules */
|
|
539
553
|
if(fields) {
|
|
@@ -932,7 +946,7 @@ export class ViewHandler {
|
|
|
932
946
|
|
|
933
947
|
}
|
|
934
948
|
|
|
935
|
-
async find(filter?: Filter, selectParams?: SelectParams , param3_unused
|
|
949
|
+
async find(filter?: Filter, selectParams?: SelectParams , param3_unused?: never, tableRules?: TableRule, localParams?: LocalParams): Promise<any[]>{
|
|
936
950
|
try {
|
|
937
951
|
filter = filter || {};
|
|
938
952
|
const allowedReturnTypes: Array<SelectParams["returnType"]> = ["row", "value", "values"]
|
|
@@ -954,9 +968,9 @@ export class ViewHandler {
|
|
|
954
968
|
if(tableRules){
|
|
955
969
|
|
|
956
970
|
let fields: FieldFilter,
|
|
957
|
-
filterFields: FieldFilter,
|
|
958
|
-
forcedFilter:
|
|
959
|
-
maxLimit: number;
|
|
971
|
+
filterFields: FieldFilter | undefined,
|
|
972
|
+
forcedFilter: AnyObject | undefined,
|
|
973
|
+
maxLimit: number | undefined | null;
|
|
960
974
|
|
|
961
975
|
if(!tableRules.select) throw "select rules missing for " + this.name;
|
|
962
976
|
fields = tableRules.select.fields;
|
|
@@ -983,7 +997,7 @@ export class ViewHandler {
|
|
|
983
997
|
}
|
|
984
998
|
|
|
985
999
|
if(returnQuery) return (_query as unknown as any[]);
|
|
986
|
-
if(["row", "value"].includes(returnType)) {
|
|
1000
|
+
if(["row", "value"].includes(returnType!)) {
|
|
987
1001
|
return (this.t || this.db).oneOrNone(_query).then(data => {
|
|
988
1002
|
return (data && returnType === "value")? Object.values(data)[0] : data;
|
|
989
1003
|
}).catch(err => makeErr(err, localParams, this));
|
|
@@ -1003,26 +1017,26 @@ export class ViewHandler {
|
|
|
1003
1017
|
}
|
|
1004
1018
|
}
|
|
1005
1019
|
|
|
1006
|
-
findOne(filter?: Filter, selectParams?: SelectParams, param3_unused
|
|
1020
|
+
findOne(filter?: Filter, selectParams?: SelectParams, param3_unused?: never, table_rules?: TableRule, localParams?: LocalParams): Promise<any>{
|
|
1007
1021
|
|
|
1008
1022
|
try {
|
|
1009
|
-
const { select = "*", orderBy
|
|
1023
|
+
const { select = "*", orderBy, offset = 0 } = selectParams || {};
|
|
1010
1024
|
if(selectParams){
|
|
1011
1025
|
const good_params = ["select", "orderBy", "offset"];
|
|
1012
1026
|
const bad_params = Object.keys(selectParams).filter(k => !good_params.includes(k));
|
|
1013
1027
|
if(bad_params && bad_params.length) throw "Invalid params: " + bad_params.join(", ") + " \n Expecting: " + good_params.join(", ");
|
|
1014
1028
|
}
|
|
1015
|
-
return this.find(filter, { select, orderBy, limit: 1, offset, returnType: "row" },
|
|
1029
|
+
return this.find(filter, { select, orderBy, limit: 1, offset, returnType: "row" }, undefined, table_rules, localParams);
|
|
1016
1030
|
} catch(e){
|
|
1017
1031
|
if(localParams && localParams.testRule) throw e;
|
|
1018
1032
|
throw { err: parseError(e), msg: `Issue with dbo.${this.name}.findOne()` };
|
|
1019
1033
|
}
|
|
1020
1034
|
}
|
|
1021
1035
|
|
|
1022
|
-
async count(filter?: Filter, param2_unused
|
|
1036
|
+
async count(filter?: Filter, param2_unused?: never, param3_unused?: never, table_rules?: TableRule, localParams: any = {}): Promise<number>{
|
|
1023
1037
|
filter = filter || {};
|
|
1024
1038
|
try {
|
|
1025
|
-
return await this.find(filter, { select: "", limit: 0 },
|
|
1039
|
+
return await this.find(filter, { select: "", limit: 0 }, undefined, table_rules, localParams)
|
|
1026
1040
|
.then(async allowed => {
|
|
1027
1041
|
const { filterFields, forcedFilter } = get(table_rules, "select") || {};
|
|
1028
1042
|
const where = (await this.prepareWhere({ filter, forcedFilter, filterFields, addKeywords: true, localParams, tableRule: table_rules }));
|
|
@@ -1035,10 +1049,10 @@ export class ViewHandler {
|
|
|
1035
1049
|
}
|
|
1036
1050
|
}
|
|
1037
1051
|
|
|
1038
|
-
async size(filter?: Filter, selectParams?: SelectParams, param3_unused
|
|
1052
|
+
async size(filter?: Filter, selectParams?: SelectParams, param3_unused?: never, table_rules?: TableRule, localParams: any = {}): Promise<string>{
|
|
1039
1053
|
filter = filter || {};
|
|
1040
1054
|
try {
|
|
1041
|
-
return await this.find(filter, { ...selectParams, limit: 2 },
|
|
1055
|
+
return await this.find(filter, { ...selectParams, limit: 2 }, undefined, table_rules, localParams)
|
|
1042
1056
|
.then(async _allowed => {
|
|
1043
1057
|
// let rules: TableRule = table_rules || {};
|
|
1044
1058
|
// rules.select.maxLimit = Number.MAX_SAFE_INTEGER;
|
|
@@ -1046,7 +1060,7 @@ export class ViewHandler {
|
|
|
1046
1060
|
|
|
1047
1061
|
const q: string = await this.find(
|
|
1048
1062
|
filter, { ...selectParams, limit: selectParams?.limit ?? Number.MAX_SAFE_INTEGER },
|
|
1049
|
-
|
|
1063
|
+
undefined,
|
|
1050
1064
|
table_rules,
|
|
1051
1065
|
{ ...localParams, returnQuery: true }
|
|
1052
1066
|
) as any;
|
|
@@ -1068,7 +1082,7 @@ export class ViewHandler {
|
|
|
1068
1082
|
getAllowedSelectFields(selectParams: FieldFilter = "*", allowed_cols: FieldFilter, allow_empty: boolean = true): string[] {
|
|
1069
1083
|
let all_columns = this.column_names.slice(0),
|
|
1070
1084
|
allowedFields = all_columns.slice(0),
|
|
1071
|
-
resultFields = [];
|
|
1085
|
+
resultFields: string[] = [];
|
|
1072
1086
|
|
|
1073
1087
|
if(selectParams){
|
|
1074
1088
|
resultFields = this.parseFieldFilter(selectParams, allow_empty);
|
|
@@ -1121,27 +1135,27 @@ export class ViewHandler {
|
|
|
1121
1135
|
* Parses group or simple filter
|
|
1122
1136
|
*/
|
|
1123
1137
|
async prepareWhere(params: {
|
|
1124
|
-
filter
|
|
1138
|
+
filter?: Filter;
|
|
1125
1139
|
select?: SelectItem[];
|
|
1126
|
-
forcedFilter
|
|
1127
|
-
filterFields
|
|
1140
|
+
forcedFilter?: AnyObject;
|
|
1141
|
+
filterFields?: FieldFilter;
|
|
1128
1142
|
addKeywords?: boolean;
|
|
1129
1143
|
tableAlias?: string,
|
|
1130
|
-
localParams: LocalParams,
|
|
1131
|
-
tableRule: TableRule
|
|
1144
|
+
localParams: LocalParams | undefined,
|
|
1145
|
+
tableRule: TableRule | undefined
|
|
1132
1146
|
}): Promise<string>
|
|
1133
1147
|
{
|
|
1134
|
-
const { filter, select, forcedFilter, filterFields: ff, addKeywords = true, tableAlias
|
|
1148
|
+
const { filter, select, forcedFilter, filterFields: ff, addKeywords = true, tableAlias, localParams, tableRule } = params;
|
|
1135
1149
|
const { $and: $and_key, $or: $or_key } = this.dboBuilder.prostgles.keywords;
|
|
1136
1150
|
|
|
1137
1151
|
let filterFields = ff;
|
|
1138
1152
|
/* Local update allow all. TODO -> FIX THIS */
|
|
1139
1153
|
if(!ff && !tableRule) filterFields = "*";
|
|
1140
1154
|
|
|
1141
|
-
const parseFullFilter = async (f: any, parentFilter: any = null) => {
|
|
1155
|
+
const parseFullFilter = async (f: any, parentFilter: any = null): Promise<string> => {
|
|
1142
1156
|
if(!f) throw "Invalid/missing group filter provided";
|
|
1143
1157
|
let result = "";
|
|
1144
|
-
let keys =
|
|
1158
|
+
let keys = getKeys(f);
|
|
1145
1159
|
if(!keys.length) return result;
|
|
1146
1160
|
if((keys.includes($and_key) || keys.includes($or_key))){
|
|
1147
1161
|
if(keys.length > 1) throw `\ngroup filter must contain only one array property. e.g.: { ${$and_key}: [...] } OR { ${$or_key}: [...] } `;
|
|
@@ -1149,7 +1163,7 @@ export class ViewHandler {
|
|
|
1149
1163
|
}
|
|
1150
1164
|
|
|
1151
1165
|
const { [$and_key]: $and, [$or_key]: $or } = f,
|
|
1152
|
-
group = $and || $or;
|
|
1166
|
+
group: AnyObject[] = $and || $or;
|
|
1153
1167
|
|
|
1154
1168
|
if(group && group.length){
|
|
1155
1169
|
const operand = $and? " AND " : " OR ";
|
|
@@ -1175,7 +1189,7 @@ export class ViewHandler {
|
|
|
1175
1189
|
if(!isPlainObject(filter)) throw "\nInvalid filter\nExpecting an object but got -> " + JSON.stringify(filter);
|
|
1176
1190
|
|
|
1177
1191
|
|
|
1178
|
-
let _filter = { ...
|
|
1192
|
+
let _filter = { ...filter };
|
|
1179
1193
|
if(forcedFilter){
|
|
1180
1194
|
_filter = {
|
|
1181
1195
|
[$and_key]: [forcedFilter, _filter].filter(f => f)
|
|
@@ -1190,7 +1204,7 @@ export class ViewHandler {
|
|
|
1190
1204
|
return cond || "";
|
|
1191
1205
|
}
|
|
1192
1206
|
|
|
1193
|
-
async prepareExistCondition(eConfig: ExistsFilterConfig, localParams: LocalParams
|
|
1207
|
+
async prepareExistCondition(eConfig: ExistsFilterConfig, localParams: LocalParams | undefined): Promise<string> {
|
|
1194
1208
|
let res = "";
|
|
1195
1209
|
const thisTable = this.name;
|
|
1196
1210
|
const isNotExists = ["$notExists", "$notExistsJoined"].includes(eConfig.existType);
|
|
@@ -1214,11 +1228,11 @@ export class ViewHandler {
|
|
|
1214
1228
|
let expectOne = true;
|
|
1215
1229
|
tables.map((t2, depth) => {
|
|
1216
1230
|
let t1 = depth? tables[depth - 1] : thisTable;
|
|
1217
|
-
let exactPaths = [t1, t2];
|
|
1231
|
+
let exactPaths: string[] | undefined = [t1, t2];
|
|
1218
1232
|
|
|
1219
1233
|
if(!depth && eConfig.shortestJoin) exactPaths = undefined;
|
|
1220
1234
|
const jinf= this.getJoins(t1, t2, exactPaths, true);
|
|
1221
|
-
expectOne = expectOne && jinf.expectOne
|
|
1235
|
+
expectOne = Boolean(expectOne && jinf.expectOne)
|
|
1222
1236
|
joinPaths = joinPaths.concat(jinf.paths);
|
|
1223
1237
|
});
|
|
1224
1238
|
|
|
@@ -1229,7 +1243,7 @@ export class ViewHandler {
|
|
|
1229
1243
|
const { paths } = joinInfo;
|
|
1230
1244
|
const jp = paths[ji];
|
|
1231
1245
|
|
|
1232
|
-
let prevTable = ji? paths[ji - 1].table : jp.source;
|
|
1246
|
+
// let prevTable = ji? paths[ji - 1].table : jp.source;
|
|
1233
1247
|
let table = paths[ji].table;
|
|
1234
1248
|
let tableAlias = asName(ji < paths.length - 1? `jd${ji}` : table);
|
|
1235
1249
|
let prevTableAlias = asName(ji? `jd${ji - 1}` : thisTable);
|
|
@@ -1248,7 +1262,7 @@ export class ViewHandler {
|
|
|
1248
1262
|
j += `AND ${finalFilter} \n`;
|
|
1249
1263
|
}
|
|
1250
1264
|
|
|
1251
|
-
const indent = (a, b) => a;
|
|
1265
|
+
const indent = (a: any, b: any) => a;
|
|
1252
1266
|
|
|
1253
1267
|
if(ji < paths.length - 1){
|
|
1254
1268
|
j += `AND ${makeJoin(joinInfo, ji + 1)} \n`
|
|
@@ -1264,9 +1278,9 @@ export class ViewHandler {
|
|
|
1264
1278
|
|
|
1265
1279
|
}
|
|
1266
1280
|
|
|
1267
|
-
let t2Rules: TableRule = undefined,
|
|
1268
|
-
forcedFilter,
|
|
1269
|
-
filterFields,
|
|
1281
|
+
let t2Rules: TableRule | undefined = undefined,
|
|
1282
|
+
forcedFilter: AnyObject | undefined,
|
|
1283
|
+
filterFields: FieldFilter | undefined,
|
|
1270
1284
|
tableAlias;
|
|
1271
1285
|
|
|
1272
1286
|
/* Check if allowed to view data */
|
|
@@ -1378,7 +1392,7 @@ export class ViewHandler {
|
|
|
1378
1392
|
|
|
1379
1393
|
let existsCond = "";
|
|
1380
1394
|
if(existsKeys.length){
|
|
1381
|
-
existsCond = (await Promise.all(existsKeys.map(async k => await this.prepareExistCondition(k,
|
|
1395
|
+
existsCond = (await Promise.all(existsKeys.map(async k => await this.prepareExistCondition(k, localParams)))).join(" AND ");
|
|
1382
1396
|
}
|
|
1383
1397
|
|
|
1384
1398
|
/* Computed field queries */
|
|
@@ -1444,7 +1458,7 @@ export class ViewHandler {
|
|
|
1444
1458
|
const complexFilterKey = "$filter";
|
|
1445
1459
|
const allowedComparators = [">", "<", "=", "<=", ">=", "<>", "!="]
|
|
1446
1460
|
if(complexFilterKey in data){
|
|
1447
|
-
const getFuncQuery = (funcData): string => {
|
|
1461
|
+
const getFuncQuery = (funcData: any): string => {
|
|
1448
1462
|
const { funcName, args } = parseFunctionObject(funcData);
|
|
1449
1463
|
const funcDef = parseFunction({ func: funcName, args, functions: FUNCTIONS, allowedFields: allowed_colnames });
|
|
1450
1464
|
return funcDef.getQuery({ args, tableAlias, allColumns: this.columns, allowedFields: allowed_colnames });
|
|
@@ -1467,6 +1481,12 @@ export class ViewHandler {
|
|
|
1467
1481
|
complexFilters.push(result);
|
|
1468
1482
|
}
|
|
1469
1483
|
|
|
1484
|
+
|
|
1485
|
+
/* Parse join filters
|
|
1486
|
+
{ $joinFilter: { $ST_DWithin: [table.col, foreignTable.col, distance] }
|
|
1487
|
+
will make an exists filter
|
|
1488
|
+
*/
|
|
1489
|
+
|
|
1470
1490
|
let filterKeys = Object.keys(data).filter(k => k !== complexFilterKey && !funcFilterkeys.find(ek => ek.name === k) && !computedFields.find(cf => cf.name === k) && !existsKeys.find(ek => ek.key === k));
|
|
1471
1491
|
// if(allowed_colnames){
|
|
1472
1492
|
// const aliasedColumns = (select || []).filter(s =>
|
|
@@ -1523,7 +1543,7 @@ export class ViewHandler {
|
|
|
1523
1543
|
}
|
|
1524
1544
|
|
|
1525
1545
|
/* This relates only to SELECT */
|
|
1526
|
-
prepareSort(orderBy: OrderBy, allowed_cols, tableAlias: string, excludeOrder: boolean = false, select: SelectItem[]): string {
|
|
1546
|
+
prepareSort(orderBy: OrderBy | undefined, allowed_cols: FieldFilter, tableAlias: string | undefined, excludeOrder: boolean = false, select: SelectItem[]): string {
|
|
1527
1547
|
let column_names = this.column_names.slice(0);
|
|
1528
1548
|
|
|
1529
1549
|
const throwErr = () => {
|
|
@@ -1534,7 +1554,7 @@ export class ViewHandler {
|
|
|
1534
1554
|
[{ key1: true }, { key2: false }] \
|
|
1535
1555
|
[{ key: 'colName', asc: true, nulls: 'first', nullEmpty: true }]"
|
|
1536
1556
|
},
|
|
1537
|
-
parseOrderObj = (orderBy, expectOne = false): { key: string, asc: boolean, nulls?: "first" | "last", nullEmpty?: boolean }[] => {
|
|
1557
|
+
parseOrderObj = (orderBy: any, expectOne = false): { key: string, asc: boolean, nulls?: "first" | "last", nullEmpty?: boolean }[] => {
|
|
1538
1558
|
if(!isPlainObject(orderBy)) return throwErr();
|
|
1539
1559
|
|
|
1540
1560
|
const keys = Object.keys(orderBy);
|
|
@@ -1572,7 +1592,7 @@ export class ViewHandler {
|
|
|
1572
1592
|
|
|
1573
1593
|
if(!orderBy) return "";
|
|
1574
1594
|
|
|
1575
|
-
let allowedFields = [];
|
|
1595
|
+
let allowedFields: string[] = [];
|
|
1576
1596
|
if(allowed_cols){
|
|
1577
1597
|
allowedFields = this.parseFieldFilter(allowed_cols);
|
|
1578
1598
|
}
|
|
@@ -1624,7 +1644,7 @@ export class ViewHandler {
|
|
|
1624
1644
|
const orderType = asc? " ASC " : " DESC ";
|
|
1625
1645
|
const index = selectedAliases.indexOf(key) + 1;
|
|
1626
1646
|
const nullOrder = nulls? ` NULLS ${nulls === "first"? " FIRST " : " LAST "}` : "";
|
|
1627
|
-
let colKey = (index > 0 && !nullEmpty)? index : [tableAlias, key].filter(
|
|
1647
|
+
let colKey = (index > 0 && !nullEmpty)? index : [tableAlias, key].filter(isDefined).map(asName).join(".");
|
|
1628
1648
|
if(nullEmpty){
|
|
1629
1649
|
colKey = `nullif(trim(${colKey}::text), '')`
|
|
1630
1650
|
}
|
|
@@ -1657,7 +1677,7 @@ export class ViewHandler {
|
|
|
1657
1677
|
} else {
|
|
1658
1678
|
|
|
1659
1679
|
/* If a limit higher than maxLimit specified throw error */
|
|
1660
|
-
if(Number.isInteger(p.select.maxLimit) && _limit > p.select.maxLimit){
|
|
1680
|
+
if(Number.isInteger(p.select.maxLimit) && _limit > p.select.maxLimit!){
|
|
1661
1681
|
throw `Unexpected LIMIT ${_limit}. Must be less than the published maxLimit: ` + p.select.maxLimit;
|
|
1662
1682
|
}
|
|
1663
1683
|
}
|
|
@@ -1667,9 +1687,9 @@ export class ViewHandler {
|
|
|
1667
1687
|
}
|
|
1668
1688
|
|
|
1669
1689
|
/* This relates only to SELECT */
|
|
1670
|
-
prepareOffsetQuery(offset
|
|
1690
|
+
prepareOffsetQuery(offset?: number): number{
|
|
1671
1691
|
if(Number.isInteger(offset)){
|
|
1672
|
-
return offset
|
|
1692
|
+
return offset!;
|
|
1673
1693
|
}
|
|
1674
1694
|
|
|
1675
1695
|
return 0;
|
|
@@ -1677,7 +1697,7 @@ export class ViewHandler {
|
|
|
1677
1697
|
|
|
1678
1698
|
|
|
1679
1699
|
intersectColumns(allowedFields: FieldFilter, dissallowedFields: FieldFilter, fixIssues: boolean = false): string[] {
|
|
1680
|
-
let result = [];
|
|
1700
|
+
let result: string[] = [];
|
|
1681
1701
|
if(allowedFields){
|
|
1682
1702
|
result = this.parseFieldFilter(allowedFields);
|
|
1683
1703
|
}
|
|
@@ -1703,7 +1723,7 @@ export class ViewHandler {
|
|
|
1703
1723
|
* @param {Object} forcedData - set/override property
|
|
1704
1724
|
* @param {string[]} allowed_cols - allowed columns (excluding forcedData) from table rules
|
|
1705
1725
|
*/
|
|
1706
|
-
prepareFieldValues(obj:
|
|
1726
|
+
prepareFieldValues(obj: Record<string, any> = {}, forcedData: object = {}, allowed_cols: FieldFilter | undefined, fixIssues = false): AnyObject {
|
|
1707
1727
|
let column_names = this.column_names.slice(0);
|
|
1708
1728
|
if(!column_names || !column_names.length) throw "table column_names mising";
|
|
1709
1729
|
let _allowed_cols = column_names.slice(0);
|
|
@@ -1713,7 +1733,7 @@ export class ViewHandler {
|
|
|
1713
1733
|
_allowed_cols = this.parseFieldFilter(allowed_cols, false);
|
|
1714
1734
|
}
|
|
1715
1735
|
let final_filter = { ..._obj },
|
|
1716
|
-
filter_keys = Object.keys(final_filter);
|
|
1736
|
+
filter_keys: Array<keyof typeof final_filter> = Object.keys(final_filter);
|
|
1717
1737
|
|
|
1718
1738
|
if(fixIssues && filter_keys.length){
|
|
1719
1739
|
final_filter = {};
|
|
@@ -1750,7 +1770,7 @@ export class ViewHandler {
|
|
|
1750
1770
|
static _parseFieldFilter(fieldParams: FieldFilter = "*", allow_empty: boolean = true, all_cols: string[]): string[] {
|
|
1751
1771
|
if(!all_cols) throw "all_cols missing"
|
|
1752
1772
|
const all_fields = all_cols;// || this.column_names.slice(0);
|
|
1753
|
-
let colNames =
|
|
1773
|
+
let colNames: string[] = [],
|
|
1754
1774
|
initialParams = JSON.stringify(fieldParams);
|
|
1755
1775
|
|
|
1756
1776
|
if(fieldParams){
|
|
@@ -1793,7 +1813,9 @@ export class ViewHandler {
|
|
|
1793
1813
|
} else if(isPlainObject(fieldParams)){
|
|
1794
1814
|
|
|
1795
1815
|
if(Object.keys(fieldParams).length){
|
|
1796
|
-
let keys = Object.keys(fieldParams
|
|
1816
|
+
let keys = Object.keys(fieldParams as {
|
|
1817
|
+
[key: string]: boolean | 0 | 1;
|
|
1818
|
+
});
|
|
1797
1819
|
if(keys[0] === ""){
|
|
1798
1820
|
if(allow_empty){
|
|
1799
1821
|
return [""];
|
|
@@ -1806,11 +1828,11 @@ export class ViewHandler {
|
|
|
1806
1828
|
|
|
1807
1829
|
keys.forEach(key => {
|
|
1808
1830
|
const allowedVals = [true, false, 0, 1];
|
|
1809
|
-
if(!allowedVals.includes(fieldParams[key])) throw `Invalid field selection value for: { ${key}: ${fieldParams[key]} }. \n Allowed values: ${allowedVals.join(" OR ")}`
|
|
1831
|
+
if(!allowedVals.includes((fieldParams as any)[key])) throw `Invalid field selection value for: { ${key}: ${(fieldParams as any)[key]} }. \n Allowed values: ${allowedVals.join(" OR ")}`
|
|
1810
1832
|
})
|
|
1811
1833
|
|
|
1812
|
-
let allowed = keys.filter(key => fieldParams[key]),
|
|
1813
|
-
disallowed = keys.filter(key => !fieldParams[key]);
|
|
1834
|
+
let allowed = keys.filter(key => (fieldParams as any)[key]),
|
|
1835
|
+
disallowed = keys.filter(key => !(fieldParams as any)[key]);
|
|
1814
1836
|
|
|
1815
1837
|
|
|
1816
1838
|
if(disallowed && disallowed.length){
|
|
@@ -1838,7 +1860,7 @@ export class ViewHandler {
|
|
|
1838
1860
|
}
|
|
1839
1861
|
}
|
|
1840
1862
|
|
|
1841
|
-
function isPojoObject(obj):
|
|
1863
|
+
function isPojoObject<T>(obj: T): obj is Record<string, any> {
|
|
1842
1864
|
if(obj && (typeof obj !== "object" || Array.isArray(obj) || obj instanceof Date)){
|
|
1843
1865
|
return false;
|
|
1844
1866
|
}
|
|
@@ -1847,10 +1869,10 @@ function isPojoObject(obj): boolean {
|
|
|
1847
1869
|
|
|
1848
1870
|
|
|
1849
1871
|
type ValidatedParams = {
|
|
1850
|
-
row:
|
|
1851
|
-
forcedData
|
|
1852
|
-
allowedFields
|
|
1853
|
-
tableRules
|
|
1872
|
+
row: AnyObject;
|
|
1873
|
+
forcedData?: AnyObject;
|
|
1874
|
+
allowedFields?: FieldFilter;
|
|
1875
|
+
tableRules?: TableRule;
|
|
1854
1876
|
fixIssues: boolean;
|
|
1855
1877
|
}
|
|
1856
1878
|
|
|
@@ -1859,7 +1881,7 @@ export class TableHandler extends ViewHandler {
|
|
|
1859
1881
|
throttle_queries_per_sec: number;
|
|
1860
1882
|
since: number,
|
|
1861
1883
|
queries: number,
|
|
1862
|
-
batching: string[]
|
|
1884
|
+
batching: string[] | null
|
|
1863
1885
|
}
|
|
1864
1886
|
|
|
1865
1887
|
constructor(db: DB, tableOrViewInfo: TableSchema, dboBuilder: DboBuilder, t?: pgPromise.ITask<{}>, dbTX?: TxHandler, joinPaths?: JoinPaths){
|
|
@@ -1894,8 +1916,8 @@ export class TableHandler extends ViewHandler {
|
|
|
1894
1916
|
}
|
|
1895
1917
|
|
|
1896
1918
|
async subscribe(filter: Filter, params: SubscribeParams, localFunc: (items: AnyObject[]) => any): Promise<{ unsubscribe: () => any }>
|
|
1897
|
-
async subscribe(filter: Filter, params: SubscribeParams, localFunc
|
|
1898
|
-
async subscribe(filter: Filter, params: SubscribeParams = {}, localFunc
|
|
1919
|
+
async subscribe(filter: Filter, params: SubscribeParams, localFunc?: (items: AnyObject[]) => any, table_rules?: TableRule, localParams?: LocalParams): Promise<string>
|
|
1920
|
+
async subscribe(filter: Filter, params: SubscribeParams = {}, localFunc?: (items: AnyObject[]) => any, table_rules?: TableRule, localParams?: LocalParams):
|
|
1899
1921
|
Promise<string | { unsubscribe: () => any }>
|
|
1900
1922
|
{
|
|
1901
1923
|
try {
|
|
@@ -1908,7 +1930,7 @@ export class TableHandler extends ViewHandler {
|
|
|
1908
1930
|
}
|
|
1909
1931
|
|
|
1910
1932
|
const { filterFields, forcedFilter } = get(table_rules, "select") || {},
|
|
1911
|
-
condition = await this.prepareWhere({ filter, forcedFilter, addKeywords: false, filterFields, tableAlias:
|
|
1933
|
+
condition = await this.prepareWhere({ filter, forcedFilter, addKeywords: false, filterFields, tableAlias: undefined, localParams, tableRule: table_rules }),
|
|
1912
1934
|
throttle = get(params, "throttle") || 0,
|
|
1913
1935
|
selectParams = filterObj(params || {}, [], ["throttle"]);
|
|
1914
1936
|
|
|
@@ -1920,21 +1942,20 @@ export class TableHandler extends ViewHandler {
|
|
|
1920
1942
|
|
|
1921
1943
|
if(!localFunc) {
|
|
1922
1944
|
if(!this.dboBuilder.prostgles.isSuperUser) throw "Subscribe not possible. Must be superuser to add triggers 1856";
|
|
1923
|
-
return await this.find(filter, { ...selectParams, limit: 0 },
|
|
1945
|
+
return await this.find(filter, { ...selectParams, limit: 0 }, undefined, table_rules, localParams)
|
|
1924
1946
|
.then(async isValid => {
|
|
1925
1947
|
|
|
1926
|
-
const { socket
|
|
1948
|
+
const { socket } = localParams ?? {};
|
|
1927
1949
|
const pubSubManager = await this.dboBuilder.getPubSubManager();
|
|
1928
1950
|
return pubSubManager.addSub({
|
|
1929
1951
|
table_info: this.tableOrViewInfo,
|
|
1930
1952
|
socket,
|
|
1931
1953
|
table_rules,
|
|
1932
1954
|
condition: condition,
|
|
1933
|
-
func:
|
|
1955
|
+
func: undefined,
|
|
1934
1956
|
filter: { ...filter },
|
|
1935
1957
|
params: { ...selectParams },
|
|
1936
|
-
|
|
1937
|
-
socket_id: socket.id,
|
|
1958
|
+
socket_id: socket?.id,
|
|
1938
1959
|
table_name: this.name,
|
|
1939
1960
|
throttle,
|
|
1940
1961
|
last_throttled: 0,
|
|
@@ -1945,14 +1966,13 @@ export class TableHandler extends ViewHandler {
|
|
|
1945
1966
|
const pubSubManager = await this.dboBuilder.getPubSubManager();
|
|
1946
1967
|
pubSubManager.addSub({
|
|
1947
1968
|
table_info: this.tableOrViewInfo,
|
|
1948
|
-
socket:
|
|
1969
|
+
socket: undefined,
|
|
1949
1970
|
table_rules,
|
|
1950
1971
|
condition,
|
|
1951
1972
|
func: localFunc,
|
|
1952
1973
|
filter: { ...filter },
|
|
1953
1974
|
params: { ...selectParams },
|
|
1954
|
-
|
|
1955
|
-
socket_id: null,
|
|
1975
|
+
socket_id: undefined,
|
|
1956
1976
|
table_name: this.name,
|
|
1957
1977
|
throttle,
|
|
1958
1978
|
last_throttled: 0,
|
|
@@ -1977,12 +1997,12 @@ export class TableHandler extends ViewHandler {
|
|
|
1977
1997
|
subscribeOne(filter: Filter, params: SubscribeParams = {}, localFunc: (item: AnyObject) => any, table_rules?: TableRule, localParams?: LocalParams):
|
|
1978
1998
|
Promise<string | { unsubscribe: () => any }>
|
|
1979
1999
|
{
|
|
1980
|
-
let func = localParams? undefined : (rows) => localFunc(rows[0]);
|
|
2000
|
+
let func = localParams? undefined : (rows: AnyObject[]) => localFunc(rows[0]);
|
|
1981
2001
|
return this.subscribe(filter, { ...params, limit: 2 }, func, table_rules, localParams);
|
|
1982
2002
|
}
|
|
1983
2003
|
|
|
1984
2004
|
|
|
1985
|
-
async updateBatch(data: [Filter, AnyObject][], params?: UpdateParams, tableRules?: TableRule, localParams
|
|
2005
|
+
async updateBatch(data: [Filter, AnyObject][], params?: UpdateParams, tableRules?: TableRule, localParams?: LocalParams): Promise<any>{
|
|
1986
2006
|
try {
|
|
1987
2007
|
const queries = await Promise.all(
|
|
1988
2008
|
data.map(async ([filter, data]) =>
|
|
@@ -2006,20 +2026,20 @@ export class TableHandler extends ViewHandler {
|
|
|
2006
2026
|
}
|
|
2007
2027
|
}
|
|
2008
2028
|
|
|
2009
|
-
async update(filter: Filter, newData:
|
|
2029
|
+
async update(filter: Filter, newData: AnyObject, params?: UpdateParams, tableRules?: TableRule, localParams?: LocalParams): Promise<AnyObject | void>{
|
|
2010
2030
|
try {
|
|
2011
2031
|
|
|
2012
|
-
const { testRule = false, returnQuery = false } = localParams
|
|
2032
|
+
const { testRule = false, returnQuery = false } = localParams ?? {};
|
|
2013
2033
|
if(!testRule){
|
|
2014
2034
|
if(!newData || !Object.keys(newData).length) throw "no update data provided\nEXPECTING db.table.update(filter, updateData, options)";
|
|
2015
2035
|
this.checkFilter(filter);
|
|
2016
2036
|
}
|
|
2017
2037
|
|
|
2018
|
-
let forcedFilter:
|
|
2019
|
-
forcedData:
|
|
2020
|
-
validate: ValidateRow,
|
|
2021
|
-
returningFields: FieldFilter = "*",
|
|
2022
|
-
filterFields: FieldFilter = "*",
|
|
2038
|
+
let forcedFilter: AnyObject | undefined = {},
|
|
2039
|
+
forcedData: AnyObject | undefined = {},
|
|
2040
|
+
validate: ValidateRow | undefined,
|
|
2041
|
+
returningFields: FieldFilter | undefined = "*",
|
|
2042
|
+
filterFields: FieldFilter | undefined = "*",
|
|
2023
2043
|
fields: FieldFilter = "*";
|
|
2024
2044
|
|
|
2025
2045
|
if(tableRules){
|
|
@@ -2034,7 +2054,7 @@ export class TableHandler extends ViewHandler {
|
|
|
2034
2054
|
await this.validateViewRules(fields, filterFields, returningFields, forcedFilter, "update");
|
|
2035
2055
|
if(forcedData) {
|
|
2036
2056
|
try {
|
|
2037
|
-
const { data, allowedCols } = this.validateNewData({ row: forcedData, forcedData:
|
|
2057
|
+
const { data, allowedCols } = this.validateNewData({ row: forcedData, forcedData: undefined, allowedFields: "*", tableRules, fixIssues: false });
|
|
2038
2058
|
const updateQ = await this.colSet.getUpdateQuery(data, allowedCols, validate) //pgp.helpers.update(data, columnSet)
|
|
2039
2059
|
let query = updateQ + " WHERE FALSE ";
|
|
2040
2060
|
await this.db.any("EXPLAIN " + query);
|
|
@@ -2079,13 +2099,13 @@ export class TableHandler extends ViewHandler {
|
|
|
2079
2099
|
if(c.data_type === "text" && d && isPlainObject(d) && !["from", "to"].find(key => typeof d[key] !== "number")){
|
|
2080
2100
|
const unrecProps = Object.keys(d).filter(k => !["from", "to", "text", "md5"].includes(k));
|
|
2081
2101
|
if(unrecProps.length) throw "Unrecognised params in textPatch field: " + unrecProps.join(", ");
|
|
2082
|
-
patchedTextData.push({ ...d, fieldName: c.name });
|
|
2102
|
+
patchedTextData.push({ ...d, fieldName: c.name } as (typeof patchedTextData)[number]);
|
|
2083
2103
|
}
|
|
2084
2104
|
});
|
|
2085
2105
|
|
|
2086
2106
|
if(patchedTextData && patchedTextData.length){
|
|
2087
2107
|
if(tableRules && !tableRules.select) throw "Select needs to be permitted to patch data";
|
|
2088
|
-
const rows = await this.find(filter, { select: patchedTextData.reduce((a, v) => ({ ...a, [v.fieldName]: 1 }), {}) },
|
|
2108
|
+
const rows = await this.find(filter, { select: patchedTextData.reduce((a, v) => ({ ...a, [v.fieldName]: 1 }), {}) }, undefined, tableRules);
|
|
2089
2109
|
|
|
2090
2110
|
if(rows.length !== 1) {
|
|
2091
2111
|
throw "Cannot patch data within a filter that affects more/less than 1 row";
|
|
@@ -2121,9 +2141,9 @@ export class TableHandler extends ViewHandler {
|
|
|
2121
2141
|
if(returnQuery) return query as unknown as void;
|
|
2122
2142
|
|
|
2123
2143
|
if(this.t){
|
|
2124
|
-
return this.t[qType](query).catch(err => makeErr(err, localParams, this, _fields));
|
|
2144
|
+
return (this.t as any)[qType](query).catch((err: any) => makeErr(err, localParams, this, _fields));
|
|
2125
2145
|
}
|
|
2126
|
-
return this.db.tx(t => t[qType](query)).catch(err => makeErr(err, localParams, this, _fields));
|
|
2146
|
+
return this.db.tx(t => (t as any)[qType](query)).catch(err => makeErr(err, localParams, this, _fields));
|
|
2127
2147
|
} catch(e){
|
|
2128
2148
|
if(localParams && localParams.testRule) throw e;
|
|
2129
2149
|
throw { err: parseError(e), msg: `Issue with dbo.${this.name}.update(${JSON.stringify(filter || {}, null, 2)}, ${JSON.stringify(newData || {}, null, 2)}, ${JSON.stringify(params || {}, null, 2)})` };
|
|
@@ -2131,7 +2151,7 @@ export class TableHandler extends ViewHandler {
|
|
|
2131
2151
|
};
|
|
2132
2152
|
|
|
2133
2153
|
validateNewData({ row, forcedData, allowedFields, tableRules, fixIssues = false }: ValidatedParams): { data: any; allowedCols: string[] } {
|
|
2134
|
-
const synced_field = get(tableRules
|
|
2154
|
+
const synced_field = get(tableRules ?? {}, "sync.synced_field");
|
|
2135
2155
|
|
|
2136
2156
|
/* Update synced_field if sync is on and missing */
|
|
2137
2157
|
if(synced_field && !row[synced_field]){
|
|
@@ -2139,7 +2159,7 @@ export class TableHandler extends ViewHandler {
|
|
|
2139
2159
|
}
|
|
2140
2160
|
|
|
2141
2161
|
let data = this.prepareFieldValues(row, forcedData, allowedFields, fixIssues);
|
|
2142
|
-
const dataKeys =
|
|
2162
|
+
const dataKeys = getKeys(data);
|
|
2143
2163
|
|
|
2144
2164
|
dataKeys.map(col => {
|
|
2145
2165
|
this.dboBuilder.prostgles?.tableConfigurator?.checkColVal({ table: this.name, col, value: data[col] });
|
|
@@ -2158,7 +2178,7 @@ export class TableHandler extends ViewHandler {
|
|
|
2158
2178
|
}
|
|
2159
2179
|
|
|
2160
2180
|
|
|
2161
|
-
private async insertDataParse(data: (AnyObject | AnyObject[]), param2?: InsertParams, param3_unused
|
|
2181
|
+
private async insertDataParse(data: (AnyObject | AnyObject[]), param2?: InsertParams, param3_unused?: never, tableRules?: TableRule, _localParams?: LocalParams): Promise<{
|
|
2162
2182
|
data?: AnyObject | AnyObject[];
|
|
2163
2183
|
insertResult?: AnyObject | AnyObject[];
|
|
2164
2184
|
}>{
|
|
@@ -2166,7 +2186,7 @@ export class TableHandler extends ViewHandler {
|
|
|
2166
2186
|
let dbTX = localParams?.dbTX || this.dbTX;
|
|
2167
2187
|
|
|
2168
2188
|
const isMultiInsert = Array.isArray(data);
|
|
2169
|
-
const getExtraKeys = d => Object.keys(d).filter(k => !this.columns.find(c => c.name === k));
|
|
2189
|
+
const getExtraKeys = (d: AnyObject)=> Object.keys(d).filter(k => !this.columns.find(c => c.name === k));
|
|
2170
2190
|
|
|
2171
2191
|
/* Nested insert is not allowed for the file table */
|
|
2172
2192
|
const isNestedInsert = this.is_media? false : (Array.isArray(data)? data : [data]).some(d => getExtraKeys(d).length);
|
|
@@ -2231,7 +2251,7 @@ export class TableHandler extends ViewHandler {
|
|
|
2231
2251
|
const _media: Media = await this.dboBuilder.prostgles.fileManager.uploadAsMedia({
|
|
2232
2252
|
item: {
|
|
2233
2253
|
data,
|
|
2234
|
-
name: media.name,
|
|
2254
|
+
name: media.name ?? "????",
|
|
2235
2255
|
content_type: media.content_type as any
|
|
2236
2256
|
},
|
|
2237
2257
|
// imageCompression: {
|
|
@@ -2251,21 +2271,21 @@ export class TableHandler extends ViewHandler {
|
|
|
2251
2271
|
} else if(extraKeys.length){
|
|
2252
2272
|
|
|
2253
2273
|
/* Ensure we're using the same transaction */
|
|
2254
|
-
const _this = this.t? this : dbTX[this.name] as TableHandler;
|
|
2274
|
+
const _this = this.t? this : dbTX![this.name] as TableHandler;
|
|
2255
2275
|
|
|
2256
|
-
let rootData = filterObj(data,
|
|
2276
|
+
let rootData = filterObj(data, undefined, extraKeys);
|
|
2257
2277
|
|
|
2258
2278
|
let insertedChildren: AnyObject[];
|
|
2259
2279
|
let targetTableRules: TableRule;
|
|
2260
2280
|
|
|
2261
|
-
const fullRootResult = await _this.insert(rootData, { returning: "*" },
|
|
2262
|
-
let returnData: AnyObject;
|
|
2281
|
+
const fullRootResult = await _this.insert(rootData, { returning: "*" }, undefined, tableRules, localParams);
|
|
2282
|
+
let returnData: AnyObject | undefined;
|
|
2263
2283
|
const returning = param2?.returning;
|
|
2264
2284
|
if(returning){
|
|
2265
2285
|
returnData = {}
|
|
2266
2286
|
const returningItems = await this.prepareReturning(returning, this.parseFieldFilter(tableRules?.insert?.returningFields));
|
|
2267
2287
|
returningItems.filter(s => s.selected).map(rs => {
|
|
2268
|
-
returnData[rs.alias] = fullRootResult[rs.alias];
|
|
2288
|
+
returnData![rs.alias] = fullRootResult[rs.alias];
|
|
2269
2289
|
})
|
|
2270
2290
|
}
|
|
2271
2291
|
|
|
@@ -2274,7 +2294,7 @@ export class TableHandler extends ViewHandler {
|
|
|
2274
2294
|
|
|
2275
2295
|
/* Must be allowed to insert into media table */
|
|
2276
2296
|
const canInsert = async (tbl: string) => {
|
|
2277
|
-
const childRules = await this.dboBuilder.publishParser
|
|
2297
|
+
const childRules = await this.dboBuilder.publishParser?.getValidatedRequestRuleWusr({ tableName: tbl, command: "insert", localParams });
|
|
2278
2298
|
if(!childRules || !childRules.insert) throw "Dissallowed nested insert into table " + childRules;
|
|
2279
2299
|
return childRules;
|
|
2280
2300
|
}
|
|
@@ -2284,9 +2304,9 @@ export class TableHandler extends ViewHandler {
|
|
|
2284
2304
|
if(!jp) throw `Could not find a valid table for the nested data { ${targetTable} } `;
|
|
2285
2305
|
|
|
2286
2306
|
const thisInfo = await this.getInfo();
|
|
2287
|
-
const childInsert = async (cdata, tableName) => {
|
|
2307
|
+
const childInsert = async (cdata: AnyObject | AnyObject[], tableName: string) => {
|
|
2288
2308
|
// console.log("childInsert", {data, tableName})
|
|
2289
|
-
if(!cdata || !dbTX[tableName] || !("insert" in dbTX[tableName])) throw "childInsertErr: Child table handler missing for: " + tableName;
|
|
2309
|
+
if(!cdata || !dbTX?.[tableName] || !("insert" in dbTX[tableName])) throw "childInsertErr: Child table handler missing for: " + tableName;
|
|
2290
2310
|
|
|
2291
2311
|
const tableRules = await canInsert(tableName);
|
|
2292
2312
|
|
|
@@ -2295,8 +2315,8 @@ export class TableHandler extends ViewHandler {
|
|
|
2295
2315
|
}
|
|
2296
2316
|
return Promise.all(
|
|
2297
2317
|
(Array.isArray(cdata)? cdata : [cdata])
|
|
2298
|
-
.map(m => (dbTX[tableName] as TableHandler)
|
|
2299
|
-
.insert(m, { returning: "*" },
|
|
2318
|
+
.map(m => (dbTX![tableName] as TableHandler)
|
|
2319
|
+
.insert(m, { returning: "*" }, undefined, tableRules, localParams)
|
|
2300
2320
|
.catch(e => {
|
|
2301
2321
|
console.trace({ childInsertErr: e })
|
|
2302
2322
|
return Promise.reject({ childInsertErr: e });
|
|
@@ -2323,10 +2343,10 @@ export class TableHandler extends ViewHandler {
|
|
|
2323
2343
|
|
|
2324
2344
|
// console.log(childDataItems, JSON.stringify(colsRefT1, null, 2))
|
|
2325
2345
|
insertedChildren = await childInsert(
|
|
2326
|
-
childDataItems.map(d => {
|
|
2346
|
+
childDataItems.map((d: AnyObject) => {
|
|
2327
2347
|
let result = {...d};
|
|
2328
2348
|
colsRefT1.map(col => {
|
|
2329
|
-
result[col.references
|
|
2349
|
+
result[col.references!.cols[0]] = fullRootResult[col.references!.fcols[0]]
|
|
2330
2350
|
})
|
|
2331
2351
|
return result;
|
|
2332
2352
|
}),
|
|
@@ -2339,7 +2359,7 @@ export class TableHandler extends ViewHandler {
|
|
|
2339
2359
|
const colsRefT3 = cols2?.filter(c => c.references?.cols.length === 1 && c.references?.ftable === tbl3);
|
|
2340
2360
|
if(!colsRefT1.length || !colsRefT3.length) throw "Incorrectly referenced or missing columns for nested insert";
|
|
2341
2361
|
|
|
2342
|
-
if(targetTable !== this.dboBuilder.prostgles.fileManager
|
|
2362
|
+
if(targetTable !== this.dboBuilder.prostgles.fileManager?.tableName){
|
|
2343
2363
|
throw "Only media allowed to have nested inserts more than 2 tables apart"
|
|
2344
2364
|
}
|
|
2345
2365
|
|
|
@@ -2352,13 +2372,13 @@ export class TableHandler extends ViewHandler {
|
|
|
2352
2372
|
|
|
2353
2373
|
/* Insert in key_lookup table */
|
|
2354
2374
|
await Promise.all(insertedChildren.map(async t3Child => {
|
|
2355
|
-
let tbl2Row = {};
|
|
2375
|
+
let tbl2Row: AnyObject = {};
|
|
2356
2376
|
|
|
2357
2377
|
colsRefT3.map(col => {
|
|
2358
|
-
tbl2Row[col.name] = t3Child[col.references
|
|
2378
|
+
tbl2Row[col.name] = t3Child[col.references!.fcols[0]];
|
|
2359
2379
|
})
|
|
2360
2380
|
colsRefT1.map(col => {
|
|
2361
|
-
tbl2Row[col.name] = fullRootResult[col.references
|
|
2381
|
+
tbl2Row[col.name] = fullRootResult[col.references!.fcols[0]];
|
|
2362
2382
|
})
|
|
2363
2383
|
// console.log({ rootResult, tbl2Row, t3Child, colsRefT3, colsRefT1, t: this.t?.ctx?.start });
|
|
2364
2384
|
|
|
@@ -2372,18 +2392,18 @@ export class TableHandler extends ViewHandler {
|
|
|
2372
2392
|
|
|
2373
2393
|
/* Return also the nested inserted data */
|
|
2374
2394
|
if(targetTableRules && insertedChildren?.length && returning){
|
|
2375
|
-
const targetTableHandler = dbTX[targetTable] as TableHandler;
|
|
2395
|
+
const targetTableHandler = dbTX![targetTable] as TableHandler;
|
|
2376
2396
|
const targetReturning = await targetTableHandler.prepareReturning("*", targetTableHandler.parseFieldFilter(targetTableRules?.insert?.returningFields));
|
|
2377
2397
|
let clientTargetInserts = insertedChildren.map(d => {
|
|
2378
2398
|
let _d = { ...d };
|
|
2379
|
-
let res = {};
|
|
2399
|
+
let res: AnyObject = {};
|
|
2380
2400
|
targetReturning.map(r => {
|
|
2381
2401
|
res[r.alias] = _d[r.alias]
|
|
2382
2402
|
});
|
|
2383
2403
|
return res;
|
|
2384
2404
|
});
|
|
2385
2405
|
|
|
2386
|
-
returnData[targetTable] = clientTargetInserts.length === 1? clientTargetInserts[0] : clientTargetInserts;
|
|
2406
|
+
returnData![targetTable] = clientTargetInserts.length === 1? clientTargetInserts[0] : clientTargetInserts;
|
|
2387
2407
|
}
|
|
2388
2408
|
}));
|
|
2389
2409
|
|
|
@@ -2404,7 +2424,7 @@ export class TableHandler extends ViewHandler {
|
|
|
2404
2424
|
return res;
|
|
2405
2425
|
}
|
|
2406
2426
|
|
|
2407
|
-
async insert(rowOrRows: (AnyObject | AnyObject[]), param2?: InsertParams, param3_unused
|
|
2427
|
+
async insert(rowOrRows: (AnyObject | AnyObject[]), param2?: InsertParams, param3_unused?: never, tableRules?: TableRule, _localParams?: LocalParams): Promise<any | any[] | boolean>{
|
|
2408
2428
|
const localParams = _localParams || {};
|
|
2409
2429
|
const {dbTX} = localParams
|
|
2410
2430
|
try {
|
|
@@ -2412,9 +2432,9 @@ export class TableHandler extends ViewHandler {
|
|
|
2412
2432
|
const { returning, onConflictDoNothing, fixIssues = false } = param2 || {};
|
|
2413
2433
|
const { testRule = false, returnQuery = false } = localParams || {};
|
|
2414
2434
|
|
|
2415
|
-
let returningFields: FieldFilter,
|
|
2416
|
-
forcedData:
|
|
2417
|
-
fields: FieldFilter;
|
|
2435
|
+
let returningFields: FieldFilter | undefined,
|
|
2436
|
+
forcedData: AnyObject | undefined,
|
|
2437
|
+
fields: FieldFilter | undefined;
|
|
2418
2438
|
|
|
2419
2439
|
if(tableRules){
|
|
2420
2440
|
if(!tableRules.insert) throw "insert rules missing for " + this.name;
|
|
@@ -2430,7 +2450,7 @@ export class TableHandler extends ViewHandler {
|
|
|
2430
2450
|
/* Safely test publish rules */
|
|
2431
2451
|
if(testRule){
|
|
2432
2452
|
// if(this.is_media && tableRules.insert.preValidate) throw "Media table cannot have a preValidate. It already is used internally by prostgles for file upload";
|
|
2433
|
-
await this.validateViewRules(fields,
|
|
2453
|
+
await this.validateViewRules(fields, undefined, returningFields, undefined, "insert");
|
|
2434
2454
|
if(forcedData) {
|
|
2435
2455
|
const keys = Object.keys(forcedData);
|
|
2436
2456
|
if(keys.length){
|
|
@@ -2462,7 +2482,7 @@ export class TableHandler extends ViewHandler {
|
|
|
2462
2482
|
|
|
2463
2483
|
if(!rowOrRows) rowOrRows = {}; //throw "Provide data in param1";
|
|
2464
2484
|
let returningSelect = this.makeReturnQuery(await this.prepareReturning(returning, this.parseFieldFilter(returningFields)));
|
|
2465
|
-
const makeQuery = async (_row, isOne = false) => {
|
|
2485
|
+
const makeQuery = async (_row: AnyObject | undefined, isOne = false) => {
|
|
2466
2486
|
let row = { ..._row };
|
|
2467
2487
|
|
|
2468
2488
|
if(!isPojoObject(row)) {
|
|
@@ -2480,7 +2500,7 @@ export class TableHandler extends ViewHandler {
|
|
|
2480
2500
|
};
|
|
2481
2501
|
|
|
2482
2502
|
let query = "";
|
|
2483
|
-
let queryType = "none";
|
|
2503
|
+
let queryType: keyof pgPromise.ITask<{}> = "none";
|
|
2484
2504
|
|
|
2485
2505
|
/**
|
|
2486
2506
|
* If media it will: upload file and continue insert
|
|
@@ -2517,9 +2537,9 @@ export class TableHandler extends ViewHandler {
|
|
|
2517
2537
|
|
|
2518
2538
|
const allowedFieldKeys = this.parseFieldFilter(fields);
|
|
2519
2539
|
if(tx) {
|
|
2520
|
-
result = tx[queryType](query).catch(err => makeErr(err, localParams, this, allowedFieldKeys));
|
|
2540
|
+
result = (tx as any)[queryType](query).catch((err: any) => makeErr(err, localParams, this, allowedFieldKeys));
|
|
2521
2541
|
} else {
|
|
2522
|
-
result = this.db.tx(t => t[queryType](query)).catch(err => makeErr(err, localParams, this, allowedFieldKeys));
|
|
2542
|
+
result = this.db.tx(t => (t as any)[queryType](query)).catch(err => makeErr(err, localParams, this, allowedFieldKeys));
|
|
2523
2543
|
}
|
|
2524
2544
|
|
|
2525
2545
|
return result;
|
|
@@ -2532,7 +2552,7 @@ export class TableHandler extends ViewHandler {
|
|
|
2532
2552
|
}
|
|
2533
2553
|
};
|
|
2534
2554
|
|
|
2535
|
-
prepareReturning = async (returning:
|
|
2555
|
+
prepareReturning = async (returning: Select<AnyObject>, allowedFields: string[]): Promise<SelectItem[]> => {
|
|
2536
2556
|
let result: SelectItem[] = [];
|
|
2537
2557
|
if(returning){
|
|
2538
2558
|
let sBuilder = new SelectItemBuilder({
|
|
@@ -2556,7 +2576,7 @@ export class TableHandler extends ViewHandler {
|
|
|
2556
2576
|
return "";
|
|
2557
2577
|
}
|
|
2558
2578
|
|
|
2559
|
-
async delete(filter?: Filter, params?: DeleteParams, param3_unused
|
|
2579
|
+
async delete(filter?: Filter, params?: DeleteParams, param3_unused?: never, table_rules?: TableRule, localParams?: LocalParams): Promise<any> { //{ socket, func, has_rules = false, socketDb } = {}
|
|
2560
2580
|
try {
|
|
2561
2581
|
const { returning } = params || {};
|
|
2562
2582
|
filter = filter || {};
|
|
@@ -2564,9 +2584,9 @@ export class TableHandler extends ViewHandler {
|
|
|
2564
2584
|
|
|
2565
2585
|
// table_rules = table_rules || {};
|
|
2566
2586
|
|
|
2567
|
-
let forcedFilter:
|
|
2568
|
-
filterFields: FieldFilter = "*",
|
|
2569
|
-
returningFields: FieldFilter = "*";
|
|
2587
|
+
let forcedFilter: AnyObject | undefined = {},
|
|
2588
|
+
filterFields: FieldFilter | undefined = "*",
|
|
2589
|
+
returningFields: FieldFilter | undefined = "*";
|
|
2570
2590
|
|
|
2571
2591
|
const { testRule = false, returnQuery = false } = localParams || {};
|
|
2572
2592
|
if(table_rules){
|
|
@@ -2582,7 +2602,7 @@ export class TableHandler extends ViewHandler {
|
|
|
2582
2602
|
|
|
2583
2603
|
/* Safely test publish rules */
|
|
2584
2604
|
if(testRule){
|
|
2585
|
-
await this.validateViewRules(
|
|
2605
|
+
await this.validateViewRules(undefined, filterFields, returningFields, forcedFilter, "delete");
|
|
2586
2606
|
return true;
|
|
2587
2607
|
}
|
|
2588
2608
|
}
|
|
@@ -2594,7 +2614,7 @@ export class TableHandler extends ViewHandler {
|
|
|
2594
2614
|
if(bad_params && bad_params.length) throw "Invalid params: " + bad_params.join(", ") + " \n Expecting: " + good_params.join(", ");
|
|
2595
2615
|
}
|
|
2596
2616
|
|
|
2597
|
-
let queryType = 'none';
|
|
2617
|
+
let queryType: keyof pgPromise.ITask<{}> = 'none';
|
|
2598
2618
|
let _query = "DELETE FROM " + this.escapedName;
|
|
2599
2619
|
|
|
2600
2620
|
_query += (await this.prepareWhere({
|
|
@@ -2614,7 +2634,7 @@ export class TableHandler extends ViewHandler {
|
|
|
2614
2634
|
}
|
|
2615
2635
|
|
|
2616
2636
|
if(returnQuery) return _query;
|
|
2617
|
-
return (this.t || this.db)[queryType](_query).catch(err => makeErr(err, localParams));
|
|
2637
|
+
return (this.t || this.db as any)[queryType](_query).catch((err: any) => makeErr(err, localParams));
|
|
2618
2638
|
} catch(e){
|
|
2619
2639
|
// console.trace(e)
|
|
2620
2640
|
if(localParams && localParams.testRule) throw e;
|
|
@@ -2622,11 +2642,11 @@ export class TableHandler extends ViewHandler {
|
|
|
2622
2642
|
}
|
|
2623
2643
|
};
|
|
2624
2644
|
|
|
2625
|
-
remove(filter: Filter, params?: UpdateParams, param3_unused?:
|
|
2645
|
+
remove(filter: Filter, params?: UpdateParams, param3_unused?: never, tableRules?: TableRule, localParams?: LocalParams){
|
|
2626
2646
|
return this.delete(filter, params, param3_unused , tableRules, localParams);
|
|
2627
2647
|
}
|
|
2628
2648
|
|
|
2629
|
-
async upsert(filter: Filter, newData
|
|
2649
|
+
async upsert(filter: Filter, newData: AnyObject, params?: UpdateParams, table_rules?: TableRule, localParams?: LocalParams): Promise<any> {
|
|
2630
2650
|
try {
|
|
2631
2651
|
/* Do it within a transaction to ensure consisency */
|
|
2632
2652
|
if(!this.t){
|
|
@@ -2636,12 +2656,12 @@ export class TableHandler extends ViewHandler {
|
|
|
2636
2656
|
}
|
|
2637
2657
|
|
|
2638
2658
|
async function _upsert(tblH: TableHandler){
|
|
2639
|
-
return tblH.find(filter, { select: "", limit: 1 },
|
|
2659
|
+
return tblH.find(filter, { select: "", limit: 1 }, undefined, table_rules, localParams)
|
|
2640
2660
|
.then(exists => {
|
|
2641
2661
|
if(exists && exists.length){
|
|
2642
2662
|
return tblH.update(filter, newData, params, table_rules, localParams);
|
|
2643
2663
|
} else {
|
|
2644
|
-
return tblH.insert({ ...newData, ...filter }, params,
|
|
2664
|
+
return tblH.insert({ ...newData, ...filter }, params, undefined, table_rules, localParams);
|
|
2645
2665
|
}
|
|
2646
2666
|
});
|
|
2647
2667
|
}
|
|
@@ -2652,7 +2672,7 @@ export class TableHandler extends ViewHandler {
|
|
|
2652
2672
|
};
|
|
2653
2673
|
|
|
2654
2674
|
/* External request. Cannot sync from server */
|
|
2655
|
-
async sync(filter: Filter, params: SelectParams, param3_unused, table_rules: TableRule, localParams: LocalParams){
|
|
2675
|
+
async sync(filter: Filter, params: SelectParams, param3_unused: never, table_rules: TableRule, localParams: LocalParams){
|
|
2656
2676
|
if(!localParams) throw "Sync not allowed within the same server code";
|
|
2657
2677
|
const { socket } = localParams;
|
|
2658
2678
|
if(!socket) throw "INTERNAL ERROR: socket missing";
|
|
@@ -2697,7 +2717,7 @@ export class TableHandler extends ViewHandler {
|
|
|
2697
2717
|
});
|
|
2698
2718
|
|
|
2699
2719
|
/* Step 1: parse command and params */
|
|
2700
|
-
return this.find(filter, { select, limit: 0 },
|
|
2720
|
+
return this.find(filter, { select, limit: 0 }, undefined, table_rules, localParams)
|
|
2701
2721
|
.then(async isValid => {
|
|
2702
2722
|
|
|
2703
2723
|
const { filterFields, forcedFilter } = get(table_rules, "select") || {};
|
|
@@ -2708,7 +2728,8 @@ export class TableHandler extends ViewHandler {
|
|
|
2708
2728
|
return pubSubManager.addSync({
|
|
2709
2729
|
table_info: this.tableOrViewInfo,
|
|
2710
2730
|
condition,
|
|
2711
|
-
id_fields, synced_field,
|
|
2731
|
+
id_fields, synced_field,
|
|
2732
|
+
allow_delete,
|
|
2712
2733
|
socket,
|
|
2713
2734
|
table_rules,
|
|
2714
2735
|
filter: { ...filter },
|
|
@@ -2755,18 +2776,18 @@ import { JOIN_TYPES } from "./Prostgles";
|
|
|
2755
2776
|
import { BasicSession } from "./AuthHandler";
|
|
2756
2777
|
|
|
2757
2778
|
export class DboBuilder {
|
|
2758
|
-
tablesOrViews
|
|
2779
|
+
tablesOrViews?: TableSchema[]; //TableSchema TableOrViewInfo
|
|
2759
2780
|
/**
|
|
2760
2781
|
* Used in obtaining column names for error messages
|
|
2761
2782
|
*/
|
|
2762
|
-
constraints
|
|
2783
|
+
constraints?: PGConstraint[];
|
|
2763
2784
|
|
|
2764
2785
|
db: DB;
|
|
2765
2786
|
schema: string = "public";
|
|
2766
2787
|
|
|
2767
2788
|
// dbo: DbHandler | DbHandlerTX;
|
|
2768
2789
|
dbo: DbHandler;
|
|
2769
|
-
_pubSubManager
|
|
2790
|
+
_pubSubManager?: PubSubManager;
|
|
2770
2791
|
|
|
2771
2792
|
getPubSubManager = async () : Promise<PubSubManager> => {
|
|
2772
2793
|
if(!this._pubSubManager){
|
|
@@ -2793,26 +2814,27 @@ export class DboBuilder {
|
|
|
2793
2814
|
console.warn(`subscribe and sync cannot be used because db user is not a superuser `)
|
|
2794
2815
|
}
|
|
2795
2816
|
}
|
|
2796
|
-
|
|
2817
|
+
if(!this._pubSubManager) throw "Could not create this._pubSubManager";
|
|
2797
2818
|
return this._pubSubManager;
|
|
2798
2819
|
}
|
|
2799
2820
|
|
|
2800
|
-
pojoDefinitions
|
|
2801
|
-
dboDefinition
|
|
2821
|
+
pojoDefinitions?: string[];
|
|
2822
|
+
dboDefinition?: string;
|
|
2802
2823
|
|
|
2803
|
-
tsTypesDefinition
|
|
2824
|
+
tsTypesDefinition?: string;
|
|
2804
2825
|
|
|
2805
|
-
joins
|
|
2806
|
-
joinGraph
|
|
2807
|
-
joinPaths: JoinPaths;
|
|
2826
|
+
joins?: Join[];
|
|
2827
|
+
joinGraph?: Graph;
|
|
2828
|
+
joinPaths: JoinPaths = [];
|
|
2808
2829
|
|
|
2809
2830
|
prostgles: Prostgles;
|
|
2810
|
-
publishParser
|
|
2831
|
+
publishParser?: PublishParser;
|
|
2811
2832
|
|
|
2812
|
-
onSchemaChange
|
|
2833
|
+
onSchemaChange?: (event: { command: string; query: string }) => void;
|
|
2813
2834
|
|
|
2814
2835
|
private constructor(prostgles: Prostgles){
|
|
2815
2836
|
this.prostgles = prostgles;
|
|
2837
|
+
if(!this.prostgles.db) throw "db missing"
|
|
2816
2838
|
this.db = this.prostgles.db;
|
|
2817
2839
|
this.schema = this.prostgles.opts.schema || "public";
|
|
2818
2840
|
this.dbo = { } as unknown as DbHandler;
|
|
@@ -2874,10 +2896,10 @@ export class DboBuilder {
|
|
|
2874
2896
|
if(dup){
|
|
2875
2897
|
throw "Duplicate join declaration for table: " + dup.tables[0];
|
|
2876
2898
|
}
|
|
2877
|
-
const tovNames = this.tablesOrViews
|
|
2899
|
+
const tovNames = this.tablesOrViews!.map(t => t.name);
|
|
2878
2900
|
|
|
2879
2901
|
// 2 find incorrect tables
|
|
2880
|
-
const missing =
|
|
2902
|
+
const missing = joins.flatMap(j => j.tables).find(t => !tovNames.includes(t));
|
|
2881
2903
|
if(missing){
|
|
2882
2904
|
throw "Table not found: " + missing;
|
|
2883
2905
|
}
|
|
@@ -2892,9 +2914,9 @@ export class DboBuilder {
|
|
|
2892
2914
|
var t = <string>v[0],
|
|
2893
2915
|
f = <string[]>v[1];
|
|
2894
2916
|
|
|
2895
|
-
let tov = this.tablesOrViews
|
|
2917
|
+
let tov = this.tablesOrViews!.find(_t => _t.name === t);
|
|
2896
2918
|
if(!tov) throw "Table not found: " + t;
|
|
2897
|
-
const m1 = f.filter(k => !tov
|
|
2919
|
+
const m1 = f.filter(k => !tov!.columns.map(c => c.name).includes(k))
|
|
2898
2920
|
if(m1 && m1.length){
|
|
2899
2921
|
throw `Table ${t}(${tov.columns.map(c => c.name).join()}) has no fields named: ${m1.join()}`;
|
|
2900
2922
|
}
|
|
@@ -2919,17 +2941,17 @@ export class DboBuilder {
|
|
|
2919
2941
|
let _t = tables.slice().sort(),
|
|
2920
2942
|
t1 = _t[0],
|
|
2921
2943
|
t2 = _t[1];
|
|
2922
|
-
this.joinGraph[t1] = this.joinGraph[t1] || {};
|
|
2923
|
-
this.joinGraph[t1][t2] = 1;
|
|
2944
|
+
this.joinGraph![t1] = this.joinGraph![t1] || {};
|
|
2945
|
+
this.joinGraph![t1][t2] = 1;
|
|
2924
2946
|
|
|
2925
|
-
this.joinGraph[t2] = this.joinGraph[t2] || {};
|
|
2926
|
-
this.joinGraph[t2][t1] = 1;
|
|
2947
|
+
this.joinGraph![t2] = this.joinGraph![t2] || {};
|
|
2948
|
+
this.joinGraph![t2][t1] = 1;
|
|
2927
2949
|
});
|
|
2928
|
-
const tables =
|
|
2950
|
+
const tables = this.joins.flatMap(t => t.tables);
|
|
2929
2951
|
this.joinPaths = [];
|
|
2930
2952
|
tables.map(t1 => {
|
|
2931
2953
|
tables.map(t2 => {
|
|
2932
|
-
const spath = findShortestPath(this.joinGraph
|
|
2954
|
+
const spath = findShortestPath(this.joinGraph!, t1, t2);
|
|
2933
2955
|
if(spath && spath.distance < Infinity){
|
|
2934
2956
|
|
|
2935
2957
|
const existing1 = this.joinPaths.find(j => j.t1 === t1 && j.t2 === t2)
|
|
@@ -2976,7 +2998,7 @@ export type TxCB = {
|
|
|
2976
2998
|
|
|
2977
2999
|
await this.parseJoins();
|
|
2978
3000
|
|
|
2979
|
-
let joinTableNames = [];
|
|
3001
|
+
let joinTableNames: string[] = [];
|
|
2980
3002
|
|
|
2981
3003
|
let allDataDefs = "";
|
|
2982
3004
|
let i18nDef = "type DeepPartial<T> = { [P in keyof T]?: DeepPartial<T[P]>; }; \n"
|
|
@@ -3004,10 +3026,10 @@ export type TxCB = {
|
|
|
3004
3026
|
const TSTableDataName = snakify(tov.name, true);
|
|
3005
3027
|
const TSTableHandlerName = JSON.stringify(tov.name)
|
|
3006
3028
|
if(tov.is_view){
|
|
3007
|
-
this.dbo[tov.name] = new ViewHandler(this.db, tov, this,
|
|
3029
|
+
this.dbo[tov.name] = new ViewHandler(this.db, tov, this, undefined, undefined, this.joinPaths);
|
|
3008
3030
|
this.dboDefinition += ` ${TSTableHandlerName}: ViewHandler<${TSTableDataName}> \n`;
|
|
3009
3031
|
} else {
|
|
3010
|
-
this.dbo[tov.name] = new TableHandler(this.db, tov, this,
|
|
3032
|
+
this.dbo[tov.name] = new TableHandler(this.db, tov, this, undefined, undefined, this.joinPaths);
|
|
3011
3033
|
this.dboDefinition += ` ${TSTableHandlerName}: TableHandler<${TSTableDataName}> \n`;
|
|
3012
3034
|
}
|
|
3013
3035
|
allDataDefs += `export type ${TSTableDataName} = { \n` +
|
|
@@ -3021,6 +3043,19 @@ export type TxCB = {
|
|
|
3021
3043
|
let table = tov.name;
|
|
3022
3044
|
joinTableNames.push(table);
|
|
3023
3045
|
|
|
3046
|
+
const makeJoin = (
|
|
3047
|
+
isLeft = true,
|
|
3048
|
+
filter: Parameters<JoinMaker<AnyObject>>[0],
|
|
3049
|
+
select: Parameters<JoinMaker<AnyObject>>[1],
|
|
3050
|
+
options: Parameters<JoinMaker<AnyObject>>[2]
|
|
3051
|
+
): ReturnType<JoinMaker<AnyObject>> => {
|
|
3052
|
+
return {
|
|
3053
|
+
[isLeft? "$leftJoin" : "$innerJoin"]: table,
|
|
3054
|
+
filter,
|
|
3055
|
+
select,
|
|
3056
|
+
...options
|
|
3057
|
+
}
|
|
3058
|
+
}
|
|
3024
3059
|
this.dbo.innerJoin = this.dbo.innerJoin || {};
|
|
3025
3060
|
this.dbo.leftJoin = this.dbo.leftJoin || {};
|
|
3026
3061
|
this.dbo.innerJoinOne = this.dbo.innerJoinOne || {};
|
|
@@ -3037,14 +3072,6 @@ export type TxCB = {
|
|
|
3037
3072
|
this.dbo.innerJoinOne[table] = (filter, select, options = {}) => {
|
|
3038
3073
|
return makeJoin(false, filter, select, {...options, limit: 1});
|
|
3039
3074
|
}
|
|
3040
|
-
function makeJoin(isLeft = true, filter, select, options){
|
|
3041
|
-
return {
|
|
3042
|
-
[isLeft? "$leftJoin" : "$innerJoin"]: table,
|
|
3043
|
-
filter,
|
|
3044
|
-
select,
|
|
3045
|
-
...options
|
|
3046
|
-
}
|
|
3047
|
-
}
|
|
3048
3075
|
}
|
|
3049
3076
|
});
|
|
3050
3077
|
i18nDef += " }> \n";
|
|
@@ -3074,17 +3101,17 @@ export type TxCB = {
|
|
|
3074
3101
|
if(!this.dbo.sql){
|
|
3075
3102
|
|
|
3076
3103
|
let needType = true;// this.publishRawSQL && typeof this.publishRawSQL === "function";
|
|
3077
|
-
let DATA_TYPES = !needType? [] : await this.db.any("SELECT oid, typname FROM pg_type");
|
|
3078
|
-
let USER_TABLES = !needType? [] : await this.db.any("SELECT relid, relname FROM pg_catalog.pg_statio_user_tables");
|
|
3104
|
+
let DATA_TYPES: {oid: string, typname: PG_COLUMN_UDT_DATA_TYPE }[] = !needType? [] : await this.db.any("SELECT oid, typname FROM pg_type");
|
|
3105
|
+
let USER_TABLES: { relid: string; relname: string; }[] = !needType? [] : await this.db.any("SELECT relid, relname FROM pg_catalog.pg_statio_user_tables");
|
|
3079
3106
|
|
|
3080
|
-
this.dbo.sql = async (query: string, params: any, options: SQLOptions, localParams?: LocalParams) => {
|
|
3107
|
+
this.dbo.sql = async (query: string, params: any, options: SQLOptions | undefined, localParams?: LocalParams) => {
|
|
3081
3108
|
|
|
3082
|
-
const canRunSQL = async (localParams
|
|
3109
|
+
const canRunSQL = async (localParams?: LocalParams) => {
|
|
3083
3110
|
if(!localParams) return true;
|
|
3084
3111
|
|
|
3085
3112
|
const { socket } = localParams;
|
|
3086
|
-
const publishParams = await this.prostgles.publishParser
|
|
3087
|
-
let res = await this.prostgles.opts.publishRawSQL(publishParams);
|
|
3113
|
+
const publishParams = await this.prostgles.publishParser!.getPublishParams({ socket });
|
|
3114
|
+
let res = await this.prostgles.opts.publishRawSQL?.(publishParams);
|
|
3088
3115
|
return Boolean(res && typeof res === "boolean" || res === "*");
|
|
3089
3116
|
}
|
|
3090
3117
|
|
|
@@ -3095,12 +3122,12 @@ export type TxCB = {
|
|
|
3095
3122
|
|
|
3096
3123
|
if(returnType === "noticeSubscription"){
|
|
3097
3124
|
if(!socket) throw "Only allowed with client socket"
|
|
3098
|
-
return await this.prostgles.dbEventsManager
|
|
3125
|
+
return await this.prostgles.dbEventsManager?.addNotice(socket);
|
|
3099
3126
|
} else if(returnType === "statement"){
|
|
3100
3127
|
try {
|
|
3101
3128
|
return pgp.as.format(query, params);
|
|
3102
3129
|
} catch (err){
|
|
3103
|
-
throw err.toString();
|
|
3130
|
+
throw (err as any).toString();
|
|
3104
3131
|
}
|
|
3105
3132
|
} else if(this.db) {
|
|
3106
3133
|
|
|
@@ -3109,8 +3136,8 @@ export type TxCB = {
|
|
|
3109
3136
|
finalQuery = new PQ({ text: pgp.as.format(query, params), rowMode: "array" });
|
|
3110
3137
|
}
|
|
3111
3138
|
|
|
3112
|
-
let
|
|
3113
|
-
const {
|
|
3139
|
+
let _qres = await this.db.result(finalQuery, params)
|
|
3140
|
+
const { fields, rows, command } = _qres;
|
|
3114
3141
|
|
|
3115
3142
|
/**
|
|
3116
3143
|
* Fallback for watchSchema in case not superuser and cannot add db event listener
|
|
@@ -3132,7 +3159,7 @@ export type TxCB = {
|
|
|
3132
3159
|
|
|
3133
3160
|
if(command === "LISTEN"){
|
|
3134
3161
|
if(!socket) throw "Only allowed with client socket"
|
|
3135
|
-
return await this.prostgles.dbEventsManager
|
|
3162
|
+
return await this.prostgles.dbEventsManager?.addNotify(query, socket);
|
|
3136
3163
|
|
|
3137
3164
|
} else if(returnType === "rows") {
|
|
3138
3165
|
return rows;
|
|
@@ -3147,22 +3174,27 @@ export type TxCB = {
|
|
|
3147
3174
|
return rows.map(r => Object.values(r[0]));
|
|
3148
3175
|
|
|
3149
3176
|
} else {
|
|
3150
|
-
|
|
3151
|
-
|
|
3152
|
-
|
|
3177
|
+
|
|
3178
|
+
let qres: SQLResult = {
|
|
3179
|
+
duration: 0,
|
|
3180
|
+
..._qres,
|
|
3181
|
+
fields: fields?.map(f => {
|
|
3182
|
+
const dataType = DATA_TYPES.find(dt => +dt.oid === +f.dataTypeID)?.typname ?? "text",
|
|
3153
3183
|
tableName = USER_TABLES.find(t => +t.relid === +f.tableID),
|
|
3154
|
-
|
|
3184
|
+
tsDataType = postgresToTsType(dataType);
|
|
3155
3185
|
|
|
3156
3186
|
return {
|
|
3157
3187
|
...f,
|
|
3158
|
-
|
|
3159
|
-
|
|
3188
|
+
tsDataType,
|
|
3189
|
+
dataType,
|
|
3190
|
+
udt_name: dataType,
|
|
3191
|
+
tableName: tableName?.relname
|
|
3160
3192
|
}
|
|
3161
|
-
})
|
|
3162
|
-
}
|
|
3193
|
+
}) ?? []
|
|
3194
|
+
};
|
|
3163
3195
|
return qres;
|
|
3164
3196
|
}
|
|
3165
|
-
|
|
3197
|
+
|
|
3166
3198
|
} else console.error("db missing");
|
|
3167
3199
|
}
|
|
3168
3200
|
} else {
|
|
@@ -3189,7 +3221,7 @@ export type TxCB = {
|
|
|
3189
3221
|
getTX = (cb: TxCB) => {
|
|
3190
3222
|
return this.db.tx((t) => {
|
|
3191
3223
|
let dbTX: TxHandler = {};
|
|
3192
|
-
this.tablesOrViews
|
|
3224
|
+
this.tablesOrViews?.map(tov => {
|
|
3193
3225
|
if(tov.is_view){
|
|
3194
3226
|
|
|
3195
3227
|
dbTX[tov.name] = new ViewHandler(this.db, tov, this, t, dbTX, this.joinPaths);
|
|
@@ -3446,17 +3478,20 @@ function validateObj(obj: object, allowedKeys: string[]): object{
|
|
|
3446
3478
|
}
|
|
3447
3479
|
|
|
3448
3480
|
|
|
3449
|
-
export function isPlainObject(o) {
|
|
3481
|
+
export function isPlainObject(o: any): o is Record<string, any> {
|
|
3450
3482
|
return Object(o) === o && Object.getPrototypeOf(o) === Object.prototype;
|
|
3451
3483
|
}
|
|
3452
|
-
|
|
3484
|
+
export function getKeys<T>(o: T): Array<keyof T>{
|
|
3485
|
+
return Object.keys(o) as any
|
|
3486
|
+
}
|
|
3453
3487
|
export function postgresToTsType(udt_data_type: PG_COLUMN_UDT_DATA_TYPE): keyof typeof TS_PG_Types {
|
|
3454
|
-
return
|
|
3488
|
+
return getKeys(TS_PG_Types).find(k => {
|
|
3489
|
+
// @ts-ignore
|
|
3455
3490
|
return TS_PG_Types[k].includes(udt_data_type) || !TS_PG_Types[k].length;
|
|
3456
3491
|
}) as keyof typeof TS_PG_Types;
|
|
3457
3492
|
}
|
|
3458
3493
|
|
|
3459
|
-
function sqlErrCodeToMsg(code){
|
|
3494
|
+
function sqlErrCodeToMsg(code: string){
|
|
3460
3495
|
const errs = {
|
|
3461
3496
|
"00000": "successful_completion",
|
|
3462
3497
|
"01000": "warning",
|
|
@@ -3701,6 +3736,7 @@ function sqlErrCodeToMsg(code){
|
|
|
3701
3736
|
},
|
|
3702
3737
|
c2 = {"20000":"case_not_found","21000":"cardinality_violation","22000":"data_exception","22001":"string_data_right_truncation","22002":"null_value_no_indicator_parameter","22003":"numeric_value_out_of_range","22004":"null_value_not_allowed","22005":"error_in_assignment","22007":"invalid_datetime_format","22008":"datetime_field_overflow","22009":"invalid_time_zone_displacement_value","22010":"invalid_indicator_parameter_value","22011":"substring_error","22012":"division_by_zero","22013":"invalid_preceding_or_following_size","22014":"invalid_argument_for_ntile_function","22015":"interval_field_overflow","22016":"invalid_argument_for_nth_value_function","22018":"invalid_character_value_for_cast","22019":"invalid_escape_character","22021":"character_not_in_repertoire","22022":"indicator_overflow","22023":"invalid_parameter_value","22024":"unterminated_c_string","22025":"invalid_escape_sequence","22026":"string_data_length_mismatch","22027":"trim_error","22030":"duplicate_json_object_key_value","22031":"invalid_argument_for_sql_json_datetime_function","22032":"invalid_json_text","22033":"invalid_sql_json_subscript","22034":"more_than_one_sql_json_item","22035":"no_sql_json_item","22036":"non_numeric_sql_json_item","22037":"non_unique_keys_in_a_json_object","22038":"singleton_sql_json_item_required","22039":"sql_json_array_not_found","23000":"integrity_constraint_violation","23001":"restrict_violation","23502":"not_null_violation","23503":"foreign_key_violation","23505":"unique_violation","23514":"check_violation","24000":"invalid_cursor_state","25000":"invalid_transaction_state","25001":"active_sql_transaction","25002":"branch_transaction_already_active","25003":"inappropriate_access_mode_for_branch_transaction","25004":"inappropriate_isolation_level_for_branch_transaction","25005":"no_active_sql_transaction_for_branch_transaction","25006":"read_only_sql_transaction","25007":"schema_and_data_statement_mixing_not_supported","25008":"held_cursor_requires_same_isolation_level","26000":"invalid_sql_statement_name","27000":"triggered_data_change_violation","28000":"invalid_authorization_specification","34000":"invalid_cursor_name","38000":"external_routine_exception","38001":"containing_sql_not_permitted","38002":"modifying_sql_data_not_permitted","38003":"prohibited_sql_statement_attempted","38004":"reading_sql_data_not_permitted","39000":"external_routine_invocation_exception","39001":"invalid_sqlstate_returned","39004":"null_value_not_allowed","40000":"transaction_rollback","40001":"serialization_failure","40002":"transaction_integrity_constraint_violation","40003":"statement_completion_unknown","42000":"syntax_error_or_access_rule_violation","42501":"insufficient_privilege","42601":"syntax_error","42602":"invalid_name","42611":"invalid_column_definition","42622":"name_too_long","42701":"duplicate_column","42702":"ambiguous_column","42703":"undefined_column","42704":"undefined_object","42710":"duplicate_object","42712":"duplicate_alias","42723":"duplicate_function","42725":"ambiguous_function","42803":"grouping_error","42804":"datatype_mismatch","42809":"wrong_object_type","42830":"invalid_foreign_key","42846":"cannot_coerce","42883":"undefined_function","42939":"reserved_name","44000":"with_check_option_violation","53000":"insufficient_resources","53100":"disk_full","53200":"out_of_memory","53300":"too_many_connections","53400":"configuration_limit_exceeded","54000":"program_limit_exceeded","54001":"statement_too_complex","54011":"too_many_columns","54023":"too_many_arguments","55000":"object_not_in_prerequisite_state","55006":"object_in_use","57000":"operator_intervention","57014":"query_canceled","58000":"system_error","58030":"io_error","72000":"snapshot_too_old","00000":"successful_completion","01000":"warning","0100C":"dynamic_result_sets_returned","01008":"implicit_zero_bit_padding","01003":"null_value_eliminated_in_set_function","01007":"privilege_not_granted","01006":"privilege_not_revoked","01004":"string_data_right_truncation","01P01":"deprecated_feature","02000":"no_data","02001":"no_additional_dynamic_result_sets_returned","03000":"sql_statement_not_yet_complete","08000":"connection_exception","08003":"connection_does_not_exist","08006":"connection_failure","08001":"sqlclient_unable_to_establish_sqlconnection","08004":"sqlserver_rejected_establishment_of_sqlconnection","08007":"transaction_resolution_unknown","08P01":"protocol_violation","09000":"triggered_action_exception","0A000":"feature_not_supported","0B000":"invalid_transaction_initiation","0F000":"locator_exception","0F001":"invalid_locator_specification","0L000":"invalid_grantor","0LP01":"invalid_grant_operation","0P000":"invalid_role_specification","0Z000":"diagnostics_exception","0Z002":"stacked_diagnostics_accessed_without_active_handler","2202E":"array_subscript_error","2200B":"escape_character_conflict","2201E":"invalid_argument_for_logarithm","2201F":"invalid_argument_for_power_function","2201G":"invalid_argument_for_width_bucket_function","2200D":"invalid_escape_octet","22P06":"nonstandard_use_of_escape_character","2201B":"invalid_regular_expression","2201W":"invalid_row_count_in_limit_clause","2201X":"invalid_row_count_in_result_offset_clause","2202H":"invalid_tablesample_argument","2202G":"invalid_tablesample_repeat","2200C":"invalid_use_of_escape_character","2200G":"most_specific_type_mismatch","2200H":"sequence_generator_limit_exceeded","2200F":"zero_length_character_string","22P01":"floating_point_exception","22P02":"invalid_text_representation","22P03":"invalid_binary_representation","22P04":"bad_copy_file_format","22P05":"untranslatable_character","2200L":"not_an_xml_document","2200M":"invalid_xml_document","2200N":"invalid_xml_content","2200S":"invalid_xml_comment","2200T":"invalid_xml_processing_instruction","2203A":"sql_json_member_not_found","2203B":"sql_json_number_not_found","2203C":"sql_json_object_not_found","2203D":"too_many_json_array_elements","2203E":"too_many_json_object_members","2203F":"sql_json_scalar_required","23P01":"exclusion_violation","25P01":"no_active_sql_transaction","25P02":"in_failed_sql_transaction","25P03":"idle_in_transaction_session_timeout","28P01":"invalid_password","2B000":"dependent_privilege_descriptors_still_exist","2BP01":"dependent_objects_still_exist","2D000":"invalid_transaction_termination","2F000":"sql_routine_exception","2F005":"function_executed_no_return_statement","2F002":"modifying_sql_data_not_permitted","2F003":"prohibited_sql_statement_attempted","2F004":"reading_sql_data_not_permitted","39P01":"trigger_protocol_violated","39P02":"srf_protocol_violated","39P03":"event_trigger_protocol_violated","3B000":"savepoint_exception","3B001":"invalid_savepoint_specification","3D000":"invalid_catalog_name","3F000":"invalid_schema_name","40P01":"deadlock_detected","42P20":"windowing_error","42P19":"invalid_recursion","42P18":"indeterminate_datatype","42P21":"collation_mismatch","42P22":"indeterminate_collation","428C9":"generated_always","42P01":"undefined_table","42P02":"undefined_parameter","42P03":"duplicate_cursor","42P04":"duplicate_database","42P05":"duplicate_prepared_statement","42P06":"duplicate_schema","42P07":"duplicate_table","42P08":"ambiguous_parameter","42P09":"ambiguous_alias","42P10":"invalid_column_reference","42P11":"invalid_cursor_definition","42P12":"invalid_database_definition","42P13":"invalid_function_definition","42P14":"invalid_prepared_statement_definition","42P15":"invalid_schema_definition","42P16":"invalid_table_definition","42P17":"invalid_object_definition","55P02":"cant_change_runtime_param","55P03":"lock_not_available","55P04":"unsafe_new_enum_value_usage","57P01":"admin_shutdown","57P02":"crash_shutdown","57P03":"cannot_connect_now","57P04":"database_dropped","58P01":"undefined_file","58P02":"duplicate_file","F0000":"config_file_error","F0001":"lock_file_exists","HV000":"fdw_error","HV005":"fdw_column_name_not_found","HV002":"fdw_dynamic_parameter_value_needed","HV010":"fdw_function_sequence_error","HV021":"fdw_inconsistent_descriptor_information","HV024":"fdw_invalid_attribute_value","HV007":"fdw_invalid_column_name","HV008":"fdw_invalid_column_number","HV004":"fdw_invalid_data_type","HV006":"fdw_invalid_data_type_descriptors","HV091":"fdw_invalid_descriptor_field_identifier","HV00B":"fdw_invalid_handle","HV00C":"fdw_invalid_option_index","HV00D":"fdw_invalid_option_name","HV090":"fdw_invalid_string_length_or_buffer_length","HV00A":"fdw_invalid_string_format","HV009":"fdw_invalid_use_of_null_pointer","HV014":"fdw_too_many_handles","HV001":"fdw_out_of_memory","HV00P":"fdw_no_schemas","HV00J":"fdw_option_name_not_found","HV00K":"fdw_reply_handle","HV00Q":"fdw_schema_not_found","HV00R":"fdw_table_not_found","HV00L":"fdw_unable_to_create_execution","HV00M":"fdw_unable_to_create_reply","HV00N":"fdw_unable_to_establish_connection","P0000":"plpgsql_error","P0001":"raise_exception","P0002":"no_data_found","P0003":"too_many_rows","P0004":"assert_failure","XX000":"internal_error","XX001":"data_corrupted","XX002":"index_corrupted"}
|
|
3703
3738
|
|
|
3739
|
+
//@ts-ignore
|
|
3704
3740
|
return c2[code] || errs[code] || code;
|
|
3705
3741
|
|
|
3706
3742
|
/*
|