public static boolean merge(HiveConf hiveConf, ReduceSinkOperator cRS, ReduceSinkOperator pRS, int minReducer)
      throws SemanticException {
    int[] result = extractMergeDirections(hiveConf, cRS, pRS, minReducer);
    if (result == null) {
      return false;
    }

    if (result[0] > 0) {
      // The sorting columns of the child RS are more specific than
      // those of the parent RS. Assign sorting columns of the child RS
      // to the parent RS.
      List<ExprNodeDesc> childKCs = cRS.getConf().getKeyCols();
      pRS.getConf().setKeyCols(ExprNodeDescUtils.backtrack(childKCs, cRS, pRS));
    }

    List<ExprNodeDesc> childPCs = cRS.getConf().getPartitionCols();
    List<ExprNodeDesc> parentPCs = pRS.getConf().getPartitionCols();
    if (canReplaceParentWithChildPartioning(result[1], childPCs, parentPCs)) {
      pRS.getConf().setPartitionCols(ExprNodeDescUtils.backtrack(childPCs, cRS, pRS));
    }

    if (result[2] > 0) {
      // The sorting order of the child RS is more specific than
      // that of the parent RS. Assign the sorting order of the child RS
      // to the parent RS.
      if (result[0] <= 0) {
        // Sorting columns of the parent RS are more specific than those of the
        // child RS but Sorting order of the child RS is more specific than
        // that of the parent RS.
        throw new SemanticException("Sorting columns and order don't match. " +
            "Try set " + HiveConf.ConfVars.HIVE_OPT_REDUCE_DEDUPLICATION + "=false;");
      }
      pRS.getConf().setOrder(cRS.getConf().getOrder());
      pRS.getConf().setNullOrder(cRS.getConf().getNullOrder());
    } else {
      // The sorting order of the parent RS is more specific or they are equal.
      // We will copy the order from the child RS, and then fill in the order
      // of the rest of columns with the one taken from parent RS.
      StringBuilder order = new StringBuilder(cRS.getConf().getOrder());
      StringBuilder orderNull = new StringBuilder(cRS.getConf().getNullOrder());
      order.append(pRS.getConf().getOrder().substring(order.length()));
      orderNull.append(pRS.getConf().getNullOrder().substring(orderNull.length()));
      pRS.getConf().setOrder(order.toString());
      pRS.getConf().setNullOrder(orderNull.toString());
    }

    if (result[3] > 0) {
      // The number of reducers of the child RS is more specific than
      // that of the parent RS. Assign the number of reducers of the child RS
      // to the parent RS.
      pRS.getConf().setNumReducers(cRS.getConf().getNumReducers());
    }

    if (result[4] > 0) {
      // This case happens only when pRS key is empty in which case we can use
      // number of distribution keys and key serialization info from cRS
      if (pRS.getConf().getKeyCols() != null && pRS.getConf().getKeyCols().size() == 0
          && cRS.getConf().getKeyCols() != null && cRS.getConf().getKeyCols().size() == 0) {
        // As setNumDistributionKeys is a subset of keycols, the size should
        // be 0 too. This condition maybe too strict. We may extend it in the
        // future.
        TableDesc keyTable = PlanUtils.getReduceKeyTableDesc(new ArrayList<FieldSchema>(), pRS
            .getConf().getOrder(), pRS.getConf().getNullOrder());
        pRS.getConf().setKeySerializeInfo(keyTable);
      } else if (cRS.getConf().getKeyCols() != null && cRS.getConf().getKeyCols().size() > 0) {
        ArrayList<String> keyColNames = Lists.newArrayList();
        for (ExprNodeDesc keyCol : pRS.getConf().getKeyCols()) {
          String keyColName = keyCol.getExprString();
          keyColNames.add(keyColName);
        }
        List<FieldSchema> fields = PlanUtils.getFieldSchemasFromColumnList(pRS.getConf().getKeyCols(),
            keyColNames, 0, "");
        TableDesc keyTable = PlanUtils.getReduceKeyTableDesc(fields, pRS.getConf().getOrder(),
            pRS.getConf().getNullOrder());
        ArrayList<String> outputKeyCols = Lists.newArrayList();
        for (int i = 0; i < fields.size(); i++) {
          outputKeyCols.add(fields.get(i).getName());
        }
        pRS.getConf().setOutputKeyColumnNames(outputKeyCols);
        pRS.getConf().setKeySerializeInfo(keyTable);
        pRS.getConf().setNumDistributionKeys(cRS.getConf().getNumDistributionKeys());
      }
    }
    return true;
  }
Current RSDedup remove/replace child RS. For key columns,
sorting order, and the number of reducers, copy
more specific part of configurations of child RS to that of parent RS.
For partitioning columns, if both child RS and parent RS have been assigned
partitioning columns, we will choose the more general partitioning columns.
If parent RS has not been assigned any partitioning column, we will use
partitioning columns (if exist) of child RS.
ql/src/java/org/apache/hadoop/hive/ql/optimizer/correlation/ReduceSinkDeDuplicationUtils.java