Skip to content

Commit a57d5c3

Browse files
authored
Add ToDouble conversion and projection for AcrossSeriesAggregate output (#138655)
1 parent 0955a82 commit a57d5c3

File tree

1 file changed

+24
-6
lines changed

1 file changed

+24
-6
lines changed

x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/optimizer/rules/logical/promql/TranslatePromqlToTimeSeriesAggregate.java

Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
import org.elasticsearch.xpack.esql.plan.logical.Eval;
3939
import org.elasticsearch.xpack.esql.plan.logical.Filter;
4040
import org.elasticsearch.xpack.esql.plan.logical.LogicalPlan;
41+
import org.elasticsearch.xpack.esql.plan.logical.Project;
4142
import org.elasticsearch.xpack.esql.plan.logical.TimeSeriesAggregate;
4243
import org.elasticsearch.xpack.esql.plan.logical.promql.AcrossSeriesAggregate;
4344
import org.elasticsearch.xpack.esql.plan.logical.promql.PlaceholderRelation;
@@ -185,7 +186,26 @@ private static MapResult mapFunction(PromqlCommand promqlCommand, PromqlFunction
185186

186187
LogicalPlan p = childResult.plan;
187188
p = new Eval(stepBucket.source(), p, List.of(stepBucket));
188-
p = new TimeSeriesAggregate(acrossAggregate.source(), p, groupings, aggs, null);
189+
TimeSeriesAggregate tsAggregate = new TimeSeriesAggregate(acrossAggregate.source(), p, groupings, aggs, null);
190+
p = tsAggregate;
191+
// ToDouble conversion of the metric using an eval to ensure a consistent output type
192+
Alias convertedValue = new Alias(
193+
acrossAggregate.source(),
194+
acrossAggregate.sourceText(),
195+
new ToDouble(acrossAggregate.source(), p.output().getFirst().toAttribute()),
196+
acrossAggregate.valueId()
197+
);
198+
p = new Eval(acrossAggregate.source(), p, List.of(convertedValue));
199+
// Project to maintain the correct output order, as declared in AcrossSeriesAggregate#output:
200+
// [value, step, ...groupings]
201+
List<NamedExpression> projections = new ArrayList<>();
202+
projections.add(convertedValue.toAttribute());
203+
List<Attribute> output = tsAggregate.output();
204+
for (int i = 1; i < output.size(); i++) {
205+
projections.add(output.get(i));
206+
}
207+
p = new Project(acrossAggregate.source(), p, projections);
208+
189209
result = new MapResult(p, extras);
190210
} else {
191211
throw new QlIllegalArgumentException("Unsupported PromQL function call: {}", functionCall);
@@ -205,13 +225,11 @@ private static void initAggregatesAndGroupings(
205225
Function esqlFunction = PromqlFunctionRegistry.INSTANCE.buildEsqlFunction(
206226
acrossAggregate.functionName(),
207227
acrossAggregate.source(),
208-
// to double conversion of the metric to ensure a consistent output type
209-
// TODO it's probably more efficient to wrap the function in the ToDouble
210-
// but for some reason this doesn't work if you have an inner and outer aggregation
211-
List.of(new ToDouble(target.source(), target))
228+
List.of(target)
212229
);
213230

214-
aggs.add(new Alias(acrossAggregate.source(), acrossAggregate.sourceText(), esqlFunction, acrossAggregate.valueId()));
231+
Alias value = new Alias(acrossAggregate.source(), acrossAggregate.sourceText(), esqlFunction);
232+
aggs.add(value);
215233

216234
// timestamp/step
217235
aggs.add(stepBucket);

0 commit comments

Comments
 (0)