[
http://opensource.atlassian.com/projects/hibernate/browse/EJB-376?page=co...
]
Mark Plutowski commented on EJB-376:
------------------------------------
Related to this issue, I noticed another anomalous behavior when attempting to perform the
same task using createNativeQuery instead. One of the columns was overwritten with the
data for a different column.
// This query overwrites column 4 (array element [3]) with column 5 (array element
4)
StringBuffer sqlQuery = new StringBuffer ();
sqlQuery.append(" Select c.pub_Id, c.clip_Id, CAST (c.duration AS INT),
CAST ( count(distinct cs.slot_Id) AS INT ) , ")
.append(" CAST (COUNT (DISTINCT (CASE WHEN (comp.serve_ts BETWEEN
:beginTs AND :endTs ) THEN comp.component_id ELSE NULL END ) ) AS INT ) " )
.append(" FROM Cm_Clip c INNER JOIN cm_Clip_Slot cs ON (cs.clip_id =
c.clip_id) left outer join cs_component comp ON (cs.clip_id = comp.clip_id) ")
.append(" where (cs.ad_Size_X * c.width) >= :adWidth and
(cs.ad_Size_Y * c.height) >= :adHeight ")
.append(" and (c.is_Qa_Done = true or c.is_Qa_Done is null) and
c.is_Enabled = true ")
.append(" group by c.pub_Id, c.clip_Id, c.duration ")
.append(" order by ")
.append( orderByCol );
Here's the transaction and parameter setting step:
transactionMgr.begin();
List<Object[]> result = em.createNativeQuery(sqlQuery.toString())
.setParameter("adWidth", (widthF-roFactor)).
setParameter("adHeight", (heightF-roFactor))
.setParameter("beginTs", beginTs,
javax.persistence.TemporalType.TIMESTAMP)
.setParameter("endTs", endTs, javax.persistence.TemporalType.TIMESTAMP)
.getResultList();
transactionMgr.commit();
We confirmed that every time this native query was run, result[3] == result[4] despite
the data in the database being such that this should not be the case. Reverting back to
the "SUM ( CASE WHEN " JQL (HQL?) approach mentioned above fixed this, such
that result[3] and result[4] were no longer showing identical data and were indeed
returning the correct result when compared to the same statement translated to SQL and run
against the target database using Pgadmin (as well as confirmed via visual inspection of
the underlying tables).
EntityManager.createQuery does not recognize COUNT CASE statement
-----------------------------------------------------------------
Key: EJB-376
URL:
http://opensource.atlassian.com/projects/hibernate/browse/EJB-376
Project: Hibernate Entity Manager
Issue Type: Bug
Components: EntityManager
Affects Versions: 3.3.1.GA, 3.4.0.CR2
Environment: Tested with both Hibernate 3.2.5.ga and Hibernate 3.3.0.CR2,
Postgres 8.1, Postgres 8.2, Linux Ubuntu.
Reporter: Mark Plutowski
I searched the Hibernate forums and did not find mention of this issue or one that was
closely related. I also posted this to the Hibernate Users forum, and did not receive any
replies recognizing the bug or stating that it has been resolved or has a workaround.
To summarize, EntityManager.createQuery does not recognize SQL related to applying a
COUNT to a CASE, whereas it does correctly run SQL that applies a SUM to a CASE. More
detail follows.
--- Summary Overview ---
EntityManager.createQuery runs a SELECT query containing the following HQL/JQL snippet
runs correctly:
" SUM ( CASE WHEN (cs.serveTs BETWEEN :beginTs AND :endTs ) THEN 1 ELSE 0 END )
"
However, the following do not work:
" COUNT ( DISTINCT CASE WHEN (cs.serveTs BETWEEN :beginTs AND :endTs ) THEN
cs.componentId ELSE NULL END ) "
" COUNT ( DISTINCT (CASE WHEN (cs.serveTs BETWEEN :beginTs AND :endTs ) THEN
cs.componentId ELSE NULL END ) ) "
" COUNT ( CASE WHEN (cs.serveTs BETWEEN :beginTs AND :endTs ) THEN cs.componentId
ELSE NULL END ) "
The first two statements run and return correct results when translated to SQL and run
against the Postgresql database in PgAdmin.
Here's the exception thrown when using COUNT ( DISTINCT CASE WHEN
101976 [main] ERROR org.hibernate.hql.PARSER - line 1:93: unexpected token: CASE
101977 [main] ERROR org.hibernate.hql.PARSER - line 1:98: unexpected token: WHEN
Here's the exception thrown when the extra parenthesis is added to give COUNT (
DISTINCT (CASE WHEN
85587 [main] ERROR org.hibernate.hql.PARSER - line 1:93: unexpected token: (
85588 [main] ERROR org.hibernate.hql.PARSER - line 1:99: unexpected token: WHEN
--- Additional Detail ---
Here is the complete SQL for the COUNT (DISTINCT (CASE use case:
String queryString = "Select c.id.pubId, c.id.clipId, c.duration, " +
"count(distinct s.slotId) , " +
" COUNT ( DISTINCT (CASE WHEN (cs.serveTs BETWEEN :beginTs AND
:endTs ) THEN cs.componentId ELSE NULL END ) ) " +
"from CmClip c " +
"join c.cmClipSlots s " +
"left outer join c.csComponents cs " +
"where (s.adSizeX * c.width) >= :adWidth " +
"and (s.adSizeY * c.height) >= :adHeight " +
"and (c.isQaDone = true or c.isQaDone is null) " +
"and c.isEnabled = true " +
"group by c.id.pubId, c.id.clipId, c.duration " +
"order by " + orderByCol;
This results in the following exception:
85587 [main] ERROR org.hibernate.hql.PARSER - line 1:93: unexpected token: (
85588 [main] ERROR org.hibernate.hql.PARSER - line 1:99: unexpected token: WHEN
Here is the SQL for the SUM CASE sql snippet that does run and return correct results:
String queryString = "Select c.id.pubId, c.id.clipId, c.duration, " +
"count(distinct s.slotId) , " +
" SUM ( CASE WHEN (cs.serveTs BETWEEN :beginTs AND :endTs ) THEN 1
ELSE 0 END ) " +
"from CmClip c " +
"join c.cmClipSlots s " +
"left outer join c.csComponents cs " +
"where (s.adSizeX * c.width) >= :adWidth " +
"and (s.adSizeY * c.height) >= :adHeight " +
"and (c.isQaDone = true or c.isQaDone is null) " +
"and c.isEnabled = true " +
"group by c.id.pubId, c.id.clipId, c.duration " +
"order by " + orderByCol;
Here is the code snippet that performs the transaction:
float roFactor = (float) 0.5;
transactionMgr.begin();
List<Object[]> result = entityMgr.createQuery(queryString)
.setParameter("adWidth", (widthF-roFactor)).
setParameter("adHeight", (heightF-roFactor))
.setParameter("beginTs", beginTs,
javax.persistence.TemporalType.TIMESTAMP)
.setParameter("endTs", endTs, javax.persistence.TemporalType.TIMESTAMP)
.getResultList();
transactionMgr.commit();
The fact that "SUM (CASE" is parsed and run correctly, whereas "COUNT
(CASE" throws an exception seems to indicate a bug. I replicated this using both
(Hibernate 3.2.5.ga with EntityManager 3.3.1.GA) and (Hibernate 3.3.0.CR2 with
EntityManager 3.4.0.CR2).
--
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators:
http://opensource.atlassian.com/projects/hibernate/secure/Administrators....
-
For more information on JIRA, see:
http://www.atlassian.com/software/jira