diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/DB2Dialect.java b/hibernate-core/src/main/java/org/hibernate/dialect/DB2Dialect.java
index 8b045485bb..a686c7da95 100644
--- a/hibernate-core/src/main/java/org/hibernate/dialect/DB2Dialect.java
+++ b/hibernate-core/src/main/java/org/hibernate/dialect/DB2Dialect.java
@@ -207,75 +207,74 @@ public class DB2Dialect extends Dialect {
public boolean supportsLimit() {
return true;
}
-
- /*public String getLimitString(String sql, boolean hasOffset) {
- 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 rownumber() over ( .... ) as rownumber_,
- * 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 boolean supportsVariableLimit() {
+ return false;
}
- public String getLimitString(String sql, boolean hasOffset) {
- int startOfSelect = sql.toLowerCase().indexOf("select");
-
- StringBuffer pagingSelect = new StringBuffer( sql.length()+100 )
- .append( sql.substring(0, startOfSelect) ) // add the comment
- .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
-
- 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();
+// /**
+// * Render the rownumber() over ( .... ) as rownumber_,
+// * 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");
+//
+// StringBuffer pagingSelect = new StringBuffer( sql.length()+100 )
+// .append( sql.substring(0, startOfSelect) ) // add the comment
+// .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
+//
+// 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
@@ -288,10 +287,10 @@ public class DB2Dialect extends Dialect {
public int convertToFirstRowValue(int zeroBasedFirstResult) {
return zeroBasedFirstResult;
}
-
- private static boolean hasDistinct(String sql) {
- return sql.toLowerCase().indexOf("select distinct")>=0;
- }
+//
+// private static boolean hasDistinct(String sql) {
+// return sql.toLowerCase().indexOf("select distinct")>=0;
+// }
public String getForUpdateString() {
return " for read only with rs";
diff --git a/hibernate-core/src/test/java/org/hibernate/test/pagination/PaginationTest.java b/hibernate-core/src/test/java/org/hibernate/test/pagination/PaginationTest.java
index eb0ef1d031..afbf3f740e 100755
--- a/hibernate-core/src/test/java/org/hibernate/test/pagination/PaginationTest.java
+++ b/hibernate-core/src/test/java/org/hibernate/test/pagination/PaginationTest.java
@@ -38,6 +38,7 @@ import org.hibernate.testing.RequiresDialectFeature;
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
/**
* @author Gavin King
@@ -145,6 +146,30 @@ public class PaginationTest extends BaseCoreFunctionalTestCase {
assertEquals( 1, result.size() );
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.close();
@@ -175,6 +200,7 @@ public class PaginationTest extends BaseCoreFunctionalTestCase {
BigDecimal x = new BigDecimal( i * 0.1d ).setScale( 19, BigDecimal.ROUND_DOWN );
dataPoint.setX( x );
dataPoint.setY( new BigDecimal( Math.cos( x.doubleValue() ) ).setScale( 19, BigDecimal.ROUND_DOWN ) );
+ dataPoint.setDescription("Description: " + i%5);
session.save( dataPoint );
}
session.getTransaction().commit();