@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.
Files changed (35) hide show
  1. package/LICENSE +166 -0
  2. package/lib/filters/abstract.d.ts +28 -0
  3. package/lib/filters/abstract.js +17 -0
  4. package/lib/filters/abstract.js.map +1 -0
  5. package/lib/filters/index.d.ts +14 -0
  6. package/lib/filters/index.js +34 -0
  7. package/lib/filters/index.js.map +1 -0
  8. package/lib/filters/interfaces.d.ts +0 -0
  9. package/lib/filters/interfaces.js +1 -0
  10. package/lib/filters/interfaces.js.map +1 -0
  11. package/lib/filters/logical.d.ts +54 -0
  12. package/lib/filters/logical.js +49 -0
  13. package/lib/filters/logical.js.map +1 -0
  14. package/lib/filters/sql/CESQLParserLexer.d.ts +55 -0
  15. package/lib/filters/sql/CESQLParserLexer.js +293 -0
  16. package/lib/filters/sql/CESQLParserLexer.js.map +1 -0
  17. package/lib/filters/sql/CESQLParserListener.d.ts +325 -0
  18. package/lib/filters/sql/CESQLParserListener.js +3 -0
  19. package/lib/filters/sql/CESQLParserListener.js.map +1 -0
  20. package/lib/filters/sql/CESQLParserParser.d.ts +313 -0
  21. package/lib/filters/sql/CESQLParserParser.js +1825 -0
  22. package/lib/filters/sql/CESQLParserParser.js.map +1 -0
  23. package/lib/filters/sql/CESQLParserVisitor.d.ts +208 -0
  24. package/lib/filters/sql/CESQLParserVisitor.js +3 -0
  25. package/lib/filters/sql/CESQLParserVisitor.js.map +1 -0
  26. package/lib/filters/sql.d.ts +426 -0
  27. package/lib/filters/sql.js +752 -0
  28. package/lib/filters/sql.js.map +1 -0
  29. package/lib/filters/string.d.ts +105 -0
  30. package/lib/filters/string.js +79 -0
  31. package/lib/filters/string.js.map +1 -0
  32. package/lib/subscription.d.ts +228 -0
  33. package/lib/subscription.js +60 -0
  34. package/lib/subscription.js.map +1 -0
  35. 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