Skip to content

Commit 3d640c0

Browse files
committed
HHH-18400 Account for converters applied to comparison operands
1 parent 07e81e4 commit 3d640c0

File tree

1 file changed

+42
-8
lines changed

1 file changed

+42
-8
lines changed

hibernate-core/src/main/java/org/hibernate/query/sqm/internal/TypecheckUtil.java

Lines changed: 42 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
import org.hibernate.type.BasicPluralType;
3030
import org.hibernate.type.BasicType;
3131
import org.hibernate.type.QueryParameterJavaObjectType;
32+
import org.hibernate.type.descriptor.converter.spi.BasicValueConverter;
3233
import org.hibernate.type.descriptor.jdbc.JdbcType;
3334

3435
import java.time.temporal.Temporal;
@@ -172,14 +173,7 @@ public static boolean areTypesComparable(
172173
// enums, user-defined types, etc.
173174

174175
if ( lhsDomainType instanceof JdbcMapping && rhsDomainType instanceof JdbcMapping ) {
175-
JdbcType lhsJdbcType = ((JdbcMapping) lhsDomainType).getJdbcType();
176-
JdbcType rhsJdbcType = ((JdbcMapping) rhsDomainType).getJdbcType();
177-
if ( lhsJdbcType.getJdbcTypeCode() == rhsJdbcType.getJdbcTypeCode()
178-
// "families" of implicitly-convertible JDBC types
179-
// (this list might need to be extended in future)
180-
|| lhsJdbcType.isStringLike() && rhsJdbcType.isStringLike()
181-
|| lhsJdbcType.isTemporal() && rhsJdbcType.isTemporal()
182-
|| lhsJdbcType.isNumber() && rhsJdbcType.isNumber() ) {
176+
if ( areJdbcMappingsComparable( (JdbcMapping) lhsDomainType, (JdbcMapping) rhsDomainType, factory ) ) {
183177
return true;
184178
}
185179
}
@@ -198,6 +192,46 @@ public static boolean areTypesComparable(
198192
return false;
199193
}
200194

195+
private static boolean areJdbcMappingsComparable(
196+
JdbcMapping lhsJdbcMapping,
197+
JdbcMapping rhsJdbcMapping,
198+
SessionFactoryImplementor factory) {
199+
if ( areJdbcTypesComparable( lhsJdbcMapping.getJdbcType(), rhsJdbcMapping.getJdbcType() ) ) {
200+
return true;
201+
}
202+
// converters are implicitly applied to the other side when its domain type is compatible
203+
else if ( lhsJdbcMapping.getValueConverter() != null || rhsJdbcMapping.getValueConverter() != null ) {
204+
final JdbcMapping lhsDomainMapping = getDomainJdbcType( lhsJdbcMapping, factory );
205+
final JdbcMapping rhsDomainMapping = getDomainJdbcType( rhsJdbcMapping, factory );
206+
return lhsDomainMapping != null && rhsDomainMapping != null && areJdbcTypesComparable(
207+
lhsDomainMapping.getJdbcType(),
208+
rhsDomainMapping.getJdbcType()
209+
);
210+
}
211+
return false;
212+
}
213+
214+
private static boolean areJdbcTypesComparable(JdbcType lhsJdbcType, JdbcType rhsJdbcType) {
215+
return lhsJdbcType.getJdbcTypeCode() == rhsJdbcType.getJdbcTypeCode()
216+
// "families" of implicitly-convertible JDBC types
217+
// (this list might need to be extended in future)
218+
|| lhsJdbcType.isStringLike() && rhsJdbcType.isStringLike()
219+
|| lhsJdbcType.isTemporal() && rhsJdbcType.isTemporal()
220+
|| lhsJdbcType.isNumber() && rhsJdbcType.isNumber();
221+
}
222+
223+
private static JdbcMapping getDomainJdbcType(JdbcMapping jdbcMapping, SessionFactoryImplementor factory) {
224+
if ( jdbcMapping.getValueConverter() != null ) {
225+
final BasicType<?> basicType = factory.getTypeConfiguration().getBasicTypeForJavaType(
226+
jdbcMapping.getValueConverter().getDomainJavaType().getJavaType()
227+
);
228+
if ( basicType != null ) {
229+
return basicType.getJdbcMapping();
230+
}
231+
}
232+
return jdbcMapping;
233+
}
234+
201235
private static EmbeddableDomainType<?> getEmbeddableType(SqmExpressible<?> expressible) {
202236
return expressible instanceof EmbeddableDomainType<?> ? (EmbeddableDomainType<?>) expressible : null;
203237
}

0 commit comments

Comments
 (0)