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:
parent
2e8a2c4baf
commit
285a167c34
|
@ -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.aggregate.AggregateFunction;
|
||||||
import org.elasticsearch.xpack.ql.expression.function.grouping.GroupingFunction;
|
import org.elasticsearch.xpack.ql.expression.function.grouping.GroupingFunction;
|
||||||
import org.elasticsearch.xpack.ql.expression.function.scalar.ScalarFunction;
|
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.Aggregate;
|
||||||
import org.elasticsearch.xpack.ql.plan.logical.Filter;
|
import org.elasticsearch.xpack.ql.plan.logical.Filter;
|
||||||
import org.elasticsearch.xpack.ql.plan.logical.Limit;
|
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 there are no (major) unresolved failures, do more in-depth analysis
|
||||||
|
|
||||||
if (failures.isEmpty()) {
|
if (failures.isEmpty()) {
|
||||||
|
Set<Failure> localFailures = new LinkedHashSet<>();
|
||||||
final Map<Attribute, Expression> collectRefs = new LinkedHashMap<>();
|
final Map<Attribute, Expression> collectRefs = new LinkedHashMap<>();
|
||||||
|
|
||||||
|
checkFullTextSearchInSelect(plan, localFailures);
|
||||||
|
|
||||||
// collect Attribute sources
|
// collect Attribute sources
|
||||||
// only Aliases are interesting since these are the only ones that hide expressions
|
// only Aliases are interesting since these are the only ones that hide expressions
|
||||||
// FieldAttribute for example are self replicating.
|
// FieldAttribute for example are self replicating.
|
||||||
|
@ -242,8 +246,6 @@ public final class Verifier {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Set<Failure> localFailures = new LinkedHashSet<>();
|
|
||||||
|
|
||||||
checkGroupingFunctionInGroupBy(p, localFailures);
|
checkGroupingFunctionInGroupBy(p, localFailures);
|
||||||
checkFilterOnAggs(p, localFailures, attributeRefs);
|
checkFilterOnAggs(p, localFailures, attributeRefs);
|
||||||
checkFilterOnGrouping(p, localFailures, attributeRefs);
|
checkFilterOnGrouping(p, localFailures, attributeRefs);
|
||||||
|
@ -297,6 +299,17 @@ public final class Verifier {
|
||||||
return failures;
|
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.
|
* Check validity of Aggregate/GroupBy.
|
||||||
* This rule is needed for multiple reasons:
|
* This rule is needed for multiple reasons:
|
||||||
|
|
|
@ -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"));
|
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]: " +
|
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",
|
"No keyword/multi-field defined exact matches for [text]; define one or use MATCH/QUERY instead",
|
||||||
error("SELECT * FROM test WHERE text = 'value'"));
|
error("SELECT * FROM test WHERE text = 'value'"));
|
||||||
|
@ -712,6 +712,19 @@ public class VerifierErrorMessagesTests extends ESTestCase {
|
||||||
error("SELECT * FROM test WHERE text RLIKE 'foo'"));
|
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() {
|
public void testAllowCorrectFieldsInIncompatibleMappings() {
|
||||||
assertNotNull(incompatibleAccept("SELECT languages FROM \"*\""));
|
assertNotNull(incompatibleAccept("SELECT languages FROM \"*\""));
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue