From 09859699f9087e5d7200999cb8eae48bc04aa201 Mon Sep 17 00:00:00 2001 From: David Ezzio Date: Tue, 28 Apr 2009 19:14:40 +0000 Subject: [PATCH] OpenJPA-1002: fixed select range for Oracle drivers, patch submitted by Amy Yang and Ravi Palacherla git-svn-id: https://svn.apache.org/repos/asf/openjpa/trunk@769505 13f79535-47bb-0310-9956-ffa450edef68 --- .../apache/openjpa/jdbc/sql/DBDictionary.java | 68 +++++++------- .../openjpa/jdbc/sql/OracleDictionary.java | 11 ++- .../persistence/jdbc/meta/TestRangeQuery.java | 92 +++++++++++++++++++ .../jdbc/common/apps/META-INF/persistence.xml | 1 + 4 files changed, 138 insertions(+), 34 deletions(-) create mode 100644 openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/meta/TestRangeQuery.java diff --git a/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/DBDictionary.java b/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/DBDictionary.java index f719a1674..405e61e30 100644 --- a/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/DBDictionary.java +++ b/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/DBDictionary.java @@ -370,7 +370,7 @@ public class DBDictionary public int batchLimit = NO_BATCH; public final Map> sqlStateCodes = - new HashMap>(); + new HashMap>(); public DBDictionary() { fixedSizeTypeNameSet.addAll(Arrays.asList(new String[]{ @@ -1727,14 +1727,14 @@ public class DBDictionary * size clause will be inserted appropriately. */ protected String insertSize(String typeName, String size) { - if (StringUtils.isEmpty(size)) { + if (StringUtils.isEmpty(size)) { int idx = typeName.indexOf("{0}"); if (idx != -1) { return typeName.substring(0, idx); } return typeName; } - + int idx = typeName.indexOf("{0}"); if (idx != -1) { // replace '{0}' with size @@ -1883,7 +1883,7 @@ public class DBDictionary from.append("("); from.append(toSelect(subSelect, null, subFrom, where, sel.getGrouping(), sel.getHaving(), null, sel.isDistinct(), - false, sel.getStartIndex(), sel.getEndIndex(), true)); + false, sel.getStartIndex(), sel.getEndIndex(), true, sel)); from.append(")"); if (requiresAliasForSubselect) from.append(" ").append(Select.FROM_SELECT_ALIAS); @@ -2076,7 +2076,7 @@ public class DBDictionary Val val = (Val) next.getValue(); if (val == null) - val = new Null(); + val = new Null(); Column col = fmd.getColumns()[0]; if (allowAlias) { sql.append(sel.getColumnAlias(col)); @@ -2371,11 +2371,12 @@ public class DBDictionary /** * Combine the given components into a SELECT statement. */ - public SQLBuffer toSelect(SQLBuffer selects, JDBCFetchConfiguration fetch, + protected SQLBuffer toSelect(SQLBuffer selects, + JDBCFetchConfiguration fetch, SQLBuffer from, SQLBuffer where, SQLBuffer group, SQLBuffer having, SQLBuffer order, boolean distinct, boolean forUpdate, long start, long end, - boolean subselect) { + boolean subselect, Select sel) { return toOperation(getSelectOperation(fetch), selects, from, where, group, having, order, distinct, start, end, getForUpdateClause(fetch, forUpdate, null), subselect); @@ -2395,7 +2396,8 @@ public class DBDictionary /** * Combine the given components into a SELECT statement. */ - public SQLBuffer toSelect(SQLBuffer selects, JDBCFetchConfiguration fetch, + protected SQLBuffer toSelect(SQLBuffer selects, + JDBCFetchConfiguration fetch, SQLBuffer from, SQLBuffer where, SQLBuffer group, SQLBuffer having, SQLBuffer order, boolean distinct, boolean forUpdate, long start, long end, @@ -3103,7 +3105,7 @@ public class DBDictionary public String[] getCreateTableSQL(Table table) { StringBuffer buf = new StringBuffer(); String tableName = checkNameLength(getFullName(table, false), - maxTableNameLength, "long-table-name"); + maxTableNameLength, "long-table-name"); buf.append("CREATE TABLE ").append(tableName); if (supportsComments && table.hasComment()) { buf.append(" "); @@ -3178,7 +3180,7 @@ public class DBDictionary StringBuffer buf = new StringBuffer(); buf.append("CREATE SEQUENCE "); String seqName = checkNameLength(getFullName(seq), maxTableNameLength, - "long-seq-name"); + "long-seq-name"); buf.append(seqName); if (seq.getInitialValue() != 0) buf.append(" START WITH ").append(seq.getInitialValue()); @@ -3318,7 +3320,7 @@ public class DBDictionary protected String getDeclareColumnSQL(Column col, boolean alter) { StringBuffer buf = new StringBuffer(); String columnName = checkNameLength(col.getName(), maxColumnNameLength, - "long-column-name"); + "long-column-name"); buf.append(columnName).append(" "); buf.append(getTypeName(col)); @@ -3499,7 +3501,7 @@ public class DBDictionary /** * Return the declaration SQL for the given unique constraint. This * method is used from within {@link #getCreateTableSQL}. - * Returns CONSTRAINT <name> UNIQUE (<col list>) + * Returns CONSTRAINT <name> UNIQUE (<col list>) * by default. */ protected String getUniqueConstraintSQL(Unique unq) { @@ -3510,7 +3512,7 @@ public class DBDictionary if (unq.getName() != null && CONS_NAME_BEFORE.equals(constraintNameMode)) buf.append("CONSTRAINT ").append(checkNameLength(unq.getName(), - maxConstraintNameLength, "long-constraint-name")).append(" "); + maxConstraintNameLength, "long-constraint-name")).append(" "); buf.append("UNIQUE "); if (unq.getName() != null && CONS_NAME_MID.equals(constraintNameMode)) buf.append(unq.getName()).append(" "); @@ -4163,22 +4165,22 @@ public class DBDictionary if (stream == null) { // User supplied dictionary but no error codes xml // use default stream = DBDictionary.class.getResourceAsStream(rsrc); - dictionaryClassName = getClass().getSuperclass().getName(); + dictionaryClassName = getClass().getSuperclass().getName(); } codeReader.parse(stream, dictionaryClassName, this); } public void addErrorCode(int errorType, String errorCode) { - if (errorCode == null || errorCode.trim().length() == 0) - return; - Set codes = sqlStateCodes.get(errorType); - if (codes == null) { - codes = new HashSet(); - codes.add(errorCode.trim()); - sqlStateCodes.put(errorType, codes); - } else { - codes.add(errorCode.trim()); - } + if (errorCode == null || errorCode.trim().length() == 0) + return; + Set codes = sqlStateCodes.get(errorType); + if (codes == null) { + codes = new HashSet(); + codes.add(errorCode.trim()); + sqlStateCodes.put(errorType, codes); + } else { + codes.add(errorCode.trim()); + } } /** @@ -4331,11 +4333,11 @@ public class DBDictionary */ public OpenJPAException newStoreException(String msg, SQLException[] causes, Object failed) { - if (causes != null && causes.length > 0) { - OpenJPAException ret = narrow(msg, causes[0]); - ret.setFailedObject(failed).setNestedThrowables(causes); - return ret; - } + if (causes != null && causes.length > 0) { + OpenJPAException ret = narrow(msg, causes[0]); + ret.setFailedObject(failed).setNestedThrowables(causes); + return ret; + } return new StoreException(msg).setFailedObject(failed). setNestedThrowables(causes); } @@ -4718,9 +4720,9 @@ public class DBDictionary * given message key otherwise returns the same name. */ final String checkNameLength(String name, int length, String msgKey) { - if (name.length() > length) - throw new UserException(_loc.get(msgKey, name, name.length(), - length)); - return name; + if (name.length() > length) + throw new UserException(_loc.get(msgKey, name, name.length(), + length)); + return name; } } \ No newline at end of file diff --git a/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/OracleDictionary.java b/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/OracleDictionary.java index 08881417f..9dec01ed3 100644 --- a/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/OracleDictionary.java +++ b/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/OracleDictionary.java @@ -360,7 +360,16 @@ public class OracleDictionary return buf; } - public SQLBuffer toSelect(SQLBuffer select, JDBCFetchConfiguration fetch, + protected SQLBuffer toSelect(SQLBuffer select, JDBCFetchConfiguration fetch, + SQLBuffer tables, SQLBuffer where, SQLBuffer group, + SQLBuffer having, SQLBuffer order, + boolean distinct, boolean forUpdate, long start, long end, + boolean subselect, Select sel) { + return toSelect(select, fetch, tables, where, group, having, order, + distinct, forUpdate, start, end, sel); + } + + protected SQLBuffer toSelect(SQLBuffer select, JDBCFetchConfiguration fetch, SQLBuffer tables, SQLBuffer where, SQLBuffer group, SQLBuffer having, SQLBuffer order, boolean distinct, boolean forUpdate, long start, long end, diff --git a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/meta/TestRangeQuery.java b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/meta/TestRangeQuery.java new file mode 100644 index 000000000..91c3c0584 --- /dev/null +++ b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/meta/TestRangeQuery.java @@ -0,0 +1,92 @@ +/* + * 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 + * + * http://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.openjpa.persistence.jdbc.meta; + +import java.util.*; +import org.apache.openjpa.jdbc.conf.JDBCConfiguration; +import org.apache.openjpa.jdbc.sql.DBDictionary; +import org.apache.openjpa.kernel.jpql.JPQLParser; +import org.apache.openjpa.persistence.FetchPlan; +import org.apache.openjpa.persistence.OpenJPAQuery; + +import org.apache.openjpa.persistence.jdbc.common.apps.*; + + +import org.apache.openjpa.persistence.OpenJPAEntityManager; +import org.apache.openjpa.persistence.jdbc.common.apps.EagerOuterJoinPC; + + +public class TestRangeQuery extends + org.apache.openjpa.persistence.jdbc.kernel.BaseJDBCTest { + + /** Creates a new instance of TestRangeQuery */ + public TestRangeQuery(String name) { + super(name); + } + + public boolean skipTest() { + DBDictionary dict = ((JDBCConfiguration) getConfiguration()). + getDBDictionaryInstance(); + return !dict.supportsSubselect; + } + + public void setUp() { + + deleteAll(HelperPC.class); + deleteAll(EagerOuterJoinPC2.class); + deleteAll(EagerOuterJoinPC.class); + } + + public void testQueryRange() { + insertManyStringList(); + + OpenJPAEntityManager em =(OpenJPAEntityManager)currentEntityManager(); + FetchPlan fetch = (FetchPlan) em.getFetchPlan(); + fetch.addField(EagerOuterJoinPC.class, "stringList"); + fetch.setFetchBatchSize(3); + OpenJPAQuery q = em.createQuery(JPQLParser.LANG_JPQL, + "select x from EagerOuterJoinPC x order by x.name asc"); + q.setFirstResult(5).setMaxResults(15); + + List results = (List) q.getResultList(); + assertEquals(5, results.size()); + + for (int i = 0; i < results.size(); i++) { + EagerOuterJoinPC pc = (EagerOuterJoinPC) results.get(i); + assertEquals(String.valueOf(i + 5), pc.getName()); + } + q.closeAll(); + em.close(); + } + + @SuppressWarnings("unchecked") + private void insertManyStringList() { + OpenJPAEntityManager em =(OpenJPAEntityManager)currentEntityManager(); + startTx(em);; + for (int i = 0; i < 10; i++) { + EagerOuterJoinPC pc = new EagerOuterJoinPC(); + pc.setName(String.valueOf(i)); + pc.getStringList().add(i + ".1"); + pc.getStringList().add(i + ".2"); + em.persist(pc); + } + endTx(em);; + em.close(); + } +} diff --git a/openjpa-persistence-jdbc/src/test/resources/org/apache/openjpa/persistence/jdbc/common/apps/META-INF/persistence.xml b/openjpa-persistence-jdbc/src/test/resources/org/apache/openjpa/persistence/jdbc/common/apps/META-INF/persistence.xml index 1e8e940df..bfdc02f2d 100644 --- a/openjpa-persistence-jdbc/src/test/resources/org/apache/openjpa/persistence/jdbc/common/apps/META-INF/persistence.xml +++ b/openjpa-persistence-jdbc/src/test/resources/org/apache/openjpa/persistence/jdbc/common/apps/META-INF/persistence.xml @@ -39,5 +39,6 @@ org.apache.openjpa.persistence.jdbc.common.apps.HelperPC4 org.apache.openjpa.persistence.jdbc.common.apps.InvertA org.apache.openjpa.persistence.jdbc.common.apps.InvertB + org.apache.openjpa.persistence.jdbc.common.apps.EagerOuterJoinPC