private Object handleUdfAnd(PcrExprProcCtx ctx, ExprNodeGenericFuncDesc fd,
        Object... nodeOutputs) {
      boolean anyUnknown = false; // Whether any of the node outputs is unknown
      boolean allDivided = true; // Whether all of the node outputs are divided
      
      List<NodeInfoWrapper> newNodeOutputsList = new ArrayList<>(nodeOutputs.length);
      for (int i = 0; i < nodeOutputs.length; i++) {
        NodeInfoWrapper c = (NodeInfoWrapper)nodeOutputs[i];
        if (c.state == WalkState.FALSE) {
          return c;
        }
        if (c.state == WalkState.UNKNOWN) {
          anyUnknown = true;
        }
        if (c.state != WalkState.DIVIDED) {
          allDivided = false;
        }
        if (c.state != WalkState.TRUE) {
          newNodeOutputsList.add(c);
        }
      }
      // If all of them were true, return true
      if (newNodeOutputsList.isEmpty()) {
        return new NodeInfoWrapper(WalkState.TRUE, null,
                new ExprNodeConstantDesc(fd.getTypeInfo(), Boolean.TRUE));
      }
      // If we are left with a single child, return the child
      if (newNodeOutputsList.size() == 1) {
        return newNodeOutputsList.get(0);
      }
      Object[] newNodeOutputs = newNodeOutputsList.toArray();
      if (anyUnknown) {
        return new NodeInfoWrapper(WalkState.UNKNOWN, null, getOutExpr(fd, newNodeOutputs));
      }
      if (allDivided) {
        Boolean[] results = new Boolean[ctx.getPartList().size()];
        for (int i = 0; i < ctx.getPartList().size(); i++) {
          Boolean[] andArray = new Boolean[newNodeOutputs.length];
          for (int j = 0; j < newNodeOutputs.length; j++) {
            andArray[j] = ((NodeInfoWrapper) newNodeOutputs[j]).ResultVector[i];
          }
          results[i] = opAnd(andArray);
        }
        return getResultWrapFromResults(results, fd, newNodeOutputs);
      }
      return new NodeInfoWrapper(WalkState.UNKNOWN, null, getOutExpr(fd, newNodeOutputs));
    }
Processor for Generic functions

If it is AND, OR or NOT, we replace the node to be the constant true or
false if we are sure the result from children, or cut one of the child
if we know partial results. In case of both child has a result vector,
we calculate the result vector for the node. If all partitions agree on
a result, we replace the node with constant true or false. Otherwise, we
pass the vector result. For other Generic functions, if it is non-deterministic
we simply pass it (with children adjusted based on results from children).
If it is deterministic, we evaluate result vector if any of the children
is partition column. Otherwise, we pass it as it is.
ql/src/java/org/apache/hadoop/hive/ql/optimizer/pcr/PcrExprProcFactory.java