This is an automated email from the ASF dual-hosted git repository. vavrtom pushed a commit to branch main in repository https://gitbox.apache.org/repos/asf/qpid-broker-j.git
The following commit(s) were added to refs/heads/main by this push: new ed0ca8759a QPID-8691: [Broker-J] Increased CPU usage during query evaluation (#277) ed0ca8759a is described below commit ed0ca8759ae79b597c889d14a468107944641d34 Author: Daniil Kirilyuk <daniel.kiril...@gmail.com> AuthorDate: Wed Apr 30 15:27:22 2025 +0200 QPID-8691: [Broker-J] Increased CPU usage during query evaluation (#277) --- .../qpid/server/filter/ComparisonExpression.java | 7 ++++++ .../server/filter/JMSSelectorFilterSyntaxTest.java | 4 ++++ .../expression/comparison/LikeExpression.java | 25 +++++++++++++++++----- .../expression/comparison/LikeExpressionTest.java | 9 ++++++++ 4 files changed, 40 insertions(+), 5 deletions(-) diff --git a/broker-core/src/main/java/org/apache/qpid/server/filter/ComparisonExpression.java b/broker-core/src/main/java/org/apache/qpid/server/filter/ComparisonExpression.java index 84bf9e05f5..0d275c06c8 100644 --- a/broker-core/src/main/java/org/apache/qpid/server/filter/ComparisonExpression.java +++ b/broker-core/src/main/java/org/apache/qpid/server/filter/ComparisonExpression.java @@ -71,6 +71,8 @@ public abstract class ComparisonExpression<T> extends BinaryExpression<T> implem static class LikeExpression<E> extends UnaryExpression<E> implements BooleanExpression<E> { + /** Repeated wildcards pattern */ + private static final Pattern REPEATED_WILDCARDS = Pattern.compile("%{2,}"); private final Pattern likePattern; @@ -78,6 +80,11 @@ public abstract class ComparisonExpression<T> extends BinaryExpression<T> implem { super(right); + if (like.contains("%%")) + { + like = REPEATED_WILDCARDS.matcher(like).replaceAll("%"); + } + StringBuilder regexp = new StringBuilder(like.length() * 2); regexp.append("\\A"); // The beginning of the input for (int i = 0; i < like.length(); i++) diff --git a/broker-core/src/test/java/org/apache/qpid/server/filter/JMSSelectorFilterSyntaxTest.java b/broker-core/src/test/java/org/apache/qpid/server/filter/JMSSelectorFilterSyntaxTest.java index 26545f5d81..e42733bd43 100644 --- a/broker-core/src/test/java/org/apache/qpid/server/filter/JMSSelectorFilterSyntaxTest.java +++ b/broker-core/src/test/java/org/apache/qpid/server/filter/JMSSelectorFilterSyntaxTest.java @@ -385,6 +385,8 @@ class JMSSelectorFilterSyntaxTest when(message.getHeader("entry")).thenReturn("aaa"); assertTrue(new JMSSelectorFilter("entry like '%aaa%'").matches(message)); + + assertTrue(new JMSSelectorFilter("entry like '%%%%%%%%%%%'").matches(message)); } @Test @@ -408,6 +410,8 @@ class JMSSelectorFilterSyntaxTest assertFalse(new JMSSelectorFilter("NOT entry LIKE '%aaa%'").matches(message)); assertTrue(new JMSSelectorFilter("NOT (entry NOT LIKE '%aaa%')").matches(message)); assertTrue(new JMSSelectorFilter("NOT entry NOT LIKE '%aaa%'").matches(message)); + + assertFalse(new JMSSelectorFilter("entry not like '%%%%%%%%%%%aaa%%%%%%%%%%%'").matches(message)); } @Test diff --git a/broker-plugins/query-engine/src/main/java/org/apache/qpid/server/query/engine/parsing/expression/comparison/LikeExpression.java b/broker-plugins/query-engine/src/main/java/org/apache/qpid/server/query/engine/parsing/expression/comparison/LikeExpression.java index e020e8aa58..85cb821a8c 100644 --- a/broker-plugins/query-engine/src/main/java/org/apache/qpid/server/query/engine/parsing/expression/comparison/LikeExpression.java +++ b/broker-plugins/query-engine/src/main/java/org/apache/qpid/server/query/engine/parsing/expression/comparison/LikeExpression.java @@ -39,6 +39,9 @@ import org.apache.qpid.server.query.engine.validation.FunctionParameterTypePredi @SuppressWarnings("java:S116") public class LikeExpression<T, R> extends AbstractComparisonExpression<T, Boolean> { + /** Repeated wildcards pattern */ + private static final Pattern REPEATED_WILDCARDS = Pattern.compile("%{2,}"); + /** * Argument type validator */ @@ -51,6 +54,16 @@ public class LikeExpression<T, R> extends AbstractComparisonExpression<T, Boolea .allowStrings() .build(); + /** Merges a sequence of '%' into a single '%' */ + private static <X> ExpressionNode<X, ?> toConstantExpression(String source) + { + if (source.contains("%%")) + { + source = REPEATED_WILDCARDS.matcher(source).replaceAll("%"); + } + return new ConstantExpression<>(source); + } + /** * Constructor initializes children expression list * @@ -60,7 +73,7 @@ public class LikeExpression<T, R> extends AbstractComparisonExpression<T, Boolea */ public LikeExpression(final ExpressionNode<T, R> left, final String source, final String escape) { - super("", left, new ConstantExpression<>(source), new ConstantExpression<>(escape)); + super("", left, toConstantExpression(source), new ConstantExpression<>(escape)); } /** @@ -97,13 +110,15 @@ public class LikeExpression<T, R> extends AbstractComparisonExpression<T, Boolea * * @return Regex pattern */ - private Pattern sqlPatternToRegex(final String pattern, final String escape) { - - if (pattern == null) { + private Pattern sqlPatternToRegex(final String pattern, final String escape) + { + if (pattern == null) + { throw new IllegalArgumentException("Null pattern"); } - if (pattern.length() == 0) { + if (pattern.length() == 0) + { throw new IllegalArgumentException("Empty pattern"); } diff --git a/broker-plugins/query-engine/src/test/java/org/apache/qpid/server/query/engine/parsing/expression/comparison/LikeExpressionTest.java b/broker-plugins/query-engine/src/test/java/org/apache/qpid/server/query/engine/parsing/expression/comparison/LikeExpressionTest.java index 9dfb252d37..a878aedfb1 100644 --- a/broker-plugins/query-engine/src/test/java/org/apache/qpid/server/query/engine/parsing/expression/comparison/LikeExpressionTest.java +++ b/broker-plugins/query-engine/src/test/java/org/apache/qpid/server/query/engine/parsing/expression/comparison/LikeExpressionTest.java @@ -250,4 +250,13 @@ public class LikeExpressionTest assertEquals(1, result.size()); assertEquals(false, result.get(0).get("result")); } + + @Test() + public void repeatedWildcards() + { + String query = "select 'test' like 't%%%' as result"; + List<Map<String, Object>> result = _queryEvaluator.execute(query).getResults(); + assertEquals(1, result.size()); + assertEquals(true, result.get(0).get("result")); + } } --------------------------------------------------------------------- To unsubscribe, e-mail: commits-unsubscr...@qpid.apache.org For additional commands, e-mail: commits-h...@qpid.apache.org