HHH-15342 Inappropriate variation of HQL left join to SQL inner join
This commit is contained in:
parent
d553dea5a8
commit
985467bcba
|
@ -1196,9 +1196,33 @@ public class ToOneAttributeMapping
|
||||||
|| fetchParent.getNavigablePath() instanceof TreatedNavigablePath
|
|| fetchParent.getNavigablePath() instanceof TreatedNavigablePath
|
||||||
&& parentNavigablePath.equals( fetchParent.getNavigablePath().getRealParent() );
|
&& 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 :
|
||||||
|| ( fetchTiming == FetchTiming.IMMEDIATE && selected )) ) {
|
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(
|
final TableGroup tableGroup = determineTableGroup(
|
||||||
fetchablePath,
|
fetchablePath,
|
||||||
fetchParent,
|
fetchParent,
|
||||||
|
@ -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) {
|
private TableGroup determineTableGroup(NavigablePath fetchablePath, FetchParent fetchParent, TableGroup parentTableGroup, String resultVariable, FromClauseAccess fromClauseAccess, DomainResultCreationState creationState) {
|
||||||
final TableGroup tableGroup;
|
final TableGroup tableGroup;
|
||||||
if ( fetchParent instanceof EntityResultJoinedSubclassImpl
|
if ( fetchParent instanceof EntityResultJoinedSubclassImpl
|
||||||
|
@ -1321,6 +1354,10 @@ public class ToOneAttributeMapping
|
||||||
false,
|
false,
|
||||||
creationState.getSqlAstCreationState()
|
creationState.getSqlAstCreationState()
|
||||||
);
|
);
|
||||||
|
if ( hasNotFoundAction() ) {
|
||||||
|
tableGroupJoin.setImplicit();
|
||||||
|
}
|
||||||
|
|
||||||
parentTableGroup.addTableGroupJoin( tableGroupJoin );
|
parentTableGroup.addTableGroupJoin( tableGroupJoin );
|
||||||
tableGroup = tableGroupJoin.getJoinedGroup();
|
tableGroup = tableGroupJoin.getJoinedGroup();
|
||||||
fromClauseAccess.registerTableGroup( fetchablePath, tableGroup );
|
fromClauseAccess.registerTableGroup( fetchablePath, tableGroup );
|
||||||
|
@ -1338,6 +1375,9 @@ public class ToOneAttributeMapping
|
||||||
false,
|
false,
|
||||||
creationState.getSqlAstCreationState()
|
creationState.getSqlAstCreationState()
|
||||||
);
|
);
|
||||||
|
if ( hasNotFoundAction() ) {
|
||||||
|
tableGroupJoin.setImplicit();
|
||||||
|
}
|
||||||
parentTableGroup.addTableGroupJoin( tableGroupJoin );
|
parentTableGroup.addTableGroupJoin( tableGroupJoin );
|
||||||
return tableGroupJoin.getJoinedGroup();
|
return tableGroupJoin.getJoinedGroup();
|
||||||
}
|
}
|
||||||
|
|
|
@ -3209,7 +3209,7 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
|
||||||
final NavigablePath parentParentPath = parentPath.getParentPath().getNavigablePath();
|
final NavigablePath parentParentPath = parentPath.getParentPath().getNavigablePath();
|
||||||
final TableGroup parentParentTableGroup = fromClauseIndex.findTableGroup( parentParentPath );
|
final TableGroup parentParentTableGroup = fromClauseIndex.findTableGroup( parentParentPath );
|
||||||
parentParentTableGroup.visitTableGroupJoins( (join) -> {
|
parentParentTableGroup.visitTableGroupJoins( (join) -> {
|
||||||
if ( join.getNavigablePath().equals( parentPath.getNavigablePath() ) ) {
|
if ( join.getNavigablePath().equals( parentPath.getNavigablePath() ) && join.isImplicit() ) {
|
||||||
join.setJoinType( SqlAstJoinType.INNER );
|
join.setJoinType( SqlAstJoinType.INNER );
|
||||||
}
|
}
|
||||||
} );
|
} );
|
||||||
|
@ -3312,6 +3312,7 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
|
||||||
false,
|
false,
|
||||||
this
|
this
|
||||||
);
|
);
|
||||||
|
tableGroupJoin.setImplicit();
|
||||||
// Implicit joins in the ON clause of attribute joins need to be added as nested table group joins
|
// 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 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
|
// 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 SqlAstJoinType joinType;
|
||||||
private Predicate predicate;
|
private Predicate predicate;
|
||||||
|
|
||||||
|
private boolean implicit;
|
||||||
|
|
||||||
public TableGroupJoin(
|
public TableGroupJoin(
|
||||||
NavigablePath navigablePath,
|
NavigablePath navigablePath,
|
||||||
SqlAstJoinType joinType,
|
SqlAstJoinType joinType,
|
||||||
|
@ -91,6 +93,14 @@ public class TableGroupJoin implements TableJoin, DomainResultProducer {
|
||||||
return navigablePath;
|
return navigablePath;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setImplicit(){
|
||||||
|
this.implicit = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isImplicit(){
|
||||||
|
return implicit;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public DomainResult createDomainResult(
|
public DomainResult createDomainResult(
|
||||||
String resultVariable,
|
String resultVariable,
|
||||||
|
|
|
@ -36,8 +36,6 @@ public class EntityFetchSelectImpl extends AbstractNonJoinedEntityFetch {
|
||||||
@SuppressWarnings("unused") DomainResultCreationState creationState) {
|
@SuppressWarnings("unused") DomainResultCreationState creationState) {
|
||||||
super( navigablePath, fetchedAttribute, fetchParent );
|
super( navigablePath, fetchedAttribute, fetchParent );
|
||||||
|
|
||||||
assert fetchedAttribute.getNotFoundAction() == null;
|
|
||||||
|
|
||||||
this.keyResult = keyResult;
|
this.keyResult = keyResult;
|
||||||
this.selectByUniqueKey = selectByUniqueKey;
|
this.selectByUniqueKey = selectByUniqueKey;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue