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 c99680429a68ebd992d99f1f4988fbe739f1e7bf Author: andreykravchenko <[email protected]> AuthorDate: Wed Feb 10 12:30:33 2021 +0300 fixed manual offset for sql server --- .../java/org/apache/cayenne/dba/AutoAdapter.java | 6 --- .../java/org/apache/cayenne/dba/DbAdapter.java | 1 - .../java/org/apache/cayenne/dba/JdbcAdapter.java | 10 ----- .../dba/sqlserver/SQLServerActionBuilder.java | 28 ++++++++++-- .../cayenne/dba/sqlserver/SQLServerAdapter.java | 18 +++++++- .../dba/sqlserver/SQLServerSelectAction.java | 50 ++++++++++++++++++++++ .../dba/sqlserver/SQLServerTreeProcessor.java | 4 +- .../sqltree/SQLServerLimitOffsetNode.java | 30 +++++++++++-- 8 files changed, 120 insertions(+), 27 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 3c68a62..87d0972 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,8 +60,6 @@ public class AutoAdapter implements DbAdapter { */ volatile DbAdapter adapter; - protected Integer version; - /** * Creates an {@link AutoAdapter} based on a delegate adapter obtained via * "adapterProvider". @@ -273,8 +271,4 @@ public class AutoAdapter implements DbAdapter { 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 70f88ae..54e8580 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 @@ -256,5 +256,4 @@ public interface DbAdapter { */ 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 ad0a0ca..4a23596 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,8 +78,6 @@ 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. @@ -655,12 +653,4 @@ 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/SQLServerActionBuilder.java b/cayenne-server/src/main/java/org/apache/cayenne/dba/sqlserver/SQLServerActionBuilder.java index 4ebde3f..f19a671 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 @@ -21,9 +21,7 @@ package org.apache.cayenne.dba.sqlserver; import org.apache.cayenne.access.DataNode; import org.apache.cayenne.dba.JdbcActionBuilder; -import org.apache.cayenne.query.BatchQuery; -import org.apache.cayenne.query.ProcedureQuery; -import org.apache.cayenne.query.SQLAction; +import org.apache.cayenne.query.*; /** * @since 1.2 @@ -53,4 +51,28 @@ public class SQLServerActionBuilder extends JdbcActionBuilder { public SQLAction procedureAction(ProcedureQuery query) { return new SQLServerProcedureAction(query, dataNode); } + + /** + * @since 4.2 + */ + @Override + public <T> SQLAction objectSelectAction(SelectQuery<T> query) { + if (query.getOrderings() == null || query.getOrderings().size() == 0) { + return new SQLServerSelectAction(query, dataNode, true); + } + + return new SQLServerSelectAction(query, dataNode, false); + } + + /** + * @since 4.2 + */ + @Override + public <T> SQLAction objectSelectAction(FluentSelect<T> query) { + if (query.getOrderings() == null || query.getOrderings().size() == 0) { + return new SQLServerSelectAction(query, dataNode, true); + } + + return new SQLServerSelectAction(query, dataNode, false); + } } 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 611260a..67871df 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 @@ -75,6 +75,15 @@ import org.apache.cayenne.resource.ResourceLocator; 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 + * + * @since 4.2 + */ + protected Integer version; + + /** * @deprecated since 4.2 unused */ @Deprecated @@ -110,7 +119,7 @@ public class SQLServerAdapter extends SybaseAdapter { @Override public SQLTreeProcessor getSqlTreeProcessor() { SQLServerTreeProcessor sqlServerTreeProcessor = new SQLServerTreeProcessor(); - sqlServerTreeProcessor.setVersion(this.getVersion()); + sqlServerTreeProcessor.setVersion(getVersion()); return sqlServerTreeProcessor; } @@ -129,4 +138,11 @@ public class SQLServerAdapter extends SybaseAdapter { return SYSTEM_SCHEMAS; } + 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/SQLServerSelectAction.java b/cayenne-server/src/main/java/org/apache/cayenne/dba/sqlserver/SQLServerSelectAction.java new file mode 100644 index 0000000..7c09eef --- /dev/null +++ b/cayenne-server/src/main/java/org/apache/cayenne/dba/sqlserver/SQLServerSelectAction.java @@ -0,0 +1,50 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.cayenne.dba.sqlserver; + +import org.apache.cayenne.access.DataNode; +import org.apache.cayenne.access.jdbc.SelectAction; +import org.apache.cayenne.query.Select; + +/** + * @since 4.2 + */ +public class SQLServerSelectAction extends SelectAction { + + /** + * When using TOP N instead of LIMIT. The offset will be manual. + * + */ + private Boolean isManualOffset; + + public SQLServerSelectAction(Select<?> query, DataNode dataNode, Boolean isManualOffset) { + super(query, dataNode); + + this.isManualOffset = isManualOffset; + } + + @Override + protected int getInMemoryOffset(int queryOffset) { + if (isManualOffset) { + return super.getInMemoryOffset(queryOffset); + } + return 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 77721a3..c1c8c98 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 @@ -38,10 +38,10 @@ public class SQLServerTreeProcessor extends SybaseSQLTreeProcessor { @Override protected void onLimitOffsetNode(Node parent, LimitOffsetNode child, int index) { - if (version >= 12) { + 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())); + replaceChild(parent, index, new SQLServerLimitOffsetNode(child.getLimit(), child.getOffset()), false); return; } } 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 index 47cda22..1b916aa 100644 --- 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 @@ -1,3 +1,22 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + package org.apache.cayenne.dba.sqlserver.sqltree; import org.apache.cayenne.access.sqlbuilder.QuotingAppendable; @@ -10,17 +29,20 @@ import org.apache.cayenne.access.sqlbuilder.sqltree.Node; 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); + super(limit, offset); } @Override public QuotingAppendable append(QuotingAppendable buffer) { + // OFFSET X ROWS FETCH NEXT Y ROWS ONLY if(limit == 0 && offset == 0) { return buffer; } - return buffer.append(" OFFSET ").append(offset).append(" ROWS FETCH NEXT ").append(limit).append(" ROWS ONLY "); + buffer.append(" OFFSET ").append(offset).append(" ROWS"); + if (limit > 0) { + return buffer.append(" FETCH NEXT ").append(limit).append(" ROWS ONLY"); + } + return buffer; } @Override
