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 { protected class NRShape implements Shape {
private final LevelledValue minLV, maxLV; 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)}. */ /** Don't call directly; see {@link #toRangeShape(com.spatial4j.core.shape.Shape, com.spatial4j.core.shape.Shape)}. */
private NRShape(LevelledValue minLV, LevelledValue maxLV) { private NRShape(LevelledValue minLV, LevelledValue maxLV) {
this.minLV = minLV; this.minLV = minLV;
this.maxLV = maxLV; 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 getMinLV() { return minLV; }
public LevelledValue getMaxLV() { return maxLV; } public LevelledValue getMaxLV() { return maxLV; }
/** How many levels are in common between minLV and maxLV. */
private int getLastLevelInCommon() { return lastLevelInCommon; }
@Override @Override
public SpatialRelation relate(Shape shape) { public SpatialRelation relate(Shape shape) {
// if (shape instanceof LevelledValue) // if (shape instanceof LevelledValue)
@ -580,17 +592,22 @@ public abstract class NumberRangePrefixTree extends SpatialPrefixTree {
final LevelledValue minLV; final LevelledValue minLV;
final LevelledValue maxLV; final LevelledValue maxLV;
final int lastLevelInCommon;//between minLV & maxLV
if (filter instanceof NRShape) { if (filter instanceof NRShape) {
NRShape nrShape = (NRShape) iterFilter; NRShape nrShape = (NRShape) iterFilter;
minLV = nrShape.getMinLV(); minLV = nrShape.getMinLV();
maxLV = nrShape.getMaxLV(); maxLV = nrShape.getMaxLV();
lastLevelInCommon = nrShape.getLastLevelInCommon();
} else { } else {
minLV = (LevelledValue) iterFilter; minLV = (LevelledValue) iterFilter;
maxLV = minLV; maxLV = minLV;
lastLevelInCommon = minLV.getLevel();
} }
//fast path check when using same filter //fast path optimization that is usually true, but never first level
if (iterFilter == parent.iterFilter) { 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 if (parent.iterFirstIsIntersects && parent.cellNumber == parent.iterFirstCellNumber
&& minLV.getLevel() >= getLevel()) { && minLV.getLevel() >= getLevel()) {
iterFirstCellNumber = minLV.getValAtLevel(getLevel()); iterFirstCellNumber = minLV.getValAtLevel(getLevel());
@ -616,7 +633,7 @@ public abstract class NumberRangePrefixTree extends SpatialPrefixTree {
return; 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); int startCmp = comparePrefixLV(minLV, parent);
if (startCmp > 0) {//start comes after this cell if (startCmp > 0) {//start comes after this cell
@ -650,6 +667,12 @@ public abstract class NumberRangePrefixTree extends SpatialPrefixTree {
iterLastCellNumber = maxLV.getValAtLevel(getLevel()); iterLastCellNumber = maxLV.getValAtLevel(getLevel());
iterLastIsIntersects = (maxLV.getLevel() > getLevel()); iterLastIsIntersects = (maxLV.getLevel() > getLevel());
} }
if (iterFirstCellNumber == iterLastCellNumber) {
if (iterLastIsIntersects)
iterFirstIsIntersects = true;
else if (iterFirstIsIntersects)
iterLastIsIntersects = true;
}
} }
@Override @Override

View File

@ -91,6 +91,15 @@ public class DateNRStrategyTest extends BaseNonFuzzySpatialOpStrategyTest {
tree.toShape(randomCalendar()), true); 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 @Override
protected Shape randomIndexedShape() { protected Shape randomIndexedShape() {
Calendar cal1 = randomCalendar(); Calendar cal1 = randomCalendar();