LUCENE-7185: fix edge case bugs in LatLonPoint bounding box query

This commit is contained in:
Robert Muir 2016-04-07 00:09:56 -04:00
parent 2965ac2ca1
commit e0c507a400
1 changed files with 16 additions and 0 deletions

View File

@ -26,6 +26,7 @@ import org.apache.lucene.search.BooleanClause;
import org.apache.lucene.search.BooleanQuery; import org.apache.lucene.search.BooleanQuery;
import org.apache.lucene.search.ConstantScoreQuery; import org.apache.lucene.search.ConstantScoreQuery;
import org.apache.lucene.search.FieldDoc; import org.apache.lucene.search.FieldDoc;
import org.apache.lucene.search.MatchNoDocsQuery;
import org.apache.lucene.search.PointRangeQuery; import org.apache.lucene.search.PointRangeQuery;
import org.apache.lucene.search.Query; import org.apache.lucene.search.Query;
import org.apache.lucene.search.SortField; import org.apache.lucene.search.SortField;
@ -285,6 +286,21 @@ public class LatLonPoint extends Field {
* @throws IllegalArgumentException if {@code field} is null, or the box has invalid coordinates. * @throws IllegalArgumentException if {@code field} is null, or the box has invalid coordinates.
*/ */
public static Query newBoxQuery(String field, double minLatitude, double maxLatitude, double minLongitude, double maxLongitude) { public static Query newBoxQuery(String field, double minLatitude, double maxLatitude, double minLongitude, double maxLongitude) {
// exact double values of lat=90.0D and lon=180.0D must be treated special as they are not represented in the encoding
// and should not drag in extra bogus junk! TODO: should encodeCeil just throw ArithmeticException to be less trappy here?
if (minLatitude == 90.0) {
// range cannot match as 90.0 can never exist
return new MatchNoDocsQuery();
}
if (minLongitude == 180.0) {
if (maxLongitude == 180.0) {
// range cannot match as 180.0 can never exist
return new MatchNoDocsQuery();
} else if (maxLongitude < minLongitude) {
// encodeCeil() with dateline wrapping!
minLongitude = -180.0;
}
}
byte[] lower = encodeCeil(minLatitude, minLongitude); byte[] lower = encodeCeil(minLatitude, minLongitude);
byte[] upper = encode(maxLatitude, maxLongitude); byte[] upper = encode(maxLatitude, maxLongitude);
// Crosses date line: we just rewrite into OR of two bboxes, with longitude as an open range: // Crosses date line: we just rewrite into OR of two bboxes, with longitude as an open range: