Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
import org.hibernate.metamodel.mapping.MappingModelExpressible;
import org.hibernate.metamodel.mapping.internal.MappingModelCreationProcess;
import org.hibernate.metamodel.model.domain.BasicDomainType;
import org.hibernate.metamodel.model.domain.DomainType;
import org.hibernate.metamodel.model.domain.EmbeddableDomainType;
import org.hibernate.metamodel.model.domain.EntityDomainType;
import org.hibernate.metamodel.model.domain.JpaMetamodel;
Expand Down Expand Up @@ -721,6 +722,10 @@ public MappingModelExpressible<?> resolveMappingExpressible(
SqmExpressible<?> sqmExpressible,
Function<NavigablePath, TableGroup> tableGroupLocator) {
if ( sqmExpressible instanceof SqmPath<?> sqmPath ) {
final DomainType<?> sqmPathType = sqmPath.getResolvedModel().getSqmPathType();
if ( sqmPathType instanceof MappingModelExpressible<?> mappingExpressible ) {
return mappingExpressible;
}
final NavigablePath navigablePath = sqmPath.getNavigablePath();
if ( navigablePath.getParent() != null ) {
final TableGroup parentTableGroup = tableGroupLocator.apply( navigablePath.getParent() );
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,29 +4,43 @@
*/
package org.hibernate.orm.test.jpa.criteria;

import java.math.BigDecimal;
import java.util.List;

import org.hibernate.testing.orm.junit.JiraKey;
import org.hibernate.testing.orm.junit.EntityManagerFactoryScope;
import org.hibernate.testing.orm.junit.Jira;
import org.hibernate.testing.orm.junit.Jpa;

import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;

import jakarta.persistence.Column;
import jakarta.persistence.Embeddable;
import jakarta.persistence.Embedded;
import jakarta.persistence.Entity;
import jakarta.persistence.Id;
import jakarta.persistence.Tuple;
import jakarta.persistence.TypedQuery;
import jakarta.persistence.criteria.CriteriaBuilder;
import jakarta.persistence.criteria.CriteriaQuery;
import jakarta.persistence.criteria.Expression;
import jakarta.persistence.criteria.ParameterExpression;
import jakarta.persistence.criteria.Root;

import static org.assertj.core.api.Assertions.assertThat;

/**
* @author Will Dazy
*/
@Jpa(annotatedClasses = CoalesceTest.HHH15291Entity.class)
@Jpa( annotatedClasses = {
CoalesceTest.HHH15291Entity.class,
CoalesceTest.ComponentEntity.class,
CoalesceTest.ComponentA.class,
} )
@JiraKey( value = "HHH-15291")
public class CoalesceTest {

@Test
public void hhh15291JPQL1Test(EntityManagerFactoryScope scope) {
scope.inEntityManager(
Expand Down Expand Up @@ -95,9 +109,74 @@ public void hhh15291Criteria2Test(EntityManagerFactoryScope scope) {
);
}

@Test
@Jira( "https://hibernate.atlassian.net/browse/HHH-18321" )
public void testCoalesceInBinaryArithmetic(EntityManagerFactoryScope scope) {
scope.inTransaction( entityManager -> {
final CriteriaBuilder cb = entityManager.getCriteriaBuilder();
final CriteriaQuery<Tuple> cquery = cb.createTupleQuery();
final Root<ComponentEntity> root = cquery.from( ComponentEntity.class );

cquery.select( cb.tuple(
root.get( "id" ),
cb.diff(
cb.coalesce( root.get( "componentA" ).get( "income" ), BigDecimal.ZERO ),
cb.coalesce( root.get( "componentA" ).get( "expense" ), BigDecimal.ZERO )
)
) );

final List<Tuple> resultList = entityManager.createQuery( cquery ).getResultList();
assertThat( resultList ).hasSize( 2 );
for ( Tuple result : resultList ) {
final Long id = result.get( 0, Long.class );
assertThat( result.get( 1, BigDecimal.class ).intValue() ).isEqualTo( id == 1L ? 0 : 1 );
}
} );
}

@Test
@Jira( "https://hibernate.atlassian.net/browse/HHH-18321" )
public void testCoalesceInBinaryArithmeticParam(EntityManagerFactoryScope scope) {
scope.inTransaction( entityManager -> {
final CriteriaBuilder cb = entityManager.getCriteriaBuilder();
final CriteriaQuery<Tuple> cquery = cb.createTupleQuery();
final Root<ComponentEntity> root = cquery.from( ComponentEntity.class );

final ParameterExpression<BigDecimal> defaultValue = cb.parameter( BigDecimal.class, "default-value" );

cquery.select( cb.tuple(
root.get( "id" ),
cb.diff(
defaultValue,
cb.coalesce( root.get( "componentA" ).get( "expense" ), defaultValue )
)
) );

final List<Tuple> resultList = entityManager.createQuery( cquery )
.setParameter( "default-value", BigDecimal.ZERO ).getResultList();
assertThat( resultList ).hasSize( 2 );
for ( Tuple result : resultList ) {
final Long id = result.get( 0, Long.class );
assertThat( result.get( 1, BigDecimal.class ).intValue() ).isEqualTo( id == 1L ? -1 : 0 );
}
} );
}

@BeforeAll
public void setUp(EntityManagerFactoryScope scope) {
scope.inTransaction( entityManager -> {
entityManager.persist( new ComponentEntity( 1L, new ComponentA( BigDecimal.ONE, BigDecimal.ONE ) ) );
entityManager.persist( new ComponentEntity( 2L, new ComponentA( BigDecimal.ONE, null ) ) );
} );
}

@AfterAll
public void tearDown(EntityManagerFactoryScope scope) {
scope.inTransaction( entityManager -> entityManager.createQuery( "delete from ComponentEntity" ).executeUpdate() );
}

@Entity(name = "HHH15291Entity")
public static class HHH15291Entity {

@Id
@Column(name = "KEY_CHAR")
private String KeyString;
Expand All @@ -116,53 +195,36 @@ public static class HHH15291Entity {

@Column(name = "ITEM_INTEGER1")
private Integer itemInteger1;
}

public String getKeyString() {
return KeyString;
}

public void setKeyString(String keyString) {
KeyString = keyString;
}

public String getItemString1() {
return itemString1;
}

public void setItemString1(String itemString1) {
this.itemString1 = itemString1;
}

public String getItemString2() {
return itemString2;
}

public void setItemString2(String itemString2) {
this.itemString2 = itemString2;
}
@Entity( name = "ComponentEntity" )
static class ComponentEntity {
@Id
private Long id;

public String getItemString3() {
return itemString3;
}
@Embedded
private ComponentA componentA;

public void setItemString3(String itemString3) {
this.itemString3 = itemString3;
public ComponentEntity() {
}

public String getItemString4() {
return itemString4;
public ComponentEntity(Long id, ComponentA componentA) {
this.id = id;
this.componentA = componentA;
}
}

public void setItemString4(String itemString4) {
this.itemString4 = itemString4;
}
@Embeddable
static class ComponentA {
private BigDecimal income;
private BigDecimal expense;

public Integer getItemInteger1() {
return itemInteger1;
public ComponentA() {
}

public void setItemInteger1(Integer itemInteger1) {
this.itemInteger1 = itemInteger1;
public ComponentA(BigDecimal income, BigDecimal expense) {
this.income = income;
this.expense = expense;
}
}
}
Loading