Fix for SOLR-2829. False-positives on cache hits.

git-svn-id: https://svn.apache.org/repos/asf/lucene/dev/trunk@1198024 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Erick Erickson 2011-11-05 19:20:37 +00:00
parent b03675131a
commit 130ec534c5
5 changed files with 162 additions and 4 deletions

View File

@ -37,8 +37,8 @@ public abstract class NumericFieldCacheSource<T extends CachedArray> extends Fie
if (o.getClass() != this.getClass()) return false; if (o.getClass() != this.getClass()) return false;
NumericFieldCacheSource other = (NumericFieldCacheSource) o; NumericFieldCacheSource other = (NumericFieldCacheSource) o;
return super.equals(other) return super.equals(other)
&& this.creator == null ? other.creator == null : && (this.creator == null ? other.creator == null :
this.creator.getClass() == other.creator.getClass(); this.creator.getClass() == other.creator.getClass());
} }
@Override @Override

View File

@ -553,7 +553,7 @@ class SpatialDistanceQuery extends Query {
/** Returns true if <code>o</code> is equal to this. */ /** Returns true if <code>o</code> is equal to this. */
@Override @Override
public boolean equals(Object o) { public boolean equals(Object o) {
if (SpatialDistanceQuery.class != o.getClass()) return false; if (!super.equals(o)) return false;
SpatialDistanceQuery other = (SpatialDistanceQuery)o; SpatialDistanceQuery other = (SpatialDistanceQuery)o;
return this.latCenter == other.latCenter return this.latCenter == other.latCenter
&& this.lonCenter == other.lonCenter && this.lonCenter == other.lonCenter

View File

@ -51,6 +51,9 @@
<fieldType name="float" class="solr.TrieFloatField" precisionStep="0" omitNorms="true" positionIncrementGap="0"/> <fieldType name="float" class="solr.TrieFloatField" precisionStep="0" omitNorms="true" positionIncrementGap="0"/>
<fieldType name="long" class="solr.TrieLongField" precisionStep="0" omitNorms="true" positionIncrementGap="0"/> <fieldType name="long" class="solr.TrieLongField" precisionStep="0" omitNorms="true" positionIncrementGap="0"/>
<fieldType name="double" class="solr.TrieDoubleField" precisionStep="0" omitNorms="true" positionIncrementGap="0"/> <fieldType name="double" class="solr.TrieDoubleField" precisionStep="0" omitNorms="true" positionIncrementGap="0"/>
<fieldType name="byte" class="solr.ByteField" omitNorms="true" positionIncrementGap="0"/>
<fieldType name="short" class="solr.ShortField" omitNorms="true" positionIncrementGap="0"/>
<fieldType name="tint" class="solr.TrieIntField" precisionStep="8" omitNorms="true" positionIncrementGap="0"/> <fieldType name="tint" class="solr.TrieIntField" precisionStep="8" omitNorms="true" positionIncrementGap="0"/>
<fieldType name="tfloat" class="solr.TrieFloatField" precisionStep="8" omitNorms="true" positionIncrementGap="0"/> <fieldType name="tfloat" class="solr.TrieFloatField" precisionStep="8" omitNorms="true" positionIncrementGap="0"/>
@ -457,6 +460,8 @@
<field name="work" type="xy" indexed="true" stored="true" multiValued="false"/> <field name="work" type="xy" indexed="true" stored="true" multiValued="false"/>
<field name="home_ll" type="latLon" indexed="true" stored="true" multiValued="false"/> <field name="home_ll" type="latLon" indexed="true" stored="true" multiValued="false"/>
<field name="work_ll" type="latLon" indexed="true" stored="true" multiValued="false"/>
<field name="home_gh" type="geohash" indexed="true" stored="true" multiValued="false"/> <field name="home_gh" type="geohash" indexed="true" stored="true" multiValued="false"/>
@ -572,6 +577,7 @@
<dynamicField name="*_l1" type="long" indexed="true" stored="true" multiValued="false"/> <dynamicField name="*_l1" type="long" indexed="true" stored="true" multiValued="false"/>
<dynamicField name="*_t" type="text" indexed="true" stored="true"/> <dynamicField name="*_t" type="text" indexed="true" stored="true"/>
<dynamicField name="*_b" type="boolean" indexed="true" stored="true"/> <dynamicField name="*_b" type="boolean" indexed="true" stored="true"/>
<dynamicField name="*_b1" type="boolean" indexed="true" stored="true" multiValued="false"/>
<dynamicField name="*_f" type="float" indexed="true" stored="true"/> <dynamicField name="*_f" type="float" indexed="true" stored="true"/>
<dynamicField name="*_f1" type="float" indexed="true" stored="true" multiValued="false"/> <dynamicField name="*_f1" type="float" indexed="true" stored="true" multiValued="false"/>
<dynamicField name="*_d" type="double" indexed="true" stored="true"/> <dynamicField name="*_d" type="double" indexed="true" stored="true"/>
@ -579,6 +585,11 @@
<dynamicField name="*_dt" type="date" indexed="true" stored="true"/> <dynamicField name="*_dt" type="date" indexed="true" stored="true"/>
<dynamicField name="*_dt1" type="date" indexed="true" stored="true" multiValued="false"/> <dynamicField name="*_dt1" type="date" indexed="true" stored="true" multiValued="false"/>
<dynamicField name="*_bcd" type="bcdstr" indexed="true" stored="true"/> <dynamicField name="*_bcd" type="bcdstr" indexed="true" stored="true"/>
<dynamicField name="*_by" type="byte" indexed="true" stored="true"/>
<dynamicField name="*_by1" type="byte" indexed="true" stored="true" multiValued="false"/>
<dynamicField name="*_sh" type="short" indexed="true" stored="true"/>
<dynamicField name="*_sh1" type="short" indexed="true" stored="true" multiValued="false"/>
<!-- some trie-coded dynamic fields for faster range queries --> <!-- some trie-coded dynamic fields for faster range queries -->
<dynamicField name="*_ti" type="tint" indexed="true" stored="true"/> <dynamicField name="*_ti" type="tint" indexed="true" stored="true"/>

View File

@ -117,6 +117,21 @@ public class SpatialFilterTest extends SolrTestCaseJ4 {
// falls outside of the real distance, but inside the bounding box // falls outside of the real distance, but inside the bounding box
checkHits(fieldName, true, "43.517030,-96.789603", 110, 0); checkHits(fieldName, true, "43.517030,-96.789603", 110, 0);
checkHits(fieldName, false, "43.517030,-96.789603", 110, 1, 17); checkHits(fieldName, false, "43.517030,-96.789603", 110, 1, 17);
// Tests SOLR-2829
String fieldNameHome = "home_ll";
String fieldNameWork = "work_ll";
clearIndex();
assertU(adoc("id", "1", fieldNameHome, "52.67,7.30", fieldNameWork,"48.60,11.61"));
assertU(commit());
checkHits(fieldNameHome, "52.67,7.30", 1, 1);
checkHits(fieldNameWork, "48.60,11.61", 1, 1);
checkHits(fieldNameWork, "52.67,7.30", 1, 0);
checkHits(fieldNameHome, "48.60,11.61", 1, 0);
} }
private void checkHits(String fieldName, String pt, double distance, int count, int ... docIds) { private void checkHits(String fieldName, String pt, double distance, int count, int ... docIds) {

View File

@ -0,0 +1,132 @@
package org.apache.solr.search;
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import org.apache.lucene.queryparser.classic.ParseException;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.QueryUtils;
import org.apache.solr.SolrTestCaseJ4;
import org.junit.BeforeClass;
import org.junit.Test;
// NOTE: this is a direct result of SOLR-2829
public class TestValueSourceCache extends SolrTestCaseJ4 {
@BeforeClass
public static void beforeClass() throws Exception {
initCore("solrconfig.xml", "schema.xml");
_func = QParser.getParser(null, FunctionQParserPlugin.NAME, lrf.makeRequest());
}
static QParser _func;
Query getQuery(String query) throws ParseException {
_func.setString(query);
return _func.parse();
}
// This is actually also tested by the tests for val_d1 below, but the bug was reported against geodist()...
@Test
public void testGeodistSource() throws ParseException {
Query q_home = getQuery("geodist(home_ll, 45.0, 43.0)");
Query q_work = getQuery("geodist(work_ll, 45.0, 43.0)");
Query q_home2 = getQuery("geodist(home_ll, 45.0, 43.0)");
QueryUtils.checkUnequal(q_work, q_home);
QueryUtils.checkEqual(q_home, q_home2);
}
@Test
public void testNumerics() throws ParseException {
String[] templates = new String[]{
"sum(#v0, #n0)",
"product(pow(#v0,#n0),#v1,#n1)",
"log(#v0)",
"log(sum(#n0,#v0,#v1,#n1))",
"scale(map(#v0,#n0,#n1,#n2),#n3,#n4)",
};
String[] numbers = new String[]{
"1,2,3,4,5",
"1.0,2.0,3.0,4.0,5.0",
"1,2.0,3,4.0,5",
"1.0,2,3.0,4,5.0",
"1000000,2000000,3000000,4000000,5000000"
};
String[] types = new String[]{
"val1_f1",
"val1_d1",
"val1_b1",
"val1_i1",
"val1_l1",
"val1_b1",
"val1_by1",
"val1_sh1"
};
for (String template : templates) {
for (String nums : numbers) {
for (String type : types) {
tryQuerySameTypes(template, nums, type);
tryQueryDiffTypes(template, nums, types);
}
}
}
}
// This test should will fail because q1 and q3 evaluate as equal unless
// fixes for bug 2829 are in place.
void tryQuerySameTypes(String template, String numbers, String type) throws ParseException {
String s1 = template;
String s2 = template;
String s3 = template;
String[] numParts = numbers.split(",");
String type2 = type.replace("val1", "val2");
for (int idx = 0; s1.contains("#"); ++idx) {
String patV = "#v" + Integer.toString(idx);
String patN = "#n" + Integer.toString(idx);
s1 = s1.replace(patV, type).replace(patN, numParts[idx]);
s2 = s2.replace(patV, type).replace(patN, numParts[idx]);
s3 = s3.replace(patV, type2).replace(patN, numParts[idx]);
}
//SolrQueryRequest req1 = req( "q","*:*", "fq", s1);
Query q1 = getQuery(s1);
Query q2 = getQuery(s2);
Query q3 = getQuery(s3);
QueryUtils.checkEqual(q1, q2);
QueryUtils.checkUnequal(q1, q3);
}
// These should always and forever fail, and would have failed without the fixes for 2829, but why not make
// some more tests just in case???
void tryQueryDiffTypes(String template, String numbers, String[] types) throws ParseException {
String s1 = template;
String s2 = template;
String[] numParts = numbers.split(",");
for (int idx = 0; s1.contains("#"); ++idx) {
String patV = "#v" + Integer.toString(idx);
String patN = "#n" + Integer.toString(idx);
s1 = s1.replace(patV, types[idx % types.length]).replace(patN, numParts[idx]);
s2 = s2.replace(patV, types[(idx + 1) % types.length]).replace(patN, numParts[idx]);
}
Query q1 = getQuery(s1);
Query q2 = getQuery(s2);
QueryUtils.checkUnequal(q1, q2);
}
}