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:
parent
e150a6140e
commit
5cc2175033
|
@ -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();
|
||||
}
|
||||
;
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue