private Operator<? extends OperatorDesc> genInputSelectForUnion(
      Operator<? extends OperatorDesc> origInputOp, Map<String, ColumnInfo> origInputFieldMap,
      String origInputAlias, RowResolver unionoutRR, String unionalias)
      throws SemanticException {

    Map<String, ColumnInfo> fieldMap = unionoutRR.getFieldMap(unionalias);

    Iterator<ColumnInfo> oIter = origInputFieldMap.values().iterator();
    Iterator<ColumnInfo> uIter = fieldMap.values().iterator();

    List<ExprNodeDesc> columns = new ArrayList<>();
    boolean needsCast = false;
    while (oIter.hasNext()) {
      ColumnInfo oInfo = oIter.next();
      ColumnInfo uInfo = uIter.next();
      ExprNodeDesc column = new ExprNodeColumnDesc(oInfo.getType(), oInfo.getInternalName(),
          oInfo.getTabAlias(), oInfo.getIsVirtualCol(), oInfo.isSkewedCol());
      if (!oInfo.getType().equals(uInfo.getType())) {
        needsCast = true;
        column = ExprNodeTypeCheck.getExprNodeDefaultExprProcessor()
            .createConversionCast(column, (PrimitiveTypeInfo)uInfo.getType());
      }
      columns.add(column);
    }

    // If none of the columns need to be cast there's no need for an additional select operator
    if (!needsCast) {
      return origInputOp;
    }

    RowResolver rowResolver = new RowResolver();
    Map<String, ExprNodeDesc> columnExprMap = new HashMap<String, ExprNodeDesc>();

    List<String> colName = new ArrayList<String>();
    for (int i = 0; i < columns.size(); i++) {
      String name = getColumnInternalName(i);
      ColumnInfo col = new ColumnInfo(name, columns.get(i)
          .getTypeInfo(), "", false);
      rowResolver.put(origInputAlias, name, col);
      colName.add(name);
      columnExprMap.put(name, columns.get(i));
    }

    Operator<SelectDesc> newInputOp = OperatorFactory.getAndMakeChild(
        new SelectDesc(columns, colName), new RowSchema(rowResolver.getColumnInfos()),
        columnExprMap, origInputOp);
    return putOpInsertMap(newInputOp, rowResolver);
  }
Generates a select operator which can go between the original input operator and the union
operator. This select casts columns to match the type of the associated column in the union,
other columns pass through unchanged. The new operator's only parent is the original input
operator to the union, and it's only child is the union. If the input does not need to be
cast, the original operator is returned, and no new select operator is added.

@param origInputOp
         The original input operator to the union.
@param origInputFieldMap
         A map from field name to ColumnInfo for the original input operator.
@param origInputAlias
         The alias associated with the original input operator.
@param unionoutRR
         The union's output row resolver.
@param unionalias
         The alias of the union.
@return
@throws SemanticException
ql/src/java/org/apache/hadoop/hive/ql/parse/SemanticAnalyzer.java