@@ -586,7 +586,7 @@ abstract class TernaryExpression extends Expression {
586586
587587object ExprCodegen {
588588
589- val placeHolderForResultCode = " __PLACEHOLDER__"
589+ private val placeHolderForResultCode = " __PLACEHOLDER__"
590590
591591 def isNotWholeStageCodegen (ctx : CodegenContext ): Boolean =
592592 ctx.INPUT_ROW != null && ctx.currentVars == null
@@ -626,39 +626,51 @@ object ExprCodegen {
626626 }
627627 }
628628
629- // Generates codes safe from 64k limit for children expressions.
629+ // Generating evaluation code for children expressions. We fold the code for each child
630+ // expression from right to left. Once code length will be larger than the threshold, we
631+ // put the code from next child expression into a method to prevent possible 64k limit.
630632 def genCodeWithChildren (
631633 ctx : CodegenContext ,
632634 expr : Expression ): (String , Seq [ExprCode ]) = {
633- val rawGenCode = expr.children.map(_.genCode(ctx))
635+ val genCodeForChildren = expr.children.map(_.genCode(ctx))
634636
635- val childrenEval = if (expr.nullable) {
636- var childIdx = expr.children.length - 1
637- rawGenCode.foldRight(placeHolderForResultCode) { case (childCode, curCode) =>
638- if (curCode.length + childCode.code.trim.length > 1024 ) {
639- genChildCodeInFunction(ctx, expr.children(childIdx), childCode)
640- }
641- val code = childCode.code +
637+ // For nullable expression, the code of children expression is wrapped in "if" blocks
638+ // for null check. We leave a special placeholder string which will be replaced with
639+ // evaluation code of this expression later.
640+ val initCode = if (expr.nullable) {
641+ placeHolderForResultCode
642+ } else {
643+ " "
644+ }
645+
646+ var childIdx = expr.children.length - 1
647+ val childrenEval = genCodeForChildren.foldRight(initCode) { case (childCode, curCode) =>
648+ if (curCode.length + childCode.code.trim.length > 1024 ) {
649+ genChildCodeInFunction(ctx, expr.children(childIdx), childCode)
650+ }
651+ val code = if (expr.nullable) {
652+ childCode.code +
642653 ctx.nullSafeExec(expr.children(childIdx).nullable, childCode.isNull) {
643654 curCode
644655 }
645- childIdx -= 1
646- code
647- }
648- } else {
649- var childIdx = expr.children.length - 1
650- rawGenCode.foldRight(" " ) { case (childCode, curCode) =>
651- if (curCode.length + childCode.code.trim.length > 1024 ) {
652- genChildCodeInFunction(ctx, expr.children(childIdx), childCode)
653- }
654- val code = childCode.code + " \n " + curCode
655- childIdx -= 1
656- code
656+ } else {
657+ childCode.code + " \n " + curCode
657658 }
659+ childIdx -= 1
660+ code
658661 }
659- (childrenEval, rawGenCode )
662+ (childrenEval, genCodeForChildren )
660663 }
661664
665+ /**
666+ * Generating evaluation code for binary and ternary expressions for now.
667+ * If either of the sub-expressions is null, the result of this computation
668+ * is assumed to be null.
669+ *
670+ * @param childrenEval Evaluation code for all sub-expressions.
671+ * @param resultCode Evaluation code for the current expression. The evaluation is based on
672+ * the values of `childrenEval`.
673+ */
662674 def nullSafeCodeGen (
663675 ctx : CodegenContext ,
664676 ev : ExprCode ,
@@ -670,7 +682,7 @@ object ExprCodegen {
670682 ${ev.isNull} = false; // resultCode could change nullability.
671683 $resultCode
672684 """
673- val nullSafeEval = childrenEval.replace(ExprCodegen . placeHolderForResultCode, insertCode)
685+ val nullSafeEval = childrenEval.replace(placeHolderForResultCode, insertCode)
674686
675687 ev.copy(code = s """
676688 boolean ${ev.isNull} = true;
0 commit comments