@vuu-ui/vuu-filter-parser 4.0.0-beta.7 → 4.0.1
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/package.json +5 -5
- package/src/filter-evaluation-utils.js +69 -37
- package/types/filter-evaluation-utils.d.ts +4 -2
- package/types/src/FilterParser.d.ts +2 -0
- package/types/src/FilterTreeWalker.d.ts +3 -0
- package/types/src/filter-evaluation-utils.d.ts +17 -0
- package/types/src/generated/filter-parser.d.ts +2 -0
- package/types/src/generated/filter-parser.terms.d.ts +1 -0
- package/types/src/index.d.ts +4 -0
package/package.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "4.0.
|
|
2
|
+
"version": "4.0.1",
|
|
3
3
|
"main": "./src/index.js",
|
|
4
4
|
"author": "heswell",
|
|
5
5
|
"license": "Apache-2.0",
|
|
@@ -12,14 +12,14 @@
|
|
|
12
12
|
"type-defs": "node ../../scripts/build-type-defs.mjs"
|
|
13
13
|
},
|
|
14
14
|
"devDependencies": {
|
|
15
|
-
"@vuu-ui/vuu-data-types": "4.0.
|
|
16
|
-
"@vuu-ui/vuu-filter-types": "4.0.
|
|
17
|
-
"@vuu-ui/vuu-table-types": "4.0.
|
|
15
|
+
"@vuu-ui/vuu-data-types": "4.0.1",
|
|
16
|
+
"@vuu-ui/vuu-filter-types": "4.0.1",
|
|
17
|
+
"@vuu-ui/vuu-table-types": "4.0.1"
|
|
18
18
|
},
|
|
19
19
|
"dependencies": {
|
|
20
20
|
"@lezer/common": "^1.0.2",
|
|
21
21
|
"@lezer/lr": "1.4.2",
|
|
22
|
-
"@vuu-ui/vuu-utils": "4.0.
|
|
22
|
+
"@vuu-ui/vuu-utils": "4.0.1"
|
|
23
23
|
},
|
|
24
24
|
"files": [
|
|
25
25
|
"README.md",
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { isFilter, isScaledDecimalFilterClause } from "@vuu-ui/vuu-utils";
|
|
1
|
+
import { getScaledDecimalScale, isFilter, isScaledDecimalFilterClause, toDecimalString, toScaledInteger } from "@vuu-ui/vuu-utils";
|
|
2
2
|
import { parseFilter } from "./FilterParser.js";
|
|
3
3
|
const filterPredicateMap = new Map();
|
|
4
4
|
const dataRowFilterPredicateMap = new Map();
|
|
@@ -32,7 +32,7 @@ function getFilterPredicate(columnMapOrFilter, filterQuery) {
|
|
|
32
32
|
}
|
|
33
33
|
throw Error("[getFilterPredicate] invalid params");
|
|
34
34
|
}
|
|
35
|
-
function filterPredicate(columnMapOrFilter, filter) {
|
|
35
|
+
function filterPredicate(columnMapOrFilter, filter, columnsByName) {
|
|
36
36
|
if (isFilter(columnMapOrFilter)) switch(columnMapOrFilter.op){
|
|
37
37
|
case "in":
|
|
38
38
|
return testDataRowInclude(columnMapOrFilter);
|
|
@@ -65,40 +65,72 @@ function filterPredicate(columnMapOrFilter, filter) {
|
|
|
65
65
|
return ()=>true;
|
|
66
66
|
}
|
|
67
67
|
}
|
|
68
|
-
if (filter)
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
68
|
+
if (filter) {
|
|
69
|
+
const scale = void 0 === filter.column ? void 0 : getScaledDecimalScale(columnsByName?.[filter.column]?.serverDataType);
|
|
70
|
+
if (void 0 !== scale && isComparisonOp(filter.op)) return testScaledDecimal(columnMapOrFilter, filter, scale);
|
|
71
|
+
switch(filter.op){
|
|
72
|
+
case "in":
|
|
73
|
+
return testInclude(columnMapOrFilter, filter);
|
|
74
|
+
case "=":
|
|
75
|
+
return testEQ(columnMapOrFilter, filter);
|
|
76
|
+
case "!=":
|
|
77
|
+
return testNE(columnMapOrFilter, filter);
|
|
78
|
+
case ">":
|
|
79
|
+
return testGT(columnMapOrFilter, filter);
|
|
80
|
+
case ">=":
|
|
81
|
+
return testGE(columnMapOrFilter, filter);
|
|
82
|
+
case "<":
|
|
83
|
+
return testLT(columnMapOrFilter, filter);
|
|
84
|
+
case "<=":
|
|
85
|
+
return testLE(columnMapOrFilter, filter);
|
|
86
|
+
case "ends":
|
|
87
|
+
return testEW(columnMapOrFilter, filter);
|
|
88
|
+
case "starts":
|
|
89
|
+
return testSW(columnMapOrFilter, filter);
|
|
90
|
+
case "contains":
|
|
91
|
+
return testContains(columnMapOrFilter, filter);
|
|
92
|
+
case "and":
|
|
93
|
+
return testAND(columnMapOrFilter, filter, columnsByName);
|
|
94
|
+
case "or":
|
|
95
|
+
return testOR(columnMapOrFilter, filter, columnsByName);
|
|
96
|
+
default:
|
|
97
|
+
{
|
|
98
|
+
const unreachable = filter;
|
|
99
|
+
console.log('unrecognized filter type', unreachable);
|
|
100
|
+
return ()=>true;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
99
103
|
}
|
|
100
104
|
throw Error("[filterPredicate] invalid params");
|
|
101
105
|
}
|
|
106
|
+
const comparisonOps = [
|
|
107
|
+
"=",
|
|
108
|
+
"!=",
|
|
109
|
+
">",
|
|
110
|
+
">=",
|
|
111
|
+
"<",
|
|
112
|
+
"<="
|
|
113
|
+
];
|
|
114
|
+
const isComparisonOp = (op)=>comparisonOps.includes(op);
|
|
115
|
+
const compare = {
|
|
116
|
+
"=": (a, b)=>a === b,
|
|
117
|
+
"!=": (a, b)=>a !== b,
|
|
118
|
+
">": (a, b)=>a > b,
|
|
119
|
+
">=": (a, b)=>a >= b,
|
|
120
|
+
"<": (a, b)=>a < b,
|
|
121
|
+
"<=": (a, b)=>a <= b
|
|
122
|
+
};
|
|
123
|
+
const testScaledDecimal = (columnMap, filter, scale)=>{
|
|
124
|
+
const op = filter.op;
|
|
125
|
+
const test = compare[op];
|
|
126
|
+
const filterValue = toScaledInteger(toDecimalString(filter.value, scale), scale);
|
|
127
|
+
const index = columnMap[filter.column];
|
|
128
|
+
return (row)=>{
|
|
129
|
+
const value = row[index];
|
|
130
|
+
if ("" === value || null == value) return "!=" === op;
|
|
131
|
+
return test(BigInt(value), filterValue);
|
|
132
|
+
};
|
|
133
|
+
};
|
|
102
134
|
const testInclude = (columnMap, filter)=>(row)=>-1 !== filter.values.indexOf(row[columnMap[filter.column]]);
|
|
103
135
|
const testDataRowInclude = (filter)=>(row)=>-1 !== filter.values.indexOf(row[filter.column]);
|
|
104
136
|
const testEQ = (columnMap, filter)=>{
|
|
@@ -173,16 +205,16 @@ const testDataRowContains = (filter)=>{
|
|
|
173
205
|
return rowValue.toLowerCase().includes(filterValue.toLowerCase());
|
|
174
206
|
};
|
|
175
207
|
};
|
|
176
|
-
const testAND = (columnMap, filter)=>{
|
|
177
|
-
const filters = filter.filters.map((f1)=>filterPredicate(columnMap, f1));
|
|
208
|
+
const testAND = (columnMap, filter, columnsByName)=>{
|
|
209
|
+
const filters = filter.filters.map((f1)=>filterPredicate(columnMap, f1, columnsByName));
|
|
178
210
|
return (row)=>filters.every((fn)=>fn(row));
|
|
179
211
|
};
|
|
180
212
|
const testDataRowAND = (filter)=>{
|
|
181
213
|
const filters = filter.filters.map((f1)=>filterPredicate(f1));
|
|
182
214
|
return (row)=>filters.every((fn)=>fn(row));
|
|
183
215
|
};
|
|
184
|
-
function testOR(columnMap, filter) {
|
|
185
|
-
const filters = filter.filters.map((f1)=>filterPredicate(columnMap, f1));
|
|
216
|
+
function testOR(columnMap, filter, columnsByName) {
|
|
217
|
+
const filters = filter.filters.map((f1)=>filterPredicate(columnMap, f1, columnsByName));
|
|
186
218
|
return (row)=>filters.some((fn)=>fn(row));
|
|
187
219
|
}
|
|
188
220
|
function testDataRowOR(filter) {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { DataSourceRowWithBigint } from "@vuu-ui/vuu-data-types";
|
|
2
|
-
import { Filter } from "@vuu-ui/vuu-filter-types";
|
|
2
|
+
import { ColumnDescriptorsByName, Filter } from "@vuu-ui/vuu-filter-types";
|
|
3
3
|
import { ColumnMap } from "@vuu-ui/vuu-utils";
|
|
4
4
|
import { VuuDataRow } from "@vuu-ui/vuu-protocol-types";
|
|
5
5
|
import { DataRow } from "@vuu-ui/vuu-table-types";
|
|
@@ -12,6 +12,8 @@ export declare function getFilterPredicate(filterQuery: string): DataRowFilterPr
|
|
|
12
12
|
* Two row formats supported:
|
|
13
13
|
* - DataRow, used by Tables, when evaluatingn a Menu filter.
|
|
14
14
|
* - DataSourceRow, used by local data source, like ArrayDataSOurce
|
|
15
|
+
* For a DataSourceRow, columnsByName provides the column types, required to
|
|
16
|
+
* compare scaled decimal values, which are held as scaled integer strings.
|
|
15
17
|
*/
|
|
16
|
-
export declare function filterPredicate(columnMap: ColumnMap, filter: Filter): FilterPredicate;
|
|
18
|
+
export declare function filterPredicate(columnMap: ColumnMap, filter: Filter, columnsByName?: ColumnDescriptorsByName): FilterPredicate;
|
|
17
19
|
export declare function filterPredicate(filter: Filter): DataRowFilterPredicate;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { DataSourceRowWithBigint } from "@vuu-ui/vuu-data-types";
|
|
2
|
+
import { Filter } from "@vuu-ui/vuu-filter-types";
|
|
3
|
+
import { ColumnMap } from "@vuu-ui/vuu-utils";
|
|
4
|
+
import { VuuDataRow } from "@vuu-ui/vuu-protocol-types";
|
|
5
|
+
import { DataRow } from "@vuu-ui/vuu-table-types";
|
|
6
|
+
export type FilterPredicate = (row: DataSourceRowWithBigint | VuuDataRow) => boolean;
|
|
7
|
+
export type DataRowFilterPredicate = (row: DataRow) => boolean;
|
|
8
|
+
export declare function getFilterPredicate(columnMap: ColumnMap, filterQuery: string): FilterPredicate;
|
|
9
|
+
export declare function getFilterPredicate(filterQuery: string): DataRowFilterPredicate;
|
|
10
|
+
/**
|
|
11
|
+
* Generates a filterPredicate that can be used to test a row against a filter
|
|
12
|
+
* Two row formats supported:
|
|
13
|
+
* - DataRow, used by Tables, when evaluatingn a Menu filter.
|
|
14
|
+
* - DataSourceRow, used by local data source, like ArrayDataSOurce
|
|
15
|
+
*/
|
|
16
|
+
export declare function filterPredicate(columnMap: ColumnMap, filter: Filter): FilterPredicate;
|
|
17
|
+
export declare function filterPredicate(filter: Filter): DataRowFilterPredicate;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const Filter = 1, ColumnValueExpression = 2, Column = 3, Operator = 4, Eq = 5, NotEq = 6, Gt = 7, Lt = 8, Starts = 9, Ends = 10, Contains = 11, Number = 12, String = 13, True = 14, False = 15, ColumnSetExpression = 16, In = 17, LBrack = 18, Values = 19, Comma = 20, RBrack = 21, AndExpression = 22, And = 23, OrExpression = 24, Or = 25, ParenthesizedExpression = 26, As = 27, FilterName = 28;
|