SQLServerDialect fallback to the pre HHH-2655 one
This commit is contained in:
parent
6e565102b5
commit
2ec009440e
|
@ -26,9 +26,9 @@ package org.hibernate.dialect;
|
||||||
import java.sql.Types;
|
import java.sql.Types;
|
||||||
|
|
||||||
import org.hibernate.LockMode;
|
import org.hibernate.LockMode;
|
||||||
import org.hibernate.dialect.function.AnsiTrimEmulationFunction;
|
|
||||||
import org.hibernate.dialect.function.SQLFunctionTemplate;
|
import org.hibernate.dialect.function.SQLFunctionTemplate;
|
||||||
import org.hibernate.dialect.function.StandardSQLFunction;
|
import org.hibernate.dialect.function.StandardSQLFunction;
|
||||||
|
import org.hibernate.dialect.function.AnsiTrimEmulationFunction;
|
||||||
import org.hibernate.type.StandardBasicTypes;
|
import org.hibernate.type.StandardBasicTypes;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -37,11 +37,7 @@ import org.hibernate.type.StandardBasicTypes;
|
||||||
* @author Gavin King
|
* @author Gavin King
|
||||||
*/
|
*/
|
||||||
public class SQLServerDialect extends AbstractTransactSQLDialect {
|
public class SQLServerDialect extends AbstractTransactSQLDialect {
|
||||||
private static final String SELECT = "select";
|
|
||||||
private static final String FROM = "from";
|
|
||||||
private static final String DISTINCT = "distinct";
|
|
||||||
|
|
||||||
|
|
||||||
public SQLServerDialect() {
|
public SQLServerDialect() {
|
||||||
registerColumnType( Types.VARBINARY, "image" );
|
registerColumnType( Types.VARBINARY, "image" );
|
||||||
registerColumnType( Types.VARBINARY, 8000, "varbinary($l)" );
|
registerColumnType( Types.VARBINARY, 8000, "varbinary($l)" );
|
||||||
|
@ -72,103 +68,14 @@ public class SQLServerDialect extends AbstractTransactSQLDialect {
|
||||||
return selectIndex + ( selectDistinctIndex == selectIndex ? 15 : 6 );
|
return selectIndex + ( selectDistinctIndex == selectIndex ? 15 : 6 );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
public String getLimitString(String querySelect, int offset, int limit) {
|
||||||
* Add a LIMIT clause to the given SQL SELECT (HHH-2655: ROW_NUMBER for Paging)
|
if ( offset > 0 ) {
|
||||||
*
|
throw new UnsupportedOperationException( "query result offset is not supported" );
|
||||||
* 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
|
|
||||||
* </pre>
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* @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 new StringBuffer( querySqlString.length() + 8 ).append( querySqlString )
|
|
||||||
.insert( getAfterSelectInsertPoint( querySqlString ), " top " + limit )
|
|
||||||
.toString();
|
|
||||||
}
|
}
|
||||||
|
return new StringBuffer( querySelect.length() + 8 )
|
||||||
StringBuilder sb = new StringBuilder( querySqlString.trim().toLowerCase() );
|
.append( querySelect )
|
||||||
|
.insert( getAfterSelectInsertPoint( querySelect ), " top " + limit )
|
||||||
int orderByIndex = sb.indexOf( "order by" );
|
.toString();
|
||||||
CharSequence orderby = orderByIndex > 0 ? sb.subSequence( orderByIndex, sb.length() ) : "ORDER BY CURRENT_TIMESTAMP";
|
|
||||||
|
|
||||||
// Delete the order by clause at the end of the query
|
|
||||||
if ( orderByIndex > 0 ) {
|
|
||||||
sb.delete( orderByIndex, orderByIndex + orderby.length() );
|
|
||||||
}
|
|
||||||
|
|
||||||
// HHH-5715 bug fix
|
|
||||||
replaceDistinctWithGroupBy( sb );
|
|
||||||
|
|
||||||
insertRowNumberFunction( sb, orderby );
|
|
||||||
|
|
||||||
//Wrap the query within a with statement:
|
|
||||||
sb.insert( 0, "WITH query AS (").append(") SELECT * FROM query " );
|
|
||||||
sb.append( "WHERE __hibernate_row_nr__ BETWEEN " ).append(offset + 1).append( " AND " ).append( limit );
|
|
||||||
|
|
||||||
return sb.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Utility method that checks if the given sql query is a select distinct one and if so replaces the distinct
|
|
||||||
* select with an equivelant simple select with a group by clause. See {@link SQLServerDialectTestCase#testReplaceDistinctWithGroupBy()}
|
|
||||||
*
|
|
||||||
* @param an sql query
|
|
||||||
*/
|
|
||||||
protected static void replaceDistinctWithGroupBy(StringBuilder sql) {
|
|
||||||
int distinctIndex = sql.indexOf( DISTINCT );
|
|
||||||
if (distinctIndex > 0) {
|
|
||||||
sql.delete(distinctIndex, distinctIndex + DISTINCT.length() + 1);
|
|
||||||
sql.append(" group by").append(getSelectFieldsWithoutAliases(sql));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This utility method searches the given sql query for the fields of the select statement and
|
|
||||||
* returns them without the aliases. See {@link SQLServerDialectTestCase#testGetSelectFieldsWithoutAliases()}
|
|
||||||
*
|
|
||||||
* @param an sql query
|
|
||||||
* @return the fields of the select statement without their alias
|
|
||||||
*/
|
|
||||||
protected static CharSequence getSelectFieldsWithoutAliases(StringBuilder sql) {
|
|
||||||
String select = sql.substring( sql.indexOf(SELECT) + SELECT.length(), sql.indexOf(FROM));
|
|
||||||
|
|
||||||
// Strip the as clauses
|
|
||||||
return stripAliases( select );
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Utility method that strips the aliases. See {@link SQLServerDialectTestCase#testStripAliases()}
|
|
||||||
*
|
|
||||||
* @param a string to replace the as statements
|
|
||||||
* @return a string without the as statements
|
|
||||||
*/
|
|
||||||
protected static String stripAliases(String str) {
|
|
||||||
return str.replaceAll( "\\sas[^,]+(,?)", "$1" );
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Right after the select statement of a given query we must place the row_number function
|
|
||||||
*
|
|
||||||
* @param sql the initial sql query without the order by clause
|
|
||||||
* @param orderby the order by clause of the query
|
|
||||||
*/
|
|
||||||
protected static void insertRowNumberFunction(StringBuilder sql, CharSequence orderby) {
|
|
||||||
// Find the end of the select statement
|
|
||||||
int selectEndIndex = sql.indexOf( SELECT ) + SELECT.length();
|
|
||||||
|
|
||||||
// Isert after the select statement the row_number() function:
|
|
||||||
sql.insert( selectEndIndex, " ROW_NUMBER() OVER (" + orderby + ") as __hibernate_row_nr__," );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -187,11 +94,6 @@ public class SQLServerDialect extends AbstractTransactSQLDialect {
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean supportsLimitOffset() {
|
public boolean supportsLimitOffset() {
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean bindLimitParametersFirst() {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -209,9 +111,9 @@ public class SQLServerDialect extends AbstractTransactSQLDialect {
|
||||||
|
|
||||||
public String appendLockHint(LockMode mode, String tableName) {
|
public String appendLockHint(LockMode mode, String tableName) {
|
||||||
if ( ( mode == LockMode.UPGRADE ) ||
|
if ( ( mode == LockMode.UPGRADE ) ||
|
||||||
( mode == LockMode.UPGRADE_NOWAIT ) ||
|
( mode == LockMode.UPGRADE_NOWAIT ) ||
|
||||||
( mode == LockMode.PESSIMISTIC_WRITE ) ||
|
( mode == LockMode.PESSIMISTIC_WRITE ) ||
|
||||||
( mode == LockMode.WRITE ) ) {
|
( mode == LockMode.WRITE ) ) {
|
||||||
return tableName + " with (updlock, rowlock)";
|
return tableName + " with (updlock, rowlock)";
|
||||||
}
|
}
|
||||||
else if ( mode == LockMode.PESSIMISTIC_READ ) {
|
else if ( mode == LockMode.PESSIMISTIC_READ ) {
|
||||||
|
@ -224,7 +126,6 @@ public class SQLServerDialect extends AbstractTransactSQLDialect {
|
||||||
|
|
||||||
// The current_timestamp is more accurate, but only known to be supported
|
// The current_timestamp is more accurate, but only known to be supported
|
||||||
// in SQL Server 7.0 and later (i.e., Sybase not known to support it at all)
|
// in SQL Server 7.0 and later (i.e., Sybase not known to support it at all)
|
||||||
|
|
||||||
public String getCurrentTimestampSelectString() {
|
public String getCurrentTimestampSelectString() {
|
||||||
return "select current_timestamp";
|
return "select current_timestamp";
|
||||||
}
|
}
|
||||||
|
@ -260,3 +161,4 @@ public class SQLServerDialect extends AbstractTransactSQLDialect {
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue