HHH-16505 Avoid using the FK for left joins with condition

This commit is contained in:
Marco Belladelli 2023-05-02 10:52:58 +02:00
parent 6a659a7f32
commit a7e3c8c7e9
1 changed files with 10 additions and 2 deletions

View File

@ -235,6 +235,7 @@ import org.hibernate.query.sqm.tree.from.SqmEntityJoin;
import org.hibernate.query.sqm.tree.from.SqmFrom; import org.hibernate.query.sqm.tree.from.SqmFrom;
import org.hibernate.query.sqm.tree.from.SqmFromClause; import org.hibernate.query.sqm.tree.from.SqmFromClause;
import org.hibernate.query.sqm.tree.from.SqmJoin; import org.hibernate.query.sqm.tree.from.SqmJoin;
import org.hibernate.query.sqm.tree.from.SqmQualifiedJoin;
import org.hibernate.query.sqm.tree.from.SqmRoot; import org.hibernate.query.sqm.tree.from.SqmRoot;
import org.hibernate.query.sqm.tree.insert.SqmInsertSelectStatement; import org.hibernate.query.sqm.tree.insert.SqmInsertSelectStatement;
import org.hibernate.query.sqm.tree.insert.SqmInsertStatement; import org.hibernate.query.sqm.tree.insert.SqmInsertStatement;
@ -3696,6 +3697,10 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
throw new InterpretationException( "SqmEntityJoin not yet resolved to TableGroup" ); throw new InterpretationException( "SqmEntityJoin not yet resolved to TableGroup" );
} }
private boolean isJoinWithPredicate(SqmFrom<?, ?> path) {
return path instanceof SqmQualifiedJoin && ( (SqmQualifiedJoin<?, ?>) path ).getJoinPredicate() != null;
}
private Expression visitTableGroup(TableGroup tableGroup, SqmFrom<?, ?> path) { private Expression visitTableGroup(TableGroup tableGroup, SqmFrom<?, ?> path) {
final ModelPartContainer tableGroupModelPart = tableGroup.getModelPart(); final ModelPartContainer tableGroupModelPart = tableGroup.getModelPart();
@ -3720,9 +3725,12 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
if ( inferredEntityMapping == null ) { if ( inferredEntityMapping == null ) {
// When the inferred mapping is null, we try to resolve to the FK by default, which is fine because // When the inferred mapping is null, we try to resolve to the FK by default, which is fine because
// expansion to all target columns for select and group by clauses is handled in EntityValuedPathInterpretation // expansion to all target columns for select and group by clauses is handled in EntityValuedPathInterpretation
if ( entityValuedModelPart instanceof EntityAssociationMapping && ( (EntityAssociationMapping) entityValuedModelPart ).isFkOptimizationAllowed() ) { if ( entityValuedModelPart instanceof EntityAssociationMapping
&& ( (EntityAssociationMapping) entityValuedModelPart ).isFkOptimizationAllowed()
&& !isJoinWithPredicate( path ) ) {
// If the table group uses an association mapping that is not a one-to-many, // If the table group uses an association mapping that is not a one-to-many,
// we make use of the FK model part // we make use of the FK model part - unless the path is a join with an explicit predicate,
// for which we should always use the target's identifier to preserve semantics
final EntityAssociationMapping associationMapping = (EntityAssociationMapping) entityValuedModelPart; final EntityAssociationMapping associationMapping = (EntityAssociationMapping) entityValuedModelPart;
final ModelPart targetPart = associationMapping.getForeignKeyDescriptor().getPart( final ModelPart targetPart = associationMapping.getForeignKeyDescriptor().getPart(
associationMapping.getSideNature() associationMapping.getSideNature()