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 <[email protected]>
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: [email protected]
For additional commands, e-mail: [email protected]