HHH-12230 - SelectCase does not work when simultaneously exists in select and group by sections
This commit is contained in:
parent
f0e0355ad8
commit
291e3dd004
|
@ -136,11 +136,6 @@ public class CriteriaSubqueryImpl<T> extends ExpressionImpl<T> implements Subque
|
|||
public String render(RenderingContext renderingContext) {
|
||||
return subQuery.render( renderingContext );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String renderProjection(RenderingContext renderingContext) {
|
||||
return render( renderingContext );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -253,7 +253,7 @@ public class QueryStructure<T> implements Serializable {
|
|||
String sep = "";
|
||||
for ( Expression grouping : getGroupings() ) {
|
||||
jpaqlQuery.append( sep )
|
||||
.append( ( (Renderable) grouping ).render( renderingContext ) );
|
||||
.append( ( (Renderable) grouping ).renderGroupBy( renderingContext ) );
|
||||
sep = ", ";
|
||||
}
|
||||
|
||||
|
|
|
@ -15,6 +15,33 @@ import org.hibernate.query.criteria.internal.compile.RenderingContext;
|
|||
* @author Steve Ebersole
|
||||
*/
|
||||
public interface Renderable {
|
||||
public String render(RenderingContext renderingContext);
|
||||
public String renderProjection(RenderingContext renderingContext);
|
||||
|
||||
/**
|
||||
* Render clause
|
||||
*
|
||||
* @param renderingContext context
|
||||
* @return rendered expression
|
||||
*/
|
||||
String render(RenderingContext renderingContext);
|
||||
|
||||
/**
|
||||
* Render SELECT clause
|
||||
*
|
||||
* @param renderingContext context
|
||||
* @return rendered expression
|
||||
*/
|
||||
default String renderProjection(RenderingContext renderingContext) {
|
||||
return render( renderingContext );
|
||||
}
|
||||
|
||||
/**
|
||||
* Render GROUP BY clause
|
||||
*
|
||||
* @param renderingContext context
|
||||
*
|
||||
* @return rendered expression
|
||||
*/
|
||||
default String renderGroupBy(RenderingContext renderingContext) {
|
||||
return render( renderingContext );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -37,7 +37,7 @@ public interface RenderingContext {
|
|||
* Register a parameter that was not part of the criteria query (at least not as a parameter).
|
||||
*
|
||||
* @param literal The literal value
|
||||
* @param javaType The java type as whcih to handle the literal value.
|
||||
* @param javaType The java type as which to handle the literal value.
|
||||
*
|
||||
* @return The JPA-QL parameter name
|
||||
*/
|
||||
|
|
|
@ -213,9 +213,4 @@ public class BinaryArithmeticOperation<N extends Number>
|
|||
( (Renderable) getRightHandOperand() ).render( renderingContext )
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String renderProjection(RenderingContext renderingContext) {
|
||||
return render( renderingContext );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -76,8 +76,4 @@ public class CoalesceExpression<T> extends ExpressionImpl<T> implements Coalesce
|
|||
}
|
||||
return buffer.append( ")" ).toString();
|
||||
}
|
||||
|
||||
public String renderProjection(RenderingContext renderingContext) {
|
||||
return render( renderingContext );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -88,8 +88,4 @@ public class CompoundSelectionImpl<X>
|
|||
}
|
||||
return buff.toString();
|
||||
}
|
||||
|
||||
public String renderProjection(RenderingContext renderingContext) {
|
||||
return render( renderingContext );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -68,8 +68,4 @@ public class ConcatExpression extends ExpressionImpl<String> implements Serializ
|
|||
+ " || "
|
||||
+ ( (Renderable) getString2() ).render( renderingContext ) + ')' ;
|
||||
}
|
||||
|
||||
public String renderProjection(RenderingContext renderingContext) {
|
||||
return render( renderingContext );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -30,8 +30,4 @@ public class EntityTypeExpression<T> extends ExpressionImpl<T> implements Serial
|
|||
// todo : is it valid for this to get rendered into the query itself?
|
||||
throw new IllegalArgumentException( "Unexpected call on EntityTypeExpression#render" );
|
||||
}
|
||||
|
||||
public String renderProjection(RenderingContext renderingContext) {
|
||||
return render( renderingContext );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -46,8 +46,4 @@ public class ListIndexExpression extends ExpressionImpl<Integer> implements Seri
|
|||
+ origin.getPathIdentifier()
|
||||
+ ")";
|
||||
}
|
||||
|
||||
public String renderProjection(RenderingContext renderingContext) {
|
||||
return render( renderingContext );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -89,6 +89,11 @@ public class LiteralExpression<T> extends ExpressionImpl<T> implements Serializa
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String renderGroupBy(RenderingContext renderingContext) {
|
||||
return renderProjection( renderingContext );
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings({ "unchecked" })
|
||||
protected void resetJavaType(Class targetType) {
|
||||
|
|
|
@ -67,8 +67,4 @@ public class NullifExpression<T> extends ExpressionImpl<T> implements Serializab
|
|||
+ ( (Renderable) getSecondaryExpression() ).render( renderingContext )
|
||||
+ ")";
|
||||
}
|
||||
|
||||
public String renderProjection(RenderingContext renderingContext) {
|
||||
return render( renderingContext );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -72,8 +72,4 @@ public class ParameterExpressionImpl<T>
|
|||
final ExplicitParameterInfo parameterInfo = renderingContext.registerExplicitParameter( this );
|
||||
return parameterInfo.render();
|
||||
}
|
||||
|
||||
public String renderProjection(RenderingContext renderingContext) {
|
||||
return render( renderingContext );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -33,8 +33,4 @@ public class PathTypeExpression<T> extends ExpressionImpl<T> implements Serializ
|
|||
public String render(RenderingContext renderingContext) {
|
||||
return "type(" + pathImpl.getPathIdentifier() + ")";
|
||||
}
|
||||
|
||||
public String renderProjection(RenderingContext renderingContext) {
|
||||
return render( renderingContext );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -119,6 +119,14 @@ public class SearchedCaseExpression<R>
|
|||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String renderGroupBy(RenderingContext renderingContext) {
|
||||
return render(
|
||||
renderingContext,
|
||||
(Renderable expression, RenderingContext context) -> expression.renderGroupBy( context )
|
||||
);
|
||||
}
|
||||
|
||||
private String render(
|
||||
RenderingContext renderingContext,
|
||||
BiFunction<Renderable, RenderingContext, String> formatter) {
|
||||
|
|
|
@ -116,6 +116,7 @@ public class SimpleCaseExpression<C,R>
|
|||
Helper.possibleParameter( getOtherwiseResult(), registry );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String render(RenderingContext renderingContext) {
|
||||
return render(
|
||||
renderingContext,
|
||||
|
@ -123,6 +124,7 @@ public class SimpleCaseExpression<C,R>
|
|||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String renderProjection(RenderingContext renderingContext) {
|
||||
return render(
|
||||
renderingContext,
|
||||
|
@ -130,6 +132,14 @@ public class SimpleCaseExpression<C,R>
|
|||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String renderGroupBy(RenderingContext renderingContext) {
|
||||
return render(
|
||||
renderingContext,
|
||||
(Renderable expression, RenderingContext context) -> expression.renderGroupBy( context )
|
||||
);
|
||||
}
|
||||
|
||||
private String render(
|
||||
RenderingContext renderingContext,
|
||||
BiFunction<Renderable, RenderingContext, String> formatter) {
|
||||
|
|
|
@ -50,8 +50,4 @@ public class SizeOfPluralAttributeExpression
|
|||
public String render(RenderingContext renderingContext) {
|
||||
return "size(" + getPluralAttributePath().render( renderingContext ) + ")";
|
||||
}
|
||||
|
||||
public String renderProjection(RenderingContext renderingContext) {
|
||||
return render( renderingContext );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -70,8 +70,4 @@ public class SubqueryComparisonModifierExpression<Y>
|
|||
public String render(RenderingContext renderingContext) {
|
||||
return getModifier().rendered() + ( (Renderable) getSubquery() ).render( renderingContext );
|
||||
}
|
||||
|
||||
public String renderProjection(RenderingContext renderingContext) {
|
||||
return render( renderingContext );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -59,9 +59,4 @@ public class UnaryArithmeticOperation<T>
|
|||
return ( getOperation() == Operation.UNARY_MINUS ? '-' : '+' )
|
||||
+ ( (Renderable) getOperand() ).render( renderingContext );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String renderProjection(RenderingContext renderingContext) {
|
||||
return render( renderingContext );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -51,8 +51,4 @@ public class BasicFunctionExpression<X>
|
|||
public String render(RenderingContext renderingContext) {
|
||||
return getFunctionName() + "()";
|
||||
}
|
||||
|
||||
public String renderProjection(RenderingContext renderingContext) {
|
||||
return render( renderingContext );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -91,16 +91,11 @@ public abstract class AbstractFromImpl<Z, X>
|
|||
}
|
||||
|
||||
@Override
|
||||
public String renderProjection(RenderingContext renderingContext) {
|
||||
public String render(RenderingContext renderingContext) {
|
||||
prepareAlias( renderingContext );
|
||||
return getAlias();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String render(RenderingContext renderingContext) {
|
||||
return renderProjection( renderingContext );
|
||||
}
|
||||
|
||||
@Override
|
||||
public Attribute<?, ?> getAttribute() {
|
||||
return null;
|
||||
|
|
|
@ -247,9 +247,4 @@ public abstract class AbstractPathImpl<X>
|
|||
return getAttribute().getName();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String renderProjection(RenderingContext renderingContext) {
|
||||
return render( renderingContext );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -90,11 +90,6 @@ public class RootImpl<X> extends AbstractFromImpl<X,X> implements Root<X>, Seria
|
|||
prepareAlias( renderingContext );
|
||||
return getAlias();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String renderProjection(RenderingContext renderingContext) {
|
||||
return render( renderingContext );
|
||||
}
|
||||
|
||||
public Set<TreatedRoot<? extends X>> getTreats() {
|
||||
return treats;
|
||||
|
|
|
@ -48,9 +48,4 @@ public abstract class AbstractSimplePredicate
|
|||
return render( isNegated(), renderingContext );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String renderProjection(RenderingContext renderingContext) {
|
||||
return render( renderingContext );
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -119,11 +119,6 @@ public class CompoundPredicate
|
|||
return operatorTextWithSeparator( this.getOperator() );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String renderProjection(RenderingContext renderingContext) {
|
||||
return render( renderingContext );
|
||||
}
|
||||
|
||||
/**
|
||||
* Create negation of compound predicate by using logic rules:
|
||||
* 1. not (x || y) is (not x && not y)
|
||||
|
|
|
@ -102,9 +102,4 @@ public class NegatedPredicateWrapper extends ExpressionImpl<Boolean> implements
|
|||
public String render(RenderingContext renderingContext) {
|
||||
return render( isNegated(), renderingContext );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String renderProjection(RenderingContext renderingContext) {
|
||||
return render( renderingContext );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,97 @@
|
|||
/*
|
||||
* 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.jpa.test.criteria.selectcase;
|
||||
|
||||
import java.util.List;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.EntityManager;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.Tuple;
|
||||
import javax.persistence.criteria.CriteriaBuilder;
|
||||
import javax.persistence.criteria.CriteriaQuery;
|
||||
import javax.persistence.criteria.Predicate;
|
||||
import javax.persistence.criteria.Root;
|
||||
|
||||
import org.hibernate.dialect.PostgreSQL95Dialect;
|
||||
import org.hibernate.jpa.test.BaseEntityManagerFunctionalTestCase;
|
||||
import org.hibernate.jpa.test.metadata.Person_;
|
||||
|
||||
import org.hibernate.testing.RequiresDialect;
|
||||
import org.hibernate.testing.TestForIssue;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.hibernate.testing.transaction.TransactionUtil.doInJPA;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
@TestForIssue(jiraKey = "HHH-12230")
|
||||
public class GroupBySelectCaseTest extends BaseEntityManagerFunctionalTestCase {
|
||||
|
||||
@Override
|
||||
protected Class<?>[] getAnnotatedClasses() {
|
||||
return new Class[] { Person.class };
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestForIssue(jiraKey = "HHH-12230")
|
||||
public void selectCaseInGroupByAndSelectExpression() {
|
||||
|
||||
doInJPA( this::entityManagerFactory, entityManager -> {
|
||||
CriteriaBuilder cb = entityManager.getCriteriaBuilder();
|
||||
CriteriaQuery<Tuple> query = cb.createTupleQuery();
|
||||
Root<Person> from = query.from( Person.class );
|
||||
|
||||
Predicate childPredicate = cb.between( from.get( Person_.AGE ), 0, 10 );
|
||||
Predicate teenagerPredicate = cb.between( from.get( Person_.AGE ), 11, 20 );
|
||||
CriteriaBuilder.Case<String> selectCase = cb.selectCase();
|
||||
selectCase.when( childPredicate, "child" )
|
||||
.when( teenagerPredicate, "teenager" )
|
||||
.otherwise( "adult" );
|
||||
|
||||
query.multiselect( selectCase );
|
||||
query.groupBy( selectCase );
|
||||
|
||||
List<Tuple> resultList = entityManager.createQuery( query ).getResultList();
|
||||
assertNotNull( resultList );
|
||||
assertTrue( resultList.isEmpty() );
|
||||
} );
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestForIssue(jiraKey = "HHH-12230")
|
||||
public void selectCaseInOrderByAndSelectExpression() {
|
||||
|
||||
doInJPA( this::entityManagerFactory, entityManager -> {
|
||||
CriteriaBuilder cb = entityManager.getCriteriaBuilder();
|
||||
CriteriaQuery<Tuple> query = cb.createTupleQuery();
|
||||
Root<Person> from = query.from( Person.class );
|
||||
|
||||
Predicate childPredicate = cb.between( from.get( Person_.AGE ), 0, 10 );
|
||||
Predicate teenagerPredicate = cb.between( from.get( Person_.AGE ), 11, 20 );
|
||||
CriteriaBuilder.Case<String> selectCase = cb.selectCase();
|
||||
selectCase.when( childPredicate, "child" )
|
||||
.when( teenagerPredicate, "teenager" )
|
||||
.otherwise( "adult" );
|
||||
|
||||
query.multiselect( selectCase );
|
||||
query.orderBy( cb.asc( selectCase ) );
|
||||
|
||||
List<Tuple> resultList = entityManager.createQuery( query ).getResultList();
|
||||
assertNotNull( resultList );
|
||||
assertTrue( resultList.isEmpty() );
|
||||
} );
|
||||
}
|
||||
|
||||
@Entity(name = "Person")
|
||||
public static class Person {
|
||||
|
||||
@Id
|
||||
private Long id;
|
||||
|
||||
private Integer age;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue