antlr.NoViableAltException: unexpected AST node: :

678 views
Skip to first unread message

Mohammad Als

unread,
Nov 29, 2015, 6:33:17 AM11/29/15
to Jinq
I just started learning Jinq. Here's my Entity classes and the Dao.

@MappedSuperclass
public abstract class BaseModel{

@Id @GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "id", nullable = false, unique = true)
Long id;

@Column(columnDefinition = "datetime")
Timestamp created;
}

@Entity
@Table(name = "addresses")
public class Address extends BaseModel implements Serializable{
private String street, city, state, country, postcode;

@ManyToOne
private Person owner;
}

@Entity
@Table(name = "persons")
public class Person extends BaseModel implements Serializable{
private String surname;
private String givenName;

@OneToMany(mappedBy = "owner", cascade = CascadeType.ALL)
private List<Address> addresses = new ArrayList<>();

@Temporal(javax.persistence.TemporalType.DATE)
private Date birthDay;
}

The Dao class is as below:

public class PersonRepositoryImpl extends AbstractRepository<Person> implements PersonsRepository {

private final JinqStream<Person> allPeople = stream.streamAll(em, Person.class);
    @Override
    public Person findById(Long id) {
return allPeople.where(p->p.getId() == id).findAny().get();
}

@Override
public List<Person> getByAddress(Address address) {
List<Person> people = addresses
.where(add->add.getCity().equals(address.getCity()))
.where(add->add.getState().equals(address.getState()))
.where(add->add.getStreet().equals(address.getStreet()))
.where(add->add.getCountry().equals(address.getCountry()))
.where(add->add.getPostcode().equals(address.getPostcode()))
.select(add->add.getOwner()).toList();
LOGGER.debug("People residing at Address:" + address + " " + people);
return people;
}
}

Whenever I'm trying to get a List of people residing at a given address I'm getting the following exception:

15:42:05.378 [main] DEBUG o.h.hql.internal.ast.ErrorCounter - throwQueryException() : no errors
15:42:05.403 [main] DEBUG o.h.h.i.antlr.HqlSqlBaseWalker - select << begin [level=1, statement=select]
15:42:05.418 [main] DEBUG o.h.h.internal.ast.tree.FromElement - FromClause{level=1} : helene.labs.jinq.model.Address (A) -> address0_
15:42:05.420 [main] DEBUG o.h.h.i.ast.tree.FromReferenceNode - Resolved : A -> address0_.id
15:42:05.421 [main] DEBUG o.h.hql.internal.ast.tree.DotNode - getDataType() : owner -> org.hibernate.type.ManyToOneType(helene.labs.jinq.model.Person)
15:42:05.421 [main] DEBUG o.h.hql.internal.ast.tree.DotNode - dereferenceEntityJoin() : generating join for owner in helene.labs.jinq.model.Address (<no alias>) parent = [ {null} ]
15:42:05.423 [main] DEBUG o.h.h.internal.ast.tree.FromElement - FromClause{level=1} : helene.labs.jinq.model.Person (<no alias>) -> person1_
15:42:05.423 [main] DEBUG o.h.hql.internal.ast.tree.FromClause - addJoinByPathMap() : A.owner -> FromElement{explicit,not a collection join,not a fetch join,fetch non-lazy properties,classAlias=null,role=null,tableName=persons,tableAlias=person1_,origin=addresses address0_,columns={address0_.owner_id ,className=helene.labs.jinq.model.Person}}
15:42:05.424 [main] DEBUG o.h.h.i.ast.tree.FromReferenceNode - Resolved : A.owner -> address0_.owner_id
15:42:05.427 [main] DEBUG o.h.h.i.ast.tree.FromReferenceNode - Resolved : A -> address0_.id
15:42:05.427 [main] DEBUG o.h.hql.internal.ast.tree.DotNode - getDataType() : city -> org.hibernate.type.StringType@5bf0d49
15:42:05.428 [main] DEBUG o.h.h.i.ast.tree.FromReferenceNode - Resolved : A.city -> address0_.city
15:42:05.429 [main] ERROR o.h.hql.internal.ast.ErrorCounter - <AST>:1:69: unexpected AST node: :
15:42:05.436 [main] ERROR o.h.hql.internal.ast.ErrorCounter - <AST>:1:69: unexpected AST node: :
antlr.NoViableAltException: unexpected AST node: :
	at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.addrExpr(HqlSqlBaseWalker.java:5022) [hibernate-core-4.3.1.Final.jar:4.3.1.Final]
	at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.addrExprLhs(HqlSqlBaseWalker.java:5337) [hibernate-core-4.3.1.Final.jar:4.3.1.Final]
	at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.addrExpr(HqlSqlBaseWalker.java:4917) [hibernate-core-4.3.1.Final.jar:4.3.1.Final]
	at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.expr(HqlSqlBaseWalker.java:1260) [hibernate-core-4.3.1.Final.jar:4.3.1.Final]

Mohammad Als

unread,
Nov 29, 2015, 6:48:24 AM11/29/15
to Jinq
However, the error goes when I pass extracted strings:

@Override
public List<Person> getByAddress(final Address address) {
final String city = address.getCity();
final String country = address.getCountry();
final String postcode = address.getPostcode();
final String state = address.getState();
final String street = address.getStreet();

List<Person> people = addresses
            .where(add->add.getCity().equals(city))
.where(add->add.getState().equals(state))
.where(add->add.getStreet().equals(street))
.where(add->add.getCountry().equals(country))
.where(add->add.getPostcode().equals(postcode))

.select(add->add.getOwner()).toList();
LOGGER.debug("People residing at Address:" + address + " " + people);
return people;
}

Jinq

unread,
Nov 29, 2015, 7:19:31 AM11/29/15
to Jinq
Yes, Hibernate and JPA in general are a little, um, inconsistent in their query models. They've added support for various features, but only in a rudimentary way, and then they didn't bother doing the extra work to handle all the corner cases and such. Unfortunately, Jinq really pushes against a lot of those corner cases. I haven't quite figured out how to deal with these issues. If Jinq only supported the parts of Hibernate and JPA that have been fully specified and are consistent, Jinq would be missing a lot of functionality. By supporting many of these murky parts of the spec though, Jinq exposes many of those corner cases to programmers, who might get stuck in them.

The corner case that you're hitting against in Hibernate is that you can pass in entities as parameters to queries, but you can't access fields on those entities.

So this is fine in JPA (you can pass an Address entity as a parameter to a query):

   addresses.where( add -> add.equals(address));

This is fine is JPA (you can pass in simple types as parameters to a query)

   String city = address.getCity();
   String postCode = address.getPostCode();
   addresses.where( add -> add.getCity().equals(city))
      .where( add -> add.getPostCode.equals(postCode) )

This doesn't work because Hibernate and JPA don't handle the corner case of letting you access the fields of the Address entity that you passed in to the query:

   addresses.where( add -> add.getCity().equals(address.getCity()))
      .where( add -> add.getPostCode.equals(address.getPostCode()) )

Mohammad Als

unread,
Nov 29, 2015, 8:09:00 AM11/29/15
to Jinq
I've implemented the equals and hashcode of the Address class.
However, doing addresses.equals() results in "Could not analyze lambda code". Here's the stacktrace

java.lang.IllegalArgumentException: Could not analyze lambda code at org.jinq.jpa.transform.LambdaAnalysis.fullyAnalyzeLambda(LambdaAnalysis.java:197) at org.jinq.jpa.transform.LambdaInfo.fullyAnalyze(LambdaInfo.java:116) at org.jinq.jpa.JPAQueryComposer.applyTransformWithLambda(JPAQueryComposer.java:278) at org.jinq.jpa.JPAQueryComposer.where(JPAQueryComposer.java:364) at org.jinq.jpa.JPAQueryComposer.where(JPAQueryComposer.java:58) at org.jinq.orm.stream.QueryJinqStream.where(QueryJinqStream.java:45) at org.jinq.jpa.QueryJPAJinqStream.where(QueryJPAJinqStream.java:86) at org.jinq.jpa.QueryJPAJinqStream.where(QueryJPAJinqStream.java:12) at helene.labs.jinq.dao.PersonRepositoryImpl.getByAddress(PersonRepositoryImpl.java:70) at helene.labs.jinq.service.PersonJinqService.lambda$getByAddress$5(PersonJinqService.java:32) at helene.labs.jinq.service.PersonJinqService$$Lambda$2/2052489518.f(Unknown Source) at fj.data.Reader.f(Reader.java:31) at helene.labs.test.jinq.Application.run(Application.java:64) at helene.labs.test.jinq.Application.getByAddress(Application.java:42) at helene.labs.test.jinq.PersonJinqServiceDITest.findByAddress(PersonJinqServiceDITest.java:102) Caused by: org.jinq.rebased.org.objectweb.asm.tree.analysis.AnalyzerException: Unknown method helene/labs/jinq/model/Address:equals(Ljava/lang/Object;)Z encountered at ch.epfl.labos.iu.orm.queryll2.symbolic.BasicSymbolicInterpreter.naryOperation(BasicSymbolicInterpreter.java:367) at org.jinq.rebased.org.objectweb.asm.tree.analysis.Frame.execute(Unknown Source) at ch.epfl.labos.iu.orm.queryll2.path.CodePath.calculateReturnValueAndConditions(CodePath.java:148) at ch.epfl.labos.iu.orm.queryll2.path.TransformationClassAnalyzer.analyzeMethod(TransformationClassAnalyzer.java:440) at ch.epfl.labos.iu.orm.queryll2.path.TransformationClassAnalyzer.analyzeLambdaMethod(TransformationClassAnalyzer.java:406) at org.jinq.jpa.transform.LambdaAnalysis.analyzeLambda(LambdaAnalysis.java:318) at org.jinq.jpa.transform.LambdaAnalysis.fullyAnalyzeLambda(LambdaAnalysis.java:187) ... 47 more


On Sunday, November 29, 2015 at 5:03:17 PM UTC+5:30, Mohammad Als wrote:

Jinq

unread,
Nov 29, 2015, 12:37:25 PM11/29/15
to Jinq
Oh, good point. That issue is on me.

Jinq doesn't know about Address.equals(), so you would have to use == instead.

   addresses.where( add -> add == address);

I guess I should have a better error message there or change Jinq so that it would assume that Address.equals() is safe.

Mohammad Als

unread,
Nov 30, 2015, 3:52:14 AM11/30/15
to Jinq, jinq-...@googlegroups.com
I suppose == compares on the basis of id field whereas, I'm trying to compare two objects and id is not a parameter to the two objects hence this doesn't work.

14:00:11.690 [main] DEBUG o.h.h.i.ast.QueryTranslatorImpl - HQL: SELECT A FROM helene.labs.jinq.model.Address A WHERE A = :param0
14:00:11.690 [main] DEBUG o.h.h.i.ast.QueryTranslatorImpl - SQL: select address0_.id as id1_0_, address0_.created as created2_0_, address0_.city as city3_0_, address0_.country as country4_0_, address0_.owner_id as owner_id8_0_, address0_.postcode as postcode5_0_, address0_.state as state6_0_, address0_.street as street7_0_ from addresses address0_ where address0_.id=?
14:00:11.690 [main] DEBUG o.h.hql.internal.ast.ErrorCounter - throwQueryException() : no errors
14:00:11.691 [main] DEBUG org.hibernate.SQL - select address0_.id as id1_0_, address0_.created as created2_0_, address0_.city as city3_0_, address0_.country as country4_0_, address0_.owner_id as owner_id8_0_, address0_.postcode as postcode5_0_, address0_.state as state6_0_, address0_.street as street7_0_ from addresses address0_ where address0_.id=? limit ?
Hibernate: select address0_.id as id1_0_, address0_.created as created2_0_, address0_.city as city3_0_, address0_.country as country4_0_, address0_.owner_id as owner_id8_0_, address0_.postcode as postcode5_0_, address0_.state as state6_0_, address0_.street as street7_0_ from addresses address0_ where address0_.id=? limit ?
14:00:11.692 [main] DEBUG o.h.j.spi.AbstractEntityManagerImpl - Mark transaction for rollback

Jinq

unread,
Nov 30, 2015, 4:01:21 AM11/30/15
to Jinq


On Monday, 30 November 2015 03:52:14 UTC-5, Mohammad Als wrote:
I suppose == compares on the basis of id field whereas, I'm trying to compare two objects and id is not a parameter to the two objects hence this doesn't work.


In that case, you'll have to do what you originally did and store each field of the parameter in a local variable and then compare each field against the corresponding local variable. 
Reply all
Reply to author
Forward
0 new messages