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

Reply via email to