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 int joinType;
|
||||||
private boolean afterFetch;
|
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 int NONE = -666;
|
||||||
|
|
||||||
private static final Map JOIN_TYPES = new HashMap();
|
private static final Map JOIN_TYPES = new HashMap();
|
||||||
|
@ -113,15 +120,33 @@ public class FromParser implements Parser {
|
||||||
afterClass = true;
|
afterClass = true;
|
||||||
}
|
}
|
||||||
else if ( lcToken.equals( "in" ) ) {
|
else if ( lcToken.equals( "in" ) ) {
|
||||||
if ( !expectingIn ) throw new QueryException( "unexpected token: in" );
|
if (alias == null ){
|
||||||
|
memberDeclarations = true;
|
||||||
|
afterMemberDeclarations = false;
|
||||||
|
}
|
||||||
|
else if ( !expectingIn ) {
|
||||||
|
throw new QueryException( "unexpected token: in" );
|
||||||
|
} else {
|
||||||
afterIn = true;
|
afterIn = true;
|
||||||
expectingIn = false;
|
expectingIn = false;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
else if ( lcToken.equals( "as" ) ) {
|
else if ( lcToken.equals( "as" ) ) {
|
||||||
if ( !expectingAs ) throw new QueryException( "unexpected token: as" );
|
if ( !expectingAs ) throw new QueryException( "unexpected token: as" );
|
||||||
afterAs = true;
|
afterAs = true;
|
||||||
expectingAs = false;
|
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 {
|
else {
|
||||||
|
|
||||||
if ( afterJoinType ) throw new QueryException( "join expected: " + token );
|
if ( afterJoinType ) throw new QueryException( "join expected: " + token );
|
||||||
|
@ -141,6 +166,9 @@ public class FromParser implements Parser {
|
||||||
if ( entityName != null ) {
|
if ( entityName != null ) {
|
||||||
q.setAliasName( token, entityName );
|
q.setAliasName( token, entityName );
|
||||||
}
|
}
|
||||||
|
else if ( collectionName != null ) {
|
||||||
|
q.setAliasName( token, collectionName );
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
throw new QueryException( "unexpected: as " + token );
|
throw new QueryException( "unexpected: as " + token );
|
||||||
}
|
}
|
||||||
|
@ -148,6 +176,10 @@ public class FromParser implements Parser {
|
||||||
expectingJoin = true;
|
expectingJoin = true;
|
||||||
expectingAs = false;
|
expectingAs = false;
|
||||||
entityName = null;
|
entityName = null;
|
||||||
|
collectionName = null;
|
||||||
|
memberDeclarations = false;
|
||||||
|
expectingPathExpression = false;
|
||||||
|
afterMemberDeclarations = false;
|
||||||
|
|
||||||
}
|
}
|
||||||
else if ( afterIn ) {
|
else if ( afterIn ) {
|
||||||
|
@ -180,6 +212,16 @@ public class FromParser implements Parser {
|
||||||
afterClass = false;
|
afterClass = false;
|
||||||
expectingJoin = true;
|
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 {
|
else {
|
||||||
|
|
||||||
// handle a path expression or class name that
|
// handle a path expression or class name that
|
||||||
|
@ -238,6 +280,7 @@ public class FromParser implements Parser {
|
||||||
|
|
||||||
public void start(QueryTranslatorImpl q) {
|
public void start(QueryTranslatorImpl q) {
|
||||||
entityName = null;
|
entityName = null;
|
||||||
|
collectionName = null;
|
||||||
alias = null;
|
alias = null;
|
||||||
afterIn = false;
|
afterIn = false;
|
||||||
afterAs = false;
|
afterAs = false;
|
||||||
|
@ -245,10 +288,18 @@ public class FromParser implements Parser {
|
||||||
expectingJoin = false;
|
expectingJoin = false;
|
||||||
expectingIn = false;
|
expectingIn = false;
|
||||||
expectingAs = false;
|
expectingAs = false;
|
||||||
|
memberDeclarations = false;
|
||||||
|
expectingPathExpression = false;
|
||||||
|
afterMemberDeclarations = false;
|
||||||
joinType = NONE;
|
joinType = NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void end(QueryTranslatorImpl q) {
|
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" );
|
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() {
|
public void testCollectionJoinsInSubselect() {
|
||||||
// caused by some goofiness in FromElementFactory that tries to
|
// caused by some goofiness in FromElementFactory that tries to
|
||||||
// handle correlated subqueries (but fails miserably) even though this
|
// 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