From b82fa307ea351d8f81398279f4e9b2a9e67efabb Mon Sep 17 00:00:00 2001 From: Christian Beikov Date: Fri, 3 Mar 2023 12:08:56 +0100 Subject: [PATCH] HHH-15802 - Fix some expression comparison type checks --- .../org/hibernate/userguide/hql/HQLTest.java | 2 +- .../mapping/basic/InstantLiteralTest.java | 2 +- .../internal/InferredBasicValueResolver.java | 9 ++- .../domain/PluralPersistentAttribute.java | 5 -- .../metamodel/model/domain/TupleType.java | 5 -- .../internal/DiscriminatorSqmPathSource.java | 5 -- .../hql/internal/SemanticQueryBuilder.java | 12 +-- .../query/internal/BindingTypeHelper.java | 5 +- .../internal/QueryParameterBindingImpl.java | 3 +- .../hibernate/query/sqm/SqmExpressible.java | 4 - .../sqm/internal/SqmCriteriaNodeBuilder.java | 81 ++++++++++++------- .../sqm/sql/BaseSqmToSqlAstConverter.java | 3 +- .../AbstractSqmSpecificPluralPartPath.java | 10 ++- .../domain/SqmElementAggregateFunction.java | 8 +- .../domain/SqmIndexAggregateFunction.java | 27 +------ .../tree/expression/SqmExpressionHelper.java | 3 +- .../descriptor/java/CurrencyJavaType.java | 1 + .../type/descriptor/java/EnumJavaType.java | 1 + .../type/descriptor/java/JavaType.java | 9 --- .../type/descriptor/java/JavaTypeHelper.java | 9 +++ .../java/spi/UnknownBasicJavaType.java | 7 +- .../type/format/jaxb/JaxbXmlFormatMapper.java | 6 +- 22 files changed, 102 insertions(+), 115 deletions(-) diff --git a/documentation/src/test/java/org/hibernate/userguide/hql/HQLTest.java b/documentation/src/test/java/org/hibernate/userguide/hql/HQLTest.java index 8f71da7f3b..4e2436c627 100644 --- a/documentation/src/test/java/org/hibernate/userguide/hql/HQLTest.java +++ b/documentation/src/test/java/org/hibernate/userguide/hql/HQLTest.java @@ -2443,7 +2443,7 @@ public class HQLTest extends BaseEntityManagerFunctionalTestCase { List persons = entityManager.createQuery( "select p " + "from Person p " + - "where p.createdOn > '1950-01-01' ", + "where p.createdOn > date 1950-01-01 ", Person.class) .getResultList(); //end::hql-relational-comparisons-example[] diff --git a/documentation/src/test/java/org/hibernate/userguide/mapping/basic/InstantLiteralTest.java b/documentation/src/test/java/org/hibernate/userguide/mapping/basic/InstantLiteralTest.java index e42e525f4f..44704c6319 100644 --- a/documentation/src/test/java/org/hibernate/userguide/mapping/basic/InstantLiteralTest.java +++ b/documentation/src/test/java/org/hibernate/userguide/mapping/basic/InstantLiteralTest.java @@ -51,7 +51,7 @@ public class InstantLiteralTest extends BaseEntityManagerFunctionalTestCase { .createQuery( "select de " + "from DateEvent de " + - "where de.createdOn = '2016-10-13T06:40:18.745Z' ", DateEvent.class) + "where de.createdOn = zoned datetime 2016-10-13 06:40:18.745Z ", DateEvent.class) .getSingleResult(); assertNotNull(dateEvent); diff --git a/hibernate-core/src/main/java/org/hibernate/boot/model/process/internal/InferredBasicValueResolver.java b/hibernate-core/src/main/java/org/hibernate/boot/model/process/internal/InferredBasicValueResolver.java index 777d144aea..0935accf8c 100644 --- a/hibernate-core/src/main/java/org/hibernate/boot/model/process/internal/InferredBasicValueResolver.java +++ b/hibernate-core/src/main/java/org/hibernate/boot/model/process/internal/InferredBasicValueResolver.java @@ -29,6 +29,7 @@ import org.hibernate.type.descriptor.java.BasicPluralJavaType; import org.hibernate.type.descriptor.java.EnumJavaType; import org.hibernate.type.descriptor.java.ImmutableMutabilityPlan; import org.hibernate.type.descriptor.java.JavaType; +import org.hibernate.type.descriptor.java.JavaTypeHelper; import org.hibernate.type.descriptor.java.MutabilityPlan; import org.hibernate.type.descriptor.java.SerializableJavaType; import org.hibernate.type.descriptor.java.TemporalJavaType; @@ -81,7 +82,7 @@ public class InferredBasicValueResolver { typeConfiguration ); } - else if ( explicitJavaType.isTemporalType() ) { + else if ( JavaTypeHelper.isTemporal( explicitJavaType ) ) { return fromTemporal( (TemporalJavaType) explicitJavaType, null, @@ -133,7 +134,7 @@ public class InferredBasicValueResolver { typeConfiguration ); } - else if ( reflectedJtd.isTemporalType() ) { + else if ( JavaTypeHelper.isTemporal( reflectedJtd ) ) { return fromTemporal( (TemporalJavaType) reflectedJtd, null, @@ -170,7 +171,7 @@ public class InferredBasicValueResolver { ); registeredElementType = resolution.getLegacyResolvedBasicType(); } - else if ( elementJtd.isTemporalType() ) { + else if ( JavaTypeHelper.isTemporal( elementJtd ) ) { final InferredBasicValueResolution resolution = InferredBasicValueResolver.fromTemporal( (TemporalJavaType) elementJtd, null, @@ -492,7 +493,7 @@ public class InferredBasicValueResolver { // Case #1 - explicit JavaType if ( explicitJavaType != null ) { - if ( !explicitJavaType.isTemporalType() ) { + if ( !JavaTypeHelper.isTemporal( explicitJavaType ) ) { throw new MappingException( "Explicit JavaType [" + explicitJavaType + "] defined for temporal value must implement TemporalJavaType" diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/PluralPersistentAttribute.java b/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/PluralPersistentAttribute.java index 2284b0374e..ddfacb9df5 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/PluralPersistentAttribute.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/PluralPersistentAttribute.java @@ -47,9 +47,4 @@ public interface PluralPersistentAttribute "Plural attribute [" + getPathName() + "] is not indexed (list / map)" ); } - - @Override - default boolean checkTypeComparability() { - return false; - } } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/TupleType.java b/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/TupleType.java index 99ac309f2d..7fd1e46ca1 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/TupleType.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/TupleType.java @@ -27,9 +27,4 @@ public interface TupleType extends SqmExpressible { SqmExpressible get(int index); SqmExpressible get(String componentName); - - @Override - default boolean checkTypeComparability() { - return false; - } } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/DiscriminatorSqmPathSource.java b/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/DiscriminatorSqmPathSource.java index 1128b5100e..ed14ee79ff 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/DiscriminatorSqmPathSource.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/DiscriminatorSqmPathSource.java @@ -60,9 +60,4 @@ public class DiscriminatorSqmPathSource extends AbstractSqmPathSource public Class getJavaType() { return getExpressibleJavaType().getJavaTypeClass(); } - - @Override - public boolean checkTypeComparability() { - return false; - } } diff --git a/hibernate-core/src/main/java/org/hibernate/query/hql/internal/SemanticQueryBuilder.java b/hibernate-core/src/main/java/org/hibernate/query/hql/internal/SemanticQueryBuilder.java index c586dbb9ee..4d0c1e587a 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/hql/internal/SemanticQueryBuilder.java +++ b/hibernate-core/src/main/java/org/hibernate/query/hql/internal/SemanticQueryBuilder.java @@ -2464,7 +2464,7 @@ public class SemanticQueryBuilder extends HqlParserBaseVisitor implem break; } } - ((SqmCriteriaNodeBuilder) creationContext.getNodeBuilder()).assertComparable( left, right ); + ( (SqmCriteriaNodeBuilder) creationContext.getNodeBuilder() ).assertComparable( left, right ); return new SqmComparisonPredicate( left, comparisonOperator, @@ -3485,9 +3485,10 @@ public class SemanticQueryBuilder extends HqlParserBaseVisitor implem private static LocalTime localTime(HqlParser.TimeContext ctx) { final int hour = Integer.parseInt( ctx.hour().getText() ); final int minute = Integer.parseInt( ctx.minute().getText() ); - if ( ctx.second() != null ) { - final String secondText = ctx.second().getText(); - final int index = secondText.indexOf( '.'); + final HqlParser.SecondContext secondContext = ctx.second(); + if ( secondContext != null ) { + final String secondText = secondContext.getText(); + final int index = secondText.indexOf( '.' ); if ( index < 0 ) { return LocalTime.of( hour, @@ -3496,11 +3497,12 @@ public class SemanticQueryBuilder extends HqlParserBaseVisitor implem ); } else { + final String secondFractions = secondText.substring( index + 1 ); return LocalTime.of( hour, minute, Integer.parseInt( secondText.substring( 0, index ) ), - Integer.parseInt( secondText.substring( index + 1 ) ) + Integer.parseInt( secondFractions ) * (int) Math.pow( 10, 9 - secondFractions.length() ) ); } } diff --git a/hibernate-core/src/main/java/org/hibernate/query/internal/BindingTypeHelper.java b/hibernate-core/src/main/java/org/hibernate/query/internal/BindingTypeHelper.java index 5e07198eb8..fcc45471dc 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/internal/BindingTypeHelper.java +++ b/hibernate-core/src/main/java/org/hibernate/query/internal/BindingTypeHelper.java @@ -18,6 +18,7 @@ import org.hibernate.metamodel.mapping.JdbcMapping; import org.hibernate.query.BindableType; import org.hibernate.query.sqm.SqmExpressible; import org.hibernate.type.StandardBasicTypes; +import org.hibernate.type.descriptor.java.JavaTypeHelper; import org.hibernate.type.descriptor.java.TemporalJavaType; import org.hibernate.type.spi.TypeConfiguration; @@ -41,7 +42,7 @@ public class BindingTypeHelper { SessionFactoryImplementor sessionFactory) { if ( precision != null ) { final SqmExpressible sqmExpressible = declaredParameterType.resolveExpressible( sessionFactory ); - if ( !( sqmExpressible.getExpressibleJavaType().isTemporalType() ) ) { + if ( !( JavaTypeHelper.isTemporal( sqmExpressible.getExpressibleJavaType() ) ) ) { throw new UnsupportedOperationException( "Cannot treat non-temporal parameter type with temporal precision" ); @@ -64,7 +65,7 @@ public class BindingTypeHelper { Object value, JdbcMapping baseType, TypeConfiguration typeConfiguration) { - if ( value == null || !baseType.getJdbcJavaType().isTemporalType() ) { + if ( value == null || !JavaTypeHelper.isTemporal( baseType.getJdbcJavaType() ) ) { return baseType; } diff --git a/hibernate-core/src/main/java/org/hibernate/query/internal/QueryParameterBindingImpl.java b/hibernate-core/src/main/java/org/hibernate/query/internal/QueryParameterBindingImpl.java index fbae9418b7..b47310a61f 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/internal/QueryParameterBindingImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/query/internal/QueryParameterBindingImpl.java @@ -21,6 +21,7 @@ import org.hibernate.query.spi.QueryParameterBindingValidator; import org.hibernate.query.sqm.SqmExpressible; import org.hibernate.type.descriptor.java.CoercionException; import org.hibernate.type.descriptor.java.JavaType; +import org.hibernate.type.descriptor.java.JavaTypeHelper; import org.hibernate.type.descriptor.java.TemporalJavaType; import org.hibernate.type.spi.TypeConfiguration; @@ -290,7 +291,7 @@ public class QueryParameterBindingImpl implements QueryParameterBinding, J } private void setExplicitTemporalPrecision(TemporalType temporalTypePrecision) { - if ( bindType == null || determineJavaType( bindType ).isTemporalType() ) { + if ( bindType == null || JavaTypeHelper.isTemporal( determineJavaType( bindType ) ) ) { this.bindType = BindingTypeHelper.INSTANCE.resolveTemporalPrecision( temporalTypePrecision, bindType, diff --git a/hibernate-core/src/main/java/org/hibernate/query/sqm/SqmExpressible.java b/hibernate-core/src/main/java/org/hibernate/query/sqm/SqmExpressible.java index c944027a1d..3070540d9c 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/sqm/SqmExpressible.java +++ b/hibernate-core/src/main/java/org/hibernate/query/sqm/SqmExpressible.java @@ -34,8 +34,4 @@ public interface SqmExpressible extends BindableType { default SqmExpressible resolveExpressible(SessionFactoryImplementor sessionFactory) { return this; } - - default boolean checkTypeComparability(){ - return true; - } } diff --git a/hibernate-core/src/main/java/org/hibernate/query/sqm/internal/SqmCriteriaNodeBuilder.java b/hibernate-core/src/main/java/org/hibernate/query/sqm/internal/SqmCriteriaNodeBuilder.java index 2897561387..39995d76a8 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/sqm/internal/SqmCriteriaNodeBuilder.java +++ b/hibernate-core/src/main/java/org/hibernate/query/sqm/internal/SqmCriteriaNodeBuilder.java @@ -45,6 +45,7 @@ import org.hibernate.metamodel.model.domain.JpaMetamodel; import org.hibernate.metamodel.model.domain.PluralPersistentAttribute; import org.hibernate.metamodel.model.domain.TupleType; import org.hibernate.metamodel.model.domain.internal.DiscriminatorSqmPathSource; +import org.hibernate.metamodel.model.domain.internal.EmbeddedSqmPathSource; import org.hibernate.metamodel.model.domain.spi.JpaMetamodelImplementor; import org.hibernate.metamodel.spi.MappingMetamodelImplementor; import org.hibernate.query.BindableType; @@ -150,6 +151,7 @@ import org.hibernate.service.ServiceRegistry; import org.hibernate.type.BasicType; import org.hibernate.type.StandardBasicTypes; import org.hibernate.type.descriptor.java.JavaType; +import org.hibernate.type.descriptor.java.JavaTypeHelper; import org.hibernate.type.spi.TypeConfiguration; import jakarta.persistence.Tuple; @@ -166,6 +168,7 @@ import jakarta.persistence.criteria.Selection; import jakarta.persistence.criteria.SetJoin; import jakarta.persistence.criteria.Subquery; import jakarta.persistence.metamodel.Bindable; +import jakarta.persistence.metamodel.EntityType; import static java.util.Arrays.asList; import static org.hibernate.query.internal.QueryHelper.highestPrecedenceType; @@ -234,40 +237,63 @@ public class SqmCriteriaNodeBuilder implements NodeBuilder, SqmCreationContext, return sessionFactory.get(); } - public boolean areTypesComparable(SqmExpressible lhsType, SqmExpressible rhsType) { - if ( lhsType == null || rhsType == null || lhsType == rhsType ) { - return true; - } - - if ( !lhsType.checkTypeComparability() || !rhsType.checkTypeComparability() ) { + public static boolean areTypesComparable(SqmExpressible lhsType, SqmExpressible rhsType) { + if ( lhsType == null || rhsType == null || lhsType == rhsType + || isDiscriminatorComparison( lhsType, rhsType ) + // Allow comparing an embeddable against a tuple literal + || lhsType instanceof EmbeddedSqmPathSource && rhsType instanceof TupleType + || rhsType instanceof EmbeddedSqmPathSource && lhsType instanceof TupleType + // Since we don't know any better, we just allow any comparison with multi-valued parameters + || lhsType instanceof MultiValueParameterType + || rhsType instanceof MultiValueParameterType) { return true; } final JavaType lhsJavaType = lhsType.getExpressibleJavaType(); final JavaType rhsJavaType = rhsType.getExpressibleJavaType(); - if ( lhsJavaType.isTemporalType() || rhsJavaType.isTemporalType() ) { - return true; - } - - if ( lhsJavaType.isUnknownType() || rhsJavaType.isUnknownType() ) { - return true; - } - - if ( lhsJavaType == rhsJavaType + return lhsJavaType == rhsJavaType + // If we don't know the java types, let's just be lenient + || JavaTypeHelper.isUnknown( lhsJavaType ) + || JavaTypeHelper.isUnknown( rhsJavaType ) + // Allow comparing two temporal expressions regardless of their concrete java types + || JavaTypeHelper.isTemporal( lhsJavaType ) && JavaTypeHelper.isTemporal( rhsJavaType ) + // Assume we can coerce one to another || lhsJavaType.isWider( rhsJavaType ) - || rhsJavaType.isWider( lhsJavaType ) ) { - // Assume we can coerce one to another - return true; + || rhsJavaType.isWider( lhsJavaType ) + // Polymorphic entity comparison + || lhsJavaType.getJavaTypeClass().isAssignableFrom( rhsJavaType.getJavaTypeClass() ) + || rhsJavaType.getJavaTypeClass().isAssignableFrom( lhsJavaType.getJavaTypeClass() ); + } + + private static boolean isDiscriminatorComparison(SqmExpressible lhsType, SqmExpressible rhsType) { + final SqmExpressible nonDiscriminator; + if ( lhsType instanceof DiscriminatorSqmPathSource ) { + nonDiscriminator = rhsType; + } + else if ( rhsType instanceof DiscriminatorSqmPathSource ) { + nonDiscriminator = lhsType; + } + else { + return false; } - if ( lhsJavaType.getJavaTypeClass().isAssignableFrom( rhsJavaType.getJavaTypeClass() ) - || rhsJavaType.getJavaTypeClass().isAssignableFrom( lhsJavaType.getJavaTypeClass() ) ) { - // Polymorphic entity comparison + // Comparing the discriminator against an entity type is fine + if ( nonDiscriminator instanceof EntityType ) { return true; } - - return false; + final JavaType nonDiscriminatorJavaType = nonDiscriminator.getExpressibleJavaType(); + // Comparing the discriminator against the discriminator value is fine + switch ( nonDiscriminatorJavaType.getJavaTypeClass().getTypeName() ) { + case "java.lang.String": + case "char": + case "java.lang.Character": + case "int": + case "java.lang.Integer": + return true; + default: + return false; + } } @Override @@ -1292,11 +1318,6 @@ public class SqmCriteriaNodeBuilder implements NodeBuilder, SqmCreationContext, public Class getBindableJavaType() { return javaType.getJavaTypeClass(); } - - @Override - public boolean checkTypeComparability() { - return false; - } } @Override @@ -2070,8 +2091,8 @@ public class SqmCriteriaNodeBuilder implements NodeBuilder, SqmCreationContext, } public void assertComparable(Expression x, Expression y) { - final SqmExpressible lhsType = ((SqmExpression) x).getNodeType(); - final SqmExpressible rhsType = ((SqmExpression) y).getNodeType(); + final SqmExpressible lhsType = ( (SqmExpression) x ).getNodeType(); + final SqmExpressible rhsType = ( (SqmExpression) y ).getNodeType(); if ( !areTypesComparable( lhsType, rhsType ) ) { throw new IllegalArgumentException( String.format( diff --git a/hibernate-core/src/main/java/org/hibernate/query/sqm/sql/BaseSqmToSqlAstConverter.java b/hibernate-core/src/main/java/org/hibernate/query/sqm/sql/BaseSqmToSqlAstConverter.java index 5fa69807b3..226924fa21 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/sqm/sql/BaseSqmToSqlAstConverter.java +++ b/hibernate-core/src/main/java/org/hibernate/query/sqm/sql/BaseSqmToSqlAstConverter.java @@ -393,6 +393,7 @@ import org.hibernate.type.descriptor.converter.internal.OrdinalEnumValueConverte import org.hibernate.type.descriptor.converter.spi.BasicValueConverter; import org.hibernate.type.descriptor.java.EnumJavaType; import org.hibernate.type.descriptor.java.JavaType; +import org.hibernate.type.descriptor.java.JavaTypeHelper; import org.hibernate.type.descriptor.java.TemporalJavaType; import org.hibernate.type.descriptor.jdbc.JdbcType; import org.hibernate.type.descriptor.jdbc.JdbcTypeIndicators; @@ -6061,7 +6062,7 @@ public abstract class BaseSqmToSqlAstConverter extends Base private static Expression getActualExpression(Expression expression) { if ( expression.getExpressionType() instanceof EmbeddableValuedModelPart ) { final EmbeddableValuedModelPart embeddableValuedModelPart = (EmbeddableValuedModelPart) expression.getExpressionType(); - if ( embeddableValuedModelPart.getJavaType().isTemporalType() ) { + if ( JavaTypeHelper.isTemporal( embeddableValuedModelPart.getJavaType() ) ) { return ( (SqlTupleContainer) expression ).getSqlTuple().getExpressions().get( 0 ); } } diff --git a/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/domain/AbstractSqmSpecificPluralPartPath.java b/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/domain/AbstractSqmSpecificPluralPartPath.java index 53abca60c4..db1a8451fa 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/domain/AbstractSqmSpecificPluralPartPath.java +++ b/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/domain/AbstractSqmSpecificPluralPartPath.java @@ -9,6 +9,7 @@ package org.hibernate.query.sqm.tree.domain; import org.hibernate.metamodel.model.domain.EntityDomainType; import org.hibernate.metamodel.model.domain.PluralPersistentAttribute; import org.hibernate.query.PathException; +import org.hibernate.query.sqm.SqmPathSource; import org.hibernate.spi.NavigablePath; /** @@ -16,15 +17,16 @@ import org.hibernate.spi.NavigablePath; */ public abstract class AbstractSqmSpecificPluralPartPath extends AbstractSqmPath implements SqmPath { private final SqmPath pluralDomainPath; - private final PluralPersistentAttribute pluralAttribute; + private final PluralPersistentAttribute pluralAttribute; public AbstractSqmSpecificPluralPartPath( NavigablePath navigablePath, SqmPath pluralDomainPath, - PluralPersistentAttribute referencedAttribute) { + PluralPersistentAttribute referencedAttribute, + SqmPathSource pathSource) { super( navigablePath, - referencedAttribute, + pathSource, pluralDomainPath, pluralDomainPath.nodeBuilder() ); @@ -36,7 +38,7 @@ public abstract class AbstractSqmSpecificPluralPartPath extends AbstractSqmPa return pluralDomainPath; } - public PluralPersistentAttribute getPluralAttribute() { + public PluralPersistentAttribute getPluralAttribute() { return pluralAttribute; } diff --git a/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/domain/SqmElementAggregateFunction.java b/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/domain/SqmElementAggregateFunction.java index f7b3b8829c..29b41ba0d5 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/domain/SqmElementAggregateFunction.java +++ b/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/domain/SqmElementAggregateFunction.java @@ -23,7 +23,8 @@ public class SqmElementAggregateFunction extends AbstractSqmSpecificPluralPar super( pluralDomainPath.getNavigablePath().getParent().append( pluralDomainPath.getNavigablePath().getLocalName(), "{" + functionName + "-element}" ), pluralDomainPath, - (PluralPersistentAttribute) pluralDomainPath.getReferencedPathSource() + (PluralPersistentAttribute) pluralDomainPath.getReferencedPathSource(), + ( (PluralPersistentAttribute) pluralDomainPath.getReferencedPathSource() ).getElementPathSource() ); this.functionName = functionName; } @@ -60,11 +61,6 @@ public class SqmElementAggregateFunction extends AbstractSqmSpecificPluralPar return sqmPath; } - @Override - public SqmPathSource getReferencedPathSource() { - return getPluralAttribute().getElementPathSource(); - } - @Override public X accept(SemanticQueryWalker walker) { return walker.visitElementAggregateFunction( this ); diff --git a/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/domain/SqmIndexAggregateFunction.java b/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/domain/SqmIndexAggregateFunction.java index e523f7d754..e8966c7361 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/domain/SqmIndexAggregateFunction.java +++ b/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/domain/SqmIndexAggregateFunction.java @@ -6,19 +6,16 @@ */ package org.hibernate.query.sqm.tree.domain; -import org.hibernate.metamodel.model.domain.ListPersistentAttribute; -import org.hibernate.metamodel.model.domain.MapPersistentAttribute; import org.hibernate.metamodel.model.domain.PluralPersistentAttribute; -import org.hibernate.query.sqm.SqmPathSource; -import org.hibernate.query.sqm.SemanticQueryWalker; import org.hibernate.query.hql.spi.SqmCreationState; +import org.hibernate.query.sqm.SemanticQueryWalker; +import org.hibernate.query.sqm.SqmPathSource; import org.hibernate.query.sqm.tree.SqmCopyContext; /** * @author Steve Ebersole */ public class SqmIndexAggregateFunction extends AbstractSqmSpecificPluralPartPath { - private final SqmPathSource indexPathSource; private final String functionName; public SqmIndexAggregateFunction(SqmPath pluralDomainPath, String functionName) { @@ -26,21 +23,10 @@ public class SqmIndexAggregateFunction extends AbstractSqmSpecificPluralPartP super( pluralDomainPath.getNavigablePath().getParent().append( pluralDomainPath.getNavigablePath().getLocalName(), "{" + functionName + "-index}" ), pluralDomainPath, - (PluralPersistentAttribute) pluralDomainPath.getReferencedPathSource() + (PluralPersistentAttribute) pluralDomainPath.getReferencedPathSource(), + (SqmPathSource) ( (PluralPersistentAttribute) pluralDomainPath.getReferencedPathSource() ).getIndexPathSource() ); this.functionName = functionName; - - if ( getPluralAttribute() instanceof ListPersistentAttribute ) { - //noinspection unchecked - this.indexPathSource = (SqmPathSource) getPluralAttribute().getIndexPathSource(); - } - else if ( getPluralAttribute() instanceof MapPersistentAttribute ) { - //noinspection unchecked - this.indexPathSource = ( (MapPersistentAttribute) getPluralAttribute() ).getKeyPathSource(); - } - else { - throw new UnsupportedOperationException( "Plural attribute [" + getPluralAttribute() + "] is not indexed" ); - } } @Override @@ -75,11 +61,6 @@ public class SqmIndexAggregateFunction extends AbstractSqmSpecificPluralPartP return sqmPath; } - @Override - public SqmPathSource getReferencedPathSource() { - return indexPathSource; - } - @Override public X accept(SemanticQueryWalker walker) { return walker.visitIndexAggregateFunction( this ); diff --git a/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/expression/SqmExpressionHelper.java b/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/expression/SqmExpressionHelper.java index 1f68f654d6..cf228e868a 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/expression/SqmExpressionHelper.java +++ b/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/expression/SqmExpressionHelper.java @@ -24,6 +24,7 @@ import org.hibernate.query.sqm.NodeBuilder; import org.hibernate.query.sqm.SqmExpressible; import org.hibernate.query.sqm.TemporalUnit; import org.hibernate.query.sqm.tree.domain.SqmPath; +import org.hibernate.type.descriptor.java.JavaTypeHelper; import org.hibernate.type.descriptor.java.JdbcDateJavaType; import org.hibernate.type.descriptor.java.JdbcTimeJavaType; import org.hibernate.type.descriptor.java.JdbcTimestampJavaType; @@ -111,7 +112,7 @@ public class SqmExpressionHelper { public static boolean isCompositeTemporal(SqmExpression expression) { // When TimeZoneStorageStrategy.COLUMN is used, that implies using a composite user type return expression instanceof SqmPath && expression.getNodeType() instanceof EmbeddedSqmPathSource - && expression.getJavaTypeDescriptor().isTemporalType(); + && JavaTypeHelper.isTemporal( expression.getJavaTypeDescriptor() ); } public static SqmExpression getActualExpression(SqmExpression expression) { diff --git a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/CurrencyJavaType.java b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/CurrencyJavaType.java index 0fc393bf90..9ea26939e7 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/CurrencyJavaType.java +++ b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/CurrencyJavaType.java @@ -63,6 +63,7 @@ public class CurrencyJavaType extends AbstractClassJavaType { @Override public boolean isWider(JavaType javaType) { + // This is necessary to allow comparing/assigning a currency attribute against a literal of the JdbcType switch ( javaType.getJavaType().getTypeName() ) { case "java.lang.String": return true; diff --git a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/EnumJavaType.java b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/EnumJavaType.java index 90a7068a30..b0f73e858c 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/EnumJavaType.java +++ b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/EnumJavaType.java @@ -230,6 +230,7 @@ public class EnumJavaType> extends AbstractClassJavaType { @Override public boolean isWider(JavaType javaType) { + // This is necessary to allow comparing/assigning an enum attribute against a literal of the JdbcType switch ( javaType.getJavaType().getTypeName() ) { case "byte": case "java.lang.Byte": diff --git a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/JavaType.java b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/JavaType.java index c4f0fdd479..96e0cfb75b 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/JavaType.java +++ b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/JavaType.java @@ -333,13 +333,4 @@ public interface JavaType extends Serializable { return false; } - /** - * Return true if the implementation is an instance of {@link org.hibernate.type.descriptor.java.spi.UnknownBasicJavaType} - * - * @return true if it is an instance of {@link UnknownBasicJavaType}; false otherwise - */ - default boolean isUnknownType(){ - return false; - } - } diff --git a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/JavaTypeHelper.java b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/JavaTypeHelper.java index 133fc61881..e993a0504f 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/JavaTypeHelper.java +++ b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/JavaTypeHelper.java @@ -7,6 +7,7 @@ package org.hibernate.type.descriptor.java; import org.hibernate.HibernateException; +import org.hibernate.type.descriptor.java.spi.UnknownBasicJavaType; /** * @author Steve Ebersole @@ -23,4 +24,12 @@ public class JavaTypeHelper { "Unknown wrap conversion requested: " + valueType.getName() + " to " + sourceType.getName() + " : `" + jtd.getClass().getName() + "` (" + jtd.getJavaTypeClass().getName() + ")" ); } + + public static boolean isTemporal(JavaType javaType) { + return javaType != null && javaType.isTemporalType(); + } + + public static boolean isUnknown(JavaType javaType) { + return javaType.getClass() == UnknownBasicJavaType.class; + } } diff --git a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/spi/UnknownBasicJavaType.java b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/spi/UnknownBasicJavaType.java index 2f414ca35a..9c8eeae72b 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/spi/UnknownBasicJavaType.java +++ b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/spi/UnknownBasicJavaType.java @@ -18,7 +18,7 @@ import org.hibernate.type.descriptor.jdbc.JdbcTypeIndicators; * {@link AbstractJavaType} adapter for cases where we do not know a proper * {@link org.hibernate.type.descriptor.java.JavaType} for a given Java type. */ -public class UnknownBasicJavaType extends AbstractJavaType { +public final class UnknownBasicJavaType extends AbstractJavaType { public UnknownBasicJavaType(Class type) { super( type ); } @@ -76,9 +76,4 @@ public class UnknownBasicJavaType extends AbstractJavaType { public String toString() { return "BasicJavaType(" + getJavaType().getTypeName() + ")"; } - - @Override - public boolean isUnknownType() { - return true; - } } diff --git a/hibernate-core/src/main/java/org/hibernate/type/format/jaxb/JaxbXmlFormatMapper.java b/hibernate-core/src/main/java/org/hibernate/type/format/jaxb/JaxbXmlFormatMapper.java index 30f3fad4cb..d1bbd255a5 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/format/jaxb/JaxbXmlFormatMapper.java +++ b/hibernate-core/src/main/java/org/hibernate/type/format/jaxb/JaxbXmlFormatMapper.java @@ -23,6 +23,8 @@ import javax.xml.namespace.QName; import org.hibernate.internal.util.ReflectHelper; import org.hibernate.internal.util.collections.CollectionHelper; import org.hibernate.sql.ast.spi.StringBuilderSqlAppender; +import org.hibernate.type.descriptor.java.JavaTypeHelper; +import org.hibernate.type.descriptor.java.spi.UnknownBasicJavaType; import org.hibernate.type.format.FormatMapper; import org.hibernate.type.descriptor.WrapperOptions; import org.hibernate.type.descriptor.java.BasicPluralJavaType; @@ -449,7 +451,7 @@ public final class JaxbXmlFormatMapper implements FormatMapper { .getTypeConfiguration() .getJavaTypeRegistry() .findDescriptor( elementClass ); - if ( exampleElement == null && ( elementJavaType == null || elementJavaType.isUnknownType() ) ) { + if ( exampleElement == null && ( elementJavaType == null || JavaTypeHelper.isUnknown( elementJavaType ) ) ) { try { final Constructor declaredConstructor = elementClass.getDeclaredConstructor(); exampleElement = declaredConstructor.newInstance(); @@ -479,7 +481,7 @@ public final class JaxbXmlFormatMapper implements FormatMapper { Object exampleElement, JAXBIntrospector introspector, WrapperOptions wrapperOptions) { - if ( exampleElement == null && elementJavaType.isUnknownType() ) { + if ( exampleElement == null && JavaTypeHelper.isUnknown( elementJavaType ) ) { try { final Constructor declaredConstructor = elementJavaType.getJavaTypeClass().getDeclaredConstructor(); exampleElement = declaredConstructor.newInstance();