Skip to content

Commit

Permalink
improve parseComplexFilter
Browse files Browse the repository at this point in the history
  • Loading branch information
prostgles committed May 2, 2024
1 parent bccc194 commit 8a7b044
Show file tree
Hide file tree
Showing 8 changed files with 78 additions and 2,463 deletions.
26 changes: 20 additions & 6 deletions lib/DboBuilder/ViewHandler/parseComplexFilter.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import { AnyObject, isObject } from "prostgles-types";
import { FILTER_OPERANDS, parseFilterRightValue } from "../../Filtering";
import { FILTER_OPERANDS, FILTER_OPERAND_TO_SQL_OPERAND, parseFilterRightValue } from "../../Filtering";
import { FUNCTIONS, parseFunction } from "../QueryBuilder/Functions";
import { asNameAlias, parseFunctionObject } from "../QueryBuilder/QueryBuilder";
import { TableSchemaColumn } from "../DboBuilderTypes";
import { asValue } from "../../PubSubManager/PubSubManager";

const allowedComparators = FILTER_OPERANDS; //[">", "<", "=", "<=", ">=", "<>", "!="]
type Args = {
Expand Down Expand Up @@ -54,28 +55,41 @@ export const parseComplexFilter = ({
if (!Array.isArray(complexFilter)) {
throw `Invalid $filter. Must contain an array of at least element but got: ${JSON.stringify(complexFilter)} `
}

const [leftFilter, comparator, rightFilterOrValue] = complexFilter;

const leftVal = getFuncQuery(leftFilter);
let result = leftVal;
if (comparator) {
if (!allowedComparators.includes(comparator)) {
if (typeof comparator !== "string" || !allowedComparators.includes(comparator as any)) {
throw `Invalid $filter. comparator ${JSON.stringify(comparator)} is not valid. Expecting one of: ${allowedComparators}`;
}
if (!rightFilterOrValue) {
throw "Invalid $filter. Expecting a value or function after the comparator";
}
const rightVal = isObject(rightFilterOrValue) ?
const maybeValidComparator = comparator as keyof typeof FILTER_OPERAND_TO_SQL_OPERAND;
const sqlOperand = FILTER_OPERAND_TO_SQL_OPERAND[maybeValidComparator];
if(!sqlOperand){
throw `Invalid $filter. comparator ${comparator} is not valid. Expecting one of: ${allowedComparators}`;
}

let rightVal = isObject(rightFilterOrValue) ?
getFuncQuery(rightFilterOrValue) :
parseFilterRightValue(rightFilterOrValue, {
selectItem: undefined,
expect: ["$in", "$nin"].includes(comparator)? "array" : undefined
expect: ["$in", "$nin"].includes(comparator)? "csv" : undefined
});
if(maybeValidComparator === "$between" || maybeValidComparator === "$notBetween"){

if(!Array.isArray(rightVal) || rightVal.length !== 2){
throw "Between filter expects an array of two values";
}
rightVal = asValue(rightVal[0]) + " AND " + asValue(rightVal[1]);
}
if (leftVal === rightVal){
throw "Invalid $filter. Cannot compare two identical function signatures: " + JSON.stringify(leftFilter);
}
result += ` ${comparator} ${rightVal}`;

result += ` ${sqlOperand} ${rightVal}`;
}

return result;
Expand Down
25 changes: 25 additions & 0 deletions lib/Filtering.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@


import {
BetweenFilterKeys,
CompareFilterKeys,
CompareInFilterKeys,
FilterDataType,
Expand All @@ -21,9 +22,33 @@ export const FILTER_OPERANDS = [
...TextFilterKeys,
...JsonbFilterKeys,
...CompareFilterKeys,
...BetweenFilterKeys,
...CompareInFilterKeys
] as const;

export const FILTER_OPERAND_TO_SQL_OPERAND = Object.fromEntries(
FILTER_OPERANDS.map(filterOperand => {
let sqlOperand = filterOperand as string;
if (filterOperand === "$eq") sqlOperand = "=";
else if (filterOperand === "$gt") sqlOperand = ">";
else if (filterOperand === "$gte") sqlOperand = ">=";
else if (filterOperand === "$lt") sqlOperand = "<";
else if (filterOperand === "$lte") sqlOperand = "<=";
else if (filterOperand === "$ne") sqlOperand = "<>";
else if (filterOperand === "$like") sqlOperand = "LIKE";
else if (filterOperand === "$ilike") sqlOperand = "ILIKE";
else if (filterOperand === "$nlike") sqlOperand = "NOT LIKE";
else if (filterOperand === "$nilike") sqlOperand = "NOT ILIKE";
else if (filterOperand === "$in") sqlOperand = "IN";
else if (filterOperand === "$nin") sqlOperand = "NOT IN";
else if (filterOperand === "$between") sqlOperand = "BETWEEN";
else if (filterOperand === "$notBetween") sqlOperand = "NOT BETWEEN";
else if (filterOperand === "$isDistinctFrom") sqlOperand = "IS DISTINCT FROM";
else if (filterOperand === "$isNotDistinctFrom") sqlOperand = "IS NOT DISTINCT FROM";
return [filterOperand, sqlOperand];
})
) as Record<typeof FILTER_OPERANDS[number], string>;

/**
* Parse a single filter
* Ensure only single key objects reach this point
Expand Down
18 changes: 9 additions & 9 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "prostgles-server",
"version": "4.2.54",
"version": "4.2.55",
"description": "",
"main": "dist/index.js",
"types": "dist/index.d.ts",
Expand Down Expand Up @@ -43,7 +43,7 @@
"pg-cursor": "^2.10.5",
"pg-promise": "^11.6.0",
"prostgles-client": "^4.0.53",
"prostgles-types": "^4.0.81"
"prostgles-types": "^4.0.84"
},
"devDependencies": {
"@types/bluebird": "^3.5.36",
Expand Down
Loading

0 comments on commit 8a7b044

Please sign in to comment.