LUCENE-5648: (NumberRangePrefixTree) Bug-fix in initIter optimization. Re-index required.

git-svn-id: https://svn.apache.org/repos/asf/lucene/dev/trunk@1602857 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
David Wayne Smiley 2014-06-16 12:38:43 +00:00
parent dc8e53b11a
commit 0a70e721ce
2 changed files with 38 additions and 6 deletions

View File

@ -96,17 +96,29 @@ public abstract class NumberRangePrefixTree extends SpatialPrefixTree {
protected class NRShape implements Shape {
private final LevelledValue minLV, maxLV;
private final int lastLevelInCommon;//computed; not part of identity
/** Don't call directly; see {@link #toRangeShape(com.spatial4j.core.shape.Shape, com.spatial4j.core.shape.Shape)}. */
private NRShape(LevelledValue minLV, LevelledValue maxLV) {
this.minLV = minLV;
this.maxLV = maxLV;
//calc lastLevelInCommon
int level = 1;
for (; level <= minLV.getLevel() && level <= maxLV.getLevel(); level++) {
if (minLV.getValAtLevel(level) != maxLV.getValAtLevel(level))
break;
}
lastLevelInCommon = level - 1;
}
public LevelledValue getMinLV() { return minLV; }
public LevelledValue getMaxLV() { return maxLV; }
/** How many levels are in common between minLV and maxLV. */
private int getLastLevelInCommon() { return lastLevelInCommon; }
@Override
public SpatialRelation relate(Shape shape) {
// if (shape instanceof LevelledValue)
@ -561,11 +573,11 @@ public abstract class NumberRangePrefixTree extends SpatialPrefixTree {
private void initIter(Shape filter) {
cellNumber = -1;
if (filter instanceof LevelledValue && ((LevelledValue)filter).getLevel() == 0)
if (filter instanceof LevelledValue && ((LevelledValue) filter).getLevel() == 0)
filter = null;//world means everything -- no filter
iterFilter = filter;
NRCell parent = getLVAtLevel(getLevel()-1);
NRCell parent = getLVAtLevel(getLevel() - 1);
// Initialize iter* members.
@ -580,17 +592,22 @@ public abstract class NumberRangePrefixTree extends SpatialPrefixTree {
final LevelledValue minLV;
final LevelledValue maxLV;
final int lastLevelInCommon;//between minLV & maxLV
if (filter instanceof NRShape) {
NRShape nrShape = (NRShape) iterFilter;
minLV = nrShape.getMinLV();
maxLV = nrShape.getMaxLV();
lastLevelInCommon = nrShape.getLastLevelInCommon();
} else {
minLV = (LevelledValue)iterFilter;
minLV = (LevelledValue) iterFilter;
maxLV = minLV;
lastLevelInCommon = minLV.getLevel();
}
//fast path check when using same filter
if (iterFilter == parent.iterFilter) {
//fast path optimization that is usually true, but never first level
if (iterFilter == parent.iterFilter &&
(getLevel() <= lastLevelInCommon || parent.iterFirstCellNumber != parent.iterLastCellNumber)) {
//TODO benchmark if this optimization pays off. We avoid two comparePrefixLV calls.
if (parent.iterFirstIsIntersects && parent.cellNumber == parent.iterFirstCellNumber
&& minLV.getLevel() >= getLevel()) {
iterFirstCellNumber = minLV.getValAtLevel(getLevel());
@ -616,7 +633,7 @@ public abstract class NumberRangePrefixTree extends SpatialPrefixTree {
return;
}
//uncommon to get here, except for level 1 which always happens
//not common to get here, except for level 1 which always happens
int startCmp = comparePrefixLV(minLV, parent);
if (startCmp > 0) {//start comes after this cell
@ -650,6 +667,12 @@ public abstract class NumberRangePrefixTree extends SpatialPrefixTree {
iterLastCellNumber = maxLV.getValAtLevel(getLevel());
iterLastIsIntersects = (maxLV.getLevel() > getLevel());
}
if (iterFirstCellNumber == iterLastCellNumber) {
if (iterLastIsIntersects)
iterFirstIsIntersects = true;
else if (iterFirstIsIntersects)
iterLastIsIntersects = true;
}
}
@Override

View File

@ -91,6 +91,15 @@ public class DateNRStrategyTest extends BaseNonFuzzySpatialOpStrategyTest {
tree.toShape(randomCalendar()), true);
}
@Test
public void testBugInitIterOptimization() throws Exception {
//bug due to fast path initIter() optimization
testOperation(
tree.parseShape("[2014-03-27T23 TO 2014-04-01T01]"),
SpatialOperation.Intersects,
tree.parseShape("[2014-04 TO 2014-04-01T02]"), true);
}
@Override
protected Shape randomIndexedShape() {
Calendar cal1 = randomCalendar();