prostgles-server 3.0.78 → 3.0.79

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (75) hide show
  1. package/dist/DboBuilder/QueryBuilder/Functions.d.ts.map +1 -1
  2. package/dist/DboBuilder/QueryBuilder/Functions.js +18 -0
  3. package/dist/DboBuilder/QueryBuilder/Functions.js.map +1 -1
  4. package/dist/DboBuilder/TableHandler.d.ts.map +1 -1
  5. package/dist/DboBuilder/TableHandler.js +1 -1
  6. package/dist/DboBuilder/TableHandler.js.map +1 -1
  7. package/dist/DboBuilder/ViewHandler.d.ts +6 -12
  8. package/dist/DboBuilder/ViewHandler.d.ts.map +1 -1
  9. package/dist/DboBuilder/ViewHandler.js +5 -207
  10. package/dist/DboBuilder/ViewHandler.js.map +1 -1
  11. package/dist/DboBuilder/delete.d.ts.map +1 -1
  12. package/dist/DboBuilder/delete.js +1 -1
  13. package/dist/DboBuilder/delete.js.map +1 -1
  14. package/dist/DboBuilder/getCondition.d.ts +19 -0
  15. package/dist/DboBuilder/getCondition.d.ts.map +1 -0
  16. package/dist/DboBuilder/getCondition.js +236 -0
  17. package/dist/DboBuilder/getCondition.js.map +1 -0
  18. package/dist/DboBuilder/insert.d.ts.map +1 -1
  19. package/dist/DboBuilder/insert.js +2 -2
  20. package/dist/DboBuilder/insert.js.map +1 -1
  21. package/dist/DboBuilder/subscribe.d.ts.map +1 -1
  22. package/dist/DboBuilder/subscribe.js +1 -1
  23. package/dist/DboBuilder/subscribe.js.map +1 -1
  24. package/dist/DboBuilder/update.d.ts.map +1 -1
  25. package/dist/DboBuilder/update.js +2 -2
  26. package/dist/DboBuilder/update.js.map +1 -1
  27. package/dist/DboBuilder.d.ts +2 -4
  28. package/dist/DboBuilder.d.ts.map +1 -1
  29. package/dist/DboBuilder.js +3 -4
  30. package/dist/DboBuilder.js.map +1 -1
  31. package/dist/Filtering.d.ts.map +1 -1
  32. package/dist/Filtering.js +94 -73
  33. package/dist/Filtering.js.map +1 -1
  34. package/dist/PubSubManager/initPubSubManager.d.ts.map +1 -1
  35. package/dist/PubSubManager/initPubSubManager.js +10 -2
  36. package/dist/PubSubManager/initPubSubManager.js.map +1 -1
  37. package/lib/DboBuilder/QueryBuilder/Functions.d.ts.map +1 -1
  38. package/lib/DboBuilder/QueryBuilder/Functions.js +18 -0
  39. package/lib/DboBuilder/QueryBuilder/Functions.ts +23 -0
  40. package/lib/DboBuilder/TableHandler.d.ts.map +1 -1
  41. package/lib/DboBuilder/TableHandler.js +1 -1
  42. package/lib/DboBuilder/TableHandler.ts +2 -2
  43. package/lib/DboBuilder/ViewHandler.d.ts +1 -14
  44. package/lib/DboBuilder/ViewHandler.d.ts.map +1 -1
  45. package/lib/DboBuilder/ViewHandler.js +5 -207
  46. package/lib/DboBuilder/ViewHandler.ts +9 -248
  47. package/lib/DboBuilder/delete.d.ts.map +1 -1
  48. package/lib/DboBuilder/delete.js +1 -1
  49. package/lib/DboBuilder/delete.ts +2 -2
  50. package/lib/DboBuilder/getCondition.d.ts +19 -0
  51. package/lib/DboBuilder/getCondition.d.ts.map +1 -0
  52. package/lib/DboBuilder/getCondition.js +235 -0
  53. package/lib/DboBuilder/getCondition.ts +279 -0
  54. package/lib/DboBuilder/insert.d.ts.map +1 -1
  55. package/lib/DboBuilder/insert.js +2 -2
  56. package/lib/DboBuilder/insert.ts +3 -3
  57. package/lib/DboBuilder/subscribe.d.ts.map +1 -1
  58. package/lib/DboBuilder/subscribe.js +1 -1
  59. package/lib/DboBuilder/subscribe.ts +2 -2
  60. package/lib/DboBuilder/update.d.ts.map +1 -1
  61. package/lib/DboBuilder/update.js +2 -2
  62. package/lib/DboBuilder/update.ts +3 -3
  63. package/lib/DboBuilder.d.ts +2 -4
  64. package/lib/DboBuilder.d.ts.map +1 -1
  65. package/lib/DboBuilder.js +3 -4
  66. package/lib/DboBuilder.ts +5 -13
  67. package/lib/Filtering.d.ts.map +1 -1
  68. package/lib/Filtering.js +94 -73
  69. package/lib/Filtering.ts +104 -79
  70. package/lib/PubSubManager/initPubSubManager.d.ts.map +1 -1
  71. package/lib/PubSubManager/initPubSubManager.js +10 -2
  72. package/lib/PubSubManager/initPubSubManager.ts +11 -2
  73. package/package.json +4 -4
  74. package/tests/client/PID.txt +1 -1
  75. package/tests/server/package-lock.json +7 -7
@@ -2,16 +2,15 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.ViewHandler = void 0;
4
4
  const makeSelectQuery_1 = require("../DboBuilder/QueryBuilder/makeSelectQuery");
5
+ const getCondition_1 = require("./getCondition");
5
6
  const runSQL_1 = require("../DboBuilder/runSQL");
6
7
  const prostgles_types_1 = require("prostgles-types");
7
8
  const DboBuilder_1 = require("../DboBuilder");
8
9
  const PubSubManager_1 = require("../PubSubManager/PubSubManager");
9
10
  const QueryBuilder_1 = require("./QueryBuilder/QueryBuilder");
10
11
  const Functions_1 = require("./QueryBuilder/Functions");
11
- const Filtering_1 = require("../Filtering");
12
12
  const getColumns_1 = require("./getColumns");
13
13
  const subscribe_1 = require("./subscribe");
14
- const FILTER_FUNCS = Functions_1.FUNCTIONS.filter(f => f.canBeUsedForFilter);
15
14
  class ColSet {
16
15
  opts;
17
16
  constructor(columns, tableName) {
@@ -579,7 +578,7 @@ class ViewHandler {
579
578
  if (["row", "value"].includes(returnType)) {
580
579
  return (this.t || this.db).oneOrNone(_query).then(data => {
581
580
  return (data && returnType === "value") ? Object.values(data)[0] : data;
582
- }).catch(err => (0, DboBuilder_1.makeErr)(err, localParams, this));
581
+ }).catch(err => (0, DboBuilder_1.makeErrorFromPGError)(err, localParams, this));
583
582
  }
584
583
  else {
585
584
  return (this.t || this.db).any(_query).then(data => {
@@ -587,7 +586,7 @@ class ViewHandler {
587
586
  return data.map(d => Object.values(d)[0]);
588
587
  }
589
588
  return data;
590
- }).catch(err => (0, DboBuilder_1.makeErr)(err, localParams, this));
589
+ }).catch(err => (0, DboBuilder_1.makeErrorFromPGError)(err, localParams, this));
591
590
  }
592
591
  }
593
592
  catch (e) {
@@ -780,7 +779,7 @@ class ViewHandler {
780
779
  throw { stack: ["prepareExistCondition()"], message: `Invalid or dissallowed table: ${t}` };
781
780
  });
782
781
  /* Nested $exists not allowed */
783
- if (f2 && Object.keys(f2).find(fk => DboBuilder_1.EXISTS_KEYS.includes(fk))) {
782
+ if (f2 && Object.keys(f2).find(fk => prostgles_types_1.EXISTS_KEYS.includes(fk))) {
784
783
  throw { stack: ["prepareExistCondition()"], message: "Nested exists dissallowed" };
785
784
  }
786
785
  const makeTableChain = (finalFilter) => {
@@ -859,208 +858,7 @@ class ViewHandler {
859
858
  }
860
859
  return res;
861
860
  }
862
- /**
863
- * parses a single filter
864
- * @example
865
- * { fff: 2 } => "fff" = 2
866
- * { fff: { $ilike: 'abc' } } => "fff" ilike 'abc'
867
- */
868
- async getCondition(params) {
869
- const { filter, select, allowed_colnames, tableAlias, localParams, tableRules } = params;
870
- let data = { ...filter };
871
- /* Exists join filter */
872
- const ERR = "Invalid exists filter. \nExpecting somethibng like: \n | { $exists: { tableName.tableName2: Filter } } \n | { $exists: { \"**.tableName3\": Filter } }\n | { path: string[]; filter: AnyObject }";
873
- const SP_WILDCARD = "**";
874
- let existsKeys = Object.keys(data)
875
- .filter(k => DboBuilder_1.EXISTS_KEYS.includes(k) && Object.keys(data[k] || {}).length)
876
- .map(key => {
877
- const isJoined = DboBuilder_1.EXISTS_KEYS.slice(-2).includes(key);
878
- const filterValue = data[key];
879
- /**
880
- * type ExistsJoined =
881
- * | { "table1.table2": { column: filterValue } }
882
- * | { path: string[]; filter: AnyObject }
883
- */
884
- const dataKeys = Object.keys(filterValue);
885
- const isDetailed = dataKeys.length === 2 && dataKeys.every(key => ["path", "filter"].includes(key));
886
- const firstKey = dataKeys[0];
887
- /**
888
- * Prevent some errors with table names that contain "."
889
- */
890
- const firstKeyIsATable = !!this.dboBuilder.dbo[firstKey];
891
- let tables = isDetailed ? filterValue.path : (firstKeyIsATable ? [firstKey] : firstKey.split("."));
892
- let f2 = isDetailed ? filterValue.filter : filterValue[firstKey];
893
- let shortestJoin = false;
894
- if (!isJoined) {
895
- if (tables.length !== 1)
896
- throw "Expecting single table in exists filter. Example: { $exists: { tableName: Filter } }";
897
- }
898
- else {
899
- /* First part can be the ** param meaning shortest join. Will be overriden by anything in tableConfig */
900
- if (!tables.length) {
901
- throw ERR + "\nBut got: " + filterValue;
902
- }
903
- if (tables[0] === SP_WILDCARD) {
904
- tables = tables.slice(1);
905
- shortestJoin = true;
906
- }
907
- }
908
- return {
909
- key,
910
- existType: key,
911
- isJoined,
912
- shortestJoin,
913
- f2,
914
- tables
915
- };
916
- });
917
- /* Exists with exact path */
918
- // Object.keys(data).map(k => {
919
- // let isthis = isPlainObject(data[k]) && !this.column_names.includes(k) && !k.split(".").find(kt => !this.dboBuilder.dbo[kt]);
920
- // if(isthis) {
921
- // existsKeys.push({
922
- // key: k,
923
- // notJoined: false,
924
- // exactPaths: k.split(".")
925
- // });
926
- // }
927
- // });
928
- let funcConds = [];
929
- const funcFilterkeys = FILTER_FUNCS.filter(f => {
930
- return f.name in data;
931
- });
932
- funcFilterkeys.map(f => {
933
- const funcArgs = data[f.name];
934
- if (!Array.isArray(funcArgs))
935
- throw `A function filter must contain an array. E.g: { $funcFilterName: ["col1"] } \n but got: ${JSON.stringify((0, prostgles_types_1.pickKeys)(data, [f.name]))} `;
936
- const fields = this.parseFieldFilter(f.getFields(funcArgs), true, allowed_colnames);
937
- const dissallowedCols = fields.filter(fname => !allowed_colnames.includes(fname));
938
- if (dissallowedCols.length) {
939
- throw `Invalid/disallowed columns found in function filter: ${dissallowedCols}`;
940
- }
941
- funcConds.push(f.getQuery({ args: funcArgs, allColumns: this.columns, allowedFields: allowed_colnames, tableAlias }));
942
- });
943
- let existsCond = "";
944
- if (existsKeys.length) {
945
- existsCond = (await Promise.all(existsKeys.map(async (k) => await this.prepareExistCondition(k, localParams)))).join(" AND ");
946
- }
947
- /* Computed field queries */
948
- const p = this.getValidatedRules(tableRules, localParams);
949
- const computedFields = p.allColumns.filter(c => c.type === "computed");
950
- let computedColConditions = [];
951
- Object.keys(data || {}).map(key => {
952
- const compCol = computedFields.find(cf => cf.name === key);
953
- if (compCol) {
954
- computedColConditions.push(compCol.getQuery({
955
- tableAlias,
956
- allowedFields: p.select.fields,
957
- allColumns: this.columns,
958
- /* CTID not available in AFTER trigger */
959
- // ctidField: this.is_view? undefined : "ctid"
960
- ctidField: undefined,
961
- }) + ` = ${DboBuilder_1.pgp.as.format("$1", [data[key]])}`);
962
- delete data[key];
963
- }
964
- });
965
- let allowedSelect = [];
966
- /* Select aliases take precedence over col names. This is to ensure filters work correctly and even on computed cols*/
967
- if (select) {
968
- /* Allow filtering by selected fields/funcs */
969
- allowedSelect = select.filter(s => {
970
- /* */
971
- if (["function", "computed", "column"].includes(s.type)) {
972
- if (s.type !== "column" || allowed_colnames.includes(s.alias)) {
973
- return true;
974
- }
975
- }
976
- return false;
977
- });
978
- }
979
- /* Add remaining allowed fields */
980
- allowedSelect = allowedSelect.concat(p.allColumns.filter(c => allowed_colnames.includes(c.name) &&
981
- !allowedSelect.find(s => s.alias === c.name)).map(f => ({
982
- type: f.type,
983
- alias: f.name,
984
- getQuery: (tableAlias) => f.getQuery({
985
- tableAlias,
986
- allColumns: this.columns,
987
- allowedFields: allowed_colnames
988
- }),
989
- selected: false,
990
- getFields: () => [f.name],
991
- column_udt_type: f.type === "column" ? this.columns.find(c => c.name === f.name)?.udt_name : undefined
992
- })));
993
- /* Parse complex filters
994
- { $filter: [{ $func: [...] }, "=", value | { $func: [..] }] }
995
- */
996
- const complexFilters = [];
997
- const complexFilterKey = "$filter";
998
- const allowedComparators = [">", "<", "=", "<=", ">=", "<>", "!="];
999
- if (complexFilterKey in data) {
1000
- const getFuncQuery = (funcData) => {
1001
- const { funcName, args } = (0, QueryBuilder_1.parseFunctionObject)(funcData);
1002
- const funcDef = (0, Functions_1.parseFunction)({ func: funcName, args, functions: Functions_1.FUNCTIONS, allowedFields: allowed_colnames });
1003
- return funcDef.getQuery({ args, tableAlias, allColumns: this.columns, allowedFields: allowed_colnames });
1004
- };
1005
- const complexFilter = data[complexFilterKey];
1006
- if (!Array.isArray(complexFilter))
1007
- throw `Invalid $filter. Must contain an array of at least element but got: ${JSON.stringify(complexFilter)} `;
1008
- const leftFilter = complexFilter[0];
1009
- const comparator = complexFilter[1];
1010
- const rightFilterOrValue = complexFilter[2];
1011
- const leftVal = getFuncQuery(leftFilter);
1012
- let result = leftVal;
1013
- if (comparator) {
1014
- if (!allowedComparators.includes(comparator))
1015
- throw `Invalid $filter. comparator ${JSON.stringify(comparator)} is not valid. Expecting one of: ${allowedComparators}`;
1016
- if (!rightFilterOrValue)
1017
- throw "Invalid $filter. Expecting a value or function after the comparator";
1018
- const rightVal = (0, prostgles_types_1.isObject)(rightFilterOrValue) ? getFuncQuery(rightFilterOrValue) : (0, PubSubManager_1.asValue)(rightFilterOrValue);
1019
- if (leftVal === rightVal)
1020
- throw "Invalid $filter. Cannot compare two identical function signatures: " + JSON.stringify(leftFilter);
1021
- result += ` ${comparator} ${rightVal}`;
1022
- }
1023
- complexFilters.push(result);
1024
- }
1025
- /* Parse join filters
1026
- { $joinFilter: { $ST_DWithin: [table.col, foreignTable.col, distance] }
1027
- will make an exists filter
1028
- */
1029
- 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));
1030
- // if(allowed_colnames){
1031
- // const aliasedColumns = (select || []).filter(s =>
1032
- // ["function", "computed", "column"].includes(s.type) && allowed_colnames.includes(s.alias) ||
1033
- // s.getFields().find(f => allowed_colnames.includes(f))
1034
- // ).map(s => s.alias);
1035
- // const validCols = [...allowed_colnames, ...aliasedColumns];
1036
- // }
1037
- const validFieldNames = allowedSelect.map(s => s.alias);
1038
- const invalidColumn = filterKeys
1039
- .find(fName => !validFieldNames.find(c => c === fName ||
1040
- (fName.startsWith(c) && (fName.slice(c.length).includes("->") ||
1041
- fName.slice(c.length).includes(".")))));
1042
- if (invalidColumn) {
1043
- throw `Table: ${this.name} -> disallowed/inexistent columns in filter: ${invalidColumn} \n Expecting one of: ${allowedSelect.map(s => s.type === "column" ? s.getQuery() : s.alias).join(", ")}`;
1044
- }
1045
- /* TODO: Allow filter funcs */
1046
- // const singleFuncs = FUNCTIONS.filter(f => f.singleColArg);
1047
- const f = (0, prostgles_types_1.pickKeys)(data, filterKeys);
1048
- const q = (0, Filtering_1.parseFilterItem)({
1049
- filter: f,
1050
- tableAlias,
1051
- pgp: DboBuilder_1.pgp,
1052
- select: allowedSelect
1053
- });
1054
- let templates = [q].filter(q => q);
1055
- if (existsCond)
1056
- templates.push(existsCond);
1057
- templates = templates.concat(funcConds);
1058
- templates = templates.concat(computedColConditions);
1059
- templates = templates.concat(complexFilters);
1060
- /* sorted to ensure duplicate subscription channels are not created due to different condition order */
1061
- return templates.sort()
1062
- .join(" AND \n");
1063
- }
861
+ getCondition = getCondition_1.getCondition.bind(this);
1064
862
  /* This relates only to SELECT */
1065
863
  prepareSortItems(orderBy, allowed_cols, tableAlias, select) {
1066
864
  const throwErr = () => {
@@ -1,4 +1,5 @@
1
- import { makeSelectQuery } from "../DboBuilder/QueryBuilder/makeSelectQuery"
1
+ import { makeSelectQuery } from "../DboBuilder/QueryBuilder/makeSelectQuery";
2
+ import { getCondition } from "./getCondition";
2
3
 
3
4
  import * as pgPromise from 'pg-promise';
4
5
  import { canRunSQL, runSQL } from "../DboBuilder/runSQL";
@@ -10,12 +11,12 @@ import {
10
11
  TableInfo as TInfo,
11
12
  AnyObject,
12
13
  isObject, isDefined, getKeys,
13
- _PG_geometric, pickKeys, SubscribeParams
14
+ _PG_geometric, pickKeys, SubscribeParams, EXISTS_KEYS, EXISTS_KEY
14
15
  } from "prostgles-types";
15
16
  import { DB, DBHandlerServer, Join } from "../Prostgles";
16
17
  import {
17
- DboBuilder, escapeTSNames, ExistsFilterConfig, EXISTS_KEY, EXISTS_KEYS, Filter, isPlainObject,
18
- JoinInfo, LocalParams, makeErr, parseError, pgp, postgresToTsType, SortItem,
18
+ DboBuilder, escapeTSNames, ExistsFilterConfig,Filter, isPlainObject,
19
+ JoinInfo, LocalParams, makeErrorFromPGError, parseError, pgp, postgresToTsType, SortItem,
19
20
  TableHandlers, TableSchema, ValidatedTableRules
20
21
  } from "../DboBuilder";
21
22
  import { Graph } from "../shortestPath";
@@ -23,8 +24,7 @@ import { TableRule, UpdateRule, ValidateRow } from "../PublishParser";
23
24
  import { asValue, omitKeys } from "../PubSubManager/PubSubManager";
24
25
  import { TableHandler } from "./TableHandler";
25
26
  import { asNameAlias, getNewQuery, parseFunctionObject, SelectItem, SelectItemValidated } from "./QueryBuilder/QueryBuilder";
26
- import { COMPUTED_FIELDS, FieldSpec, FUNCTIONS, parseFunction, } from "./QueryBuilder/Functions";
27
- import { parseFilterItem } from "../Filtering";
27
+ import { COMPUTED_FIELDS, FieldSpec } from "./QueryBuilder/Functions";
28
28
  import { getColumns } from "./getColumns";
29
29
  import { LocalFunc, subscribe } from "./subscribe";
30
30
  export type JoinPaths = {
@@ -34,8 +34,6 @@ export type JoinPaths = {
34
34
  }[];
35
35
 
36
36
 
37
- const FILTER_FUNCS = FUNCTIONS.filter(f => f.canBeUsedForFilter);
38
-
39
37
 
40
38
  class ColSet {
41
39
  opts: {
@@ -684,14 +682,14 @@ export class ViewHandler {
684
682
  if (["row", "value"].includes(returnType!)) {
685
683
  return (this.t || this.db).oneOrNone(_query).then(data => {
686
684
  return (data && returnType === "value") ? Object.values(data)[0] : data;
687
- }).catch(err => makeErr(err, localParams, this));
685
+ }).catch(err => makeErrorFromPGError(err, localParams, this));
688
686
  } else {
689
687
  return (this.t || this.db).any(_query).then(data => {
690
688
  if (returnType === "values") {
691
689
  return data.map(d => Object.values(d)[0]);
692
690
  }
693
691
  return data;
694
- }).catch(err => makeErr(err, localParams, this));
692
+ }).catch(err => makeErrorFromPGError(err, localParams, this));
695
693
  }
696
694
 
697
695
  } catch (e) {
@@ -1027,244 +1025,7 @@ export class ViewHandler {
1027
1025
  return res;
1028
1026
  }
1029
1027
 
1030
- /**
1031
- * parses a single filter
1032
- * @example
1033
- * { fff: 2 } => "fff" = 2
1034
- * { fff: { $ilike: 'abc' } } => "fff" ilike 'abc'
1035
- */
1036
- async getCondition(params: { filter: any, select?: SelectItem[], allowed_colnames: string[], tableAlias?: string, localParams?: LocalParams, tableRules?: TableRule }) {
1037
- const { filter, select, allowed_colnames, tableAlias, localParams, tableRules } = params;
1038
-
1039
-
1040
- let data = { ... (filter as any) } as any;
1041
-
1042
- /* Exists join filter */
1043
- const ERR = "Invalid exists filter. \nExpecting somethibng like: \n | { $exists: { tableName.tableName2: Filter } } \n | { $exists: { \"**.tableName3\": Filter } }\n | { path: string[]; filter: AnyObject }"
1044
- const SP_WILDCARD = "**";
1045
- let existsKeys: ExistsFilterConfig[] = Object.keys(data)
1046
- .filter(k => EXISTS_KEYS.includes(k as EXISTS_KEY) && Object.keys(data[k] || {}).length)
1047
- .map(key => {
1048
-
1049
- const isJoined = EXISTS_KEYS.slice(-2).includes(key as EXISTS_KEY);
1050
-
1051
- const filterValue = data[key];
1052
- /**
1053
- * type ExistsJoined =
1054
- * | { "table1.table2": { column: filterValue } }
1055
- * | { path: string[]; filter: AnyObject }
1056
- */
1057
- const dataKeys = Object.keys(filterValue);
1058
- const isDetailed = dataKeys.length === 2 && dataKeys.every(key => ["path", "filter"].includes(key));
1059
-
1060
- const firstKey = dataKeys[0];
1061
-
1062
- /**
1063
- * Prevent some errors with table names that contain "."
1064
- */
1065
- const firstKeyIsATable = !!this.dboBuilder.dbo[firstKey];
1066
- let tables = isDetailed? filterValue.path : (firstKeyIsATable? [firstKey] : firstKey.split("."));
1067
- let f2 = isDetailed? filterValue.filter : filterValue[firstKey];
1068
- let shortestJoin = false;
1069
-
1070
- if (!isJoined) {
1071
- if (tables.length !== 1) throw "Expecting single table in exists filter. Example: { $exists: { tableName: Filter } }"
1072
- } else {
1073
- /* First part can be the ** param meaning shortest join. Will be overriden by anything in tableConfig */
1074
-
1075
- if (!tables.length) {
1076
- throw ERR + "\nBut got: " + filterValue;
1077
- }
1078
-
1079
- if (tables[0] === SP_WILDCARD) {
1080
- tables = tables.slice(1);
1081
- shortestJoin = true;
1082
- }
1083
- }
1084
-
1085
- return {
1086
- key,
1087
- existType: key as EXISTS_KEY,
1088
- isJoined,
1089
- shortestJoin,
1090
- f2,
1091
- tables
1092
- }
1093
- });
1094
- /* Exists with exact path */
1095
- // Object.keys(data).map(k => {
1096
- // let isthis = isPlainObject(data[k]) && !this.column_names.includes(k) && !k.split(".").find(kt => !this.dboBuilder.dbo[kt]);
1097
- // if(isthis) {
1098
- // existsKeys.push({
1099
- // key: k,
1100
- // notJoined: false,
1101
- // exactPaths: k.split(".")
1102
- // });
1103
- // }
1104
- // });
1105
- let funcConds: string[] = [];
1106
- const funcFilterkeys = FILTER_FUNCS.filter(f => {
1107
- return f.name in data;
1108
- });
1109
- funcFilterkeys.map(f => {
1110
- const funcArgs = data[f.name];
1111
- if (!Array.isArray(funcArgs)) throw `A function filter must contain an array. E.g: { $funcFilterName: ["col1"] } \n but got: ${JSON.stringify(pickKeys(data, [f.name]))} `;
1112
- const fields = this.parseFieldFilter(f.getFields(funcArgs), true, allowed_colnames);
1113
-
1114
- const dissallowedCols = fields.filter(fname => !allowed_colnames.includes(fname))
1115
- if (dissallowedCols.length) {
1116
- throw `Invalid/disallowed columns found in function filter: ${dissallowedCols}`
1117
- }
1118
- funcConds.push(f.getQuery({ args: funcArgs, allColumns: this.columns, allowedFields: allowed_colnames, tableAlias }));
1119
- })
1120
-
1121
-
1122
- let existsCond = "";
1123
- if (existsKeys.length) {
1124
- existsCond = (await Promise.all(existsKeys.map(async k => await this.prepareExistCondition(k, localParams)))).join(" AND ");
1125
- }
1126
-
1127
- /* Computed field queries */
1128
- const p = this.getValidatedRules(tableRules, localParams);
1129
- const computedFields = p.allColumns.filter(c => c.type === "computed");
1130
- let computedColConditions: string[] = [];
1131
- Object.keys(data || {}).map(key => {
1132
- const compCol = computedFields.find(cf => cf.name === key);
1133
- if (compCol) {
1134
- computedColConditions.push(
1135
- compCol.getQuery({
1136
- tableAlias,
1137
- allowedFields: p.select.fields,
1138
- allColumns: this.columns,
1139
-
1140
- /* CTID not available in AFTER trigger */
1141
- // ctidField: this.is_view? undefined : "ctid"
1142
-
1143
- ctidField: undefined,
1144
- }) + ` = ${pgp.as.format("$1", [(data as any)[key]])}`
1145
- );
1146
- delete (data as any)[key];
1147
- }
1148
- });
1149
-
1150
- let allowedSelect: SelectItem[] = [];
1151
- /* Select aliases take precedence over col names. This is to ensure filters work correctly and even on computed cols*/
1152
- if (select) {
1153
- /* Allow filtering by selected fields/funcs */
1154
- allowedSelect = select.filter(s => {
1155
- /* */
1156
- if (["function", "computed", "column"].includes(s.type)) {
1157
- if (s.type !== "column" || allowed_colnames.includes(s.alias)) {
1158
- return true;
1159
- }
1160
- }
1161
- return false;
1162
- })
1163
- }
1164
-
1165
- /* Add remaining allowed fields */
1166
- allowedSelect = allowedSelect.concat(
1167
- p.allColumns.filter(c =>
1168
- allowed_colnames.includes(c.name) &&
1169
- !allowedSelect.find(s => s.alias === c.name)
1170
- ).map(f => ({
1171
- type: f.type,
1172
- alias: f.name,
1173
- getQuery: (tableAlias) => f.getQuery({
1174
- tableAlias,
1175
- allColumns: this.columns,
1176
- allowedFields: allowed_colnames
1177
- }),
1178
- selected: false,
1179
- getFields: () => [f.name],
1180
- column_udt_type: f.type === "column" ? this.columns.find(c => c.name === f.name)?.udt_name : undefined
1181
- }))
1182
- );
1183
-
1184
- /* Parse complex filters
1185
- { $filter: [{ $func: [...] }, "=", value | { $func: [..] }] }
1186
- */
1187
- const complexFilters: string[] = [];
1188
- const complexFilterKey = "$filter";
1189
- const allowedComparators = [">", "<", "=", "<=", ">=", "<>", "!="]
1190
- if (complexFilterKey in data) {
1191
- const getFuncQuery = (funcData: any): string => {
1192
- const { funcName, args } = parseFunctionObject(funcData);
1193
- const funcDef = parseFunction({ func: funcName, args, functions: FUNCTIONS, allowedFields: allowed_colnames });
1194
- return funcDef.getQuery({ args, tableAlias, allColumns: this.columns, allowedFields: allowed_colnames });
1195
- }
1196
-
1197
- const complexFilter = data[complexFilterKey];
1198
- if (!Array.isArray(complexFilter)) throw `Invalid $filter. Must contain an array of at least element but got: ${JSON.stringify(complexFilter)} `
1199
- const leftFilter = complexFilter[0];
1200
- const comparator = complexFilter[1];
1201
- const rightFilterOrValue = complexFilter[2];
1202
- const leftVal = getFuncQuery(leftFilter);
1203
- let result = leftVal;
1204
- if (comparator) {
1205
- if (!allowedComparators.includes(comparator)) throw `Invalid $filter. comparator ${JSON.stringify(comparator)} is not valid. Expecting one of: ${allowedComparators}`
1206
- if (!rightFilterOrValue) throw "Invalid $filter. Expecting a value or function after the comparator";
1207
- const rightVal = isObject(rightFilterOrValue) ? getFuncQuery(rightFilterOrValue) : asValue(rightFilterOrValue);
1208
- if (leftVal === rightVal) throw "Invalid $filter. Cannot compare two identical function signatures: " + JSON.stringify(leftFilter);
1209
- result += ` ${comparator} ${rightVal}`;
1210
- }
1211
- complexFilters.push(result);
1212
- }
1213
-
1214
-
1215
- /* Parse join filters
1216
- { $joinFilter: { $ST_DWithin: [table.col, foreignTable.col, distance] }
1217
- will make an exists filter
1218
- */
1219
-
1220
- 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));
1221
- // if(allowed_colnames){
1222
- // const aliasedColumns = (select || []).filter(s =>
1223
- // ["function", "computed", "column"].includes(s.type) && allowed_colnames.includes(s.alias) ||
1224
- // s.getFields().find(f => allowed_colnames.includes(f))
1225
- // ).map(s => s.alias);
1226
- // const validCols = [...allowed_colnames, ...aliasedColumns];
1227
-
1228
- // }
1229
- const validFieldNames = allowedSelect.map(s => s.alias);
1230
- const invalidColumn = filterKeys
1231
- .find(fName => !validFieldNames.find(c =>
1232
- c === fName ||
1233
- (
1234
- fName.startsWith(c) && (
1235
- fName.slice(c.length).includes("->") ||
1236
- fName.slice(c.length).includes(".")
1237
- )
1238
- )
1239
- ));
1240
-
1241
- if (invalidColumn) {
1242
- throw `Table: ${this.name} -> disallowed/inexistent columns in filter: ${invalidColumn} \n Expecting one of: ${allowedSelect.map(s => s.type === "column" ? s.getQuery() : s.alias).join(", ")}`;
1243
- }
1244
-
1245
- /* TODO: Allow filter funcs */
1246
- // const singleFuncs = FUNCTIONS.filter(f => f.singleColArg);
1247
-
1248
- const f = pickKeys(data, filterKeys);
1249
- const q = parseFilterItem({
1250
- filter: f,
1251
- tableAlias,
1252
- pgp,
1253
- select: allowedSelect
1254
- });
1255
-
1256
- let templates: string[] = [q].filter(q => q);
1257
-
1258
- if (existsCond) templates.push(existsCond);
1259
- templates = templates.concat(funcConds);
1260
- templates = templates.concat(computedColConditions);
1261
- templates = templates.concat(complexFilters);
1262
-
1263
- /* sorted to ensure duplicate subscription channels are not created due to different condition order */
1264
- return templates.sort()
1265
- .join(" AND \n");
1266
-
1267
- }
1028
+ getCondition = getCondition.bind(this);
1268
1029
 
1269
1030
  /* This relates only to SELECT */
1270
1031
  prepareSortItems(orderBy: OrderBy | undefined, allowed_cols: string[], tableAlias: string | undefined, select: SelectItemValidated[]): SortItem[] {
@@ -1 +1 @@
1
- {"version":3,"file":"delete.d.ts","sourceRoot":"","sources":["delete.ts"],"names":[],"mappings":"AACA,OAAO,EAAqB,YAAY,EAAe,MAAM,iBAAiB,CAAC;AAC/E,OAAO,EAAE,MAAM,EAAE,WAAW,EAAuB,MAAM,eAAe,CAAC;AACzE,OAAO,EAAc,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAEzD,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAE9C,wBAAsB,OAAO,CAAC,IAAI,EAAE,YAAY,EAAE,MAAM,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,YAAY,EAAE,aAAa,CAAC,EAAE,SAAS,EAAE,WAAW,CAAC,EAAE,SAAS,EAAE,WAAW,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,GAAG,CAAC,CA6HrL"}
1
+ {"version":3,"file":"delete.d.ts","sourceRoot":"","sources":["delete.ts"],"names":[],"mappings":"AACA,OAAO,EAAqB,YAAY,EAAe,MAAM,iBAAiB,CAAC;AAC/E,OAAO,EAAE,MAAM,EAAE,WAAW,EAAoC,MAAM,eAAe,CAAC;AACtF,OAAO,EAAc,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAEzD,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAE9C,wBAAsB,OAAO,CAAC,IAAI,EAAE,YAAY,EAAE,MAAM,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,YAAY,EAAE,aAAa,CAAC,EAAE,SAAS,EAAE,WAAW,CAAC,EAAE,SAAS,EAAE,WAAW,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,GAAG,CAAC,CA6HrL"}
@@ -112,7 +112,7 @@ async function _delete(filter, params, param3_unused, table_rules, localParams)
112
112
  }
113
113
  }
114
114
  }
115
- return dbHandler[queryType](_query).catch((err) => (0, DboBuilder_1.makeErr)(err, localParams));
115
+ return dbHandler[queryType](_query).catch((err) => (0, DboBuilder_1.makeErrorFromPGError)(err, localParams));
116
116
  }
117
117
  catch (e) {
118
118
  // console.trace(e)
@@ -1,6 +1,6 @@
1
1
  import pgPromise from "pg-promise";
2
2
  import { AnyObject, asName, DeleteParams, FieldFilter } from "prostgles-types";
3
- import { Filter, LocalParams, makeErr, parseError } from "../DboBuilder";
3
+ import { Filter, LocalParams, makeErrorFromPGError, parseError } from "../DboBuilder";
4
4
  import { DeleteRule, TableRule } from "../PublishParser";
5
5
  import { pickKeys } from "../PubSubManager/PubSubManager";
6
6
  import { TableHandler } from "./TableHandler";
@@ -124,7 +124,7 @@ export async function _delete(this: TableHandler, filter?: Filter, params?: Dele
124
124
  }
125
125
  }
126
126
 
127
- return dbHandler[queryType](_query).catch((err: any) => makeErr(err, localParams));
127
+ return dbHandler[queryType](_query).catch((err: any) => makeErrorFromPGError(err, localParams));
128
128
  } catch (e) {
129
129
  // console.trace(e)
130
130
  if (localParams && localParams.testRule) throw e;
@@ -0,0 +1,19 @@
1
+ import { LocalParams } from "../DboBuilder";
2
+ import { TableRule } from "../PublishParser";
3
+ import { SelectItem } from "./QueryBuilder/QueryBuilder";
4
+ import { ViewHandler } from "./ViewHandler";
5
+ /**
6
+ * parses a single filter
7
+ * @example
8
+ * { fff: 2 } => "fff" = 2
9
+ * { fff: { $ilike: 'abc' } } => "fff" ilike 'abc'
10
+ */
11
+ export declare function getCondition(this: ViewHandler, params: {
12
+ filter: any;
13
+ select?: SelectItem[];
14
+ allowed_colnames: string[];
15
+ tableAlias?: string;
16
+ localParams?: LocalParams;
17
+ tableRules?: TableRule;
18
+ }): Promise<string>;
19
+ //# sourceMappingURL=getCondition.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"getCondition.d.ts","sourceRoot":"","sources":["getCondition.ts"],"names":[],"mappings":"AACA,OAAO,EAAsB,WAAW,EAA6B,MAAM,eAAe,CAAC;AAC3F,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAG7C,OAAO,EAAoC,UAAU,EAAE,MAAM,6BAA6B,CAAC;AAC3F,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAM1C;;;;;GAKG;AACH,wBAAsB,YAAY,CAAC,IAAI,EAAE,WAAW,EAAE,MAAM,EAAE;IAAE,MAAM,EAAE,GAAG,CAAC;IAAC,MAAM,CAAC,EAAE,UAAU,EAAE,CAAC;IAAC,gBAAgB,EAAE,MAAM,EAAE,CAAC;IAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAAC,WAAW,CAAC,EAAE,WAAW,CAAC;IAAC,UAAU,CAAC,EAAE,SAAS,CAAA;CAAE,mBAoQvM"}