From b08f1580f923b751df7ca6fc4bfa085c82ef286e Mon Sep 17 00:00:00 2001 From: Rob Bygrave Date: Sat, 3 Dec 2016 15:10:11 +1300 Subject: [PATCH] #910 - SQL Server update - Add ANSI based row limiter (2012+) and make as default platform --- .../dbplatform/SqlServer2005Platform.java | 11 +++++ .../dbplatform/SqlServer2012SqlLimiter.java | 47 +++++++++++++++++++ .../dbplatform/SqlServerBasicSqlLimiter.java | 24 ++++++++++ .../config/dbplatform/SqlServerPlatform.java | 3 +- 4 files changed, 84 insertions(+), 1 deletion(-) create mode 100644 src/main/java/com/avaje/ebean/config/dbplatform/SqlServer2005Platform.java create mode 100644 src/main/java/com/avaje/ebean/config/dbplatform/SqlServer2012SqlLimiter.java create mode 100644 src/main/java/com/avaje/ebean/config/dbplatform/SqlServerBasicSqlLimiter.java diff --git a/src/main/java/com/avaje/ebean/config/dbplatform/SqlServer2005Platform.java b/src/main/java/com/avaje/ebean/config/dbplatform/SqlServer2005Platform.java new file mode 100644 index 000000000..8d631acb3 --- /dev/null +++ b/src/main/java/com/avaje/ebean/config/dbplatform/SqlServer2005Platform.java @@ -0,0 +1,11 @@ +package com.avaje.ebean.config.dbplatform; + +/** + * SQL Server platform using the older ROW_NUMBER() mechanism. + */ +public class SqlServer2005Platform extends SqlServerPlatform { + + public SqlServer2005Platform() { + this.sqlLimiter = new SqlServer2005SqlLimiter(); + } +} diff --git a/src/main/java/com/avaje/ebean/config/dbplatform/SqlServer2012SqlLimiter.java b/src/main/java/com/avaje/ebean/config/dbplatform/SqlServer2012SqlLimiter.java new file mode 100644 index 000000000..9eb9104f0 --- /dev/null +++ b/src/main/java/com/avaje/ebean/config/dbplatform/SqlServer2012SqlLimiter.java @@ -0,0 +1,47 @@ +package com.avaje.ebean.config.dbplatform; + +/** + * Use ANSI offset rows syntax or top n. + */ +public class SqlServer2012SqlLimiter implements SqlLimiter { + + public SqlServer2012SqlLimiter() { + } + + public SqlLimitResponse limit(SqlLimitRequest request) { + + String dbSql = request.getDbSql(); + StringBuilder sb = new StringBuilder(50 + dbSql.length()); + + int firstRow = request.getFirstRow(); + int maxRows = request.getMaxRows(); + + if (firstRow < 1) { + // just use top n + sb.append("select "); + if (request.isDistinct()) { + sb.append("distinct "); + } + sb.append("top ").append(maxRows).append(" "); + sb.append(dbSql); + return new SqlLimitResponse(sb.toString(), false); + } + + sb.append("select "); + if (request.isDistinct()) { + sb.append("distinct "); + } + + sb.append(dbSql); + if (firstRow > 0) { + sb.append(" ").append("offset"); + sb.append(" ").append(firstRow).append(" rows"); + } + if (maxRows > 0) { + sb.append(" fetch next ").append(maxRows).append(" rows only"); + } + String sql = sb.toString(); + return new SqlLimitResponse(sql, false); + } + +} diff --git a/src/main/java/com/avaje/ebean/config/dbplatform/SqlServerBasicSqlLimiter.java b/src/main/java/com/avaje/ebean/config/dbplatform/SqlServerBasicSqlLimiter.java new file mode 100644 index 000000000..245fcc449 --- /dev/null +++ b/src/main/java/com/avaje/ebean/config/dbplatform/SqlServerBasicSqlLimiter.java @@ -0,0 +1,24 @@ +package com.avaje.ebean.config.dbplatform; + +/** + * SQL Server 2012 style limiter for raw sql. + */ +public class SqlServerBasicSqlLimiter implements BasicSqlLimiter { + + @Override + public String limit(String dbSql, int firstRow, int maxRows) { + + StringBuilder sb = new StringBuilder(50 + dbSql.length()); + sb.append(dbSql); + if (!dbSql.toLowerCase().contains("order by")) { + sb.append(" order by 1 "); + } + sb.append(" ").append("offset"); + sb.append(" ").append(firstRow).append(" rows"); + if (maxRows > 0) { + sb.append(" fetch next ").append(maxRows).append(" rows only"); + } + return sb.toString(); + } + +} diff --git a/src/main/java/com/avaje/ebean/config/dbplatform/SqlServerPlatform.java b/src/main/java/com/avaje/ebean/config/dbplatform/SqlServerPlatform.java index 2590dba2f..a31dca29a 100644 --- a/src/main/java/com/avaje/ebean/config/dbplatform/SqlServerPlatform.java +++ b/src/main/java/com/avaje/ebean/config/dbplatform/SqlServerPlatform.java @@ -16,7 +16,8 @@ public class SqlServerPlatform extends DatabasePlatform { this.persistBatchOnCascade = PersistBatch.NONE; this.idInExpandedForm = true; this.selectCountWithAlias = true; - this.sqlLimiter = new SqlServer2005SqlLimiter(); + this.sqlLimiter = new SqlServer2012SqlLimiter(); + this.basicSqlLimiter = new SqlServerBasicSqlLimiter(); this.platformDdl = new MsSqlServerDdl(this); this.dbIdentity.setIdType(IdType.IDENTITY); this.dbIdentity.setSupportsGetGeneratedKeys(true);