HHH-17454 Correct type checking with concrete generic types

This commit is contained in:
Marco Belladelli 2023-11-21 14:24:45 +01:00
parent b3b0a8daf4
commit c6bc135b2d
3 changed files with 22 additions and 14 deletions

View File

@ -7,13 +7,13 @@
package org.hibernate.query.sqm.internal; package org.hibernate.query.sqm.internal;
import jakarta.persistence.criteria.Expression; import jakarta.persistence.criteria.Expression;
import jakarta.persistence.metamodel.EmbeddableType;
import jakarta.persistence.metamodel.EntityType; import jakarta.persistence.metamodel.EntityType;
import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.metamodel.mapping.JdbcMapping; import org.hibernate.metamodel.mapping.JdbcMapping;
import org.hibernate.metamodel.model.domain.DomainType; import org.hibernate.metamodel.model.domain.DomainType;
import org.hibernate.metamodel.model.domain.TupleType; import org.hibernate.metamodel.model.domain.TupleType;
import org.hibernate.metamodel.model.domain.internal.DiscriminatorSqmPathSource; import org.hibernate.metamodel.model.domain.internal.DiscriminatorSqmPathSource;
import org.hibernate.metamodel.model.domain.internal.EmbeddedSqmPathSource;
import org.hibernate.persister.entity.EntityPersister; import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.query.SemanticException; import org.hibernate.query.SemanticException;
import org.hibernate.query.sqm.BinaryArithmeticOperator; import org.hibernate.query.sqm.BinaryArithmeticOperator;
@ -119,10 +119,10 @@ public class TypecheckUtil {
// for embeddables, the embeddable class must match exactly // for embeddables, the embeddable class must match exactly
if ( lhsType instanceof EmbeddedSqmPathSource && rhsType instanceof EmbeddedSqmPathSource ) { if ( lhsType instanceof EmbeddableType<?> && rhsType instanceof EmbeddableType<?> ) {
return areEmbeddableTypesComparable( return areEmbeddableTypesComparable(
(EmbeddedSqmPathSource<?>) lhsType, (EmbeddableType<?>) lhsType,
(EmbeddedSqmPathSource<?>) rhsType (EmbeddableType<?>) rhsType
); );
} }
@ -134,8 +134,8 @@ public class TypecheckUtil {
// allow comparing an embeddable against a tuple literal // allow comparing an embeddable against a tuple literal
if ( lhsType instanceof EmbeddedSqmPathSource<?> && rhsType instanceof TupleType if ( lhsType instanceof EmbeddableType<?> && rhsType instanceof TupleType
|| rhsType instanceof EmbeddedSqmPathSource<?> && lhsType instanceof TupleType ) { || rhsType instanceof EmbeddableType<?> && lhsType instanceof TupleType ) {
// TODO: do something meaningful here // TODO: do something meaningful here
return true; return true;
} }
@ -192,10 +192,10 @@ public class TypecheckUtil {
} }
private static boolean areEmbeddableTypesComparable( private static boolean areEmbeddableTypesComparable(
EmbeddedSqmPathSource<?> lhsType, EmbeddableType<?> lhsType,
EmbeddedSqmPathSource<?> rhsType) { EmbeddableType<?> rhsType) {
// no polymorphism for embeddable types // no polymorphism for embeddable types
return rhsType.getNodeJavaType() == lhsType.getNodeJavaType(); return rhsType.getJavaType() == lhsType.getJavaType();
} }
private static boolean areTupleTypesComparable( private static boolean areTupleTypesComparable(
@ -340,9 +340,9 @@ public class TypecheckUtil {
} }
// allow comparing literal null to things // allow comparing literal null to things
if ( !(left instanceof SqmLiteralNull) && !(right instanceof SqmLiteralNull) ) { if ( !( left instanceof SqmLiteralNull ) && !( right instanceof SqmLiteralNull ) ) {
final SqmExpressible<?> leftType = left.getNodeType(); final SqmExpressible<?> leftType = getNodeType( left );
final SqmExpressible<?> rightType = right.getNodeType(); final SqmExpressible<?> rightType = getNodeType( right );
if ( !areTypesComparable( leftType, rightType, factory ) ) { if ( !areTypesComparable( leftType, rightType, factory ) ) {
throw new SemanticException( throw new SemanticException(
String.format( String.format(
@ -355,6 +355,12 @@ public class TypecheckUtil {
} }
} }
private static SqmExpressible<?> getNodeType(SqmExpression<?> expression) {
return expression instanceof SqmPath<?> ?
( (SqmPath<?>) expression ).getResolvedModel().getSqmType() :
expression.getNodeType();
}
/** /**
* @see TypecheckUtil#assertComparable(Expression, Expression, SessionFactoryImplementor) * @see TypecheckUtil#assertComparable(Expression, Expression, SessionFactoryImplementor)
*/ */

View File

@ -132,7 +132,8 @@ public class SqmBasicValuedSimplePath<T>
@Override @Override
public DomainType<T> getSqmType() { public DomainType<T> getSqmType() {
return getNodeType().getSqmType(); //noinspection unchecked
return (DomainType<T>) getResolvedModel().getSqmType();
} }

View File

@ -77,7 +77,8 @@ public class SqmEmbeddedValuedSimplePath<T>
@Override @Override
public DomainType<T> getSqmType() { public DomainType<T> getSqmType() {
return getReferencedPathSource().getSqmType(); //noinspection unchecked
return (DomainType<T>) getResolvedModel().getSqmType();
} }
@Override @Override