private static ExprNodeDesc evaluateFunction(GenericUDF udf, List<ExprNodeDesc> exprs,
      List<ExprNodeDesc> oldExprs) {
    DeferredJavaObject[] arguments = new DeferredJavaObject[exprs.size()];
    ObjectInspector[] argois = new ObjectInspector[exprs.size()];
    for (int i = 0; i < exprs.size(); i++) {
      ExprNodeDesc desc = exprs.get(i);
      if (desc instanceof ExprNodeConstantDesc) {
        ExprNodeConstantDesc constant = (ExprNodeConstantDesc) exprs.get(i);
        if (!constant.getTypeInfo().equals(oldExprs.get(i).getTypeInfo())) {
          constant = typeCast(constant, oldExprs.get(i).getTypeInfo());
          if (constant == null) {
            return null;
          }
        }
        if (constant.getTypeInfo().getCategory() != Category.PRIMITIVE) {
          // nested complex types cannot be folded cleanly
          return null;
        }
        Object value = constant.getValue();
        PrimitiveTypeInfo pti = (PrimitiveTypeInfo) constant.getTypeInfo();
        Object writableValue = null == value ? value :
            PrimitiveObjectInspectorFactory.getPrimitiveJavaObjectInspector(pti)
                .getPrimitiveWritableObject(value);
        arguments[i] = new DeferredJavaObject(writableValue);
        argois[i] =
            ObjectInspectorUtils.getConstantObjectInspector(constant.getWritableObjectInspector(),
                writableValue);

      } else if (desc instanceof ExprNodeGenericFuncDesc) {
        ExprNodeDesc evaluatedFn = foldExpr((ExprNodeGenericFuncDesc)desc);
        if (null == evaluatedFn || !(evaluatedFn instanceof ExprNodeConstantDesc)) {
          return null;
        }
        ExprNodeConstantDesc constant = (ExprNodeConstantDesc) evaluatedFn;
        if (constant.getTypeInfo().getCategory() != Category.PRIMITIVE) {
          // nested complex types cannot be folded cleanly
          return null;
        }
        Object writableValue = PrimitiveObjectInspectorFactory.getPrimitiveJavaObjectInspector(
          (PrimitiveTypeInfo) constant.getTypeInfo()).getPrimitiveWritableObject(constant.getValue());
        arguments[i] = new DeferredJavaObject(writableValue);
        argois[i] = ObjectInspectorUtils.getConstantObjectInspector(constant.getWritableObjectInspector(), writableValue);
      } else {
        return null;
      }
    }

    try {
      ObjectInspector oi = udf.initialize(argois);
      Object o = udf.evaluate(arguments);
      if (LOG.isDebugEnabled()) {
        LOG.debug(udf.getClass().getName() + "(" + exprs + ")=" + o);
      }
      if (o == null) {
        return new ExprNodeConstantDesc(
            TypeInfoUtils.getTypeInfoFromObjectInspector(oi), o);
      }
      Class<?> clz = o.getClass();
      if (PrimitiveObjectInspectorUtils.isPrimitiveWritableClass(clz)) {
        PrimitiveObjectInspector poi = (PrimitiveObjectInspector) oi;
        TypeInfo typeInfo = poi.getTypeInfo();
        o = poi.getPrimitiveJavaObject(o);
        if (typeInfo.getTypeName().contains(serdeConstants.DECIMAL_TYPE_NAME)
            || typeInfo.getTypeName().contains(serdeConstants.VARCHAR_TYPE_NAME)
            || typeInfo.getTypeName().contains(serdeConstants.CHAR_TYPE_NAME)
            || typeInfo.getTypeName().contains(serdeConstants.TIMESTAMPLOCALTZ_TYPE_NAME)) {
          return new ExprNodeConstantDesc(typeInfo, o);
        }
      } else if (udf instanceof GenericUDFStruct
          && oi instanceof StandardConstantStructObjectInspector) {
        // do not fold named_struct, only struct()
        ConstantObjectInspector coi = (ConstantObjectInspector) oi;
        TypeInfo structType = TypeInfoUtils.getTypeInfoFromObjectInspector(coi);
        return new ExprNodeConstantDesc(structType,
            ObjectInspectorUtils.copyToStandardJavaObject(o, coi));
      } else if (!PrimitiveObjectInspectorUtils.isPrimitiveJavaClass(clz)) {
        if (LOG.isErrorEnabled()) {
          LOG.error("Unable to evaluate {}({}). Return value unrecognizable.",
              udf.getClass().getName(), exprs);
        }
        return null;
      } else {
        // fall through
      }
      String constStr = null;
      if (arguments.length == 1 && FunctionRegistry.isOpCast(udf)) {
        // remember original string representation of constant.
        constStr = arguments[0].get().toString();
      }
      return new ExprNodeConstantDesc(o).setFoldedFromVal(constStr);
    } catch (HiveException e) {
      LOG.error("Evaluation function {}({}) failed in Constant Propagation Optimizer.",
          udf.getClass().getName(), exprs);
      throw new RuntimeException(e);
    }
  }
Evaluate UDF

@param udf UDF object
@param exprs
@param oldExprs
@return null if expression cannot be evaluated (not all parameters are constants). Or evaluated
        ExprNodeConstantDesc if possible.
@throws HiveException
ql/src/java/org/apache/hadoop/hive/ql/optimizer/ConstantPropagateProcFactory.java