This is an automated email from the ASF dual-hosted git repository. dsmiley pushed a commit to branch branch_9x in repository https://gitbox.apache.org/repos/asf/solr.git
commit c13a35b9a99bf2999927f0f2ab9dfcfddc25dea1 Author: David Smiley <[email protected]> AuthorDate: Sat May 24 10:35:52 2025 -0400 Refactoring: add QParser.parseAsValueSource (#3343) It's common to need to parse a ValueSource from a QParser. Callers were typically doing the same thing including unfortunate instanceof checks. * Disable FunctionQParser.parseMultipleSources by default and deprecate it. Test the exception. Doesn't break any existing tests. This aspect is very exotic and could go away once we remove some old things relying on it. (cherry picked from commit 759df4aacd76226984532fd6bbf8d594680ba361) --- .../apache/solr/handler/component/StatsField.java | 21 +----- .../org/apache/solr/search/BoostQParserPlugin.java | 9 +-- .../apache/solr/search/ExtendedDismaxQParser.java | 13 ++-- .../org/apache/solr/search/FunctionQParser.java | 60 ++++++++++++----- .../solr/search/FunctionRangeQParserPlugin.java | 9 +-- .../src/java/org/apache/solr/search/Grouping.java | 24 ++----- .../src/java/org/apache/solr/search/QParser.java | 22 ++++++ .../org/apache/solr/search/SolrReturnFields.java | 43 +----------- .../org/apache/solr/search/SortSpecParsing.java | 78 +++++++++++----------- .../org/apache/solr/search/ValueSourceParser.java | 7 +- .../function/distance/DistanceFunctionTest.java | 39 ++++++----- 11 files changed, 145 insertions(+), 180 deletions(-) diff --git a/solr/core/src/java/org/apache/solr/handler/component/StatsField.java b/solr/core/src/java/org/apache/solr/handler/component/StatsField.java index e74e00f015b..3f7df67da8d 100644 --- a/solr/core/src/java/org/apache/solr/handler/component/StatsField.java +++ b/solr/core/src/java/org/apache/solr/handler/component/StatsField.java @@ -30,10 +30,8 @@ import java.util.List; import java.util.Map; import java.util.Set; import org.apache.lucene.index.LeafReaderContext; -import org.apache.lucene.queries.function.FunctionQuery; import org.apache.lucene.queries.function.ValueSource; import org.apache.lucene.queries.function.valuesource.FieldCacheSource; -import org.apache.lucene.queries.function.valuesource.QueryValueSource; import org.apache.lucene.search.Query; import org.apache.solr.common.SolrException; import org.apache.solr.common.SolrException.ErrorCode; @@ -276,7 +274,7 @@ public class StatsField { qplug.createParser(localParams.get(QueryParsing.V), localParams, params, rb.req); // figure out what type of query we are dealing, get the most direct ValueSource - vs = extractValueSource(qp.parse()); + vs = qp.parseAsValueSource(); // if this ValueSource directly corresponds to a SchemaField, act as if // we were asked to compute stats on it directly @@ -338,23 +336,6 @@ public class StatsField { : "exactly one of valueSource & schemaField must be null"; } - /** - * Inspects a {@link Query} to see if it directly maps to a {@link ValueSource}, and if so returns - * it -- otherwise wraps it as needed. - * - * @param q Query whose scores we have been asked to compute stats of - * @returns a ValueSource to use for computing the stats - */ - private static ValueSource extractValueSource(Query q) { - return (q instanceof FunctionQuery) - ? - // Common case: we're wrapping a func, so we can directly pull out ValueSource - ((FunctionQuery) q).getValueSource() - : - // asked to compute stats over a query, wrap it up as a ValueSource - new QueryValueSource(q, 0.0F); - } - /** * Inspects a {@link ValueSource} to see if it directly maps to a {@link SchemaField}, and if so * returns it. diff --git a/solr/core/src/java/org/apache/solr/search/BoostQParserPlugin.java b/solr/core/src/java/org/apache/solr/search/BoostQParserPlugin.java index 96c9d566221..ef1d457b2f4 100644 --- a/solr/core/src/java/org/apache/solr/search/BoostQParserPlugin.java +++ b/solr/core/src/java/org/apache/solr/search/BoostQParserPlugin.java @@ -16,10 +16,8 @@ */ package org.apache.solr.search; -import org.apache.lucene.queries.function.FunctionQuery; import org.apache.lucene.queries.function.FunctionScoreQuery; import org.apache.lucene.queries.function.ValueSource; -import org.apache.lucene.queries.function.valuesource.QueryValueSource; import org.apache.lucene.search.Query; import org.apache.solr.common.params.SolrParams; import org.apache.solr.common.util.NamedList; @@ -56,12 +54,7 @@ public class BoostQParserPlugin extends QParserPlugin { Query q = baseParser.getQuery(); if (b == null) return q; - Query bq = subQuery(b, FunctionQParserPlugin.NAME).getQuery(); - if (bq instanceof FunctionQuery) { - vs = ((FunctionQuery) bq).getValueSource(); - } else { - vs = new QueryValueSource(bq, 0.0f); - } + vs = subQuery(b, FunctionQParserPlugin.NAME).parseAsValueSource(); return FunctionScoreQuery.boostByValue(q, vs.asDoubleValuesSource()); } diff --git a/solr/core/src/java/org/apache/solr/search/ExtendedDismaxQParser.java b/solr/core/src/java/org/apache/solr/search/ExtendedDismaxQParser.java index 3d593669ed5..139d0d53eff 100644 --- a/solr/core/src/java/org/apache/solr/search/ExtendedDismaxQParser.java +++ b/solr/core/src/java/org/apache/solr/search/ExtendedDismaxQParser.java @@ -29,7 +29,6 @@ import org.apache.lucene.analysis.Analyzer; import org.apache.lucene.analysis.TokenFilterFactory; import org.apache.lucene.analysis.core.StopFilterFactory; import org.apache.lucene.index.Term; -import org.apache.lucene.queries.function.FunctionQuery; import org.apache.lucene.queries.function.FunctionScoreQuery; import org.apache.lucene.queries.function.ValueSource; import org.apache.lucene.queries.function.valuesource.ProductFloatFunction; @@ -532,13 +531,11 @@ public class ExtendedDismaxQParser extends QParser { List<ValueSource> boosts = new ArrayList<>(); if (config.hasMultiplicativeBoosts()) { for (String boostStr : config.multBoosts) { - if (boostStr == null || boostStr.length() == 0) continue; - Query boost = subQuery(boostStr, FunctionQParserPlugin.NAME).getQuery(); - ValueSource vs; - if (boost instanceof FunctionQuery) { - vs = ((FunctionQuery) boost).getValueSource(); - } else { - vs = new QueryValueSource(boost, 1.0f); + if (boostStr == null || boostStr.isEmpty()) continue; + ValueSource vs = subQuery(boostStr, FunctionQParserPlugin.NAME).parseAsValueSource(); + // the default score should be 1, not 0 + if (vs instanceof QueryValueSource && ((QueryValueSource) vs).getDefaultValue() == 0.0f) { + vs = new QueryValueSource(((QueryValueSource) vs).getQuery(), 1.0f); } boosts.add(vs); } diff --git a/solr/core/src/java/org/apache/solr/search/FunctionQParser.java b/solr/core/src/java/org/apache/solr/search/FunctionQParser.java index 2a3dcd9dc68..a88dfe52316 100644 --- a/solr/core/src/java/org/apache/solr/search/FunctionQParser.java +++ b/solr/core/src/java/org/apache/solr/search/FunctionQParser.java @@ -26,7 +26,6 @@ import org.apache.lucene.queries.function.valuesource.ConstKnnFloatValueSource; import org.apache.lucene.queries.function.valuesource.ConstValueSource; import org.apache.lucene.queries.function.valuesource.DoubleConstValueSource; import org.apache.lucene.queries.function.valuesource.LiteralValueSource; -import org.apache.lucene.queries.function.valuesource.QueryValueSource; import org.apache.lucene.queries.function.valuesource.VectorValueSource; import org.apache.lucene.search.Query; import org.apache.solr.common.params.ModifiableSolrParams; @@ -36,6 +35,13 @@ import org.apache.solr.schema.SchemaField; import org.apache.solr.search.facet.AggValueSource; import org.apache.solr.search.function.FieldNameValueSource; +/** + * Does "function query" parsing of function-call like strings, producing a {@link ValueSource}. As + * this implements {@link QParser}, we produce a {@link Query}, but more often {@link + * #parseAsValueSource()} is called instead. + * + * @see ValueSourceParser + */ public class FunctionQParser extends QParser { public static final int FLAG_CONSUME_DELIMITER = 0x01; // consume delimiter after parsing arg @@ -53,14 +59,27 @@ public class FunctionQParser extends QParser { */ public StrParser sp; - boolean parseMultipleSources = true; - boolean parseToEnd = true; + @Deprecated private boolean parseMultipleSources = false; + private boolean parseToEnd = true; public FunctionQParser( String qstr, SolrParams localParams, SolrParams params, SolrQueryRequest req) { super(qstr, localParams, params, req); setFlags(FLAG_DEFAULT); setString(qstr); + if (localParams != null && localParams.getPrimitiveBool("multiple")) { + setParseMultipleSources(true); + } + } + + /** + * Parses the string to a {@link ValueSource}. Typically, this is not used, however. + * + * @see QParser#parseAsValueSource() + */ + public static ValueSource parseAsValueSource(String string, SolrQueryRequest request) + throws SyntaxError { + return getParser(string, FunctionQParserPlugin.NAME, request).parseAsValueSource(); } @Override @@ -71,11 +90,18 @@ public class FunctionQParser extends QParser { } } + @Deprecated public void setParseMultipleSources(boolean parseMultipleSources) { this.parseMultipleSources = parseMultipleSources; } - /** parse multiple comma separated value sources */ + /** + * Parse multiple comma separated value sources encapsulated into a {@link VectorValueSource} when + * {@link #getQuery()} or {@link #parseAsValueSource()} is called. + * + * @deprecated this is only needed for an unusual use-case and seems hard to support + */ + @Deprecated public boolean getParseMultipleSources() { return parseMultipleSources; } @@ -86,11 +112,23 @@ public class FunctionQParser extends QParser { /** throw exception if there is extra stuff at the end of the parsed valuesource(s). */ public boolean getParseToEnd() { - return parseMultipleSources; + return parseToEnd; } @Override public Query parse() throws SyntaxError { + return new FunctionQuery(parseAsValueSource()); + } + + /** + * Parses as a ValueSource, not a Query. <em>NOT</em> intended to be called by {@link + * ValueSourceParser#parse(FunctionQParser)}; it's intended for general code that has a {@link + * QParser} but actually wants to parse a ValueSource. + * + * @return A {@link VectorValueSource} for multiple VS, otherwise just the single VS. + */ + @Override + public ValueSource parseAsValueSource() throws SyntaxError { ValueSource vs = null; List<ValueSource> lst = null; @@ -126,8 +164,7 @@ public class FunctionQParser extends QParser { if (lst != null) { vs = new VectorValueSource(lst); } - - return new FunctionQuery(vs); + return vs; } /** @@ -429,14 +466,7 @@ public class FunctionQParser extends QParser { subFunc.setParseMultipleSources(true); subFunc.setFlags(flags); } - Query subQuery = subParser.getQuery(); - if (subQuery == null) { - valueSource = new ConstValueSource(0.0f); - } else if (subQuery instanceof FunctionQuery) { - valueSource = ((FunctionQuery) subQuery).getValueSource(); - } else { - valueSource = new QueryValueSource(subQuery, 0.0f); - } + valueSource = subParser.parseAsValueSource(); } /* diff --git a/solr/core/src/java/org/apache/solr/search/FunctionRangeQParserPlugin.java b/solr/core/src/java/org/apache/solr/search/FunctionRangeQParserPlugin.java index ad7fee8a556..0c15b2d33d7 100644 --- a/solr/core/src/java/org/apache/solr/search/FunctionRangeQParserPlugin.java +++ b/solr/core/src/java/org/apache/solr/search/FunctionRangeQParserPlugin.java @@ -16,9 +16,7 @@ */ package org.apache.solr.search; -import org.apache.lucene.queries.function.FunctionQuery; import org.apache.lucene.queries.function.ValueSource; -import org.apache.lucene.queries.function.valuesource.QueryValueSource; import org.apache.lucene.search.Query; import org.apache.solr.common.params.SolrParams; import org.apache.solr.request.SolrQueryRequest; @@ -50,12 +48,7 @@ public class FunctionRangeQParserPlugin extends QParserPlugin { QParser subParser = subQuery(funcStr, FunctionQParserPlugin.NAME); subParser.setIsFilter( false); // the range can be based on the relevancy score of embedded queries. - Query funcQ = subParser.getQuery(); - if (funcQ instanceof FunctionQuery) { - vs = ((FunctionQuery) funcQ).getValueSource(); - } else { - vs = new QueryValueSource(funcQ, 0.0f); - } + vs = subParser.parseAsValueSource(); String l = localParams.get("l"); String u = localParams.get("u"); diff --git a/solr/core/src/java/org/apache/solr/search/Grouping.java b/solr/core/src/java/org/apache/solr/search/Grouping.java index 606be2874fe..f6ad2931d9e 100644 --- a/solr/core/src/java/org/apache/solr/search/Grouping.java +++ b/solr/core/src/java/org/apache/solr/search/Grouping.java @@ -28,9 +28,7 @@ import java.util.Map; import java.util.Set; import org.apache.lucene.index.ExitableDirectoryReader; import org.apache.lucene.index.IndexableField; -import org.apache.lucene.queries.function.FunctionQuery; import org.apache.lucene.queries.function.ValueSource; -import org.apache.lucene.queries.function.valuesource.QueryValueSource; import org.apache.lucene.search.CachingCollector; import org.apache.lucene.search.Collector; import org.apache.lucene.search.MatchNoDocsQuery; @@ -179,24 +177,16 @@ public class Grouping { } public void addFunctionCommand(String groupByStr, SolrQueryRequest request) throws SyntaxError { - QParser parser = QParser.getParser(groupByStr, FunctionQParserPlugin.NAME, request); - Query q = parser.getQuery(); + ValueSource valueSource = FunctionQParser.parseAsValueSource(groupByStr, request); final Grouping.Command<?> gc; - if (q instanceof FunctionQuery) { - ValueSource valueSource = ((FunctionQuery) q).getValueSource(); - if (valueSource instanceof StrFieldSource) { - String field = ((StrFieldSource) valueSource).getField(); - CommandField commandField = new CommandField(); - commandField.groupBy = field; - gc = commandField; - } else { - CommandFunc commandFunc = new CommandFunc(); - commandFunc.groupBy = valueSource; - gc = commandFunc; - } + if (valueSource instanceof StrFieldSource) { + String field = ((StrFieldSource) valueSource).getField(); + CommandField commandField = new CommandField(); + commandField.groupBy = field; + gc = commandField; } else { CommandFunc commandFunc = new CommandFunc(); - commandFunc.groupBy = new QueryValueSource(q, 0.0f); + commandFunc.groupBy = valueSource; gc = commandFunc; } gc.withinGroupSort = withinGroupSort; diff --git a/solr/core/src/java/org/apache/solr/search/QParser.java b/solr/core/src/java/org/apache/solr/search/QParser.java index e6723cff3bf..1a292186542 100644 --- a/solr/core/src/java/org/apache/solr/search/QParser.java +++ b/solr/core/src/java/org/apache/solr/search/QParser.java @@ -21,6 +21,10 @@ import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.Map; +import org.apache.lucene.queries.function.FunctionQuery; +import org.apache.lucene.queries.function.FunctionScoreQuery; +import org.apache.lucene.queries.function.ValueSource; +import org.apache.lucene.queries.function.valuesource.QueryValueSource; import org.apache.lucene.search.Query; import org.apache.solr.common.SolrException; import org.apache.solr.common.params.CommonParams; @@ -30,6 +34,7 @@ import org.apache.solr.common.util.NamedList; import org.apache.solr.common.util.StrUtils; import org.apache.solr.core.SolrConfig; import org.apache.solr.request.SolrQueryRequest; +import org.apache.solr.search.ValueSourceParser.LongConstValueSource; /** * <b>Note: This API is experimental and may change in non backward-compatible ways in the @@ -324,6 +329,23 @@ public abstract class QParser { return getReq().getCore().getSolrConfig().prefixQueryMinPrefixLength; } + /** + * Parse the string into a {@link ValueSource} <em>instead of a {@link Query}</em>. Solr calls + * this in most places that "function queries" go. Overridden by {@link FunctionQParser}. + */ + public ValueSource parseAsValueSource() throws SyntaxError { + Query q = getQuery(); + if (q == null) { + return new LongConstValueSource(0); + } else if (q instanceof FunctionQuery) { + return ((FunctionQuery) q).getValueSource(); + } else if (q instanceof FunctionScoreQuery) { + return ValueSource.fromDoubleValuesSource(((FunctionScoreQuery) q).getSource()); + } else { + return new QueryValueSource(q, 0.0f); + } + } + /** * Create a {@link QParser} to parse <code>qstr</code>, using the "lucene" * (QParserPlugin.DEFAULT_QTYPE) query parser. The query parser may be overridden by local-params diff --git a/solr/core/src/java/org/apache/solr/search/SolrReturnFields.java b/solr/core/src/java/org/apache/solr/search/SolrReturnFields.java index f0b9cbb1f42..16a2f6781af 100644 --- a/solr/core/src/java/org/apache/solr/search/SolrReturnFields.java +++ b/solr/core/src/java/org/apache/solr/search/SolrReturnFields.java @@ -28,10 +28,7 @@ import java.util.List; import java.util.Map; import java.util.Set; import java.util.function.Supplier; -import org.apache.lucene.queries.function.FunctionQuery; import org.apache.lucene.queries.function.ValueSource; -import org.apache.lucene.queries.function.valuesource.QueryValueSource; -import org.apache.lucene.search.Query; import org.apache.solr.common.SolrException; import org.apache.solr.common.params.CommonParams; import org.apache.solr.common.params.ModifiableSolrParams; @@ -382,48 +379,10 @@ public class SolrReturnFields extends ReturnFields { // let's try it as a function instead QParser parser = QParser.getParser(funcStr, FunctionQParserPlugin.NAME, req); - Query q = null; - ValueSource vs = null; - try { - if (parser instanceof FunctionQParser) { - FunctionQParser fparser = (FunctionQParser) parser; - fparser.setParseMultipleSources(false); - fparser.setParseToEnd(false); - - q = fparser.getQuery(); - - if (fparser.localParams != null) { - if (fparser.valFollowedParams) { - // need to find the end of the function query via the string parser - int leftOver = fparser.sp.end - fparser.sp.pos; - sp.pos = sp.end - leftOver; // reset our parser to the same amount of leftover - } else { - // the value was via the "v" param in localParams, so we need to find - // the end of the local params themselves to pick up where we left off - sp.pos = start + fparser.localParamsEnd; - } - } else { - // need to find the end of the function query via the string parser - int leftOver = fparser.sp.end - fparser.sp.pos; - sp.pos = sp.end - leftOver; // reset our parser to the same amount of leftover - } - } else { - // A QParser that's not for function queries. - // It must have been specified via local params. - q = parser.getQuery(); - - assert parser.getLocalParams() != null; - sp.pos = start + parser.localParamsEnd; - } + ValueSource vs = SortSpecParsing.parseValueSource(parser, sp, start); funcStr = sp.val.substring(start, sp.pos); - if (q instanceof FunctionQuery) { - vs = ((FunctionQuery) q).getValueSource(); - } else { - vs = new QueryValueSource(q, 0.0f); - } - if (key == null) { SolrParams localParams = parser.getLocalParams(); if (localParams != null) { diff --git a/solr/core/src/java/org/apache/solr/search/SortSpecParsing.java b/solr/core/src/java/org/apache/solr/search/SortSpecParsing.java index 6b71f139133..22430a19afe 100644 --- a/solr/core/src/java/org/apache/solr/search/SortSpecParsing.java +++ b/solr/core/src/java/org/apache/solr/search/SortSpecParsing.java @@ -19,9 +19,7 @@ package org.apache.solr.search; import java.util.ArrayList; import java.util.Collections; import java.util.List; -import org.apache.lucene.queries.function.FunctionQuery; -import org.apache.lucene.queries.function.valuesource.QueryValueSource; -import org.apache.lucene.search.Query; +import org.apache.lucene.queries.function.ValueSource; import org.apache.lucene.search.Sort; import org.apache.lucene.search.SortField; import org.apache.solr.common.SolrException; @@ -113,47 +111,13 @@ public class SortSpecParsing { String funcStr = sp.val.substring(start); QParser parser = QParser.getParser(funcStr, FunctionQParserPlugin.NAME, optionalReq); - Query q = null; try { - if (parser instanceof FunctionQParser) { - FunctionQParser fparser = (FunctionQParser) parser; - fparser.setParseMultipleSources(false); - fparser.setParseToEnd(false); - - q = fparser.getQuery(); - - if (fparser.localParams != null) { - if (fparser.valFollowedParams) { - // need to find the end of the function query via the string parser - int leftOver = fparser.sp.end - fparser.sp.pos; - sp.pos = sp.end - leftOver; // reset our parser to the same amount of leftover - } else { - // the value was via the "v" param in localParams, so we need to find - // the end of the local params themselves to pick up where we left off - sp.pos = start + fparser.localParamsEnd; - } - } else { - // need to find the end of the function query via the string parser - int leftOver = fparser.sp.end - fparser.sp.pos; - sp.pos = sp.end - leftOver; // reset our parser to the same amount of leftover - } - } else { - // A QParser that's not for function queries. - // It must have been specified via local params. - q = parser.getQuery(); - - assert parser.getLocalParams() != null; - sp.pos = start + parser.localParamsEnd; - } + ValueSource vs = parseValueSource(parser, sp, start); Boolean top = sp.getSortDirection(); if (null != top) { - // we have a Query and a valid direction - if (q instanceof FunctionQuery) { - sorts.add(((FunctionQuery) q).getValueSource().getSortField(top)); - } else { - sorts.add((new QueryValueSource(q, 0.0f)).getSortField(top)); - } + // we have a value source and a valid direction + sorts.add(vs.getSortField(top)); fields.add(null); continue; } @@ -221,6 +185,40 @@ public class SortSpecParsing { return new SortSpec(s, fields); } + static ValueSource parseValueSource(QParser parser, StrParser sp, int start) throws SyntaxError { + ValueSource vs; + if (parser instanceof FunctionQParser) { + FunctionQParser fparser = (FunctionQParser) parser; + fparser.setParseToEnd(false); + + vs = fparser.parseAsValueSource(); + + if (fparser.localParams != null) { + if (fparser.valFollowedParams) { + // need to find the end of the function query via the string parser + int leftOver = fparser.sp.end - fparser.sp.pos; + sp.pos = sp.end - leftOver; // reset our parser to the same amount of leftover + } else { + // the value was via the "v" param in localParams, so we need to find + // the end of the local params themselves to pick up where we left off + sp.pos = start + fparser.localParamsEnd; + } + } else { + // need to find the end of the function query via the string parser + int leftOver = fparser.sp.end - fparser.sp.pos; + sp.pos = sp.end - leftOver; // reset our parser to the same amount of leftover + } + } else { + // A QParser that's not for function queries. + // It must have been specified via local params. + vs = parser.parseAsValueSource(); + + assert parser.getLocalParams() != null; + sp.pos = start + parser.localParamsEnd; + } + return vs; + } + private static SortSpec newEmptySortSpec() { return new SortSpec(null, Collections.<SchemaField>emptyList()); } diff --git a/solr/core/src/java/org/apache/solr/search/ValueSourceParser.java b/solr/core/src/java/org/apache/solr/search/ValueSourceParser.java index a6bd40f8f49..c5c0d06dc7d 100644 --- a/solr/core/src/java/org/apache/solr/search/ValueSourceParser.java +++ b/solr/core/src/java/org/apache/solr/search/ValueSourceParser.java @@ -121,8 +121,11 @@ import org.apache.solr.util.plugin.NamedListInitializedPlugin; import org.locationtech.spatial4j.distance.DistanceUtils; /** - * A factory that parses user queries to generate ValueSource instances. Intended usage is to create - * pluggable, named functions for use in function queries. + * A factory parsing arguments (from {@link FunctionQParser}) into a real function whose results are + * emitted from a {@link ValueSource}. Custom ones can be registered by name and configured in + * {@code solrconfig.xml}. + * + * @see FunctionQParser */ public abstract class ValueSourceParser implements NamedListInitializedPlugin { /** Parse the user input into a ValueSource. */ diff --git a/solr/core/src/test/org/apache/solr/search/function/distance/DistanceFunctionTest.java b/solr/core/src/test/org/apache/solr/search/function/distance/DistanceFunctionTest.java index 1a6c85e5894..aad2052ec81 100644 --- a/solr/core/src/test/org/apache/solr/search/function/distance/DistanceFunctionTest.java +++ b/solr/core/src/test/org/apache/solr/search/function/distance/DistanceFunctionTest.java @@ -17,7 +17,7 @@ package org.apache.solr.search.function.distance; import org.apache.solr.SolrTestCaseJ4; -import org.apache.solr.common.SolrException; +import org.apache.solr.common.SolrException.ErrorCode; import org.junit.BeforeClass; import org.junit.Test; @@ -282,25 +282,24 @@ public class DistanceFunctionTest extends SolrTestCaseJ4 { "fq", "id:5"), "//float[@name='score']='" + (float) (2.3 * 2.3 + 5.5 * 5.5 + 7.9 * 7.9 + 2.4 * 2.4) + "'"); - // Pass in imbalanced list, throw exception - try { - ignoreException("Illegal number of sources"); - assertQ( - req( - "fl", - "*,score", - "q", - "{!func}sqedist(x_td, y_td, z_td, w_td, 0, 0, 0)", - "fq", - "id:1"), - "//float[@name='score']='0.0'"); - fail("should throw an exception"); - } catch (Exception e) { - Throwable cause = e.getCause(); - assertNotNull(cause); - assertTrue(cause instanceof SolrException); - } - resetExceptionIgnores(); + + assertQEx( + "(should fail)", + "Illegal number of sources", + req("q", "{!func}sqedist(x_td, y_td, z_td, w_td, 0, 0, 0)"), // odd args + ErrorCode.BAD_REQUEST); + + assertQEx( + "(should fail)", + "Unexpected text after function", + req("q", "{!func}sqedist(x_td, y_td), 0"), // text following the func call + ErrorCode.BAD_REQUEST); + + assertQEx( + "(should fail)", + "Unexpected text after function", + req("q", "{!func}x_td, y_td, z_td, w_td, 0, 0, 0"), + ErrorCode.BAD_REQUEST); // do one test of Euclidean // two dimensions, notice how we only pass in 4 value sources
