HHH-18330 Check model part when reusing table group for to-one fetch

This commit is contained in:
Marco Belladelli 2024-07-09 10:58:22 +02:00
parent c27ec0fd29
commit 8d39709cec
1 changed files with 52 additions and 45 deletions

View File

@ -1741,52 +1741,59 @@ public class ToOneAttributeMapping
else {
joinType = null;
}
return fromClauseAccess.resolveTableGroup(
fetchablePath,
np -> {
// Try to reuse an existing join if possible,
// and note that we prefer reusing an inner over a left join,
// because a left join might stay uninitialized if unused
TableGroup leftJoined = null;
for ( TableGroupJoin tableGroupJoin : parentTableGroup.getTableGroupJoins() ) {
switch ( tableGroupJoin.getJoinType() ) {
case INNER:
// If this is an inner joins, it's fine if the paths match
// Since this inner join would filter the parent row anyway,
// it makes no sense to add another left join for this association
if ( tableGroupJoin.getNavigablePath().pathsMatch( np ) ) {
return tableGroupJoin.getJoinedGroup();
}
break;
case LEFT:
// For an existing left join on the other hand which is row preserving,
// it is important to check if the predicate has user defined bits in it
// and only if it doesn't, we can reuse the join
if ( tableGroupJoin.getNavigablePath().pathsMatch( np )
&& isSimpleJoinPredicate( tableGroupJoin.getPredicate() ) ) {
leftJoined = tableGroupJoin.getJoinedGroup();
}
}
}
if ( leftJoined != null ) {
return leftJoined;
}
final TableGroupJoin tableGroupJoin = createTableGroupJoin(
fetchablePath,
parentTableGroup,
resultVariable,
null,
joinType,
true,
false,
creationState.getSqlAstCreationState()
);
parentTableGroup.addTableGroupJoin( tableGroupJoin );
return tableGroupJoin.getJoinedGroup();
}
final TableGroup existingTableGroup = fromClauseAccess.findTableGroupForGetOrCreate(
fetchablePath
);
if ( existingTableGroup != null && existingTableGroup.getModelPart() == this ) {
return existingTableGroup;
}
else {
// Try to reuse an existing join if possible,
// and note that we prefer reusing an inner over a left join,
// because a left join might stay uninitialized if unused
TableGroup leftJoined = null;
for ( TableGroupJoin tableGroupJoin : parentTableGroup.getTableGroupJoins() ) {
if ( tableGroupJoin.getJoinedGroup().getModelPart() == this ) {
switch ( tableGroupJoin.getJoinType() ) {
case INNER:
// If this is an inner joins, it's fine if the paths match
// Since this inner join would filter the parent row anyway,
// it makes no sense to add another left join for this association
if ( tableGroupJoin.getNavigablePath().pathsMatch( fetchablePath ) ) {
return tableGroupJoin.getJoinedGroup();
}
break;
case LEFT:
// For an existing left join on the other hand which is row preserving,
// it is important to check if the predicate has user defined bits in it
// and only if it doesn't, we can reuse the join
if ( tableGroupJoin.getNavigablePath().pathsMatch( fetchablePath )
&& isSimpleJoinPredicate( tableGroupJoin.getPredicate() ) ) {
leftJoined = tableGroupJoin.getJoinedGroup();
}
}
}
}
if ( leftJoined != null ) {
return leftJoined;
}
final TableGroupJoin tableGroupJoin = createTableGroupJoin(
fetchablePath,
parentTableGroup,
resultVariable,
null,
joinType,
true,
false,
creationState.getSqlAstCreationState()
);
parentTableGroup.addTableGroupJoin( tableGroupJoin );
final TableGroup joinedGroup = tableGroupJoin.getJoinedGroup();
fromClauseAccess.registerTableGroup( fetchablePath, joinedGroup );
return joinedGroup;
}
}
private TableGroup createTableGroupForDelayedFetch(