From 277f10d987ed3aa70b14aa8f7ab7d4c0046c869b Mon Sep 17 00:00:00 2001 From: Christian Beikov Date: Mon, 21 Feb 2022 16:07:41 +0100 Subject: [PATCH] Support implicit joins in plural path parts and fix issues with type resolving of sub query paths --- .../hql/internal/SemanticQueryBuilder.java | 15 ++++++-- .../sqm/internal/SqmMappingModelHelper.java | 9 ++++- .../sqm/sql/BaseSqmToSqlAstConverter.java | 35 +++---------------- .../mapcompelem/MapCompositeElementTest.java | 2 -- 4 files changed, 26 insertions(+), 35 deletions(-) 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 388d4c6967..74343d2546 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 @@ -3871,8 +3871,19 @@ public class SemanticQueryBuilder extends HqlParserBaseVisitor implem ); final SqmSelectClause selectClause = new SqmSelectClause( false, 1, creationContext.getNodeBuilder() ); final SqmFromClause fromClause = new SqmFromClause( 1 ); - final SqmCorrelation correlation = ( (AbstractSqmFrom) pluralAttributePath.getLhs() ).createCorrelation(); - final SqmAttributeJoin collectionJoin = correlation.join( pluralAttributePath.getNavigablePath().getUnaliasedLocalName() ); + SqmPath lhs = pluralAttributePath.getLhs(); + final List implicitJoinPaths = new ArrayList<>(); + while ( !( lhs instanceof AbstractSqmFrom ) ) { + implicitJoinPaths.add( lhs.getNavigablePath().getUnaliasedLocalName() ); + lhs = lhs.getLhs(); + } + final AbstractSqmFrom correlationBase = (AbstractSqmFrom) lhs; + final SqmCorrelation correlation = correlationBase.createCorrelation(); + SqmFrom joinBase = correlation; + for ( int i = implicitJoinPaths.size() - 1; i >= 0; i-- ) { + joinBase = joinBase.join( implicitJoinPaths.get( i ) ); + } + final SqmAttributeJoin collectionJoin = joinBase.join( pluralAttributePath.getNavigablePath().getUnaliasedLocalName() ); fromClause.addRoot( correlation.getCorrelatedRoot() ); if ( collectionReferenceCtx == null ) { final SqmLiteral literal = new SqmLiteral<>( diff --git a/hibernate-core/src/main/java/org/hibernate/query/sqm/internal/SqmMappingModelHelper.java b/hibernate-core/src/main/java/org/hibernate/query/sqm/internal/SqmMappingModelHelper.java index 9173e97d97..62b37e7856 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/sqm/internal/SqmMappingModelHelper.java +++ b/hibernate-core/src/main/java/org/hibernate/query/sqm/internal/SqmMappingModelHelper.java @@ -185,7 +185,14 @@ public class SqmMappingModelHelper { return domainModel.findEntityDescriptor( entityDomainType.getHibernateEntityName() ); } final TableGroup lhsTableGroup = tableGroupLocator.apply( sqmPath.getLhs().getNavigablePath() ); - return lhsTableGroup.getModelPart().findSubPart( sqmPath.getReferencedPathSource().getPathName(), null ); + final ModelPartContainer modelPart; + if ( lhsTableGroup == null ) { + modelPart = (ModelPartContainer) resolveSqmPath( sqmPath.getLhs(), domainModel, tableGroupLocator ); + } + else { + modelPart = lhsTableGroup.getModelPart(); + } + return modelPart.findSubPart( sqmPath.getReferencedPathSource().getPathName(), null ); } public static EntityMappingType resolveExplicitTreatTarget( 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 7a8be9b12a..6f01df9c07 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 @@ -4555,7 +4555,6 @@ public abstract class BaseSqmToSqlAstConverter extends Base } else if ( sqmExpression instanceof SqmPath ) { log.debugf( "Determining mapping-model type for SqmPath : %s ", sqmExpression ); - prepareReusablePath( (SqmPath) sqmExpression, fromClauseIndex, () -> null ); final MappingMetamodel domainModel = creationContext.getSessionFactory() .getRuntimeMetamodels() .getMappingMetamodel(); @@ -4577,40 +4576,16 @@ public abstract class BaseSqmToSqlAstConverter extends Base final SqmSelectClause selectClause = subQuery.getQuerySpec().getSelectClause(); if ( selectClause.getSelections().size() == 1 ) { final SqmSelection subQuerySelection = selectClause.getSelections().get( 0 ); + final SqmSelectableNode selectableNode = subQuerySelection.getSelectableNode(); + if ( selectableNode instanceof SqmExpression ) { + return determineValueMapping( (SqmExpression) selectableNode, fromClauseIndex ); + } final SqmExpressible selectionNodeType = subQuerySelection.getNodeType(); if ( selectionNodeType != null ) { - final SqmExpressible sqmExpressible; - if ( selectionNodeType instanceof PluralPersistentAttribute ) { - sqmExpressible = ( (PluralPersistentAttribute) selectionNodeType ).getElementPathSource(); - } - else if ( selectionNodeType instanceof SqmPathSource) { - final SqmPathSource pathSource = (SqmPathSource) selectionNodeType; - final CollectionPart.Nature partNature = CollectionPart.Nature.fromName( - pathSource.getPathName() - ); - if ( partNature == null ) { - sqmExpressible = selectionNodeType; - } - else { - final SqmPath sqmPath = (SqmPath) subQuerySelection.getSelectableNode(); - final NavigablePath navigablePath = sqmPath.getNavigablePath().getParent(); - if ( navigablePath.getParent() != null ) { - final TableGroup parentTableGroup = fromClauseIndex.findTableGroup( navigablePath.getParent() ); - final PluralAttributeMapping pluralPart = (PluralAttributeMapping) parentTableGroup.getModelPart() - .findSubPart( navigablePath.getUnaliasedLocalName(), null ); - return pluralPart.findSubPart( pathSource.getPathName(), null ); - } - return fromClauseIndex.findTableGroup( navigablePath ).getModelPart(); - } - } - else { - sqmExpressible = selectionNodeType; - } - final MappingMetamodel domainModel = creationContext.getSessionFactory() .getRuntimeMetamodels() .getMappingMetamodel(); - final MappingModelExpressible expressible = domainModel.resolveMappingExpressible(sqmExpressible, this::findTableGroupByPath ); + final MappingModelExpressible expressible = domainModel.resolveMappingExpressible(selectionNodeType, this::findTableGroupByPath ); if ( expressible != null ) { return expressible; diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/mapping/collections/mapcompelem/MapCompositeElementTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/mapping/collections/mapcompelem/MapCompositeElementTest.java index 8ecd482ef4..246809974e 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/mapping/collections/mapcompelem/MapCompositeElementTest.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/mapping/collections/mapcompelem/MapCompositeElementTest.java @@ -9,7 +9,6 @@ package org.hibernate.orm.test.mapping.collections.mapcompelem; import java.util.List; import org.hibernate.testing.orm.junit.DomainModel; -import org.hibernate.testing.orm.junit.NotImplementedYet; import org.hibernate.testing.orm.junit.SessionFactory; import org.hibernate.testing.orm.junit.SessionFactoryScope; import org.junit.jupiter.api.Test; @@ -61,7 +60,6 @@ public class MapCompositeElementTest { @SuppressWarnings( {"unchecked"}) @Test - @NotImplementedYet( strict = false ) public void testQueryMapCompositeElement(SessionFactoryScope scope) { scope.inTransaction( (s) -> { Part top = new Part("top", "The top part");