Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -3170,10 +3170,6 @@ else if ( useKind == EntityNameUse.UseKind.PROJECTION ) {
subType.getEntityName(),
(s, existingUse) -> finalEntityNameUse.stronger( existingUse )
);
actualTableGroup.resolveTableReference(
null,
subType.getEntityPersister().getMappedTableDetails().getTableName()
);
}
}
}
Expand Down Expand Up @@ -7141,6 +7137,8 @@ public CaseSimpleExpression visitSimpleCaseExpression(SqmCaseSimple<?, ?> expres
inferrableTypeAccessStack.push( () -> fixtureType );
final Expression checkValue = (Expression) whenFragment.getCheckValue().accept( this );
inferrableTypeAccessStack.pop();
handleTypeInCaseExpression( fixture, checkValue );

final MappingModelExpressible<?> alreadyKnown = resolved;
inferrableTypeAccessStack.push(
() -> alreadyKnown == null && inferenceSupplier != null ? inferenceSupplier.get() : alreadyKnown
Expand Down Expand Up @@ -7176,6 +7174,42 @@ public CaseSimpleExpression visitSimpleCaseExpression(SqmCaseSimple<?, ?> expres
);
}

private void handleTypeInCaseExpression(Expression fixture, Expression checkValue) {
if ( fixture instanceof DiscriminatorPathInterpretation<?> ) {
final DiscriminatorPathInterpretation<?> typeExpression = (DiscriminatorPathInterpretation<?>) fixture;
final TableGroup tableGroup = getFromClauseIndex().getTableGroup( typeExpression.getNavigablePath().getParent() );
final MappingType partMappingType = tableGroup.getModelPart().getPartMappingType();
if ( !(partMappingType instanceof EntityMappingType) ) {
return;
}
final EntityMappingType entityMappingType = (EntityMappingType) partMappingType;
if ( entityMappingType.getDiscriminatorMapping().hasPhysicalColumn() ) {
// If the entity type has a physical type column we only need to register an expression
// usage for the root type to prevent pruning the table where the discriminator is found
registerEntityNameUsage(
tableGroup,
EntityNameUse.EXPRESSION,
entityMappingType.getRootEntityDescriptor().getEntityName()
);
}
else if ( checkValue instanceof EntityTypeLiteral ) {
// Register an expression type usage for the literal subtype to prevent pruning its table group
registerEntityNameUsage(
tableGroup,
EntityNameUse.EXPRESSION,
( (EntityTypeLiteral) checkValue ).getEntityTypeDescriptor().getEntityName()
);
}
else {
// We have to assume all types are possible and can't do optimizations
registerEntityNameUsage( tableGroup, EntityNameUse.EXPRESSION, entityMappingType.getEntityName() );
for ( EntityMappingType subMappingType : entityMappingType.getSubMappingTypes() ) {
registerEntityNameUsage( tableGroup, EntityNameUse.EXPRESSION, subMappingType.getEntityName() );
}
}
}
}

@Override
public CaseSearchedExpression visitSearchedCaseExpression(SqmCaseSearched<?> expression) {
final List<CaseSearchedExpression.WhenFragment> whenFragments = new ArrayList<>( expression.getWhenFragments().size() );
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
*/
package org.hibernate.orm.test.inheritance;

import org.hibernate.testing.jdbc.SQLStatementInspector;
import org.hibernate.testing.orm.junit.DomainModel;
import org.hibernate.testing.orm.junit.Jira;
import org.hibernate.testing.orm.junit.SessionFactory;
Expand All @@ -28,7 +29,7 @@
/**
* @author Marco Belladelli
*/
@SessionFactory
@SessionFactory( useCollectingStatementInspector = true )
@DomainModel( annotatedClasses = {
JoinedInheritanceTreatQueryTest.Product.class,
JoinedInheritanceTreatQueryTest.ProductOwner.class,
Expand All @@ -37,6 +38,7 @@
JoinedInheritanceTreatQueryTest.Description.class,
} )
@Jira( "https://hibernate.atlassian.net/browse/HHH-16574" )
@Jira( "https://hibernate.atlassian.net/browse/HHH-18745" )
public class JoinedInheritanceTreatQueryTest {
@BeforeAll
public void setUp(SessionFactoryScope scope) {
Expand All @@ -63,6 +65,8 @@ public void tearDown(SessionFactoryScope scope) {

@Test
public void testTreatedJoin(SessionFactoryScope scope) {
final SQLStatementInspector inspector = scope.getCollectingStatementInspector();
inspector.clear();
scope.inTransaction( session -> {
final Product result = session.createQuery(
"from Product p " +
Expand All @@ -72,11 +76,14 @@ public void testTreatedJoin(SessionFactoryScope scope) {
).getSingleResult();
assertThat( result.getOwner() ).isInstanceOf( ProductOwner1.class );
assertThat( ( (ProductOwner1) result.getOwner() ).getDescription().getText() ).isEqualTo( "description" );
inspector.assertNumberOfJoins( 0, 3 );
} );
}

@Test
public void testImplicitTreatedJoin(SessionFactoryScope scope) {
final SQLStatementInspector inspector = scope.getCollectingStatementInspector();
inspector.clear();
scope.inTransaction( session -> {
final Product result = session.createQuery(
"from Product p " +
Expand All @@ -85,11 +92,14 @@ public void testImplicitTreatedJoin(SessionFactoryScope scope) {
).getSingleResult();
assertThat( result.getOwner() ).isInstanceOf( ProductOwner1.class );
assertThat( ( (ProductOwner1) result.getOwner() ).getDescription().getText() ).isEqualTo( "description" );
inspector.assertNumberOfJoins( 0, 3 );
} );
}

@Test
public void testTreatedRoot(SessionFactoryScope scope) {
final SQLStatementInspector inspector = scope.getCollectingStatementInspector();
inspector.clear();
scope.inTransaction( session -> {
final ProductOwner result = session.createQuery(
"from ProductOwner owner " +
Expand All @@ -98,11 +108,14 @@ public void testTreatedRoot(SessionFactoryScope scope) {
).getSingleResult();
assertThat( result ).isInstanceOf( ProductOwner1.class );
assertThat( ( (ProductOwner1) result ).getDescription().getText() ).isEqualTo( "description" );
inspector.assertNumberOfJoins( 0, 3 );
} );
}

@Test
public void testTreatedEntityJoin(SessionFactoryScope scope) {
final SQLStatementInspector inspector = scope.getCollectingStatementInspector();
inspector.clear();
scope.inTransaction( session -> {
final Product result = session.createQuery(
"from Product p " +
Expand All @@ -112,11 +125,14 @@ public void testTreatedEntityJoin(SessionFactoryScope scope) {
).getSingleResult();
assertThat( result.getOwner() ).isInstanceOf( ProductOwner1.class );
assertThat( ( (ProductOwner1) result.getOwner() ).getDescription().getText() ).isEqualTo( "description" );
inspector.assertNumberOfJoins( 0, 3 );
} );
}

@Test
public void testBasicProperty(SessionFactoryScope scope) {
final SQLStatementInspector inspector = scope.getCollectingStatementInspector();
inspector.clear();
scope.inTransaction( session -> {
final Product result = session.createQuery(
"from Product p " +
Expand All @@ -126,6 +142,7 @@ public void testBasicProperty(SessionFactoryScope scope) {
).getSingleResult();
assertThat( result.getOwner() ).isInstanceOf( ProductOwner2.class );
assertThat( ( (ProductOwner2) result.getOwner() ).getBasicProp() ).isEqualTo( "basic_prop" );
inspector.assertNumberOfJoins( 0, 2 );
} );
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -141,28 +141,28 @@ public void testSelectInstance(SessionFactoryScope scope) {
inspector.clear();

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

assertThat( session.createQuery(
"from ParentEntity p where type(p) = ParentEntity",
ParentEntity.class
).getResultList() ).hasSize( 1 );
inspector.assertNumberOfJoins( 0, 3 );
inspector.assertNumberOfJoins( 0, 2 );
inspector.clear();

assertThat( session.createQuery(
"from ParentEntity p where type(p) = ChildA",
ParentEntity.class
).getResultList() ).hasSize( 1 );
inspector.assertNumberOfJoins( 0, 3 );
inspector.assertNumberOfJoins( 0, 2 );
inspector.clear();

assertThat( session.createQuery(
"from ParentEntity p where type(p) = SubChildA",
ParentEntity.class
).getResultList() ).hasSize( 1 );
inspector.assertNumberOfJoins( 0, 3 );
inspector.assertNumberOfJoins( 0, 2 );
inspector.clear();

// With treat() we only join the needed subclasses
Expand Down
Loading