Skip to content

Commit cb89514

Browse files
mbelladebeikov
authored andcommitted
HHH-18745 Avoid resolving unnecessary table references for subtypes
Also, handle type expressions in case statements like we do for comparison logic.
1 parent a92e0db commit cb89514

File tree

2 files changed

+42
-8
lines changed

2 files changed

+42
-8
lines changed

hibernate-core/src/main/java/org/hibernate/query/sqm/sql/BaseSqmToSqlAstConverter.java

Lines changed: 38 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3170,10 +3170,6 @@ else if ( useKind == EntityNameUse.UseKind.PROJECTION ) {
31703170
subType.getEntityName(),
31713171
(s, existingUse) -> finalEntityNameUse.stronger( existingUse )
31723172
);
3173-
actualTableGroup.resolveTableReference(
3174-
null,
3175-
subType.getEntityPersister().getMappedTableDetails().getTableName()
3176-
);
31773173
}
31783174
}
31793175
}
@@ -7141,6 +7137,8 @@ public CaseSimpleExpression visitSimpleCaseExpression(SqmCaseSimple<?, ?> expres
71417137
inferrableTypeAccessStack.push( () -> fixtureType );
71427138
final Expression checkValue = (Expression) whenFragment.getCheckValue().accept( this );
71437139
inferrableTypeAccessStack.pop();
7140+
handleTypeInCaseExpression( fixture, checkValue );
7141+
71447142
final MappingModelExpressible<?> alreadyKnown = resolved;
71457143
inferrableTypeAccessStack.push(
71467144
() -> alreadyKnown == null && inferenceSupplier != null ? inferenceSupplier.get() : alreadyKnown
@@ -7176,6 +7174,42 @@ public CaseSimpleExpression visitSimpleCaseExpression(SqmCaseSimple<?, ?> expres
71767174
);
71777175
}
71787176

7177+
private void handleTypeInCaseExpression(Expression fixture, Expression checkValue) {
7178+
if ( fixture instanceof DiscriminatorPathInterpretation<?> ) {
7179+
final DiscriminatorPathInterpretation<?> typeExpression = (DiscriminatorPathInterpretation<?>) fixture;
7180+
final TableGroup tableGroup = getFromClauseIndex().getTableGroup( typeExpression.getNavigablePath().getParent() );
7181+
final MappingType partMappingType = tableGroup.getModelPart().getPartMappingType();
7182+
if ( !(partMappingType instanceof EntityMappingType) ) {
7183+
return;
7184+
}
7185+
final EntityMappingType entityMappingType = (EntityMappingType) partMappingType;
7186+
if ( entityMappingType.getDiscriminatorMapping().hasPhysicalColumn() ) {
7187+
// If the entity type has a physical type column we only need to register an expression
7188+
// usage for the root type to prevent pruning the table where the discriminator is found
7189+
registerEntityNameUsage(
7190+
tableGroup,
7191+
EntityNameUse.EXPRESSION,
7192+
entityMappingType.getRootEntityDescriptor().getEntityName()
7193+
);
7194+
}
7195+
else if ( checkValue instanceof EntityTypeLiteral ) {
7196+
// Register an expression type usage for the literal subtype to prevent pruning its table group
7197+
registerEntityNameUsage(
7198+
tableGroup,
7199+
EntityNameUse.EXPRESSION,
7200+
( (EntityTypeLiteral) checkValue ).getEntityTypeDescriptor().getEntityName()
7201+
);
7202+
}
7203+
else {
7204+
// We have to assume all types are possible and can't do optimizations
7205+
registerEntityNameUsage( tableGroup, EntityNameUse.EXPRESSION, entityMappingType.getEntityName() );
7206+
for ( EntityMappingType subMappingType : entityMappingType.getSubMappingTypes() ) {
7207+
registerEntityNameUsage( tableGroup, EntityNameUse.EXPRESSION, subMappingType.getEntityName() );
7208+
}
7209+
}
7210+
}
7211+
}
7212+
71797213
@Override
71807214
public CaseSearchedExpression visitSearchedCaseExpression(SqmCaseSearched<?> expression) {
71817215
final List<CaseSearchedExpression.WhenFragment> whenFragments = new ArrayList<>( expression.getWhenFragments().size() );

hibernate-core/src/test/java/org/hibernate/orm/test/inheritance/discriminator/JoinedInheritanceDiscriminatorSelectionTest.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -141,28 +141,28 @@ public void testSelectInstance(SessionFactoryScope scope) {
141141
inspector.clear();
142142

143143
scope.inTransaction( session -> {
144-
// With type filters we still join all subclasses when selecting the entity instance
144+
// With type filters we still join all subclasses that have properties when selecting the entity instance
145145
// because we are not aware of the type restriction when processing the selection
146146

147147
assertThat( session.createQuery(
148148
"from ParentEntity p where type(p) = ParentEntity",
149149
ParentEntity.class
150150
).getResultList() ).hasSize( 1 );
151-
inspector.assertNumberOfJoins( 0, 3 );
151+
inspector.assertNumberOfJoins( 0, 2 );
152152
inspector.clear();
153153

154154
assertThat( session.createQuery(
155155
"from ParentEntity p where type(p) = ChildA",
156156
ParentEntity.class
157157
).getResultList() ).hasSize( 1 );
158-
inspector.assertNumberOfJoins( 0, 3 );
158+
inspector.assertNumberOfJoins( 0, 2 );
159159
inspector.clear();
160160

161161
assertThat( session.createQuery(
162162
"from ParentEntity p where type(p) = SubChildA",
163163
ParentEntity.class
164164
).getResultList() ).hasSize( 1 );
165-
inspector.assertNumberOfJoins( 0, 3 );
165+
inspector.assertNumberOfJoins( 0, 2 );
166166
inspector.clear();
167167

168168
// With treat() we only join the needed subclasses

0 commit comments

Comments
 (0)