private List<ExprNodeDesc> getReduceKeysForReduceSink(List<ASTNode> grpByExprs,
                                                             RowResolver reduceSinkInputRowResolver, RowResolver reduceSinkOutputRowResolver,
                                                             List<String> outputKeyColumnNames, Map<String, ExprNodeDesc> colExprMap)
      throws SemanticException {

    List<ExprNodeDesc> reduceKeys = new ArrayList<ExprNodeDesc>();

    for (ASTNode grpbyExpr : grpByExprs) {
      ExprNodeDesc inputExpr = genExprNodeDesc(grpbyExpr,
          reduceSinkInputRowResolver);
      ColumnInfo prev = reduceSinkOutputRowResolver.getExpression(grpbyExpr);
      if (prev != null && isConsistentWithinQuery(inputExpr)) {
        colExprMap.put(prev.getInternalName(), inputExpr);
        continue;
      }
      reduceKeys.add(inputExpr);
      outputKeyColumnNames.add(getColumnInternalName(reduceKeys.size() - 1));
      String field = ReduceField.KEY.toString() + "."
          + getColumnInternalName(reduceKeys.size() - 1);
      ColumnInfo colInfo = new ColumnInfo(field, reduceKeys.get(
          reduceKeys.size() - 1).getTypeInfo(), null, false);
      reduceSinkOutputRowResolver.putExpression(grpbyExpr, colInfo);
      colExprMap.put(colInfo.getInternalName(), inputExpr);
    }

    return reduceKeys;
  }
Generate the ReduceSinkOperator for the Group By Query Block
(qb.getPartInfo().getXXX(dest)). The new ReduceSinkOperator will be a child
of inputOperatorInfo.

It will put all Group By keys and the distinct field (if any) in the
map-reduce sort key, and all other fields in the map-reduce value.

@param numPartitionFields
         the number of fields for map-reduce partitioning. This is usually
         the number of fields in the Group By keys.
@return the new ReduceSinkOperator.
@throws SemanticException
ql/src/java/org/apache/hadoop/hive/ql/parse/SemanticAnalyzer.java