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

View File

@ -9,35 +9,44 @@ package org.hibernate.orm.test.jpa.criteria.subquery;
import java.util.ArrayList;
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.JiraKey;
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.EntityManager;
import jakarta.persistence.Id;
import jakarta.persistence.ManyToOne;
import jakarta.persistence.OneToMany;
import jakarta.persistence.Table;
import jakarta.persistence.Tuple;
import jakarta.persistence.criteria.CriteriaBuilder;
import jakarta.persistence.criteria.CriteriaQuery;
import jakarta.persistence.criteria.Root;
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.junit.jupiter.api.Assertions.assertEquals;
@Jpa(
annotatedClasses = {
RootInSubqueryWhereClauseTest.Person.class,
RootInSubqueryWhereClauseTest.Address.class
SubqueryTests.Person.class,
SubqueryTests.Address.class
}
)
@TestForIssue(jiraKey = "HHH-15477")
public class RootInSubqueryWhereClauseTest {
public class SubqueryTests {
@BeforeEach
@BeforeAll
public void setUp(EntityManagerFactoryScope scope){
scope.inTransaction(
entityManager -> {
@ -54,7 +63,8 @@ public class RootInSubqueryWhereClauseTest {
}
@Test
public void testSubquery(EntityManagerFactoryScope scope) {
@JiraKey(value = "HHH-15477")
public void testRootInSubqueryWhereClause(EntityManagerFactoryScope scope) {
scope.inTransaction(
entityManager -> {
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")
public static class Person {
@Id
@ -83,6 +137,8 @@ public class RootInSubqueryWhereClauseTest {
String name;
String surName;
@OneToMany
List<Address> addresses =new ArrayList<>();
@ -90,8 +146,13 @@ public class RootInSubqueryWhereClauseTest {
}
public Person(Integer id, String name) {
this(id,name,null);
}
public Person(Integer id, String name, String surName) {
this.id = id;
this.name = name;
this.surName = surName;
}
public void addAddress(Address address){
@ -107,6 +168,10 @@ public class RootInSubqueryWhereClauseTest {
return name;
}
public String getSurName() {
return surName;
}
public List<Address> getAddresses() {
return addresses;
}