HHH-16657 Propagate PROJECTION entity name use from subquery to outer table group
This commit is contained in:
parent
7f5ebc207e
commit
4795b94f68
|
@ -2973,14 +2973,20 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
|
|||
return;
|
||||
}
|
||||
final TableGroup actualTableGroup;
|
||||
final EntityNameUse finalEntityNameUse;
|
||||
if ( tableGroup instanceof PluralTableGroup ) {
|
||||
actualTableGroup = ( (PluralTableGroup) tableGroup ).getElementTableGroup();
|
||||
finalEntityNameUse = entityNameUse;
|
||||
}
|
||||
else if ( tableGroup instanceof CorrelatedTableGroup ) {
|
||||
actualTableGroup = ( (CorrelatedTableGroup) tableGroup ).getCorrelatedTableGroup();
|
||||
// For correlated table groups we can't apply filters,
|
||||
// as the context is in which the use happens may only affect the result of the subquery
|
||||
finalEntityNameUse = entityNameUse == EntityNameUse.EXPRESSION ? entityNameUse : EntityNameUse.PROJECTION;
|
||||
}
|
||||
else {
|
||||
actualTableGroup = tableGroup;
|
||||
finalEntityNameUse = entityNameUse;
|
||||
}
|
||||
final Map<String, EntityNameUse> entityNameUses = tableGroupEntityNameUses.computeIfAbsent(
|
||||
actualTableGroup,
|
||||
|
@ -2988,13 +2994,13 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
|
|||
);
|
||||
entityNameUses.compute(
|
||||
hibernateEntityName,
|
||||
(s, existingUse) -> entityNameUse.stronger( existingUse )
|
||||
(s, existingUse) -> finalEntityNameUse.stronger( existingUse )
|
||||
);
|
||||
|
||||
// Resolve the table reference for all types which we register an entity name use for
|
||||
actualTableGroup.resolveTableReference( null, persister.getTableName() );
|
||||
|
||||
if ( entityNameUse == EntityNameUse.PROJECTION ) {
|
||||
if ( finalEntityNameUse == EntityNameUse.PROJECTION ) {
|
||||
// For projections also register uses of all super and subtypes,
|
||||
// as well as resolve the respective table references
|
||||
EntityMappingType superMappingType = persister;
|
||||
|
@ -3014,7 +3020,7 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
|
|||
actualTableGroup.resolveTableReference( null, persister.getSubclassTableName( i ) );
|
||||
}
|
||||
}
|
||||
else if ( entityNameUse == EntityNameUse.TREAT ) {
|
||||
else if ( finalEntityNameUse == EntityNameUse.TREAT ) {
|
||||
// If we encounter a treat use, we also want register the use for all subtypes.
|
||||
// We do this here to not have to expand entity name uses during pruning later on
|
||||
for ( EntityMappingType subType : persister.getSubMappingTypes() ) {
|
||||
|
|
|
@ -15,19 +15,27 @@ import jakarta.persistence.GeneratedValue;
|
|||
import jakarta.persistence.Id;
|
||||
import jakarta.persistence.criteria.CriteriaBuilder;
|
||||
import jakarta.persistence.criteria.CriteriaQuery;
|
||||
import jakarta.persistence.criteria.Join;
|
||||
import jakarta.persistence.criteria.Root;
|
||||
import jakarta.persistence.criteria.Subquery;
|
||||
import jakarta.persistence.metamodel.EntityType;
|
||||
|
||||
import org.hibernate.orm.test.jpa.BaseEntityManagerFunctionalTestCase;
|
||||
import org.hibernate.orm.test.jpa.metamodel.Thing;
|
||||
import org.hibernate.orm.test.jpa.metamodel.ThingWithQuantity;
|
||||
import org.hibernate.orm.test.jpa.metamodel.ThingWithQuantity_;
|
||||
import org.hibernate.orm.test.jpa.ql.TreatKeywordTest.JoinedEntity;
|
||||
import org.hibernate.orm.test.jpa.ql.TreatKeywordTest.JoinedEntitySubSubclass;
|
||||
import org.hibernate.orm.test.jpa.ql.TreatKeywordTest.JoinedEntitySubSubclass2;
|
||||
import org.hibernate.orm.test.jpa.ql.TreatKeywordTest.JoinedEntitySubclass;
|
||||
import org.hibernate.orm.test.jpa.ql.TreatKeywordTest.JoinedEntitySubclass2;
|
||||
|
||||
import org.hibernate.testing.TestForIssue;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNull;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
|
@ -37,6 +45,8 @@ public class TreatKeywordTest extends BaseEntityManagerFunctionalTestCase {
|
|||
@Override
|
||||
protected Class<?>[] getAnnotatedClasses() {
|
||||
return new Class[] {
|
||||
JoinedEntity.class, JoinedEntitySubclass.class, JoinedEntitySubSubclass.class,
|
||||
JoinedEntitySubclass2.class, JoinedEntitySubSubclass2.class,
|
||||
Animal.class, Elephant.class, Human.class, Thing.class, ThingWithQuantity.class,
|
||||
TreatAnimal.class, Dog.class, Dachshund.class, Greyhound.class
|
||||
};
|
||||
|
@ -254,6 +264,46 @@ public class TreatKeywordTest extends BaseEntityManagerFunctionalTestCase {
|
|||
em.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestForIssue(jiraKey = "HHH-16657")
|
||||
public void testTypeFilterInSubquery() {
|
||||
EntityManager em = getOrCreateEntityManager();
|
||||
EntityTransaction entityTransaction = em.getTransaction();
|
||||
entityTransaction.begin();
|
||||
|
||||
JoinedEntitySubclass2 child1 = new JoinedEntitySubclass2( 3, "child1");
|
||||
JoinedEntitySubSubclass2 child2 = new JoinedEntitySubSubclass2( 4, "child2");
|
||||
JoinedEntitySubclass root1 = new JoinedEntitySubclass( 1, "root1", child1);
|
||||
JoinedEntitySubSubclass root2 = new JoinedEntitySubSubclass( 2, "root2", child2);
|
||||
em.persist( child1 );
|
||||
em.persist( child2 );
|
||||
em.persist( root1 );
|
||||
em.persist( root2 );
|
||||
|
||||
CriteriaBuilder cb = em.getCriteriaBuilder();
|
||||
CriteriaQuery<String> query = cb.createQuery( String.class );
|
||||
Root<JoinedEntitySubclass> root = query.from( JoinedEntitySubclass.class );
|
||||
query.orderBy( cb.asc( root.get( "id" ) ) );
|
||||
Subquery<String> subquery = query.subquery( String.class );
|
||||
Root<JoinedEntitySubclass> subqueryRoot = subquery.correlate( root );
|
||||
Join<Object, Object> other = subqueryRoot.join( "other" );
|
||||
subquery.select( other.get( "name" ) );
|
||||
subquery.where( cb.equal( root.type(), cb.literal( JoinedEntitySubclass.class ) ) );
|
||||
query.select( subquery );
|
||||
|
||||
List<String> results = em.createQuery(
|
||||
"select (select o.name from j.other o where type(j) = JoinedEntitySubSubclass) from JoinedEntitySubclass j order by j.id",
|
||||
String.class
|
||||
).getResultList();
|
||||
|
||||
assertEquals( 2, results.size() );
|
||||
assertNull( results.get( 0 ) );
|
||||
assertEquals( "child2", results.get( 1 ) );
|
||||
|
||||
entityTransaction.commit();
|
||||
em.close();
|
||||
}
|
||||
|
||||
@Entity(name = "TreatAnimal")
|
||||
public static abstract class TreatAnimal {
|
||||
@Id
|
||||
|
|
|
@ -30,6 +30,7 @@ import org.hibernate.testing.TestForIssue;
|
|||
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
/**
|
||||
|
@ -208,6 +209,34 @@ public class TreatKeywordTest extends BaseCoreFunctionalTestCase {
|
|||
s.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestForIssue(jiraKey = "HHH-16657")
|
||||
public void testTypeFilterInSubquery() {
|
||||
Session s = openSession();
|
||||
Transaction tx = s.beginTransaction();
|
||||
|
||||
JoinedEntitySubclass2 child1 = new JoinedEntitySubclass2(3, "child1");
|
||||
JoinedEntitySubSubclass2 child2 = new JoinedEntitySubSubclass2(4, "child2");
|
||||
JoinedEntitySubclass root1 = new JoinedEntitySubclass(1, "root1", child1);
|
||||
JoinedEntitySubSubclass root2 = new JoinedEntitySubSubclass(2, "root2", child2);
|
||||
s.persist( child1 );
|
||||
s.persist( child2 );
|
||||
s.persist( root1 );
|
||||
s.persist( root2 );
|
||||
|
||||
List<String> results = s.createSelectionQuery(
|
||||
"select (select o.name from j.other o where type(j) = JoinedEntitySubSubclass) from JoinedEntitySubclass j order by j.id",
|
||||
String.class
|
||||
).list();
|
||||
|
||||
assertEquals( 2, results.size() );
|
||||
assertNull( results.get( 0 ) );
|
||||
assertEquals( "child2", results.get( 1 ) );
|
||||
|
||||
tx.commit();
|
||||
s.close();
|
||||
}
|
||||
|
||||
@Entity( name = "JoinedEntity" )
|
||||
@Table( name = "JoinedEntity" )
|
||||
@Inheritance( strategy = InheritanceType.JOINED )
|
||||
|
|
Loading…
Reference in New Issue