HHH-17776 - Add test and fix

Signed-off-by: Jan Schatteman <jschatte@redhat.com>
This commit is contained in:
Jan Schatteman 2024-02-28 18:37:25 +01:00 committed by Christian Beikov
parent 0d67d64ff4
commit ee76f005aa
2 changed files with 82 additions and 16 deletions

View File

@ -64,13 +64,13 @@ public class SqmQuerySpec<T> extends SqmQueryPart<T>
public SqmQuerySpec(NodeBuilder nodeBuilder) { public SqmQuerySpec(NodeBuilder nodeBuilder) {
super( nodeBuilder ); super( nodeBuilder );
// Enforce non-nullness of the fromClause
this.fromClause = new SqmFromClause();
} }
public SqmQuerySpec(SqmQuerySpec<T> original, SqmCopyContext context) { public SqmQuerySpec(SqmQuerySpec<T> original, SqmCopyContext context) {
super( original, context ); super( original, context );
if ( original.fromClause != null ) { this.fromClause = original.fromClause.copy( context );
this.fromClause = original.fromClause.copy( context );
}
if ( original.selectClause != null ) { if ( original.selectClause != null ) {
this.selectClause = original.selectClause.copy( context ); this.selectClause = original.selectClause.copy( context );
} }
@ -96,9 +96,7 @@ public class SqmQuerySpec<T> extends SqmQueryPart<T>
return existing; return existing;
} }
final SqmQuerySpec<T> querySpec = context.registerCopy( this, new SqmQuerySpec<>( nodeBuilder() ) ); final SqmQuerySpec<T> querySpec = context.registerCopy( this, new SqmQuerySpec<>( nodeBuilder() ) );
if ( fromClause != null ) { querySpec.fromClause = fromClause.copy( context );
querySpec.fromClause = fromClause.copy( context );
}
if ( selectClause != null ) { if ( selectClause != null ) {
querySpec.selectClause = selectClause.copy( context ); querySpec.selectClause = selectClause.copy( context );
} }
@ -145,7 +143,10 @@ public class SqmQuerySpec<T> extends SqmQueryPart<T>
} }
public void setFromClause(SqmFromClause fromClause) { public void setFromClause(SqmFromClause fromClause) {
this.fromClause = fromClause; // Enforce non-nullness of the fromClause
if ( fromClause != null ) {
this.fromClause = fromClause;
}
} }
public boolean producesUniqueResults() { public boolean producesUniqueResults() {

View File

@ -9,35 +9,44 @@ package org.hibernate.orm.test.jpa.criteria.subquery;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import org.hibernate.testing.TestForIssue; import org.hibernate.Session;
import org.hibernate.query.criteria.HibernateCriteriaBuilder;
import org.hibernate.query.criteria.JpaCriteriaQuery;
import org.hibernate.query.criteria.JpaDerivedRoot;
import org.hibernate.query.criteria.JpaSubQuery;
import org.hibernate.testing.orm.junit.EntityManagerFactoryScope; import org.hibernate.testing.orm.junit.EntityManagerFactoryScope;
import org.hibernate.testing.orm.junit.JiraKey;
import org.hibernate.testing.orm.junit.Jpa; import org.hibernate.testing.orm.junit.Jpa;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import jakarta.persistence.Entity; import jakarta.persistence.Entity;
import jakarta.persistence.EntityManager;
import jakarta.persistence.Id; import jakarta.persistence.Id;
import jakarta.persistence.ManyToOne; import jakarta.persistence.ManyToOne;
import jakarta.persistence.OneToMany; import jakarta.persistence.OneToMany;
import jakarta.persistence.Table; import jakarta.persistence.Table;
import jakarta.persistence.Tuple;
import jakarta.persistence.criteria.CriteriaBuilder; import jakarta.persistence.criteria.CriteriaBuilder;
import jakarta.persistence.criteria.CriteriaQuery; import jakarta.persistence.criteria.CriteriaQuery;
import jakarta.persistence.criteria.Root; import jakarta.persistence.criteria.Root;
import jakarta.persistence.criteria.Subquery; import jakarta.persistence.criteria.Subquery;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.jupiter.api.Assertions.assertEquals;
@Jpa( @Jpa(
annotatedClasses = { annotatedClasses = {
RootInSubqueryWhereClauseTest.Person.class, SubqueryTests.Person.class,
RootInSubqueryWhereClauseTest.Address.class SubqueryTests.Address.class
} }
) )
@TestForIssue(jiraKey = "HHH-15477") public class SubqueryTests {
public class RootInSubqueryWhereClauseTest {
@BeforeEach @BeforeAll
public void setUp(EntityManagerFactoryScope scope){ public void setUp(EntityManagerFactoryScope scope){
scope.inTransaction( scope.inTransaction(
entityManager -> { entityManager -> {
@ -54,7 +63,8 @@ public class RootInSubqueryWhereClauseTest {
} }
@Test @Test
public void testSubquery(EntityManagerFactoryScope scope) { @JiraKey(value = "HHH-15477")
public void testRootInSubqueryWhereClause(EntityManagerFactoryScope scope) {
scope.inTransaction( scope.inTransaction(
entityManager -> { entityManager -> {
CriteriaBuilder builder = entityManager.getCriteriaBuilder(); CriteriaBuilder builder = entityManager.getCriteriaBuilder();
@ -76,6 +86,50 @@ public class RootInSubqueryWhereClauseTest {
); );
} }
@Test
@JiraKey(value = "HHH-17776")
public void testNoFromClauseInSubquery(EntityManagerFactoryScope scope) {
scope.inTransaction(
entityManager -> {
List<Person> entities = getEntities(entityManager);
assertEquals( 2, entities.size());
assertEquals("Jack", entities.get(0).getName());
assertEquals("Black", entities.get(0).getSurName());
assertEquals("John", entities.get(1).getName());
assertEquals("Doe", entities.get(1).getSurName());
}
);
}
private List<Person> getEntities(EntityManager entityManager) {
HibernateCriteriaBuilder builder = entityManager.unwrap( Session.class ).getCriteriaBuilder();
JpaCriteriaQuery<Person> mainQuery = builder.createQuery( Person.class );
JpaSubQuery<Tuple> q1 = mainQuery.subquery(Tuple.class);
q1.multiselect(
builder.literal("John").alias("name"),
builder.literal("Doe").alias("surName")
);
JpaSubQuery<Tuple> q2 = mainQuery.subquery(Tuple.class);
q2.multiselect(
builder.literal("Jack").alias("name"),
builder.literal("Black").alias("surName")
);
JpaSubQuery<Tuple> unionAllSubQuery = builder.unionAll(q1, q2);
JpaDerivedRoot<Tuple> mainQueryRoot = mainQuery.from( unionAllSubQuery );
mainQuery.multiselect(
builder.trim(mainQueryRoot.get("name")).alias("name"),
builder.trim(mainQueryRoot.get("surName")).alias("surName")
);
mainQuery.orderBy( builder.asc(mainQueryRoot.get("name")) );
return entityManager.createQuery(mainQuery).getResultList();
}
@Entity(name = "Person") @Entity(name = "Person")
public static class Person { public static class Person {
@Id @Id
@ -83,6 +137,8 @@ public class RootInSubqueryWhereClauseTest {
String name; String name;
String surName;
@OneToMany @OneToMany
List<Address> addresses =new ArrayList<>(); List<Address> addresses =new ArrayList<>();
@ -90,8 +146,13 @@ public class RootInSubqueryWhereClauseTest {
} }
public Person(Integer id, String name) { public Person(Integer id, String name) {
this(id,name,null);
}
public Person(Integer id, String name, String surName) {
this.id = id; this.id = id;
this.name = name; this.name = name;
this.surName = surName;
} }
public void addAddress(Address address){ public void addAddress(Address address){
@ -107,6 +168,10 @@ public class RootInSubqueryWhereClauseTest {
return name; return name;
} }
public String getSurName() {
return surName;
}
public List<Address> getAddresses() { public List<Address> getAddresses() {
return addresses; return addresses;
} }