HHH-2655: Modified the SQLServer2008Dialect to make use of the ROW_NUMBER function for queries with limit
This commit is contained in:
parent
ca009f5340
commit
895e1bf716
|
@ -25,8 +25,8 @@ package org.hibernate.dialect;
|
|||
|
||||
import java.sql.Types;
|
||||
|
||||
import org.hibernate.Hibernate;
|
||||
import org.hibernate.dialect.function.NoArgSQLFunction;
|
||||
import org.hibernate.type.StandardBasicTypes;
|
||||
|
||||
/**
|
||||
* A dialect for Microsoft SQL Server 2008 with JDBC Driver 3.0 and above
|
||||
|
@ -34,11 +34,77 @@ import org.hibernate.dialect.function.NoArgSQLFunction;
|
|||
* @author Gavin King
|
||||
*/
|
||||
public class SQLServer2008Dialect extends SQLServerDialect {
|
||||
public SQLServer2008Dialect(){
|
||||
registerColumnType( Types.DATE, "date" );
|
||||
registerColumnType( Types.TIME, "time" );
|
||||
registerColumnType( Types.TIMESTAMP, "datetime2" );
|
||||
public SQLServer2008Dialect() {
|
||||
registerColumnType(Types.DATE, "date");
|
||||
registerColumnType(Types.TIME, "time");
|
||||
registerColumnType(Types.TIMESTAMP, "datetime2");
|
||||
|
||||
registerFunction( "current_timestamp", new NoArgSQLFunction("current_timestamp", Hibernate.TIMESTAMP,false) );
|
||||
registerFunction("current_timestamp", new NoArgSQLFunction("current_timestamp", StandardBasicTypes.TIMESTAMP, false));
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a LIMIT clause to the given SQL SELECT (HHH-2655: ROW_NUMBER for Paging)
|
||||
*
|
||||
* The LIMIT SQL will look like:
|
||||
*
|
||||
* <pre>
|
||||
* WITH query AS (SELECT ROW_NUMBER() OVER (ORDER BY orderby) as __hibernate_row_nr__, original_query_without_orderby)
|
||||
* SELECT * FROM query WHERE __hibernate_row_nr__ BEETWIN offset AND offset + last
|
||||
* --ORDER BY __hibernate_row_nr__
|
||||
* </pre>
|
||||
*
|
||||
* I don't think that the last order by clause is mandatory
|
||||
*
|
||||
* @param querySqlString
|
||||
* The SQL statement to base the limit query off of.
|
||||
* @param offset
|
||||
* Offset of the first row to be returned by the query (zero-based)
|
||||
* @param limit
|
||||
* Maximum number of rows to be returned by the query
|
||||
* @return A new SQL statement with the LIMIT clause applied.
|
||||
*/
|
||||
@Override
|
||||
public String getLimitString(String querySqlString, int offset, int limit) {
|
||||
if (offset == 0) return super.getLimitString(querySqlString, offset, limit);
|
||||
|
||||
StringBuilder sb = new StringBuilder(querySqlString.trim());
|
||||
|
||||
String querySqlLowered = querySqlString.trim().toLowerCase();
|
||||
int orderByIndex = querySqlLowered.toLowerCase().indexOf("order by");
|
||||
String orderby = orderByIndex > 0 ? querySqlString.substring(orderByIndex) : "ORDER BY CURRENT_TIMESTAMP";
|
||||
|
||||
// Delete the order by clause at the end of the query
|
||||
if (orderByIndex > 0) sb.delete(orderByIndex, orderByIndex + orderby.length());
|
||||
|
||||
// Find the end of the select statement
|
||||
int selectIndex = querySqlLowered.trim().startsWith("select distinct") ? 15 : 6;
|
||||
|
||||
// Isert after the select statement the row_number() function:
|
||||
sb.insert(selectIndex, " ROW_NUMBER() OVER (" + orderby + ") as __hibernate_row_nr__,");
|
||||
|
||||
// Wrap the query within a with statement:
|
||||
sb.insert(0, "WITH query AS (").append(") SELECT * FROM query ");
|
||||
sb.append("WHERE __hibernate_row_nr__ ");
|
||||
if (offset > 0) sb.append("BETWEEN ").append(offset).append(" AND ").append(limit);
|
||||
else sb.append(" <= ").append(limit);
|
||||
|
||||
// As mentioned before I don't think that we really need this last order by clause
|
||||
// sb.append(" ORDER BY __hibernate_row_nr__");
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsLimit() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsLimitOffset() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean bindLimitParametersFirst() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue