use of org.apache.flink.table.data.utils.CastExecutor in project flink by apache.
the class AbstractCodeGeneratorCastRule method create.
@SuppressWarnings("unchecked")
@Override
public CastExecutor<IN, OUT> create(CastRule.Context castRuleContext, LogicalType inputLogicalType, LogicalType targetLogicalType) {
final String inputTerm = "_myInput";
final String inputIsNullTerm = "_myInputIsNull";
final String castExecutorClassName = CodeGenUtils.newName("GeneratedCastExecutor");
final String inputTypeTerm = CodeGenUtils.boxedTypeTermForType(inputLogicalType);
final CastExecutorCodeGeneratorContext ctx = new CastExecutorCodeGeneratorContext(castRuleContext);
final CastCodeBlock codeBlock = generateCodeBlock(ctx, inputTerm, inputIsNullTerm, inputLogicalType, targetLogicalType);
// Class fields can contain type serializers
final String classFieldDecls = Stream.concat(ctx.typeSerializers.values().stream().map(entry -> "private final " + className(entry.getValue().getClass()) + " " + entry.getKey() + ";"), ctx.getClassFields().stream()).collect(Collectors.joining("\n"));
final String constructorSignature = "public " + castExecutorClassName + "(" + ctx.typeSerializers.values().stream().map(entry -> className(entry.getValue().getClass()) + " " + entry.getKey()).collect(Collectors.joining(", ")) + ")";
final String constructorBody = ctx.getDeclaredTypeSerializers().stream().map(name -> "this." + name + " = " + name + ";\n").collect(Collectors.joining());
// Because janino doesn't support generics, we need to manually cast the input variable of
// the cast method
final String functionSignature = "@Override public Object cast(Object _myInputObj) throws " + className(TableException.class);
// Write the function body
final CastRuleUtils.CodeWriter bodyWriter = new CastRuleUtils.CodeWriter();
bodyWriter.declStmt(inputTypeTerm, inputTerm, cast(inputTypeTerm, "_myInputObj"));
bodyWriter.declStmt("boolean", inputIsNullTerm, "_myInputObj == null");
ctx.variableDeclarationStatements.forEach(decl -> bodyWriter.appendBlock(decl + "\n"));
if (this.canFail(inputLogicalType, targetLogicalType)) {
bodyWriter.tryCatchStmt(tryWriter -> tryWriter.append(codeBlock).stmt("return " + codeBlock.getReturnTerm()), (exceptionTerm, catchWriter) -> catchWriter.throwStmt(constructorCall(TableException.class, strLiteral("Error when casting " + inputLogicalType + " to " + targetLogicalType + "."), exceptionTerm)));
} else {
bodyWriter.append(codeBlock).stmt("return " + codeBlock.getReturnTerm());
}
final String classCode = "public final class " + castExecutorClassName + " implements " + className(CastExecutor.class) + " {\n" + classFieldDecls + "\n" + constructorSignature + " {\n" + constructorBody + "}\n" + functionSignature + " {\n" + bodyWriter + "}\n}";
try {
Object[] constructorArgs = ctx.getTypeSerializersInstances().toArray(new TypeSerializer[0]);
return (CastExecutor<IN, OUT>) CompileUtils.compile(castRuleContext.getClassLoader(), castExecutorClassName, classCode).getConstructors()[0].newInstance(constructorArgs);
} catch (Throwable e) {
throw new FlinkRuntimeException("Cast executor cannot be instantiated. This is a bug. Please file an issue. Code:\n" + classCode, e);
}
}
Aggregations