in paimon-codegen/src/main/scala/org/apache/paimon/codegen/ExprCodeGenerator.scala [90:164]
def generateResultExpression(
fieldExprs: Seq[GeneratedExpression],
fieldExprIdxToOutputRowPosMap: Map[Int, Int],
returnType: RowType,
returnTypeClazz: Class[_ <: InternalRow],
outRow: String,
outRowWriter: Option[String],
reusedOutRow: Boolean,
outRowAlreadyExists: Boolean): GeneratedExpression = {
// initial type check
if (returnType.getFieldCount != fieldExprs.length) {
throw new CodeGenException(
s"Arity [${returnType.getFieldCount}] of result type [$returnType] does not match " +
s"number [${fieldExprs.length}] of expressions [$fieldExprs].")
}
if (fieldExprIdxToOutputRowPosMap.size != fieldExprs.length) {
throw new CodeGenException(
s"Size [${returnType.getFieldCount}] of fieldExprIdxToOutputRowPosMap does not match " +
s"number [${fieldExprs.length}] of expressions [$fieldExprs].")
}
// type check
fieldExprs.zipWithIndex.foreach {
// timestamp type(Include TimeIndicator) and generic type can compatible with each other.
case (fieldExpr, i) if fieldExpr.resultType.isInstanceOf[TimestampType] =>
if (returnType.getTypeAt(i).getClass != fieldExpr.resultType.getClass) {
throw new CodeGenException(
s"Incompatible types of expression and result type, Expression[$fieldExpr] type is " +
s"[${fieldExpr.resultType}], result type is [${returnType.getTypeAt(i)}]")
}
case (fieldExpr, i) if !isInteroperable(fieldExpr.resultType, returnType.getTypeAt(i)) =>
throw new CodeGenException(
s"Incompatible types of expression and result type. Expression[$fieldExpr] type is " +
s"[${fieldExpr.resultType}], result type is [${returnType.getTypeAt(i)}]")
case _ => // ok
}
val setFieldsCode = fieldExprs.zipWithIndex
.map {
case (fieldExpr, index) =>
val pos = fieldExprIdxToOutputRowPosMap.getOrElse(
index,
throw new CodeGenException(s"Illegal field expr index: $index"))
rowSetField(ctx, returnTypeClazz, outRow, pos.toString, fieldExpr, outRowWriter)
}
.mkString("\n")
val outRowInitCode = if (!outRowAlreadyExists) {
val initCode = generateRecordStatement(returnType, returnTypeClazz, outRow, outRowWriter, ctx)
if (reusedOutRow) {
NO_CODE
} else {
initCode
}
} else {
NO_CODE
}
val code = if (returnTypeClazz == classOf[BinaryRow] && outRowWriter.isDefined) {
val writer = outRowWriter.get
val resetWriter = s"$writer.reset();"
val completeWriter: String = s"$writer.complete();"
s"""
|$outRowInitCode
|$resetWriter
|$setFieldsCode
|$completeWriter
""".stripMargin
} else {
s"""
|$outRowInitCode
|$setFieldsCode
""".stripMargin
}
GeneratedExpression(outRow, NEVER_NULL, code, returnType)
}