use of io.crate.execution.dsl.projection.WindowAggProjection in project crate by crate.
the class WindowAgg method build.
@Override
public ExecutionPlan build(PlannerContext plannerContext, Set<PlanHint> planHints, ProjectionBuilder projectionBuilder, int limit, int offset, @Nullable OrderBy order, @Nullable Integer pageSizeHint, Row params, SubQueryResults subQueryResults) {
InputColumns.SourceSymbols sourceSymbols = new InputColumns.SourceSymbols(source.outputs());
SubQueryAndParamBinder binder = new SubQueryAndParamBinder(params, subQueryResults);
Function<Symbol, Symbol> toInputCols = binder.andThen(s -> InputColumns.create(s, sourceSymbols));
List<WindowFunction> boundWindowFunctions = (List<WindowFunction>) (List) Lists2.map(windowFunctions, toInputCols);
List<Projection> projections = new ArrayList<>();
WindowAggProjection windowAggProjection = new WindowAggProjection(windowDefinition.map(toInputCols), boundWindowFunctions, InputColumns.create(this.standalone, sourceSymbols));
projections.add(windowAggProjection);
ExecutionPlan sourcePlan = source.build(plannerContext, planHints, projectionBuilder, TopN.NO_LIMIT, TopN.NO_OFFSET, null, pageSizeHint, params, subQueryResults);
ResultDescription resultDescription = sourcePlan.resultDescription();
boolean executesOnHandler = executesOnHandler(plannerContext.handlerNode(), resultDescription.nodeIds());
boolean nonDistExecution = windowDefinition.partitions().isEmpty() || resultDescription.hasRemainingLimitOrOffset() || executesOnHandler;
if (nonDistExecution) {
sourcePlan = Merge.ensureOnHandler(sourcePlan, plannerContext);
for (Projection projection : projections) {
sourcePlan.addProjection(projection);
}
} else {
sourcePlan.setDistributionInfo(new DistributionInfo(DistributionType.MODULO, source.outputs().indexOf(windowDefinition.partitions().iterator().next())));
MergePhase distWindowAgg = new MergePhase(UUIDs.dirtyUUID(), plannerContext.nextExecutionPhaseId(), "distWindowAgg", resultDescription.nodeIds().size(), resultDescription.numOutputs(), resultDescription.nodeIds(), resultDescription.streamOutputs(), projections, DistributionInfo.DEFAULT_BROADCAST, null);
return new Merge(sourcePlan, distWindowAgg, TopN.NO_LIMIT, TopN.NO_OFFSET, windowAggProjection.outputs().size(), resultDescription.maxRowsPerNode(), null);
}
return sourcePlan;
}
use of io.crate.execution.dsl.projection.WindowAggProjection in project crate by crate.
the class WindowProjector method fromProjection.
public static Projector fromProjection(WindowAggProjection projection, NodeContext nodeCtx, InputFactory inputFactory, TransactionContext txnCtx, RamAccounting ramAccounting, MemoryManager memoryManager, Version minNodeVersion, Version indexVersionCreated, IntSupplier numThreads, Executor executor) {
var windowFunctionSymbols = projection.windowFunctions();
var numWindowFunctions = windowFunctionSymbols.size();
assert numWindowFunctions > 0 : "WindowAggProjection must have at least 1 window function.";
ArrayList<WindowFunction> windowFunctions = new ArrayList<>(numWindowFunctions);
ArrayList<CollectExpression<Row, ?>> windowFuncArgsExpressions = new ArrayList<>(numWindowFunctions);
Input[][] windowFuncArgsInputs = new Input[numWindowFunctions][];
Boolean[] ignoreNulls = new Boolean[numWindowFunctions];
for (int idx = 0; idx < numWindowFunctions; idx++) {
var windowFunctionSymbol = windowFunctionSymbols.get(idx);
InputFactory.Context<CollectExpression<Row, ?>> ctx = inputFactory.ctxForInputColumns(txnCtx);
ctx.add(windowFunctionSymbol.arguments());
FunctionImplementation impl = nodeCtx.functions().getQualified(windowFunctionSymbol, txnCtx.sessionSettings().searchPath());
assert impl != null : "Function implementation not found using full qualified lookup";
if (impl instanceof AggregationFunction) {
var filterInputFactoryCtx = inputFactory.ctxForInputColumns(txnCtx);
var filterSymbol = windowFunctionSymbol.filter();
// noinspection unchecked
Input<Boolean> filterInput = filterSymbol == null ? Literal.BOOLEAN_TRUE : (Input<Boolean>) filterInputFactoryCtx.add(filterSymbol);
ExpressionsInput<Row, Boolean> filter = new ExpressionsInput<>(filterInput, filterInputFactoryCtx.expressions());
windowFunctions.add(new AggregateToWindowFunctionAdapter((AggregationFunction) impl, filter, indexVersionCreated, ramAccounting, memoryManager, minNodeVersion));
} else if (impl instanceof WindowFunction) {
windowFunctions.add((WindowFunction) impl);
} else {
throw new AssertionError("Function needs to be either a window or an aggregate function");
}
windowFuncArgsExpressions.addAll(ctx.expressions());
windowFuncArgsInputs[idx] = ctx.topLevelInputs().toArray(new Input[0]);
ignoreNulls[idx] = windowFunctionSymbol.ignoreNulls();
}
var windowDefinition = projection.windowDefinition();
var partitions = windowDefinition.partitions();
Supplier<InputFactory.Context<CollectExpression<Row, ?>>> createInputFactoryContext = () -> inputFactory.ctxForInputColumns(txnCtx);
int arrayListElementOverHead = 32;
RowAccountingWithEstimators accounting = new RowAccountingWithEstimators(Symbols.typeView(projection.standalone()), ramAccounting, arrayListElementOverHead);
Comparator<Object[]> cmpPartitionBy = partitions.isEmpty() ? null : createComparator(createInputFactoryContext, new OrderBy(windowDefinition.partitions()));
Comparator<Object[]> cmpOrderBy = createComparator(createInputFactoryContext, windowDefinition.orderBy());
int numCellsInSourceRow = projection.standalone().size();
ComputeFrameBoundary<Object[]> computeFrameStart = createComputeStartFrameBoundary(numCellsInSourceRow, txnCtx, nodeCtx, windowDefinition, cmpOrderBy);
ComputeFrameBoundary<Object[]> computeFrameEnd = createComputeEndFrameBoundary(numCellsInSourceRow, txnCtx, nodeCtx, windowDefinition, cmpOrderBy);
return sourceRows -> WindowFunctionBatchIterator.of(sourceRows, accounting, computeFrameStart, computeFrameEnd, cmpPartitionBy, cmpOrderBy, numCellsInSourceRow, numThreads, executor, windowFunctions, windowFuncArgsExpressions, ignoreNulls, windowFuncArgsInputs);
}
use of io.crate.execution.dsl.projection.WindowAggProjection in project crate by crate.
the class WindowDefinitionTest method testUnboundedPrecedingUnboundedFollowingFrameIsAllowed.
@Test
public void testUnboundedPrecedingUnboundedFollowingFrameIsAllowed() {
Collect collect = e.plan("select sum(col1) over(RANGE BETWEEN UNBOUNDED PRECEDING and UNBOUNDED FOLLOWING) FROM " + "unnest([1, 2, 1, 1, 1, 4])");
List<Projection> projections = collect.collectPhase().projections();
assertThat(projections.size(), is(2));
WindowAggProjection windowProjection = null;
for (Projection projection : projections) {
if (projection instanceof WindowAggProjection) {
windowProjection = (WindowAggProjection) projection;
break;
}
}
assertThat(windowProjection, is(notNullValue()));
List<? extends Symbol> outputs = windowProjection.outputs();
// IC and window function
assertThat(outputs.size(), is(2));
WindowFunction windowFunction = null;
for (Symbol output : outputs) {
if (output instanceof WindowFunction) {
windowFunction = (WindowFunction) output;
}
}
assertThat(windowFunction, is(notNullValue()));
assertThat(windowFunction.windowDefinition().windowFrameDefinition().start().type(), is(UNBOUNDED_PRECEDING));
assertThat(windowFunction.windowDefinition().windowFrameDefinition().end().type(), is(UNBOUNDED_FOLLOWING));
}
Aggregations