cayenne-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From ntimof...@apache.org
Subject [cayenne] 05/05: CAY-2587 SQLServer Limit Offset translation - refactoring and cleanup - release notes
Date Thu, 25 Feb 2021 12:21:52 GMT
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 37ee115185a3234c14d7dcf1bc6afc014e7225c1
Author: Nikita Timofeev <stariy95@gmail.com>
AuthorDate: Thu Feb 25 15:21:36 2021 +0300

    CAY-2587 SQLServer Limit Offset translation
     - refactoring and cleanup
     - release notes
---
 RELEASE-NOTES.txt                                  |  1 +
 .../access/sqlbuilder/sqltree/NodeType.java        |  3 +-
 .../access/sqlbuilder/sqltree/OrderByNode.java     |  5 +++
 .../dba/sqlserver/SQLServerActionBuilder.java      | 41 ++++++++++----------
 .../cayenne/dba/sqlserver/SQLServerAdapter.java    | 26 +++++++------
 .../dba/sqlserver/SQLServerSelectAction.java       | 15 +++-----
 .../dba/sqlserver/SQLServerTreeProcessor.java      | 26 +------------
 ...ocessor.java => SQLServerTreeProcessorV12.java} | 44 ++++++++++------------
 8 files changed, 70 insertions(+), 91 deletions(-)

diff --git a/RELEASE-NOTES.txt b/RELEASE-NOTES.txt
index 5b821b1..ddd59d4 100644
--- a/RELEASE-NOTES.txt
+++ b/RELEASE-NOTES.txt
@@ -13,6 +13,7 @@ Date:
 ----------------------------------
 Changes/New Features:
 
+CAY-2587 SQLServer Limit Offset translation
 CAY-2677 Custom Class Generation Templates for Embeddables and DataMaps
 CAY-2689 ServerRuntime API: missing some variants of the performInTransaction() method
 CAY-2692 Add entity lifecycle callbacks via annotated methods
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/access/sqlbuilder/sqltree/NodeType.java
b/cayenne-server/src/main/java/org/apache/cayenne/access/sqlbuilder/sqltree/NodeType.java
index 575d330..f463c07 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/access/sqlbuilder/sqltree/NodeType.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/access/sqlbuilder/sqltree/NodeType.java
@@ -38,5 +38,6 @@ public enum NodeType {
     FROM,
     UPDATE_SET,
     INSERT_COLUMNS,
-    INSERT_VALUES
+    INSERT_VALUES,
+    ORDER_BY
 }
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/access/sqlbuilder/sqltree/OrderByNode.java
b/cayenne-server/src/main/java/org/apache/cayenne/access/sqlbuilder/sqltree/OrderByNode.java
index 7e54ae6..663f66c 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/access/sqlbuilder/sqltree/OrderByNode.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/access/sqlbuilder/sqltree/OrderByNode.java
@@ -40,4 +40,9 @@ public class OrderByNode extends Node {
     public Node copy() {
         return new OrderByNode();
     }
+
+    @Override
+    public NodeType getType() {
+        return NodeType.ORDER_BY;
+    }
 }
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/dba/sqlserver/SQLServerActionBuilder.java
b/cayenne-server/src/main/java/org/apache/cayenne/dba/sqlserver/SQLServerActionBuilder.java
index bd43ee9..bb82143 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/dba/sqlserver/SQLServerActionBuilder.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/dba/sqlserver/SQLServerActionBuilder.java
@@ -33,23 +33,32 @@ public class SQLServerActionBuilder extends JdbcActionBuilder {
 	 *
 	 * @since 4.2
 	 */
-	private Integer version;
+	private final Integer version;
 
 	/**
+	 * @param dataNode current data node
 	 * @since 4.0
 	 */
 	public SQLServerActionBuilder(DataNode dataNode) {
+		this(dataNode, null);
+	}
+
+	/**
+	 * @param dataNode current data node
+	 * @param version database server version
+	 * @since 4.2
+	 */
+	public SQLServerActionBuilder(DataNode dataNode, Integer version) {
 		super(dataNode);
+		this.version = version;
 	}
 
 	@Override
 	public SQLAction batchAction(BatchQuery query) {
 		// check run strategy...
 
-		// optimistic locking is not supported in batches due to JDBC driver
-		// limitations
+		// optimistic locking is not supported in batches due to JDBC driver limitations
 		boolean useOptimisticLock = query.isUsingOptimisticLocking();
-
 		boolean runningAsBatch = !useOptimisticLock && dataNode.getAdapter().supportsBatchUpdates();
 		return new SQLServerBatchAction(query, dataNode, runningAsBatch);
 	}
@@ -64,12 +73,7 @@ public class SQLServerActionBuilder extends JdbcActionBuilder {
 	 */
 	@Override
 	public <T> SQLAction objectSelectAction(SelectQuery<T> query) {
-		if (query.getOrderings() == null || query.getOrderings().size() == 0 ||
-				version == null || version < 12) {
-			return new SQLServerSelectAction(query, dataNode, true);
-		}
-
-		return new SQLServerSelectAction(query, dataNode, false);
+		return new SQLServerSelectAction(query, dataNode, needInMemoryOffset(query));
 	}
 
 	/**
@@ -77,19 +81,16 @@ public class SQLServerActionBuilder extends JdbcActionBuilder {
 	 */
 	@Override
 	public <T> SQLAction objectSelectAction(FluentSelect<T> query) {
-		if (query.getOrderings() == null || query.getOrderings().size() == 0 ||
-				version == null || version < 12) {
-			return new SQLServerSelectAction(query, dataNode, true);
-		}
-
-		return new SQLServerSelectAction(query, dataNode, false);
+		return new SQLServerSelectAction(query, dataNode, needInMemoryOffset(query));
 	}
 
-	public Integer getVersion() {
-		return version;
+	private boolean needInMemoryOffset(SelectQuery<?> query) {
+		return query.getOrderings() == null || query.getOrderings().size() == 0
+				|| version == null || version < 12;
 	}
 
-	public void setVersion(Integer version) {
-		this.version = version;
+	private boolean needInMemoryOffset(FluentSelect<?> query) {
+		return query.getOrderings() == null || query.getOrderings().size() == 0
+				|| version == null || version < 12;
 	}
 }
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 9805e0d..6642e8e 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
@@ -76,8 +76,7 @@ public class SQLServerAdapter extends SybaseAdapter {
 
 	/**
 	 * Stores the major version of the database.
-	 * Database versions 12 and higher support the use of LIMIT,
-	 * lower versions use TOP N
+	 * Database versions 12 and higher supports the use of LIMIT,lower versions use TOP N.
 	 *
 	 * @since 4.2
 	 */
@@ -89,10 +88,12 @@ public class SQLServerAdapter extends SybaseAdapter {
 	@Deprecated
 	public static final String TRIM_FUNCTION = "RTRIM";
 
-	private List<String> SYSTEM_SCHEMAS = Arrays.asList("db_accessadmin", "db_backupoperator",
+	private final List<String> SYSTEM_SCHEMAS = Arrays.asList(
+			"db_accessadmin", "db_backupoperator",
 			"db_datareader", "db_datawriter", "db_ddladmin", "db_denydatareader",
 			"db_denydatawriter","dbo", "sys", "db_owner", "db_securityadmin", "guest",
-			"INFORMATION_SCHEMA");
+			"INFORMATION_SCHEMA"
+	);
 
 	public SQLServerAdapter(@Inject RuntimeProperties runtimeProperties,
 							@Inject(Constants.SERVER_DEFAULT_TYPES_LIST) List<ExtendedType> defaultExtendedTypes,
@@ -106,7 +107,7 @@ public class SQLServerAdapter extends SybaseAdapter {
 	}
 
     /**
-     * Not supported, see: <a href="http://microsoft/mssql-jdbc#245">mssql-jdbc #245</a>
+     * Not supported, see: <a href="https://github.com/microsoft/mssql-jdbc/issues/245">mssql-jdbc
#245</a>
      */
 	@Override
 	public boolean supportsGeneratedKeysForBatchInserts() {
@@ -118,9 +119,10 @@ public class SQLServerAdapter extends SybaseAdapter {
 	 */
 	@Override
 	public SQLTreeProcessor getSqlTreeProcessor() {
-		SQLServerTreeProcessor sqlServerTreeProcessor = new SQLServerTreeProcessor();
-		sqlServerTreeProcessor.setVersion(getVersion());
-		return sqlServerTreeProcessor;
+		if(getVersion() != null && getVersion() >= 12) {
+			return new SQLServerTreeProcessorV12();
+		}
+		return new SQLServerTreeProcessor();
 	}
 
 	/**
@@ -130,9 +132,7 @@ public class SQLServerAdapter extends SybaseAdapter {
 	 */
 	@Override
 	public SQLAction getAction(Query query, DataNode node) {
-		SQLServerActionBuilder sqlServerActionBuilder = new SQLServerActionBuilder(node);
-		sqlServerActionBuilder.setVersion(this.version);
-		return query.createSQLAction(sqlServerActionBuilder);
+		return query.createSQLAction(new SQLServerActionBuilder(node, getVersion()));
 	}
 
 	@Override
@@ -144,6 +144,10 @@ public class SQLServerAdapter extends SybaseAdapter {
 		return version;
 	}
 
+	/**
+	 * @since 4.2
+	 * @param version of the server as provided by the JDBC driver
+	 */
 	public void setVersion(Integer version) {
 		this.version = version;
 	}
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/dba/sqlserver/SQLServerSelectAction.java
b/cayenne-server/src/main/java/org/apache/cayenne/dba/sqlserver/SQLServerSelectAction.java
index 7c09eef..5c9d7d2 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/dba/sqlserver/SQLServerSelectAction.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/dba/sqlserver/SQLServerSelectAction.java
@@ -29,22 +29,17 @@ import org.apache.cayenne.query.Select;
 public class SQLServerSelectAction extends SelectAction {
 
     /**
-     * When using TOP N instead of LIMIT. The offset will be manual.
-     *
+     * When using TOP N instead of LIMIT the offset will be processed in-memory.
      */
-    private Boolean isManualOffset;
+    private final boolean needsInMemoryOffset;
 
-    public SQLServerSelectAction(Select<?> query, DataNode dataNode, Boolean isManualOffset)
{
+    public SQLServerSelectAction(Select<?> query, DataNode dataNode, boolean needsInMemoryOffset)
{
         super(query, dataNode);
-
-        this.isManualOffset = isManualOffset;
+        this.needsInMemoryOffset = needsInMemoryOffset;
     }
 
     @Override
     protected int getInMemoryOffset(int queryOffset) {
-        if (isManualOffset) {
-            return super.getInMemoryOffset(queryOffset);
-        }
-        return 0;
+        return needsInMemoryOffset ? super.getInMemoryOffset(queryOffset) : 0;
     }
 }
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 347da1f..46be80d 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
@@ -21,7 +21,6 @@ package org.apache.cayenne.dba.sqlserver;
 
 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,32 +28,9 @@ 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 != null && 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()), false);
-                    return;
-                }
-            }
-        }
-
-        super.onLimitOffsetNode(parent, child, index);
-    }
-
-    public Integer getVersion() {
-        return version;
+        replaceChild(parent, index, new SQLServerColumnNode(child));
     }
 
-    public void setVersion(Integer version) {
-        this.version = version;
-    }
 }
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/SQLServerTreeProcessorV12.java
similarity index 57%
copy from cayenne-server/src/main/java/org/apache/cayenne/dba/sqlserver/SQLServerTreeProcessor.java
copy to cayenne-server/src/main/java/org/apache/cayenne/dba/sqlserver/SQLServerTreeProcessorV12.java
index 347da1f..7a7bb27 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/SQLServerTreeProcessorV12.java
@@ -19,42 +19,38 @@
 
 package org.apache.cayenne.dba.sqlserver;
 
-import org.apache.cayenne.access.sqlbuilder.sqltree.*;
-import org.apache.cayenne.dba.sqlserver.sqltree.SQLServerColumnNode;
+import org.apache.cayenne.access.sqlbuilder.sqltree.LimitOffsetNode;
+import org.apache.cayenne.access.sqlbuilder.sqltree.Node;
+import org.apache.cayenne.access.sqlbuilder.sqltree.NodeType;
 import org.apache.cayenne.dba.sqlserver.sqltree.SQLServerLimitOffsetNode;
-import org.apache.cayenne.dba.sybase.SybaseSQLTreeProcessor;
 
 /**
+ * SQL tree processor that supports OFFSET X ROWS FETCH NEXT Y ROWS ONLY clause
+ * for the SQLServer 2012 and later.
+ *
  * @since 4.2
  */
-public class SQLServerTreeProcessor extends SybaseSQLTreeProcessor {
-
-    private Integer version;
-
-    @Override
-    protected void onColumnNode(Node parent, ColumnNode child, int index) {
-        replaceChild(parent, index,  new SQLServerColumnNode(child));
-    }
+public class SQLServerTreeProcessorV12 extends SQLServerTreeProcessor {
 
     @Override
     protected void onLimitOffsetNode(Node parent, LimitOffsetNode child, int index) {
-        if (version != null && 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()), false);
-                    return;
-                }
-            }
+        if (hasOrderingClause(parent)) {
+            replaceChild(parent, index, new SQLServerLimitOffsetNode(child.getLimit(), child.getOffset()),
false);
+            return;
         }
-
         super.onLimitOffsetNode(parent, child, index);
     }
 
-    public Integer getVersion() {
-        return version;
+    protected boolean hasOrderingClause(Node parent) {
+        if(parent == null) {
+            return false;
+        }
+        for (int i = 0; i < parent.getChildrenCount(); i++) {
+            if (parent.getChild(i).getType() == NodeType.ORDER_BY) {
+                return true;
+            }
+        }
+        return hasOrderingClause(parent.getParent());
     }
 
-    public void setVersion(Integer version) {
-        this.version = version;
-    }
 }


Mime
View raw message