Rikkola opened a new issue, #2344:
URL: https://github.com/apache/incubator-kie-issues/issues/2344
When an executable-model rule contains a top-level or(...) whose branch is a
join containing a negation (and(not(x), y)), and a later pattern carries a
temporal after constraint, the rule throws an NPE during fact evaluation.
The
DRL path is unaffected (its parser expands disjunctions into separate rules
before compilation); the bug is specific to the model→KiePackage
compilation
path.
Symptom
```
org.drools.modelcompiler.constraints.ConstraintEvaluationException:
Error evaluating constraint '' in and in more rules
at LambdaConstraint.isAllowedCachedLeft(LambdaConstraint.java:222)
at SingleBetaConstraints.isAllowedCachedLeft(...)
at PhreakJoinNode.doLeftInserts(PhreakJoinNode.java:118)
...
Caused by: java.lang.NullPointerException:
Cannot invoke "org.drools.core.reteoo.TupleImpl.getIndex()" because
"entry" is null
at org.drools.core.reteoo.TupleImpl.get(TupleImpl.java:274)
at
TemporalConstraintEvaluator.getBetaInvocationFactHandles(TemporalConstra
intEvaluator.java:70)
at
TemporalConstraintEvaluator.evaluate(TemporalConstraintEvaluator.java:50)
```
Minimal reproducer (executable model, STREAM)
```
// Event types with @Role(EVENT): EvE, EvC, EvD
Variable<EvE> e1 = declarationOf(EvE.class);
Variable<EvE> e2 = declarationOf(EvE.class);
Variable<EvC> c = declarationOf(EvC.class);
Variable<EvE> et = declarationOf(EvE.class);
Variable<EvD> d = declarationOf(EvD.class);
Rule r = rule("min-or-negjoin-after").build(
or(
pattern(e1).expr("e1", v -> true),
and(not(pattern(e2).expr("e2", v -> true)), // OR branch is a
negated join
pattern(c).expr("c", v -> true))
),
pattern(et).expr("et", v -> true),
pattern(d).expr("d", v -> true).expr("d_after_et", et, after()), //
downstream temporal beta
execute(() -> {})
);
```
// build STREAM KieBase, insert a few events of each type, fireAllRules()
->
NPE
Both ingredients are required (each removed individually makes it pass):
- a bare or(pattern, pattern) does not trigger it,
- a lone not(...) branch does not,
- the negated join without the OR does not,
- the OR + negated join without the downstream after does not.
Root cause
When the LHS or is expanded into per-branch subrules (LogicTransformer),
the
shared trailing elements (here ET and D after ET) are cloned into each
subrule, and each clone's declarations are independently rebound to its own
subrule's patterns via Constraint.replaceDeclaration (which reassigns a
slot
in the evaluator's declarations[] array).
TemporalConstraintEvaluator.clone() passed the original declarations array
by
reference (getDeclarations()) instead of copying it, so all clones shared
one array. The last subrule's rebinding therefore clobbered the others,
leaving the narrow branch's D after ET pointing at the wide branch's ET
pattern (tuple index 3) — an index absent from the narrow branch's 2-deep
tuple, so TupleImpl.get walks off the parent chain and dereferences a null
entry.
(Equal-width OR branches mask the bug, since the shared index stays valid —
which is why a plain or(pattern, pattern) doesn't reproduce.)
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]