mirror of https://github.com/apache/lucene.git
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:
parent
dc8e53b11a
commit
0a70e721ce
|
@ -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)
|
||||||
|
@ -561,11 +573,11 @@ public abstract class NumberRangePrefixTree extends SpatialPrefixTree {
|
||||||
|
|
||||||
private void initIter(Shape filter) {
|
private void initIter(Shape filter) {
|
||||||
cellNumber = -1;
|
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
|
filter = null;//world means everything -- no filter
|
||||||
iterFilter = filter;
|
iterFilter = filter;
|
||||||
|
|
||||||
NRCell parent = getLVAtLevel(getLevel()-1);
|
NRCell parent = getLVAtLevel(getLevel() - 1);
|
||||||
|
|
||||||
// Initialize iter* members.
|
// Initialize iter* members.
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
|
|
@ -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();
|
||||||
|
|
Loading…
Reference in New Issue