@webda/cloudevents 3.0.0
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/LICENSE +166 -0
- package/lib/filters/abstract.d.ts +28 -0
- package/lib/filters/abstract.js +17 -0
- package/lib/filters/abstract.js.map +1 -0
- package/lib/filters/index.d.ts +14 -0
- package/lib/filters/index.js +34 -0
- package/lib/filters/index.js.map +1 -0
- package/lib/filters/interfaces.d.ts +0 -0
- package/lib/filters/interfaces.js +1 -0
- package/lib/filters/interfaces.js.map +1 -0
- package/lib/filters/logical.d.ts +54 -0
- package/lib/filters/logical.js +49 -0
- package/lib/filters/logical.js.map +1 -0
- package/lib/filters/sql/CESQLParserLexer.d.ts +55 -0
- package/lib/filters/sql/CESQLParserLexer.js +293 -0
- package/lib/filters/sql/CESQLParserLexer.js.map +1 -0
- package/lib/filters/sql/CESQLParserListener.d.ts +325 -0
- package/lib/filters/sql/CESQLParserListener.js +3 -0
- package/lib/filters/sql/CESQLParserListener.js.map +1 -0
- package/lib/filters/sql/CESQLParserParser.d.ts +313 -0
- package/lib/filters/sql/CESQLParserParser.js +1825 -0
- package/lib/filters/sql/CESQLParserParser.js.map +1 -0
- package/lib/filters/sql/CESQLParserVisitor.d.ts +208 -0
- package/lib/filters/sql/CESQLParserVisitor.js +3 -0
- package/lib/filters/sql/CESQLParserVisitor.js.map +1 -0
- package/lib/filters/sql.d.ts +426 -0
- package/lib/filters/sql.js +752 -0
- package/lib/filters/sql.js.map +1 -0
- package/lib/filters/string.d.ts +105 -0
- package/lib/filters/string.js +79 -0
- package/lib/filters/string.js.map +1 -0
- package/lib/subscription.d.ts +228 -0
- package/lib/subscription.js +60 -0
- package/lib/subscription.js.map +1 -0
- package/package.json +61 -0
|
@@ -0,0 +1,752 @@
|
|
|
1
|
+
import { ANTLRInputStream, CommonTokenStream } from "antlr4ts";
|
|
2
|
+
import { AbstractParseTreeVisitor } from "antlr4ts/tree.js";
|
|
3
|
+
import { FilterImplementation } from "./abstract.js";
|
|
4
|
+
import { CESQLParserLexer } from "./sql/CESQLParserLexer.js";
|
|
5
|
+
import { CESQLParserParser } from "./sql/CESQLParserParser.js";
|
|
6
|
+
import { ExactFilterImplementation, PrefixFilterImplementation, SuffixFilterImplementation } from "./string.js";
|
|
7
|
+
/**
|
|
8
|
+
* Functions implementation
|
|
9
|
+
*/
|
|
10
|
+
const functions = {
|
|
11
|
+
ABS: (...args) => {
|
|
12
|
+
if (args.length > 1) {
|
|
13
|
+
throw new Error("Too many arguments");
|
|
14
|
+
}
|
|
15
|
+
return Math.abs(args[0]);
|
|
16
|
+
},
|
|
17
|
+
LENGTH: (...args) => {
|
|
18
|
+
if (args.length > 1) {
|
|
19
|
+
throw new Error("Too many arguments");
|
|
20
|
+
}
|
|
21
|
+
return (args[0] || "").length;
|
|
22
|
+
},
|
|
23
|
+
CONCAT: (...args) => {
|
|
24
|
+
return args.join("");
|
|
25
|
+
},
|
|
26
|
+
CONCAT_WS: (...args) => {
|
|
27
|
+
let merger = args.shift();
|
|
28
|
+
return args.join(merger);
|
|
29
|
+
},
|
|
30
|
+
LOWER: (...args) => {
|
|
31
|
+
if (args.length > 1) {
|
|
32
|
+
throw new Error("Too many arguments");
|
|
33
|
+
}
|
|
34
|
+
return (args[0] || "").toLowerCase();
|
|
35
|
+
},
|
|
36
|
+
UPPER: (...args) => {
|
|
37
|
+
if (args.length > 1) {
|
|
38
|
+
throw new Error("Too many arguments");
|
|
39
|
+
}
|
|
40
|
+
return (args[0] || "").toUpperCase();
|
|
41
|
+
},
|
|
42
|
+
TRIM: (...args) => {
|
|
43
|
+
if (args.length > 1) {
|
|
44
|
+
throw new Error("Too many arguments");
|
|
45
|
+
}
|
|
46
|
+
return (args[0] || "").trim();
|
|
47
|
+
},
|
|
48
|
+
LEFT: (...args) => {
|
|
49
|
+
if (args.length !== 2) {
|
|
50
|
+
throw new Error("Wrong arguments count");
|
|
51
|
+
}
|
|
52
|
+
return (args[0] || "").substr(0, args[1]);
|
|
53
|
+
},
|
|
54
|
+
RIGHT: (...args) => {
|
|
55
|
+
if (args.length !== 2) {
|
|
56
|
+
throw new Error("Wrong arguments count");
|
|
57
|
+
}
|
|
58
|
+
args[0] ?? (args[0] = "");
|
|
59
|
+
return args[0].substr(args[0].length - args[1]);
|
|
60
|
+
},
|
|
61
|
+
SUBSTRING: (...args) => {
|
|
62
|
+
if (args.length > 3 || args.length < 2) {
|
|
63
|
+
throw new Error("Wrong arguments count");
|
|
64
|
+
}
|
|
65
|
+
return (args[0] || "").substring(args[1], args[2]);
|
|
66
|
+
},
|
|
67
|
+
INT: (...args) => {
|
|
68
|
+
if (args.length > 1) {
|
|
69
|
+
throw new Error("Too many arguments");
|
|
70
|
+
}
|
|
71
|
+
switch (typeof args[0]) {
|
|
72
|
+
case "number":
|
|
73
|
+
return args[0];
|
|
74
|
+
case "string":
|
|
75
|
+
let res = Number.parseInt(args[0]);
|
|
76
|
+
if (!Number.isNaN(res)) {
|
|
77
|
+
return res;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
return 0;
|
|
81
|
+
},
|
|
82
|
+
BOOL: (...args) => {
|
|
83
|
+
if (args.length > 1) {
|
|
84
|
+
throw new Error("Too many arguments");
|
|
85
|
+
}
|
|
86
|
+
if (typeof args[0] === "string") {
|
|
87
|
+
return args[0].toLowerCase() === "true";
|
|
88
|
+
}
|
|
89
|
+
else if (typeof args[0] === "boolean") {
|
|
90
|
+
return args[0];
|
|
91
|
+
}
|
|
92
|
+
return false;
|
|
93
|
+
},
|
|
94
|
+
STRING: (...args) => {
|
|
95
|
+
if (args.length > 1) {
|
|
96
|
+
throw new Error("Too many arguments");
|
|
97
|
+
}
|
|
98
|
+
if (typeof args[0] === "boolean") {
|
|
99
|
+
return args[0].toString().toUpperCase();
|
|
100
|
+
}
|
|
101
|
+
return args[0].toString();
|
|
102
|
+
},
|
|
103
|
+
IS_BOOL: (...args) => {
|
|
104
|
+
if (args.length > 1) {
|
|
105
|
+
throw new Error("Too many arguments");
|
|
106
|
+
}
|
|
107
|
+
return typeof args[0] === "boolean";
|
|
108
|
+
},
|
|
109
|
+
IS_INT: (...args) => {
|
|
110
|
+
if (args.length > 1) {
|
|
111
|
+
throw new Error("Too many arguments");
|
|
112
|
+
}
|
|
113
|
+
return typeof args[0] === "number";
|
|
114
|
+
}
|
|
115
|
+
};
|
|
116
|
+
/**
|
|
117
|
+
* Represent the query expression or subset
|
|
118
|
+
*/
|
|
119
|
+
export class Expression {
|
|
120
|
+
constructor() {
|
|
121
|
+
this.deps = [];
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Resolve the expression if possible
|
|
125
|
+
*
|
|
126
|
+
* If the expression only contains static values then it can be resolved
|
|
127
|
+
* @returns
|
|
128
|
+
*/
|
|
129
|
+
resolve() {
|
|
130
|
+
if (this.deps.length && this.deps.every(d => d instanceof ValueExpression)) {
|
|
131
|
+
return new ValueExpression(this.eval({}));
|
|
132
|
+
}
|
|
133
|
+
return this;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* Represent an attribute expression
|
|
138
|
+
*/
|
|
139
|
+
export class AttributeExpression extends Expression {
|
|
140
|
+
constructor(attribute) {
|
|
141
|
+
super();
|
|
142
|
+
this.attribute = attribute;
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* @override
|
|
146
|
+
*/
|
|
147
|
+
eval(target) {
|
|
148
|
+
return target[this.attribute];
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* @override
|
|
152
|
+
*/
|
|
153
|
+
toString() {
|
|
154
|
+
return this.attribute;
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
/**
|
|
158
|
+
* Represent a function expression
|
|
159
|
+
*/
|
|
160
|
+
export class FunctionExpression extends Expression {
|
|
161
|
+
/**
|
|
162
|
+
*
|
|
163
|
+
* @param functionName to execute
|
|
164
|
+
* @param args to call with the function
|
|
165
|
+
*/
|
|
166
|
+
constructor(functionName, ...args) {
|
|
167
|
+
super();
|
|
168
|
+
this.functionName = functionName;
|
|
169
|
+
if (!functions[functionName]) {
|
|
170
|
+
throw new Error(`Unknown function: '${functionName}'`);
|
|
171
|
+
}
|
|
172
|
+
this.deps.push(...args);
|
|
173
|
+
this.args = args;
|
|
174
|
+
}
|
|
175
|
+
/**
|
|
176
|
+
* @override
|
|
177
|
+
*/
|
|
178
|
+
eval(target) {
|
|
179
|
+
return functions[this.functionName](...this.args.map(a => a.eval(target)));
|
|
180
|
+
}
|
|
181
|
+
/**
|
|
182
|
+
* @override
|
|
183
|
+
*/
|
|
184
|
+
toString() {
|
|
185
|
+
return `${this.functionName}(${this.args.map(a => a.toString()).join(",")})`;
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
/**
|
|
189
|
+
* Represent a unary logic expression
|
|
190
|
+
*/
|
|
191
|
+
export class UnaryLogicExpression extends Expression {
|
|
192
|
+
/**
|
|
193
|
+
* Invert the result of the child expression
|
|
194
|
+
* @param child
|
|
195
|
+
*/
|
|
196
|
+
constructor(child) {
|
|
197
|
+
super();
|
|
198
|
+
this.child = child;
|
|
199
|
+
this.deps.push(child);
|
|
200
|
+
}
|
|
201
|
+
/**
|
|
202
|
+
* @override
|
|
203
|
+
*/
|
|
204
|
+
eval(target) {
|
|
205
|
+
return !this.deps[0].eval(target);
|
|
206
|
+
}
|
|
207
|
+
/**
|
|
208
|
+
* @override
|
|
209
|
+
*/
|
|
210
|
+
toString() {
|
|
211
|
+
return `NOT ${this.deps[0].toString()}`;
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
/**
|
|
215
|
+
* Represent a unary numeric expression
|
|
216
|
+
*/
|
|
217
|
+
export class UnaryNumericExpression extends Expression {
|
|
218
|
+
/**
|
|
219
|
+
* Negative the result of the child expression
|
|
220
|
+
* @param child
|
|
221
|
+
*/
|
|
222
|
+
constructor(child) {
|
|
223
|
+
super();
|
|
224
|
+
this.child = child;
|
|
225
|
+
this.deps.push(child);
|
|
226
|
+
}
|
|
227
|
+
/**
|
|
228
|
+
* @override
|
|
229
|
+
*/
|
|
230
|
+
eval(target) {
|
|
231
|
+
return -1 * this.child.eval(target);
|
|
232
|
+
}
|
|
233
|
+
/**
|
|
234
|
+
* @override
|
|
235
|
+
*/
|
|
236
|
+
toString() {
|
|
237
|
+
return `-${this.child.toString()}`;
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
/**
|
|
241
|
+
* Represent a LIKE expression
|
|
242
|
+
*/
|
|
243
|
+
export class LikeExpression extends Expression {
|
|
244
|
+
/**
|
|
245
|
+
*
|
|
246
|
+
* @param left part of the expression
|
|
247
|
+
* @param right part of the expression the regexp with % and _
|
|
248
|
+
* @param invert if NOT LIKE is used
|
|
249
|
+
*/
|
|
250
|
+
constructor(left, right, invert) {
|
|
251
|
+
super();
|
|
252
|
+
this.left = left;
|
|
253
|
+
this.right = right;
|
|
254
|
+
this.invert = invert;
|
|
255
|
+
this.deps.push(left);
|
|
256
|
+
this.regexp = new RegExp(right
|
|
257
|
+
.substring(1, right.length - 1)
|
|
258
|
+
.replace(/([^\\])%/g, "$1.*")
|
|
259
|
+
.replace(/([^\\])_/g, "$1.?"));
|
|
260
|
+
}
|
|
261
|
+
/**
|
|
262
|
+
* @override
|
|
263
|
+
*/
|
|
264
|
+
eval(target) {
|
|
265
|
+
let res = this.regexp.exec(this.left.eval(target)) !== null;
|
|
266
|
+
if (this.invert) {
|
|
267
|
+
return !res;
|
|
268
|
+
}
|
|
269
|
+
return res;
|
|
270
|
+
}
|
|
271
|
+
/**
|
|
272
|
+
* @override
|
|
273
|
+
*/
|
|
274
|
+
toString() {
|
|
275
|
+
return `${this.left.toString()} ${this.invert ? "NOT " : ""}LIKE ${this.right}`;
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
/**
|
|
279
|
+
* Represent a EXISTS expression
|
|
280
|
+
*/
|
|
281
|
+
export class ExistsExpression extends Expression {
|
|
282
|
+
/**
|
|
283
|
+
*
|
|
284
|
+
* @param property to check
|
|
285
|
+
*/
|
|
286
|
+
constructor(property) {
|
|
287
|
+
super();
|
|
288
|
+
this.property = property;
|
|
289
|
+
}
|
|
290
|
+
/**
|
|
291
|
+
* @override
|
|
292
|
+
*/
|
|
293
|
+
eval(target) {
|
|
294
|
+
return target[this.property] !== undefined;
|
|
295
|
+
}
|
|
296
|
+
/**
|
|
297
|
+
* @override
|
|
298
|
+
*/
|
|
299
|
+
toString() {
|
|
300
|
+
return `EXISTS ${this.property}`;
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
/**
|
|
304
|
+
* Represent a IN expression
|
|
305
|
+
*/
|
|
306
|
+
export class InExpression extends Expression {
|
|
307
|
+
/**
|
|
308
|
+
*
|
|
309
|
+
* @param left part of the expression
|
|
310
|
+
* @param right part of the expression
|
|
311
|
+
* @param invert if NOT IN
|
|
312
|
+
*/
|
|
313
|
+
constructor(left, right, invert = false) {
|
|
314
|
+
super();
|
|
315
|
+
this.left = left;
|
|
316
|
+
this.right = right;
|
|
317
|
+
this.invert = invert;
|
|
318
|
+
this.deps.push(left, ...right);
|
|
319
|
+
this.staticContent = right.every(d => d instanceof ValueExpression) ? right.map(r => r.eval({})) : undefined;
|
|
320
|
+
}
|
|
321
|
+
/**
|
|
322
|
+
* @override
|
|
323
|
+
*/
|
|
324
|
+
eval(target) {
|
|
325
|
+
let right = this.staticContent || this.right.map(r => r.eval(target));
|
|
326
|
+
if (this.invert) {
|
|
327
|
+
return !right.includes(this.left.eval(target));
|
|
328
|
+
}
|
|
329
|
+
return right.includes(this.left.eval(target));
|
|
330
|
+
}
|
|
331
|
+
/**
|
|
332
|
+
* @override
|
|
333
|
+
*/
|
|
334
|
+
toString() {
|
|
335
|
+
return `${this.left.toString()} ${this.invert ? "NOT " : ""}IN (${this.right.map(r => r.toString()).join(",")})`;
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
/**
|
|
339
|
+
* Represent a binary multiplicative expression
|
|
340
|
+
*/
|
|
341
|
+
export class BinaryMultiplicativeExpression extends Expression {
|
|
342
|
+
/**
|
|
343
|
+
*
|
|
344
|
+
* @param left part of the expression
|
|
345
|
+
* @param right part of the expression
|
|
346
|
+
* @param operator
|
|
347
|
+
*/
|
|
348
|
+
constructor(left, right, operator) {
|
|
349
|
+
super();
|
|
350
|
+
this.left = left;
|
|
351
|
+
this.right = right;
|
|
352
|
+
this.operator = operator;
|
|
353
|
+
this.deps.push(left, right);
|
|
354
|
+
}
|
|
355
|
+
/**
|
|
356
|
+
* @override
|
|
357
|
+
*/
|
|
358
|
+
eval(target) {
|
|
359
|
+
switch (this.operator) {
|
|
360
|
+
case "*":
|
|
361
|
+
return this.left.eval(target) * this.right.eval(target);
|
|
362
|
+
case "/":
|
|
363
|
+
return this.left.eval(target) / this.right.eval(target);
|
|
364
|
+
case "%":
|
|
365
|
+
return this.left.eval(target) % this.right.eval(target);
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
/**
|
|
369
|
+
* @override
|
|
370
|
+
*/
|
|
371
|
+
toString() {
|
|
372
|
+
return `${this.left.toString()} ${this.operator} ${this.right.toString()}`;
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
/**
|
|
376
|
+
* Represent a binary additive expression
|
|
377
|
+
*/
|
|
378
|
+
export class BinaryAdditiveExpression extends Expression {
|
|
379
|
+
/**
|
|
380
|
+
*
|
|
381
|
+
* @param left part of the expression
|
|
382
|
+
* @param right part of the expression
|
|
383
|
+
* @param operator
|
|
384
|
+
*/
|
|
385
|
+
constructor(left, right, operator) {
|
|
386
|
+
super();
|
|
387
|
+
this.left = left;
|
|
388
|
+
this.right = right;
|
|
389
|
+
this.operator = operator;
|
|
390
|
+
this.deps.push(left, right);
|
|
391
|
+
}
|
|
392
|
+
/**
|
|
393
|
+
* @override
|
|
394
|
+
*/
|
|
395
|
+
eval(target) {
|
|
396
|
+
return this.left.eval(target) + this.right.eval(target) * (this.operator === "+" ? 1 : -1);
|
|
397
|
+
}
|
|
398
|
+
/**
|
|
399
|
+
* @override
|
|
400
|
+
*/
|
|
401
|
+
toString() {
|
|
402
|
+
return `${this.left.toString()} + ${this.right.toString()}`;
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
/**
|
|
406
|
+
* Represent a binary comparison expression
|
|
407
|
+
*/
|
|
408
|
+
export class BinaryComparisonExpression extends Expression {
|
|
409
|
+
/**
|
|
410
|
+
*
|
|
411
|
+
* @param left part of the expression
|
|
412
|
+
* @param right part of the expression
|
|
413
|
+
* @param operator to use
|
|
414
|
+
*/
|
|
415
|
+
constructor(left, right, operator) {
|
|
416
|
+
super();
|
|
417
|
+
this.left = left;
|
|
418
|
+
this.right = right;
|
|
419
|
+
this.operator = operator;
|
|
420
|
+
this.deps.push(left, right);
|
|
421
|
+
}
|
|
422
|
+
/**
|
|
423
|
+
* @override
|
|
424
|
+
*/
|
|
425
|
+
eval(target) {
|
|
426
|
+
switch (this.operator) {
|
|
427
|
+
case ">":
|
|
428
|
+
return this.left.eval(target) > this.right.eval(target);
|
|
429
|
+
case "<":
|
|
430
|
+
return this.left.eval(target) < this.right.eval(target);
|
|
431
|
+
case ">=":
|
|
432
|
+
return this.left.eval(target) >= this.right.eval(target);
|
|
433
|
+
case "<=":
|
|
434
|
+
return this.left.eval(target) <= this.right.eval(target);
|
|
435
|
+
case "!=":
|
|
436
|
+
return this.left.eval(target) != this.right.eval(target);
|
|
437
|
+
case "=":
|
|
438
|
+
return this.left.eval(target) == this.right.eval(target);
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
/**
|
|
442
|
+
* @override
|
|
443
|
+
*/
|
|
444
|
+
toString() {
|
|
445
|
+
return `${this.left.toString()} ${this.operator} ${this.right.toString()}`;
|
|
446
|
+
}
|
|
447
|
+
}
|
|
448
|
+
/**
|
|
449
|
+
* Represent a binary logic expression
|
|
450
|
+
*/
|
|
451
|
+
export class BinaryLogicExpression extends Expression {
|
|
452
|
+
/**
|
|
453
|
+
*
|
|
454
|
+
* @param left part of the expression
|
|
455
|
+
* @param right part of the expression
|
|
456
|
+
* @param operator to use
|
|
457
|
+
*/
|
|
458
|
+
constructor(left, right, operator) {
|
|
459
|
+
super();
|
|
460
|
+
this.left = left;
|
|
461
|
+
this.right = right;
|
|
462
|
+
this.operator = operator;
|
|
463
|
+
this.deps.push(left, right);
|
|
464
|
+
}
|
|
465
|
+
/**
|
|
466
|
+
* @override
|
|
467
|
+
*/
|
|
468
|
+
eval(target) {
|
|
469
|
+
switch (this.operator) {
|
|
470
|
+
case "OR":
|
|
471
|
+
return this.left.eval(target) || this.right.eval(target);
|
|
472
|
+
case "XOR":
|
|
473
|
+
return this.left.eval(target) ? !this.right.eval(target) : this.right.eval(target);
|
|
474
|
+
case "AND":
|
|
475
|
+
return this.left.eval(target) && this.right.eval(target);
|
|
476
|
+
}
|
|
477
|
+
}
|
|
478
|
+
/**
|
|
479
|
+
* @override
|
|
480
|
+
*/
|
|
481
|
+
toString() {
|
|
482
|
+
return `${this.left.toString()} ${this.operator} ${this.right.toString()}`;
|
|
483
|
+
}
|
|
484
|
+
}
|
|
485
|
+
/**
|
|
486
|
+
* Represent a value expression
|
|
487
|
+
*/
|
|
488
|
+
export class ValueExpression extends Expression {
|
|
489
|
+
/**
|
|
490
|
+
* Value represented by the expression
|
|
491
|
+
* @param value
|
|
492
|
+
*/
|
|
493
|
+
constructor(value) {
|
|
494
|
+
super();
|
|
495
|
+
this.value = value;
|
|
496
|
+
}
|
|
497
|
+
/**
|
|
498
|
+
* @override
|
|
499
|
+
*/
|
|
500
|
+
eval(target) {
|
|
501
|
+
return this.value;
|
|
502
|
+
}
|
|
503
|
+
/**
|
|
504
|
+
* @override
|
|
505
|
+
*/
|
|
506
|
+
toString() {
|
|
507
|
+
if (typeof this.value === "string") {
|
|
508
|
+
return `"${this.value}"`;
|
|
509
|
+
}
|
|
510
|
+
else if (typeof this.value === "boolean") {
|
|
511
|
+
return this.value.toString().toUpperCase();
|
|
512
|
+
}
|
|
513
|
+
return this.value.toString();
|
|
514
|
+
}
|
|
515
|
+
}
|
|
516
|
+
/**
|
|
517
|
+
* Create Expression based on the parsed token
|
|
518
|
+
*
|
|
519
|
+
* Expression allow to optimize and split between Query and Filter
|
|
520
|
+
*/
|
|
521
|
+
export class CESQLExpressionBuilder extends AbstractParseTreeVisitor {
|
|
522
|
+
/**
|
|
523
|
+
* By default accepting it
|
|
524
|
+
* @returns
|
|
525
|
+
*/
|
|
526
|
+
defaultResult() {
|
|
527
|
+
return new ValueExpression(true);
|
|
528
|
+
}
|
|
529
|
+
/**
|
|
530
|
+
* @override
|
|
531
|
+
*/
|
|
532
|
+
visitCesql(ctx) {
|
|
533
|
+
return this.visit(ctx.children[0]);
|
|
534
|
+
}
|
|
535
|
+
/**
|
|
536
|
+
* @override
|
|
537
|
+
*/
|
|
538
|
+
visitFunctionInvocationExpression(ctx) {
|
|
539
|
+
let args = [];
|
|
540
|
+
for (let i = 1; i < ctx.childCount; i += 2) {
|
|
541
|
+
args.push(...this.visit(ctx.children[i]));
|
|
542
|
+
}
|
|
543
|
+
return new FunctionExpression(ctx.children[0].text, ...args).resolve();
|
|
544
|
+
}
|
|
545
|
+
/**
|
|
546
|
+
* @override
|
|
547
|
+
*/
|
|
548
|
+
visitUnaryLogicExpression(ctx) {
|
|
549
|
+
return new UnaryLogicExpression(this.getChildrenResults(ctx)[1]).resolve();
|
|
550
|
+
}
|
|
551
|
+
/**
|
|
552
|
+
* @override
|
|
553
|
+
*/
|
|
554
|
+
visitUnaryNumericExpression(ctx) {
|
|
555
|
+
return new UnaryNumericExpression(this.getChildrenResults(ctx)[1]).resolve();
|
|
556
|
+
}
|
|
557
|
+
/**
|
|
558
|
+
* @override
|
|
559
|
+
*/
|
|
560
|
+
visitLikeExpression(ctx) {
|
|
561
|
+
const [left, regexp] = [this.visit(ctx.children[0]), ctx.children[ctx.children.length - 1].text];
|
|
562
|
+
return new LikeExpression(left, regexp, ctx.childCount === 4).resolve();
|
|
563
|
+
}
|
|
564
|
+
/**
|
|
565
|
+
* @override
|
|
566
|
+
*/
|
|
567
|
+
visitExistsExpression(ctx) {
|
|
568
|
+
let results = this.getChildrenResults(ctx);
|
|
569
|
+
return new ExistsExpression(results[1]).resolve();
|
|
570
|
+
}
|
|
571
|
+
/**
|
|
572
|
+
* @override
|
|
573
|
+
*/
|
|
574
|
+
visitInExpression(ctx) {
|
|
575
|
+
let results = this.getChildrenResults(ctx);
|
|
576
|
+
if (ctx.childCount === 4) {
|
|
577
|
+
return new InExpression(results[0], results[3], true).resolve();
|
|
578
|
+
}
|
|
579
|
+
return new InExpression(results[0], results[2]).resolve();
|
|
580
|
+
}
|
|
581
|
+
/**
|
|
582
|
+
* @override
|
|
583
|
+
*/
|
|
584
|
+
visitBinaryMultiplicativeExpression(ctx) {
|
|
585
|
+
let [left, op, right] = [this.visit(ctx.children[0]), ctx.children[1].text, this.visit(ctx.children[2])];
|
|
586
|
+
/* istanbul ignore next */
|
|
587
|
+
if (!["*", "/", "%"].includes(op)) {
|
|
588
|
+
throw new Error("Not implemented");
|
|
589
|
+
}
|
|
590
|
+
return new BinaryMultiplicativeExpression(left, right, op).resolve();
|
|
591
|
+
}
|
|
592
|
+
/**
|
|
593
|
+
* @override
|
|
594
|
+
*/
|
|
595
|
+
visitBinaryAdditiveExpression(ctx) {
|
|
596
|
+
let [left, op, right] = [this.visit(ctx.children[0]), ctx.children[1].text, this.visit(ctx.children[2])];
|
|
597
|
+
/* istanbul ignore next */
|
|
598
|
+
if (!["+", "-"].includes(op)) {
|
|
599
|
+
throw new Error("Not implemented");
|
|
600
|
+
}
|
|
601
|
+
return new BinaryAdditiveExpression(left, right, op).resolve();
|
|
602
|
+
}
|
|
603
|
+
/**
|
|
604
|
+
* Retrieve the children results
|
|
605
|
+
* @param ctx
|
|
606
|
+
* @returns
|
|
607
|
+
*/
|
|
608
|
+
getChildrenResults(ctx) {
|
|
609
|
+
return ctx.children.map((c) => this.visit(c));
|
|
610
|
+
}
|
|
611
|
+
/**
|
|
612
|
+
*
|
|
613
|
+
* @param ctx
|
|
614
|
+
* @returns
|
|
615
|
+
*/
|
|
616
|
+
visitBinaryComparisonExpression(ctx) {
|
|
617
|
+
let [left, op, right] = [this.visit(ctx.children[0]), ctx.children[1].text, this.visit(ctx.children[2])];
|
|
618
|
+
/* istanbul ignore next */
|
|
619
|
+
if (!["<", ">", "<=", ">=", "!=", "="].includes(op)) {
|
|
620
|
+
throw new Error("Not implemented");
|
|
621
|
+
}
|
|
622
|
+
return new BinaryComparisonExpression(left, right, op).resolve();
|
|
623
|
+
}
|
|
624
|
+
/**
|
|
625
|
+
* @override
|
|
626
|
+
*/
|
|
627
|
+
visitBinaryLogicExpression(ctx) {
|
|
628
|
+
let [left, op, right] = [this.visit(ctx.children[0]), ctx.children[1].text, this.visit(ctx.children[2])];
|
|
629
|
+
/* istanbul ignore next */
|
|
630
|
+
if (!["AND", "OR", "XOR"].includes(op)) {
|
|
631
|
+
throw new Error("Not implemented");
|
|
632
|
+
}
|
|
633
|
+
return new BinaryLogicExpression(left, right, op).resolve();
|
|
634
|
+
}
|
|
635
|
+
/**
|
|
636
|
+
* @override
|
|
637
|
+
*/
|
|
638
|
+
visitSubExpression(ctx) {
|
|
639
|
+
return this.visit(ctx.children[1]);
|
|
640
|
+
}
|
|
641
|
+
/**
|
|
642
|
+
* @override
|
|
643
|
+
*/
|
|
644
|
+
visitIdentifier(ctx) {
|
|
645
|
+
return new AttributeExpression(ctx.text);
|
|
646
|
+
}
|
|
647
|
+
/**
|
|
648
|
+
* @override
|
|
649
|
+
*/
|
|
650
|
+
visitBooleanLiteral(ctx) {
|
|
651
|
+
return new ValueExpression(ctx.text === "TRUE");
|
|
652
|
+
}
|
|
653
|
+
/**
|
|
654
|
+
* @override
|
|
655
|
+
*/
|
|
656
|
+
visitStringLiteral(ctx) {
|
|
657
|
+
// Remove quotes
|
|
658
|
+
return new ValueExpression(ctx.text.substr(1, ctx.text.length - 2));
|
|
659
|
+
}
|
|
660
|
+
/**
|
|
661
|
+
* @override
|
|
662
|
+
*/
|
|
663
|
+
visitIntegerLiteral(ctx) {
|
|
664
|
+
return new ValueExpression(Number(ctx.text));
|
|
665
|
+
}
|
|
666
|
+
/**
|
|
667
|
+
* @override
|
|
668
|
+
*/
|
|
669
|
+
visitFunctionParameterList(ctx) {
|
|
670
|
+
// Only take the odd part LBRACKET exp1 COMMA exp2 RBRACKET
|
|
671
|
+
return this.getChildrenResults(ctx).filter((_, i) => i % 2);
|
|
672
|
+
}
|
|
673
|
+
/**
|
|
674
|
+
* @override
|
|
675
|
+
*/
|
|
676
|
+
visitSetExpression(ctx) {
|
|
677
|
+
// Only take the odd part LBRACKET exp1 COMMA exp2 RBRACKET
|
|
678
|
+
return this.getChildrenResults(ctx)
|
|
679
|
+
.filter((_, i) => i % 2)
|
|
680
|
+
.map(e => e.resolve());
|
|
681
|
+
}
|
|
682
|
+
}
|
|
683
|
+
/**
|
|
684
|
+
* SQL Filter implementation
|
|
685
|
+
*/
|
|
686
|
+
export class SqlFilterImplementation extends FilterImplementation {
|
|
687
|
+
/**
|
|
688
|
+
*
|
|
689
|
+
* @param definition {sql: "CESQL Expression"}
|
|
690
|
+
*/
|
|
691
|
+
constructor(definition) {
|
|
692
|
+
super(definition);
|
|
693
|
+
this.lexer = new CESQLParserLexer(new ANTLRInputStream(definition.sql));
|
|
694
|
+
let tokenStream = new CommonTokenStream(this.lexer);
|
|
695
|
+
let parser = new CESQLParserParser(tokenStream);
|
|
696
|
+
// Parse the input, where `compilationUnit` is whatever entry point you defined
|
|
697
|
+
this.tree = parser.cesql();
|
|
698
|
+
this.query = new CESQLExpressionBuilder().visit(this.tree);
|
|
699
|
+
// Display query post optimization
|
|
700
|
+
// console.log("SQL", definition.sql, " => ", this.query.toString());
|
|
701
|
+
}
|
|
702
|
+
/**
|
|
703
|
+
* Check if a cloudevent match the filter
|
|
704
|
+
* @param event
|
|
705
|
+
* @returns
|
|
706
|
+
*/
|
|
707
|
+
match(event) {
|
|
708
|
+
return this.query.eval(event);
|
|
709
|
+
}
|
|
710
|
+
/**
|
|
711
|
+
* Some filter can be optimized into a simpler form
|
|
712
|
+
*
|
|
713
|
+
* Samples:
|
|
714
|
+
* LEFT(a, 3) = "foo" => prefix: {a: "foo"}
|
|
715
|
+
* RIGHT(a, 3) = "foo" => suffix: {a: "foo"}
|
|
716
|
+
* a = "foo" => exact: {a: "foo"}
|
|
717
|
+
*
|
|
718
|
+
* @returns
|
|
719
|
+
*/
|
|
720
|
+
optimize() {
|
|
721
|
+
if (this.query instanceof BinaryComparisonExpression &&
|
|
722
|
+
this.query.operator === "=" &&
|
|
723
|
+
this.query.right instanceof ValueExpression) {
|
|
724
|
+
if (this.query.left instanceof AttributeExpression) {
|
|
725
|
+
return new ExactFilterImplementation({
|
|
726
|
+
exact: {
|
|
727
|
+
[this.query.left.attribute]: this.query.right.value
|
|
728
|
+
}
|
|
729
|
+
});
|
|
730
|
+
}
|
|
731
|
+
else if (this.query.left instanceof FunctionExpression &&
|
|
732
|
+
this.query.left.args[0] instanceof AttributeExpression) {
|
|
733
|
+
if (this.query.left.functionName === "LEFT") {
|
|
734
|
+
return new PrefixFilterImplementation({
|
|
735
|
+
prefix: {
|
|
736
|
+
[this.query.left.args[0].attribute]: this.query.right.value
|
|
737
|
+
}
|
|
738
|
+
});
|
|
739
|
+
}
|
|
740
|
+
else if (this.query.left.functionName === "RIGHT") {
|
|
741
|
+
return new SuffixFilterImplementation({
|
|
742
|
+
suffix: {
|
|
743
|
+
[this.query.left.args[0].attribute]: this.query.right.value
|
|
744
|
+
}
|
|
745
|
+
});
|
|
746
|
+
}
|
|
747
|
+
}
|
|
748
|
+
}
|
|
749
|
+
return this;
|
|
750
|
+
}
|
|
751
|
+
}
|
|
752
|
+
//# sourceMappingURL=sql.js.map
|