public static boolean strictMerge(ReduceSinkOperator cRS, List<ReduceSinkOperator> pRSs)
          throws SemanticException {
    ReduceSinkDesc cRSc = cRS.getConf();
    for (ReduceSinkOperator pRS : pRSs) {
      ReduceSinkDesc pRSc = pRS.getConf();
      if (cRSc.getKeyCols().size() != pRSc.getKeyCols().size()) {
        return false;
      }
      if (cRSc.getPartitionCols().size() != pRSc.getPartitionCols().size()) {
        return false;
      }

      Integer moveRSOrderTo = checkOrder(true, cRSc.getOrder(), pRSc.getOrder(),
              cRSc.getNullOrder(), pRSc.getNullOrder());
      if (moveRSOrderTo == null) {
        return false;
      }

      int cKeySize = cRSc.getKeyCols().size();
      for (int i = 0; i < cKeySize; i++) {
        ExprNodeDesc cExpr = cRSc.getKeyCols().get(i);
        ExprNodeDesc pExpr = pRSc.getKeyCols().get(i);
        if (cExpr instanceof ExprNodeConstantDesc || pExpr instanceof ExprNodeConstantDesc) {
          // If ckeys or pkeys have constant node expressions avoid the merge.
          return false;
        }
        ExprNodeDesc backtrackCExpr = ExprNodeDescUtils.backtrack(cExpr, cRS, pRS);
        if (backtrackCExpr == null || !pExpr.isSame(backtrackCExpr)) {
          return false;
        }
      }

      int cPartSize = cRSc.getPartitionCols().size();
      for (int i = 0; i < cPartSize; i++) {
        ExprNodeDesc cExpr = cRSc.getPartitionCols().get(i);
        ExprNodeDesc pExpr = pRSc.getPartitionCols().get(i);
        if (cExpr instanceof ExprNodeConstantDesc || pExpr instanceof ExprNodeConstantDesc) {
          // If cpartcols or ppartcols have constant node expressions avoid the merge.
          return false;
        }
        ExprNodeDesc backtrackCExpr = ExprNodeDescUtils.backtrack(cExpr, cRS, pRS);
        if (backtrackCExpr == null || !pExpr.isSame(backtrackCExpr)) {
          return false;
        }
      }

      if (cRSc.getBucketCols() != null || pRSc.getBucketCols() != null) {
        if (cRSc.getBucketCols() == null || pRSc.getBucketCols() == null) {
          return false;
        }
        if (cRSc.getBucketCols().size() != pRSc.getBucketCols().size()) {
          return false;
        }
        int cBucketColsSize = cRSc.getBucketCols().size();
        for (int i = 0; i < cBucketColsSize; i++) {
          ExprNodeDesc cExpr = cRSc.getBucketCols().get(i);
          ExprNodeDesc pExpr = pRSc.getBucketCols().get(i);
          if (cExpr instanceof ExprNodeConstantDesc || pExpr instanceof ExprNodeConstantDesc) {
            // If cbucketcols or pbucketcols have constant node expressions avoid the merge.
            return false;
          }
          ExprNodeDesc backtrackCExpr = ExprNodeDescUtils.backtrack(cExpr, cRS, pRS);
          if (backtrackCExpr == null || !pExpr.isSame(backtrackCExpr)) {
            return false;
          }
        }
      }

      // Meets all requirements
      return true;
    }

    // Default
    return false;
  }
This is a more strict version of the merge check, where:
- cRS and pRS should have exactly the same keys in the same positions, and
- cRS and pRS should have exactly the same partition columns in the same positions, and
- cRS and pRS should have exactly the same bucket columns in the same positions, and
- cRS and pRS should sort in the same direction
ql/src/java/org/apache/hadoop/hive/ql/optimizer/correlation/ReduceSinkDeDuplicationUtils.java