This is an automated email from the ASF dual-hosted git repository. ntimofeev pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/cayenne.git
commit ed66f0e4e8aa73c5cd49fd6237452786b85db7e7 Author: andreykravchenko <[email protected]> AuthorDate: Mon Feb 8 15:46:18 2021 +0300 CAY-2587 SQLServer Limit Offset convertation --- .../java/org/apache/cayenne/dba/AutoAdapter.java | 7 +++++ .../java/org/apache/cayenne/dba/DbAdapter.java | 2 ++ .../java/org/apache/cayenne/dba/JdbcAdapter.java | 10 +++++++ .../cayenne/dba/sqlserver/SQLServerAdapter.java | 4 ++- .../cayenne/dba/sqlserver/SQLServerSniffer.java | 1 + .../dba/sqlserver/SQLServerTreeProcessor.java | 28 +++++++++++++++++-- .../sqltree/SQLServerLimitOffsetNode.java | 31 ++++++++++++++++++++++ 7 files changed, 80 insertions(+), 3 deletions(-) diff --git a/cayenne-server/src/main/java/org/apache/cayenne/dba/AutoAdapter.java b/cayenne-server/src/main/java/org/apache/cayenne/dba/AutoAdapter.java index 54baa19..3c68a62 100644 --- a/cayenne-server/src/main/java/org/apache/cayenne/dba/AutoAdapter.java +++ b/cayenne-server/src/main/java/org/apache/cayenne/dba/AutoAdapter.java @@ -60,6 +60,8 @@ public class AutoAdapter implements DbAdapter { */ volatile DbAdapter adapter; + protected Integer version; + /** * Creates an {@link AutoAdapter} based on a delegate adapter obtained via * "adapterProvider". @@ -270,4 +272,9 @@ public class AutoAdapter implements DbAdapter { public List<String> getSystemSchemas() { return getAdapter().getSystemSchemas(); } + + @Override + public Integer getVersion() { + return version; + } } diff --git a/cayenne-server/src/main/java/org/apache/cayenne/dba/DbAdapter.java b/cayenne-server/src/main/java/org/apache/cayenne/dba/DbAdapter.java index a043e2f..70f88ae 100644 --- a/cayenne-server/src/main/java/org/apache/cayenne/dba/DbAdapter.java +++ b/cayenne-server/src/main/java/org/apache/cayenne/dba/DbAdapter.java @@ -255,4 +255,6 @@ public interface DbAdapter { * @return list of system schemas */ List<String> getSystemSchemas(); + + Integer getVersion(); } diff --git a/cayenne-server/src/main/java/org/apache/cayenne/dba/JdbcAdapter.java b/cayenne-server/src/main/java/org/apache/cayenne/dba/JdbcAdapter.java index 4a23596..ad0a0ca 100644 --- a/cayenne-server/src/main/java/org/apache/cayenne/dba/JdbcAdapter.java +++ b/cayenne-server/src/main/java/org/apache/cayenne/dba/JdbcAdapter.java @@ -78,6 +78,8 @@ public class JdbcAdapter implements DbAdapter { protected ResourceLocator resourceLocator; protected boolean caseInsensitiveCollations; + protected Integer version; + /** * @since 3.1 * @deprecated since 4.0 BatchQueryBuilderfactory is attached to the DataNode. @@ -653,4 +655,12 @@ public class JdbcAdapter implements DbAdapter { return this; } + @Override + public Integer getVersion() { + return version; + } + + public void setVersion(Integer version) { + this.version = version; + } } diff --git a/cayenne-server/src/main/java/org/apache/cayenne/dba/sqlserver/SQLServerAdapter.java b/cayenne-server/src/main/java/org/apache/cayenne/dba/sqlserver/SQLServerAdapter.java index 92fcd46..611260a 100644 --- a/cayenne-server/src/main/java/org/apache/cayenne/dba/sqlserver/SQLServerAdapter.java +++ b/cayenne-server/src/main/java/org/apache/cayenne/dba/sqlserver/SQLServerAdapter.java @@ -109,7 +109,9 @@ public class SQLServerAdapter extends SybaseAdapter { */ @Override public SQLTreeProcessor getSqlTreeProcessor() { - return new SQLServerTreeProcessor(); + SQLServerTreeProcessor sqlServerTreeProcessor = new SQLServerTreeProcessor(); + sqlServerTreeProcessor.setVersion(this.getVersion()); + return sqlServerTreeProcessor; } /** diff --git a/cayenne-server/src/main/java/org/apache/cayenne/dba/sqlserver/SQLServerSniffer.java b/cayenne-server/src/main/java/org/apache/cayenne/dba/sqlserver/SQLServerSniffer.java index 052e8eb..f0c7d6f 100644 --- a/cayenne-server/src/main/java/org/apache/cayenne/dba/sqlserver/SQLServerSniffer.java +++ b/cayenne-server/src/main/java/org/apache/cayenne/dba/sqlserver/SQLServerSniffer.java @@ -50,6 +50,7 @@ public class SQLServerSniffer implements DbAdapterDetector { SQLServerAdapter adapter = objectFactory.newInstance( SQLServerAdapter.class, SQLServerAdapter.class.getName()); + adapter.setVersion(md.getDatabaseMajorVersion()); // detect whether generated keys are supported boolean generatedKeys = false; diff --git a/cayenne-server/src/main/java/org/apache/cayenne/dba/sqlserver/SQLServerTreeProcessor.java b/cayenne-server/src/main/java/org/apache/cayenne/dba/sqlserver/SQLServerTreeProcessor.java index e2ecd53..77721a3 100644 --- a/cayenne-server/src/main/java/org/apache/cayenne/dba/sqlserver/SQLServerTreeProcessor.java +++ b/cayenne-server/src/main/java/org/apache/cayenne/dba/sqlserver/SQLServerTreeProcessor.java @@ -19,9 +19,9 @@ package org.apache.cayenne.dba.sqlserver; -import org.apache.cayenne.access.sqlbuilder.sqltree.ColumnNode; -import org.apache.cayenne.access.sqlbuilder.sqltree.Node; +import org.apache.cayenne.access.sqlbuilder.sqltree.*; import org.apache.cayenne.dba.sqlserver.sqltree.SQLServerColumnNode; +import org.apache.cayenne.dba.sqlserver.sqltree.SQLServerLimitOffsetNode; import org.apache.cayenne.dba.sybase.SybaseSQLTreeProcessor; /** @@ -29,8 +29,32 @@ import org.apache.cayenne.dba.sybase.SybaseSQLTreeProcessor; */ public class SQLServerTreeProcessor extends SybaseSQLTreeProcessor { + private Integer version; + @Override protected void onColumnNode(Node parent, ColumnNode child, int index) { replaceChild(parent, index, new SQLServerColumnNode(child)); } + + @Override + protected void onLimitOffsetNode(Node parent, LimitOffsetNode child, int index) { + if (version >= 12) { + for (int i = 0; i < parent.getChildrenCount(); i++) { + if (parent.getChild(i) instanceof OrderByNode) { + replaceChild(parent, index, new SQLServerLimitOffsetNode(child.getLimit(), child.getOffset())); + return; + } + } + } + + super.onLimitOffsetNode(parent, child, index); + } + + public Integer getVersion() { + return version; + } + + public void setVersion(Integer version) { + this.version = version; + } } diff --git a/cayenne-server/src/main/java/org/apache/cayenne/dba/sqlserver/sqltree/SQLServerLimitOffsetNode.java b/cayenne-server/src/main/java/org/apache/cayenne/dba/sqlserver/sqltree/SQLServerLimitOffsetNode.java new file mode 100644 index 0000000..47cda22 --- /dev/null +++ b/cayenne-server/src/main/java/org/apache/cayenne/dba/sqlserver/sqltree/SQLServerLimitOffsetNode.java @@ -0,0 +1,31 @@ +package org.apache.cayenne.dba.sqlserver.sqltree; + +import org.apache.cayenne.access.sqlbuilder.QuotingAppendable; +import org.apache.cayenne.access.sqlbuilder.sqltree.LimitOffsetNode; +import org.apache.cayenne.access.sqlbuilder.sqltree.Node; + +/** + * @since 4.2 + */ +public class SQLServerLimitOffsetNode extends LimitOffsetNode { + + public SQLServerLimitOffsetNode(int limit, int offset) { + // Per SQLServer documentation: "To retrieve all rows from a certain offset up to the end of the result set, + // you can use some large number for the second parameter." + super(limit == 0 && offset > 0 ? Integer.MAX_VALUE : limit, offset); + } + + @Override + public QuotingAppendable append(QuotingAppendable buffer) { + if(limit == 0 && offset == 0) { + return buffer; + } + return buffer.append(" OFFSET ").append(offset).append(" ROWS FETCH NEXT ").append(limit).append(" ROWS ONLY "); + } + + @Override + public Node copy() { + return new SQLServerLimitOffsetNode(limit, offset); + } + +}
