public static TypeInfo getCommonClassForUnionAll(TypeInfo a, TypeInfo b) {
    if (a.equals(b)) {
      return a;
    }
    if (a.getCategory() != Category.PRIMITIVE || b.getCategory() != Category.PRIMITIVE) {
      return null;
    }
    PrimitiveCategory pcA = ((PrimitiveTypeInfo)a).getPrimitiveCategory();
    PrimitiveCategory pcB = ((PrimitiveTypeInfo)b).getPrimitiveCategory();

    if (pcA == pcB) {
      // Same primitive category but different qualifiers.
      return getTypeInfoForPrimitiveCategory((PrimitiveTypeInfo)a, (PrimitiveTypeInfo)b, pcA);
    }

    PrimitiveGrouping pgA = PrimitiveObjectInspectorUtils.getPrimitiveGrouping(pcA);
    PrimitiveGrouping pgB = PrimitiveObjectInspectorUtils.getPrimitiveGrouping(pcB);

    // untyped nulls
    if (pgA == PrimitiveGrouping.VOID_GROUP) {
      return b;
    }
    if (pgB == PrimitiveGrouping.VOID_GROUP) {
      return a;
    }

    if (pgA != pgB) {
      return null;
    }

    switch(pgA) {
    case STRING_GROUP:
      return getTypeInfoForPrimitiveCategory(
          (PrimitiveTypeInfo)a, (PrimitiveTypeInfo)b,PrimitiveCategory.STRING);
    case NUMERIC_GROUP:
      return TypeInfoUtils.implicitConvertible(a, b) ? b : a;
    case DATE_GROUP:
      return TypeInfoFactory.timestampTypeInfo;
    default:
      return null;
    }
  }
Find a common type for union-all operator. Only the common types for the same
type group will resolve to a common type. No implicit conversion across different
type groups will be done.
ql/src/java/org/apache/hadoop/hive/ql/exec/FunctionRegistry.java