private ExprNodeDesc analyzeExpr(
    ExprNodeGenericFuncDesc expr,
    List<IndexSearchCondition> searchConditions,
    Object... nodeOutputs) throws SemanticException {

    if (FunctionRegistry.isOpAnd(expr)) {
      assert(nodeOutputs.length >= 2);
      List<ExprNodeDesc> residuals = new ArrayList<ExprNodeDesc>();
      for (Object residual : nodeOutputs) {
        if (null != residual) {
          residuals.add((ExprNodeDesc)residual);
        }
      }
      if (residuals.size() == 0) {
        return null;
      } else if (residuals.size() == 1) {
        return residuals.get(0);
      } else if (residuals.size() > 1) {
        return new ExprNodeGenericFuncDesc(
            TypeInfoFactory.booleanTypeInfo,
            FunctionRegistry.getGenericUDFForAnd(),
            residuals);
      }
    }

    GenericUDF genericUDF = expr.getGenericUDF();
    if (!(genericUDF instanceof GenericUDFBaseCompare)) {
      return expr;
    }
    ExprNodeDesc expr1 = (ExprNodeDesc) nodeOutputs[0];
    ExprNodeDesc expr2 = (ExprNodeDesc) nodeOutputs[1];
    // We may need to peel off the GenericUDFBridge that is added by CBO or user
    if (expr1.getTypeInfo().equals(expr2.getTypeInfo())) {
      expr1 = getColumnExpr(expr1);
      expr2 = getColumnExpr(expr2);
    }

    ExprNodeDesc[] extracted = ExprNodeDescUtils.extractComparePair(expr1, expr2);
    if (extracted == null || (extracted.length > 2 && !acceptsFields)) {
      return expr;
    }

    ExprNodeColumnDesc columnDesc;
    ExprNodeConstantDesc constantDesc;
    if (extracted[0] instanceof ExprNodeConstantDesc) {
      genericUDF = genericUDF.flip();
      columnDesc = (ExprNodeColumnDesc) extracted[1];
      constantDesc = (ExprNodeConstantDesc) extracted[0];
    } else {
      columnDesc = (ExprNodeColumnDesc) extracted[0];
      constantDesc = (ExprNodeConstantDesc) extracted[1];
    }

    Set<String> allowed = columnToUDFs.get(columnDesc.getColumn());
    if (allowed == null) {
      return expr;
    }

    String udfName = genericUDF.getUdfName();
    if (!allowed.contains(genericUDF.getUdfName())) {
      return expr;
    }

    String[] fields = null;
    if (extracted.length > 2) {
      ExprNodeFieldDesc fieldDesc = (ExprNodeFieldDesc) extracted[2];
      if (!isValidField(fieldDesc)) {
        return expr;
      }
      fields = ExprNodeDescUtils.extractFields(fieldDesc);
    }

    // We also need to update the expr so that the index query can be generated.
    // Note that, hive does not support UDFToDouble etc in the query text.
    List<ExprNodeDesc> list = new ArrayList<ExprNodeDesc>();
    list.add(expr1);
    list.add(expr2);
    ExprNodeGenericFuncDesc indexExpr =
            new ExprNodeGenericFuncDesc(expr.getTypeInfo(), expr.getGenericUDF(), list);

    searchConditions.add(
      new IndexSearchCondition(
        columnDesc,
        udfName,
        constantDesc,
        indexExpr,
        expr,
        fields));

    // we converted the expression to a search condition, so
    // remove it from the residual predicate
    return fields == null ? null : expr;
  }
Analyzes a predicate.

@param predicate predicate to be analyzed

@param searchConditions receives conditions produced by analysis

@return residual predicate which could not be translated to
searchConditions
ql/src/java/org/apache/hadoop/hive/ql/index/IndexPredicateAnalyzer.java