HHH-2176 DB2 setMaxResults problem in Hibernate 3.1.3

This commit is contained in:
Strong Liu 2011-06-07 17:52:48 +08:00
parent f78c79d676
commit 2077b5f43c
2 changed files with 95 additions and 70 deletions

View File

@ -207,75 +207,74 @@ public class DB2Dialect extends Dialect {
public boolean supportsLimit() { public boolean supportsLimit() {
return true; return true;
} }
public boolean supportsVariableLimit() {
/*public String getLimitString(String sql, boolean hasOffset) { return false;
StringBuffer rownumber = new StringBuffer(50)
.append(" rownumber() over(");
int orderByIndex = sql.toLowerCase().indexOf("order by");
if (orderByIndex>0) rownumber.append( sql.substring(orderByIndex) );
rownumber.append(") as row_,");
StringBuffer pagingSelect = new StringBuffer( sql.length()+100 )
.append("select * from ( ")
.append(sql)
.insert( getAfterSelectInsertPoint(sql)+16, rownumber.toString() )
.append(" ) as temp_ where row_ ");
if (hasOffset) {
pagingSelect.append("between ?+1 and ?");
}
else {
pagingSelect.append("<= ?");
}
return pagingSelect.toString();
}*/
/**
* Render the <tt>rownumber() over ( .... ) as rownumber_,</tt>
* bit, that goes in the select list
*/
private String getRowNumber(String sql) {
StringBuffer rownumber = new StringBuffer(50)
.append("rownumber() over(");
int orderByIndex = sql.toLowerCase().indexOf("order by");
if ( orderByIndex>0 && !hasDistinct(sql) ) {
rownumber.append( sql.substring(orderByIndex) );
}
rownumber.append(") as rownumber_,");
return rownumber.toString();
} }
public String getLimitString(String sql, boolean hasOffset) { // /**
int startOfSelect = sql.toLowerCase().indexOf("select"); // * Render the <tt>rownumber() over ( .... ) as rownumber_,</tt>
// * bit, that goes in the select list
StringBuffer pagingSelect = new StringBuffer( sql.length()+100 ) // */
.append( sql.substring(0, startOfSelect) ) // add the comment // private String getRowNumber(String sql) {
.append("select * from ( select ") // nest the main query in an outer select // StringBuffer rownumber = new StringBuffer(50)
.append( getRowNumber(sql) ); // add the rownnumber bit into the outer query select list // .append("rownumber() over(");
//
if ( hasDistinct(sql) ) { // int orderByIndex = sql.toLowerCase().indexOf("order by");
pagingSelect.append(" row_.* from ( ") // add another (inner) nested select //
.append( sql.substring(startOfSelect) ) // add the main query // if ( orderByIndex>0 && !hasDistinct(sql) ) {
.append(" ) as row_"); // close off the inner nested select // rownumber.append( sql.substring(orderByIndex) );
} // }
else { //
pagingSelect.append( sql.substring( startOfSelect + 6 ) ); // add the main query // rownumber.append(") as rownumber_,");
} //
// return rownumber.toString();
pagingSelect.append(" ) as temp_ where rownumber_ "); // }
//
//add the restriction to the outer select // public String getLimitString(String sql, boolean hasOffset) {
if (hasOffset) { // int startOfSelect = sql.toLowerCase().indexOf("select");
pagingSelect.append("between ?+1 and ?"); //
} // StringBuffer pagingSelect = new StringBuffer( sql.length()+100 )
else { // .append( sql.substring(0, startOfSelect) ) // add the comment
pagingSelect.append("<= ?"); // .append("select * from ( select ") // nest the main query in an outer select
} // .append( getRowNumber(sql) ); // add the rownnumber bit into the outer query select list
//
return pagingSelect.toString(); // if ( hasDistinct(sql) ) {
// pagingSelect.append(" row_.* from ( ") // add another (inner) nested select
// .append( sql.substring(startOfSelect) ) // add the main query
// .append(" ) as row_"); // close off the inner nested select
// }
// else {
// pagingSelect.append( sql.substring( startOfSelect + 6 ) ); // add the main query
// }
//
// pagingSelect.append(" ) as temp_ where rownumber_ ");
//
// //add the restriction to the outer select
// if (hasOffset) {
// pagingSelect.append("between ?+1 and ?");
// }
// else {
// pagingSelect.append("<= ?");
// }
//
// return pagingSelect.toString();
// }
public String getLimitString(String sql, int offset, int limit) {
if ( offset == 0 ) {
return sql + " fetch first " + limit + " rows only";
} }
StringBuilder pagingSelect = new StringBuilder( sql.length() + 200 )
.append(
"select * from ( select inner2_.*, rownumber() over(order by order of inner2_) as rownumber_ from ( "
)
.append( sql ) //nest the main query in an outer select
.append( " fetch first " )
.append( limit )
.append( " rows only ) as inner2_ ) as inner1_ where rownumber_ > " )
.append( offset )
.append( " order by rownumber_" );
return pagingSelect.toString();
}
/** /**
* DB2 does have a one-based offset, however this was actually already handled in the limit string building * DB2 does have a one-based offset, however this was actually already handled in the limit string building
@ -288,10 +287,10 @@ public class DB2Dialect extends Dialect {
public int convertToFirstRowValue(int zeroBasedFirstResult) { public int convertToFirstRowValue(int zeroBasedFirstResult) {
return zeroBasedFirstResult; return zeroBasedFirstResult;
} }
//
private static boolean hasDistinct(String sql) { // private static boolean hasDistinct(String sql) {
return sql.toLowerCase().indexOf("select distinct")>=0; // return sql.toLowerCase().indexOf("select distinct")>=0;
} // }
public String getForUpdateString() { public String getForUpdateString() {
return " for read only with rs"; return " for read only with rs";

View File

@ -38,6 +38,7 @@ import org.hibernate.testing.RequiresDialectFeature;
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
/** /**
* @author Gavin King * @author Gavin King
@ -145,6 +146,30 @@ public class PaginationTest extends BaseCoreFunctionalTestCase {
assertEquals( 1, result.size() ); assertEquals( 1, result.size() );
assertEquals( 99, ( ( DataPoint ) result.get( 0 ) ).getSequence() ); assertEquals( 99, ( ( DataPoint ) result.get( 0 ) ).getSequence() );
result = session.createQuery("select distinct description from DataPoint order by description")
.setFirstResult( 2 )
.setMaxResults( 3 )
.list();
assertEquals( 3, result.size() );
assertEquals( "Description: 2", result.get(0));
assertEquals( "Description: 3", result.get(1));
assertEquals( "Description: 4", result.get(2));
result = session.createSQLQuery( "select description, xval, yval from DataPoint order by xval, yval" )
.setFirstResult( 2 )
.setMaxResults( 5 )
.list();
assertEquals( 5, result.size() );
Object[] row = (Object[]) result.get(0);
assertTrue( row[0] instanceof String);
result = session.createSQLQuery( "select * from DataPoint order by xval, yval" )
.setFirstResult( 2 )
.setMaxResults( 5 )
.list();
assertEquals( 5, result.size() );
session.getTransaction().commit(); session.getTransaction().commit();
session.close(); session.close();
@ -175,6 +200,7 @@ public class PaginationTest extends BaseCoreFunctionalTestCase {
BigDecimal x = new BigDecimal( i * 0.1d ).setScale( 19, BigDecimal.ROUND_DOWN ); BigDecimal x = new BigDecimal( i * 0.1d ).setScale( 19, BigDecimal.ROUND_DOWN );
dataPoint.setX( x ); dataPoint.setX( x );
dataPoint.setY( new BigDecimal( Math.cos( x.doubleValue() ) ).setScale( 19, BigDecimal.ROUND_DOWN ) ); dataPoint.setY( new BigDecimal( Math.cos( x.doubleValue() ) ).setScale( 19, BigDecimal.ROUND_DOWN ) );
dataPoint.setDescription("Description: " + i%5);
session.save( dataPoint ); session.save( dataPoint );
} }
session.getTransaction().commit(); session.getTransaction().commit();