Skip to content

Commit

Permalink
[ES|QL] Verify aggregation filter's type is boolean to avoid class_ca…
Browse files Browse the repository at this point in the history
…st_exception (elastic#116274)

* validate agg filter's type is boolean

(cherry picked from commit 0e044d7)
  • Loading branch information
fang-xing-esql committed Nov 6, 2024
1 parent 0ac7f65 commit 4932be3
Show file tree
Hide file tree
Showing 3 changed files with 23 additions and 0 deletions.
5 changes: 5 additions & 0 deletions docs/changelog/116274.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
pr: 116274
summary: "[ES|QL] Verify aggregation filter's type is boolean to avoid `class_cast_exception`"
area: ES|QL
type: bug
issues: []
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@
import static org.elasticsearch.xpack.esql.common.Failure.fail;
import static org.elasticsearch.xpack.esql.core.expression.TypeResolutions.ParamOrdinal.FIRST;
import static org.elasticsearch.xpack.esql.core.type.DataType.BOOLEAN;
import static org.elasticsearch.xpack.esql.core.type.DataType.NULL;

/**
* This class is part of the planner. Responsible for failing impossible queries with a human-readable error message. In particular, this
Expand Down Expand Up @@ -315,6 +316,10 @@ private static void checkInvalidNamedExpressionUsage(
Expression filter = fe.filter();
failures.add(fail(filter, "WHERE clause allowed only for aggregate functions, none found in [{}]", fe.sourceText()));
}
Expression f = fe.filter(); // check the filter has to be a boolean term, similar as checkFilterConditionType
if (f.dataType() != NULL && f.dataType() != BOOLEAN) {
failures.add(fail(f, "Condition expression needs to be boolean, found [{}]", f.dataType()));
}
// but that the filter doesn't use grouping or aggregate functions
fe.filter().forEachDown(c -> {
if (c instanceof AggregateFunction af) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -394,6 +394,19 @@ public void testAggFilterOnBucketingOrAggFunctions() {
assertEquals("1:60: Unknown column [m]", error("from test | stats m = max(languages), min(languages) WHERE m + 2 > 1 by emp_no"));
}

public void testAggWithNonBooleanFilter() {
for (String filter : List.of("\"true\"", "1", "1 + 0", "concat(\"a\", \"b\")")) {
String type = (filter.equals("1") || filter.equals("1 + 0")) ? "INTEGER" : "KEYWORD";
assertEquals("1:19: Condition expression needs to be boolean, found [" + type + "]", error("from test | where " + filter));
for (String by : List.of("", " by languages", " by bucket(salary, 10)")) {
assertEquals(
"1:34: Condition expression needs to be boolean, found [" + type + "]",
error("from test | stats count(*) where " + filter + by)
);
}
}
}

public void testGroupingInsideAggsAsAgg() {
assertEquals(
"1:18: can only use grouping function [bucket(emp_no, 5.)] part of the BY clause",
Expand Down

0 comments on commit 4932be3

Please sign in to comment.