CodeGen-Expression
BoundReference: override def genCode(ctx: CodegenContext, ev: ExprCode): String = {
val javaType = ctx.javaType(dataType)
// return the code to retrieve a vlue from the current input row at the ordinal.
val value = ctx.getValue(ctx.INPUT_ROW, dataType, ordinal.toString)
// if we already have everything ready.
if (ctx.currentVars != null && ctx.currentVars(ordinal) != null) {
val oev = ctx.currentVars(ordinal)
ev.isNull = oev.isNull
ev.value = oev.value
val code = oev.code
// the code to retrieve the value has already invoked, no need to call it again.
oev.code = ""
code
} else if (nullable) {
s"""
boolean ${ev.isNull} = ${ctx.INPUT_ROW}.isNullAt($ordinal);
$javaType ${ev.value} = ${ev.isNull} ? ${ctx.defaultValue(dataType)} : ($value);
"""
} else {
ev.isNull = "false"
s"""
$javaType ${ev.value} = $value;
"""
}
} }
Now let's look at CreateStruct:
override def genCode(ctx: CodegenContext, ev: ExprCode): String = {
val rowClass = classOf[GenericInternalRow].getName
val values = ctx.freshName("values")
s"""
boolean ${ev.isNull} = false;
final Object[] $values = new Object[${children.size}];
""" +
children.zipWithIndex.map { case (e, i) =>
val eval = e.gen(ctx)
eval.code + s"""
// set the value in the array at the ordinal
if (${eval.isNull}) {
$values[$i] = null;
} else {
$values[$i] = ${eval.value};
}
"""
}.mkString("\n") +
// Construct the GenericInternalRow with the input array (values) retrieved above.
s"final InternalRow ${ev.value} = new $rowClass($values);"
}
Now let's look at top level Expression:
def gen(ctx: CodegenContext): ExprCode = {
ctx.subExprEliminationExprs.get(this).map { subExprState =>
// This expression is repeated meaning the code to evaluated has already been added
// as a function and called in advance. Just use it.
val code = s"/* ${toCommentSafeString(this.toString)} */"
ExprCode(code, subExprState.isNull, subExprState.value)
}.getOrElse {
val isNull = ctx.freshName("isNull")
val value = ctx.freshName("value")
// We construct a new ExprCode, and genCode will fill the code, which also
// set the value, null etc.
val ve = ExprCode("", isNull, value)
ve.code = genCode(ctx, ve)
if (ve.code != "") {
// Add `this` in the comment.
ve.copy(s"/* ${toCommentSafeString(this.toString)} */\n" + ve.code.trim)
} else {
ve
}
}
}