public static ExprNodeDesc flattenExpr(ExprNodeDesc source) {
    if (source instanceof ExprNodeGenericFuncDesc) {
      // all children expression should be resolved
      ExprNodeGenericFuncDesc function = (ExprNodeGenericFuncDesc) source.clone();
      List<ExprNodeDesc> newChildren = flattenExprList(function.getChildren());
      for (ExprNodeDesc newChild : newChildren) {
        if (newChild == null) {
          // Could not resolve all of the function children, fail
          return null;
        }
      }
      function.setChildren(newChildren);
      return function;
    }
    if (source instanceof ExprNodeColumnDesc) {
      ExprNodeColumnDesc column = (ExprNodeColumnDesc) source;
      // Create a new ColumnInfo, replacing STRUCT.COLUMN with STRUCT_COLUMN
      String newColumn = column.getColumn().replace('.', '_');
      return new ExprNodeColumnDesc(source.getTypeInfo(), newColumn, column.getTabAlias(), false);
    }
    if (source instanceof ExprNodeFieldDesc) {
      // field expression should be resolved
      ExprNodeFieldDesc field = (ExprNodeFieldDesc) source.clone();
      ExprNodeDesc fieldDesc = flattenExpr(field.getDesc());
      if (fieldDesc == null) {
        return null;
      }
      field.setDesc(fieldDesc);
      return field;
    }
    // constant or null expr, just return
    return source;
  }
A normal reduce operator's rowObjectInspector looks like a struct containing
 nested key/value structs that contain the column values:
 { key: { reducesinkkey0:int }, value: { _col0:int, _col1:int, .. } }

While the rowObjectInspector looks the same for vectorized queries during
compilation time, within the tasks at query execution the rowObjectInspector
has changed to a flatter structure without nested key/value structs:
 { 'key.reducesinkkey0':int, 'value._col0':int, 'value._col1':int, .. }

Trying to fetch 'key.reducesinkkey0' by name from the list of flattened
ObjectInspectors does not work because the '.' gets interpreted as a field member,
even though it is a flattened list of column values.
This workaround converts the column name referenced in the ExprNodeDesc
from a nested field name (key.reducesinkkey0) to key_reducesinkkey0,
simply by replacing '.' with '_'.
@param source
@return
ql/src/java/org/apache/hadoop/hive/ql/plan/ExprNodeDescUtils.java