Skip to content

Commit 114ea15

Browse files
dreab8sebersole
authored andcommitted
HHH-10085 HHH-10143 - Fix issues with Criteria and case expressions
1 parent 73aa359 commit 114ea15

File tree

8 files changed

+96
-67
lines changed

8 files changed

+96
-67
lines changed

hibernate-core/src/main/java/org/hibernate/hql/internal/ast/tree/SearchedCaseNode.java

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,8 @@
2828
* @author Gavin King
2929
* @author Steve Ebersole
3030
*/
31-
public class SearchedCaseNode extends AbstractSelectExpression implements SelectExpression {
31+
public class SearchedCaseNode extends AbstractSelectExpression implements SelectExpression, ExpectedTypeAwareNode {
32+
3233
@Override
3334
public Type getDataType() {
3435
// option is used to hold each WHEN/ELSE in turn
@@ -58,13 +59,35 @@ else if ( option.getType() == HqlSqlTokenTypes.ELSE ) {
5859

5960
option = option.getNextSibling();
6061
}
61-
62-
throw new QueryException( "Could not determine data type for searched case statement" );
62+
return null;
6363
}
6464

6565
@Override
6666
public void setScalarColumnText(int i) throws SemanticException {
6767
ColumnHelper.generateSingleScalarColumn( this, i );
6868
}
6969

70+
@Override
71+
public void setExpectedType(Type expectedType) {
72+
AST option = getFirstChild();
73+
while ( option != null ) {
74+
if ( option.getType() == HqlSqlTokenTypes.WHEN ) {
75+
if ( ParameterNode.class.isAssignableFrom( option.getFirstChild().getNextSibling().getClass() ) ) {
76+
((ParameterNode) option.getFirstChild().getNextSibling()).setExpectedType( expectedType );
77+
}
78+
}
79+
else if ( option.getType() == HqlSqlTokenTypes.ELSE ) {
80+
if ( ParameterNode.class.isAssignableFrom( option.getFirstChild().getClass() ) ) {
81+
((ParameterNode) option.getFirstChild()).setExpectedType( expectedType );
82+
}
83+
}
84+
85+
option = option.getNextSibling();
86+
}
87+
}
88+
89+
@Override
90+
public Type getExpectedType() {
91+
return null;
92+
}
7093
}

hibernate-core/src/main/java/org/hibernate/hql/internal/ast/tree/SelectClause.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,7 @@ public void initializeExplicitSelectClause(FromClause fromClause) throws Semanti
155155

156156
Type type = selectExpression.getDataType();
157157
if ( type == null ) {
158-
throw new IllegalStateException(
158+
throw new QueryException(
159159
"No data type for node: " + selectExpression.getClass().getName() + " "
160160
+ new ASTPrinter( SqlTokenTypes.class ).showAsString( (AST) selectExpression, "" )
161161
);

hibernate-core/src/main/java/org/hibernate/hql/internal/ast/tree/SimpleCaseNode.java

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,8 @@
2727
* @author Gavin King
2828
* @author Steve Ebersole
2929
*/
30-
public class SimpleCaseNode extends AbstractSelectExpression implements SelectExpression {
31-
30+
public class SimpleCaseNode extends AbstractSelectExpression implements SelectExpression, ExpectedTypeAwareNode {
31+
3232
public Type getDataType() {
3333
final AST expression = getFirstChild();
3434
// option is used to hold each WHEN/ELSE in turn
@@ -58,12 +58,33 @@ else if ( option.getType() == HqlSqlTokenTypes.ELSE ) {
5858

5959
option = option.getNextSibling();
6060
}
61-
62-
throw new QueryException( "Could not determine data type for simple case statement" );
61+
return null;
6362
}
6463

6564
public void setScalarColumnText(int i) throws SemanticException {
6665
ColumnHelper.generateSingleScalarColumn( this, i );
6766
}
6867

68+
@Override
69+
public void setExpectedType(Type expectedType) {
70+
AST option = getFirstChild();
71+
while ( option != null ) {
72+
if ( option.getType() == HqlSqlTokenTypes.WHEN ) {
73+
if ( ParameterNode.class.isAssignableFrom( option.getFirstChild().getNextSibling().getClass() ) ) {
74+
((ParameterNode) option.getFirstChild().getNextSibling()).setExpectedType( expectedType );
75+
}
76+
}
77+
else if ( option.getType() == HqlSqlTokenTypes.ELSE ) {
78+
if ( ParameterNode.class.isAssignableFrom( option.getFirstChild().getClass() ) ) {
79+
((ParameterNode) option.getFirstChild()).setExpectedType( expectedType );
80+
}
81+
}
82+
option = option.getNextSibling();
83+
}
84+
}
85+
86+
@Override
87+
public Type getExpectedType() {
88+
return null;
89+
}
6990
}

hibernate-core/src/main/java/org/hibernate/query/criteria/internal/expression/CaseLiteralExpression.java

Lines changed: 0 additions & 38 deletions
This file was deleted.

hibernate-core/src/main/java/org/hibernate/query/criteria/internal/expression/LiteralExpression.java

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -49,9 +49,6 @@ public String render(RenderingContext renderingContext) {
4949
if ( ValueHandlerFactory.isNumeric( literal ) ) {
5050
return ValueHandlerFactory.determineAppropriateHandler( (Class) literal.getClass() ).render( literal );
5151
}
52-
else if ( ValueHandlerFactory.isBoolean( literal ) ) {
53-
return ValueHandlerFactory.determineAppropriateHandler( (Class) literal.getClass() ).render( literal );
54-
}
5552

5653
// else...
5754
final String parameterName = renderingContext.registerLiteralParameterBinding( getLiteral(), getJavaType() );

hibernate-core/src/main/java/org/hibernate/query/criteria/internal/expression/SearchedCaseExpression.java

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
import java.io.Serializable;
1010
import java.util.ArrayList;
1111
import java.util.List;
12+
import java.util.function.BiFunction;
1213
import javax.persistence.criteria.CriteriaBuilder.Case;
1314
import javax.persistence.criteria.Expression;
1415

@@ -70,7 +71,7 @@ private LiteralExpression<R> buildLiteral(R result) {
7071
final Class<R> type = result != null
7172
? (Class<R>) result.getClass()
7273
: getJavaType();
73-
return new CaseLiteralExpression<R>( criteriaBuilder(), type, result );
74+
return new LiteralExpression<R>( criteriaBuilder(), type, result );
7475
}
7576

7677
public Case<R> when(Expression<Boolean> condition, Expression<? extends R> result) {
@@ -114,20 +115,33 @@ public void registerParameters(ParameterRegistry registry) {
114115
}
115116

116117
public String render(RenderingContext renderingContext) {
118+
return render(
119+
renderingContext,
120+
(Renderable expression, RenderingContext context) -> expression.render( context )
121+
);
122+
}
123+
124+
public String renderProjection(RenderingContext renderingContext) {
125+
return render(
126+
renderingContext,
127+
(Renderable expression, RenderingContext context) -> expression.renderProjection( context )
128+
);
129+
}
130+
131+
private String render(
132+
RenderingContext renderingContext,
133+
BiFunction<Renderable, RenderingContext, String> formatter) {
117134
StringBuilder caseStatement = new StringBuilder( "case" );
118135
for ( WhenClause whenClause : getWhenClauses() ) {
119136
caseStatement.append( " when " )
120-
.append( ( (Renderable) whenClause.getCondition() ).render( renderingContext ) )
137+
.append( formatter.apply( (Renderable) whenClause.getCondition(), renderingContext ) )
121138
.append( " then " )
122-
.append( ( (Renderable) whenClause.getResult() ).render( renderingContext ) );
139+
.append( formatter.apply( ((Renderable) whenClause.getResult()), renderingContext ) );
123140
}
124141
caseStatement.append( " else " )
125-
.append( ( (Renderable) getOtherwiseResult() ).render( renderingContext ) )
142+
.append( formatter.apply( (Renderable) getOtherwiseResult(), renderingContext ) )
126143
.append( " end" );
127144
return caseStatement.toString();
128145
}
129146

130-
public String renderProjection(RenderingContext renderingContext) {
131-
return render( renderingContext );
132-
}
133147
}

hibernate-core/src/main/java/org/hibernate/query/criteria/internal/expression/SimpleCaseExpression.java

Lines changed: 23 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
import java.io.Serializable;
1010
import java.util.ArrayList;
1111
import java.util.List;
12+
import java.util.function.BiFunction;
1213
import javax.persistence.criteria.CriteriaBuilder.SimpleCase;
1314
import javax.persistence.criteria.Expression;
1415

@@ -78,7 +79,7 @@ private LiteralExpression<R> buildLiteral(R result) {
7879
final Class<R> type = result != null
7980
? (Class<R>) result.getClass()
8081
: getJavaType();
81-
return new CaseLiteralExpression<R>( criteriaBuilder(), type, result );
82+
return new LiteralExpression<R>( criteriaBuilder(), type, result );
8283
}
8384

8485
public SimpleCase<C, R> when(C condition, Expression<? extends R> result) {
@@ -125,22 +126,35 @@ public void registerParameters(ParameterRegistry registry) {
125126
}
126127

127128
public String render(RenderingContext renderingContext) {
129+
return render(
130+
renderingContext,
131+
(Renderable expression, RenderingContext context) -> expression.render( context )
132+
);
133+
}
134+
135+
public String renderProjection(RenderingContext renderingContext) {
136+
return render(
137+
renderingContext,
138+
(Renderable expression, RenderingContext context) -> expression.renderProjection( context )
139+
);
140+
}
141+
142+
private String render(
143+
RenderingContext renderingContext,
144+
BiFunction<Renderable, RenderingContext, String> formatter) {
128145
StringBuilder caseExpr = new StringBuilder();
129146
caseExpr.append( "case " )
130-
.append( ( (Renderable) getExpression() ).render( renderingContext ) );
147+
.append( formatter.apply( (Renderable) getExpression(), renderingContext ) );
131148
for ( WhenClause whenClause : getWhenClauses() ) {
132149
caseExpr.append( " when " )
133-
.append( whenClause.getCondition().render( renderingContext ) )
134-
.append( " then " )
135-
.append( ( (Renderable) whenClause.getResult() ).render( renderingContext ) );
150+
.append( formatter.apply( whenClause.getCondition(), renderingContext ) )
151+
.append( " then " )
152+
.append( formatter.apply( (Renderable) whenClause.getResult(), renderingContext ) );
136153
}
137154
caseExpr.append( " else " )
138-
.append( ( (Renderable) getOtherwiseResult() ).render( renderingContext ) )
155+
.append( formatter.apply( (Renderable) getOtherwiseResult(), renderingContext ) )
139156
.append( " end" );
140157
return caseExpr.toString();
141158
}
142159

143-
public String renderProjection(RenderingContext renderingContext) {
144-
return render( renderingContext );
145-
}
146160
}

hibernate-core/src/test/java/org/hibernate/jpa/test/criteria/selectcase/SelectCaseTest.java

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,6 @@ protected Class<?>[] getAnnotatedClasses() {
5050
}
5151

5252
@Test
53-
@RequiresDialect(value = H2Dialect.class, jiraKey = "HHH-10143")
5453
public void selectCaseWithValuesShouldWork() {
5554
EntityManager entityManager = getOrCreateEntityManager();
5655
CriteriaBuilder cb = entityManager.getCriteriaBuilder();
@@ -86,7 +85,6 @@ public void selectCaseWithCastedTypeValuesShouldWork() {
8685
}
8786

8887
@Test
89-
@RequiresDialect(value = H2Dialect.class, jiraKey = "HHH-10143")
9088
public void simpleSelectCaseWithValuesShouldWork() {
9189
EntityManager entityManager = getOrCreateEntityManager();
9290

0 commit comments

Comments
 (0)