OPENJPA-175. PagingResultObjectProvider to use FetchBatchSize when set for eager selects. Fix to handle Oracle in-clause limit of 1000

git-svn-id: https://svn.apache.org/repos/asf/incubator/openjpa/trunk@521443 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Srinivasa Segu 2007-03-22 20:26:18 +00:00
parent 68e4f9a85b
commit ae2d8685e1
4 changed files with 79 additions and 21 deletions

View File

@ -22,6 +22,7 @@ import java.util.BitSet;
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 @@ public class PagingResultObjectProvider
// 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 @@ public class PagingResultObjectProvider
// 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 @@ public class PagingResultObjectProvider
}
}
/**
* 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.
*/

View File

@ -19,6 +19,7 @@ import java.util.ArrayList;
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 @@ class InExpression
_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,15 +106,46 @@ class InExpression
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(")");
}
}
/**
* Construct an IN clause with the value of the given collection.
*/

View File

@ -237,6 +237,7 @@ public class DBDictionary
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";

View File

@ -116,6 +116,7 @@ public class OracleDictionary
maxConstraintNameLength = 30;
maxEmbeddedBlobSize = 4000;
maxEmbeddedClobSize = 4000;
inClauseLimit = 1000;
supportsDeferredConstraints = true;
supportsLockingWithDistinctClause = false;