diff --git a/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/expression/Compatibility.java b/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/expression/Compatibility.java index 6e74a5953c..365e69d5ca 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/expression/Compatibility.java +++ b/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/expression/Compatibility.java @@ -102,14 +102,14 @@ public class Compatibility { } else if ( isIntegralTypePrimitive( to ) ) { return from == byte.class - || isIntegralTypePrimitive( from ) + || isCompatibleIntegralTypePrimitive( to, from ) // this would for sure cause loss of precision || isFloatingTypePrimitive( from ); } else if ( isFloatingTypePrimitive( to ) ) { return from == byte.class || isIntegralTypePrimitive( from ) - || isFloatingTypePrimitive( from ); + || isCompatibleFloatingTypePrimitive( to, from ); } return false; @@ -133,6 +133,22 @@ public class Compatibility { || potentialIntegral == long.class; } + private static boolean isCompatibleIntegralTypePrimitive(Class to, Class from) { + assert isIntegralTypePrimitive( to ); + assert from.isPrimitive(); + + if ( to == short.class ) { + return from == short.class; + } + else if ( to == int.class ) { + return from == short.class + || from == int.class; + } + else { + return isIntegralTypePrimitive( from ); + } + } + public static boolean isFloatingType(Class potentialFloating) { if ( potentialFloating.isPrimitive() ) { return isFloatingTypePrimitive( potentialFloating ); @@ -150,6 +166,18 @@ public class Compatibility { || potentialFloating == double.class; } + private static boolean isCompatibleFloatingTypePrimitive(Class to, Class from) { + assert isFloatingTypePrimitive( to ); + assert from.isPrimitive(); + + if ( to == float.class ) { + return from == float.class; + } + else { + return isFloatingTypePrimitive( from ); + } + } + public static boolean areAssignmentCompatible( JavaType to, JavaType from) {