This is an automated email from the ASF dual-hosted git repository.
yesamer pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/incubator-kie.git
The following commit(s) were added to refs/heads/main by this push:
new 9b055f0c6c9 [incubator-kie#7144] fix(drools): keep contains on a
generic Map.get() String matching after jitting (#7145)
9b055f0c6c9 is described below
commit 9b055f0c6c94287602c4bdc9e29de4308d42ed72
Author: Andrii Tsepukh <[email protected]>
AuthorDate: Wed Sep 30 10:10:11 2026 +0200
[incubator-kie#7144] fix(drools): keep contains on a generic Map.get()
String matching after jitting (#7145)
PatternBuilder resolves Map<K, String>.get(...) to String from the
generics, so the build accepts `contains` on it. The interpreted MVEL
evaluator then does a substring check on the runtime String. Once the
constraint is jitted, ASMConditionEvaluatorJitter sees the erased
Object type and emits EvaluatorHelper.contains(Object, Object), which
handled only collections and arrays and returned false for a String.
The rule matched for the first drools.jittingThreshold evaluations and
stopped matching after that.
EvaluatorHelper.contains(Object, Object) now does the same String check
as ParseTools.containsCheck, so the jitted and interpreted evaluators
agree.
Co-authored-by: AndriiTsepukh <[email protected]>
Co-authored-by: Claude Opus 5.5 <[email protected]>
---
.../main/java/org/drools/mvel/EvaluatorHelper.java | 3 +++
.../drools/mvel/integrationtests/JittingTest.java | 30 ++++++++++++++++++++++
2 files changed, 33 insertions(+)
diff --git a/drools-mvel/src/main/java/org/drools/mvel/EvaluatorHelper.java
b/drools-mvel/src/main/java/org/drools/mvel/EvaluatorHelper.java
index 30958340b73..6fd17b962f3 100644
--- a/drools-mvel/src/main/java/org/drools/mvel/EvaluatorHelper.java
+++ b/drools-mvel/src/main/java/org/drools/mvel/EvaluatorHelper.java
@@ -93,6 +93,9 @@ public class EvaluatorHelper {
return ((Collection)list).contains(item);
} else if (list instanceof Object[]) {
return arrayContains( ( Object[] ) list, item );
+ } else if (list instanceof String) {
+ // same check as the interpreted MVEL evaluator
+ return ((String) list).contains( String.valueOf( item ) );
} else if (item == null) {
return false;
} else if (list instanceof int[]) {
diff --git
a/drools-test-coverage/test-compiler-integration/src/test/java/org/drools/mvel/integrationtests/JittingTest.java
b/drools-test-coverage/test-compiler-integration/src/test/java/org/drools/mvel/integrationtests/JittingTest.java
index b66951c6c9d..528f90e292e 100644
---
a/drools-test-coverage/test-compiler-integration/src/test/java/org/drools/mvel/integrationtests/JittingTest.java
+++
b/drools-test-coverage/test-compiler-integration/src/test/java/org/drools/mvel/integrationtests/JittingTest.java
@@ -28,6 +28,7 @@ import java.util.stream.Stream;
import org.drools.mvel.compiler.Person;
import org.drools.mvel.integrationtests.facts.AnEnum;
import org.drools.mvel.integrationtests.facts.FactWithEnum;
+import org.drools.mvel.integrationtests.facts.FactWithMap;
import org.drools.testcoverage.common.util.KieBaseTestConfiguration;
import org.drools.testcoverage.common.util.KieBaseUtil;
import org.drools.testcoverage.common.util.KieUtil;
@@ -257,6 +258,35 @@ public class JittingTest {
assertThat(ksession.fireAllRules()).isEqualTo(expectedFires);
}
+ @ParameterizedTest(name = "KieBase type={0}")
+ @MethodSource("parameters")
+ public void testJitContainsOnStringTypedAsObject(KieBaseTestConfiguration
kieBaseTestConfiguration) {
+ // The build resolves itemsMap.get() to String from the generics; the
jitter sees the erased Object
+ checkJitContainsOnStringTypedAsObject(kieBaseTestConfiguration,
"itemsMap.get(1) contains \"T80011\"", 1);
+ checkJitContainsOnStringTypedAsObject(kieBaseTestConfiguration,
"itemsMap.get(1) contains \"T99999\"", 0);
+ checkJitContainsOnStringTypedAsObject(kieBaseTestConfiguration,
"itemsMap.get(1) not contains \"T80011\"", 0);
+ checkJitContainsOnStringTypedAsObject(kieBaseTestConfiguration,
"itemsMap.get(1) not contains \"T99999\"", 1);
+ }
+
+ private void
checkJitContainsOnStringTypedAsObject(KieBaseTestConfiguration
kieBaseTestConfiguration, String constraint, int expectedFires) {
+ String drl =
+ "import " + FactWithMap.class.getCanonicalName() + ";\n" +
+ "rule R when\n" +
+ " FactWithMap( " + constraint + " )\n" +
+ "then\n" +
+ "end\n";
+
+ final KieModule kieModule = KieUtil.getKieModuleFromDrls("test",
kieBaseTestConfiguration, drl);
+ final KieBase kieBase =
KieBaseUtil.newKieBaseFromKieModuleWithAdditionalOptions(kieModule,
kieBaseTestConfiguration, ConstraintJittingThresholdOption.get(0));
+ final KieSession ksession = kieBase.newKieSession();
+ try {
+ ksession.insert(new FactWithMap(1,
"FAILURE.T80011,FAILURE.T80012"));
+
assertThat(ksession.fireAllRules()).as(constraint).isEqualTo(expectedFires);
+ } finally {
+ ksession.dispose();
+ }
+ }
+
@ParameterizedTest(name = "KieBase type={0}")
@MethodSource("parameters")
public void testJittingBigDecimalAdd(KieBaseTestConfiguration
kieBaseTestConfiguration) {
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]