HHH-16003 Create correct table group for embedded valued paths

This commit is contained in:
Marco Belladelli 2023-01-30 18:23:51 +01:00 committed by Christian Beikov
parent 2e3a18a3c6
commit e884ab3082
6 changed files with 60 additions and 4 deletions

View File

@ -3351,7 +3351,7 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> 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<T extends Statement> 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<T extends Statement> 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 );

View File

@ -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<NavigablePath, TableGroup> creator) {
TableGroup tableGroup = findTableGroup( navigablePath );
TableGroup tableGroup = findTableGroupForGetOrCreate( navigablePath );
if ( tableGroup == null ) {
tableGroup = creator.apply( navigablePath );
registerTableGroup( navigablePath, tableGroup );

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -13,4 +13,5 @@ package org.hibernate.sql.ast.tree.from;
* @author Steve Ebersole
*/
public interface VirtualTableGroup extends TableGroup {
TableGroup getUnderlyingTableGroup();
}