Fix simple_query_string on invalid input (#28219)

This change converts any exception that occurs during the parsing of
a simple_query_string to a match_no_docs query (instead of a null query)
when leniency is activated.

Closes #28204
This commit is contained in:
Jim Ferenczi 2018-01-18 10:49:34 +01:00 committed by GitHub
parent 06f931fcc4
commit c38c12e3bf
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 25 additions and 6 deletions

View File

@ -33,6 +33,7 @@ import org.apache.lucene.search.PrefixQuery;
import org.apache.lucene.search.Query; import org.apache.lucene.search.Query;
import org.apache.lucene.search.SynonymQuery; import org.apache.lucene.search.SynonymQuery;
import org.apache.lucene.util.BytesRef; import org.apache.lucene.util.BytesRef;
import org.elasticsearch.common.lucene.search.Queries;
import org.elasticsearch.common.unit.Fuzziness; import org.elasticsearch.common.unit.Fuzziness;
import org.elasticsearch.index.mapper.MappedFieldType; import org.elasticsearch.index.mapper.MappedFieldType;
import org.elasticsearch.index.query.AbstractQueryBuilder; import org.elasticsearch.index.query.AbstractQueryBuilder;
@ -86,11 +87,11 @@ public class SimpleQueryStringQueryParser extends SimpleQueryParser {
} }
/** /**
* Rethrow the runtime exception, unless the lenient flag has been set, returns null * Rethrow the runtime exception, unless the lenient flag has been set, returns {@link MatchNoDocsQuery}
*/ */
private Query rethrowUnlessLenient(RuntimeException e) { private Query rethrowUnlessLenient(RuntimeException e) {
if (settings.lenient()) { if (settings.lenient()) {
return null; return Queries.newMatchNoDocsQuery("failed query, caused by " + e.getMessage());
} }
throw e; throw e;
} }
@ -115,7 +116,7 @@ public class SimpleQueryStringQueryParser extends SimpleQueryParser {
try { try {
return queryBuilder.parse(MultiMatchQueryBuilder.Type.MOST_FIELDS, weights, text, null); return queryBuilder.parse(MultiMatchQueryBuilder.Type.MOST_FIELDS, weights, text, null);
} catch (IOException e) { } catch (IOException e) {
return rethrowUnlessLenient(new IllegalArgumentException(e.getMessage())); return rethrowUnlessLenient(new IllegalStateException(e.getMessage()));
} }
} }
@ -135,7 +136,7 @@ public class SimpleQueryStringQueryParser extends SimpleQueryParser {
settings.fuzzyMaxExpansions, settings.fuzzyTranspositions); settings.fuzzyMaxExpansions, settings.fuzzyTranspositions);
disjuncts.add(wrapWithBoost(query, entry.getValue())); disjuncts.add(wrapWithBoost(query, entry.getValue()));
} catch (RuntimeException e) { } catch (RuntimeException e) {
rethrowUnlessLenient(e); disjuncts.add(rethrowUnlessLenient(e));
} }
} }
if (disjuncts.size() == 1) { if (disjuncts.size() == 1) {
@ -156,7 +157,7 @@ public class SimpleQueryStringQueryParser extends SimpleQueryParser {
} }
return queryBuilder.parse(MultiMatchQueryBuilder.Type.PHRASE, phraseWeights, text, null); return queryBuilder.parse(MultiMatchQueryBuilder.Type.PHRASE, phraseWeights, text, null);
} catch (IOException e) { } catch (IOException e) {
return rethrowUnlessLenient(new IllegalArgumentException(e.getMessage())); return rethrowUnlessLenient(new IllegalStateException(e.getMessage()));
} finally { } finally {
queryBuilder.setPhraseSlop(0); queryBuilder.setPhraseSlop(0);
} }
@ -184,7 +185,7 @@ public class SimpleQueryStringQueryParser extends SimpleQueryParser {
disjuncts.add(wrapWithBoost(query, entry.getValue())); disjuncts.add(wrapWithBoost(query, entry.getValue()));
} }
} catch (RuntimeException e) { } catch (RuntimeException e) {
return rethrowUnlessLenient(e); disjuncts.add(rethrowUnlessLenient(e));
} }
} }
if (disjuncts.size() == 1) { if (disjuncts.size() == 1) {

View File

@ -46,15 +46,18 @@ import org.elasticsearch.search.internal.SearchContext;
import org.elasticsearch.test.AbstractQueryTestCase; import org.elasticsearch.test.AbstractQueryTestCase;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.List;
import java.util.Locale; import java.util.Locale;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import static org.hamcrest.Matchers.anyOf; import static org.hamcrest.Matchers.anyOf;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.either; import static org.hamcrest.Matchers.either;
import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.instanceOf; import static org.hamcrest.Matchers.instanceOf;
@ -607,6 +610,21 @@ public class SimpleQueryStringBuilderTests extends AbstractQueryTestCase<SimpleQ
assertEquals(expected, query); assertEquals(expected, query);
} }
public void testLenientToPrefixQuery() throws Exception {
assumeTrue("test runs only when at least a type is registered", getCurrentTypes().length > 0);
Query query = new SimpleQueryStringBuilder("t*")
.field(DATE_FIELD_NAME)
.field(STRING_FIELD_NAME)
.lenient(true)
.toQuery(createShardContext());
List<Query> expectedQueries = new ArrayList<>();
expectedQueries.add(new MatchNoDocsQuery(""));
expectedQueries.add(new PrefixQuery(new Term(STRING_FIELD_NAME, "t")));
DisjunctionMaxQuery expected = new DisjunctionMaxQuery(expectedQueries, 1.0f);
assertEquals(expected, query);
}
private static IndexMetaData newIndexMeta(String name, Settings oldIndexSettings, Settings indexSettings) { private static IndexMetaData newIndexMeta(String name, Settings oldIndexSettings, Settings indexSettings) {
Settings build = Settings.builder().put(oldIndexSettings) Settings build = Settings.builder().put(oldIndexSettings)
.put(indexSettings) .put(indexSettings)