SQL: equality on analyzed through TermQuery on not-analyzed (elastic/x-pack-elasticsearch#3524)

Always use term equality for analyzed terms by falling back (to possible
not present) to the not-analyzed field.
Add clarifying comment in test

Original commit: elastic/x-pack-elasticsearch@9e735d3fef
This commit is contained in:
Costin Leau 2018-01-11 00:01:30 +02:00 committed by GitHub
parent 2870312320
commit e5e5583bd8
2 changed files with 90 additions and 1 deletions

View File

@ -621,8 +621,10 @@ abstract class QueryTranslator {
if (bc instanceof Equals) {
if (bc.left() instanceof FieldAttribute) {
FieldAttribute fa = (FieldAttribute) bc.left();
// equality should always be against an exact match
// (which is important for strings)
if (fa.isInexact()) {
return new MatchQuery(loc, name, value);
name = fa.exactAttribute().name();
}
}
return new TermQuery(loc, name, value);

View File

@ -0,0 +1,87 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
package org.elasticsearch.xpack.sql.planner;
import org.elasticsearch.test.ESTestCase;
import org.elasticsearch.xpack.sql.analysis.analyzer.Analyzer;
import org.elasticsearch.xpack.sql.analysis.index.EsIndex;
import org.elasticsearch.xpack.sql.analysis.index.IndexResolution;
import org.elasticsearch.xpack.sql.analysis.index.MappingException;
import org.elasticsearch.xpack.sql.expression.Expression;
import org.elasticsearch.xpack.sql.expression.function.FunctionRegistry;
import org.elasticsearch.xpack.sql.parser.SqlParser;
import org.elasticsearch.xpack.sql.plan.logical.Filter;
import org.elasticsearch.xpack.sql.plan.logical.LogicalPlan;
import org.elasticsearch.xpack.sql.plan.logical.Project;
import org.elasticsearch.xpack.sql.planner.QueryTranslator.QueryTranslation;
import org.elasticsearch.xpack.sql.querydsl.query.Query;
import org.elasticsearch.xpack.sql.querydsl.query.TermQuery;
import org.elasticsearch.xpack.sql.type.DataType;
import org.elasticsearch.xpack.sql.type.TypesTests;
import org.joda.time.DateTimeZone;
import java.util.Map;
public class QueryTranslatorTests extends ESTestCase {
private SqlParser parser;
private IndexResolution getIndexResult;
private FunctionRegistry functionRegistry;
private Analyzer analyzer;
public QueryTranslatorTests() {
parser = new SqlParser(DateTimeZone.UTC);
functionRegistry = new FunctionRegistry();
Map<String, DataType> mapping = TypesTests.loadMapping("mapping-multi-field-variation.json");
EsIndex test = new EsIndex("test", mapping);
getIndexResult = IndexResolution.valid(test);
analyzer = new Analyzer(functionRegistry, getIndexResult, DateTimeZone.UTC);
}
private LogicalPlan plan(String sql) {
return analyzer.analyze(parser.createStatement(sql), true);
}
public void testTermEqualityAnalyzer() {
LogicalPlan p = plan("SELECT some.string FROM test WHERE some.string = 'value'");
assertTrue(p instanceof Project);
p = ((Project) p).child();
assertTrue(p instanceof Filter);
Expression condition = ((Filter) p).condition();
QueryTranslation translation = QueryTranslator.toQuery(condition, false);
Query query = translation.query;
assertTrue(query instanceof TermQuery);
TermQuery tq = (TermQuery) query;
assertEquals("some.string.typical", tq.term());
assertEquals("value", tq.value());
}
public void testTermEqualityAnalyzerAmbiguous() {
LogicalPlan p = plan("SELECT some.string FROM test WHERE some.ambiguous = 'value'");
assertTrue(p instanceof Project);
p = ((Project) p).child();
assertTrue(p instanceof Filter);
Expression condition = ((Filter) p).condition();
// the message is checked elsewhere (in FieldAttributeTests)
expectThrows(MappingException.class, () -> QueryTranslator.toQuery(condition, false));
}
public void testTermEqualityNotAnalyzed() {
LogicalPlan p = plan("SELECT some.string FROM test WHERE int = 5");
assertTrue(p instanceof Project);
p = ((Project) p).child();
assertTrue(p instanceof Filter);
Expression condition = ((Filter) p).condition();
QueryTranslation translation = QueryTranslator.toQuery(condition, false);
Query query = translation.query;
assertTrue(query instanceof TermQuery);
TermQuery tq = (TermQuery) query;
assertEquals("int", tq.term());
assertEquals(5, tq.value());
}
}