@Override
    public Object process(Node nd, Stack<Node> stack, NodeProcessorCtx procCtx,
        Object... nodeOutputs) throws SemanticException {

      ExprNodeDesc newfd = null;
      ExprNodeGenericFuncDesc fd = (ExprNodeGenericFuncDesc) nd;

      boolean unknown = false;

      if (FunctionRegistry.isOpAndOrNot(fd)) {
        // do nothing because "And" and "Or" and "Not" supports null value
        // evaluation
        // NOTE: In the future all UDFs that treats null value as UNKNOWN (both
        // in parameters and return
        // values) should derive from a common base class UDFNullAsUnknown, so
        // instead of listing the classes
        // here we would test whether a class is derived from that base class.
        // If All childs are null, set unknown to true
        boolean isAllNull = true;
        for (Object child : nodeOutputs) {
          ExprNodeDesc child_nd = (ExprNodeDesc) child;
          if (!(child_nd instanceof ExprNodeConstantDesc
              && ((ExprNodeConstantDesc) child_nd).getValue() == null)) {
            isAllNull = false;
          }
        }
        unknown = isAllNull;
      } else if (!FunctionRegistry.isConsistentWithinQuery(fd.getGenericUDF())) {
        // If it's a non-deterministic UDF, set unknown to true
        unknown = true;
      } else {
        // If any child is null, set unknown to true
        for (Object child : nodeOutputs) {
          ExprNodeDesc child_nd = (ExprNodeDesc) child;
          if (child_nd instanceof ExprNodeConstantDesc
              && ((ExprNodeConstantDesc) child_nd).getValue() == null) {
            unknown = true;
          }
        }
      }

      if (unknown) {
        newfd = new ExprNodeConstantDesc(fd.getTypeInfo(), null);
      } else {
        // Create the list of children
        ArrayList<ExprNodeDesc> children = new ArrayList<ExprNodeDesc>();
        for (Object child : nodeOutputs) {
          children.add((ExprNodeDesc) child);
        }
        // Create a copy of the function descriptor
        newfd = new ExprNodeGenericFuncDesc(fd.getTypeInfo(), fd.getGenericUDF(), children);
      }

      return newfd;
    }
If all children are candidates and refer only to one table alias then this
expr is a candidate else it is not a candidate but its children could be
final candidates.
ql/src/java/org/apache/hadoop/hive/ql/optimizer/PrunerExpressionOperatorFactory.java