Skip to content

Commit 9d45943

Browse files
Fix like expression (#381)
Signed-off-by: Francesco Guardiani <[email protected]>
1 parent 0a1a03d commit 9d45943

File tree

2 files changed

+51
-7
lines changed

2 files changed

+51
-7
lines changed

sql/src/main/java/io/cloudevents/sql/impl/expressions/LikeExpression.java

Lines changed: 35 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,7 @@ public LikeExpression(Interval expressionInterval, String expressionText, Expres
1717
super(expressionInterval, expressionText);
1818
this.internal = internal;
1919
// Converting to regex is not the most performant impl, but it works
20-
this.pattern = Pattern.compile("^" +
21-
pattern.replaceAll("(?<!\\\\)\\%", ".*")
22-
.replaceAll("(?<!\\\\)\\_", ".")
23-
.replaceAll("\\\\\\%", "%")
24-
.replaceAll("\\\\_", "_") + "$"
25-
);
20+
this.pattern = convertLikePatternToRegex(pattern);
2621
}
2722

2823
@Override
@@ -35,4 +30,38 @@ public Object evaluate(EvaluationRuntime runtime, CloudEvent event, ExceptionThr
3530

3631
return pattern.matcher(value).matches();
3732
}
33+
34+
private Pattern convertLikePatternToRegex(String pattern) {
35+
StringBuilder builder = new StringBuilder();
36+
builder.append("^\\Q");
37+
38+
for (int i = 0; i < pattern.length(); i++) {
39+
if (pattern.charAt(i) == '\\' && i < pattern.length() - 1) {
40+
if (pattern.charAt(i + 1) == '%') {
41+
// \% case
42+
builder.append('%');
43+
i++;
44+
continue;
45+
} else if (pattern.charAt(i + 1) == '_') {
46+
// \_ case
47+
builder.append('_');
48+
i++;
49+
continue;
50+
}
51+
}
52+
if (pattern.charAt(i) == '_') {
53+
// replace with .
54+
builder.append("\\E.\\Q");
55+
} else if (pattern.charAt(i) == '%') {
56+
// replace with .*
57+
builder.append("\\E.*\\Q");
58+
} else {
59+
builder.append(pattern.charAt(i));
60+
}
61+
}
62+
63+
builder.append("\\E$");
64+
65+
return Pattern.compile(builder.toString());
66+
}
3867
}

sql/src/test/resources/tck/like_expression.yaml

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
11
name: Like expression
22
tests:
3-
- name: Exact match
3+
- name: Exact match (1)
44
expression: "'abc' LIKE 'abc'"
55
result: true
6+
- name: Exact match (2)
7+
expression: "'ab\\c' LIKE 'ab\\c'"
8+
result: true
69
- name: Exact match (negate)
710
expression: "'abc' NOT LIKE 'abc'"
811
result: false
@@ -25,6 +28,12 @@ tests:
2528
- name: Percentage operator (6)
2629
expression: "'' LIKE 'abc'"
2730
result: false
31+
- name: Percentage operator (7)
32+
expression: "'.ab.cde.' LIKE '.%.%.'"
33+
result: true
34+
- name: Percentage operator (8)
35+
expression: "'ab.cde' LIKE '.%.%.'"
36+
result: false
2837

2938
- name: Underscore operator (1)
3039
expression: "'abc' LIKE 'a_b_c'"
@@ -41,6 +50,12 @@ tests:
4150
- name: Underscore operator (5)
4251
expression: "'azbzc' LIKE 'a_b_c'"
4352
result: true
53+
- name: Underscore operator (6)
54+
expression: "'.a.b.' LIKE '._._.'"
55+
result: true
56+
- name: Underscore operator (7)
57+
expression: "'abcd.' LIKE '._._.'"
58+
result: false
4459

4560
- name: Escaped underscore wildcards (1)
4661
expression: "'a_b_c' LIKE 'a\\_b\\_c'"

0 commit comments

Comments
 (0)