SOLR-15156: [child childFilter='...:...'] no longer escapes (#2367)

The query escaping it did was inconsistent with all other places in Solr where a Lucene query may be provided.
This commit is contained in:
David Smiley 2021-02-16 22:37:34 -05:00 committed by GitHub
parent 15bd858d34
commit 253b20c3c6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 29 additions and 8 deletions

View File

@ -75,6 +75,9 @@ Improvements
* SOLR-15011: /admin/logging handler will now propagate setLevel (log threshold) to all nodes * SOLR-15011: /admin/logging handler will now propagate setLevel (log threshold) to all nodes
when told to. The admin UI now tells it to. (Nazerke Seidan, David Smiley) when told to. The admin UI now tells it to. (Nazerke Seidan, David Smiley)
* SOLR-15156: [child] doc transformer's childFilter param no longer applies query syntax
escaping. It was inconsistent with other Solr options. (David Smiley)
Other Changes Other Changes
---------------------- ----------------------
* SOLR-14656: Autoscaling framework removed (Ishan Chattopadhyaya, noble, Ilan Ginzburg) * SOLR-14656: Autoscaling framework removed (Ishan Chattopadhyaya, noble, Ilan Ginzburg)

View File

@ -144,24 +144,24 @@ public class ChildDocTransformerFactory extends TransformerFactory {
try { try {
return QParser.getParser(qstr, req).getQuery(); return QParser.getParser(qstr, req).getQuery();
} catch (SyntaxError syntaxError) { } catch (SyntaxError syntaxError) {
throw new SolrException(ErrorCode.BAD_REQUEST, "Failed to parse '" + param + "' param."); throw new SolrException(
ErrorCode.BAD_REQUEST,
"Failed to parse '" + param + "' param: " + syntaxError.getMessage(),
syntaxError);
} }
} }
// NOTE: THIS FEATURE IS PRESENTLY EXPERIMENTAL; WAIT TO SEE IT IN THE REF GUIDE. FINAL SYNTAX IS TBD.
protected static String processPathHierarchyQueryString(String queryString) { protected static String processPathHierarchyQueryString(String queryString) {
// if the filter includes a path string, build a lucene query string to match those specific child documents. // if the filter includes a path string, build a lucene query string to match those specific child documents.
// e.g. /toppings/ingredients/name_s:cocoa -> +_nest_path_:/toppings/ingredients +(name_s:cocoa) // e.g. /toppings/ingredients/name_s:cocoa -> +_nest_path_:/toppings/ingredients +(name_s:cocoa)
// ingredients/name_s:cocoa -> +_nest_path_:*/ingredients +(name_s:cocoa) // ingredients/name_s:cocoa -> +_nest_path_:*/ingredients +(name_s:cocoa)
int indexOfFirstColon = queryString.indexOf(':'); int indexOfFirstColon = queryString.indexOf(':');
if (indexOfFirstColon <= 0) { if (indexOfFirstColon <= 0) {
return queryString;// give up return queryString; // regular filter, not hierarchy based.
} }
int indexOfLastPathSepChar = queryString.lastIndexOf(PATH_SEP_CHAR, indexOfFirstColon); int indexOfLastPathSepChar = queryString.lastIndexOf(PATH_SEP_CHAR, indexOfFirstColon);
if (indexOfLastPathSepChar < 0) { if (indexOfLastPathSepChar < 0) {
// regular filter, not hierarchy based. return queryString; // regular filter, not hierarchy based.
return ClientUtils.escapeQueryChars(queryString.substring(0, indexOfFirstColon))
+ ":" + ClientUtils.escapeQueryChars(queryString.substring(indexOfFirstColon + 1));
} }
final boolean isAbsolutePath = queryString.charAt(0) == PATH_SEP_CHAR; final boolean isAbsolutePath = queryString.charAt(0) == PATH_SEP_CHAR;
String path = ClientUtils.escapeQueryChars(queryString.substring(0, indexOfLastPathSepChar)); String path = ClientUtils.escapeQueryChars(queryString.substring(0, indexOfLastPathSepChar));

View File

@ -75,6 +75,21 @@ public class TestChildDocTransformerHierarchy extends SolrTestCaseJ4 {
assertU(commit()); assertU(commit());
} }
@Test
public void testNonTrivialChildFilter() throws Exception {
// just check we don't throw an exception. This used to throw before SOLR-15152
assertQ(
req(
"q",
"*:*",
"sort",
"id asc",
"fl",
"*, _nest_path_, [child childFilter='type_s:Regular OR type_s:Chocolate']",
"fq",
fqToExcludeNonTestedDocs));
}
@Test @Test
public void testParentFilterJSON() throws Exception { public void testParentFilterJSON() throws Exception {
indexSampleData(numberOfDocsPerNestedTest); indexSampleData(numberOfDocsPerNestedTest);
@ -111,7 +126,7 @@ public class TestChildDocTransformerHierarchy extends SolrTestCaseJ4 {
public void testParentFilterLimitJSON() throws Exception { public void testParentFilterLimitJSON() throws Exception {
indexSampleData(numberOfDocsPerNestedTest); indexSampleData(numberOfDocsPerNestedTest);
try(SolrQueryRequest req = req("q", "type_s:donut", "sort", "id asc", "fl", "id, type_s, toppings, _nest_path_, [child childFilter='_nest_path_:/toppings' limit=1]", try(SolrQueryRequest req = req("q", "type_s:donut", "sort", "id asc", "fl", "id, type_s, toppings, _nest_path_, [child childFilter='{!field f=_nest_path_}/toppings' limit=1]",
"fq", fqToExcludeNonTestedDocs)) { "fq", fqToExcludeNonTestedDocs)) {
BasicResultContext res = (BasicResultContext) h.queryAndResponse("/select", req).getResponse(); BasicResultContext res = (BasicResultContext) h.queryAndResponse("/select", req).getResponse();
Iterator<SolrDocument> docsStreamer = res.getProcessedDocuments(); Iterator<SolrDocument> docsStreamer = res.getProcessedDocuments();
@ -158,7 +173,7 @@ public class TestChildDocTransformerHierarchy extends SolrTestCaseJ4 {
assertU(delQ("_nest_path_:\\/toppings")); assertU(delQ("_nest_path_:\\/toppings"));
assertU(commit()); assertU(commit());
try(SolrQueryRequest req = req("q", "type_s:donut", "sort", "id asc", "fl", "id, type_s, toppings, _nest_path_, [child childFilter='_nest_path_:/toppings' limit=1]", try(SolrQueryRequest req = req("q", "type_s:donut", "sort", "id asc", "fl", "id, type_s, toppings, _nest_path_, [child childFilter='_nest_path_:\\\\/toppings' limit=1]",
"fq", fqToExcludeNonTestedDocs)) { "fq", fqToExcludeNonTestedDocs)) {
BasicResultContext res = (BasicResultContext) h.queryAndResponse("/select", req).getResponse(); BasicResultContext res = (BasicResultContext) h.queryAndResponse("/select", req).getResponse();
Iterator<SolrDocument> docsStreamer = res.getProcessedDocuments(); Iterator<SolrDocument> docsStreamer = res.getProcessedDocuments();

View File

@ -150,6 +150,9 @@ _(raw; not yet edited)_
* SOLR-15121: XSLTResponseWriter moved to /contrib/scripting/ package instead * SOLR-15121: XSLTResponseWriter moved to /contrib/scripting/ package instead
of shipping as part of Solr, due to security concerns. of shipping as part of Solr, due to security concerns.
* SOLR-15156: Child Doc Transformer's `childFilter` param no longer applies query syntax
escaping because it's inconsistent with the rest of Solr and was limiting. This refers to `[child childFilter='field:value']`.
=== Upgrade Prerequisites in Solr 9 === Upgrade Prerequisites in Solr 9
* Upgrade all collections in stateFormat=1 to stateFormat=2 *before* upgrading to Solr 9, as Solr 9 does not support the * Upgrade all collections in stateFormat=1 to stateFormat=2 *before* upgrading to Solr 9, as Solr 9 does not support the