Hi.
I ran into a problem that seems exactly the same as this thread.
I'd like to provide some HQL AST logs, that might help diagnose the problem.
I give an alias to an expression in the select clause, try to refer it in the where clause. In SQL, Hibernate replaces the alias in the select clause, but leaves the original text in the where clause. I believe this is a bug (though that wouldn't turn down my applause to hibernate).
My environment is
DB: MySQL5 on Solarisx86
App: Hibernate3.2 on Win2K
This is the HQL:
Code:
select (p.endDate - p.startDate) as [color=red]period[/color], p
from Project as p
where [color=red]period [/color]> :period_length
See above where the alias 'period' appears.
Now, This is the resulting SQL:
Code:
select
project0_.end_date-project0_.start_date as [color=blue]col_0_0_[/color],
project0_.id as col_1_0_,
project0_.id as id0_,
project0_.name as name0_,
project0_.start_date as start3_0_,
project0_.end_date as end4_0_
from PROJECT project0_ where [color=blue]period[/color]>?
Note above the 'period' that was in the select clause is replaced with machine generated "col_0_0_", but that is not applied for the alias in the where clause.
The following are the AST dumps in the hibernate logs.
Here is the AST (is that abstract syntax tree?) of the HQL:
Code:
DEBUG [main] (QueryTranslatorImpl.java:266) - --- HQL AST ---
\-[QUERY] 'query'
+-[SELECT_FROM] 'SELECT_FROM'
| +-[FROM] 'from'
| | \-[RANGE] 'RANGE'
| | +-[DOT] '.'
| | | +-[IDENT] 'entities'
| | | \-[IDENT] 'Project'
| | \-[ALIAS] 'p'
| \-[SELECT] 'select'
| +-[AS] 'as'
| | +-[MINUS] '-'
| | | +-[DOT] '.'
| | | | +-[IDENT] 'p'
| | | | \-[IDENT] 'endDate'
| | | \-[DOT] '.'
| | | +-[IDENT] 'p'
| | | \-[IDENT] 'startDate'
| | \-[IDENT] 'period'
| \-[IDENT] 'p'
\-[WHERE] 'where'
\-[GT] '>'
+-[IDENT] 'period'
\-[COLON] ':'
\-[IDENT] 'period_length'
Doesn't look bad to me.
And here is the AST of the SQL:
Code:
DEBUG [main] (QueryTranslatorImpl.java:232) - --- SQL AST ---
\-[SELECT] QueryNode: 'SELECT' querySpaces (PROJECT)
+-[SELECT_CLAUSE] SelectClause: '{select clause}'
| +-[MINUS] BinaryArithmeticOperatorNode: '-' {dataType=org.hibernate.type.DoubleType@1ffc686}
| | +-[DOT] DotNode: 'project0_.end_date' {propertyName=endDate,dereferenceType=4,propertyPath=endDate,path=p.endDate,tableAlias=project0_,className=entities.Project,classAlias=p}
| | | +-[ALIAS_REF] IdentNode: 'project0_.id' {alias=p, className=entities.Project, tableAlias=project0_}
| | | \-[IDENT] IdentNode: 'endDate' {originalText=endDate}
| | \-[DOT] DotNode: 'project0_.start_date' {propertyName=startDate,dereferenceType=4,propertyPath=startDate,path=p.startDate,tableAlias=project0_,className=entities.Project,classAlias=p}
| | +-[ALIAS_REF] IdentNode: 'project0_.id' {alias=p, className=entities.Project, tableAlias=project0_}
| | \-[IDENT] IdentNode: 'startDate' {originalText=startDate}
| [color=red]+-[SELECT_COLUMNS] SqlNode: ' as col_0_0_'[/color]
| +-[ALIAS_REF] IdentNode: 'project0_.id as col_1_0_' {alias=p, className=entities.Project, tableAlias=project0_}
| +-[SQL_TOKEN] SqlFragment: 'project0_.id as id0_'
| \-[SQL_TOKEN] SqlFragment: 'project0_.name as name0_, project0_.start_date as start3_0_, project0_.end_date as end4_0_'
+-[FROM] FromClause: 'from' FromClause{level=1, fromElementCounter=1, fromElements=1, fromElementByClassAlias=[p], fromElementByTableAlias=[project0_], fromElementsByPath=[], collectionJoinFromElementsByPath=[], impliedElements=[]}
| \-[FROM_FRAGMENT] FromElement: 'PROJECT project0_' FromElement{explicit,not a collection join,not a fetch join,fetch non-lazy properties,classAlias=p,role=null,tableName=PROJECT,tableAlias=project0_,origin=null,colums={,className=entities.Project}}
\-[WHERE] SqlNode: 'where'
\-[GT] BinaryLogicOperatorNode: '>'
+-[IDENT] IdentNode: 'period' {originalText=period}
\-[NAMED_PARAM] ParameterNode: '?' {name=period_length, expectedType=null}
The red portion looks erroneous to me.
The above example is a simplified version of my original situation.
My original problem included UDF calls.
I know that there is a workaround by not using aliases in this case, but I do want to use aliases to avoid duplicate calculation.
I want to use this feature in my production site, and I am willing to provide any more info that could help. If requested, I can post the test case program that produced the above output.
Thanks.
natto lover.
toyrunr wrote:
Yeah, ofcourse it works for me, however the UDF does some very CPU intensive calculations and the only reason I went with this whole SQL/UDF approach is to reduce overhead and speed up my APP that was already working correctly. If I call the UDF twice, I'll only make the APP slower defeating the purpose of this entire venture.
I see what you are doing and I see how it is working for you. However, I need the results returned and I also need to sort based on them. It works great with regular SQL query, but Hibernate fails to maintain the proper alias that I assign.
score -> col_1_0_
Thank you for your help. I hope this gets fixed in near future, otherwise I'd have to abandon Hibernate altogether.
Code: