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<?> if ( sqmPath instanceof SqmEntityValuedSimplePath<?>
|| sqmPath instanceof SqmEmbeddedValuedSimplePath<?> || sqmPath instanceof SqmEmbeddedValuedSimplePath<?>
|| sqmPath instanceof SqmAnyValuedSimplePath<?> ) { || sqmPath instanceof SqmAnyValuedSimplePath<?> ) {
final TableGroup existingTableGroup = fromClauseIndex.findTableGroup( sqmPath.getNavigablePath() ); final TableGroup existingTableGroup = fromClauseIndex.findTableGroupForGetOrCreate( sqmPath.getNavigablePath() );
if ( existingTableGroup == null ) { if ( existingTableGroup == null ) {
final TableGroup createdTableGroup = createTableGroup( final TableGroup createdTableGroup = createTableGroup(
fromClauseIndex.getTableGroup( sqmPath.getLhs().getNavigablePath() ), fromClauseIndex.getTableGroup( sqmPath.getLhs().getNavigablePath() ),
@ -3387,7 +3387,7 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
if ( parentPath == null ) { if ( parentPath == null ) {
return null; return null;
} }
final TableGroup tableGroup = fromClauseIndex.findTableGroup( parentPath.getNavigablePath() ); final TableGroup tableGroup = fromClauseIndex.findTableGroupForGetOrCreate( parentPath.getNavigablePath() );
if ( tableGroup == null ) { if ( tableGroup == null ) {
final TableGroup parentTableGroup = prepareReusablePath( final TableGroup parentTableGroup = prepareReusablePath(
fromClauseIndex, fromClauseIndex,
@ -3454,7 +3454,7 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
path = selectionPath; path = selectionPath;
} }
final FromClauseIndex fromClauseIndex = getFromClauseIndex(); final FromClauseIndex fromClauseIndex = getFromClauseIndex();
final TableGroup tableGroup = fromClauseIndex.findTableGroup( path.getNavigablePath() ); final TableGroup tableGroup = fromClauseIndex.findTableGroupForGetOrCreate( path.getNavigablePath() );
if ( tableGroup == null ) { if ( tableGroup == null ) {
prepareReusablePath( path, () -> null ); prepareReusablePath( path, () -> null );

View File

@ -33,6 +33,15 @@ public interface FromClauseAccess {
*/ */
TableGroup findTableGroup(NavigablePath navigablePath); 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 * Get a TableGroup by the NavigablePath it is registered under. If there is
* no registration, an exception is thrown. * no registration, an exception is thrown.
@ -62,7 +71,7 @@ public interface FromClauseAccess {
* @see #registerTableGroup * @see #registerTableGroup
*/ */
default TableGroup resolveTableGroup(NavigablePath navigablePath, Function<NavigablePath, TableGroup> creator) { default TableGroup resolveTableGroup(NavigablePath navigablePath, Function<NavigablePath, TableGroup> creator) {
TableGroup tableGroup = findTableGroup( navigablePath ); TableGroup tableGroup = findTableGroupForGetOrCreate( navigablePath );
if ( tableGroup == null ) { if ( tableGroup == null ) {
tableGroup = creator.apply( navigablePath ); tableGroup = creator.apply( navigablePath );
registerTableGroup( navigablePath, tableGroup ); registerTableGroup( navigablePath, tableGroup );

View File

@ -9,9 +9,12 @@ package org.hibernate.sql.ast.spi;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; 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.spi.NavigablePath;
import org.hibernate.sql.ast.SqlTreeCreationLogger; import org.hibernate.sql.ast.SqlTreeCreationLogger;
import org.hibernate.sql.ast.tree.from.TableGroup; import org.hibernate.sql.ast.tree.from.TableGroup;
import org.hibernate.sql.ast.tree.from.VirtualTableGroup;
import org.jboss.logging.Logger; import org.jboss.logging.Logger;
@ -47,6 +50,39 @@ public class SimpleFromClauseAccessImpl implements FromClauseAccess {
return parent.findTableGroup( navigablePath ); 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 @Override
public void registerTableGroup(NavigablePath navigablePath, TableGroup tableGroup) { public void registerTableGroup(NavigablePath navigablePath, TableGroup tableGroup) {
final Logger logger = SqlTreeCreationLogger.LOGGER; final Logger logger = SqlTreeCreationLogger.LOGGER;

View File

@ -47,6 +47,11 @@ public class MappedByTableGroup extends DelegatingTableGroup implements VirtualT
return underlyingTableGroup; return underlyingTableGroup;
} }
@Override
public TableGroup getUnderlyingTableGroup() {
return underlyingTableGroup;
}
@Override @Override
public NavigablePath getNavigablePath() { public NavigablePath getNavigablePath() {
return navigablePath; return navigablePath;

View File

@ -41,6 +41,11 @@ public class StandardVirtualTableGroup extends AbstractTableGroup implements Vir
return getModelPart(); return getModelPart();
} }
@Override
public TableGroup getUnderlyingTableGroup() {
return underlyingTableGroup;
}
@Override @Override
public boolean isFetched() { public boolean isFetched() {
return fetched; return fetched;

View File

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