Author: ssegu Date: Thu Mar 22 13:26:18 2007 New Revision: 521443 URL: http://svn.apache.org/viewvc?view=rev&rev=521443 Log: OPENJPA-175. PagingResultObjectProvider to use FetchBatchSize when set for eager selects. Fix to handle Oracle in-clause limit of 1000
Modified: incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/PagingResultObjectProvider.java incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/InExpression.java incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/DBDictionary.java incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/OracleDictionary.java Modified: incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/PagingResultObjectProvider.java URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/PagingResultObjectProvider.java?view=diff&rev=521443&r1=521442&r2=521443 ============================================================================== --- incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/PagingResultObjectProvider.java (original) +++ incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/PagingResultObjectProvider.java Thu Mar 22 13:26:18 2007 @@ -22,6 +22,7 @@ import org.apache.openjpa.jdbc.meta.ClassMapping; import org.apache.openjpa.jdbc.meta.FieldMapping; import org.apache.openjpa.jdbc.schema.Column; +import org.apache.openjpa.jdbc.sql.DBDictionary; import org.apache.openjpa.jdbc.sql.Result; import org.apache.openjpa.jdbc.sql.SQLBuffer; import org.apache.openjpa.jdbc.sql.Select; @@ -149,28 +150,24 @@ // try to find a good page size. if the known size < batch size, use // it. if the batch size is set, then use that; if it's sorta close // to the size, then use the size / 2 to get two full pages rather - // than a possible big one and small one. cap everything at 50. + // than a possible big one and small one int batch = getFetchConfiguration().getFetchBatchSize(); int pageSize; - if (size <= batch && size <= 50) + if (batch < 0) pageSize = (int) size; - else if (batch > 0 && batch <= 50) { - if (size <= batch * 2) { + else { + if (batch == 0) + batch = 50; // reasonable default + if (size <= batch) + pageSize = (int) size; + else if (size <= batch * 2) { if (size % 2 == 0) pageSize = (int) (size / 2); else pageSize = (int) (size / 2 + 1); } else pageSize = batch; - } else if (size <= 50) - pageSize = (int) size; - else if (size <= 100) { - if (size % 2 == 0) - pageSize = (int) (size / 2); - else - pageSize = (int) (size / 2 + 1); - } else - pageSize = 50; + } _page = new Object[pageSize]; if (_paged.length > 1) @@ -341,10 +338,11 @@ // create where condition limiting instances to this page JDBCStore store = getStore(); Select sel = store.getSQLFactory().newSelect(); - SQLBuffer buf = new SQLBuffer(store.getDBDictionary()); + DBDictionary dict = store.getDBDictionary(); + SQLBuffer buf = new SQLBuffer(dict); Column[] pks = mapping.getPrimaryKeyColumns(); if (pks.length == 1) - inContains(sel, buf, mapping, pks, start, end); + createInContains(sel, dict, buf, mapping, pks, start, end); else orContains(sel, buf, mapping, pks, start, end); sel.where(buf); @@ -388,6 +386,32 @@ } } + /** + * Based on the DBDictionary, create the needed IN clauses. + */ + private void createInContains(Select sel, DBDictionary dict, SQLBuffer buf, + ClassMapping mapping, Column[] pks, int start, int end) { + int inClauseLimit = dict.inClauseLimit; + if ((inClauseLimit == -1) || ((end - start) <= inClauseLimit)) + inContains(sel, buf, mapping, pks, start, end); + else { + buf.append("("); + + int low = start; + for (int i = 1, stop = (end - start)/inClauseLimit; i <= stop; i++) { + inContains(sel, buf, mapping, pks, low, low + inClauseLimit); + low += inClauseLimit; + if (low < end) + buf.append(" OR "); + } + // Remaining + if (low < end) + inContains(sel, buf, mapping, pks, low, end); + + buf.append(")"); + } + } + /** * Create an IN clause limiting the results to the current page. */ Modified: incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/InExpression.java URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/InExpression.java?view=diff&rev=521443&r1=521442&r2=521443 ============================================================================== --- incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/InExpression.java (original) +++ incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/InExpression.java Thu Mar 22 13:26:18 2007 @@ -19,6 +19,7 @@ import java.util.Collection; import java.util.Collections; import java.util.Iterator; +import java.util.List; import java.util.Map; import org.apache.openjpa.jdbc.schema.Column; @@ -90,13 +91,13 @@ _const.calculateValue(sel, ctx, istate.constantState, null, null); _val.calculateValue(sel, ctx, istate.valueState, null, null); + List list = null; Collection coll = getCollection(ctx, istate.constantState); if (coll != null) { - Collection ds = new ArrayList(coll.size()); + list = new ArrayList(coll.size()); for (Iterator itr = coll.iterator(); itr.hasNext();) - ds.add(_val.toDataStoreValue(sel, ctx, istate.valueState, + list.add(_val.toDataStoreValue(sel, ctx, istate.valueState, itr.next())); - coll = ds; } Column[] cols = null; @@ -105,13 +106,44 @@ else if (_val instanceof GetObjectId) cols = ((GetObjectId) _val).getColumns(istate.valueState); - if (coll == null || coll.isEmpty()) + if (list == null || list.isEmpty()) buf.append("1 <> 1"); else if (_val.length(sel, ctx, istate.valueState) == 1) - inContains(sel, ctx, istate.valueState, buf, coll, cols); + createInContains(sel, ctx, istate.valueState, buf, list, cols); else - orContains(sel, ctx, istate.valueState, buf, coll, cols); + orContains(sel, ctx, istate.valueState, buf, list, cols); sel.append(buf, state.joins); + } + + /** + * Based on the inClauseLimit of the DBDictionary, create the needed IN + * clauses + */ + private void createInContains(Select sel, ExpContext ctx, ExpState state, + SQLBuffer buf, List list, Column[] cols) { + + int inClauseLimit = ctx.store.getDBDictionary().inClauseLimit; + if ((inClauseLimit == -1) || (list.size() < inClauseLimit)) + inContains(sel, ctx, state, buf, list, cols); + else { + buf.append("("); + + int low = 0; + for (int i = 1, stop = list.size()/inClauseLimit; i <= stop; i++) { + List subList = list.subList(low, low + inClauseLimit); + inContains(sel, ctx, state, buf, subList, cols); + low += inClauseLimit; + if (low < list.size()) + buf.append(" OR "); + } + // Remaining + if (low < list.size()) { + List rem = list.subList(low, list.size()); + inContains(sel, ctx, state, buf, rem, cols); + } + + buf.append(")"); + } } /** Modified: incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/DBDictionary.java URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/DBDictionary.java?view=diff&rev=521443&r1=521442&r2=521443 ============================================================================== --- incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/DBDictionary.java (original) +++ incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/DBDictionary.java Thu Mar 22 13:26:18 2007 @@ -237,6 +237,7 @@ public boolean useSetStringForClobs = false; public int maxEmbeddedBlobSize = -1; public int maxEmbeddedClobSize = -1; + public int inClauseLimit = -1; public int datePrecision = MILLI; public int characterColumnSize = 255; public String arrayTypeName = "ARRAY"; Modified: incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/OracleDictionary.java URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/OracleDictionary.java?view=diff&rev=521443&r1=521442&r2=521443 ============================================================================== --- incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/OracleDictionary.java (original) +++ incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/OracleDictionary.java Thu Mar 22 13:26:18 2007 @@ -116,6 +116,7 @@ maxConstraintNameLength = 30; maxEmbeddedBlobSize = 4000; maxEmbeddedClobSize = 4000; + inClauseLimit = 1000; supportsDeferredConstraints = true; supportsLockingWithDistinctClause = false;