mirror of https://github.com/apache/openjpa.git
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:
parent
68e4f9a85b
commit
ae2d8685e1
|
@ -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.
|
||||
*/
|
||||
|
|
|
@ -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.
|
||||
*/
|
||||
|
|
|
@ -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";
|
||||
|
|
|
@ -116,6 +116,7 @@ public class OracleDictionary
|
|||
maxConstraintNameLength = 30;
|
||||
maxEmbeddedBlobSize = 4000;
|
||||
maxEmbeddedClobSize = 4000;
|
||||
inClauseLimit = 1000;
|
||||
|
||||
supportsDeferredConstraints = true;
|
||||
supportsLockingWithDistinctClause = false;
|
||||
|
|
Loading…
Reference in New Issue