HHH-17766 Correct return type of by duration and numeric operations on converted attributes

This commit is contained in:
Marco Belladelli 2024-02-21 14:23:17 +01:00
parent c6e41c6f21
commit f87ea083e6
4 changed files with 30 additions and 16 deletions

View File

@ -398,8 +398,8 @@ public class TypecheckUtil {
final SqmExpressible<?> leftNodeType = left.getNodeType();
final SqmExpressible<?> rightNodeType = right.getNodeType();
if ( leftNodeType != null && rightNodeType != null ) {
final Class<?> leftJavaType = leftNodeType.getExpressibleJavaType().getJavaTypeClass();
final Class<?> rightJavaType = rightNodeType.getExpressibleJavaType().getJavaTypeClass();
final Class<?> leftJavaType = leftNodeType.getRelationalJavaType().getJavaTypeClass();
final Class<?> rightJavaType = rightNodeType.getRelationalJavaType().getJavaTypeClass();
if ( Number.class.isAssignableFrom( leftJavaType ) ) {
// left operand is a number
switch (op) {
@ -494,7 +494,7 @@ public class TypecheckUtil {
}
}
private static boolean isNumberArray(SqmExpressible<?> expressible) {
public static boolean isNumberArray(SqmExpressible<?> expressible) {
final DomainType<?> domainType;
if ( expressible != null && ( domainType = expressible.getSqmType() ) != null ) {
return domainType instanceof BasicPluralType<?, ?> && Number.class.isAssignableFrom(

View File

@ -6366,7 +6366,7 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
return new UnaryOperation(
interpret( expression.getOperation() ),
toSqlExpression( expression.getOperand().accept( this ) ),
(BasicValuedMapping) determineValueMapping( expression.getOperand() )
getExpressionType( expression )
);
}
@ -6429,7 +6429,7 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
}
}
private BasicValuedMapping getExpressionType(SqmBinaryArithmetic<?> expression) {
private BasicValuedMapping getExpressionType(SqmExpression<?> expression) {
final SqmExpressible<?> nodeType = expression.getNodeType();
if ( nodeType != null ) {
if ( nodeType instanceof BasicValuedMapping ) {

View File

@ -6,9 +6,10 @@
*/
package org.hibernate.query.sqm.tree.expression;
import org.hibernate.query.sqm.UnaryArithmeticOperator;
import org.hibernate.query.sqm.NodeBuilder;
import org.hibernate.query.sqm.SemanticQueryWalker;
import org.hibernate.query.sqm.SqmExpressible;
import org.hibernate.query.sqm.UnaryArithmeticOperator;
import org.hibernate.query.sqm.tree.SqmCopyContext;
import org.hibernate.query.sqm.tree.select.SqmSelectableNode;
@ -19,10 +20,14 @@ public class SqmUnaryOperation<T> extends AbstractSqmExpression<T> implements Sq
private final UnaryArithmeticOperator operation;
private final SqmExpression<T> operand;
public SqmUnaryOperation(
UnaryArithmeticOperator operation,
SqmExpression<T> operand) {
this( operation, operand, operand.getNodeType() );
public SqmUnaryOperation(UnaryArithmeticOperator operation, SqmExpression<T> operand) {
this(
operation,
operand,
operand.nodeBuilder().getTypeConfiguration().getBasicTypeForJavaType(
operand.getNodeType().getRelationalJavaType().getJavaType()
)
);
}
public SqmUnaryOperation(

View File

@ -80,6 +80,7 @@ import org.hibernate.type.internal.ParameterizedTypeImpl;
import jakarta.persistence.TemporalType;
import static org.hibernate.internal.CoreLogging.messageLogger;
import static org.hibernate.query.sqm.internal.TypecheckUtil.isNumberArray;
/**
* Each instance defines a set of {@linkplain Type types} available in a given
@ -679,16 +680,24 @@ public class TypeConfiguration implements SessionFactoryObserver, Serializable {
return getBasicTypeRegistry().getRegisteredType( Duration.class );
}
if ( secondType == null || firstType != null
&& firstType.getExpressibleJavaType().isWider( secondType.getExpressibleJavaType() ) ) {
return firstType;
if ( firstType != null && ( secondType == null
|| firstType.getRelationalJavaType().isWider( secondType.getRelationalJavaType() ) ) ) {
return resolveBasicArithmeticType( firstType );
}
return secondType;
return secondType != null ? resolveBasicArithmeticType( secondType ) : null;
}
private BasicType<?> resolveBasicArithmeticType(SqmExpressible<?> expressible) {
if ( isNumberArray( expressible ) ) {
return (BasicType<?>) expressible.getSqmType();
}
// Use the relational java type to account for possible converters
return getBasicTypeForJavaType( expressible.getRelationalJavaType().getJavaTypeClass() );
}
private static boolean matchesJavaType(SqmExpressible<?> type, Class<?> javaType) {
assert javaType != null;
return type != null && javaType.isAssignableFrom( type.getExpressibleJavaType().getJavaTypeClass() );
return type != null && javaType.isAssignableFrom( type.getRelationalJavaType().getJavaTypeClass() );
}
@ -778,7 +787,7 @@ public class TypeConfiguration implements SessionFactoryObserver, Serializable {
if ( type == null ) {
return null;
}
return getSqlTemporalType( type.getExpressibleJavaType().getRecommendedJdbcType( getCurrentBaseSqlTypeIndicators() ) );
return getSqlTemporalType( type.getRelationalJavaType().getRecommendedJdbcType( getCurrentBaseSqlTypeIndicators() ) );
}
public static TemporalType getSqlTemporalType(JdbcMapping jdbcMapping) {