Skip to content

Commit

Permalink
SQL Server: if possible, use OFFSET and FETCH instead of JDBC methods (
Browse files Browse the repository at this point in the history
…#300)

Signed-off-by: Richard DiCroce <Rich.DiCroce@scientificgames.com>
  • Loading branch information
rdicroce authored and lukasj committed Dec 14, 2018
1 parent 4a31edd commit 0ce1cbc
Showing 1 changed file with 47 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,8 @@
* @since TOPLink/Java 1.0
*/
public class SQLServerPlatform extends org.eclipse.persistence.platform.database.DatabasePlatform {
/** Support for sequence objects added in SQL Server 2012 */
private boolean supportsSequenceObjects;
/** Support for sequence objects and OFFSET FETCH NEXT added in SQL Server 2012 */
private boolean isVersion11OrHigher;
private boolean isConnectionDataInitialized;

public SQLServerPlatform(){
Expand All @@ -62,7 +62,7 @@ public void initializeConnectionData(Connection connection) throws SQLException
}
DatabaseMetaData dmd = connection.getMetaData();
int databaseVersion = dmd.getDatabaseMajorVersion();
supportsSequenceObjects = databaseVersion >= 11;
isVersion11OrHigher = databaseVersion >= 11;
isConnectionDataInitialized = true;
this.driverSupportsNationalCharacterVarying = Helper.compareVersions(dmd.getDriverVersion(), "4.0.0") >= 0;
}
Expand Down Expand Up @@ -690,7 +690,7 @@ public boolean supportsIdentity() {
*/
@Override
public boolean supportsSequenceObjects() {
return supportsSequenceObjects;
return isVersion11OrHigher;
}

/**
Expand Down Expand Up @@ -732,4 +732,47 @@ public void writeUpdateOriginalFromTempTableSql(Writer writer, DatabaseTable tab
writer.write(tempTableName);
writeAutoJoinWhereClause(writer, tableName, tempTableName, pkFields, this);
}

@Override
public void printSQLSelectStatement(DatabaseCall call, ExpressionSQLPrinter printer, SQLSelectStatement statement) {
ReadQuery query = statement.getQuery();
if (query == null || !isVersion11OrHigher || !shouldUseRownumFiltering()) {
super.printSQLSelectStatement(call, printer, statement);
return;
}

int max = Math.max(0, query.getMaxRows());
int first = Math.max(0, query.getFirstResult());

if (max == 0 && first == 0) {
super.printSQLSelectStatement(call, printer, statement);
return;
}

// OFFSET + FETCH NEXT requires ORDER BY, so add an ordering if there are none
// this SQL will satisfy the query parser without actually changing the ordering of the rows
List<Expression> orderBy = statement.getOrderByExpressions();
if (orderBy.isEmpty()) {
orderBy.add(statement.getBuilder().literal("ROW_NUMBER() OVER (ORDER BY (SELECT null))"));
}

// decide exact syntax to use, depending on whether a limit is specified (could just have an offset)
String offsetFetchSql;
List<?> offsetFetchArgs;
if (max == 0) {
offsetFetchSql = "? OFFSET ? ROWS";
offsetFetchArgs = Arrays.asList(first);
} else {
offsetFetchSql = "? OFFSET ? ROWS FETCH NEXT ? ROWS ONLY";
offsetFetchArgs = Arrays.asList(first, max - first);
}

// append to the last ORDER BY clause
orderBy.add(orderBy.remove(orderBy.size() - 1).sql(offsetFetchSql, offsetFetchArgs));

super.printSQLSelectStatement(call, printer, statement);

call.setIgnoreFirstRowSetting(true);
call.setIgnoreMaxResultsSetting(true);
}
}

0 comments on commit 0ce1cbc

Please sign in to comment.