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.ClassMapping;
|
||||||
import org.apache.openjpa.jdbc.meta.FieldMapping;
|
import org.apache.openjpa.jdbc.meta.FieldMapping;
|
||||||
import org.apache.openjpa.jdbc.schema.Column;
|
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.Result;
|
||||||
import org.apache.openjpa.jdbc.sql.SQLBuffer;
|
import org.apache.openjpa.jdbc.sql.SQLBuffer;
|
||||||
import org.apache.openjpa.jdbc.sql.Select;
|
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
|
// 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
|
// 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
|
// 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 batch = getFetchConfiguration().getFetchBatchSize();
|
||||||
int pageSize;
|
int pageSize;
|
||||||
if (size <= batch && size <= 50)
|
if (batch < 0)
|
||||||
pageSize = (int) size;
|
pageSize = (int) size;
|
||||||
else if (batch > 0 && batch <= 50) {
|
else {
|
||||||
if (size <= batch * 2) {
|
if (batch == 0)
|
||||||
|
batch = 50; // reasonable default
|
||||||
|
if (size <= batch)
|
||||||
|
pageSize = (int) size;
|
||||||
|
else if (size <= batch * 2) {
|
||||||
if (size % 2 == 0)
|
if (size % 2 == 0)
|
||||||
pageSize = (int) (size / 2);
|
pageSize = (int) (size / 2);
|
||||||
else
|
else
|
||||||
pageSize = (int) (size / 2 + 1);
|
pageSize = (int) (size / 2 + 1);
|
||||||
} else
|
} else
|
||||||
pageSize = batch;
|
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];
|
_page = new Object[pageSize];
|
||||||
if (_paged.length > 1)
|
if (_paged.length > 1)
|
||||||
|
@ -341,10 +338,11 @@ public class PagingResultObjectProvider
|
||||||
// create where condition limiting instances to this page
|
// create where condition limiting instances to this page
|
||||||
JDBCStore store = getStore();
|
JDBCStore store = getStore();
|
||||||
Select sel = store.getSQLFactory().newSelect();
|
Select sel = store.getSQLFactory().newSelect();
|
||||||
SQLBuffer buf = new SQLBuffer(store.getDBDictionary());
|
DBDictionary dict = store.getDBDictionary();
|
||||||
|
SQLBuffer buf = new SQLBuffer(dict);
|
||||||
Column[] pks = mapping.getPrimaryKeyColumns();
|
Column[] pks = mapping.getPrimaryKeyColumns();
|
||||||
if (pks.length == 1)
|
if (pks.length == 1)
|
||||||
inContains(sel, buf, mapping, pks, start, end);
|
createInContains(sel, dict, buf, mapping, pks, start, end);
|
||||||
else
|
else
|
||||||
orContains(sel, buf, mapping, pks, start, end);
|
orContains(sel, buf, mapping, pks, start, end);
|
||||||
sel.where(buf);
|
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.
|
* 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.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import org.apache.openjpa.jdbc.schema.Column;
|
import org.apache.openjpa.jdbc.schema.Column;
|
||||||
|
@ -90,13 +91,13 @@ class InExpression
|
||||||
_const.calculateValue(sel, ctx, istate.constantState, null, null);
|
_const.calculateValue(sel, ctx, istate.constantState, null, null);
|
||||||
_val.calculateValue(sel, ctx, istate.valueState, null, null);
|
_val.calculateValue(sel, ctx, istate.valueState, null, null);
|
||||||
|
|
||||||
|
List list = null;
|
||||||
Collection coll = getCollection(ctx, istate.constantState);
|
Collection coll = getCollection(ctx, istate.constantState);
|
||||||
if (coll != null) {
|
if (coll != null) {
|
||||||
Collection ds = new ArrayList(coll.size());
|
list = new ArrayList(coll.size());
|
||||||
for (Iterator itr = coll.iterator(); itr.hasNext();)
|
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()));
|
itr.next()));
|
||||||
coll = ds;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Column[] cols = null;
|
Column[] cols = null;
|
||||||
|
@ -105,15 +106,46 @@ class InExpression
|
||||||
else if (_val instanceof GetObjectId)
|
else if (_val instanceof GetObjectId)
|
||||||
cols = ((GetObjectId) _val).getColumns(istate.valueState);
|
cols = ((GetObjectId) _val).getColumns(istate.valueState);
|
||||||
|
|
||||||
if (coll == null || coll.isEmpty())
|
if (list == null || list.isEmpty())
|
||||||
buf.append("1 <> 1");
|
buf.append("1 <> 1");
|
||||||
else if (_val.length(sel, ctx, istate.valueState) == 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
|
else
|
||||||
orContains(sel, ctx, istate.valueState, buf, coll, cols);
|
orContains(sel, ctx, istate.valueState, buf, list, cols);
|
||||||
sel.append(buf, state.joins);
|
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.
|
* Construct an IN clause with the value of the given collection.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -237,6 +237,7 @@ public class DBDictionary
|
||||||
public boolean useSetStringForClobs = false;
|
public boolean useSetStringForClobs = false;
|
||||||
public int maxEmbeddedBlobSize = -1;
|
public int maxEmbeddedBlobSize = -1;
|
||||||
public int maxEmbeddedClobSize = -1;
|
public int maxEmbeddedClobSize = -1;
|
||||||
|
public int inClauseLimit = -1;
|
||||||
public int datePrecision = MILLI;
|
public int datePrecision = MILLI;
|
||||||
public int characterColumnSize = 255;
|
public int characterColumnSize = 255;
|
||||||
public String arrayTypeName = "ARRAY";
|
public String arrayTypeName = "ARRAY";
|
||||||
|
|
|
@ -116,6 +116,7 @@ public class OracleDictionary
|
||||||
maxConstraintNameLength = 30;
|
maxConstraintNameLength = 30;
|
||||||
maxEmbeddedBlobSize = 4000;
|
maxEmbeddedBlobSize = 4000;
|
||||||
maxEmbeddedClobSize = 4000;
|
maxEmbeddedClobSize = 4000;
|
||||||
|
inClauseLimit = 1000;
|
||||||
|
|
||||||
supportsDeferredConstraints = true;
|
supportsDeferredConstraints = true;
|
||||||
supportsLockingWithDistinctClause = false;
|
supportsLockingWithDistinctClause = false;
|
||||||
|
|
Loading…
Reference in New Issue