Fix like expression (#381) (#385)

Signed-off-by: Francesco Guardiani <francescoguard@gmail.com>
(cherry picked from commit 9d45943844)
This commit is contained in:
Francesco Guardiani 2021-05-06 14:15:25 +02:00 committed by GitHub
parent dc3e4c7a66
commit cc426ffd61
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 51 additions and 7 deletions

View File

@ -17,12 +17,7 @@ public class LikeExpression extends BaseExpression {
super(expressionInterval, expressionText);
this.internal = internal;
// Converting to regex is not the most performant impl, but it works
this.pattern = Pattern.compile("^" +
pattern.replaceAll("(?<!\\\\)\\%", ".*")
.replaceAll("(?<!\\\\)\\_", ".")
.replaceAll("\\\\\\%", "%")
.replaceAll("\\\\_", "_") + "$"
);
this.pattern = convertLikePatternToRegex(pattern);
}
@Override
@ -35,4 +30,38 @@ public class LikeExpression extends BaseExpression {
return pattern.matcher(value).matches();
}
private Pattern convertLikePatternToRegex(String pattern) {
StringBuilder builder = new StringBuilder();
builder.append("^\\Q");
for (int i = 0; i < pattern.length(); i++) {
if (pattern.charAt(i) == '\\' && i < pattern.length() - 1) {
if (pattern.charAt(i + 1) == '%') {
// \% case
builder.append('%');
i++;
continue;
} else if (pattern.charAt(i + 1) == '_') {
// \_ case
builder.append('_');
i++;
continue;
}
}
if (pattern.charAt(i) == '_') {
// replace with .
builder.append("\\E.\\Q");
} else if (pattern.charAt(i) == '%') {
// replace with .*
builder.append("\\E.*\\Q");
} else {
builder.append(pattern.charAt(i));
}
}
builder.append("\\E$");
return Pattern.compile(builder.toString());
}
}

View File

@ -1,8 +1,11 @@
name: Like expression
tests:
- name: Exact match
- name: Exact match (1)
expression: "'abc' LIKE 'abc'"
result: true
- name: Exact match (2)
expression: "'ab\\c' LIKE 'ab\\c'"
result: true
- name: Exact match (negate)
expression: "'abc' NOT LIKE 'abc'"
result: false
@ -25,6 +28,12 @@ tests:
- name: Percentage operator (6)
expression: "'' LIKE 'abc'"
result: false
- name: Percentage operator (7)
expression: "'.ab.cde.' LIKE '.%.%.'"
result: true
- name: Percentage operator (8)
expression: "'ab.cde' LIKE '.%.%.'"
result: false
- name: Underscore operator (1)
expression: "'abc' LIKE 'a_b_c'"
@ -41,6 +50,12 @@ tests:
- name: Underscore operator (5)
expression: "'azbzc' LIKE 'a_b_c'"
result: true
- name: Underscore operator (6)
expression: "'.a.b.' LIKE '._._.'"
result: true
- name: Underscore operator (7)
expression: "'abcd.' LIKE '._._.'"
result: false
- name: Escaped underscore wildcards (1)
expression: "'a_b_c' LIKE 'a\\_b\\_c'"