From e60d2c878b8dbad1d694c01e1a18424f951c2d31 Mon Sep 17 00:00:00 2001 From: Marco Belladelli Date: Wed, 26 Apr 2023 16:37:25 +0200 Subject: [PATCH] HHH-16397 Allow fk optimization for correlated paths in subqueries --- .../internal/ToOneAttributeMapping.java | 8 +++---- .../EntityValuedPathInterpretation.java | 24 ++----------------- .../sql/ast/spi/AbstractSqlAstTranslator.java | 2 +- 3 files changed, 7 insertions(+), 27 deletions(-) diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/ToOneAttributeMapping.java b/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/ToOneAttributeMapping.java index 7dfe0ed28a..ef3418b36e 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/ToOneAttributeMapping.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/ToOneAttributeMapping.java @@ -2058,9 +2058,9 @@ public class ToOneAttributeMapping } final TableGroupProducer tableGroupProducer; - if ( realParentTableGroup instanceof CorrelatedTableGroup ) { - // If the parent is a correlated table group, we can't refer to columns of the table in the outer query, - // because the context in which a column is used could be an aggregate function. + if ( requestedJoinType != null && realParentTableGroup instanceof CorrelatedTableGroup ) { + // If the parent is a correlated table group, and we're explicitly joining, we can't refer to columns of the + // table in the outer query, because the context in which a column is used could be an aggregate function. // Using a parent column in such a case would lead to an error if the parent query lacks a proper group by tableGroupProducer = entityMappingType; } @@ -2105,7 +2105,7 @@ public class ToOneAttributeMapping ); } - if ( realParentTableGroup instanceof CorrelatedTableGroup ) { + if ( requestedJoinType != null && realParentTableGroup instanceof CorrelatedTableGroup ) { // Force initialization of the underlying table group join to retain cardinality lazyTableGroup.getPrimaryTableReference(); } 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 e0b593752b..69b9a42a85 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 @@ -208,13 +208,8 @@ public class EntityValuedPathInterpretation extends AbstractSqmPathInterpreta .findTableGroup( tableGroup.getNavigablePath().getParent() ); } else { - if ( isCorrelated( tableGroup, sqlAstCreationState ) - || !tableGroup.getNavigablePath().isParentOrEqual( navigablePath ) ) { - // Access to the parent table group is forbidden for correlated table groups. For more details, - // see: `ToOneAttributeMapping.createRootTableGroupJoin` - // Due to that, we forcefully use the model part to which this association points to i.e. the target - - // Also force the use of the FK target key if the navigable path for this entity valued path is + if ( !tableGroup.getNavigablePath().isParentOrEqual( navigablePath ) ) { + // Force the use of the FK target key if the navigable path for this entity valued path is // not equal to or a child of the table group navigable path. // This can happen when using an implicit join path e.g. `where root.association.id is null`, // yet also an explicit join was made which is compatible e.g. `join fetch root.association`. @@ -261,21 +256,6 @@ public class EntityValuedPathInterpretation extends AbstractSqmPathInterpreta ); } - private static boolean isCorrelated(TableGroup tableGroup, SqmToSqlAstConverter sqlAstCreationState) { - final SqlAstProcessingState processingState = sqlAstCreationState.getCurrentProcessingState(); - if ( !( processingState instanceof SqlAstQueryPartProcessingState ) - || ( (SqlAstQueryPartProcessingState) processingState ).getInflightQueryPart().isRoot() ) { - return false; - } - final FromClauseAccess fromClauseAccess = sqlAstCreationState.getFromClauseAccess(); - - TableGroup realParentTableGroup = fromClauseAccess.findTableGroup( tableGroup.getNavigablePath().getParent() ); - while ( realParentTableGroup.getModelPart() instanceof EmbeddableValuedModelPart ) { - realParentTableGroup = fromClauseAccess.findTableGroup( realParentTableGroup.getNavigablePath().getParent() ); - } - return realParentTableGroup instanceof CorrelatedTableGroup; - } - private static boolean hasNotFound(EntityValuedModelPart mapping) { return mapping instanceof ToOneAttributeMapping && ( (ToOneAttributeMapping) mapping ).hasNotFoundAction(); } diff --git a/hibernate-core/src/main/java/org/hibernate/sql/ast/spi/AbstractSqlAstTranslator.java b/hibernate-core/src/main/java/org/hibernate/sql/ast/spi/AbstractSqlAstTranslator.java index 23fe0c4629..0c456545a4 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/ast/spi/AbstractSqlAstTranslator.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/ast/spi/AbstractSqlAstTranslator.java @@ -5128,7 +5128,7 @@ public abstract class AbstractSqlAstTranslator implemen separator = renderFromClauseRoot( tableGroupJoin.getJoinedGroup(), separator ); } } - else { + else if ( root.isInitialized() ) { appendSql( separator ); renderRootTableGroup( root, null ); separator = COMA_SEPARATOR;