-
Notifications
You must be signed in to change notification settings - Fork 9
How beta range index works
As of drools 7.47.0.Final, beta range index works only for ExistsNode and NotNode.
rule R1
when
$s : String()
exists Cheese( type > $s )
then
end
ksession.insert("cheddar");
ksession.insert("gorgonzola");
ksession.insert("stilton");
ksession.insert(new Cheese("gorgonzola", 10));
Rule Build:
- PatternBuilder.buildConstraintForPattern() picks [$s] as declr.
- MVELConstraint [type > $s] is created. indexingDeclaration is [$s]
- ExistsNode is created.
- SingleBetaConstraints.initIndexes()
- IndexUtil.canHaveRangeIndex() returns true
- SingleBetaConstraints.indexed = true
- SingleBetaConstraints.initIndexes()
Runtime:
-
SingleBetaConstraints.createBetaMemory()
- IndexUtil$Factory$IndexSpec.init()
- MVELConstraint.getFieldIndex()
- new AbstractHashTable.FieldIndex(extractor, indexingDeclaration, PlainIndexEvaluator.INSTANCE);
- MVELConstraint.getFieldIndex()
- IndexUtil$Factory.createBetaMemory()
- IndexUtil$Factory.createLeftMemory()
- TupleIndexRBTree is created for leftMemory
- IndexUtil$Factory.createRightMemory()
- TupleIndexRBTree is created for rightMemory (left = false, AbstractHashTable$FieldIndex is the same as leftMemory)
- IndexUtil$Factory.createLeftMemory()
- IndexUtil$Factory$IndexSpec.init()
-
PhreakExistsNode.doRightInserts()
- rightTuple : RightTupleImpl(= Cheese "gorgonzola")
- TupleIndexRBTree.add(rightTuple) for rightMemory
- getLeftIndexedValue()
- getIndexedValue() : left = false
-
(Comparable) index.getExtractor().getValue( tuple.getFactHandle().getObject() );
- Get the value of Cheese.type (= "gorgonzola")
- this is the key to insert into the tree
- TupleList list = tree.insert(key);
- this TupleList is the Node of the tree
- list.add(tuple);
- So we can add multiple tuples for the same key
- getLeftIndexedValue()
-
PhreakExistsNode.doLeftInserts()
-
srcLeftTuples : "stilton", "gorgonzola", "cheddar"
-
Loop 1 : leftTuple : NotNodeLeftTuple (= "stilton")
-
RuleNetworkEvaluator.findLeftTupleBlocker()
- BetaNode.getFirstRightTuple() : This means, rightMemory is the tree. leftTuple is the key. So get the nearest rightTuple which matches the constraint [ type > $s (= leftTuple)]
- TupleIndexRBTree.getFirst()
- getRightIndexedValue() : NOTE that this inverses TupleIndexRBTree.left
- getIndexedValue() : left = true
-
(Comparable) index.getDeclaration().getExtractor().getValue( tuple.getObject( index.getDeclaration() ) ) :
- Get the object ("stilton") from NotNodeLeftTuple using declaration.getOffset(). This means it picks the expected value [$s]. (So, [$s] is "left")
- getRightIndexedValue() : NOTE that this inverses TupleIndexRBTree.left
- getNext() : key = "stilton", first = true
- getNextRight() : because this is rightMemory.
- GREATER_THAN :
-
firstNode = tree.findNearestNode(key, false, Boundary.LOWER);
- Boundary.LOWER means "If this key is lower than a treeNode, the treeNode matches"
- TupleRBTree.findNearestNode()
- compResult > 0 (<- "stilton" is larger than "gorgonzola")
- acceptNode() returns false
-
n = accepted ^ boundary == Boundary.LOWER ? n.right : n.left;
- true, so n.right. We want to traverse to upper nodes to find a match.
- but no more node, so returns null
- getNextRight() : because this is rightMemory.
-
So RuleNetworkEvaluator.findLeftTupleBlocker() doesn't find a blocker.
-
ltm.add(leftTuple);
- TupleIndexRBTree.add(leftTuple) for leftMemory
- getLeftIndexedValue()
- getIndexedValue() : left = true
-
(Comparable) index.getDeclaration().getExtractor().getValue( tuple.getObject( index.getDeclaration() ) ) :
- Get the object ("stilton") from NotNodeLeftTuple using declaration.getOffset(). This means it picks the expected value [$s]. (So, [$s] is "left")
- getLeftIndexedValue()
- TupleList list = tree.insert(key);
- So leftMemory tree is also maintained
- TupleIndexRBTree.add(leftTuple) for leftMemory
-
Loop 2 : leftTuple : NotNodeLeftTuple (= "gorgonzola")
-
Similarly, RuleNetworkEvaluator.findLeftTupleBlocker() doesn't hit
-
ltm.add(leftTuple);
-
Loop 3 : leftTuple : NotNodeLeftTuple (= "cheddar")
-
RuleNetworkEvaluator.findLeftTupleBlocker()
- tree.findNearestNode()
- acceptNode() returns true
- nearest = Node key=gorgonzola
- n = n.left , We want to traverse to lower nodes to find a better match.
- but no more node, so returns Node for "gorgonzola"
- firstNode.getFirst() returns RightTupleImpl(= Cheese "gorgonzola")
RightTuple nextRight = (RightTuple) it.next(rightTuple);
-
if (constraints.isAllowedCachedLeft(contextEntry,
- Retreive nextRight from iterator: all tuples should match the constraint
- In isAllowedCachedLeft(), evaluation is skipped because it's indexed
- leftTuple.setBlocker(rightTuple);
- rightTuple.addBlocked(leftTuple);
- It means the rightTuple(= Cheese "gorgonzola") blocks the leftTuple (= String "cheddar")
- tree.findNearestNode()
-
insertChildLeftTuple()
- insert leftTuple to trgLeftTuples for the next sink
-
rule R1
when
$pet : Pet()
Person( age > $pet.age )
then
end
ksession.insert(new Pet(PetType.CAT, 10));
ksession.insert(new Person("Paul", 20));
ksession.fireAllRules();
Rule Build:
- PatternBuilder.buildConstraintForPattern() puts [$pet] into declarations and picks [age] as decr.
- MVELConstraint [age > $pet.age] is created. indexingDeclaration is [age]
- JoinNode is created.
- SingleBetaConstraints.initIndexes()
- IndexUtil.canHaveRangeIndex() returns true
- SingleBetaConstraints.indexed = true
- SingleBetaConstraints.initIndexes()
Runtime:
-
SingleBetaConstraints.createBetaMemory()
- Same as ExistsNode. Create AbstractHashTable.FieldIndex and used it for both leftMemory TupleIndexRBTree and rightMemory TupleIndexRBTree.
-
PhreakJoinNode.doRightInserts()
- rightTuple : RightTupleImpl(= Person age=20)
- TupleIndexRBTree.add(rightTuple) for rightMemory
- getLeftIndexedValue()
- getIndexedValue() : left = false
-
(Comparable) index.getExtractor().getValue( tuple.getFactHandle().getObject() );
- Get the key (= 20)
- insert to the rightMemory tree
- getLeftIndexedValue()
-
PhreakJoinNode.doLeftInserts()
- srcLeftTuples : Pet age=10
- leftTuple : JoinNodeLeftTuple (= Pet age=10)
- ltm.add(leftTuple);
- TupleIndexRBTree.add(leftTuple) for leftMemory
- getLeftIndexedValue()
- getIndexedValue() : left = true
-
(Comparable) index.getDeclaration().getExtractor().getValue( tuple.getObject( index.getDeclaration() ) ) :
- Get the key (= 10) from JoinNodeLeftTuple using declaration.getOffset(). This means it picks the expected value [$pet.age]. (So, [$pet.age] is "left")
- TupleList list = tree.insert(key);
- So leftMemory tree is also maintained
- getLeftIndexedValue()
- TupleIndexRBTree.add(leftTuple) for leftMemory
- BetaNode.getFirstRightTuple() : This means, rightMemory is the tree. leftTuple is the key. So get the nearest rightTuple which matches the constraint [ age > $pet.age ]
- TupleIndexRBTree.getFirst()
- getRightIndexedValue() : NOTE that this inverses TupleIndexRBTree.left
- getIndexedValue() : left = true
-
(Comparable) index.getDeclaration().getExtractor().getValue( tuple.getObject( index.getDeclaration() ) ) :
- Get the key (= 10) from JoinNodeLeftTuple using declaration.getOffset(). This means it picks the expected value [$pet.age]. (So, [$pet.age] is "left")
- getNext() : key = 10, first = true
- getNextRight() : because this is rightMemory.
- GREATER_THAN :
-
firstNode = tree.findNearestNode(key, false, Boundary.LOWER);
- Boundary.LOWER means "If this key is lower than a treeNode, the treeNode matches"
- TupleRBTree.findNearestNode()
- compResult < 0
- acceptNode() returns true. nearest = Node key=20
-
n = accepted ^ boundary == Boundary.LOWER ? n.right : n.left;
- false, so n.left. We want to traverse to lower nodes to find a better match.
- but no more node, so returns Node (Person age=20)
- getNextRight() : because this is rightMemory.
- getRightIndexedValue() : NOTE that this inverses TupleIndexRBTree.left
- TupleIndexRBTree.getFirst()
- isAllowedCachedLeft() skips evaluation because the constraint is indexed
- insertChildLeftTuple()
- insert a new leftTuple to trgLeftTuples for the next sink
TupleIndexRBTree
private Comparable getIndexedValue( Tuple tuple, boolean left ) {
return left ?
(Comparable) index.getDeclaration().getExtractor().getValue( tuple.getObject( index.getDeclaration() ) ) :
(Comparable) index.getExtractor().getValue( tuple.getFactHandle().getObject() );
}
- left = true : get a value from "indexingDeclaration"
- left = false : get a value from the fact itself