From e884ab3082eea99beeab0756e6658ff01d03d991 Mon Sep 17 00:00:00 2001 From: Marco Belladelli Date: Mon, 30 Jan 2023 18:23:51 +0100 Subject: [PATCH] HHH-16003 Create correct table group for embedded valued paths --- .../sqm/sql/BaseSqmToSqlAstConverter.java | 6 ++-- .../sql/ast/spi/FromClauseAccess.java | 11 +++++- .../ast/spi/SimpleFromClauseAccessImpl.java | 36 +++++++++++++++++++ .../sql/ast/tree/from/MappedByTableGroup.java | 5 +++ .../tree/from/StandardVirtualTableGroup.java | 5 +++ .../sql/ast/tree/from/VirtualTableGroup.java | 1 + 6 files changed, 60 insertions(+), 4 deletions(-) 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 2af562ee18..c85e62bfe7 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 @@ -3351,7 +3351,7 @@ public abstract class BaseSqmToSqlAstConverter extends Base if ( sqmPath instanceof SqmEntityValuedSimplePath || sqmPath instanceof SqmEmbeddedValuedSimplePath || sqmPath instanceof SqmAnyValuedSimplePath ) { - final TableGroup existingTableGroup = fromClauseIndex.findTableGroup( sqmPath.getNavigablePath() ); + final TableGroup existingTableGroup = fromClauseIndex.findTableGroupForGetOrCreate( sqmPath.getNavigablePath() ); if ( existingTableGroup == null ) { final TableGroup createdTableGroup = createTableGroup( fromClauseIndex.getTableGroup( sqmPath.getLhs().getNavigablePath() ), @@ -3387,7 +3387,7 @@ public abstract class BaseSqmToSqlAstConverter extends Base if ( parentPath == null ) { return null; } - final TableGroup tableGroup = fromClauseIndex.findTableGroup( parentPath.getNavigablePath() ); + final TableGroup tableGroup = fromClauseIndex.findTableGroupForGetOrCreate( parentPath.getNavigablePath() ); if ( tableGroup == null ) { final TableGroup parentTableGroup = prepareReusablePath( fromClauseIndex, @@ -3454,7 +3454,7 @@ public abstract class BaseSqmToSqlAstConverter extends Base path = selectionPath; } final FromClauseIndex fromClauseIndex = getFromClauseIndex(); - final TableGroup tableGroup = fromClauseIndex.findTableGroup( path.getNavigablePath() ); + final TableGroup tableGroup = fromClauseIndex.findTableGroupForGetOrCreate( path.getNavigablePath() ); if ( tableGroup == null ) { prepareReusablePath( path, () -> null ); diff --git a/hibernate-core/src/main/java/org/hibernate/sql/ast/spi/FromClauseAccess.java b/hibernate-core/src/main/java/org/hibernate/sql/ast/spi/FromClauseAccess.java index 391ef8fd5a..a31a1d93f0 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/ast/spi/FromClauseAccess.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/ast/spi/FromClauseAccess.java @@ -33,6 +33,15 @@ public interface FromClauseAccess { */ TableGroup findTableGroup(NavigablePath navigablePath); + /** + * Find the TableGroup by the NavigablePath for the purpose of creating a + * new TableGroup if none can be found. Returns {@code null} if no TableGroup + * or parent table group is registered under that NavigablePath + */ + default TableGroup findTableGroupForGetOrCreate(NavigablePath navigablePath) { + return findTableGroup( navigablePath ); + } + /** * Get a TableGroup by the NavigablePath it is registered under. If there is * no registration, an exception is thrown. @@ -62,7 +71,7 @@ public interface FromClauseAccess { * @see #registerTableGroup */ default TableGroup resolveTableGroup(NavigablePath navigablePath, Function creator) { - TableGroup tableGroup = findTableGroup( navigablePath ); + TableGroup tableGroup = findTableGroupForGetOrCreate( navigablePath ); if ( tableGroup == null ) { tableGroup = creator.apply( navigablePath ); registerTableGroup( navigablePath, tableGroup ); diff --git a/hibernate-core/src/main/java/org/hibernate/sql/ast/spi/SimpleFromClauseAccessImpl.java b/hibernate-core/src/main/java/org/hibernate/sql/ast/spi/SimpleFromClauseAccessImpl.java index 0c36f6be7c..2fb244350b 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/ast/spi/SimpleFromClauseAccessImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/ast/spi/SimpleFromClauseAccessImpl.java @@ -9,9 +9,12 @@ package org.hibernate.sql.ast.spi; import java.util.HashMap; import java.util.Map; +import org.hibernate.metamodel.mapping.EmbeddableValuedModelPart; +import org.hibernate.metamodel.model.domain.NavigableRole; import org.hibernate.spi.NavigablePath; import org.hibernate.sql.ast.SqlTreeCreationLogger; import org.hibernate.sql.ast.tree.from.TableGroup; +import org.hibernate.sql.ast.tree.from.VirtualTableGroup; import org.jboss.logging.Logger; @@ -47,6 +50,39 @@ public class SimpleFromClauseAccessImpl implements FromClauseAccess { return parent.findTableGroup( navigablePath ); } + @Override + public TableGroup findTableGroupForGetOrCreate(NavigablePath navigablePath) { + final TableGroup tableGroup = findTableGroup( navigablePath ); + if ( parent != null && tableGroup instanceof VirtualTableGroup && tableGroup.getModelPart() instanceof EmbeddableValuedModelPart ) { + final NavigableRole navigableRole = tableGroup.getModelPart().getNavigableRole(); + if ( navigableRole != null ) { + // Traverse up the navigable path to the point where resolving the path leads us to a regular TableGroup + NavigableRole parentRole = navigableRole.getParent(); + NavigablePath parentPath = navigablePath.getParent(); + while ( parentRole.getParent() != null ) { + parentRole = parentRole.getParent(); + parentPath = parentPath.getParent(); + } + // Only return the TableGroup if its regular parent TableGroup corresponds to the underlying one + if ( findTableGroup( parentPath ) == getUnderlyingTableGroup( (VirtualTableGroup) tableGroup ) ) { + return tableGroup; + } + else { + return null; + } + } + } + return tableGroup; + } + + private TableGroup getUnderlyingTableGroup(VirtualTableGroup virtualTableGroup) { + final TableGroup tableGroup = virtualTableGroup.getUnderlyingTableGroup(); + if ( tableGroup instanceof VirtualTableGroup ) { + return getUnderlyingTableGroup( (VirtualTableGroup) tableGroup ); + } + return tableGroup; + } + @Override public void registerTableGroup(NavigablePath navigablePath, TableGroup tableGroup) { final Logger logger = SqlTreeCreationLogger.LOGGER; diff --git a/hibernate-core/src/main/java/org/hibernate/sql/ast/tree/from/MappedByTableGroup.java b/hibernate-core/src/main/java/org/hibernate/sql/ast/tree/from/MappedByTableGroup.java index de76d468c0..b7a1b290fe 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/ast/tree/from/MappedByTableGroup.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/ast/tree/from/MappedByTableGroup.java @@ -47,6 +47,11 @@ public class MappedByTableGroup extends DelegatingTableGroup implements VirtualT return underlyingTableGroup; } + @Override + public TableGroup getUnderlyingTableGroup() { + return underlyingTableGroup; + } + @Override public NavigablePath getNavigablePath() { return navigablePath; diff --git a/hibernate-core/src/main/java/org/hibernate/sql/ast/tree/from/StandardVirtualTableGroup.java b/hibernate-core/src/main/java/org/hibernate/sql/ast/tree/from/StandardVirtualTableGroup.java index 1c06dd9ff0..a4f75c7ffe 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/ast/tree/from/StandardVirtualTableGroup.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/ast/tree/from/StandardVirtualTableGroup.java @@ -41,6 +41,11 @@ public class StandardVirtualTableGroup extends AbstractTableGroup implements Vir return getModelPart(); } + @Override + public TableGroup getUnderlyingTableGroup() { + return underlyingTableGroup; + } + @Override public boolean isFetched() { return fetched; diff --git a/hibernate-core/src/main/java/org/hibernate/sql/ast/tree/from/VirtualTableGroup.java b/hibernate-core/src/main/java/org/hibernate/sql/ast/tree/from/VirtualTableGroup.java index f705d4e1d2..ae1769354b 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/ast/tree/from/VirtualTableGroup.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/ast/tree/from/VirtualTableGroup.java @@ -13,4 +13,5 @@ package org.hibernate.sql.ast.tree.from; * @author Steve Ebersole */ public interface VirtualTableGroup extends TableGroup { + TableGroup getUnderlyingTableGroup(); }