diff --git a/hibernate-core/src/main/antlr/hql-sql.g b/hibernate-core/src/main/antlr/hql-sql.g index ca7b63225f..90fb1e32d6 100644 --- a/hibernate-core/src/main/antlr/hql-sql.g +++ b/hibernate-core/src/main/antlr/hql-sql.g @@ -611,10 +611,36 @@ arithmeticExpr ; caseExpr - : #(CASE { inCase = true; } (#(WHEN logicalExpr expr))+ (#(ELSE expr))?) { inCase = false; } - | #(CASE2 { inCase = true; } expr (#(WHEN expr expr))+ (#(ELSE expr))?) { inCase = false; } + : simpleCaseExpression + | searchedCaseExpression ; +expressionOrSubQuery + : expr + | query + ; + +simpleCaseExpression + : #(CASE2 {inCase=true;} expressionOrSubQuery (simpleCaseWhenClause)+ (elseClause)?) {inCase=false;} + ; + +simpleCaseWhenClause + : #(WHEN expressionOrSubQuery expressionOrSubQuery) + ; + +elseClause + : #(ELSE expressionOrSubQuery) + ; + +searchedCaseExpression + : #(CASE {inCase = true;} (searchedCaseWhenClause)+ (elseClause)?) {inCase = false;} + ; + +searchedCaseWhenClause + : #(WHEN logicalExpr expressionOrSubQuery) + ; + + //TODO: I don't think we need this anymore .. how is it different to // maxelements, etc, which are handled by functionCall collectionFunction diff --git a/hibernate-core/src/main/antlr/hql.g b/hibernate-core/src/main/antlr/hql.g index c4b72d0f69..49d519cdbc 100644 --- a/hibernate-core/src/main/antlr/hql.g +++ b/hibernate-core/src/main/antlr/hql.g @@ -639,23 +639,34 @@ unaryExpression | quantifiedExpression | atom ; - + caseExpression - : CASE^ (whenClause)+ (elseClause)? END! - | CASE^ { #CASE.setType(CASE2); } unaryExpression (altWhenClause)+ (elseClause)? END! + // NOTE : the unaryExpression rule contains the subQuery rule + : simpleCaseStatement + | searchedCaseStatement ; - -whenClause - : (WHEN^ logicalExpression THEN! unaryExpression) + +simpleCaseStatement + : CASE^ unaryExpression (simpleCaseWhenClause)+ (elseClause)? END! { + #simpleCaseStatement.setType(CASE2); + } ; - -altWhenClause + +simpleCaseWhenClause : (WHEN^ unaryExpression THEN! unaryExpression) ; - + elseClause : (ELSE^ unaryExpression) ; + +searchedCaseStatement + : CASE^ (searchedCaseWhenClause)+ (elseClause)? END! + ; + +searchedCaseWhenClause + : (WHEN^ logicalExpression THEN! unaryExpression) + ; quantifiedExpression : ( SOME^ | EXISTS^ | ALL^ | ANY^ ) diff --git a/hibernate-core/src/test/java/org/hibernate/test/hql/SubQueryTest.java b/hibernate-core/src/test/java/org/hibernate/test/hql/SubQueryTest.java index e0541b1d1f..f04f13332a 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/hql/SubQueryTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/hql/SubQueryTest.java @@ -17,6 +17,7 @@ import javax.persistence.Table; import org.hibernate.Session; +import org.hibernate.testing.FailureExpected; import org.hibernate.testing.TestForIssue; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; import org.junit.Test; @@ -155,4 +156,64 @@ public class SubQueryTest extends BaseCoreFunctionalTestCase { s.close(); } + + @Test + @TestForIssue( jiraKey = "HHH-1689, SQM-30" ) + public void testSubQueryAsSearchedCaseResultExpression() { + final String query = "SELECT CASE WHEN l.id IS NOT NULL THEN (SELECT COUNT(r.id) FROM Root r) ELSE 0 END FROM Leaf l"; + // simple syntax check + Session s = openSession(); + s.beginTransaction(); + s.createQuery( query ).list(); + s.getTransaction().commit(); + s.close(); + } + + @Test + @TestForIssue( jiraKey = "HHH-1689, SQM-30" ) + public void testSubQueryAsSearchedCaseExpression() { + final String query = "SELECT CASE WHEN (SELECT COUNT(r.id) FROM Root r) > 1 THEN 1 ELSE 0 END FROM Leaf l"; + // simple syntax check + Session s = openSession(); + s.beginTransaction(); + s.createQuery( query ).list(); + s.getTransaction().commit(); + s.close(); + } + + @Test + @TestForIssue( jiraKey = "HHH-1689, SQM-30" ) + public void testSubQueryAsCaseElseResultExpression() { + final String query = "SELECT CASE WHEN l.id > 1 THEN 1 ELSE (SELECT COUNT(r.id) FROM Root r) END FROM Leaf l"; + // simple syntax check + Session s = openSession(); + s.beginTransaction(); + s.createQuery( query ).list(); + s.getTransaction().commit(); + s.close(); + } + + @Test + @TestForIssue( jiraKey = "HHH-1689, SQM-30" ) + public void testSubQueryAsSimpleCaseTestExpression() { + final String query = "SELECT CASE (SELECT COUNT(r.id) FROM Root r) WHEN 1 THEN 1 ELSE 0 END FROM Leaf l"; + // simple syntax check + Session s = openSession(); + s.beginTransaction(); + s.createQuery( query ).list(); + s.getTransaction().commit(); + s.close(); + } + + @Test + @TestForIssue( jiraKey = "HHH-1689, SQM-30" ) + public void testSubQueryAsSimpleCaseWhenExpression() { + final String query = "SELECT CASE l.id WHEN (SELECT COUNT(r.id) FROM Root r) THEN 1 ELSE 0 END FROM Leaf l"; + // simple syntax check + Session s = openSession(); + s.beginTransaction(); + s.createQuery( query ).list(); + s.getTransaction().commit(); + s.close(); + } }