Fix missing parenthesis around composite properties in WHERE clauses

The currentClauseType field would not be correct if the query contained a
subquery.

Signed-off-by: Andrea Boriero <andrea@hibernate.org>
This commit is contained in:
Eskil Bylund 2012-08-09 12:53:38 +02:00 committed by Andrea Boriero
parent e150a6140e
commit 5cc2175033
3 changed files with 78 additions and 4 deletions

View File

@ -2,6 +2,8 @@ header
{
package org.hibernate.hql.internal.antlr;
import java.util.Stack;
import org.hibernate.internal.CoreMessageLogger;
import org.jboss.logging.Logger;
}
@ -75,6 +77,7 @@ tokens
private int currentClauseType;
private int currentTopLevelClauseType;
private int currentStatementType;
private Stack<Integer> parentClauses = new Stack<Integer>();
public final boolean isSubQuery() {
return level > 1;
@ -153,12 +156,17 @@ tokens
}
private void handleClauseStart(int clauseType) {
parentClauses.push(currentClauseType);
currentClauseType = clauseType;
if ( level == 1 ) {
currentTopLevelClauseType = clauseType;
}
}
private void handleClauseEnd() {
currentClauseType = parentClauses.pop();
}
///////////////////////////////////////////////////////////////////////////
// NOTE: The real implementations for the following are in the subclass.
@ -300,6 +308,7 @@ intoClause! {
}
: #( INTO { handleClauseStart( INTO ); } (p=path) ps:insertablePropertySpec ) {
#intoClause = createIntoClause(p, ps);
handleClauseEnd();
}
;
@ -308,7 +317,9 @@ insertablePropertySpec
;
setClause
: #( SET { handleClauseStart( SET ); } (assignment)* )
: #( SET { handleClauseStart( SET ); } (assignment)* ) {
handleClauseEnd();
}
;
assignment
@ -346,7 +357,9 @@ query!
;
orderClause
: #(ORDER { handleClauseStart( ORDER ); } orderExprs)
: #(ORDER { handleClauseStart( ORDER ); } orderExprs) {
handleClauseEnd();
}
;
orderExprs
@ -376,12 +389,15 @@ resultVariableRef!
;
groupClause
: #(GROUP { handleClauseStart( GROUP ); } (expr)+ ( #(HAVING logicalExpr) )? )
: #(GROUP { handleClauseStart( GROUP ); } (expr)+ ( #(HAVING logicalExpr) )? ) {
handleClauseEnd();
}
;
selectClause!
: #(SELECT { handleClauseStart( SELECT ); beforeSelectClause(); } (d:DISTINCT)? x:selectExprList ) {
#selectClause = #([SELECT_CLAUSE,"{select clause}"], #d, #x);
handleClauseEnd();
}
;
@ -439,7 +455,9 @@ fromClause {
// the ouput AST (#fromClause) has not been built yet.
prepareFromClauseInputTree(#fromClause_in);
}
: #(f:FROM { pushFromClause(#fromClause,f); handleClauseStart( FROM ); } fromElementList )
: #(f:FROM { pushFromClause(#fromClause,f); handleClauseStart( FROM ); } fromElementList ) {
handleClauseEnd();
}
;
fromElementList {
@ -530,6 +548,7 @@ withClause
// rule during recognition...
: #(w:WITH { handleClauseStart( WITH ); } b:logicalExpr ) {
#withClause = #(w , #b);
handleClauseEnd();
}
;
@ -537,6 +556,7 @@ whereClause
: #(w:WHERE { handleClauseStart( WHERE ); } b:logicalExpr ) {
// Use the *output* AST for the boolean expression!
#whereClause = #(w , #b);
handleClauseEnd();
}
;

View File

@ -18,6 +18,14 @@ public class CompositeId implements Serializable {
private int id1;
private int id2;
public CompositeId() {
}
public CompositeId(int id1, int id2) {
this.id1 = id1;
this.id2 = id2;
}
public int getId1() {
return id1;
}

View File

@ -0,0 +1,46 @@
package org.hibernate.jpa.test;
import javax.persistence.EntityManager;
import javax.persistence.Query;
import org.hibernate.dialect.Dialect;
import org.hibernate.dialect.H2Dialect;
import org.junit.Test;
import org.hibernate.testing.TestForIssue;
import static org.junit.Assert.assertThat;
import static org.hamcrest.core.Is.is;
@TestForIssue( jiraKey = "HHH-9029")
public class CompositeIdRowValueTest extends BaseEntityManagerFunctionalTestCase {
@Override
protected Dialect getDialect() {
return new RowValueConstructorDialect();
}
@Test
public void testTupleAfterSubQuery() {
EntityManager em = getOrCreateEntityManager();
Query q = em.createQuery("SELECT e FROM EntityWithCompositeId e "
+ "WHERE EXISTS (SELECT 1 FROM EntityWithCompositeId) "
+ "AND e.id = :id");
q.setParameter("id", new CompositeId(1, 2));
assertThat(q.getResultList().size(), is(0));
}
@Override
protected Class[] getAnnotatedClasses() {
return new Class[] {EntityWithCompositeId.class, CompositeId.class};
}
public static class RowValueConstructorDialect extends H2Dialect {
@Override
public boolean supportsRowValueConstructorSyntax() {
return true;
}
}
}