-->
These old forums are deprecated now and set to read-only. We are waiting for you on our new forums!
More modern, Discourse-based and with GitHub/Google/Twitter authentication built-in.

All times are UTC - 5 hours [ DST ]



Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 9 posts ] 
Author Message
 Post subject: Wrong number of rows with HQL distinct and maxResults
PostPosted: Mon Mar 10, 2008 3:58 pm 
Newbie

Joined: Mon Mar 10, 2008 3:50 pm
Posts: 5
Hibernate version: 3.2.1 and 3.2.6
Oracle version: 10g with Oracle9Dialect.

We seem to have found an error in the way Hibernate processes the
combination of a distinct with a result limit in HQL. The HQL result
will only contain 10 rows, but if you run the equivalent SQL query the
result has the correct number of rows.

Here is a reproduction, UnitTestFactory in our system is just a place
to hang the Hibernate SessionFactory injected by Spring.

public void runHibernateSearch() {

UnitTestFactory utf = UnitTestFactory.getFactory();
SessionFactory sf = utf.getSessionFactory();
Session s = sf.openSession();

int maxResults = 100;

String hql = "select distinct identityAlias.name, identityAlias.id from sailpoint.object.Identity identityAlias";
Query q = s.createQuery(hql);
q.setMaxResults(maxResults);

List rows = q.list();
// there will be 10 rows
println("Result had " + rows.size() + " rows");

String sql = "select distinct identityAlias.name, identityAlias.id from ciq_identity identityAlias";
q = s.createSQLQuery(sql);
q.setMaxResults(maxResults);

rows = q.list();
// there will be 100 rows
println("Result had " + rows.size() + " rows");
}

When show_sql is on, the following statement is logged for the HQL query:

Hibernate: select * from ( select distinct identity0_.name as col_0_0_, identity0_.id as col_1_0_ from ciq_identity identity0_ ) where rownum <= ?

And this is logged for the SQL query:

Hibernate: select * from ( select distinct identityAlias.name, identityAlias.id from ciq_identity identityAlias ) where rownum <= ?


Hibernate trace does not show the value being substituted for the
rownum parameter. When we cut the logged SQL statement and paste it
into a JDBC query tool, substituting 100 for the ? it returns the
correct result. The SQL being generated therefore appears to be
correct, it is the parameter value being used for the rownum comparison
that is incorrect.

What is also interesting is that when maxResults is set to a number
less than 10 then both queries return the same number of rows. It is
only when maxResults is greater than 10 that the queries are different.

If you remove the "distinct" the queries are the same.

If you remove identityAlias.id from the select list and only select
distinct identityAlias.name the queries are the same.

Any suggestions would be greatly appreciated!


Last edited by jlarson2000 on Mon Mar 10, 2008 4:13 pm, edited 1 time in total.

Top
 Profile  
 
 Post subject:
PostPosted: Mon Mar 10, 2008 4:10 pm 
Newbie

Joined: Mon Mar 10, 2008 3:50 pm
Posts: 5
Also note that this only happens on Oracle. It works on MySQL.


Top
 Profile  
 
 Post subject:
PostPosted: Mon Mar 10, 2008 4:26 pm 
Newbie

Joined: Mon Mar 10, 2008 3:50 pm
Posts: 5
Here is an even simpler example. We run the
same HQL query twice. The first time the first row
is zero and the second time the first row is 1. The
first query returns 10 rows and the second 100 rows.

Session s = sf.openSession();

int maxResults = 100;

String hql = "select distinct identityAlias.name, identityAlias.id from sailpoint.object.Identity identityAlias";
Query q = s.createQuery(hql);
q.setMaxResults(maxResults);

List rows = q.list();
// there will be 10 rows
println("Result had " + rows.size() + " rows");

q = s.createQuery(hql);
q.setFirstResult(1);
q.setMaxResults(maxResults);

rows = q.list();
// there will be 100 rows
println("Result had " + rows.size() + " rows");


Top
 Profile  
 
 Post subject: actually a JDBC driver problem
PostPosted: Mon Mar 10, 2008 5:28 pm 
Newbie

Joined: Mon Mar 10, 2008 3:50 pm
Posts: 5
After more investigation this appears to be a JDBC driver
problem. If you prepare a statement that has a one
sided rownum comparison,

select * from ... where rownum <= ?";

The driver we use will only return 10 rows. If you
have both ends of the range it works.

select * from ... where rownum >= ? and rownum <= ?";

Unfortunately when the starting rownum is zero, Hibernate
optimizes out the >= term and we hit the driver bug.

The driver we are using is from Oracle, version 10.2.0.1.0

While this is apparently an Oracle bug, it would be nice if
Hibernate could work around it by adding a rownum >= ? term
with a zero value.


Top
 Profile  
 
 Post subject:
PostPosted: Mon Mar 10, 2008 6:05 pm 
Newbie

Joined: Mon Mar 10, 2008 3:50 pm
Posts: 5
I know you're all just riveted by this conversation I'm having with
myself so here's the latest tidbit.

This does appear to be a driver problem but it is related
to the unusual syntax Hibernate is generating. Here is
the HQL:

select distinct identityAlias.name, identityAlias.id
from sailpoint.object.Identity identityAlias";

With FirstResult = 0 and MaxResults = 100 in the Query.

The SQL that is generated is this:

select * from (
select distinct identity0_.name as col_0_0_,
identity0_.id as col_1_0_
from ciq_identity identity0_ ) where rownum <= ?

The inner query does the work, then we're wrapping it in a funky
select * with the rownum being applied to the outer result. I have
verified that if you try to run this SQL in a PreparedStatement with
100 bound to the first parameter you only get 10 rows back. Clearly a
bug. But if you remove the unusual wrapping:

select distinct identity0_.name as col_0_0_,
identity0_.id as col_1_0_
from ciq_identity identity0_ where rownum <= ?";

it works as expected. So while this is arguably a driver bug
I do think it is something Hibernate needs to address since it
is in control of the syntax.

This BTW is a problem in all versions of the Oracle driver
from 10.2.0.1 through 11.1.0.6.


Top
 Profile  
 
 Post subject: A Work-Around...
PostPosted: Wed Dec 10, 2008 4:59 pm 
Beginner
Beginner

Joined: Tue Jun 07, 2005 8:24 am
Posts: 33
Location: Cincinnati, OH
FYI:

We got around this issue by using our own dialect.

Code:
public class MyOracle10gDialect extends Oracle10gDialect
{
    public String getLimitString(final String s, final int min, final int max)
    {
        String limitString = super.getLimitString(s, min, max);
        if(min == 0)
        {
            limitString += " and rownum > 0";
        }
        return limitString;
    }
}


We also found that this only happens (in our case) when you have an order by clause on your query (we built it by Criteria). Weird!


Top
 Profile  
 
 Post subject: Re: A Work-Around...
PostPosted: Tue Jan 13, 2009 11:40 am 
Newbie

Joined: Fri Sep 19, 2008 11:43 am
Posts: 3
Thanks for such a detailed explanation of this issue. I'm seeing exactly the same thing happening in my code. Has this issue been logged as a bug/enhancement either to oracle or hibernate?


Top
 Profile  
 
 Post subject: rownum in pagination
PostPosted: Tue Mar 03, 2009 7:00 pm 
Beginner
Beginner

Joined: Thu Jun 23, 2005 10:23 pm
Posts: 22
Is your order by column returning unique values? Refer to the bottom part of this article: http://www.oracle.com/technology/oramag ... sktom.html


Top
 Profile  
 
 Post subject: Re: Wrong number of rows with HQL distinct and maxResults
PostPosted: Tue Jan 22, 2013 3:34 pm 
Newbie

Joined: Tue Jan 22, 2013 3:18 pm
Posts: 1
I have the Same Problem with Oracle 10.2.0.3.0 and JDBC Driver ojdbc6-11.1.0.7.0.jar

The following Implementation solves the Problem.

Code:
public class Oracle10gDialectLimitBugfix extends Oracle10gDialect {

    @Override
    public boolean forceLimitUsage() {
        return true;
    }
}


@jwcarman
Thanks for the right hint

UPDATE: It seems to be fixed in Oracle 11.2.0.1.0


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 9 posts ] 

All times are UTC - 5 hours [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.