@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.
} else if (!FunctionRegistry.isDeterministic(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;
}