Skip to content

Commit ab9e671

Browse files
committed
HHH-18564 Handle attribute converters for query literals
Allow both domain and relational forms when an attribute converter is present
1 parent 6017ae4 commit ab9e671

File tree

1 file changed

+40
-38
lines changed

1 file changed

+40
-38
lines changed

hibernate-core/src/main/java/org/hibernate/query/sqm/sql/BaseSqmToSqlAstConverter.java

Lines changed: 40 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -5629,40 +5629,7 @@ else if ( inferableExpressible instanceof BasicValuedMapping ) {
56295629
final BasicValuedMapping basicValuedMapping = (BasicValuedMapping) inferableExpressible;
56305630
final BasicValueConverter valueConverter = basicValuedMapping.getJdbcMapping().getValueConverter();
56315631
if ( valueConverter != null ) {
5632-
final Object value = literal.getLiteralValue();
5633-
final Object sqlLiteralValue;
5634-
// For converted query literals, we support both, the domain and relational java type
5635-
if ( value == null || valueConverter.getDomainJavaType().isInstance( value ) ) {
5636-
sqlLiteralValue = valueConverter.toRelationalValue( value );
5637-
}
5638-
else if ( valueConverter.getRelationalJavaType().isInstance( value ) ) {
5639-
sqlLiteralValue = value;
5640-
}
5641-
else if ( Character.class.isAssignableFrom( valueConverter.getRelationalJavaType().getJavaTypeClass() )
5642-
&& value instanceof CharSequence && ( (CharSequence) value ).length() == 1 ) {
5643-
sqlLiteralValue = ( (CharSequence) value ).charAt( 0 );
5644-
}
5645-
// In HQL, number literals might not match the relational java type exactly,
5646-
// so we allow coercion between the number types
5647-
else if ( Number.class.isAssignableFrom( valueConverter.getRelationalJavaType().getJavaTypeClass() )
5648-
&& value instanceof Number ) {
5649-
sqlLiteralValue = valueConverter.getRelationalJavaType().coerce(
5650-
value,
5651-
creationContext.getSessionFactory()::getTypeConfiguration
5652-
);
5653-
}
5654-
else {
5655-
throw new SemanticException(
5656-
String.format(
5657-
Locale.ROOT,
5658-
"Literal type '%s' did not match domain type '%s' nor converted type '%s'",
5659-
value.getClass(),
5660-
valueConverter.getDomainJavaType().getJavaTypeClass().getName(),
5661-
valueConverter.getRelationalJavaType().getJavaTypeClass().getName()
5662-
)
5663-
);
5664-
}
5665-
return new QueryLiteral<>( sqlLiteralValue, basicValuedMapping );
5632+
return new QueryLiteral<>( sqlLiteralValue( valueConverter, literal.getLiteralValue() ), basicValuedMapping );
56665633
}
56675634
}
56685635

@@ -5779,6 +5746,40 @@ else if ( expressible instanceof EntityValuedModelPart ) {
57795746
}
57805747
}
57815748

5749+
private <D> Object sqlLiteralValue(BasicValueConverter<D,?> valueConverter, D value) {
5750+
// For converted query literals, we support both, the domain and relational java type
5751+
if ( value == null || valueConverter.getDomainJavaType().isInstance( value ) ) {
5752+
return valueConverter.toRelationalValue( value );
5753+
}
5754+
else if ( valueConverter.getRelationalJavaType().isInstance( value ) ) {
5755+
return value;
5756+
}
5757+
else if ( Character.class.isAssignableFrom( valueConverter.getRelationalJavaType().getJavaTypeClass() )
5758+
&& value instanceof CharSequence && ( (CharSequence) value ).length() == 1 ) {
5759+
return ( (CharSequence) value ).charAt( 0 );
5760+
}
5761+
// In HQL, number literals might not match the relational java type exactly,
5762+
// so we allow coercion between the number types
5763+
else if ( Number.class.isAssignableFrom( valueConverter.getRelationalJavaType().getJavaTypeClass() )
5764+
&& value instanceof Number ) {
5765+
return valueConverter.getRelationalJavaType().coerce(
5766+
value,
5767+
creationContext.getSessionFactory()::getTypeConfiguration
5768+
);
5769+
}
5770+
else {
5771+
throw new SemanticException(
5772+
String.format(
5773+
Locale.ROOT,
5774+
"Literal type '%s' did not match domain type '%s' nor converted type '%s'",
5775+
value.getClass(),
5776+
valueConverter.getDomainJavaType().getJavaTypeClass().getName(),
5777+
valueConverter.getRelationalJavaType().getJavaTypeClass().getName()
5778+
)
5779+
);
5780+
}
5781+
}
5782+
57825783
@Override
57835784
public <N extends Number> Expression visitHqlNumericLiteral(SqmHqlNumericLiteral<N> numericLiteral) {
57845785
final BasicValuedMapping inferredExpressible = (BasicValuedMapping) getInferredValueMapping();
@@ -7362,12 +7363,13 @@ private static <T extends Enum<T>> QueryLiteral<T> queryLiteral(
73627363
);
73637364
}
73647365

7366+
@SuppressWarnings({"unchecked", "rawtypes"})
73657367
@Override
73667368
public Object visitFieldLiteral(SqmFieldLiteral<?> sqmFieldLiteral) {
7367-
return new QueryLiteral<>(
7368-
sqmFieldLiteral.getValue(),
7369-
(BasicValuedMapping) determineValueMapping( sqmFieldLiteral )
7370-
);
7369+
final BasicValuedMapping valueMapping = (BasicValuedMapping) determineValueMapping( sqmFieldLiteral );
7370+
final Object value = sqmFieldLiteral.getValue();
7371+
final BasicValueConverter converter = valueMapping.getJdbcMapping().getValueConverter();
7372+
return new QueryLiteral<>( converter != null ? sqlLiteralValue( converter, value ) : value, valueMapping );
73717373
}
73727374

73737375
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

0 commit comments

Comments
 (0)