private List<ExprNodeDesc> getChildExpressionsWithImplicitCast(GenericUDF genericUDF,
      List<ExprNodeDesc> children, TypeInfo returnType) throws HiveException {

    if (isCustomUDF(genericUDF.getUdfName())) {
      // no implicit casts possible
      return children;
    }

    if (isExcludedFromCast(genericUDF)) {
      // No implicit cast needed
      return children;
    }
    if (children == null) {
      return null;
    }

    TypeInfo commonType = getCommonTypeForChildExpressions(genericUDF, children, returnType);

    if (commonType == null) {

      // Couldn't determine common type, don't cast
      return children;
    }

    List<ExprNodeDesc> childrenWithCasts = new ArrayList<>();
    boolean atleastOneCastNeeded = false;
    if (genericUDF instanceof GenericUDFElt) {
      int i = 0;
      for (ExprNodeDesc child : children) {
        TypeInfo castType = commonType;
        if (i++ == 0) {
          castType = isIntFamily(child.getTypeString()) ? child.getTypeInfo() : TypeInfoFactory.intTypeInfo;
        }
        ExprNodeDesc castExpression = getImplicitCastExpression(genericUDF, child, castType);
        if (castExpression != null) {
          atleastOneCastNeeded = true;
          childrenWithCasts.add(castExpression);
        } else {
          childrenWithCasts.add(child);
        }
      }
    } else if (genericUDF instanceof GenericUDFIf) {
      int i = 0;
      for (ExprNodeDesc child : children) {
        if (i++ == 0) {

          // Skip boolean predicate.
          childrenWithCasts.add(child);
          continue;
        }
        if (child instanceof ExprNodeConstantDesc &&
            ((ExprNodeConstantDesc) child).getValue() == null) {

          // Don't cast NULL using ConstantValueExpression but replace the NULL expression with the
          // desired type set. This lets the doGetIfExpression logic use IfExprCondExprNull, etc.
          childrenWithCasts.add(new ExprNodeConstantDesc(commonType, null));
          atleastOneCastNeeded = true;
          continue;
        }
        ExprNodeDesc castExpression = getImplicitCastExpression(genericUDF, child, commonType);
        if (castExpression != null) {
          atleastOneCastNeeded = true;
          childrenWithCasts.add(castExpression);
        } else {
          childrenWithCasts.add(child);
        }
      }
    } else if(genericUDF instanceof GenericUDFWhen) {
      boolean hasElseClause = children.size() % 2 == 1 ;
      for (int i=0; i<children.size(); i++) {
        ExprNodeDesc castExpression = null;
        if (i % 2 == 1) {
          castExpression = getImplicitCastExpression(genericUDF, children.get(i), commonType);
        }
        if(hasElseClause && i == children.size()-1) {
          castExpression = getImplicitCastExpression(genericUDF, children.get(i), commonType);
        }
        if (castExpression != null) {
          atleastOneCastNeeded = true;
          childrenWithCasts.add(castExpression);
        } else {
          childrenWithCasts.add(children.get(i));
        }
      }
    } else {
      for (ExprNodeDesc child : children) {
        ExprNodeDesc castExpression = getImplicitCastExpression(genericUDF, child, commonType);
        if (castExpression != null) {
          atleastOneCastNeeded = true;
          childrenWithCasts.add(castExpression);
        } else {
          childrenWithCasts.add(child);
        }
      }
    }
    if (atleastOneCastNeeded) {
      return childrenWithCasts;
    } else {
      return children;
    }
  }
Add a cast expression to the expression tree if needed. The output of child expressions of a given UDF might
need a cast if their return type is different from the return type of the UDF.

@param genericUDF The given UDF
@param children Child expressions of the UDF that might require a cast.
@param returnType The return type of the UDF.
@return List of child expressions added with cast.
ql/src/java/org/apache/hadoop/hive/ql/exec/vector/VectorizationContext.java