private static ExprNodeConstantDesc typeCast(ExprNodeDesc desc, TypeInfo ti, boolean performSafeTypeCast) {
    if (desc instanceof ExprNodeConstantDesc && null == ((ExprNodeConstantDesc)desc).getValue()) {
      return null;
    }
    if (!(ti instanceof PrimitiveTypeInfo) || !(desc.getTypeInfo() instanceof PrimitiveTypeInfo)) {
      return null;
    }

    PrimitiveTypeInfo priti = (PrimitiveTypeInfo) ti;
    PrimitiveTypeInfo descti = (PrimitiveTypeInfo) desc.getTypeInfo();


    if (unSupportedTypes.contains(priti.getPrimitiveCategory())
        || unSupportedTypes.contains(descti.getPrimitiveCategory())) {
      // FIXME: support template types. It currently has conflict with ExprNodeConstantDesc
      LOG.debug("Unsupported types {}; {}", priti, descti);
      return null;
    }

    // We shouldn't cast strings to other types because that can break original data in cases of
    // leading zeros or zeros trailing after decimal point.
    // Example: "000126" => 126 => "126"
    boolean brokenDataTypesCombination = unsafeConversionTypes.contains(priti.getPrimitiveCategory())
        && !unsafeConversionTypes.contains(descti.getPrimitiveCategory())
        || priti.getPrimitiveCategory() == PrimitiveCategory.TIMESTAMP && descti.getPrimitiveCategory() == PrimitiveCategory.DATE;
    if (performSafeTypeCast && brokenDataTypesCombination) {
      LOG.debug("Unsupported cast {}; {}", priti, descti);
      return null;
    }

    LOG.debug("Casting {} to type {}", desc, ti);
    ExprNodeConstantDesc c = (ExprNodeConstantDesc) desc;
    if (null != c.getFoldedFromVal() && priti.getTypeName().equals(serdeConstants.STRING_TYPE_NAME)) {
      // avoid double casting to preserve original string representation of constant.
      return new ExprNodeConstantDesc(c.getFoldedFromVal());
    }
    ObjectInspector origOI =
        TypeInfoUtils.getStandardJavaObjectInspectorFromTypeInfo(desc.getTypeInfo());
    ObjectInspector oi =
        TypeInfoUtils.getStandardJavaObjectInspectorFromTypeInfo(ti);
    Converter converter = ObjectInspectorConverters.getConverter(origOI, oi);
    Object convObj = converter.convert(c.getValue());

    // Convert integer related types because converters are not sufficient
    if (convObj instanceof Integer) {
      switch (priti.getPrimitiveCategory()) {
      case BYTE:
        convObj = Byte.valueOf((((Integer) convObj).byteValue()));
        break;
      case SHORT:
        convObj = Short.valueOf(((Integer) convObj).shortValue());
        break;
      case LONG:
        convObj = Long.valueOf(((Integer) convObj).intValue());
      default:
      }
    }
    return new ExprNodeConstantDesc(ti, convObj);
  }
Cast type from expression type to expected type ti.

@param desc constant expression
@param ti expected type info
@param performSafeTypeCast when true then don't perform typecast because it could be unsafe (loosing leading zeroes etc.)
@return cast constant, or null if the type cast failed.
ql/src/java/org/apache/hadoop/hive/ql/optimizer/ConstantPropagateProcFactory.java