keywords as parameter names

Description

Query worked fine using Hibernate 4.2.10
Query borked using Hibernate 4.2.12
query in question:
delete from com.mrbear.Transactionrelation trel where trel.timeperiod = :TIMEPERIOD and trel.krlObject = :OBJECT and not exists ( select '' from com.mrbear.Taxationtransaction tatr where tatr.transactionrelation.transactionRelationNr = trel.transactionRelationNr )

The problem disappears when I rename :OBJECT to :KRLOBJECT.

It is possible that OBJECT is a keyword in HQL and not allowed to be used, but why then did it work in the previous version of Hibernate (4.2.10)?

I hope you can reproduce it.

caused by

Activity

Show:

Maarten van Leunen May 17, 2014 at 8:26 PM

Thanks very much for the extensive explanation. I'll keep it in mind, when writing HQL queries.

Steve Ebersole May 15, 2014 at 10:00 PM
Edited

From Gail:

... need to get a list of reserved words, at least those that were affected by this bug.

I tried a couple of random tokens in hql.g and they did not cause a problem without the fix. Do you know what other than "class" and "OBJECT" would be affected? I did notice that things like "claSs" and "object" were also affected by by the bug, so case doesn't matter.

Did this bug only affect named parameters?

It should only affect named parameters, specifically named parameters whose name is recognized as something other than an IDENT in the lexer. This will be any tokens whose text is explicitly named in the grammar (the hql.g file). As an example, look at the difference in how the ALL (or OBJECT or CLASS) token is defined versus say the FIRST token:

tokens { ALL="all"; ... CLASS="class"; ... OBJECT="object"; ... FIRST; }

This difference has an effect on the lexer. The lexer, based on the above declarations, will recognized the character sequence "all" (any case) as a token with type ALL (not IDENT!!!) and text "all". Whereas it will recognize the character sequence "first" as a token with type IDENT and text "first".

Using "all" or "object" or "class" (or any other "token literals") as a named parameter name will trigger this; meanwhile, using ":first" as a named parameter should be fine. So look through hql.g and find all the defined tokens that assign a text literal... those are the words that will trigger this if used as a named parameter name. There are some others, but this rule covers most cases.

Steve Ebersole May 15, 2014 at 2:44 PM

For reasons I cannot fully explain, adding the semantic predicates to the atom rule caused the prediction checks in the generated parser to be very different. As far as I can tell our use of k=3 in the grammar also comes into play as the predictions were checking 3 tokens out. The end result being that after COLON the parser was always looking specifically for IDENT (not allowing for keyword-turned-ident). Moving the semantic predicates (and therefore recognition of CAST/FUNCTION) to primaryExpression instead fixed the problem.

This part of the grammar (atom/primaryExpression and related sub-rules) is a mess imo. It tries to generically handle too many cases. However refactoring them to be more readable would require major changes and is best left for the new parser

Former user May 13, 2014 at 11:10 PM

15:31:41,973 DEBUG QueryTranslatorImpl:267 - parse() - HQL: from org.hibernate.test.hql.Human h where h.name = :OBJECT
15:31:41,973 ERROR ErrorCounter:54 - line 1:52: unexpected token: :
15:31:41,973 ERROR ErrorCounter:50 - line 1:52: unexpected token: :
line 1:52: unexpected token: :
at org.hibernate.hql.internal.antlr.HqlBaseParser.atom(HqlBaseParser.java:3608)
at org.hibernate.hql.internal.antlr.HqlBaseParser.unaryExpression(HqlBaseParser.java:3267)
at org.hibernate.hql.internal.antlr.HqlBaseParser.multiplyExpression(HqlBaseParser.java:3139)
at org.hibernate.hql.internal.antlr.HqlBaseParser.additiveExpression(HqlBaseParser.java:2844)
at org.hibernate.hql.internal.antlr.HqlBaseParser.concatenation(HqlBaseParser.java:582)
at org.hibernate.hql.internal.antlr.HqlBaseParser.relationalExpression(HqlBaseParser.java:2610)
at org.hibernate.hql.internal.antlr.HqlBaseParser.equalityExpression(HqlBaseParser.java:2566)
at org.hibernate.hql.internal.antlr.HqlBaseParser.negatedExpression(HqlBaseParser.java:2435)
at org.hibernate.hql.internal.antlr.HqlBaseParser.logicalAndExpression(HqlBaseParser.java:2351)
at org.hibernate.hql.internal.antlr.HqlBaseParser.logicalOrExpression(HqlBaseParser.java:2316)
at org.hibernate.hql.internal.antlr.HqlBaseParser.expression(HqlBaseParser.java:2026)
at org.hibernate.hql.internal.antlr.HqlBaseParser.logicalExpression(HqlBaseParser.java:1802)
at org.hibernate.hql.internal.antlr.HqlBaseParser.whereClause(HqlBaseParser.java:466)
at org.hibernate.hql.internal.antlr.HqlBaseParser.queryRule(HqlBaseParser.java:722)
at org.hibernate.hql.internal.antlr.HqlBaseParser.selectStatement(HqlBaseParser.java:308)
at org.hibernate.hql.internal.antlr.HqlBaseParser.statement(HqlBaseParser.java:171)
at org.hibernate.hql.internal.ast.QueryTranslatorImpl.parse(QueryTranslatorImpl.java:268)
at org.hibernate.hql.internal.ast.QueryTranslatorImpl.doCompile(QueryTranslatorImpl.java:182)
at org.hibernate.hql.internal.ast.QueryTranslatorImpl.compile(QueryTranslatorImpl.java:138)
at org.hibernate.engine.query.spi.HQLQueryPlan.<init>(HQLQueryPlan.java:104)
at org.hibernate.engine.query.spi.HQLQueryPlan.<init>(HQLQueryPlan.java:79)
at org.hibernate.engine.query.spi.QueryPlanCache.getHQLQueryPlan(QueryPlanCache.java:168)
at org.hibernate.internal.AbstractSessionImpl.getHQLQueryPlan(AbstractSessionImpl.java:222)
at org.hibernate.internal.AbstractSessionImpl.createQuery(AbstractSessionImpl.java:200)
at org.hibernate.internal.SessionImpl.createQuery(SessionImpl.java:1703)
at org.hibernate.test.hql.ASTParserLoadingTest.testObjectAsParameter(ASTParserLoadingTest.java:295)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:45)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:42)
at org.hibernate.testing.junit4.ExtendedFrameworkMethod.invokeExplosively(ExtendedFrameworkMethod.java:63)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:28)
at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:30)
at org.junit.internal.runners.statements.FailOnTimeout$StatementThread.run(FailOnTimeout.java:62)

Former user May 13, 2014 at 11:06 PM

I've added 2 tests to ASTParserLoadingTest that reproduce this issue: testClassAsParameter() (using a parameter name "class"), and testClassAsParameter() (using a parameter named "OBJECT").

It's been pushed to 4.2, 4.3, and master.

On 4.2, it was introduced by the first commit for HHH-9100: 6cef805a328c7490671f82c8390cc37b79b188ce .

Fixed

Details

Assignee

Reporter

Labels

Original estimate

Time tracking

4.82h logged8h remaining

Components

Fix versions

Affects versions

Priority

Created May 2, 2014 at 2:06 PM
Updated May 5, 2022 at 11:03 AM
Resolved May 5, 2022 at 11:03 AM