HHH-17638 Prevent reusing left joins for implicitly joined paths

This commit is contained in:
Marco Belladelli 2024-01-19 15:23:30 +01:00
parent 86dad3d702
commit 18d88a4430
2 changed files with 21 additions and 4 deletions

View File

@ -3647,7 +3647,10 @@ 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.findTableGroupForGetOrCreate( sqmPath.getNavigablePath() ); final TableGroup existingTableGroup = fromClauseIndex.findTableGroupForGetOrCreate(
sqmPath.getNavigablePath(),
allowLeftJoins
);
if ( existingTableGroup == null ) { if ( existingTableGroup == null ) {
final TableGroup createdTableGroup = createTableGroup( final TableGroup createdTableGroup = createTableGroup(
getActualTableGroup( getActualTableGroup(
@ -3900,9 +3903,9 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
private boolean isMappedByOrNotFoundToOne(TableGroupJoinProducer joinProducer) { private boolean isMappedByOrNotFoundToOne(TableGroupJoinProducer joinProducer) {
if ( joinProducer instanceof ToOneAttributeMapping ) { if ( joinProducer instanceof ToOneAttributeMapping ) {
final ToOneAttributeMapping toOne = (ToOneAttributeMapping) joinProducer; final ToOneAttributeMapping toOne = (ToOneAttributeMapping) joinProducer;
if ( toOne.hasNotFoundAction() || toOne.getReferencedPropertyName() != null ) { return toOne.hasNotFoundAction() ||
return true; // ToOne( mappedBy = "..." ) always has a referenced property name and is the target side
} ( toOne.getReferencedPropertyName() != null && toOne.getSideNature() == ForeignKeyDescriptor.Nature.TARGET );
} }
return false; return false;
} }

View File

@ -9,11 +9,14 @@ 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.CollectionPart;
import org.hibernate.metamodel.model.domain.NavigableRole; import org.hibernate.metamodel.model.domain.NavigableRole;
import org.hibernate.spi.NavigablePath; import org.hibernate.spi.NavigablePath;
import org.hibernate.sql.ast.SqlAstJoinType;
import org.hibernate.sql.ast.SqlTreeCreationLogger; import org.hibernate.sql.ast.SqlTreeCreationLogger;
import org.hibernate.sql.ast.tree.from.CorrelatedTableGroup; import org.hibernate.sql.ast.tree.from.CorrelatedTableGroup;
import org.hibernate.sql.ast.tree.from.TableGroup; import org.hibernate.sql.ast.tree.from.TableGroup;
import org.hibernate.sql.ast.tree.from.TableGroupJoin;
import org.jboss.logging.Logger; import org.jboss.logging.Logger;
@ -83,6 +86,17 @@ public class SimpleFromClauseAccessImpl implements FromClauseAccess {
} }
} }
public TableGroup findTableGroupForGetOrCreate(NavigablePath navigablePath, boolean allowLeftJoins) {
final TableGroup tableGroup = findTableGroupForGetOrCreate( navigablePath );
if ( !allowLeftJoins && tableGroup != null && navigablePath.getParent() != null
&& CollectionPart.Nature.fromNameExact( navigablePath.getLocalName() ) == null ) {
// This is an implicitly joined path, do not reuse existing table group if it's left joined
final TableGroupJoin join = findTableGroup( navigablePath.getParent() ).findTableGroupJoin( tableGroup );
return join != null && join.getJoinType() == SqlAstJoinType.LEFT ? null : tableGroup;
}
return tableGroup;
}
private TableGroup getCorrelatedTableGroup(TableGroup tableGroup) { private TableGroup getCorrelatedTableGroup(TableGroup tableGroup) {
if ( tableGroup instanceof CorrelatedTableGroup ) { if ( tableGroup instanceof CorrelatedTableGroup ) {
return getCorrelatedTableGroup( ( (CorrelatedTableGroup) tableGroup ).getCorrelatedTableGroup() ); return getCorrelatedTableGroup( ( (CorrelatedTableGroup) tableGroup ).getCorrelatedTableGroup() );