HHH-5727 Collection member declaration not handling optional AS in HQL.
This commit is contained in:
parent
55e27c3825
commit
4c7983151c
|
@ -52,6 +52,13 @@ public class FromParser implements Parser {
|
|||
private int joinType;
|
||||
private boolean afterFetch;
|
||||
|
||||
//support collection member declarations
|
||||
//e.g. "from Customer c, in(c.orders) as o"
|
||||
private boolean memberDeclarations;
|
||||
private boolean expectingPathExpression;
|
||||
private boolean afterMemberDeclarations;
|
||||
private String collectionName;
|
||||
|
||||
private static final int NONE = -666;
|
||||
|
||||
private static final Map JOIN_TYPES = new HashMap();
|
||||
|
@ -113,15 +120,33 @@ public class FromParser implements Parser {
|
|||
afterClass = true;
|
||||
}
|
||||
else if ( lcToken.equals( "in" ) ) {
|
||||
if ( !expectingIn ) throw new QueryException( "unexpected token: in" );
|
||||
afterIn = true;
|
||||
expectingIn = false;
|
||||
if (alias == null ){
|
||||
memberDeclarations = true;
|
||||
afterMemberDeclarations = false;
|
||||
}
|
||||
else if ( !expectingIn ) {
|
||||
throw new QueryException( "unexpected token: in" );
|
||||
} else {
|
||||
afterIn = true;
|
||||
expectingIn = false;
|
||||
}
|
||||
}
|
||||
else if ( lcToken.equals( "as" ) ) {
|
||||
if ( !expectingAs ) throw new QueryException( "unexpected token: as" );
|
||||
afterAs = true;
|
||||
expectingAs = false;
|
||||
}
|
||||
else if ( "(".equals( token ) ){
|
||||
if( !memberDeclarations ) throw new QueryException( "unexpected token: (" );
|
||||
//TODO alias should be null here
|
||||
expectingPathExpression = true;
|
||||
|
||||
}
|
||||
else if ( ")".equals( token ) ){
|
||||
// memberDeclarations = false;
|
||||
// expectingPathExpression = false;
|
||||
afterMemberDeclarations = true;
|
||||
}
|
||||
else {
|
||||
|
||||
if ( afterJoinType ) throw new QueryException( "join expected: " + token );
|
||||
|
@ -141,6 +166,9 @@ public class FromParser implements Parser {
|
|||
if ( entityName != null ) {
|
||||
q.setAliasName( token, entityName );
|
||||
}
|
||||
else if ( collectionName != null ) {
|
||||
q.setAliasName( token, collectionName );
|
||||
}
|
||||
else {
|
||||
throw new QueryException( "unexpected: as " + token );
|
||||
}
|
||||
|
@ -148,6 +176,10 @@ public class FromParser implements Parser {
|
|||
expectingJoin = true;
|
||||
expectingAs = false;
|
||||
entityName = null;
|
||||
collectionName = null;
|
||||
memberDeclarations = false;
|
||||
expectingPathExpression = false;
|
||||
afterMemberDeclarations = false;
|
||||
|
||||
}
|
||||
else if ( afterIn ) {
|
||||
|
@ -180,6 +212,16 @@ public class FromParser implements Parser {
|
|||
afterClass = false;
|
||||
expectingJoin = true;
|
||||
}
|
||||
else if( memberDeclarations && expectingPathExpression ){
|
||||
expectingAs = true;
|
||||
peParser.setJoinType( JoinFragment.INNER_JOIN );
|
||||
peParser.setUseThetaStyleJoin( false );
|
||||
ParserHelper.parse( peParser, q.unalias( token ), ParserHelper.PATH_SEPARATORS, q );
|
||||
if ( !peParser.isCollectionValued() ) throw new QueryException( "path expression did not resolve to collection: " + token );
|
||||
collectionName = peParser.addFromCollection( q );
|
||||
expectingPathExpression = false;
|
||||
memberDeclarations = false;
|
||||
}
|
||||
else {
|
||||
|
||||
// handle a path expression or class name that
|
||||
|
@ -238,6 +280,7 @@ public class FromParser implements Parser {
|
|||
|
||||
public void start(QueryTranslatorImpl q) {
|
||||
entityName = null;
|
||||
collectionName = null;
|
||||
alias = null;
|
||||
afterIn = false;
|
||||
afterAs = false;
|
||||
|
@ -245,10 +288,18 @@ public class FromParser implements Parser {
|
|||
expectingJoin = false;
|
||||
expectingIn = false;
|
||||
expectingAs = false;
|
||||
memberDeclarations = false;
|
||||
expectingPathExpression = false;
|
||||
afterMemberDeclarations = false;
|
||||
joinType = NONE;
|
||||
}
|
||||
|
||||
public void end(QueryTranslatorImpl q) {
|
||||
if( afterMemberDeclarations ){
|
||||
//The exception throwned by the AST query translator contains the error token location, respensent by line and colum,
|
||||
//but it hard to get that info here.
|
||||
throw new QueryException("alias not specified for IN");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,36 +0,0 @@
|
|||
package org.hibernate.test.hql;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.persistence.CascadeType;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.OneToMany;
|
||||
|
||||
@Entity
|
||||
public class EntityBean {
|
||||
@Id
|
||||
@GeneratedValue
|
||||
private Long id;
|
||||
|
||||
@OneToMany(cascade=CascadeType.ALL)
|
||||
private Set<Item> items = new HashSet<Item>();
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public Set<Item> getItems() {
|
||||
return items;
|
||||
}
|
||||
|
||||
public void setItems(Set<Item> items) {
|
||||
this.items = items;
|
||||
}
|
||||
}
|
|
@ -1,39 +0,0 @@
|
|||
package org.hibernate.test.hql;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.hibernate.Query;
|
||||
import org.hibernate.Session;
|
||||
import org.hibernate.test.annotations.TestCase;
|
||||
|
||||
public class EntityBeanTest extends TestCase {
|
||||
|
||||
|
||||
@Override
|
||||
protected Class<?>[] getAnnotatedClasses() {
|
||||
return new Class[]{EntityBean.class,Item.class};
|
||||
}
|
||||
public void testAAA(){
|
||||
Session s=openSession();
|
||||
s.beginTransaction();
|
||||
Item item = new Item();
|
||||
item.setItemValue("1");
|
||||
EntityBean eb = new EntityBean();
|
||||
eb.getItems().add(item);
|
||||
item=new Item();
|
||||
item.setItemValue("2");
|
||||
eb.getItems().add(item);
|
||||
s.persist(eb);
|
||||
s.getTransaction().commit();
|
||||
s.close();
|
||||
|
||||
s=openSession();
|
||||
s.beginTransaction();
|
||||
Query query = s.createQuery("SELECT o FROM EntityBean AS o, IN (o.items) l WHERE l.itemValue = '1'");
|
||||
List list = query.list();
|
||||
assertEquals(list.size(), 1);
|
||||
s.getTransaction().commit();
|
||||
s.close();
|
||||
}
|
||||
|
||||
}
|
|
@ -145,6 +145,19 @@ public class HQLTest extends QueryTranslatorTestCase {
|
|||
assertTranslation( "select h from Human as h join fetch h.nickNames" );
|
||||
}
|
||||
|
||||
public void testCollectionMemberDeclarations() {
|
||||
assertTranslation( "from Customer c, in(c.orders) o" );
|
||||
assertTranslation( "from Customer c, in(c.orders) as o" );
|
||||
assertTranslation( "select c.name from Customer c, in(c.orders) as o where c.id = o.id.customerId" );
|
||||
}
|
||||
public void testCollectionMemberDeclarationsFailureExpected(){
|
||||
// both these two query translators throw exeptions for this HQL since
|
||||
// IN asks an alias, but the difference is that the error message from AST
|
||||
// contains the error token location (by lines and columns), which is hardly
|
||||
// to get from Classic query translator --stliu
|
||||
assertTranslation( "from Customer c, in(c.orders)" );
|
||||
}
|
||||
|
||||
public void testCollectionJoinsInSubselect() {
|
||||
// caused by some goofiness in FromElementFactory that tries to
|
||||
// handle correlated subqueries (but fails miserably) even though this
|
||||
|
|
|
@ -1,32 +0,0 @@
|
|||
package org.hibernate.test.hql;
|
||||
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.Id;
|
||||
|
||||
@Entity
|
||||
public class Item {
|
||||
@Id
|
||||
@GeneratedValue
|
||||
private Long id;
|
||||
|
||||
private String itemValue;
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
|
||||
public String getItemValue() {
|
||||
return itemValue;
|
||||
}
|
||||
|
||||
public void setItemValue(String itemValue) {
|
||||
this.itemValue = itemValue;
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue