|
@@ -18,6 +18,8 @@ import org.elasticsearch.xpack.sql.expression.function.Function;
|
|
|
import org.elasticsearch.xpack.sql.expression.function.FunctionAttribute;
|
|
|
import org.elasticsearch.xpack.sql.expression.function.Functions;
|
|
|
import org.elasticsearch.xpack.sql.expression.function.Score;
|
|
|
+import org.elasticsearch.xpack.sql.expression.function.aggregate.AggregateFunctionAttribute;
|
|
|
+import org.elasticsearch.xpack.sql.expression.function.grouping.GroupingFunctionAttribute;
|
|
|
import org.elasticsearch.xpack.sql.expression.function.scalar.ScalarFunction;
|
|
|
import org.elasticsearch.xpack.sql.expression.predicate.conditional.ConditionalFunction;
|
|
|
import org.elasticsearch.xpack.sql.expression.predicate.operator.comparison.In;
|
|
@@ -224,6 +226,7 @@ public final class Verifier {
|
|
|
validateConditional(p, localFailures);
|
|
|
|
|
|
checkFilterOnAggs(p, localFailures);
|
|
|
+ checkFilterOnGrouping(p, localFailures);
|
|
|
|
|
|
if (!groupingFailures.contains(p)) {
|
|
|
checkGroupBy(p, localFailures, resolvedFunctions, groupingFailures);
|
|
@@ -419,7 +422,7 @@ public final class Verifier {
|
|
|
return true;
|
|
|
}
|
|
|
// skip aggs (allowed to refer to non-group columns)
|
|
|
- if (Functions.isAggregate(e)) {
|
|
|
+ if (Functions.isAggregate(e) || Functions.isGrouping(e)) {
|
|
|
return true;
|
|
|
}
|
|
|
|
|
@@ -448,6 +451,21 @@ public final class Verifier {
|
|
|
}
|
|
|
}));
|
|
|
|
|
|
+ a.groupings().forEach(e -> {
|
|
|
+ if (Functions.isGrouping(e) == false) {
|
|
|
+ e.collectFirstChildren(c -> {
|
|
|
+ if (Functions.isGrouping(c)) {
|
|
|
+ localFailures.add(fail(c,
|
|
|
+ "Cannot combine [%s] grouping function inside GROUP BY, found [%s];"
|
|
|
+ + " consider moving the expression inside the histogram",
|
|
|
+ Expressions.name(c), Expressions.name(e)));
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ return false;
|
|
|
+ });
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
if (!localFailures.isEmpty()) {
|
|
|
return false;
|
|
|
}
|
|
@@ -547,19 +565,30 @@ public final class Verifier {
|
|
|
if (p instanceof Filter) {
|
|
|
Filter filter = (Filter) p;
|
|
|
if ((filter.child() instanceof Aggregate) == false) {
|
|
|
- filter.condition().forEachDown(f -> {
|
|
|
- if (Functions.isAggregate(f) || Functions.isGrouping(f)) {
|
|
|
- String type = Functions.isAggregate(f) ? "aggregate" : "grouping";
|
|
|
- localFailures.add(fail(f,
|
|
|
- "Cannot use WHERE filtering on %s function [%s], use HAVING instead", type, Expressions.name(f)));
|
|
|
+ filter.condition().forEachDown(e -> {
|
|
|
+ if (Functions.isAggregate(e) || e instanceof AggregateFunctionAttribute) {
|
|
|
+ localFailures.add(
|
|
|
+ fail(e, "Cannot use WHERE filtering on aggregate function [%s], use HAVING instead", Expressions.name(e)));
|
|
|
}
|
|
|
-
|
|
|
- }, Function.class);
|
|
|
+ }, Expression.class);
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
|
|
|
+ private static void checkFilterOnGrouping(LogicalPlan p, Set<Failure> localFailures) {
|
|
|
+ if (p instanceof Filter) {
|
|
|
+ Filter filter = (Filter) p;
|
|
|
+ filter.condition().forEachDown(e -> {
|
|
|
+ if (Functions.isGrouping(e) || e instanceof GroupingFunctionAttribute) {
|
|
|
+ localFailures
|
|
|
+ .add(fail(e, "Cannot filter on grouping function [%s], use its argument instead", Expressions.name(e)));
|
|
|
+ }
|
|
|
+ }, Expression.class);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
private static void checkForScoreInsideFunctions(LogicalPlan p, Set<Failure> localFailures) {
|
|
|
// Make sure that SCORE is only used in "top level" functions
|
|
|
p.forEachExpressions(e ->
|
|
@@ -647,4 +676,4 @@ public final class Verifier {
|
|
|
(left.isNumeric() && right.isNumeric());
|
|
|
}
|
|
|
}
|
|
|
-}
|
|
|
+}
|