|
@@ -11,7 +11,6 @@ import org.elasticsearch.search.sort.SortOrder;
|
|
|
import org.elasticsearch.xpack.ql.expression.Expression;
|
|
|
import org.elasticsearch.xpack.ql.expression.FieldAttribute;
|
|
|
import org.elasticsearch.xpack.ql.expression.Foldables;
|
|
|
-import org.elasticsearch.xpack.ql.expression.Literal;
|
|
|
import org.elasticsearch.xpack.ql.expression.NamedExpression;
|
|
|
import org.elasticsearch.xpack.ql.expression.function.Function;
|
|
|
import org.elasticsearch.xpack.ql.expression.function.aggregate.AggregateFunction;
|
|
@@ -60,6 +59,7 @@ import org.elasticsearch.xpack.sql.expression.function.scalar.geo.StDistance;
|
|
|
import org.elasticsearch.xpack.sql.expression.literal.geo.GeoShape;
|
|
|
import org.elasticsearch.xpack.sql.expression.predicate.operator.comparison.In;
|
|
|
import org.elasticsearch.xpack.sql.querydsl.agg.AggFilter;
|
|
|
+import org.elasticsearch.xpack.sql.querydsl.agg.AggSource;
|
|
|
import org.elasticsearch.xpack.sql.querydsl.agg.AndAggFilter;
|
|
|
import org.elasticsearch.xpack.sql.querydsl.agg.AvgAgg;
|
|
|
import org.elasticsearch.xpack.sql.querydsl.agg.CardinalityAgg;
|
|
@@ -92,7 +92,7 @@ final class QueryTranslator {
|
|
|
public static final String DATE_FORMAT = "strict_date_time";
|
|
|
public static final String TIME_FORMAT = "strict_hour_minute_second_millis";
|
|
|
|
|
|
- private QueryTranslator(){}
|
|
|
+ private QueryTranslator() {}
|
|
|
|
|
|
private static final List<SqlExpressionTranslator<?>> QUERY_TRANSLATORS = Arrays.asList(
|
|
|
new BinaryComparisons(),
|
|
@@ -135,10 +135,6 @@ final class QueryTranslator {
|
|
|
this(query, null);
|
|
|
}
|
|
|
|
|
|
- QueryTranslation(AggFilter aggFilter) {
|
|
|
- this(null, aggFilter);
|
|
|
- }
|
|
|
-
|
|
|
QueryTranslation(Query query, AggFilter aggFilter) {
|
|
|
this.query = query;
|
|
|
this.aggFilter = aggFilter;
|
|
@@ -240,39 +236,36 @@ final class QueryTranslator {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- static String dateFormat(Expression e) {
|
|
|
- if (e instanceof DateTimeFunction) {
|
|
|
- return ((DateTimeFunction) e).dateTimeFormat();
|
|
|
+ static String field(AggregateFunction af, Expression arg) {
|
|
|
+ if (arg.foldable()) {
|
|
|
+ return String.valueOf(arg.fold());
|
|
|
}
|
|
|
- return null;
|
|
|
- }
|
|
|
-
|
|
|
- static String field(AggregateFunction af) {
|
|
|
- Expression arg = af.field();
|
|
|
if (arg instanceof FieldAttribute) {
|
|
|
FieldAttribute field = (FieldAttribute) arg;
|
|
|
// COUNT(DISTINCT) uses cardinality aggregation which works on exact values (not changed by analyzers or normalizers)
|
|
|
- if (af instanceof Count && ((Count) af).distinct()) {
|
|
|
+ if ((af instanceof Count && ((Count) af).distinct()) || af instanceof TopHits) {
|
|
|
// use the `keyword` version of the field, if there is one
|
|
|
return field.exactAttribute().name();
|
|
|
}
|
|
|
return field.name();
|
|
|
}
|
|
|
- if (arg instanceof Literal) {
|
|
|
- return String.valueOf(((Literal) arg).value());
|
|
|
- }
|
|
|
throw new SqlIllegalArgumentException("Does not know how to convert argument {} for function {}", arg.nodeString(),
|
|
|
af.nodeString());
|
|
|
}
|
|
|
|
|
|
- private static String topAggsField(AggregateFunction af, Expression e) {
|
|
|
+ private static boolean isFieldOrLiteral(Expression e) {
|
|
|
+ return e.foldable() || e instanceof FieldAttribute;
|
|
|
+ }
|
|
|
+
|
|
|
+ private static AggSource asFieldOrLiteralOrScript(AggregateFunction af) {
|
|
|
+ return asFieldOrLiteralOrScript(af, af.field());
|
|
|
+ }
|
|
|
+
|
|
|
+ private static AggSource asFieldOrLiteralOrScript(AggregateFunction af, Expression e) {
|
|
|
if (e == null) {
|
|
|
return null;
|
|
|
}
|
|
|
- if (e instanceof FieldAttribute) {
|
|
|
- return ((FieldAttribute) e).exactAttribute().name();
|
|
|
- }
|
|
|
- throw new SqlIllegalArgumentException("Does not know how to convert argument {} for function {}", e.nodeString(), af.nodeString());
|
|
|
+ return isFieldOrLiteral(e) ? AggSource.of(field(af, e)) : AggSource.of(((ScalarFunction) e).asScript());
|
|
|
}
|
|
|
|
|
|
// TODO: see whether escaping is needed
|
|
@@ -524,9 +517,9 @@ final class QueryTranslator {
|
|
|
@Override
|
|
|
protected LeafAgg toAgg(String id, Count c) {
|
|
|
if (c.distinct()) {
|
|
|
- return new CardinalityAgg(id, field(c));
|
|
|
+ return new CardinalityAgg(id, asFieldOrLiteralOrScript(c));
|
|
|
} else {
|
|
|
- return new FilterExistsAgg(id, field(c));
|
|
|
+ return new FilterExistsAgg(id, asFieldOrLiteralOrScript(c));
|
|
|
}
|
|
|
}
|
|
|
}
|
|
@@ -535,7 +528,7 @@ final class QueryTranslator {
|
|
|
|
|
|
@Override
|
|
|
protected LeafAgg toAgg(String id, Sum s) {
|
|
|
- return new SumAgg(id, field(s));
|
|
|
+ return new SumAgg(id, asFieldOrLiteralOrScript(s));
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -543,7 +536,7 @@ final class QueryTranslator {
|
|
|
|
|
|
@Override
|
|
|
protected LeafAgg toAgg(String id, Avg a) {
|
|
|
- return new AvgAgg(id, field(a));
|
|
|
+ return new AvgAgg(id, asFieldOrLiteralOrScript(a));
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -551,7 +544,7 @@ final class QueryTranslator {
|
|
|
|
|
|
@Override
|
|
|
protected LeafAgg toAgg(String id, Max m) {
|
|
|
- return new MaxAgg(id, field(m));
|
|
|
+ return new MaxAgg(id, asFieldOrLiteralOrScript(m));
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -559,14 +552,14 @@ final class QueryTranslator {
|
|
|
|
|
|
@Override
|
|
|
protected LeafAgg toAgg(String id, Min m) {
|
|
|
- return new MinAgg(id, field(m));
|
|
|
+ return new MinAgg(id, asFieldOrLiteralOrScript(m));
|
|
|
}
|
|
|
}
|
|
|
|
|
|
static class MADs extends SingleValueAggTranslator<MedianAbsoluteDeviation> {
|
|
|
@Override
|
|
|
protected LeafAgg toAgg(String id, MedianAbsoluteDeviation m) {
|
|
|
- return new MedianAbsoluteDeviationAgg(id, field(m));
|
|
|
+ return new MedianAbsoluteDeviationAgg(id, asFieldOrLiteralOrScript(m));
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -574,8 +567,14 @@ final class QueryTranslator {
|
|
|
|
|
|
@Override
|
|
|
protected LeafAgg toAgg(String id, First f) {
|
|
|
- return new TopHitsAgg(id, topAggsField(f, f.field()), f.dataType(),
|
|
|
- topAggsField(f, f.orderField()), f.orderField() == null ? null : f.orderField().dataType(), SortOrder.ASC);
|
|
|
+ return new TopHitsAgg(
|
|
|
+ id,
|
|
|
+ asFieldOrLiteralOrScript(f, f.field()),
|
|
|
+ f.dataType(),
|
|
|
+ asFieldOrLiteralOrScript(f, f.orderField()),
|
|
|
+ f.orderField() == null ? null : f.orderField().dataType(),
|
|
|
+ SortOrder.ASC
|
|
|
+ );
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -583,8 +582,14 @@ final class QueryTranslator {
|
|
|
|
|
|
@Override
|
|
|
protected LeafAgg toAgg(String id, Last l) {
|
|
|
- return new TopHitsAgg(id, topAggsField(l, l.field()), l.dataType(),
|
|
|
- topAggsField(l, l.orderField()), l.orderField() == null ? null : l.orderField().dataType(), SortOrder.DESC);
|
|
|
+ return new TopHitsAgg(
|
|
|
+ id,
|
|
|
+ asFieldOrLiteralOrScript(l, l.field()),
|
|
|
+ l.dataType(),
|
|
|
+ asFieldOrLiteralOrScript(l, l.orderField()),
|
|
|
+ l.orderField() == null ? null : l.orderField().dataType(),
|
|
|
+ SortOrder.DESC
|
|
|
+ );
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -592,7 +597,7 @@ final class QueryTranslator {
|
|
|
|
|
|
@Override
|
|
|
protected LeafAgg toAgg(String id, Stats s) {
|
|
|
- return new StatsAgg(id, field(s));
|
|
|
+ return new StatsAgg(id, asFieldOrLiteralOrScript(s));
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -600,7 +605,7 @@ final class QueryTranslator {
|
|
|
|
|
|
@Override
|
|
|
protected LeafAgg toAgg(String id, ExtendedStats e) {
|
|
|
- return new ExtendedStatsAgg(id, field(e));
|
|
|
+ return new ExtendedStatsAgg(id, asFieldOrLiteralOrScript(e));
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -608,7 +613,13 @@ final class QueryTranslator {
|
|
|
|
|
|
@Override
|
|
|
protected LeafAgg toAgg(String id, MatrixStats m) {
|
|
|
- return new MatrixStatsAgg(id, singletonList(field(m)));
|
|
|
+ if (isFieldOrLiteral(m.field())) {
|
|
|
+ return new MatrixStatsAgg(id, singletonList(field(m, m.field())));
|
|
|
+ }
|
|
|
+ throw new SqlIllegalArgumentException(
|
|
|
+ "Cannot use scalar functions or operators: [{}] in aggregate functions [KURTOSIS] and [SKEWNESS]",
|
|
|
+ m.field().toString()
|
|
|
+ );
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -616,7 +627,7 @@ final class QueryTranslator {
|
|
|
|
|
|
@Override
|
|
|
protected LeafAgg toAgg(String id, Percentiles p) {
|
|
|
- return new PercentilesAgg(id, field(p), foldAndConvertToDoubles(p.percents()));
|
|
|
+ return new PercentilesAgg(id, asFieldOrLiteralOrScript(p), foldAndConvertToDoubles(p.percents()));
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -624,7 +635,7 @@ final class QueryTranslator {
|
|
|
|
|
|
@Override
|
|
|
protected LeafAgg toAgg(String id, PercentileRanks p) {
|
|
|
- return new PercentileRanksAgg(id, field(p), foldAndConvertToDoubles(p.values()));
|
|
|
+ return new PercentileRanksAgg(id, asFieldOrLiteralOrScript(p), foldAndConvertToDoubles(p.values()));
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -632,7 +643,7 @@ final class QueryTranslator {
|
|
|
|
|
|
@Override
|
|
|
protected LeafAgg toAgg(String id, Min m) {
|
|
|
- return new MinAgg(id, field(m));
|
|
|
+ return new MinAgg(id, asFieldOrLiteralOrScript(m));
|
|
|
}
|
|
|
}
|
|
|
|