From e993e9483a9daf0e0f603362d31fbc231a344ab7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dennis=20Du=20Kr=C3=B8ger?= Date: Tue, 12 Jul 2016 16:28:00 +0200 Subject: [PATCH 1/2] METAMODEL-1103: Anchor WildcardPattern to start This makes sure the WildcardPattern anchors its test to the start of the string, not only the end. This comes with a minor performance penalty (quick test said 5-10% ), but I think correctness trumps speed here. I would have liked to compare speed with pre-compiled regexes (`Pattern.quote()` the operand, replace `%` with `.*?` and anchor it with `^` and `$`), but if the LIKE operand is inside a SelectItem, that would mean compiling a new regex pattern for every row, which would probably be _very_ expensive, so I opted not to try. There seem to be some similar optimization of the IN operator, so I might be wrong. Fixes METAMODEL-1103 --- .../java/org/apache/metamodel/util/WildcardPattern.java | 7 +++++-- .../org/apache/metamodel/util/WildcardPatternTest.java | 7 +++++++ 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/core/src/main/java/org/apache/metamodel/util/WildcardPattern.java b/core/src/main/java/org/apache/metamodel/util/WildcardPattern.java index 648c2cac8..9ddeceffb 100644 --- a/core/src/main/java/org/apache/metamodel/util/WildcardPattern.java +++ b/core/src/main/java/org/apache/metamodel/util/WildcardPattern.java @@ -32,13 +32,15 @@ public final class WildcardPattern implements Serializable { private static final long serialVersionUID = 857462137797209624L; + private final boolean _startsWithDelim; + private final boolean _endsWithDelim; private String _pattern; private char _wildcard; - private boolean _endsWithDelim; public WildcardPattern(String pattern, char wildcard) { _pattern = pattern; _wildcard = wildcard; + _startsWithDelim = (_pattern.charAt(0) == _wildcard); _endsWithDelim = (_pattern.charAt(pattern.length() - 1) == _wildcard); } @@ -50,9 +52,10 @@ public boolean matches(String value) { Character.toString(_wildcard)); int charIndex = 0; while (st.hasMoreTokens()) { + int oldIndex = charIndex; String token = st.nextToken(); charIndex = value.indexOf(token, charIndex); - if (charIndex == -1) { + if (charIndex == -1 || !_startsWithDelim && oldIndex == 0 && charIndex != 0) { return false; } charIndex = charIndex + token.length(); diff --git a/core/src/test/java/org/apache/metamodel/util/WildcardPatternTest.java b/core/src/test/java/org/apache/metamodel/util/WildcardPatternTest.java index 1e075dd0d..987842541 100644 --- a/core/src/test/java/org/apache/metamodel/util/WildcardPatternTest.java +++ b/core/src/test/java/org/apache/metamodel/util/WildcardPatternTest.java @@ -41,5 +41,12 @@ public void testMatches() throws Exception { assertTrue(pattern.matches("foobarbar")); assertFalse(pattern.matches("w00p")); + pattern = new WildcardPattern("oba%", '%'); + assertTrue(pattern.matches("obar")); + assertFalse(pattern.matches("foobar")); + + pattern = new WildcardPattern("bar", '%'); + assertTrue(pattern.matches("bar")); + assertFalse(pattern.matches("foobar")); } } \ No newline at end of file From 49d7a5cddab34cd85fb01385d97450998064dcef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dennis=20Du=20Kr=C3=B8ger?= Date: Wed, 13 Jul 2016 08:52:25 +0200 Subject: [PATCH 2/2] Support the empty pattern Make sure that the empty pattern doesn't break. --- .../java/org/apache/metamodel/util/WildcardPattern.java | 8 ++++++-- .../org/apache/metamodel/util/WildcardPatternTest.java | 4 ++++ 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/core/src/main/java/org/apache/metamodel/util/WildcardPattern.java b/core/src/main/java/org/apache/metamodel/util/WildcardPattern.java index 9ddeceffb..715e0d2a1 100644 --- a/core/src/main/java/org/apache/metamodel/util/WildcardPattern.java +++ b/core/src/main/java/org/apache/metamodel/util/WildcardPattern.java @@ -40,8 +40,12 @@ public final class WildcardPattern implements Serializable { public WildcardPattern(String pattern, char wildcard) { _pattern = pattern; _wildcard = wildcard; - _startsWithDelim = (_pattern.charAt(0) == _wildcard); - _endsWithDelim = (_pattern.charAt(pattern.length() - 1) == _wildcard); + if(_pattern.isEmpty()){ + _startsWithDelim = _endsWithDelim = false; + } else { + _startsWithDelim = _pattern.charAt(0) == _wildcard; + _endsWithDelim = _pattern.charAt(pattern.length() - 1) == _wildcard; + } } public boolean matches(String value) { diff --git a/core/src/test/java/org/apache/metamodel/util/WildcardPatternTest.java b/core/src/test/java/org/apache/metamodel/util/WildcardPatternTest.java index 987842541..4bc45f7fc 100644 --- a/core/src/test/java/org/apache/metamodel/util/WildcardPatternTest.java +++ b/core/src/test/java/org/apache/metamodel/util/WildcardPatternTest.java @@ -48,5 +48,9 @@ public void testMatches() throws Exception { pattern = new WildcardPattern("bar", '%'); assertTrue(pattern.matches("bar")); assertFalse(pattern.matches("foobar")); + + pattern = new WildcardPattern("", '%'); + assertTrue(pattern.matches("")); + assertFalse(pattern.matches("foo")); } } \ No newline at end of file