diff --git a/hibernate-core/src/main/java/org/hibernate/boot/query/HbmResultSetMappingDescriptor.java b/hibernate-core/src/main/java/org/hibernate/boot/query/HbmResultSetMappingDescriptor.java index 75f9f638a0..8372c60ec4 100644 --- a/hibernate-core/src/main/java/org/hibernate/boot/query/HbmResultSetMappingDescriptor.java +++ b/hibernate-core/src/main/java/org/hibernate/boot/query/HbmResultSetMappingDescriptor.java @@ -674,10 +674,11 @@ public class HbmResultSetMappingDescriptor implements NamedResultSetMappingDescr navigablePath = navigablePath.append( fetchable.getFetchableName() ); } - if ( fetchable instanceof BasicValuedModelPart ) { + final BasicValuedModelPart basicPart = fetchable.asBasicValuedModelPart(); + if ( basicPart != null ) { return new FetchMementoBasicStandard( navigablePath, - (BasicValuedModelPart) fetchable, + basicPart, columnAliases.get( 0 ) ); } diff --git a/hibernate-core/src/main/java/org/hibernate/boot/query/SqlResultSetMappingDescriptor.java b/hibernate-core/src/main/java/org/hibernate/boot/query/SqlResultSetMappingDescriptor.java index 133bb4f7de..e17a113942 100644 --- a/hibernate-core/src/main/java/org/hibernate/boot/query/SqlResultSetMappingDescriptor.java +++ b/hibernate-core/src/main/java/org/hibernate/boot/query/SqlResultSetMappingDescriptor.java @@ -347,14 +347,9 @@ public class SqlResultSetMappingDescriptor implements NamedResultSetMappingDescr final ModelPart subPart = entityMapping.findSubPart( propertyPath, null ); - //noinspection StatementWithEmptyBody - if ( subPart == null ) { - // throw an exception - } - - if ( subPart instanceof BasicValuedModelPart ) { + final BasicValuedModelPart basicPart = subPart != null ? subPart.asBasicValuedModelPart() : null; + if ( basicPart != null ) { assert columnNames.size() == 1; - final BasicValuedModelPart basicPart = (BasicValuedModelPart) subPart; return new ModelPartResultMementoBasicImpl( path, basicPart, columnNames.get( 0 ) ); } @@ -405,10 +400,9 @@ public class SqlResultSetMappingDescriptor implements NamedResultSetMappingDescr } private FetchMemento getFetchMemento(NavigablePath navigablePath, ModelPart subPart) { - if ( subPart instanceof BasicValuedModelPart ) { + final BasicValuedModelPart basicPart = subPart.asBasicValuedModelPart(); + if ( basicPart != null ) { assert columnNames.size() == 1; - final BasicValuedModelPart basicPart = (BasicValuedModelPart) subPart; - return new FetchMementoBasicStandard( navigablePath, basicPart, columnNames.get( 0 ) ); } else if ( subPart instanceof EntityValuedFetchable ) { diff --git a/hibernate-core/src/main/java/org/hibernate/loader/ast/internal/LoaderSelectBuilder.java b/hibernate-core/src/main/java/org/hibernate/loader/ast/internal/LoaderSelectBuilder.java index 8e46b9c1b8..f029d28e0f 100644 --- a/hibernate-core/src/main/java/org/hibernate/loader/ast/internal/LoaderSelectBuilder.java +++ b/hibernate-core/src/main/java/org/hibernate/loader/ast/internal/LoaderSelectBuilder.java @@ -974,7 +974,7 @@ public class LoaderSelectBuilder { } else if ( fetchDepth > maximumFetchDepth + 1 ) { // We can preserve the existing value of joined for basic and embedded values - if ( !( fetchable instanceof BasicValuedModelPart ) && !( fetchable instanceof EmbeddedAttributeMapping ) ) { + if ( fetchable.asBasicValuedModelPart() == null && !( fetchable instanceof EmbeddedAttributeMapping ) ) { joined = false; } } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/MappingModelHelper.java b/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/MappingModelHelper.java index 09737cabbf..4c95b6cae9 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/MappingModelHelper.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/MappingModelHelper.java @@ -8,6 +8,8 @@ package org.hibernate.metamodel.mapping; import org.hibernate.persister.entity.UnionSubclassEntityPersister; +import static org.hibernate.internal.util.NullnessUtil.castNonNull; + /** * @author Steve Ebersole */ @@ -134,18 +136,21 @@ public class MappingModelHelper { } return true; } - else if ( attribute1 instanceof BasicValuedModelPart ) { - final BasicValuedModelPart basic1 = (BasicValuedModelPart) attribute1; - final BasicValuedModelPart basic2 = (BasicValuedModelPart) attribute2; - if ( !basic1.getSelectionExpression().equals( basic2.getSelectionExpression() ) ) { - return false; + else { + final BasicValuedModelPart basic1 = attribute1.asBasicValuedModelPart(); + if ( basic1 != null ) { + final BasicValuedModelPart basic2 = castNonNull( attribute2.asBasicValuedModelPart() ); + if ( !basic1.getSelectionExpression().equals( basic2.getSelectionExpression() ) ) { + return false; + } + if ( basic1.getContainingTableExpression().equals( basic2.getContainingTableExpression() ) ) { + return true; + } + // For union subclass mappings we also consider mappings compatible that just match the selection expression, + // because we match up columns of disjoint union subclass types by column name + return attribute1.findContainingEntityMapping() + .getEntityPersister() instanceof UnionSubclassEntityPersister; } - if ( basic1.getContainingTableExpression().equals( basic2.getContainingTableExpression() ) ) { - return true; - } - // For union subclass mappings we also consider mappings compatible that just match the selection expression, - // because we match up columns of disjoint union subclass types by column name - return attribute1.findContainingEntityMapping().getEntityPersister() instanceof UnionSubclassEntityPersister; } return false; } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/AbstractDomainPath.java b/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/AbstractDomainPath.java index 0aa6733960..085fafc63b 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/AbstractDomainPath.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/AbstractDomainPath.java @@ -32,6 +32,7 @@ import org.hibernate.sql.ast.tree.select.SortSpecification; import org.hibernate.sql.results.graph.Fetchable; import org.hibernate.sql.results.internal.SqlSelectionImpl; +import static org.hibernate.internal.util.NullnessUtil.castNonNull; import static org.hibernate.sql.ast.spi.SqlExpressionResolver.createColumnReferenceKey; /** @@ -61,8 +62,8 @@ public abstract class AbstractDomainPath implements DomainPath { TableGroup tableGroup, String modelPartName, SqlAstCreationState creationState) { - if ( referenceModelPart instanceof BasicValuedModelPart ) { - final BasicValuedModelPart selection = (BasicValuedModelPart) referenceModelPart; + final BasicValuedModelPart selection = referenceModelPart.asBasicValuedModelPart(); + if ( selection != null ) { final TableReference tableReference = tableGroup.resolveTableReference( null, selection, @@ -104,7 +105,7 @@ public abstract class AbstractDomainPath implements DomainPath { } else { ModelPart subPart = embeddableValuedModelPart.findSubPart( modelPartName, null ); - assert subPart instanceof BasicValuedModelPart; + assert subPart.asBasicValuedModelPart() != null; return resolve( subPart, ast, tableGroup, modelPartName, creationState ); } } @@ -144,9 +145,10 @@ public abstract class AbstractDomainPath implements DomainPath { SortDirection sortOrder, NullPrecedence nullPrecedence, SqlAstCreationState creationState) { - if ( referenceModelPart instanceof BasicValuedModelPart ) { + final BasicValuedModelPart basicPart = referenceModelPart.asBasicValuedModelPart(); + if ( basicPart != null ) { addSortSpecification( - (BasicValuedModelPart) referenceModelPart, + basicPart, ast, tableGroup, collation, @@ -231,9 +233,8 @@ public abstract class AbstractDomainPath implements DomainPath { } else { ModelPart subPart = embeddableValuedModelPart.findSubPart( modelPartName, null ); - assert subPart instanceof BasicValuedModelPart; addSortSpecification( - (BasicValuedModelPart) subPart, + castNonNull( subPart.asBasicValuedModelPart() ), ast, tableGroup, collation, diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/ManyToManyCollectionPart.java b/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/ManyToManyCollectionPart.java index d197318c02..fe52a9d710 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/ManyToManyCollectionPart.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/ManyToManyCollectionPart.java @@ -620,14 +620,15 @@ public class ManyToManyCollectionPart extends AbstractEntityCollectionPart imple final String collectionTableName = ( (CollectionMutationTarget) getCollectionDescriptor() ).getCollectionTableMapping().getTableName(); - if ( fkTargetModelPart instanceof BasicValuedModelPart ) { + final BasicValuedModelPart basicFkTarget = fkTargetModelPart.asBasicValuedModelPart(); + if ( basicFkTarget != null ) { return createSimpleForeignKeyDescriptor( fkBootDescriptorSource, entityType, creationProcess, dialect, collectionTableName, - (BasicValuedModelPart) fkTargetModelPart + basicFkTarget ); } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/MappingModelCreationHelper.java b/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/MappingModelCreationHelper.java index 78a50d683c..8c50571e1f 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/MappingModelCreationHelper.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/MappingModelCreationHelper.java @@ -101,6 +101,7 @@ import org.hibernate.type.descriptor.java.MutabilityPlan; import org.hibernate.type.descriptor.java.spi.JavaTypeRegistry; import org.hibernate.type.spi.TypeConfiguration; +import static org.hibernate.internal.util.NullnessUtil.castNonNull; import static org.hibernate.metamodel.mapping.MappingModelCreationLogging.MAPPING_MODEL_CREATION_MESSAGE_LOGGER; import static org.hibernate.sql.ast.spi.SqlExpressionResolver.createColumnReferenceKey; @@ -769,9 +770,8 @@ public class MappingModelCreationHelper { if ( keyType instanceof BasicType ) { assert bootValueMappingKey.getColumnSpan() == 1; - assert fkTargetPart instanceof BasicValuedModelPart; - final BasicValuedModelPart simpleFkTargetPart = (BasicValuedModelPart) fkTargetPart; + final BasicValuedModelPart simpleFkTargetPart = castNonNull( fkTargetPart.asBasicValuedModelPart() ); final String keyTableExpression = collectionTableName;//getTableIdentifierExpression( bootValueMappingKey.getTable(), creationProcess ); final SelectableMapping keySelectableMapping = SelectableMappingImpl.from( @@ -921,8 +921,8 @@ public class MappingModelCreationHelper { fkTarget = referencedEntityDescriptor.findByPath( bootValueMapping.getReferencedPropertyName() ); } - if ( fkTarget instanceof BasicValuedModelPart ) { - final BasicValuedModelPart simpleFkTarget = (BasicValuedModelPart) fkTarget; + final BasicValuedModelPart simpleFkTarget = fkTarget.asBasicValuedModelPart(); + if ( simpleFkTarget != null ) { final Iterator columnIterator = bootValueMapping.getSelectables().iterator(); final Table table = bootValueMapping.getTable(); final String tableExpression = getTableIdentifierExpression( table, creationProcess ); @@ -1597,8 +1597,7 @@ public class MappingModelCreationHelper { return new SqlTuple( columnReferences, modelPart ); } else { - assert modelPart instanceof BasicValuedModelPart; - final BasicValuedModelPart basicPart = (BasicValuedModelPart) modelPart; + final BasicValuedModelPart basicPart = castNonNull( modelPart.asBasicValuedModelPart() ); final String qualifier; if ( tableGroup == null ) { qualifier = basicPart.getContainingTableExpression(); diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/SimpleForeignKeyDescriptor.java b/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/SimpleForeignKeyDescriptor.java index 1b129070f7..64bc6d850c 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/SimpleForeignKeyDescriptor.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/SimpleForeignKeyDescriptor.java @@ -227,7 +227,7 @@ public class SimpleForeignKeyDescriptor implements ForeignKeyDescriptor, BasicVa public ForeignKeyDescriptor withTargetPart(ValuedModelPart targetPart) { return new SimpleForeignKeyDescriptor( keySide.getModelPart(), - (BasicValuedModelPart) targetPart, + targetPart.asBasicValuedModelPart(), refersToPrimaryKey, hasConstraint, false diff --git a/hibernate-core/src/main/java/org/hibernate/persister/entity/AbstractEntityPersister.java b/hibernate-core/src/main/java/org/hibernate/persister/entity/AbstractEntityPersister.java index b8e65b33a5..066196692d 100644 --- a/hibernate-core/src/main/java/org/hibernate/persister/entity/AbstractEntityPersister.java +++ b/hibernate-core/src/main/java/org/hibernate/persister/entity/AbstractEntityPersister.java @@ -1907,7 +1907,7 @@ public abstract class AbstractEntityPersister // Ignore plural attributes if ( !( fetchable instanceof PluralAttributeMapping ) ) { final FetchTiming fetchTiming = fetchable.getMappedFetchOptions().getTiming(); - if ( fetchable instanceof BasicValuedModelPart ) { + if ( fetchable.asBasicValuedModelPart() != null ) { // Ignore lazy basic columns if ( fetchTiming == FetchTiming.DELAYED ) { continue; @@ -4662,7 +4662,7 @@ public abstract class AbstractEntityPersister final List generatedBasicAttributes = new ArrayList<>( originalSize ); for ( AttributeMapping generatedAttribute : generatedAttributes ) { // todo (7.0) : support non selectable mappings? Component, ToOneAttributeMapping, ... - if ( generatedAttribute instanceof BasicValuedModelPart + if ( generatedAttribute.asBasicValuedModelPart() != null && generatedAttribute.getContainingTableExpression().equals( getSubclassTableName( 0 ) ) ) { generatedBasicAttributes.add( generatedAttribute ); } diff --git a/hibernate-core/src/main/java/org/hibernate/query/internal/ImplicitModelPartResultMemento.java b/hibernate-core/src/main/java/org/hibernate/query/internal/ImplicitModelPartResultMemento.java index 366bc10eb2..cf7018807c 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/internal/ImplicitModelPartResultMemento.java +++ b/hibernate-core/src/main/java/org/hibernate/query/internal/ImplicitModelPartResultMemento.java @@ -40,8 +40,9 @@ public class ImplicitModelPartResultMemento implements ModelPartResultMemento { public ResultBuilder resolve( Consumer querySpaceConsumer, ResultSetMappingResolutionContext context) { - if ( referencedModelPart instanceof BasicValuedModelPart ) { - return new ImplicitModelPartResultBuilderBasic( navigablePath, (BasicValuedModelPart) referencedModelPart ); + final BasicValuedModelPart basicPart = referencedModelPart.asBasicValuedModelPart(); + if ( basicPart != null ) { + return new ImplicitModelPartResultBuilderBasic( navigablePath, basicPart ); } if ( referencedModelPart instanceof EmbeddableValuedModelPart ) { diff --git a/hibernate-core/src/main/java/org/hibernate/query/internal/ResultMementoEntityJpa.java b/hibernate-core/src/main/java/org/hibernate/query/internal/ResultMementoEntityJpa.java index 57f9d62942..56307a0a80 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/internal/ResultMementoEntityJpa.java +++ b/hibernate-core/src/main/java/org/hibernate/query/internal/ResultMementoEntityJpa.java @@ -87,11 +87,11 @@ public class ResultMementoEntityJpa implements ResultMementoEntity, FetchMemento // Implicit basic fetches are DELAYED by default, so register fetch builders for the remaining basic fetchables entityDescriptor.forEachAttributeMapping( attributeMapping -> { - final Function fetchBuilderCreator; - if ( attributeMapping instanceof BasicValuedModelPart ) { - fetchBuilderCreator = k -> new DelayedFetchBuilderBasicPart( + final BasicValuedModelPart basicPart = attributeMapping.asBasicValuedModelPart(); + if ( basicPart != null ) { + final Function fetchBuilderCreator = k -> new DelayedFetchBuilderBasicPart( navigablePath.append( k ), - (BasicValuedModelPart) attributeMapping, + basicPart, isEnhancedForLazyLoading ); explicitFetchBuilderMap.computeIfAbsent( diff --git a/hibernate-core/src/main/java/org/hibernate/query/results/Builders.java b/hibernate-core/src/main/java/org/hibernate/query/results/Builders.java index f936786199..c8999ed24c 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/results/Builders.java +++ b/hibernate-core/src/main/java/org/hibernate/query/results/Builders.java @@ -269,8 +269,8 @@ public class Builders { NavigablePath fetchPath, Fetchable fetchable, DomainResultCreationState creationState) { - if ( fetchable instanceof BasicValuedModelPart ) { - final BasicValuedModelPart basicValuedFetchable = (BasicValuedModelPart) fetchable; + final BasicValuedModelPart basicValuedFetchable = fetchable.asBasicValuedModelPart(); + if ( basicValuedFetchable != null ) { return new ImplicitFetchBuilderBasic( fetchPath, basicValuedFetchable, creationState ); } diff --git a/hibernate-core/src/main/java/org/hibernate/query/results/dynamic/DynamicFetchBuilderStandard.java b/hibernate-core/src/main/java/org/hibernate/query/results/dynamic/DynamicFetchBuilderStandard.java index 5565578101..b0710a2471 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/results/dynamic/DynamicFetchBuilderStandard.java +++ b/hibernate-core/src/main/java/org/hibernate/query/results/dynamic/DynamicFetchBuilderStandard.java @@ -83,7 +83,8 @@ public class DynamicFetchBuilderStandard final Fetchable attributeMapping = (Fetchable) parent.getReferencedMappingContainer().findSubPart( fetchableName, null ); final SqlExpressionResolver sqlExpressionResolver = domainResultCreationState.getSqlAstCreationState().getSqlExpressionResolver(); - if ( attributeMapping instanceof BasicValuedModelPart ) { + final BasicValuedModelPart basicPart = attributeMapping.asBasicValuedModelPart(); + if ( basicPart != null ) { attributeMapping.forEachSelectable( getSelectableConsumer( fetchPath, @@ -92,7 +93,7 @@ public class DynamicFetchBuilderStandard creationStateImpl, ownerTableGroup, sqlExpressionResolver, - (BasicValuedModelPart) attributeMapping + basicPart ) ); return parent.generateFetchableFetch( diff --git a/hibernate-core/src/main/java/org/hibernate/query/sqm/mutation/internal/inline/InPredicateRestrictionProducer.java b/hibernate-core/src/main/java/org/hibernate/query/sqm/mutation/internal/inline/InPredicateRestrictionProducer.java index 052a8a001c..4dcd8a4ecc 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/sqm/mutation/internal/inline/InPredicateRestrictionProducer.java +++ b/hibernate-core/src/main/java/org/hibernate/query/sqm/mutation/internal/inline/InPredicateRestrictionProducer.java @@ -25,6 +25,8 @@ import org.hibernate.sql.ast.tree.from.TableReference; import org.hibernate.sql.ast.tree.predicate.InListPredicate; import org.hibernate.sql.exec.spi.ExecutionContext; +import static org.hibernate.internal.util.NullnessUtil.castNonNull; + /** * MatchingIdRestrictionProducer producing a restriction based on an in-values-list predicate. E.g.: * @@ -88,7 +90,7 @@ public class InPredicateRestrictionProducer implements MatchingIdRestrictionProd final InListPredicate predicate; if ( idColumnCount == 1 ) { - final BasicValuedModelPart basicIdMapping = (BasicValuedModelPart) identifierMapping; + final BasicValuedModelPart basicIdMapping = castNonNull( identifierMapping.asBasicValuedModelPart() ); final String idColumn = basicIdMapping.getSelectionExpression(); final Expression inFixture = new ColumnReference( mutatingTableReference, 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 216b714c15..bb908e81a9 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 @@ -2991,7 +2991,7 @@ public abstract class BaseSqmToSqlAstConverter extends Base final ModelPart subPart = parentType.findSubPart( attributeName ); final EntityNameUse entityNameUse; // We only apply this optimization for basic valued model parts for now - if ( subPart instanceof BasicValuedModelPart ) { + if ( subPart.asBasicValuedModelPart() != null ) { entityNameUse = EntityNameUse.OPTIONAL_TREAT; } else { @@ -4206,50 +4206,52 @@ public abstract class BaseSqmToSqlAstConverter extends Base tableGroup ); } - else if ( actualModelPart instanceof BasicValuedModelPart ) { - final BasicValuedModelPart mapping = (BasicValuedModelPart) actualModelPart; - final TableReference tableReference = tableGroup.resolveTableReference( - navigablePath.append( actualModelPart.getPartName() ), - mapping, - mapping.getContainingTableExpression() - ); + else { + final BasicValuedModelPart mapping = actualModelPart.asBasicValuedModelPart(); + if ( mapping != null ) { + final TableReference tableReference = tableGroup.resolveTableReference( + navigablePath.append( actualModelPart.getPartName() ), + mapping, + mapping.getContainingTableExpression() + ); - final Expression expression = getSqlExpressionResolver().resolveSqlExpression( - tableReference, - mapping - ); - final ColumnReference columnReference; - if ( expression instanceof ColumnReference ) { - columnReference = (ColumnReference) expression; + final Expression expression = getSqlExpressionResolver().resolveSqlExpression( + tableReference, + mapping + ); + final ColumnReference columnReference; + if ( expression instanceof ColumnReference ) { + columnReference = (ColumnReference) expression; + } + else if ( expression instanceof SqlSelectionExpression ) { + final Expression selectedExpression = ( (SqlSelectionExpression) expression ).getSelection().getExpression(); + assert selectedExpression instanceof ColumnReference; + columnReference = (ColumnReference) selectedExpression; + } + else { + throw new UnsupportedOperationException( "Unsupported basic-valued path expression : " + expression ); + } + result = new BasicValuedPathInterpretation<>( + columnReference, + navigablePath, + mapping, + tableGroup + ); } - else if ( expression instanceof SqlSelectionExpression ) { - final Expression selectedExpression = ( (SqlSelectionExpression) expression ).getSelection().getExpression(); - assert selectedExpression instanceof ColumnReference; - columnReference = (ColumnReference) selectedExpression; + else if ( actualModelPart instanceof AnonymousTupleTableGroupProducer ) { + throw new SemanticException( + "The derived SqmFrom" + ( (AnonymousTupleType) path.getReferencedPathSource() ).getComponentNames() + " can not be used in a context where the expression needs to " + + "be expanded to identifying parts, because a derived model part does not have identifying parts. " + + "Replace uses of the root with paths instead e.g. `derivedRoot.get(\"alias1\")` or `derivedRoot.alias1`" + ); } else { - throw new UnsupportedOperationException( "Unsupported basic-valued path expression : " + expression ); + throw new SemanticException( + "The SqmFrom node [" + path + "] can not be used in a context where the expression needs to " + + "be expanded to identifying parts, because the model part [" + actualModelPart + + "] does not have identifying parts." + ); } - result = new BasicValuedPathInterpretation<>( - columnReference, - navigablePath, - mapping, - tableGroup - ); - } - else if ( actualModelPart instanceof AnonymousTupleTableGroupProducer ) { - throw new SemanticException( - "The derived SqmFrom" + ( (AnonymousTupleType) path.getReferencedPathSource() ).getComponentNames() + " can not be used in a context where the expression needs to " + - "be expanded to identifying parts, because a derived model part does not have identifying parts. " + - "Replace uses of the root with paths instead e.g. `derivedRoot.get(\"alias1\")` or `derivedRoot.alias1`" - ); - } - else { - throw new SemanticException( - "The SqmFrom node [" + path + "] can not be used in a context where the expression needs to " + - "be expanded to identifying parts, because the model part [" + actualModelPart + - "] does not have identifying parts." - ); } return withTreatRestriction( result, path ); @@ -4434,9 +4436,8 @@ public abstract class BaseSqmToSqlAstConverter extends Base final TableReference tableReference = tableGroup.resolveTableReference( toOneMapping.getContainingTableExpression() ); final ModelPart fkKeyPart = fkDescriptor.getPart( toOneMapping.getSideNature() ); - if ( fkKeyPart instanceof BasicValuedModelPart ) { - final BasicValuedModelPart basicFkPart = (BasicValuedModelPart) fkKeyPart; - + final BasicValuedModelPart basicFkPart = fkKeyPart.asBasicValuedModelPart(); + if ( basicFkPart != null ) { return getSqlExpressionResolver().resolveSqlExpression( tableReference, basicFkPart @@ -4965,8 +4966,9 @@ public abstract class BaseSqmToSqlAstConverter extends Base ) ); final Set compatibleTableExpressions; - if ( modelPart instanceof BasicValuedModelPart ) { - compatibleTableExpressions = Collections.singleton( ( (BasicValuedModelPart) modelPart ).getContainingTableExpression() ); + final BasicValuedModelPart basicPart = modelPart.asBasicValuedModelPart(); + if ( basicPart != null ) { + compatibleTableExpressions = Collections.singleton( basicPart.getContainingTableExpression() ); } else if ( modelPart instanceof EmbeddableValuedModelPart ) { compatibleTableExpressions = Collections.singleton( ( (EmbeddableValuedModelPart) modelPart ).getContainingTableExpression() ); diff --git a/hibernate-core/src/main/java/org/hibernate/query/sqm/sql/internal/BasicValuedPathInterpretation.java b/hibernate-core/src/main/java/org/hibernate/query/sqm/sql/internal/BasicValuedPathInterpretation.java index 92c21e8d95..b3691da05b 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/sqm/sql/internal/BasicValuedPathInterpretation.java +++ b/hibernate-core/src/main/java/org/hibernate/query/sqm/sql/internal/BasicValuedPathInterpretation.java @@ -34,6 +34,7 @@ import org.hibernate.sql.ast.tree.from.TableGroup; import org.hibernate.sql.ast.tree.from.TableReference; import org.hibernate.sql.ast.tree.update.Assignable; +import static org.hibernate.internal.util.NullnessUtil.castNonNull; import static org.hibernate.query.sqm.internal.SqmUtil.needsTargetTableMapping; /** @@ -81,22 +82,22 @@ public class BasicValuedPathInterpretation extends AbstractSqmPathInterpretat } } - final BasicValuedModelPart mapping; + final ModelPart modelPart; if ( needsTargetTableMapping( sqmPath, modelPartContainer ) ) { // We have to make sure we render the column of the target table - mapping = (BasicValuedModelPart) ( (ManagedMappingType) modelPartContainer.getPartMappingType() ).findSubPart( + modelPart = ( (ManagedMappingType) modelPartContainer.getPartMappingType() ).findSubPart( sqmPath.getReferencedPathSource().getPathName(), treatTarget ); } else { - mapping = (BasicValuedModelPart) modelPartContainer.findSubPart( + modelPart = modelPartContainer.findSubPart( sqmPath.getReferencedPathSource().getPathName(), treatTarget ); } - if ( mapping == null ) { + if ( modelPart == null ) { if ( jpaQueryComplianceEnabled ) { // to get the better error, see if we got nothing because of treat handling final ModelPart subPart = tableGroup.getModelPart().findSubPart( @@ -111,6 +112,7 @@ public class BasicValuedPathInterpretation extends AbstractSqmPathInterpretat throw new UnknownPathException( "Path '" + sqmPath.getNavigablePath() + "' did not reference a known model part" ); } + final BasicValuedModelPart mapping = castNonNull( modelPart.asBasicValuedModelPart() ); final TableReference tableReference = tableGroup.resolveTableReference( sqmPath.getNavigablePath(), mapping, diff --git a/hibernate-core/src/main/java/org/hibernate/query/sqm/sql/internal/EntityValuedPathInterpretation.java b/hibernate-core/src/main/java/org/hibernate/query/sqm/sql/internal/EntityValuedPathInterpretation.java index 24d5185afb..f95d7ce56c 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/sqm/sql/internal/EntityValuedPathInterpretation.java +++ b/hibernate-core/src/main/java/org/hibernate/query/sqm/sql/internal/EntityValuedPathInterpretation.java @@ -325,8 +325,8 @@ public class EntityValuedPathInterpretation extends AbstractSqmPathInterpreta sqlExpression = new SqlTuple( expressions, entityMappingType ); } else { - if ( resultModelPart instanceof BasicValuedModelPart ) { - final BasicValuedModelPart basicValuedModelPart = (BasicValuedModelPart) resultModelPart; + final BasicValuedModelPart basicValuedModelPart = resultModelPart.asBasicValuedModelPart(); + if ( basicValuedModelPart != null ) { final TableReference tableReference = tableGroup.resolveTableReference( navigablePath, basicValuedModelPart,