Query Refactoring: moving validation to constructors and setters

This PR is an initial step to move the query validation we started
to collect in the validate() method to the corresponding setters
and constructors.
This commit is contained in:
Christoph Büscher 2015-09-16 17:40:02 +02:00
parent 125be0a05f
commit 887399eebf
28 changed files with 283 additions and 347 deletions

View File

@ -68,6 +68,9 @@ public class BoolQueryBuilder extends AbstractQueryBuilder<BoolQueryBuilder> {
* contribute to scoring. No <tt>null</tt> value allowed.
*/
public BoolQueryBuilder must(QueryBuilder queryBuilder) {
if (queryBuilder == null) {
throw new IllegalArgumentException("inner bool query clause cannot be null");
}
mustClauses.add(queryBuilder);
return this;
}
@ -84,6 +87,9 @@ public class BoolQueryBuilder extends AbstractQueryBuilder<BoolQueryBuilder> {
* not contribute to scoring. No <tt>null</tt> value allowed.
*/
public BoolQueryBuilder filter(QueryBuilder queryBuilder) {
if (queryBuilder == null) {
throw new IllegalArgumentException("inner bool query clause cannot be null");
}
filterClauses.add(queryBuilder);
return this;
}
@ -100,6 +106,9 @@ public class BoolQueryBuilder extends AbstractQueryBuilder<BoolQueryBuilder> {
* No <tt>null</tt> value allowed.
*/
public BoolQueryBuilder mustNot(QueryBuilder queryBuilder) {
if (queryBuilder == null) {
throw new IllegalArgumentException("inner bool query clause cannot be null");
}
mustNotClauses.add(queryBuilder);
return this;
}
@ -119,6 +128,9 @@ public class BoolQueryBuilder extends AbstractQueryBuilder<BoolQueryBuilder> {
* @see #minimumNumberShouldMatch(int)
*/
public BoolQueryBuilder should(QueryBuilder queryBuilder) {
if (queryBuilder == null) {
throw new IllegalArgumentException("inner bool query clause cannot be null");
}
shouldClauses.add(queryBuilder);
return this;
}
@ -264,16 +276,6 @@ public class BoolQueryBuilder extends AbstractQueryBuilder<BoolQueryBuilder> {
return adjustPureNegative ? fixNegativeQueryIfNeeded(booleanQuery) : booleanQuery;
}
@Override
public QueryValidationException validate() {
QueryValidationException validationException = null;
validationException = validateInnerQueries(mustClauses, validationException);
validationException = validateInnerQueries(shouldClauses, validationException);
validationException = validateInnerQueries(mustNotClauses, validationException);
validationException = validateInnerQueries(filterClauses, validationException);
return validationException;
}
private void addBooleanClauses(QueryShardContext context, BooleanQuery.Builder booleanQueryBuilder, List<QueryBuilder> clauses, Occur occurs) throws IOException {
for (QueryBuilder query : clauses) {
Query luceneQuery = null;

View File

@ -50,7 +50,7 @@ public class BoostingQueryBuilder extends AbstractQueryBuilder<BoostingQueryBuil
private float negativeBoost = -1;
static final BoostingQueryBuilder PROTOTYPE = new BoostingQueryBuilder(null, null);
static final BoostingQueryBuilder PROTOTYPE = new BoostingQueryBuilder(EmptyQueryBuilder.PROTOTYPE, EmptyQueryBuilder.PROTOTYPE);
/**
* Create a new {@link BoostingQueryBuilder}
@ -59,6 +59,12 @@ public class BoostingQueryBuilder extends AbstractQueryBuilder<BoostingQueryBuil
* @param negativeQuery the negative query for this boosting query.
*/
public BoostingQueryBuilder(QueryBuilder positiveQuery, QueryBuilder negativeQuery) {
if (positiveQuery == null) {
throw new IllegalArgumentException("inner clause [positive] cannot be null.");
}
if (negativeQuery == null) {
throw new IllegalArgumentException("inner clause [negative] cannot be null.");
}
this.positiveQuery = positiveQuery;
this.negativeQuery = negativeQuery;
}
@ -81,6 +87,9 @@ public class BoostingQueryBuilder extends AbstractQueryBuilder<BoostingQueryBuil
* Set the negative boost factor.
*/
public BoostingQueryBuilder negativeBoost(float negativeBoost) {
if (negativeBoost < 0) {
throw new IllegalArgumentException("query requires negativeBoost to be set to positive value");
}
this.negativeBoost = negativeBoost;
return this;
}
@ -104,25 +113,6 @@ public class BoostingQueryBuilder extends AbstractQueryBuilder<BoostingQueryBuil
builder.endObject();
}
@Override
public QueryValidationException validate() {
QueryValidationException validationException = null;
if (negativeBoost < 0) {
validationException = addValidationError("query requires negativeBoost to be set to positive value", validationException);
}
if (negativeQuery == null) {
validationException = addValidationError("inner clause [negative] cannot be null.", validationException);
} else {
validationException = validateInnerQuery(negativeQuery, validationException);
}
if (positiveQuery == null) {
validationException = addValidationError("inner clause [positive] cannot be null.", validationException);
} else {
validationException = validateInnerQuery(positiveQuery, validationException);
}
return validationException;
}
@Override
public String getWriteableName() {
return NAME;

View File

@ -85,12 +85,18 @@ public class CommonTermsQueryBuilder extends AbstractQueryBuilder<CommonTermsQue
private float cutoffFrequency = DEFAULT_CUTOFF_FREQ;
static final CommonTermsQueryBuilder PROTOTYPE = new CommonTermsQueryBuilder(null, null);
static final CommonTermsQueryBuilder PROTOTYPE = new CommonTermsQueryBuilder("field", "text");
/**
* Constructs a new common terms query.
*/
public CommonTermsQueryBuilder(String fieldName, Object text) {
if (Strings.isEmpty(fieldName)) {
throw new IllegalArgumentException("field name is null or empty");
}
if (text == null) {
throw new IllegalArgumentException("text cannot be null.");
}
this.fieldName = fieldName;
this.text = text;
}
@ -281,18 +287,6 @@ public class CommonTermsQueryBuilder extends AbstractQueryBuilder<CommonTermsQue
return query;
}
@Override
public QueryValidationException validate() {
QueryValidationException validationException = null;
if (Strings.isEmpty(this.fieldName)) {
validationException = addValidationError("field name cannot be null or empty.", validationException);
}
if (this.text == null) {
validationException = addValidationError("query text cannot be null", validationException);
}
return validationException;
}
@Override
protected CommonTermsQueryBuilder doReadFrom(StreamInput in) throws IOException {
CommonTermsQueryBuilder commonTermsQueryBuilder = new CommonTermsQueryBuilder(in.readString(), in.readGenericValue());

View File

@ -38,7 +38,7 @@ public class ConstantScoreQueryBuilder extends AbstractQueryBuilder<ConstantScor
private final QueryBuilder filterBuilder;
static final ConstantScoreQueryBuilder PROTOTYPE = new ConstantScoreQueryBuilder(null);
static final ConstantScoreQueryBuilder PROTOTYPE = new ConstantScoreQueryBuilder(EmptyQueryBuilder.PROTOTYPE);
/**
* A query that wraps another query and simply returns a constant score equal to the
@ -47,6 +47,9 @@ public class ConstantScoreQueryBuilder extends AbstractQueryBuilder<ConstantScor
* @param filterBuilder The query to wrap in a constant score query
*/
public ConstantScoreQueryBuilder(QueryBuilder filterBuilder) {
if (filterBuilder == null) {
throw new IllegalArgumentException("inner clause [filter] cannot be null.");
}
this.filterBuilder = filterBuilder;
}
@ -76,17 +79,6 @@ public class ConstantScoreQueryBuilder extends AbstractQueryBuilder<ConstantScor
return new ConstantScoreQuery(innerFilter);
}
@Override
public QueryValidationException validate() {
QueryValidationException validationException = null;
if (filterBuilder == null) {
validationException = addValidationError("inner clause [filter] cannot be null.", validationException);
} else {
validationException = validateInnerQuery(filterBuilder, validationException);
}
return validationException;
}
@Override
public String getWriteableName() {
return NAME;

View File

@ -21,7 +21,6 @@ package org.elasticsearch.index.query;
import org.elasticsearch.common.ParseField;
import org.elasticsearch.common.Strings;
import org.elasticsearch.common.inject.Inject;
import org.elasticsearch.common.xcontent.XContentParser;
import java.io.IOException;

View File

@ -52,6 +52,9 @@ public class DisMaxQueryBuilder extends AbstractQueryBuilder<DisMaxQueryBuilder>
* Add a sub-query to this disjunction.
*/
public DisMaxQueryBuilder add(QueryBuilder queryBuilder) {
if (queryBuilder == null) {
throw new IllegalArgumentException("inner dismax query clause cannot be null");
}
queries.add(queryBuilder);
return this;
}
@ -106,11 +109,6 @@ public class DisMaxQueryBuilder extends AbstractQueryBuilder<DisMaxQueryBuilder>
return new DisjunctionMaxQuery(luceneQueries, tieBreaker);
}
@Override
public QueryValidationException validate() {
return validateInnerQueries(queries, null);
}
@Override
protected DisMaxQueryBuilder doReadFrom(StreamInput in) throws IOException {
DisMaxQueryBuilder disMax = new DisMaxQueryBuilder();

View File

@ -20,6 +20,7 @@
package org.elasticsearch.index.query;
import org.apache.lucene.search.*;
import org.elasticsearch.common.Strings;
import org.elasticsearch.common.io.stream.StreamInput;
import org.elasticsearch.common.io.stream.StreamOutput;
import org.elasticsearch.common.lucene.search.Queries;
@ -41,9 +42,12 @@ public class ExistsQueryBuilder extends AbstractQueryBuilder<ExistsQueryBuilder>
private final String fieldName;
static final ExistsQueryBuilder PROTOTYPE = new ExistsQueryBuilder(null);
static final ExistsQueryBuilder PROTOTYPE = new ExistsQueryBuilder("field");
public ExistsQueryBuilder(String fieldName) {
if (Strings.isEmpty(fieldName)) {
throw new IllegalArgumentException("field name is null or empty");
}
this.fieldName = fieldName;
}
@ -67,12 +71,6 @@ public class ExistsQueryBuilder extends AbstractQueryBuilder<ExistsQueryBuilder>
return newFilter(context, fieldName);
}
@Override
public QueryValidationException validate() {
// nothing to validate
return null;
}
public static Query newFilter(QueryShardContext context, String fieldPattern) {
final FieldNamesFieldMapper.FieldNamesFieldType fieldNamesFieldType = (FieldNamesFieldMapper.FieldNamesFieldType)context.mapperService().fullName(FieldNamesFieldMapper.NAME);
if (fieldNamesFieldType == null) {

View File

@ -22,6 +22,7 @@ package org.elasticsearch.index.query;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.spans.FieldMaskingSpanQuery;
import org.apache.lucene.search.spans.SpanQuery;
import org.elasticsearch.common.Strings;
import org.elasticsearch.common.io.stream.StreamInput;
import org.elasticsearch.common.io.stream.StreamOutput;
import org.elasticsearch.common.xcontent.XContentBuilder;
@ -38,7 +39,7 @@ public class FieldMaskingSpanQueryBuilder extends AbstractQueryBuilder<FieldMask
private final String fieldName;
static final FieldMaskingSpanQueryBuilder PROTOTYPE = new FieldMaskingSpanQueryBuilder(null, null);
static final FieldMaskingSpanQueryBuilder PROTOTYPE = new FieldMaskingSpanQueryBuilder(new SpanTermQueryBuilder("field", "text"), "field");
/**
* Constructs a new {@link FieldMaskingSpanQueryBuilder} given an inner {@link SpanQueryBuilder} for
@ -47,6 +48,12 @@ public class FieldMaskingSpanQueryBuilder extends AbstractQueryBuilder<FieldMask
* @param fieldName the field name
*/
public FieldMaskingSpanQueryBuilder(SpanQueryBuilder queryBuilder, String fieldName) {
if (Strings.isEmpty(fieldName)) {
throw new IllegalArgumentException("field name is null or empty");
}
if (queryBuilder == null) {
throw new IllegalArgumentException("inner clause [query] cannot be null.");
}
this.queryBuilder = queryBuilder;
this.fieldName = fieldName;
}
@ -87,20 +94,6 @@ public class FieldMaskingSpanQueryBuilder extends AbstractQueryBuilder<FieldMask
return new FieldMaskingSpanQuery((SpanQuery)innerQuery, fieldInQuery);
}
@Override
public QueryValidationException validate() {
QueryValidationException validationException = null;
if (queryBuilder == null) {
validationException = addValidationError("inner clause [query] cannot be null.", validationException);
} else {
validationException = validateInnerQuery(queryBuilder, validationException);
}
if (fieldName == null || fieldName.isEmpty()) {
validationException = addValidationError("field name is null or empty", validationException);
}
return validationException;
}
@Override
protected FieldMaskingSpanQueryBuilder doReadFrom(StreamInput in) throws IOException {
QueryBuilder innerQueryBuilder = in.readQuery();

View File

@ -51,7 +51,7 @@ public class FuzzyQueryBuilder extends AbstractQueryBuilder<FuzzyQueryBuilder> i
/** Default maximum number of terms that the fuzzy query will expand to. Defaults to 50. */
public static final int DEFAULT_MAX_EXPANSIONS = FuzzyQuery.defaultMaxExpansions;
/** Default as to whether transpositions should be treated as a primitive edit operation,
/** Default as to whether transpositions should be treated as a primitive edit operation,
* instead of classic Levenshtein algorithm. Defaults to false. */
public static final boolean DEFAULT_TRANSPOSITIONS = false;
@ -70,7 +70,7 @@ public class FuzzyQueryBuilder extends AbstractQueryBuilder<FuzzyQueryBuilder> i
private String rewrite;
static final FuzzyQueryBuilder PROTOTYPE = new FuzzyQueryBuilder(null, null);
static final FuzzyQueryBuilder PROTOTYPE = new FuzzyQueryBuilder();
/**
* Constructs a new fuzzy query.
@ -139,10 +139,22 @@ public class FuzzyQueryBuilder extends AbstractQueryBuilder<FuzzyQueryBuilder> i
* @param value The value of the term
*/
public FuzzyQueryBuilder(String fieldName, Object value) {
if (Strings.isEmpty(fieldName)) {
throw new IllegalArgumentException("field name cannot be null or empty.");
}
if (value == null) {
throw new IllegalArgumentException("query value cannot be null");
}
this.fieldName = fieldName;
this.value = convertToBytesRefIfString(value);
}
private FuzzyQueryBuilder() {
// for protoype
this.fieldName = null;
this.value = null;
}
public String fieldName() {
return this.fieldName;
}
@ -155,7 +167,7 @@ public class FuzzyQueryBuilder extends AbstractQueryBuilder<FuzzyQueryBuilder> i
this.fuzziness = (fuzziness == null) ? DEFAULT_FUZZINESS : fuzziness;
return this;
}
public Fuzziness fuzziness() {
return this.fuzziness;
}
@ -164,7 +176,7 @@ public class FuzzyQueryBuilder extends AbstractQueryBuilder<FuzzyQueryBuilder> i
this.prefixLength = prefixLength;
return this;
}
public int prefixLength() {
return this.prefixLength;
}
@ -239,18 +251,6 @@ public class FuzzyQueryBuilder extends AbstractQueryBuilder<FuzzyQueryBuilder> i
return query;
}
@Override
public QueryValidationException validate() {
QueryValidationException validationException = null;
if (Strings.isEmpty(this.fieldName)) {
validationException = addValidationError("field name cannot be null or empty.", validationException);
}
if (this.value == null) {
validationException = addValidationError("query text cannot be null", validationException);
}
return validationException;
}
@Override
public FuzzyQueryBuilder doReadFrom(StreamInput in) throws IOException {
FuzzyQueryBuilder fuzzyQueryBuilder = new FuzzyQueryBuilder(in.readString(), in.readGenericValue());

View File

@ -42,12 +42,7 @@ public class IndicesQueryBuilder extends AbstractQueryBuilder<IndicesQueryBuilde
private QueryBuilder noMatchQuery = defaultNoMatchQuery();
static final IndicesQueryBuilder PROTOTYPE = new IndicesQueryBuilder();
private IndicesQueryBuilder() {
this.innerQuery = null;
this.indices = null;
}
static final IndicesQueryBuilder PROTOTYPE = new IndicesQueryBuilder(EmptyQueryBuilder.PROTOTYPE, "index");
public IndicesQueryBuilder(QueryBuilder innerQuery, String... indices) {
this.innerQuery = Objects.requireNonNull(innerQuery);
@ -118,7 +113,7 @@ public class IndicesQueryBuilder extends AbstractQueryBuilder<IndicesQueryBuilde
query.setBoost(boost);
}
}
@Override
public QueryValidationException validate() {
QueryValidationException validationException = null;
@ -146,12 +141,12 @@ public class IndicesQueryBuilder extends AbstractQueryBuilder<IndicesQueryBuilde
out.writeStringArray(indices);
out.writeQuery(noMatchQuery);
}
@Override
public int doHashCode() {
return Objects.hash(innerQuery, noMatchQuery, Arrays.hashCode(indices));
}
@Override
protected boolean doEquals(IndicesQueryBuilder other) {
return Objects.equals(innerQuery, other.innerQuery) &&

View File

@ -48,12 +48,6 @@ public class MatchAllQueryBuilder extends AbstractQueryBuilder<MatchAllQueryBuil
return Queries.newMatchAllQuery();
}
@Override
public QueryValidationException validate() {
// nothing to validate
return null;
}
@Override
protected boolean doEquals(MatchAllQueryBuilder other) {
return true;

View File

@ -52,12 +52,6 @@ public class MatchNoneQueryBuilder extends AbstractQueryBuilder<MatchNoneQueryBu
//no-op this query doesn't support boost
}
@Override
public QueryValidationException validate() {
// nothing to validate
return null;
}
@Override
protected boolean doEquals(MatchNoneQueryBuilder other) {
return true;

View File

@ -19,7 +19,11 @@
package org.elasticsearch.index.query;
import org.apache.lucene.search.*;
import org.apache.lucene.search.BooleanClause;
import org.apache.lucene.search.BooleanQuery;
import org.apache.lucene.search.ConstantScoreQuery;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.TermRangeQuery;
import org.elasticsearch.common.Strings;
import org.elasticsearch.common.io.stream.StreamInput;
import org.elasticsearch.common.io.stream.StreamOutput;
@ -50,25 +54,37 @@ public class MissingQueryBuilder extends AbstractQueryBuilder<MissingQueryBuilde
private boolean existence = DEFAULT_EXISTENCE_VALUE;
static final MissingQueryBuilder PROTOTYPE = new MissingQueryBuilder(null);
static final MissingQueryBuilder PROTOTYPE = new MissingQueryBuilder("field", DEFAULT_NULL_VALUE, DEFAULT_EXISTENCE_VALUE);
/**
* Constructs a filter that returns documents with only null values or no value in the original field.
* @param fieldPattern the field to query
* @param nullValue should the missing filter automatically include fields with null value configured in the
* mappings. Defaults to <tt>false</tt>.
* @param existance should the missing filter include documents where the field doesn't exist in the docs.
* Defaults to <tt>true</tt>.
* @throws IllegalArgumentException when both <tt>existence</tt> and <tt>nullValue</tt> are set to false
*/
public MissingQueryBuilder(String fieldPattern, boolean nullValue, boolean existence) {
if (Strings.isEmpty(fieldPattern)) {
throw new IllegalArgumentException("missing query must be provided with a [field]");
}
if (nullValue == false && existence == false) {
throw new IllegalArgumentException("missing query must have either 'existence', or 'null_value', or both set to true");
}
this.fieldPattern = fieldPattern;
this.nullValue = nullValue;
this.existence = existence;
}
public MissingQueryBuilder(String fieldPattern) {
this.fieldPattern = fieldPattern;
this(fieldPattern, DEFAULT_NULL_VALUE, DEFAULT_EXISTENCE_VALUE);
}
public String fieldPattern() {
return this.fieldPattern;
}
/**
* Should the missing filter automatically include fields with null value configured in the
* mappings. Defaults to <tt>false</tt>.
*/
public MissingQueryBuilder nullValue(boolean nullValue) {
this.nullValue = nullValue;
return this;
}
/**
* Returns true if the missing filter will include documents where the field contains a null value, otherwise
* these documents will not be included.
@ -77,15 +93,6 @@ public class MissingQueryBuilder extends AbstractQueryBuilder<MissingQueryBuilde
return this.nullValue;
}
/**
* Should the missing filter include documents where the field doesn't exist in the docs.
* Defaults to <tt>true</tt>.
*/
public MissingQueryBuilder existence(boolean existence) {
this.existence = existence;
return this;
}
/**
* Returns true if the missing filter will include documents where the field has no values, otherwise
* these documents will not be included.
@ -201,24 +208,9 @@ public class MissingQueryBuilder extends AbstractQueryBuilder<MissingQueryBuilde
return new ConstantScoreQuery(filter);
}
@Override
public QueryValidationException validate() {
QueryValidationException validationException = null;
if (Strings.isEmpty(this.fieldPattern)) {
validationException = addValidationError("missing must be provided with a [field]", validationException);
}
if (!existence && !nullValue) {
validationException = addValidationError("missing must have either existence, or null_value, or both set to true", validationException);
}
return validationException;
}
@Override
protected MissingQueryBuilder doReadFrom(StreamInput in) throws IOException {
MissingQueryBuilder missingQueryBuilder = new MissingQueryBuilder(in.readString());
missingQueryBuilder.nullValue = in.readBoolean();
missingQueryBuilder.existence = in.readBoolean();
return missingQueryBuilder;
return new MissingQueryBuilder(in.readString(), in.readBoolean(), in.readBoolean());
}
@Override

View File

@ -19,7 +19,6 @@
package org.elasticsearch.index.query;
import org.elasticsearch.common.inject.Inject;
import org.elasticsearch.common.xcontent.XContentParser;
import java.io.IOException;
@ -69,9 +68,7 @@ public class MissingQueryParser extends BaseQueryParser<MissingQueryBuilder> {
if (fieldPattern == null) {
throw new QueryParsingException(parseContext, "missing must be provided with a [field]");
}
return new MissingQueryBuilder(fieldPattern)
.nullValue(nullValue)
.existence(existence)
return new MissingQueryBuilder(fieldPattern, nullValue, existence)
.boost(boost)
.queryName(queryName);
}

View File

@ -19,7 +19,6 @@
package org.elasticsearch.index.query;
import org.elasticsearch.common.inject.Inject;
import org.elasticsearch.common.unit.Fuzziness;
import org.elasticsearch.common.xcontent.XContentParser;
import org.elasticsearch.index.search.MatchQuery;

View File

@ -757,11 +757,23 @@ public abstract class QueryBuilders {
/**
* A filter to filter only documents where a field does not exists in them.
*
* @param name The name of the field
* @param fieldPattern the field to query
*/
public static MissingQueryBuilder missingQuery(String name) {
return new MissingQueryBuilder(name);
return missingQuery(name, MissingQueryBuilder.DEFAULT_NULL_VALUE, MissingQueryBuilder.DEFAULT_EXISTENCE_VALUE);
}
/**
* A filter to filter only documents where a field does not exists in them.
* @param fieldPattern the field to query
* @param nullValue should the missing filter automatically include fields with null value configured in the
* mappings. Defaults to <tt>false</tt>.
* @param existence should the missing filter include documents where the field doesn't exist in the docs.
* Defaults to <tt>true</tt>.
* @throws IllegalArgumentException when both <tt>existence</tt> and <tt>nullValue</tt> are set to false
*/
public static MissingQueryBuilder missingQuery(String name, boolean nullValue, boolean existence) {
return new MissingQueryBuilder(name, nullValue, existence);
}
public static NotQueryBuilder notQuery(QueryBuilder filter) {

View File

@ -146,61 +146,31 @@ public class BoolQueryBuilderTests extends AbstractQueryTestCase<BoolQueryBuilde
}
@Test
public void testValidate() {
public void testIllegalArguments() {
BoolQueryBuilder booleanQuery = new BoolQueryBuilder();
int iters = randomIntBetween(0, 3);
int totalExpectedErrors = 0;
for (int i = 0; i < iters; i++) {
if (randomBoolean()) {
if (randomBoolean()) {
booleanQuery.must(RandomQueryBuilder.createInvalidQuery(random()));
} else {
booleanQuery.must(null);
}
totalExpectedErrors++;
} else {
booleanQuery.must(RandomQueryBuilder.createQuery(random()));
}
try {
booleanQuery.must(null);
fail("cannot be null");
} catch (IllegalArgumentException e) {
}
iters = randomIntBetween(0, 3);
for (int i = 0; i < iters; i++) {
if (randomBoolean()) {
if (randomBoolean()) {
booleanQuery.should(RandomQueryBuilder.createInvalidQuery(random()));
} else {
booleanQuery.should(null);
}
totalExpectedErrors++;
} else {
booleanQuery.should(RandomQueryBuilder.createQuery(random()));
}
try {
booleanQuery.mustNot(null);
fail("cannot be null");
} catch (IllegalArgumentException e) {
}
iters = randomIntBetween(0, 3);
for (int i = 0; i < iters; i++) {
if (randomBoolean()) {
if (randomBoolean()) {
booleanQuery.mustNot(RandomQueryBuilder.createInvalidQuery(random()));
} else {
booleanQuery.mustNot(null);
}
totalExpectedErrors++;
} else {
booleanQuery.mustNot(RandomQueryBuilder.createQuery(random()));
}
try {
booleanQuery.filter(null);
fail("cannot be null");
} catch (IllegalArgumentException e) {
}
iters = randomIntBetween(0, 3);
for (int i = 0; i < iters; i++) {
if (randomBoolean()) {
if (randomBoolean()) {
booleanQuery.filter(RandomQueryBuilder.createInvalidQuery(random()));
} else {
booleanQuery.filter(null);
}
totalExpectedErrors++;
} else {
booleanQuery.filter(RandomQueryBuilder.createQuery(random()));
}
try {
booleanQuery.should(null);
fail("cannot be null");
} catch (IllegalArgumentException e) {
}
assertValidate(booleanQuery, totalExpectedErrors);
}
}

View File

@ -49,33 +49,26 @@ public class BoostingQueryBuilderTests extends AbstractQueryTestCase<BoostingQue
}
@Test
public void testValidate() {
int totalExpectedErrors = 0;
QueryBuilder positive = null;
QueryBuilder negative = null;
if (frequently()) {
if (randomBoolean()) {
negative = RandomQueryBuilder.createInvalidQuery(random());
}
totalExpectedErrors++;
} else {
negative = RandomQueryBuilder.createQuery(random());
public void testIllegalArguments() {
try {
new BoostingQueryBuilder(null, new MatchAllQueryBuilder());
fail("must not be null");
} catch (IllegalArgumentException e) {
//
}
if (frequently()) {
if (randomBoolean()) {
positive = RandomQueryBuilder.createInvalidQuery(random());
}
totalExpectedErrors++;
} else {
positive = RandomQueryBuilder.createQuery(random());
try {
new BoostingQueryBuilder(new MatchAllQueryBuilder(), null);
fail("must not be null");
} catch (IllegalArgumentException e) {
//
}
BoostingQueryBuilder boostingQuery = new BoostingQueryBuilder(positive, negative);
if (frequently()) {
boostingQuery.negativeBoost(0.5f);
} else {
boostingQuery.negativeBoost(-0.5f);
totalExpectedErrors++;
try {
new BoostingQueryBuilder(new MatchAllQueryBuilder(), new MatchAllQueryBuilder()).negativeBoost(-1.0f);
fail("must not be negative");
} catch (IllegalArgumentException e) {
//
}
assertValidate(boostingQuery, totalExpectedErrors);
}
}

View File

@ -27,7 +27,6 @@ import java.io.IOException;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.instanceOf;
import static org.hamcrest.Matchers.is;
public class CommonTermsQueryBuilderTests extends AbstractQueryTestCase<CommonTermsQueryBuilder> {
@ -84,15 +83,24 @@ public class CommonTermsQueryBuilderTests extends AbstractQueryTestCase<CommonTe
}
@Test
public void testValidate() {
CommonTermsQueryBuilder commonTermsQueryBuilder = new CommonTermsQueryBuilder("", "text");
assertThat(commonTermsQueryBuilder.validate().validationErrors().size(), is(1));
public void testIllegalArguments() {
try {
if (randomBoolean()) {
new CommonTermsQueryBuilder(null, "text");
} else {
new CommonTermsQueryBuilder("", "text");
}
fail("must be non null");
} catch (IllegalArgumentException e) {
// okay
}
commonTermsQueryBuilder = new CommonTermsQueryBuilder("field", null);
assertThat(commonTermsQueryBuilder.validate().validationErrors().size(), is(1));
commonTermsQueryBuilder = new CommonTermsQueryBuilder("field", "text");
assertNull(commonTermsQueryBuilder.validate());
try {
new CommonTermsQueryBuilder("fieldName", null);
fail("must be non null");
} catch (IllegalArgumentException e) {
// okay
}
}
@Test

View File

@ -59,18 +59,12 @@ public class ConstantScoreQueryBuilderTests extends AbstractQueryTestCase<Consta
}
@Test
public void testValidate() {
QueryBuilder innerQuery = null;
int totalExpectedErrors = 0;
if (randomBoolean()) {
if (randomBoolean()) {
innerQuery = RandomQueryBuilder.createInvalidQuery(random());
}
totalExpectedErrors++;
} else {
innerQuery = RandomQueryBuilder.createQuery(random());
public void testIllegalArguments() {
try {
new ConstantScoreQueryBuilder(null);
fail("must not be null");
} catch (IllegalArgumentException e) {
// expected
}
ConstantScoreQueryBuilder constantScoreQuery = new ConstantScoreQueryBuilder(innerQuery);
assertValidate(constantScoreQuery, totalExpectedErrors);
}
}

View File

@ -107,22 +107,13 @@ public class DisMaxQueryBuilderTests extends AbstractQueryTestCase<DisMaxQueryBu
}
@Test
public void testValidate() {
public void testIllegalArguments() {
DisMaxQueryBuilder disMaxQuery = new DisMaxQueryBuilder();
int iters = randomIntBetween(0, 5);
int totalExpectedErrors = 0;
for (int i = 0; i < iters; i++) {
if (randomBoolean()) {
if (randomBoolean()) {
disMaxQuery.add(RandomQueryBuilder.createInvalidQuery(random()));
} else {
disMaxQuery.add(null);
}
totalExpectedErrors++;
} else {
disMaxQuery.add(RandomQueryBuilder.createQuery(random()));
}
try {
disMaxQuery.add(null);
fail("cannot be null");
} catch (IllegalArgumentException e) {
// expected
}
assertValidate(disMaxQuery, totalExpectedErrors);
}
}

View File

@ -25,6 +25,7 @@ import org.apache.lucene.search.ConstantScoreQuery;
import org.apache.lucene.search.Query;
import org.elasticsearch.cluster.metadata.MetaData;
import org.elasticsearch.index.mapper.object.ObjectMapper;
import org.junit.Test;
import java.io.IOException;
import java.util.Collection;
@ -78,4 +79,18 @@ public class ExistsQueryBuilderTests extends AbstractQueryTestCase<ExistsQueryBu
}
}
}
@Test
public void testIllegalArguments() {
try {
if (randomBoolean()) {
new ExistsQueryBuilder(null);
} else {
new ExistsQueryBuilder("");
}
fail("must not be null or empty");
} catch (IllegalArgumentException e) {
// expected
}
}
}

View File

@ -57,27 +57,24 @@ public class FieldMaskingSpanQueryBuilderTests extends AbstractQueryTestCase<Fie
}
@Test
public void testValidate() {
String fieldName = null;
SpanQueryBuilder spanQueryBuilder = null;
int totalExpectedErrors = 0;
if (randomBoolean()) {
fieldName = "fieldName";
} else {
if (randomBoolean()) {
fieldName = "";
}
totalExpectedErrors++;
public void testIllegalArguments() {
try {
new FieldMaskingSpanQueryBuilder(null, "maskedField");
fail("must be non null");
} catch (IllegalArgumentException e) {
// okay
}
if (randomBoolean()) {
try {
SpanQueryBuilder span = new SpanTermQueryBuilder("name", "value");
if (randomBoolean()) {
spanQueryBuilder = new SpanTermQueryBuilder("", "test");
new FieldMaskingSpanQueryBuilder(span, null);
} else {
new FieldMaskingSpanQueryBuilder(span, "");
}
totalExpectedErrors++;
} else {
spanQueryBuilder = new SpanTermQueryBuilder("name", "value");
fail("must be non null");
} catch (IllegalArgumentException e) {
// okay
}
FieldMaskingSpanQueryBuilder queryBuilder = new FieldMaskingSpanQueryBuilder(spanQueryBuilder, fieldName);
assertValidate(queryBuilder, totalExpectedErrors);
}
}

View File

@ -30,7 +30,6 @@ import org.junit.Test;
import java.io.IOException;
import static org.hamcrest.Matchers.instanceOf;
import static org.hamcrest.Matchers.is;
public class FuzzyQueryBuilderTests extends AbstractQueryTestCase<FuzzyQueryBuilder> {
@ -66,25 +65,34 @@ public class FuzzyQueryBuilderTests extends AbstractQueryTestCase<FuzzyQueryBuil
}
@Test
public void testValidate() {
FuzzyQueryBuilder fuzzyQueryBuilder = new FuzzyQueryBuilder("", "text");
assertThat(fuzzyQueryBuilder.validate().validationErrors().size(), is(1));
public void testIllegalArguments() {
try {
new FuzzyQueryBuilder(null, "text");
fail("must not be null");
} catch (IllegalArgumentException e) {
// expected
}
fuzzyQueryBuilder = new FuzzyQueryBuilder("field", null);
assertThat(fuzzyQueryBuilder.validate().validationErrors().size(), is(1));
try {
new FuzzyQueryBuilder("", "text");
fail("must not be empty");
} catch (IllegalArgumentException e) {
// expected
}
fuzzyQueryBuilder = new FuzzyQueryBuilder("field", "text");
assertNull(fuzzyQueryBuilder.validate());
fuzzyQueryBuilder = new FuzzyQueryBuilder(null, null);
assertThat(fuzzyQueryBuilder.validate().validationErrors().size(), is(2));
try {
new FuzzyQueryBuilder("field", null);
fail("must not be null");
} catch (IllegalArgumentException e) {
// expected
}
}
@Test
public void testUnsupportedFuzzinessForStringType() throws IOException {
QueryShardContext context = createShardContext();
context.setAllowUnmappedFields(true);
FuzzyQueryBuilder fuzzyQueryBuilder = new FuzzyQueryBuilder(STRING_FIELD_NAME, "text");
fuzzyQueryBuilder.fuzziness(Fuzziness.build(randomFrom("a string which is not auto", "3h", "200s")));

View File

@ -24,24 +24,21 @@ import org.junit.Test;
import java.io.IOException;
import static org.hamcrest.Matchers.is;
public class MissingQueryBuilderTests extends AbstractQueryTestCase<MissingQueryBuilder> {
@Override
protected MissingQueryBuilder doCreateTestQueryBuilder() {
MissingQueryBuilder query = new MissingQueryBuilder(randomBoolean() ? randomFrom(MAPPED_FIELD_NAMES) : randomAsciiOfLengthBetween(1, 10));
if (randomBoolean()) {
query.nullValue(randomBoolean());
String fieldName = randomBoolean() ? randomFrom(MAPPED_FIELD_NAMES) : randomAsciiOfLengthBetween(1, 10);
Boolean existence = randomBoolean();
Boolean nullValue = randomBoolean();
if (existence == false && nullValue == false) {
if (randomBoolean()) {
existence = true;
} else {
nullValue = true;
}
}
if (randomBoolean()) {
query.existence(randomBoolean());
}
// cannot set both to false
if ((query.nullValue() == false) && (query.existence() == false)) {
query.existence(!query.existence());
}
return query;
return new MissingQueryBuilder(fieldName, nullValue, existence);
}
@Override
@ -50,18 +47,31 @@ public class MissingQueryBuilderTests extends AbstractQueryTestCase<MissingQuery
}
@Test
public void testValidate() {
MissingQueryBuilder missingQueryBuilder = new MissingQueryBuilder("");
assertThat(missingQueryBuilder.validate().validationErrors().size(), is(1));
public void testIllegalArguments() {
try {
if (randomBoolean()) {
new MissingQueryBuilder("", true, true);
} else {
new MissingQueryBuilder(null, true, true);
}
fail("must not be null or empty");
} catch (IllegalArgumentException e) {
// expected
}
missingQueryBuilder = new MissingQueryBuilder(null);
assertThat(missingQueryBuilder.validate().validationErrors().size(), is(1));
try {
new MissingQueryBuilder("fieldname", false, false);
fail("existence and nullValue cannot both be false");
} catch (IllegalArgumentException e) {
// expected
}
missingQueryBuilder = new MissingQueryBuilder("field").existence(false).nullValue(false);
assertThat(missingQueryBuilder.validate().validationErrors().size(), is(1));
missingQueryBuilder = new MissingQueryBuilder("field");
assertNull(missingQueryBuilder.validate());
try {
new MissingQueryBuilder("fieldname", MissingQueryBuilder.DEFAULT_NULL_VALUE, false);
fail("existence and nullValue cannot both be false");
} catch (IllegalArgumentException e) {
// expected
}
}
@Test(expected = QueryShardException.class)

View File

@ -75,14 +75,10 @@ public class RandomQueryBuilder {
* will return an error. We can rely on the fact that a single error will be returned per query.
*/
public static QueryBuilder createInvalidQuery(Random r) {
switch (RandomInts.randomIntBetween(r, 0, 3)) {
switch (RandomInts.randomIntBetween(r, 0, 1)) {
case 0:
return new TermQueryBuilder("", "test");
case 1:
return new BoostingQueryBuilder(new MatchAllQueryBuilder(), new MatchAllQueryBuilder()).negativeBoost(-1f);
case 2:
return new CommonTermsQueryBuilder("", "text");
case 3:
return new SimpleQueryStringBuilder(null);
default:
throw new UnsupportedOperationException();

View File

@ -23,7 +23,6 @@ import com.google.common.collect.ImmutableMap;
import org.elasticsearch.action.explain.ExplainResponse;
import org.elasticsearch.action.index.IndexRequestBuilder;
import org.elasticsearch.action.search.SearchPhaseExecutionException;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.json.JsonXContent;
@ -158,19 +157,19 @@ public class ExistsMissingIT extends ESIntegTestCase {
client().prepareIndex("idx", "type", "3").setSource("g", "bar"),
client().prepareIndex("idx", "type", "4").setSource("f", "bar"));
SearchResponse resp = client().prepareSearch("idx").setQuery(QueryBuilders.missingQuery("f").existence(true).nullValue(true)).get();
SearchResponse resp = client().prepareSearch("idx").setQuery(QueryBuilders.missingQuery("f", true, true)).get();
assertSearchHits(resp, "2", "3");
resp = client().prepareSearch("idx").setQuery(QueryBuilders.missingQuery("f").existence(true).nullValue(false)).get();
resp = client().prepareSearch("idx").setQuery(QueryBuilders.missingQuery("f", false, true)).get();
assertSearchHits(resp, "2", "3");
resp = client().prepareSearch("idx").setQuery(QueryBuilders.missingQuery("f").existence(false).nullValue(true)).get();
resp = client().prepareSearch("idx").setQuery(QueryBuilders.missingQuery("f", true, false)).get();
assertSearchHits(resp);
try {
client().prepareSearch("idx").setQuery(QueryBuilders.missingQuery("f").existence(false).nullValue(false)).get();
client().prepareSearch("idx").setQuery(QueryBuilders.missingQuery("f", false, false)).get();
fail("both existence and null_value can't be false");
} catch (SearchPhaseExecutionException e) {
} catch (IllegalArgumentException e) {
// expected
}
}
@ -183,19 +182,19 @@ public class ExistsMissingIT extends ESIntegTestCase {
client().prepareIndex("idx", "type", "3").setSource("g", "bar"),
client().prepareIndex("idx", "type", "4").setSource("f", "bar"));
SearchResponse resp = client().prepareSearch("idx").setQuery(QueryBuilders.missingQuery("f").existence(true).nullValue(true)).get();
SearchResponse resp = client().prepareSearch("idx").setQuery(QueryBuilders.missingQuery("f", true, true)).get();
assertSearchHits(resp, "2", "3", "4");
resp = client().prepareSearch("idx").setQuery(QueryBuilders.missingQuery("f").existence(true).nullValue(false)).get();
resp = client().prepareSearch("idx").setQuery(QueryBuilders.missingQuery("f", false, true)).get();
assertSearchHits(resp, "3");
resp = client().prepareSearch("idx").setQuery(QueryBuilders.missingQuery("f").existence(false).nullValue(true)).get();
resp = client().prepareSearch("idx").setQuery(QueryBuilders.missingQuery("f", true, false)).get();
assertSearchHits(resp, "2", "4");
try {
client().prepareSearch("idx").setQuery(QueryBuilders.missingQuery("f").existence(false).nullValue(false)).get();
client().prepareSearch("idx").setQuery(QueryBuilders.missingQuery("f", false, false)).get();
fail("both existence and null_value can't be false");
} catch (SearchPhaseExecutionException e) {
} catch (IllegalArgumentException e) {
// expected
}
}

View File

@ -112,3 +112,9 @@ Also reusing new Operator enum.
Removed ability to pass in boost value using `field(String field)` method in form e.g. `field^2`.
Use the `field(String, float)` method instead.
==== MissingQueryBuilder
The two individual setters for existence() and nullValue() were removed in favour of
optional constructor settings in order to better capture and validate their interdependent
settings at construction time.