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);
+    }
+
+}

Reply via email to