Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
HHH-14482 Do not discard prior implicit join by key
- Loading branch information
Showing
2 changed files
with
150 additions
and
7 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
148 changes: 148 additions & 0 deletions
148
...rc/test/java/org/hibernate/orm/test/query/sqm/exec/SubQueryImplicitJoinReferenceTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,148 @@ | ||
/* | ||
* 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 <http://www.gnu.org/licenses/lgpl-2.1.html>. | ||
*/ | ||
package org.hibernate.orm.test.query.sqm.exec; | ||
|
||
import java.io.Serializable; | ||
import java.util.Objects; | ||
|
||
import javax.persistence.Embeddable; | ||
import javax.persistence.EmbeddedId; | ||
import javax.persistence.Entity; | ||
import javax.persistence.Id; | ||
import javax.persistence.ManyToOne; | ||
|
||
import org.junit.jupiter.api.Test; | ||
|
||
import org.hibernate.testing.TestForIssue; | ||
import org.hibernate.testing.orm.junit.DomainModel; | ||
import org.hibernate.testing.orm.junit.SessionFactory; | ||
import org.hibernate.testing.orm.junit.SessionFactoryScope; | ||
|
||
/** | ||
* Test that uses a subquery that makes an implicit join to a previously resolved implicit join in the | ||
* outer query. This test verifies that the query succeeds when such a query is executed. | ||
* | ||
* @author Chris Cranford | ||
*/ | ||
@DomainModel(annotatedClasses = { | ||
SubQueryImplicitJoinReferenceTest.TheEntity.class, | ||
SubQueryImplicitJoinReferenceTest.RevisionInfoEntity.class }) | ||
@SessionFactory | ||
@TestForIssue(jiraKey = "HHH-14482") | ||
public class SubQueryImplicitJoinReferenceTest { | ||
|
||
@Test | ||
public void performDataPreparation(SessionFactoryScope scope) { | ||
// Simulate creating revision 1 | ||
final RevisionInfoEntity revEntity = new RevisionInfoEntity(); | ||
revEntity.setId( 1 ); | ||
|
||
// Simulate creating the audit record | ||
final TheEntity entity = new TheEntity(); | ||
entity.setOriginalId( OriginalId.from( revEntity, 1 ) ); | ||
entity.setData( "Test" ); | ||
|
||
// Persist the entities | ||
scope.inTransaction( session -> { session.save( revEntity ); session.save( entity ); } ); | ||
} | ||
|
||
@Test | ||
public void performHqlTest(SessionFactoryScope scope) { | ||
// Now simulate running an audit query | ||
scope.inSession( session -> { | ||
session.createQuery( "select e__ FROM org.hibernate.orm.test.SubQueryImplicitJoinReferenceTest$TheEntity e__ " | ||
+ "WHERE e__.originalId.rev.id = (select max(e2__.originalId.rev.id) FROM " | ||
+ "org.hibernate.orm.test.SubQueryImplicitJoinReferenceTest$TheEntity e2__ WHERE " + | ||
"e2__.originalId.rev.id <= 2 and e__.originalId.id = e2__.originalId.id)" ).list(); | ||
} ); | ||
} | ||
|
||
@Entity | ||
public static class TheEntity { | ||
@EmbeddedId | ||
private OriginalId originalId; | ||
private String data; | ||
|
||
public OriginalId getOriginalId() { | ||
return originalId; | ||
} | ||
|
||
public void setOriginalId(OriginalId originalId) { | ||
this.originalId = originalId; | ||
} | ||
|
||
public String getData() { | ||
return data; | ||
} | ||
|
||
public void setData(String data) { | ||
this.data = data; | ||
} | ||
} | ||
|
||
@Entity | ||
public static class RevisionInfoEntity { | ||
@Id | ||
private Integer id; | ||
|
||
public Integer getId() { | ||
return id; | ||
} | ||
|
||
public void setId(Integer id) { | ||
this.id = id; | ||
} | ||
} | ||
|
||
@Embeddable | ||
public static class OriginalId implements Serializable { | ||
@ManyToOne | ||
private RevisionInfoEntity rev; | ||
private Integer id; | ||
|
||
public RevisionInfoEntity getRev() { | ||
return rev; | ||
} | ||
|
||
public void setRev(RevisionInfoEntity rev) { | ||
this.rev = rev; | ||
} | ||
|
||
public Integer getId() { | ||
return id; | ||
} | ||
|
||
public void setId(Integer id) { | ||
this.id = id; | ||
} | ||
|
||
public static OriginalId from(RevisionInfoEntity rev, Integer id) { | ||
OriginalId oId = new OriginalId(); | ||
oId.rev = rev; | ||
oId.id = id; | ||
return oId; | ||
} | ||
|
||
@Override | ||
public int hashCode() { | ||
return Objects.hash(rev, id); | ||
} | ||
|
||
@Override | ||
public boolean equals(Object obj) { | ||
if ( obj == null ) { | ||
return false; | ||
} | ||
if ( obj.getClass() != this.getClass() ) { | ||
return false; | ||
} | ||
|
||
final OriginalId other = (OriginalId) obj; | ||
return Objects.equals( rev, other.rev ) && Objects.equals( id, other.id ); | ||
} | ||
} | ||
} |