prostgles-server 4.2.483 → 4.2.485

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 (40) hide show
  1. package/dist/DboBuilder/ViewHandler/ViewHandler.d.ts +1 -0
  2. package/dist/DboBuilder/ViewHandler/ViewHandler.d.ts.map +1 -1
  3. package/dist/DboBuilder/ViewHandler/parseComplexFilter.d.ts.map +1 -1
  4. package/dist/DboBuilder/ViewHandler/parseComplexFilter.js +3 -2
  5. package/dist/DboBuilder/ViewHandler/parseComplexFilter.js.map +1 -1
  6. package/dist/DboBuilder/ViewHandler/prepareWhere.d.ts +1 -0
  7. package/dist/DboBuilder/ViewHandler/prepareWhere.d.ts.map +1 -1
  8. package/dist/DboBuilder/ViewHandler/prepareWhere.js +33 -15
  9. package/dist/DboBuilder/ViewHandler/prepareWhere.js.map +1 -1
  10. package/dist/DboBuilder/getCondition.d.ts +1 -0
  11. package/dist/DboBuilder/getCondition.d.ts.map +1 -1
  12. package/dist/DboBuilder/getCondition.js +10 -8
  13. package/dist/DboBuilder/getCondition.js.map +1 -1
  14. package/dist/DboBuilder/getSubscribeRelatedTables.d.ts.map +1 -1
  15. package/dist/DboBuilder/getSubscribeRelatedTables.js +1 -1
  16. package/dist/DboBuilder/getSubscribeRelatedTables.js.map +1 -1
  17. package/dist/{Filtering.d.ts → Filtering/Filtering.d.ts} +5 -7
  18. package/dist/Filtering/Filtering.d.ts.map +1 -0
  19. package/dist/Filtering/Filtering.js +244 -0
  20. package/dist/Filtering/Filtering.js.map +1 -0
  21. package/dist/Filtering/getFilterItemCondition.d.ts +7 -0
  22. package/dist/Filtering/getFilterItemCondition.d.ts.map +1 -0
  23. package/dist/Filtering/getFilterItemCondition.js +186 -0
  24. package/dist/Filtering/getFilterItemCondition.js.map +1 -0
  25. package/dist/Filtering/parseFilterRightValue.d.ts +8 -0
  26. package/dist/Filtering/parseFilterRightValue.d.ts.map +1 -0
  27. package/dist/Filtering/parseFilterRightValue.js +23 -0
  28. package/dist/Filtering/parseFilterRightValue.js.map +1 -0
  29. package/lib/DboBuilder/ViewHandler/parseComplexFilter.ts +2 -5
  30. package/lib/DboBuilder/ViewHandler/prepareWhere.ts +38 -17
  31. package/lib/DboBuilder/getCondition.ts +15 -13
  32. package/lib/DboBuilder/getSubscribeRelatedTables.ts +3 -1
  33. package/lib/Filtering/Filtering.ts +286 -0
  34. package/lib/Filtering/getFilterItemCondition.ts +205 -0
  35. package/lib/Filtering/parseFilterRightValue.ts +24 -0
  36. package/package.json +1 -1
  37. package/dist/Filtering.d.ts.map +0 -1
  38. package/dist/Filtering.js +0 -418
  39. package/dist/Filtering.js.map +0 -1
  40. package/lib/Filtering.ts +0 -468
@@ -0,0 +1,7 @@
1
+ import type { SelectItemValidated } from "../DboBuilder/QueryBuilder/QueryBuilder";
2
+ export declare const getFilterItemCondition: ({ selItem, leftQ, rightF, }: {
3
+ leftQ: string;
4
+ selItem: SelectItemValidated;
5
+ rightF: unknown;
6
+ }) => string;
7
+ //# sourceMappingURL=getFilterItemCondition.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"getFilterItemCondition.d.ts","sourceRoot":"","sources":["../../lib/Filtering/getFilterItemCondition.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,yCAAyC,CAAC;AAGnF,eAAO,MAAM,sBAAsB,GAAI,6BAIpC;IACD,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,mBAAmB,CAAC;IAC7B,MAAM,EAAE,OAAO,CAAC;CACjB,KAAG,MAsLH,CAAC"}
@@ -0,0 +1,186 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getFilterItemCondition = void 0;
4
+ const prostgles_types_1 = require("prostgles-types");
5
+ const parseFilterRightValue_1 = require("./parseFilterRightValue");
6
+ const Filtering_1 = require("./Filtering");
7
+ const DboBuilderTypes_1 = require("../DboBuilder/DboBuilderTypes");
8
+ const getFilterItemCondition = ({ selItem, leftQ, rightF, }) => {
9
+ const asValue = (v) => DboBuilderTypes_1.pgp.as.format("$1", [v]);
10
+ const parseRightVal = (val, expect) => {
11
+ try {
12
+ return (0, parseFilterRightValue_1.parseFilterRightValue)(val, { selectItem: selItem, expect });
13
+ }
14
+ catch (e) {
15
+ throw new Error(e);
16
+ }
17
+ };
18
+ /* Matching sel item */
19
+ if ((0, prostgles_types_1.isObject)(rightF)) {
20
+ const filterKeys = Object.keys(rightF);
21
+ let filterOperand = filterKeys[0];
22
+ /** JSON cannot be compared so we'll cast it to TEXT */
23
+ if (selItem.column_udt_type === "json" || (0, prostgles_types_1.includes)(prostgles_types_1.TextFilterKeys, filterOperand)) {
24
+ leftQ += "::TEXT ";
25
+ }
26
+ /** It's an object key which means it's an equality comparison against a json object */
27
+ if (selItem.column_udt_type?.startsWith("json") && !(0, prostgles_types_1.includes)(Filtering_1.FILTER_OPERANDS, filterOperand)) {
28
+ return leftQ + " = " + parseRightVal(rightF);
29
+ }
30
+ let filterValue = rightF[filterOperand];
31
+ const ALLOWED_FUNCS = [...prostgles_types_1.GeomFilter_Funcs, ...prostgles_types_1.TextFilter_FullTextSearchFilterKeys];
32
+ let funcName;
33
+ let funcArgs;
34
+ if (selItem.column_udt_type === "interval" &&
35
+ (0, prostgles_types_1.isObject)(rightF) &&
36
+ Object.values(rightF).every((v) => Number.isFinite(v))) {
37
+ filterOperand = "=";
38
+ filterValue = Object.entries(rightF)
39
+ .map(([k, v]) => `${v}${k}`)
40
+ .join(" ");
41
+ }
42
+ else if ((filterKeys.length !== 1 || !(0, prostgles_types_1.isDefined)(filterOperand)) &&
43
+ selItem.column_udt_type !== "jsonb") {
44
+ throw new Error("Bad filter. Expecting one key only");
45
+ }
46
+ else if ((0, prostgles_types_1.isObject)(filterValue) && !(filterValue instanceof Date)) {
47
+ /**
48
+ * Filter notation
49
+ * geom && st_makeenvelope(funcArgs)
50
+ */
51
+ const filterValueKeys = Object.keys(filterValue);
52
+ funcName = filterValueKeys[0];
53
+ if ((0, prostgles_types_1.includes)(ALLOWED_FUNCS, funcName)) {
54
+ funcArgs = filterValue[funcName];
55
+ }
56
+ else {
57
+ funcName = undefined;
58
+ }
59
+ }
60
+ /** st_makeenvelope */
61
+ if ((0, prostgles_types_1.includes)(prostgles_types_1.GeomFilterKeys, filterOperand) &&
62
+ funcName &&
63
+ (0, prostgles_types_1.includes)(prostgles_types_1.GeomFilter_Funcs, funcName)) {
64
+ /**
65
+ * If leftQ is geography then:
66
+ * - err can happen: 'Antipodal (180 degrees long) edge detected!'
67
+ * - inacurrate results at large envelopes due to the curvature of the earth
68
+ * https://gis.stackexchange.com/questions/78816/maximum-size-on-the-bounding-box-with-st-makeenvelope-and-and-geography-colum
69
+ */
70
+ if (funcName.toLowerCase() === "st_makeenvelope") {
71
+ leftQ += "::geometry";
72
+ }
73
+ return `${leftQ} ${filterOperand} ${funcName}${parseRightVal(funcArgs, "csv")}`;
74
+ }
75
+ else if (["=", "$eq"].includes(filterOperand) && !funcName) {
76
+ if (filterValue === null)
77
+ return leftQ + " IS NULL ";
78
+ return leftQ + " = " + parseRightVal(filterValue);
79
+ }
80
+ else if (["<>", "$ne"].includes(filterOperand)) {
81
+ if (filterValue === null)
82
+ return leftQ + " IS NOT NULL ";
83
+ return leftQ + " <> " + parseRightVal(filterValue);
84
+ }
85
+ else if ([">", "$gt"].includes(filterOperand)) {
86
+ return leftQ + " > " + parseRightVal(filterValue);
87
+ }
88
+ else if (["<", "$lt"].includes(filterOperand)) {
89
+ return leftQ + " < " + parseRightVal(filterValue);
90
+ }
91
+ else if ([">=", "$gte"].includes(filterOperand)) {
92
+ return leftQ + " >= " + parseRightVal(filterValue);
93
+ }
94
+ else if (["<=", "$lte"].includes(filterOperand)) {
95
+ return leftQ + " <= " + parseRightVal(filterValue);
96
+ }
97
+ else if (["$in", "$nin"].includes(filterOperand)) {
98
+ const isIn = filterOperand === "$in";
99
+ if (filterValue !== null && !Array.isArray(filterValue)) {
100
+ throw new Error("In filter expects an array");
101
+ }
102
+ if (!filterValue?.length) {
103
+ return isIn ? " FALSE " : " TRUE ";
104
+ }
105
+ const nonNullFilterValues = filterValue.filter((v) => v !== null);
106
+ const conditions = [];
107
+ if (nonNullFilterValues.length) {
108
+ conditions.push(leftQ + (isIn ? " IN " : " NOT IN ") + parseRightVal(nonNullFilterValues, "csv"));
109
+ }
110
+ if (filterValue.includes(null)) {
111
+ const comparator = isIn ? " IS NULL " : " IS NOT NULL ";
112
+ conditions.push(` ${leftQ} ${comparator} `);
113
+ }
114
+ const joinedConditions = conditions.join(isIn ? " OR " : " AND ");
115
+ return conditions.length > 1 ? `(${joinedConditions})` : joinedConditions;
116
+ }
117
+ else if (["$between"].includes(filterOperand)) {
118
+ if (!Array.isArray(filterValue) || filterValue.length !== 2) {
119
+ throw new Error("Between filter expects an array of two values");
120
+ }
121
+ return leftQ + " BETWEEN " + asValue(filterValue[0]) + " AND " + asValue(filterValue[1]);
122
+ }
123
+ else if (["$ilike"].includes(filterOperand)) {
124
+ return leftQ + " ILIKE " + asValue(filterValue);
125
+ }
126
+ else if (["$like"].includes(filterOperand)) {
127
+ return leftQ + " LIKE " + asValue(filterValue);
128
+ }
129
+ else if (["$nilike"].includes(filterOperand)) {
130
+ return leftQ + " NOT ILIKE " + asValue(filterValue);
131
+ }
132
+ else if (["$nlike"].includes(filterOperand)) {
133
+ return leftQ + " NOT LIKE " + asValue(filterValue);
134
+ }
135
+ else if (filterOperand === "$isDistinctFrom" || filterOperand === "$isNotDistinctFrom") {
136
+ const operator = Filtering_1.FILTER_OPERAND_TO_SQL_OPERAND[filterOperand];
137
+ return leftQ + ` ${operator} ` + asValue(filterValue);
138
+ /* MAYBE TEXT OR MAYBE ARRAY */
139
+ }
140
+ else if (["@>", "<@", "$contains", "$containedBy", "$overlaps", "&&", "@@"].includes(filterOperand)) {
141
+ const operand = filterOperand === "@@" ? "@@"
142
+ : ["@>", "$contains"].includes(filterOperand) ? "@>"
143
+ : ["&&", "$overlaps"].includes(filterOperand) ? "&&"
144
+ : "<@";
145
+ if (operand === "<@" || operand === "@>") {
146
+ if (selItem.column_udt_type === "jsonb") {
147
+ const filterValueAsString = typeof filterValue === "string" ? filterValue : JSON.stringify(filterValue);
148
+ return leftQ + operand + parseRightVal(filterValueAsString);
149
+ }
150
+ }
151
+ /* Array for sure */
152
+ if (Array.isArray(filterValue)) {
153
+ return leftQ + operand + parseRightVal(filterValue, "array");
154
+ /* FTSQuery */
155
+ }
156
+ else if (["@@"].includes(filterOperand) &&
157
+ (0, prostgles_types_1.includes)(prostgles_types_1.TextFilter_FullTextSearchFilterKeys, funcName)) {
158
+ let lq = `to_tsvector(${leftQ}::text)`;
159
+ if (selItem.columnPGDataType === "tsvector")
160
+ lq = leftQ;
161
+ const res = `${lq} ${operand} ` + `${funcName}${parseRightVal(funcArgs, "csv")}`;
162
+ return res;
163
+ }
164
+ else {
165
+ throw new Error("Unrecognised filter operand: " + filterOperand + " ");
166
+ }
167
+ }
168
+ else {
169
+ throw new Error("Unrecognised filter operand: " + filterOperand + " ");
170
+ }
171
+ }
172
+ /* Is an equal filter */
173
+ if (rightF === null) {
174
+ return leftQ + " IS NULL ";
175
+ }
176
+ /**
177
+ * Ensure that when comparing an array to a json column, the array is cast to json
178
+ */
179
+ let valueStr = asValue(rightF);
180
+ if (selItem.column_udt_type?.startsWith("json") && Array.isArray(rightF)) {
181
+ valueStr = DboBuilderTypes_1.pgp.as.format(`$1::jsonb`, [JSON.stringify(rightF)]);
182
+ }
183
+ return `${leftQ} = ${valueStr}`;
184
+ };
185
+ exports.getFilterItemCondition = getFilterItemCondition;
186
+ //# sourceMappingURL=getFilterItemCondition.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"getFilterItemCondition.js","sourceRoot":"","sources":["../../lib/Filtering/getFilterItemCondition.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ import { type SelectItemValidated } from "../DboBuilder/QueryBuilder/QueryBuilder";
2
+ type ParseRightValOpts = {
3
+ expect?: "csv" | "array" | "json" | "jsonb";
4
+ selectItem: SelectItemValidated | undefined;
5
+ };
6
+ export declare const parseFilterRightValue: (val: any, { expect, selectItem }: ParseRightValOpts) => string;
7
+ export {};
8
+ //# sourceMappingURL=parseFilterRightValue.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parseFilterRightValue.d.ts","sourceRoot":"","sources":["../../lib/Filtering/parseFilterRightValue.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,mBAAmB,EAAE,MAAM,yCAAyC,CAAC;AAEnF,KAAK,iBAAiB,GAAG;IACvB,MAAM,CAAC,EAAE,KAAK,GAAG,OAAO,GAAG,MAAM,GAAG,OAAO,CAAC;IAC5C,UAAU,EAAE,mBAAmB,GAAG,SAAS,CAAC;CAC7C,CAAC;AACF,eAAO,MAAM,qBAAqB,GAAI,KAAK,GAAG,EAAE,wBAAwB,iBAAiB,WAgBxF,CAAC"}
@@ -0,0 +1,23 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.parseFilterRightValue = void 0;
4
+ const DboBuilderTypes_1 = require("../DboBuilder/DboBuilderTypes");
5
+ const parseFilterRightValue = (val, { expect, selectItem }) => {
6
+ const asValue = (v) => DboBuilderTypes_1.pgp.as.format("$1", [v]);
7
+ const checkIfArr = () => {
8
+ if (!Array.isArray(val)) {
9
+ throw "This type of filter/column expects an Array of items";
10
+ }
11
+ };
12
+ if (expect === "csv" || expect?.startsWith("json")) {
13
+ checkIfArr();
14
+ return DboBuilderTypes_1.pgp.as.format(`($1:${expect})`, [val]);
15
+ }
16
+ else if (expect === "array" || selectItem?.columnPGDataType === "ARRAY") {
17
+ checkIfArr();
18
+ return DboBuilderTypes_1.pgp.as.format(" ARRAY[$1:csv]", [val]);
19
+ }
20
+ return asValue(val);
21
+ };
22
+ exports.parseFilterRightValue = parseFilterRightValue;
23
+ //# sourceMappingURL=parseFilterRightValue.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parseFilterRightValue.js","sourceRoot":"","sources":["../../lib/Filtering/parseFilterRightValue.ts"],"names":[],"mappings":";;;AAAA,mEAAoD;AAO7C,MAAM,qBAAqB,GAAG,CAAC,GAAQ,EAAE,EAAE,MAAM,EAAE,UAAU,EAAqB,EAAE,EAAE;IAC3F,MAAM,OAAO,GAAG,CAAC,CAAM,EAAE,EAAE,CAAC,qBAAG,CAAC,EAAE,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;IACrD,MAAM,UAAU,GAAG,GAAG,EAAE;QACtB,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC;YACxB,MAAM,sDAAsD,CAAC;QAC/D,CAAC;IACH,CAAC,CAAC;IACF,IAAI,MAAM,KAAK,KAAK,IAAI,MAAM,EAAE,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC;QACnD,UAAU,EAAE,CAAC;QACb,OAAO,qBAAG,CAAC,EAAE,CAAC,MAAM,CAAC,OAAO,MAAM,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IAChD,CAAC;SAAM,IAAI,MAAM,KAAK,OAAO,IAAI,UAAU,EAAE,gBAAgB,KAAK,OAAO,EAAE,CAAC;QAC1E,UAAU,EAAE,CAAC;QACb,OAAO,qBAAG,CAAC,EAAE,CAAC,MAAM,CAAC,gBAAgB,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IAChD,CAAC;IAED,OAAO,OAAO,CAAC,GAAG,CAAC,CAAC;AACtB,CAAC,CAAC;AAhBW,QAAA,qBAAqB,yBAgBhC"}
@@ -1,16 +1,13 @@
1
1
  import type { AnyObject } from "prostgles-types";
2
2
  import { isObject } from "prostgles-types";
3
- import {
4
- FILTER_OPERANDS,
5
- FILTER_OPERAND_TO_SQL_OPERAND,
6
- parseFilterRightValue,
7
- } from "../../Filtering";
3
+ import { FILTER_OPERANDS, FILTER_OPERAND_TO_SQL_OPERAND } from "../../Filtering/Filtering";
8
4
  import { FUNCTIONS } from "../QueryBuilder/Functions/Functions";
9
5
  import { parseFunctionObject } from "../QueryBuilder/QueryBuilder";
10
6
  import type { TableSchemaColumn } from "../DboBuilderTypes";
11
7
  import { asValue } from "../../PubSubManager/PubSubManagerUtils";
12
8
  import { parseFunction } from "../QueryBuilder/Functions/parseFunction";
13
9
  import { asNameAlias } from "../../utils/asNameAlias";
10
+ import { parseFilterRightValue } from "../../Filtering/parseFilterRightValue";
14
11
 
15
12
  const allowedComparators = FILTER_OPERANDS; //[">", "<", "=", "<=", ">=", "<>", "!="]
16
13
  type Args = {
@@ -22,6 +22,7 @@ export async function prepareWhere(
22
22
  this: ViewHandler,
23
23
  params: PrepareWhereParams,
24
24
  ): Promise<{
25
+ columnsUsed: string[];
25
26
  condition: string;
26
27
  where: string;
27
28
  filter: AnyObject;
@@ -45,17 +46,18 @@ export async function prepareWhere(
45
46
 
46
47
  const exists: ExistsFilterConfig[] = [];
47
48
 
49
+ type FilterItemResult = { condition: string; columnsUsed: string[] };
48
50
  const parseFullFilter = async (
49
51
  f: any,
50
52
  parentFilter: AnyObject | null = null,
51
53
  isForcedFilterBypass: boolean,
52
- ): Promise<string> => {
54
+ ): Promise<FilterItemResult | undefined> => {
53
55
  if (!f) throw "Invalid/missing group filter provided";
54
56
  if (!isObject(f)) throw "\nInvalid filter\nExpecting an object but got -> " + JSON.stringify(f);
55
- let result = "";
57
+
56
58
  const keys = getKeys(f);
57
59
  if (!keys.length) {
58
- return result;
60
+ return;
59
61
  }
60
62
  if (keys.includes($and_key) || keys.includes($or_key)) {
61
63
  if (keys.length > 1)
@@ -69,19 +71,23 @@ export async function prepareWhere(
69
71
 
70
72
  if (group && group.length) {
71
73
  const operand = $and ? " AND " : " OR ";
72
- const conditions = (
74
+ const conditionItems = (
73
75
  await Promise.all(
74
76
  group.map(async (gf) => await parseFullFilter(gf, group, isForcedFilterBypass)),
75
77
  )
76
- ).filter((c) => c);
78
+ )
79
+ .filter(isDefined)
80
+ .filter((c) => c.condition);
77
81
 
78
- if (conditions.length) {
79
- if (conditions.length === 1) return conditions.join(operand);
80
- else return ` ( ${conditions.sort().join(operand)} ) `;
82
+ if (conditionItems.length) {
83
+ const conditions = conditionItems.map((c) => c.condition);
84
+ const columnsUsed = conditionItems.map((c) => c.columnsUsed).flat();
85
+ if (conditions.length === 1) return { columnsUsed, condition: conditions.join(operand) };
86
+ else return { columnsUsed, condition: ` ( ${conditions.sort().join(operand)} ) ` };
81
87
  }
82
88
  } else if (!group) {
83
89
  /** forcedFilters do not get checked against publish and are treated as server-side requests */
84
- const cond = await getCondition.bind(this)({
90
+ const itemInfo = await getCondition.bind(this)({
85
91
  filter: { ...f },
86
92
  select,
87
93
  allowed_colnames:
@@ -91,18 +97,27 @@ export async function prepareWhere(
91
97
  tableRules: isForcedFilterBypass ? undefined : tableRule,
92
98
  isHaving: params.isHaving,
93
99
  });
94
- result = cond.condition;
95
- exists.push(...cond.exists);
100
+ exists.push(...itemInfo.exists);
101
+ return {
102
+ condition: itemInfo.condition,
103
+ columnsUsed: itemInfo.columnsUsed,
104
+ };
96
105
  }
97
- return result;
98
106
  };
99
107
 
100
108
  /* A forced filter condition will not check if the existsJoined filter tables have been published */
101
109
  const forcedFilterCond =
102
110
  forcedFilter ? await parseFullFilter(forcedFilter, null, true) : undefined;
103
111
  const filterCond = await parseFullFilter(filter, null, false);
104
- let cond = [forcedFilterCond, filterCond].filter((c) => c).join(" AND ");
112
+ let combinedConditions = [forcedFilterCond, filterCond]
113
+ .map((c) => (c?.condition ? c.condition : undefined))
114
+ .filter(isDefined)
115
+ .join(" AND ");
105
116
 
117
+ const combinedColumnsUsed = [
118
+ ...(forcedFilterCond?.columnsUsed ?? []),
119
+ ...(filterCond?.columnsUsed ?? []),
120
+ ];
106
121
  const finalFilter =
107
122
  forcedFilter ?
108
123
  {
@@ -110,9 +125,15 @@ export async function prepareWhere(
110
125
  }
111
126
  : { ...filter };
112
127
 
113
- const condition = cond;
114
- if (cond && addKeywords) {
115
- cond = `WHERE ${cond}`;
128
+ const condition = combinedConditions;
129
+ if (combinedConditions && addKeywords) {
130
+ combinedConditions = `WHERE ${combinedConditions}`;
116
131
  }
117
- return { condition, where: cond || "", filter: finalFilter, exists };
132
+ return {
133
+ columnsUsed: combinedColumnsUsed,
134
+ condition,
135
+ where: combinedConditions || "",
136
+ filter: finalFilter,
137
+ exists,
138
+ };
118
139
  }
@@ -1,5 +1,5 @@
1
- import { asName, pickKeys } from "prostgles-types";
2
- import { parseFilterItem } from "../Filtering";
1
+ import { pickKeys } from "prostgles-types";
2
+ import { parseFilterItem } from "../Filtering/Filtering";
3
3
  import type { ParsedTableRule } from "../PublishParser/PublishParser";
4
4
  import type { ExistsFilterConfig, LocalParams, PGIdentifier } from "./DboBuilder";
5
5
  import { pgp } from "./DboBuilder";
@@ -29,7 +29,7 @@ export async function getCondition(
29
29
  tableRules?: ParsedTableRule;
30
30
  isHaving?: boolean;
31
31
  },
32
- ): Promise<{ exists: ExistsFilterConfig[]; condition: string }> {
32
+ ): Promise<{ exists: ExistsFilterConfig[]; condition: string; columnsUsed: string[] }> {
33
33
  const {
34
34
  filter: rawFilter,
35
35
  select,
@@ -179,21 +179,22 @@ export async function getCondition(
179
179
  !existsConfigs.find((ek) => ek.existType === k),
180
180
  );
181
181
 
182
- const validFieldNames = allowedSelect.map((s) => s.alias);
182
+ const selectAliases = allowedSelect.map((s) => s.alias);
183
183
  const invalidColumn = filterKeys.find(
184
- (fName) =>
185
- !validFieldNames.find(
186
- (c) =>
187
- c === fName ||
188
- (fName.startsWith(c) &&
189
- (fName.slice(c.length).includes("->") || fName.slice(c.length).includes("."))),
184
+ (filterKey) =>
185
+ !selectAliases.find(
186
+ (alias) =>
187
+ alias === filterKey ||
188
+ (filterKey.startsWith(alias) &&
189
+ (filterKey.slice(alias.length).includes("->") ||
190
+ filterKey.slice(alias.length).includes("."))),
190
191
  ),
191
192
  );
192
193
 
193
194
  if (invalidColumn) {
194
- const selItem = select?.find((s) => s.alias === invalidColumn);
195
+ const selectItem = select?.find((s) => s.alias === invalidColumn);
195
196
  let isComplexFilter = false;
196
- if (selItem?.type === "aggregation") {
197
+ if (selectItem?.type === "aggregation") {
197
198
  if (!params.isHaving) {
198
199
  throw new Error(
199
200
  `Filtering by ${this.name}.${invalidColumn} is not allowed. Aggregations cannot be filtered. Use HAVING clause instead.`,
@@ -227,7 +228,7 @@ export async function getCondition(
227
228
  : this.parseFieldFilter(tableRules.select?.filterFields ?? tableRules.select?.fields),
228
229
  });
229
230
 
230
- let templates: string[] = [q].filter((q) => q);
231
+ let templates: string[] = q?.condition ? [q.condition] : [];
231
232
 
232
233
  if (existsCond) templates.push(existsCond);
233
234
  templates = templates.concat(funcConds);
@@ -236,6 +237,7 @@ export async function getCondition(
236
237
 
237
238
  /* sorted to ensure duplicate subscription channels are not created due to different condition order */
238
239
  return {
240
+ columnsUsed: q?.columnsUsed ?? [],
239
241
  exists: existsConfigs,
240
242
  condition: templates.sort().join(" AND \n"),
241
243
  };
@@ -80,7 +80,9 @@ export async function getSubscribeRelatedTables(
80
80
  const joinColumns =
81
81
  relatedTableJoinPathItem?.on.map((columnPair) => Object.values(columnPair)).flat() ?? [];
82
82
 
83
- const trackedColumns = Array.from(new Set([...(selectedColumnNames ?? []), ...joinColumns]));
83
+ const trackedColumns = Array.from(
84
+ new Set([...(selectedColumnNames ?? []), ...joinColumns, ...joinConditionInfo.columnsUsed]),
85
+ );
84
86
 
85
87
  viewOptions.relatedTables.push({
86
88
  tableName: relatedTableName,