Skip to content

Commit 36b61d4

Browse files
authored
SOLR-18181: ValueSourceAugmenter NPE when rows exceed 1000 and scores requested (#4314)
Fixed an NPE caused by queries using ValueSourceAugmenter and querying for > 1000 rows with score. Moved to overriding non-deprecated transform method and correctly referencing DocIterationInfo for score.
1 parent 4c9a0e3 commit 36b61d4

3 files changed

Lines changed: 87 additions & 3 deletions

File tree

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
title: Fix NPE in ValueSourceAugmenter when rows exceed prefetch limit with scores requested
2+
type: fixed
3+
authors:
4+
- name: Matthew Biscocho
5+
links:
6+
- name: SOLR-18181
7+
url: https://issues.apache.org/jira/browse/SOLR-18181

solr/core/src/java/org/apache/solr/response/transform/ValueSourceAugmenter.java

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
import org.apache.solr.common.SolrDocument;
3131
import org.apache.solr.common.SolrException;
3232
import org.apache.solr.response.ResultContext;
33+
import org.apache.solr.search.DocIterationInfo;
3334
import org.apache.solr.search.QParser;
3435
import org.apache.solr.search.SolrIndexSearcher;
3536

@@ -142,7 +143,7 @@ public float score() throws IOException {
142143
IntObjectHashMap<Object> cachedValuesById;
143144

144145
@Override
145-
public void transform(SolrDocument doc, int docid) {
146+
public void transform(SolrDocument doc, int docid, DocIterationInfo docIterationInfo) {
146147
Object cacheValue = (cachedValuesById != null) ? cachedValuesById.get(docid) : null;
147148
if (cacheValue != null) {
148149
setValue(doc, cacheValue != NULL_SENTINEL ? cacheValue : null);
@@ -153,8 +154,8 @@ public void transform(SolrDocument doc, int docid) {
153154
LeafReaderContext rcontext = readerContexts.get(idx);
154155
int localId = docid - rcontext.docBase;
155156

156-
if (context.wantsScores()) {
157-
fcontext.put("scorer", new ScoreAndDoc(localId, (float) doc.get("score")));
157+
if (context.wantsScores() && docIterationInfo != null) {
158+
fcontext.put("scorer", new ScoreAndDoc(localId, docIterationInfo.score()));
158159
}
159160

160161
FunctionValues values = valueSource.getValues(fcontext, rcontext);
@@ -168,6 +169,11 @@ public void transform(SolrDocument doc, int docid) {
168169
}
169170
}
170171

172+
@Override
173+
public void transform(SolrDocument doc, int docid) {
174+
transform(doc, docid, null);
175+
}
176+
171177
private abstract static class MutableScorable extends Scorable {
172178

173179
int docBase;
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one or more
3+
* contributor license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright ownership.
5+
* The ASF licenses this file to You under the Apache License, Version 2.0
6+
* (the "License"); you may not use this file except in compliance with
7+
* the License. You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
package org.apache.solr.response.transform;
18+
19+
import org.apache.solr.SolrTestCaseJ4;
20+
import org.junit.BeforeClass;
21+
22+
public class TestValueSourceAugmenterPrefetchLimit extends SolrTestCaseJ4 {
23+
24+
private static final int MAX_PREFETCH_SIZE = 1000;
25+
26+
@BeforeClass
27+
public static void beforeTests() throws Exception {
28+
initCore("solrconfig.xml", "schema.xml");
29+
30+
// Index enough documents to exceed the prefetch limit
31+
final int numDocs = MAX_PREFETCH_SIZE + 10;
32+
for (int i = 0; i < numDocs; i++) {
33+
assertU(adoc("id", Integer.toString(i)));
34+
}
35+
assertU(commit());
36+
}
37+
38+
public void testWithScoreBelowPrefetchLimit() {
39+
assertQ(
40+
"fl=foo:field(id),score with rows within prefetch limit",
41+
req(
42+
"q", "*:*",
43+
"fl", "foo:field(id),score",
44+
"rows", String.valueOf(MAX_PREFETCH_SIZE)),
45+
"//result[@numFound='" + (MAX_PREFETCH_SIZE + 10) + "']",
46+
"//result/doc/float[@name='score']");
47+
}
48+
49+
public void testWithScoreAbovePrefetchLimit() {
50+
assertQ(
51+
"fl=foo:field(id),score with rows exceeding prefetch limit",
52+
req(
53+
"q", "*:*",
54+
"fl", "foo:field(id),score",
55+
"rows", String.valueOf(MAX_PREFETCH_SIZE + 10)),
56+
"//result[@numFound='" + (MAX_PREFETCH_SIZE + 10) + "']",
57+
"//result/doc/float[@name='score']");
58+
}
59+
60+
public void testWithScoreAbovePrefetchLimitUsingPreFetchDocsParam() {
61+
assertQ(
62+
"fl=foo:field(id),score with custom preFetchDocs",
63+
req(
64+
"q", "*:*",
65+
"fl", "foo:field(id),score",
66+
"rows", String.valueOf(MAX_PREFETCH_SIZE + 10),
67+
"preFetchDocs", "2000"), // Set to 2000
68+
"//result[@numFound='" + (MAX_PREFETCH_SIZE + 10) + "']",
69+
"//result/doc/float[@name='score']");
70+
}
71+
}

0 commit comments

Comments
 (0)