Expression filter,
List<Expression> projections,
Map<Input, Type> inputTypes,
DynamicClassLoader classLoader)
{
ClassDefinition classDefinition = new ClassDefinition(new CompilerContext(bootstrapMethod),
a(PUBLIC, FINAL),
typeFromPathName("ScanFilterAndProjectOperator_" + CLASS_ID.incrementAndGet()),
type(AbstractScanFilterAndProjectOperator.class));
// declare fields
FieldDefinition sessionField = classDefinition.declareField(a(PRIVATE, FINAL), "session", Session.class);
// constructor
classDefinition.declareConstructor(new CompilerContext(bootstrapMethod),
a(PUBLIC),
arg("operatorContext", OperatorContext.class),
arg("sourceId", PlanNodeId.class),
arg("dataStreamProvider", DataStreamProvider.class),
arg("columns", type(Iterable.class, ColumnHandle.class)),
arg("tupleInfos", type(Iterable.class, TupleInfo.class)))
.getBody()
.comment("super(operatorContext, sourceId, dataStreamProvider, columns, tupleInfos);")
.pushThis()
.getVariable("operatorContext")
.getVariable("sourceId")
.getVariable("dataStreamProvider")
.getVariable("columns")
.getVariable("tupleInfos")
.invokeConstructor(AbstractScanFilterAndProjectOperator.class, OperatorContext.class, PlanNodeId.class, DataStreamProvider.class, Iterable.class, Iterable.class)
.comment("this.session = operatorContext.getSession();")
.pushThis()
.getVariable("operatorContext")
.invokeVirtual(OperatorContext.class, "getSession", Session.class)
.putField(sessionField)
.ret();
generateFilterAndProjectRowOriented(classDefinition, projections, inputTypes);
generateFilterAndProjectCursorMethod(classDefinition, projections);
//
// filter method
//
generateFilterMethod(classDefinition, filter, inputTypes, true);
generateFilterMethod(classDefinition, filter, inputTypes, false);
//
// project methods
//
List<TupleInfo> tupleInfos = new ArrayList<>();
int projectionIndex = 0;
for (Expression projection : projections) {
Class<?> type = generateProjectMethod(classDefinition, "project_" + projectionIndex, projection, inputTypes, true);
generateProjectMethod(classDefinition, "project_" + projectionIndex, projection, inputTypes, false);
if (type == boolean.class) {
tupleInfos.add(TupleInfo.SINGLE_BOOLEAN);
}
// todo remove assumption that void is a long
else if (type == long.class || type == void.class) {
tupleInfos.add(TupleInfo.SINGLE_LONG);
}
else if (type == double.class) {
tupleInfos.add(TupleInfo.SINGLE_DOUBLE);
}
else if (type == Slice.class) {
tupleInfos.add(TupleInfo.SINGLE_VARBINARY);
}
else {
throw new IllegalStateException("Type " + type.getName() + "can be output");
}
projectionIndex++;
}
//
// toString method
//
classDefinition.declareMethod(new CompilerContext(bootstrapMethod), a(PUBLIC), "toString", type(String.class))
.getBody()
.push(toStringHelper(classDefinition.getType().getJavaClassName())
.add("filter", filter)
.add("projections", projections)
.toString())
.retObject();