|
@@ -79,7 +79,6 @@ import org.elasticsearch.xpack.ql.type.DataTypes;
|
|
|
import org.elasticsearch.xpack.ql.util.Holder;
|
|
|
|
|
|
import java.util.ArrayList;
|
|
|
-import java.util.Arrays;
|
|
|
import java.util.BitSet;
|
|
|
import java.util.HashMap;
|
|
|
import java.util.HashSet;
|
|
@@ -204,7 +203,8 @@ public class LocalExecutionPlanner {
|
|
|
}
|
|
|
|
|
|
private PhysicalOperation planAggregation(AggregateExec aggregate, LocalExecutionPlannerContext context) {
|
|
|
- return physicalOperationProviders.groupingPhysicalOperation(aggregate, plan(aggregate.child(), context), context);
|
|
|
+ var source = plan(aggregate.child(), context);
|
|
|
+ return physicalOperationProviders.groupingPhysicalOperation(aggregate, source, context);
|
|
|
}
|
|
|
|
|
|
private PhysicalOperation planEsQueryNode(EsQueryExec esQuery, LocalExecutionPlannerContext context) {
|
|
@@ -260,19 +260,28 @@ public class LocalExecutionPlanner {
|
|
|
PhysicalOperation source = plan(outputExec.child(), context);
|
|
|
var output = outputExec.output();
|
|
|
|
|
|
+ return source.withSink(
|
|
|
+ new OutputOperatorFactory(
|
|
|
+ Expressions.names(output),
|
|
|
+ alignPageToAttributes(output, source.layout),
|
|
|
+ outputExec.getPageConsumer()
|
|
|
+ ),
|
|
|
+ source.layout
|
|
|
+ );
|
|
|
+ }
|
|
|
+
|
|
|
+ private static Function<Page, Page> alignPageToAttributes(List<Attribute> attrs, Layout layout) {
|
|
|
// align the page layout with the operator output
|
|
|
// extraction order - the list ordinal is the same as the column one
|
|
|
// while the value represents the position in the original page
|
|
|
- final int[] mappedPosition = new int[output.size()];
|
|
|
+ final int[] mappedPosition = new int[attrs.size()];
|
|
|
int index = -1;
|
|
|
boolean transformRequired = false;
|
|
|
- for (var attribute : output) {
|
|
|
- mappedPosition[++index] = source.layout.getChannel(attribute.id());
|
|
|
- if (transformRequired == false) {
|
|
|
- transformRequired = mappedPosition[index] != index;
|
|
|
- }
|
|
|
+ for (var attribute : attrs) {
|
|
|
+ mappedPosition[++index] = layout.getChannel(attribute.id());
|
|
|
+ transformRequired |= mappedPosition[index] != index;
|
|
|
}
|
|
|
- Function<Page, Page> mapper = transformRequired ? p -> {
|
|
|
+ Function<Page, Page> transformer = transformRequired ? p -> {
|
|
|
var blocks = new Block[mappedPosition.length];
|
|
|
for (int i = 0; i < blocks.length; i++) {
|
|
|
blocks[i] = p.getBlock(mappedPosition[i]);
|
|
@@ -280,7 +289,7 @@ public class LocalExecutionPlanner {
|
|
|
return new Page(blocks);
|
|
|
} : Function.identity();
|
|
|
|
|
|
- return source.withSink(new OutputOperatorFactory(Expressions.names(output), mapper, outputExec.getPageConsumer()), source.layout);
|
|
|
+ return transformer;
|
|
|
}
|
|
|
|
|
|
private PhysicalOperation planExchange(ExchangeExec exchangeExec, LocalExecutionPlannerContext context) {
|
|
@@ -290,26 +299,26 @@ public class LocalExecutionPlanner {
|
|
|
private PhysicalOperation planExchangeSink(ExchangeSinkExec exchangeSink, LocalExecutionPlannerContext context) {
|
|
|
Objects.requireNonNull(exchangeSinkHandler, "ExchangeSinkHandler wasn't provided");
|
|
|
PhysicalOperation source = plan(exchangeSink.child(), context);
|
|
|
- return source.withSink(new ExchangeSinkOperatorFactory(exchangeSinkHandler::createExchangeSink), source.layout);
|
|
|
+
|
|
|
+ Function<Page, Page> transformer = exchangeSink.child() instanceof AggregateExec
|
|
|
+ ? Function.identity()
|
|
|
+ : alignPageToAttributes(exchangeSink.output(), source.layout);
|
|
|
+
|
|
|
+ return source.withSink(new ExchangeSinkOperatorFactory(exchangeSinkHandler::createExchangeSink, transformer), source.layout);
|
|
|
}
|
|
|
|
|
|
private PhysicalOperation planExchangeSource(ExchangeSourceExec exchangeSource, LocalExecutionPlannerContext context) {
|
|
|
- // TODO: ugly hack for now to get the same layout - need to properly support it and have it exposed in the plan and over the wire
|
|
|
- LocalExecutionPlannerContext dummyContext = new LocalExecutionPlannerContext(
|
|
|
- new ArrayList<>(),
|
|
|
- new Holder<>(DriverParallelism.SINGLE),
|
|
|
- 1,
|
|
|
- DataPartitioning.SHARD,
|
|
|
- 1,
|
|
|
- BigArrays.NON_RECYCLING_INSTANCE
|
|
|
- );
|
|
|
-
|
|
|
- var planToGetLayout = plan(exchangeSource.nodeLayout(), dummyContext);
|
|
|
Objects.requireNonNull(exchangeSourceHandler, "ExchangeSourceHandler wasn't provided");
|
|
|
- return PhysicalOperation.fromSource(
|
|
|
- new ExchangeSourceOperatorFactory(exchangeSourceHandler::createExchangeSource),
|
|
|
- planToGetLayout.layout
|
|
|
- );
|
|
|
+
|
|
|
+ var builder = new Layout.Builder();
|
|
|
+ for (var attr : exchangeSource.output()) {
|
|
|
+ builder.appendChannel(attr.id());
|
|
|
+ }
|
|
|
+ // decorate the layout
|
|
|
+ var l = builder.build();
|
|
|
+ var layout = exchangeSource.isIntermediateAgg() ? new ExchangeLayout(l) : l;
|
|
|
+
|
|
|
+ return PhysicalOperation.fromSource(new ExchangeSourceOperatorFactory(exchangeSourceHandler::createExchangeSource), layout);
|
|
|
}
|
|
|
|
|
|
private PhysicalOperation planTopN(TopNExec topNExec, LocalExecutionPlannerContext context) {
|
|
@@ -374,8 +383,6 @@ public class LocalExecutionPlanner {
|
|
|
}
|
|
|
final Expression expr = dissect.inputExpression();
|
|
|
String[] attributeNames = Expressions.names(dissect.extractedFields()).toArray(new String[0]);
|
|
|
- ElementType[] types = new ElementType[dissect.extractedFields().size()];
|
|
|
- Arrays.fill(types, ElementType.BYTES_REF);
|
|
|
|
|
|
Layout layout = layoutBuilder.build();
|
|
|
source = source.with(
|