diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/analysis/analyzer/Verifier.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/analysis/analyzer/Verifier.java index 90265670255..b2818ee2145 100644 --- a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/analysis/analyzer/Verifier.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/analysis/analyzer/Verifier.java @@ -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 localFailures = new LinkedHashSet<>(); final Map 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 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 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: diff --git a/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/analysis/analyzer/VerifierErrorMessagesTests.java b/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/analysis/analyzer/VerifierErrorMessagesTests.java index 413898ea290..35872f3a6f6 100644 --- a/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/analysis/analyzer/VerifierErrorMessagesTests.java +++ b/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/analysis/analyzer/VerifierErrorMessagesTests.java @@ -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 \"*\"")); }