From 05e6a41e5fc13cc76dd8f42b8b665fdbf775b2d3 Mon Sep 17 00:00:00 2001 From: Jan-Willem Gmelig Meyling Date: Thu, 31 Oct 2019 18:42:58 +0100 Subject: [PATCH] HHH-13670 - Reproducer Missing from clause in query with joined inheritance, regression in 5.4.5 --- .../query/hhh13670/HHH13670Test.java | 146 ++++++++++++++++++ 1 file changed, 146 insertions(+) create mode 100644 hibernate-core/src/test/java/org/hibernate/query/hhh13670/HHH13670Test.java diff --git a/hibernate-core/src/test/java/org/hibernate/query/hhh13670/HHH13670Test.java b/hibernate-core/src/test/java/org/hibernate/query/hhh13670/HHH13670Test.java new file mode 100644 index 0000000000..701de49b1d --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/query/hhh13670/HHH13670Test.java @@ -0,0 +1,146 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * License: GNU Lesser General Public License (LGPL), version 2.1 or later. + * See the lgpl.txt file in the root directory or . + */ +package org.hibernate.query.hhh13670; + +import org.hibernate.cfg.Configuration; +import org.hibernate.testing.TestForIssue; +import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; +import org.junit.Before; +import org.junit.Test; + +import javax.persistence.Column; +import javax.persistence.ConstraintMode; +import javax.persistence.Entity; +import javax.persistence.FetchType; +import javax.persistence.ForeignKey; +import javax.persistence.Id; +import javax.persistence.Inheritance; +import javax.persistence.InheritanceType; +import javax.persistence.JoinColumn; +import javax.persistence.ManyToOne; +import javax.persistence.Tuple; +import java.util.List; + +import static org.hibernate.testing.transaction.TransactionUtil.doInJPA; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; + +@TestForIssue(jiraKey = "HHH-13670") +public class HHH13670Test extends BaseCoreFunctionalTestCase { + + @Before + public void setUp() { + doInJPA(this::sessionFactory, em -> { + SubA a_1 = new SubA(1L); + SubA a_2 = new SubA(2L); + SubA a_3 = new SubA(3L); + SubA a_14 = em.getReference(SubA.class, 10L); + SubB b_4 = new SubB(4L, null); + SubB b_5 = new SubB(5L, a_3); + SubB b_6 = new SubB(6L, b_4); + SubB b_7 = new SubB(7L, a_14); + + em.merge(a_1); + em.merge(a_2); + em.merge(a_3); + em.merge(b_4); + em.merge(b_5); + em.merge(b_6); + em.merge(b_7); + }); + } + + @Test + public void testRootTypeJoinWithGroupJoins() { + doInJPA(this::sessionFactory, em -> { + List resultList = em.createQuery("SELECT subB_0.id, subA_0.id, subB_0.id, subA_0.id FROM SubB subB_0 LEFT JOIN Super subA_0 ON subA_0.id = subB_0.parent.id ORDER BY subB_0.id ASC, subA_0.id ASC", Tuple.class) + .getResultList(); + + assertEquals("Rows omitted despite optional association should have rendered a left join", 4, resultList.size()); + + assertEquals((Long) 4L , resultList.get(0).get(0)); + assertEquals((Long) 5L , resultList.get(1).get(0)); + assertEquals((Long) 6L , resultList.get(2).get(0)); + assertEquals((Long) 7L , resultList.get(3).get(0)); + + assertNull(resultList.get(0).get(1, Long.class)); + assertEquals((Long) 3L , resultList.get(1).get(1, Long.class)); + assertEquals((Long) 4L , resultList.get(2).get(1, Long.class)); + assertNull("Missing entry in foreign table should not be returned", resultList.get(3).get(1, Long.class)); + }); + } + + @Test + public void testSubTypeJoinWithTableGroupJoins() { + doInJPA(this::sessionFactory, em -> { + List resultList = em.createQuery("SELECT subB_0.id, subA_0.id, subB_0.id, subA_0.id FROM SubB subB_0 LEFT JOIN SubA subA_0 ON subA_0.id = subB_0.parent.id ORDER BY subB_0.id ASC, subA_0.id ASC", Tuple.class) + .getResultList(); + + assertEquals("Rows omitted despite optional association should have rendered a left join", 4, resultList.size()); + + assertEquals((Long) 4L, resultList.get(0).get(0)); + assertEquals((Long) 5L, resultList.get(1).get(0)); + assertEquals((Long) 6L, resultList.get(2).get(0)); + assertEquals((Long) 7L, resultList.get(3).get(0)); + + assertNull(resultList.get(0).get(1, Long.class)); + assertEquals((Long) 3L, resultList.get(1).get(1, Long.class)); + assertNull("Another subtype than queried for was returned", resultList.get(2).get(1)); + assertNull("Missing entry in foreign table should not be returned", resultList.get(3).get(1, Long.class)); + }); + } + + @Override + protected Class[] getAnnotatedClasses() { + return new Class[] { Super.class, SubA.class, SubB.class }; + } + + @Override + protected void configure(Configuration configuration) { + super.afterConfigurationBuilt( configuration ); + // Uncomment to fix tests +// configuration.setProperty( AvailableSettings.OMIT_JOIN_OF_SUPERCLASS_TABLES, "false" ); + } + + @Entity(name = "Super") + @Inheritance(strategy = InheritanceType.JOINED) + public static class Super { + + @Id + @Column + Long id; + + @JoinColumn(foreignKey = @ForeignKey(ConstraintMode.NO_CONSTRAINT)) + @ManyToOne(targetEntity = Super.class, fetch = FetchType.LAZY) + SubType parent; + + } + + @Entity(name = "SubA") + public static class SubA extends Super { + + SubA() {} + + SubA(Long id) { + this.id = id; + } + + } + + @Entity(name = "SubB") + public static class SubB extends Super { + + SubB() {} + + SubB(Long id, Super parent) { + this.id = id; + ((Super) this).parent = parent; + } + + } + +}