private VectorExpression getCustomUDFExpression(ExprNodeGenericFuncDesc expr, VectorExpressionDescriptor.Mode mode)
      throws HiveException {

    boolean isFilter = false;    // Assume.
    if (mode == VectorExpressionDescriptor.Mode.FILTER) {

      // Is output type a BOOLEAN?
      TypeInfo resultTypeInfo = expr.getTypeInfo();
      if (resultTypeInfo.getCategory() == Category.PRIMITIVE &&
          ((PrimitiveTypeInfo) resultTypeInfo).getPrimitiveCategory() == PrimitiveCategory.BOOLEAN) {
        isFilter = true;
      } else {
        return null;
      }
    }

    //GenericUDFBridge udfBridge = (GenericUDFBridge) expr.getGenericUDF();
    List<ExprNodeDesc> childExprList = expr.getChildren();
    final int childrenCount = childExprList.size();

    // argument descriptors
    VectorUDFArgDesc[] argDescs = new VectorUDFArgDesc[childrenCount];
    for (int i = 0; i < argDescs.length; i++) {
      argDescs[i] = new VectorUDFArgDesc();
    }

    // positions of variable arguments (columns or non-constant expressions)
    List<Integer> variableArgPositions = new ArrayList<>();

    // Column numbers of batch corresponding to expression result arguments
    List<Integer> exprResultColumnNums = new ArrayList<>();

    // Prepare children
    List<VectorExpression> vectorExprs = new ArrayList<>();

    TypeInfo[] inputTypeInfos = new TypeInfo[childrenCount];
    DataTypePhysicalVariation[] inputDataTypePhysicalVariations = new DataTypePhysicalVariation[childrenCount];

    for (int i = 0; i < childrenCount; i++) {
      ExprNodeDesc child = childExprList.get(i);
      inputTypeInfos[i] = child.getTypeInfo();
      inputDataTypePhysicalVariations[i] = DataTypePhysicalVariation.NONE;

      if (child instanceof ExprNodeGenericFuncDesc) {
        VectorExpression e = getVectorExpression(child, VectorExpressionDescriptor.Mode.PROJECTION);
        vectorExprs.add(e);
        variableArgPositions.add(i);
        exprResultColumnNums.add(e.getOutputColumnNum());
        argDescs[i].setVariable(e.getOutputColumnNum());
      } else if (child instanceof ExprNodeColumnDesc) {
        variableArgPositions.add(i);
        argDescs[i].setVariable(getInputColumnIndex(((ExprNodeColumnDesc) child).getColumn()));
      } else if (child instanceof ExprNodeConstantDesc) {
        // this is a constant (or null)
        if (child.getTypeInfo().getCategory() != Category.PRIMITIVE &&
            child.getTypeInfo().getCategory() != Category.STRUCT) {

          // Complex type constants currently not supported by VectorUDFArgDesc.prepareConstant.
          throw new HiveException(
              "Unable to vectorize custom UDF. LIST, MAP, and UNION type constants not supported: " + child);
        }
        argDescs[i].setConstant((ExprNodeConstantDesc) child);
      } else if (child instanceof ExprNodeDynamicValueDesc) {
        VectorExpression e = getVectorExpression(child, VectorExpressionDescriptor.Mode.PROJECTION);
        vectorExprs.add(e);
        variableArgPositions.add(i);
        exprResultColumnNums.add(e.getOutputColumnNum());
        argDescs[i].setVariable(e.getOutputColumnNum());
      } else if (child instanceof ExprNodeFieldDesc) {
        // Get the GenericUDFStructField to process the field of Struct type
        VectorExpression e =
            getGenericUDFStructField(
                (ExprNodeFieldDesc) child, VectorExpressionDescriptor.Mode.PROJECTION,
                child.getTypeInfo());
        vectorExprs.add(e);
        variableArgPositions.add(i);
        exprResultColumnNums.add(e.getOutputColumnNum());
        argDescs[i].setVariable(e.getOutputColumnNum());
      } else {
        throw new HiveException("Unable to vectorize custom UDF. Encountered unsupported expr desc : "
            + child);
      }
    }

    // Allocate output column and get column number;
    TypeInfo resultTypeInfo = expr.getTypeInfo();
    String resultTypeName = resultTypeInfo.getTypeName();

    final int outputColumnNum = ocm.allocateOutputColumn(expr.getTypeInfo());

    // Make vectorized operator
    VectorUDFAdaptor ve = new VectorUDFAdaptor(expr, outputColumnNum, resultTypeName, argDescs);
    ve.setSuppressEvaluateExceptions(adaptorSuppressEvaluateExceptions);

    // Set child expressions
    VectorExpression[] childVEs = null;
    if (exprResultColumnNums.size() != 0) {
      childVEs = new VectorExpression[exprResultColumnNums.size()];
      for (int i = 0; i < childVEs.length; i++) {
        childVEs[i] = vectorExprs.get(i);
      }
    }
    ve.setChildExpressions(childVEs);

    ve.setInputTypeInfos(inputTypeInfos);
    ve.setInputDataTypePhysicalVariations(inputDataTypePhysicalVariations);

    ve.setOutputTypeInfo(resultTypeInfo);
    ve.setOutputDataTypePhysicalVariation(DataTypePhysicalVariation.NONE);

    // Free output columns if inputs have non-leaf expression trees.
    for (Integer i : exprResultColumnNums) {
      ocm.freeOutputColumn(i);
    }

    if (isFilter) {
      SelectColumnIsTrue filterVectorExpr = new SelectColumnIsTrue(outputColumnNum);

      filterVectorExpr.setChildExpressions(new VectorExpression[] {ve});

      filterVectorExpr.setInputTypeInfos(ve.getOutputTypeInfo());
      filterVectorExpr.setInputDataTypePhysicalVariations(ve.getOutputDataTypePhysicalVariation());

      return filterVectorExpr;
    } else {
      return ve;
    }
  }
Invoke special handling for expressions that can't be vectorized by regular
descriptor based lookup.
ql/src/java/org/apache/hadoop/hive/ql/exec/vector/VectorizationContext.java