private void generateFilterAndProjectRowOriented(
ClassDefinition classDefinition,
RowExpression filter,
List<RowExpression> projections)
{
MethodDefinition filterAndProjectMethod = classDefinition.declareMethod(new CompilerContext(BOOTSTRAP_METHOD),
a(PUBLIC),
"filterAndProjectRowOriented",
type(void.class),
arg("page", com.facebook.presto.operator.Page.class),
arg("pageBuilder", PageBuilder.class));
CompilerContext compilerContext = filterAndProjectMethod.getCompilerContext();
Variable positionVariable = compilerContext.declareVariable(int.class, "position");
Variable rowsVariable = compilerContext.declareVariable(int.class, "rows");
filterAndProjectMethod.getBody()
.comment("int rows = page.getPositionCount();")
.getVariable("page")
.invokeVirtual(com.facebook.presto.operator.Page.class, "getPositionCount", int.class)
.putVariable(rowsVariable);
List<Integer> allInputChannels = getInputChannels(Iterables.concat(projections, ImmutableList.of(filter)));
for (int channel : allInputChannels) {
Variable blockVariable = compilerContext.declareVariable(com.facebook.presto.spi.block.Block.class, "block_" + channel);
filterAndProjectMethod.getBody()
.comment("Block %s = page.getBlock(%s);", blockVariable.getName(), channel)
.getVariable("page")
.push(channel)
.invokeVirtual(com.facebook.presto.operator.Page.class, "getBlock", com.facebook.presto.spi.block.Block.class, int.class)
.putVariable(blockVariable);
}
//
// for loop body
//
// for (position = 0; position < rows; position++)
ForLoopBuilder forLoop = forLoopBuilder(compilerContext)
.comment("for (position = 0; position < rows; position++)")
.initialize(new Block(compilerContext).putVariable(positionVariable, 0))
.condition(new Block(compilerContext)
.getVariable(positionVariable)
.getVariable(rowsVariable)
.invokeStatic(CompilerOperations.class, "lessThan", boolean.class, int.class, int.class))
.update(new Block(compilerContext).incrementVariable(positionVariable, (byte) 1));
Block forLoopBody = new Block(compilerContext);
IfStatementBuilder ifStatement = new IfStatementBuilder(compilerContext)
.comment("if (filter(position, blocks...)");
Block condition = new Block(compilerContext);
condition.pushThis();
condition.getVariable(positionVariable);
List<Integer> filterInputChannels = getInputChannels(filter);
for (int channel : filterInputChannels) {
condition.getVariable("block_" + channel);
}
condition.invokeVirtual(classDefinition.getType(),
"filter",
type(boolean.class),
ImmutableList.<ParameterizedType>builder()
.add(type(int.class))
.addAll(nCopies(filterInputChannels.size(), type(com.facebook.presto.spi.block.Block.class)))
.build());
ifStatement.condition(condition);
Block trueBlock = new Block(compilerContext);
if (projections.isEmpty()) {
trueBlock
.comment("pageBuilder.declarePosition()")
.getVariable("pageBuilder")
.invokeVirtual(PageBuilder.class, "declarePosition", void.class);
}
else {
// pageBuilder.getBlockBuilder(0).append(block.getDouble(0);
for (int projectionIndex = 0; projectionIndex < projections.size(); projectionIndex++) {
trueBlock.comment("project_%s(position, blocks..., pageBuilder.getBlockBuilder(%s))", projectionIndex, projectionIndex);
trueBlock.pushThis();
List<Integer> projectionInputs = getInputChannels(projections.get(projectionIndex));
trueBlock.getVariable(positionVariable);
for (int channel : projectionInputs) {
trueBlock.getVariable("block_" + channel);
}
// pageBuilder.getBlockBuilder(0)
trueBlock.getVariable("pageBuilder")
.push(projectionIndex)
.invokeVirtual(PageBuilder.class, "getBlockBuilder", BlockBuilder.class, int.class);
// project(position, block_0, block_1, blockBuilder)
trueBlock.invokeVirtual(classDefinition.getType(),
"project_" + projectionIndex,
type(void.class),
ImmutableList.<ParameterizedType>builder()
.add(type(int.class))
.addAll(nCopies(projectionInputs.size(), type(com.facebook.presto.spi.block.Block.class)))
.add(type(BlockBuilder.class))
.build());
}
}
ifStatement.ifTrue(trueBlock);
forLoopBody.append(ifStatement.build());
filterAndProjectMethod.getBody().append(forLoop.body(forLoopBody).build());
filterAndProjectMethod.getBody().ret();
}