ClassCastException with parameter as CASE results

Description

Hql query with CASE .. WHEN and parameter in THEN clause throws a classCastException.
Example :

Exception
java.lang.ClassCastException: org.hibernate.hql.ast.tree.ParameterNode cannot be cast to org.hibernate.hql.ast.tree.SelectExpression
at org.hibernate.hql.ast.tree.CaseNode.getFirstThenNode(CaseNode.java:44)
at org.hibernate.hql.ast.tree.CaseNode.getDataType(CaseNode.java:40)
at org.hibernate.hql.ast.tree.BinaryLogicOperatorNode.extractDataType(BinaryLogicOperatorNode.java:210)
at org.hibernate.hql.ast.tree.BinaryLogicOperatorNode.initialize(BinaryLogicOperatorNode.java:58)
at org.hibernate.hql.ast.HqlSqlWalker.prepareLogicOperator(HqlSqlWalker.java:1133)
at org.hibernate.hql.ast.HqlSqlWalker.evaluateAssignment(HqlSqlWalker.java:1043)
at org.hibernate.hql.antlr.HqlSqlBaseWalker.assignment(HqlSqlBaseWalker.java:1086)
at org.hibernate.hql.antlr.HqlSqlBaseWalker.setClause(HqlSqlBaseWalker.java:766)
at org.hibernate.hql.antlr.HqlSqlBaseWalker.updateStatement(HqlSqlBaseWalker.java:361)
at org.hibernate.hql.antlr.HqlSqlBaseWalker.statement(HqlSqlBaseWalker.java:239)
at org.hibernate.hql.ast.QueryTranslatorImpl.analyze(QueryTranslatorImpl.java:254)
at org.hibernate.hql.ast.QueryTranslatorImpl.doCompile(QueryTranslatorImpl.java:185)
at org.hibernate.hql.ast.QueryTranslatorImpl.compile(QueryTranslatorImpl.java:136)
at com.bnpparibas.eqd.DMLCaseTest.runQuery(DMLCaseTest.java:67)
at com.bnpparibas.eqd.DMLCaseTest.doesntWork(DMLCaseTest.java:35)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.junit.internal.runners.TestMethod.invoke(TestMethod.java:59)
at org.junit.internal.runners.MethodRoadie.runTestMethod(MethodRoadie.java:98)
at org.junit.internal.runners.MethodRoadie$2.run(MethodRoadie.java:79)
at org.junit.internal.runners.MethodRoadie.runBeforesThenTestThenAfters(MethodRoadie.java:87)
at org.junit.internal.runners.MethodRoadie.runTest(MethodRoadie.java:77)
at org.junit.internal.runners.MethodRoadie.run(MethodRoadie.java:42)
at org.junit.internal.runners.JUnit4ClassRunner.invokeTestMethod(JUnit4ClassRunner.java:88)
at org.junit.internal.runners.JUnit4ClassRunner.runMethods(JUnit4ClassRunner.java:51)
at org.junit.internal.runners.JUnit4ClassRunner$1.run(JUnit4ClassRunner.java:44)
at org.junit.internal.runners.ClassRoadie.runUnprotected(ClassRoadie.java:27)
at org.junit.internal.runners.ClassRoadie.runProtected(ClassRoadie.java:37)
at org.junit.internal.runners.JUnit4ClassRunner.run(JUnit4ClassRunner.java:42)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:46)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)

This issue have been posted in user forum.

It works with Hibernate 3.1.3.

A test case (designed for Hibernate 3.3.2.ga) which illustrate this issue is attached.

Environment

Hibernate 3.3.2.ga

Activity

Show:
Maxim Frolov
February 6, 2013, 6:00 PM

It affects the version 4.1.9 as well.
Please fix this!

Steve Ebersole
April 2, 2014, 8:37 PM

This one is tougher to fix than HHH-6747. Its easy enough to work around the CCE. The real problem is being able to actually resolve the type for the case statement. If the "results" (the `then` clauses) are all parameters we cannot properly determine the overall type.

Steve Ebersole
April 3, 2014, 11:56 AM
Edited

As I said in the previous comment, the current problem is in resolving the Type for the CASE overall. For example, in the CASE:

we can interpret the overall Type for the case, because one of the results is Typed (here, the ELSE result). However, when all the possible results are parameters we cannot resolve the Type:


The only solution I can think of for that problem is to require CASTing the parameters:

(at least one of them):

or CASTing the CASE statement overall:

BTW, the query in the original report is not conceptually valid since it gives no ELSE result.

Jean-Baptiste Mille
April 3, 2014, 12:19 PM

Syntaxe without ELSE could be valid if no update is expected when WHEN clause is wrong (like it was done in Hibernate 3.1.3).

Steve Ebersole
April 3, 2014, 1:38 PM

As I said, the query in the initial report is not conceptually valid. You'd have to assume that updating all rows in `MyObject` would include rows that do NOT match the WHEN, otherwise why even waste time/resources having the CASE.

Assignee

Steve Ebersole

Reporter

Jean-Baptiste Mille

Fix versions

Labels

None

backPortable

None

Suitable for new contributors

None

Requires Release Note

None

Pull Request

None

backportDecision

None

Components

Priority

Minor
Configure