HHH-15342 Inappropriate variation of HQL left join to SQL inner join
This commit is contained in:
parent
d553dea5a8
commit
985467bcba
|
@ -1196,8 +1196,32 @@ public class ToOneAttributeMapping
|
|||
|| fetchParent.getNavigablePath() instanceof TreatedNavigablePath
|
||||
&& parentNavigablePath.equals( fetchParent.getNavigablePath().getRealParent() );
|
||||
|
||||
/*
|
||||
In case of @NotFound we are going to add fetch for the `fetchablePath` only if there is not already a `TableGroupJoin`.
|
||||
|
||||
if ( (hasNotFoundAction()
|
||||
e.g. given :
|
||||
public static class EntityA {
|
||||
...
|
||||
|
||||
@ManyToOne(fetch = FetchType.LAZY)
|
||||
@NotFound(action = NotFoundAction.IGNORE)
|
||||
private EntityB entityB;
|
||||
}
|
||||
|
||||
@Entity(name = "EntityB")
|
||||
public static class EntityB {
|
||||
...
|
||||
|
||||
private String name;
|
||||
}
|
||||
|
||||
and the HQL query :
|
||||
|
||||
`Select a From EntityA a Left Join a.entityB b Where ( b.name IS NOT NULL )`
|
||||
|
||||
having the left join we don't want to add an extra implicit join that will be translated into an SQL inner join (see HHH-15342)
|
||||
*/
|
||||
if ( ( ( hasNotFoundAction() && doesNotExistATableGroupJoin( parentTableGroup, fetchablePath ) )
|
||||
|| ( fetchTiming == FetchTiming.IMMEDIATE && selected ) ) ) {
|
||||
final TableGroup tableGroup = determineTableGroup(
|
||||
fetchablePath,
|
||||
|
@ -1308,6 +1332,15 @@ public class ToOneAttributeMapping
|
|||
);
|
||||
}
|
||||
|
||||
private boolean doesNotExistATableGroupJoin(TableGroup parentTableGroup, NavigablePath fetchablePath) {
|
||||
for ( TableGroupJoin tableGroupJoin : parentTableGroup.getTableGroupJoins() ) {
|
||||
if ( tableGroupJoin.getNavigablePath().pathsMatch( fetchablePath ) ) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private TableGroup determineTableGroup(NavigablePath fetchablePath, FetchParent fetchParent, TableGroup parentTableGroup, String resultVariable, FromClauseAccess fromClauseAccess, DomainResultCreationState creationState) {
|
||||
final TableGroup tableGroup;
|
||||
if ( fetchParent instanceof EntityResultJoinedSubclassImpl
|
||||
|
@ -1321,6 +1354,10 @@ public class ToOneAttributeMapping
|
|||
false,
|
||||
creationState.getSqlAstCreationState()
|
||||
);
|
||||
if ( hasNotFoundAction() ) {
|
||||
tableGroupJoin.setImplicit();
|
||||
}
|
||||
|
||||
parentTableGroup.addTableGroupJoin( tableGroupJoin );
|
||||
tableGroup = tableGroupJoin.getJoinedGroup();
|
||||
fromClauseAccess.registerTableGroup( fetchablePath, tableGroup );
|
||||
|
@ -1338,6 +1375,9 @@ public class ToOneAttributeMapping
|
|||
false,
|
||||
creationState.getSqlAstCreationState()
|
||||
);
|
||||
if ( hasNotFoundAction() ) {
|
||||
tableGroupJoin.setImplicit();
|
||||
}
|
||||
parentTableGroup.addTableGroupJoin( tableGroupJoin );
|
||||
return tableGroupJoin.getJoinedGroup();
|
||||
}
|
||||
|
|
|
@ -3209,7 +3209,7 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
|
|||
final NavigablePath parentParentPath = parentPath.getParentPath().getNavigablePath();
|
||||
final TableGroup parentParentTableGroup = fromClauseIndex.findTableGroup( parentParentPath );
|
||||
parentParentTableGroup.visitTableGroupJoins( (join) -> {
|
||||
if ( join.getNavigablePath().equals( parentPath.getNavigablePath() ) ) {
|
||||
if ( join.getNavigablePath().equals( parentPath.getNavigablePath() ) && join.isImplicit() ) {
|
||||
join.setJoinType( SqlAstJoinType.INNER );
|
||||
}
|
||||
} );
|
||||
|
@ -3312,6 +3312,7 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
|
|||
false,
|
||||
this
|
||||
);
|
||||
tableGroupJoin.setImplicit();
|
||||
// Implicit joins in the ON clause of attribute joins need to be added as nested table group joins
|
||||
// We don't have to do that for entity joins etc. as these do not have an inherent dependency on the lhs.
|
||||
// We can just add the implicit join before the currently processing join
|
||||
|
|
|
@ -27,6 +27,8 @@ public class TableGroupJoin implements TableJoin, DomainResultProducer {
|
|||
private SqlAstJoinType joinType;
|
||||
private Predicate predicate;
|
||||
|
||||
private boolean implicit;
|
||||
|
||||
public TableGroupJoin(
|
||||
NavigablePath navigablePath,
|
||||
SqlAstJoinType joinType,
|
||||
|
@ -91,6 +93,14 @@ public class TableGroupJoin implements TableJoin, DomainResultProducer {
|
|||
return navigablePath;
|
||||
}
|
||||
|
||||
public void setImplicit(){
|
||||
this.implicit = true;
|
||||
}
|
||||
|
||||
public boolean isImplicit(){
|
||||
return implicit;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DomainResult createDomainResult(
|
||||
String resultVariable,
|
||||
|
|
|
@ -36,8 +36,6 @@ public class EntityFetchSelectImpl extends AbstractNonJoinedEntityFetch {
|
|||
@SuppressWarnings("unused") DomainResultCreationState creationState) {
|
||||
super( navigablePath, fetchedAttribute, fetchParent );
|
||||
|
||||
assert fetchedAttribute.getNotFoundAction() == null;
|
||||
|
||||
this.keyResult = keyResult;
|
||||
this.selectByUniqueKey = selectByUniqueKey;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue