SQL: Verify Full-Text Search functions not allowed in SELECT (#51568)

Add a verification that full-text search functions `MATCH()` and `QUERY()`
are not allowed in the SELECT clause, so that a nice error message is
returned to the user early instead of an "ugly" exception.

Fixes: #47446
This commit is contained in:
Marios Trivyzas 2020-01-30 12:22:03 +01:00
parent 2e8a2c4baf
commit 285a167c34
2 changed files with 29 additions and 3 deletions

View File

@ -22,6 +22,7 @@ import org.elasticsearch.xpack.ql.expression.function.Functions;
import org.elasticsearch.xpack.ql.expression.function.aggregate.AggregateFunction;
import org.elasticsearch.xpack.ql.expression.function.grouping.GroupingFunction;
import org.elasticsearch.xpack.ql.expression.function.scalar.ScalarFunction;
import org.elasticsearch.xpack.ql.expression.predicate.fulltext.FullTextPredicate;
import org.elasticsearch.xpack.ql.plan.logical.Aggregate;
import org.elasticsearch.xpack.ql.plan.logical.Filter;
import org.elasticsearch.xpack.ql.plan.logical.Limit;
@ -215,8 +216,11 @@ public final class Verifier {
// if there are no (major) unresolved failures, do more in-depth analysis
if (failures.isEmpty()) {
Set<Failure> localFailures = new LinkedHashSet<>();
final Map<Attribute, Expression> collectRefs = new LinkedHashMap<>();
checkFullTextSearchInSelect(plan, localFailures);
// collect Attribute sources
// only Aliases are interesting since these are the only ones that hide expressions
// FieldAttribute for example are self replicating.
@ -242,8 +246,6 @@ public final class Verifier {
return;
}
Set<Failure> localFailures = new LinkedHashSet<>();
checkGroupingFunctionInGroupBy(p, localFailures);
checkFilterOnAggs(p, localFailures, attributeRefs);
checkFilterOnGrouping(p, localFailures, attributeRefs);
@ -297,6 +299,17 @@ public final class Verifier {
return failures;
}
private void checkFullTextSearchInSelect(LogicalPlan plan, Set<Failure> localFailures) {
plan.forEachUp(p -> {
for (NamedExpression ne : p.projections()) {
ne.forEachUp((e) ->
localFailures.add(fail(e, "Cannot use MATCH() or QUERY() full-text search " +
"functions in the SELECT clause")),
FullTextPredicate.class);
}
}, Project.class);
}
/**
* Check validity of Aggregate/GroupBy.
* This rule is needed for multiple reasons:

View File

@ -511,7 +511,7 @@ public class VerifierErrorMessagesTests extends ESTestCase {
assertEquals("1:8: Cannot use field [x.y] with unsupported type [foobar]", error("SELECT x.y FROM test"));
}
public void testTermEqualitOnInexact() {
public void testTermEqualityOnInexact() {
assertEquals("1:26: [text = 'value'] cannot operate on first argument field of data type [text]: " +
"No keyword/multi-field defined exact matches for [text]; define one or use MATCH/QUERY instead",
error("SELECT * FROM test WHERE text = 'value'"));
@ -712,6 +712,19 @@ public class VerifierErrorMessagesTests extends ESTestCase {
error("SELECT * FROM test WHERE text RLIKE 'foo'"));
}
public void testMatchAndQueryFunctionsNotAllowedInSelect() {
assertEquals("1:8: Cannot use MATCH() or QUERY() full-text search functions in the SELECT clause",
error("SELECT MATCH(text, 'foo') FROM test"));
assertEquals("1:8: Cannot use MATCH() or QUERY() full-text search functions in the SELECT clause",
error("SELECT MATCH(text, 'foo') AS fullTextSearch FROM test"));
assertEquals("1:38: Cannot use MATCH() or QUERY() full-text search functions in the SELECT clause",
error("SELECT int > 10 AND (bool = false OR QUERY('foo*')) AS fullTextSearch FROM test"));
assertEquals("1:8: Cannot use MATCH() or QUERY() full-text search functions in the SELECT clause\n" +
"line 1:28: Cannot use MATCH() or QUERY() full-text search functions in the SELECT clause",
error("SELECT MATCH(text, 'foo'), MATCH(text, 'bar') FROM test"));
accept("SELECT * FROM test WHERE MATCH(text, 'foo')");
}
public void testAllowCorrectFieldsInIncompatibleMappings() {
assertNotNull(incompatibleAccept("SELECT languages FROM \"*\""));
}