mirror of https://github.com/apache/openjpa.git
Cleanup and fixes to changes for OPENJPA-168.
git-svn-id: https://svn.apache.org/repos/asf/incubator/openjpa/trunk@523425 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
3a5d06436c
commit
1679c05c89
|
@ -43,7 +43,6 @@ import org.apache.openjpa.jdbc.sql.SQLExceptions;
|
||||||
import org.apache.openjpa.jdbc.sql.SQLFactory;
|
import org.apache.openjpa.jdbc.sql.SQLFactory;
|
||||||
import org.apache.openjpa.jdbc.sql.Select;
|
import org.apache.openjpa.jdbc.sql.Select;
|
||||||
import org.apache.openjpa.jdbc.sql.SelectExecutor;
|
import org.apache.openjpa.jdbc.sql.SelectExecutor;
|
||||||
import org.apache.openjpa.jdbc.sql.SelectImpl;
|
|
||||||
import org.apache.openjpa.jdbc.sql.Union;
|
import org.apache.openjpa.jdbc.sql.Union;
|
||||||
import org.apache.openjpa.kernel.FetchConfiguration;
|
import org.apache.openjpa.kernel.FetchConfiguration;
|
||||||
import org.apache.openjpa.kernel.LockManager;
|
import org.apache.openjpa.kernel.LockManager;
|
||||||
|
@ -370,10 +369,7 @@ public class JDBCStoreManager
|
||||||
JDBCFetchConfiguration.EAGER_JOIN, true, false))
|
JDBCFetchConfiguration.EAGER_JOIN, true, false))
|
||||||
return null;
|
return null;
|
||||||
sel.wherePrimaryKey(sm.getObjectId(), mapping, this);
|
sel.wherePrimaryKey(sm.getObjectId(), mapping, this);
|
||||||
// Set the expectedResultCount for the select as 1 as a single
|
sel.setExpectedResultCount(1, false);
|
||||||
// object is being loaded. force = true is an indicator that it is
|
|
||||||
// internally generated value
|
|
||||||
sel.setExpectedResultCount(1,true);
|
|
||||||
return sel.execute(this, fetch);
|
return sel.execute(this, fetch);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -389,7 +385,7 @@ public class JDBCStoreManager
|
||||||
JDBCFetchConfiguration.EAGER_JOIN);
|
JDBCFetchConfiguration.EAGER_JOIN);
|
||||||
|
|
||||||
Union union = _sql.newUnion(mappings.length);
|
Union union = _sql.newUnion(mappings.length);
|
||||||
union.setExpectedResultCount(1,true);
|
union.setExpectedResultCount(1, false);
|
||||||
if (fetch.getSubclassFetchMode(mapping) != fetch.EAGER_JOIN)
|
if (fetch.getSubclassFetchMode(mapping) != fetch.EAGER_JOIN)
|
||||||
union.abortUnion();
|
union.abortUnion();
|
||||||
union.select(new Union.Selector() {
|
union.select(new Union.Selector() {
|
||||||
|
|
|
@ -310,32 +310,25 @@ public class JDBCStoreQuery
|
||||||
List selMappings, boolean subclasses, BitSet subclassBits,
|
List selMappings, boolean subclasses, BitSet subclassBits,
|
||||||
BitSet nextBits, ExpressionFactory[] facts, QueryExpressions[] exps,
|
BitSet nextBits, ExpressionFactory[] facts, QueryExpressions[] exps,
|
||||||
QueryExpressionsState[] states, ExpContext ctx, int subclassMode) {
|
QueryExpressionsState[] states, ExpContext ctx, int subclassMode) {
|
||||||
|
Number optHint = (Number) ctx.fetch.getHint
|
||||||
|
(QueryHints.HINT_RESULT_COUNT);
|
||||||
ClassMapping[] verts;
|
ClassMapping[] verts;
|
||||||
boolean unionable = true;
|
boolean unionable = true;
|
||||||
Select sel;
|
Select sel;
|
||||||
Object optHint = null;
|
|
||||||
for (int i = 0; i < mappings.length; i++) {
|
for (int i = 0; i < mappings.length; i++) {
|
||||||
// determine vertical mappings to select separately
|
// determine vertical mappings to select separately
|
||||||
verts = getVerticalMappings(mappings[i], subclasses, exps[i],
|
verts = getVerticalMappings(mappings[i], subclasses, exps[i],
|
||||||
subclassMode);
|
subclassMode);
|
||||||
if (verts.length == 1 && subclasses)
|
if (verts.length == 1 && subclasses)
|
||||||
subclassBits.set(sels.size());
|
subclassBits.set(sels.size());
|
||||||
|
|
||||||
// create criteria select and clone for each vert mapping
|
// create criteria select and clone for each vert mapping
|
||||||
sel = ((JDBCExpressionFactory) facts[i]).getSelectConstructor().
|
sel = ((JDBCExpressionFactory) facts[i]).getSelectConstructor().
|
||||||
evaluate(ctx, null, null, exps[i], states[i]);
|
evaluate(ctx, null, null, exps[i], states[i]);
|
||||||
// It means it is coming from getSingleResult so set the
|
if (optHint != null)
|
||||||
// expectedResultCount to 1.force = true indicates that this is
|
sel.setExpectedResultCount(optHint.intValue(), true);
|
||||||
// internally generated value
|
else if (this.ctx.isUnique())
|
||||||
if (this.ctx.isUnique())
|
sel.setExpectedResultCount(1, false);
|
||||||
sel.setExpectedResultCount(1,true);
|
|
||||||
// It means this is coming from getResultList so set the
|
|
||||||
// expectedResultCount based on any optimize hint if provided
|
|
||||||
else {
|
|
||||||
if ((optHint = ctx.fetch.getHint
|
|
||||||
(QueryHints.HINT_RESULT_COUNT))!= null)
|
|
||||||
sel.setExpectedResultCount
|
|
||||||
(((Integer)optHint).intValue(),false);
|
|
||||||
}
|
|
||||||
for (int j = 0; j < verts.length; j++) {
|
for (int j = 0; j < verts.length; j++) {
|
||||||
selMappings.add(verts[j]);
|
selMappings.add(verts[j]);
|
||||||
if (j == verts.length - 1) {
|
if (j == verts.length - 1) {
|
||||||
|
|
|
@ -236,9 +236,8 @@ class LRSProxyMap
|
||||||
final JDBCFetchConfiguration fetch = store.getFetchConfiguration();
|
final JDBCFetchConfiguration fetch = store.getFetchConfiguration();
|
||||||
final ClassMapping[] clss = _strat.getIndependentValueMappings(true);
|
final ClassMapping[] clss = _strat.getIndependentValueMappings(true);
|
||||||
final Joins[] resJoins = new Joins[Math.max(1, clss.length)];
|
final Joins[] resJoins = new Joins[Math.max(1, clss.length)];
|
||||||
Union union = store.getSQLFactory().newUnion
|
Union union = store.getSQLFactory().newUnion(Math.max(1, clss.length));
|
||||||
(Math.max(1, clss.length));
|
union.setExpectedResultCount(1, false);
|
||||||
union.setExpectedResultCount(1,true);
|
|
||||||
if (fetch.getSubclassFetchMode(_strat.getFieldMapping().
|
if (fetch.getSubclassFetchMode(_strat.getFieldMapping().
|
||||||
getElementMapping().getTypeMapping())
|
getElementMapping().getTypeMapping())
|
||||||
!= JDBCFetchConfiguration.EAGER_JOIN)
|
!= JDBCFetchConfiguration.EAGER_JOIN)
|
||||||
|
|
|
@ -578,7 +578,7 @@ public class RelationFieldStrategy
|
||||||
// back to our fk table if not an inverse mapping (in which case we
|
// back to our fk table if not an inverse mapping (in which case we
|
||||||
// can just make sure the inverse cols == our pk values)
|
// can just make sure the inverse cols == our pk values)
|
||||||
Union union = store.getSQLFactory().newUnion(rels.length);
|
Union union = store.getSQLFactory().newUnion(rels.length);
|
||||||
union.setExpectedResultCount(1,true);
|
union.setExpectedResultCount(1, false);
|
||||||
if (fetch.getSubclassFetchMode(field.getTypeMapping())
|
if (fetch.getSubclassFetchMode(field.getTypeMapping())
|
||||||
!= JDBCFetchConfiguration.EAGER_JOIN)
|
!= JDBCFetchConfiguration.EAGER_JOIN)
|
||||||
union.abortUnion();
|
union.abortUnion();
|
||||||
|
|
|
@ -28,9 +28,10 @@ import org.apache.openjpa.jdbc.schema.Sequence;
|
||||||
*/
|
*/
|
||||||
public class DB2Dictionary
|
public class DB2Dictionary
|
||||||
extends AbstractDB2Dictionary {
|
extends AbstractDB2Dictionary {
|
||||||
// variables to support optimize clause
|
|
||||||
public String optimizeClause = "optimize for";
|
public String optimizeClause = "optimize for";
|
||||||
public String rowClause = "row";
|
public String rowClause = "row";
|
||||||
|
|
||||||
public DB2Dictionary() {
|
public DB2Dictionary() {
|
||||||
platform = "DB2";
|
platform = "DB2";
|
||||||
validationSQL = "SELECT DISTINCT(CURRENT TIMESTAMP) FROM "
|
validationSQL = "SELECT DISTINCT(CURRENT TIMESTAMP) FROM "
|
||||||
|
@ -197,60 +198,13 @@ public class DB2Dictionary
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Based on the expectedResultCount of the select create the optimize
|
|
||||||
* for clause
|
|
||||||
*/
|
|
||||||
public String getOptimizeClause(JDBCFetchConfiguration fetch,
|
|
||||||
int expectedResultCount) {
|
|
||||||
Integer rows = null;
|
|
||||||
StringBuffer optimizeString = new StringBuffer();
|
|
||||||
if (expectedResultCount != 0)
|
|
||||||
optimizeString.append(" ").append(optimizeClause).append(" ")
|
|
||||||
.append(expectedResultCount).append(" ")
|
|
||||||
.append(rowClause).append(" ");
|
|
||||||
return optimizeString.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Override the DBDictionary toSelect to call getOptimizeClause and append
|
|
||||||
* to the select string
|
|
||||||
*/
|
|
||||||
public SQLBuffer toSelect(SQLBuffer selects, JDBCFetchConfiguration fetch,
|
|
||||||
SQLBuffer from, SQLBuffer where, SQLBuffer group,
|
|
||||||
SQLBuffer having, SQLBuffer order,
|
|
||||||
boolean distinct, boolean forUpdate, long start, long end,
|
|
||||||
int expectedResultCount) {
|
|
||||||
String optimizeString = null;
|
|
||||||
SQLBuffer selString = toOperation(getSelectOperation(fetch),
|
|
||||||
selects, from, where,
|
|
||||||
group, having, order, distinct,
|
|
||||||
forUpdate, start, end);
|
|
||||||
if (fetch != null)
|
|
||||||
optimizeString = getOptimizeClause(fetch, expectedResultCount);
|
|
||||||
if (optimizeString != null && optimizeString.length() > 0)
|
|
||||||
selString.append(optimizeString);
|
|
||||||
return selString;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Override the DBDictionary toSelect to pass expectedResultcount to the
|
|
||||||
* other toSelect method
|
|
||||||
*/
|
|
||||||
public SQLBuffer toSelect(Select sel, boolean forUpdate,
|
public SQLBuffer toSelect(Select sel, boolean forUpdate,
|
||||||
JDBCFetchConfiguration fetch) {
|
JDBCFetchConfiguration fetch) {
|
||||||
sel.addJoinClassConditions();
|
SQLBuffer buf = super.toSelect(sel, forUpdate, fetch);
|
||||||
boolean update = forUpdate && sel.getFromSelect() == null;
|
if (sel.getExpectedResultCount() > 0)
|
||||||
SQLBuffer select = getSelects(sel, false, update);
|
buf.append(" ").append(optimizeClause).append(" ").
|
||||||
SQLBuffer ordering = null;
|
append(String.valueOf(sel.getExpectedResultCount())).
|
||||||
if (!sel.isAggregate() || sel.getGrouping() != null)
|
append(" ").append(rowClause);
|
||||||
ordering = sel.getOrdering();
|
return buf;
|
||||||
SQLBuffer from;
|
|
||||||
if (sel.getFromSelect() != null)
|
|
||||||
from = getFromSelect(sel, forUpdate);
|
|
||||||
else
|
|
||||||
from = getFrom(sel, update);
|
|
||||||
SQLBuffer where = getWhere(sel, update);
|
|
||||||
return toSelect(select, fetch, from, where, sel.getGrouping(),
|
|
||||||
sel.getHaving(), ordering, sel.isDistinct(), forUpdate,
|
|
||||||
sel.getStartIndex(),
|
|
||||||
sel.getEndIndex(),sel.getExpectedResultCount());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -47,8 +47,7 @@ public class LogicalUnion
|
||||||
|
|
||||||
private static final Localizer _loc = Localizer.forPackage
|
private static final Localizer _loc = Localizer.forPackage
|
||||||
(LogicalUnion.class);
|
(LogicalUnion.class);
|
||||||
protected int expectedResultCount = 0;
|
|
||||||
protected boolean force = false;
|
|
||||||
protected final UnionSelect[] sels;
|
protected final UnionSelect[] sels;
|
||||||
protected final DBDictionary dict;
|
protected final DBDictionary dict;
|
||||||
protected final ClassMapping[] mappings;
|
protected final ClassMapping[] mappings;
|
||||||
|
@ -157,6 +156,16 @@ public class LogicalUnion
|
||||||
sels[i].setLRS(lrs);
|
sels[i].setLRS(lrs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int getExpectedResultCount() {
|
||||||
|
return sels[0].getExpectedResultCount();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setExpectedResultCount(int expectedResultCount,
|
||||||
|
boolean force) {
|
||||||
|
for (int i = 0; i < sels.length; i++)
|
||||||
|
sels[i].setExpectedResultCount(expectedResultCount, force);
|
||||||
|
}
|
||||||
|
|
||||||
public int getJoinSyntax() {
|
public int getJoinSyntax() {
|
||||||
return sels[0].getJoinSyntax();
|
return sels[0].getJoinSyntax();
|
||||||
}
|
}
|
||||||
|
@ -208,13 +217,9 @@ public class LogicalUnion
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.getExpectedResultCount()== 1) {
|
if (getExpectedResultCount() == 1) {
|
||||||
AbstractResult res;
|
AbstractResult res;
|
||||||
for (int i = 0; i < sels.length; i++) {
|
for (int i = 0; i < sels.length; i++) {
|
||||||
// For each select set the expected result count to 1
|
|
||||||
// and force true indicating that this internally generated
|
|
||||||
// value
|
|
||||||
sels[i].sel.setExpectedResultCount(1,true);
|
|
||||||
res = (AbstractResult) sels[i].execute(store, fetch,
|
res = (AbstractResult) sels[i].execute(store, fetch,
|
||||||
lockLevel);
|
lockLevel);
|
||||||
res.setBaseMapping(mappings[i]);
|
res.setBaseMapping(mappings[i]);
|
||||||
|
@ -302,8 +307,6 @@ public class LogicalUnion
|
||||||
protected final int pos;
|
protected final int pos;
|
||||||
protected int orders = 0;
|
protected int orders = 0;
|
||||||
protected List orderIdxs = null;
|
protected List orderIdxs = null;
|
||||||
protected int expectedResultCount = 0;
|
|
||||||
protected boolean force = false;
|
|
||||||
|
|
||||||
public UnionSelect(SelectImpl sel, int pos) {
|
public UnionSelect(SelectImpl sel, int pos) {
|
||||||
this.sel = sel;
|
this.sel = sel;
|
||||||
|
@ -839,17 +842,12 @@ public class LogicalUnion
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getExpectedResultCount() {
|
public int getExpectedResultCount() {
|
||||||
return expectedResultCount;
|
return sel.getExpectedResultCount();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setExpectedResultCount(int expectedResultCount,
|
public void setExpectedResultCount(int expectedResultCount,
|
||||||
boolean force) {
|
boolean force) {
|
||||||
this.expectedResultCount = expectedResultCount;
|
sel.setExpectedResultCount(expectedResultCount, force);
|
||||||
this.force = force;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isExpRsltCntForced() {
|
|
||||||
return force;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -931,18 +929,4 @@ public class LogicalUnion
|
||||||
return a1.length - a2.length;
|
return a1.length - a2.length;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getExpectedResultCount() {
|
|
||||||
return expectedResultCount;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setExpectedResultCount(int expectedResultCount,
|
|
||||||
boolean force) {
|
|
||||||
this.expectedResultCount = expectedResultCount;
|
|
||||||
this.force = force;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isExpRsltCntForced() {
|
|
||||||
return force;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -79,6 +79,19 @@ public interface SelectExecutor {
|
||||||
*/
|
*/
|
||||||
public void setLRS(boolean lrs);
|
public void setLRS(boolean lrs);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The expected result count for the query.
|
||||||
|
*/
|
||||||
|
public int getExpectedResultCount();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The expected result count for the query.
|
||||||
|
*
|
||||||
|
* @param force if false, the count will be discarded if this select has
|
||||||
|
* any to-many eager joins that would throw off the result count
|
||||||
|
*/
|
||||||
|
public void setExpectedResultCount(int expectedResultCount, boolean force);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The join syntax for this select, as one of the syntax constants from
|
* The join syntax for this select, as one of the syntax constants from
|
||||||
* {@link JoinSyntaxes}.
|
* {@link JoinSyntaxes}.
|
||||||
|
@ -119,21 +132,4 @@ public interface SelectExecutor {
|
||||||
public Result execute(JDBCStore store, JDBCFetchConfiguration fetch,
|
public Result execute(JDBCStore store, JDBCFetchConfiguration fetch,
|
||||||
int lockLevel)
|
int lockLevel)
|
||||||
throws SQLException;
|
throws SQLException;
|
||||||
|
|
||||||
/**
|
|
||||||
* Return the expected result count for the query
|
|
||||||
*/
|
|
||||||
public int getExpectedResultCount() ;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the expected result count for the query
|
|
||||||
* force indicates whether the count is internally generated
|
|
||||||
* or given by the user as optimize hint
|
|
||||||
*/
|
|
||||||
public void setExpectedResultCount(int expectedResultCount,boolean force) ;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Indicates whether the expectedResultCount is internally generated
|
|
||||||
*/
|
|
||||||
public boolean isExpRsltCntForced();
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -82,6 +82,7 @@ public class SelectImpl
|
||||||
private static final int EAGER_TO_MANY = 2 << 10;
|
private static final int EAGER_TO_MANY = 2 << 10;
|
||||||
private static final int RECORD_ORDERED = 2 << 11;
|
private static final int RECORD_ORDERED = 2 << 11;
|
||||||
private static final int GROUPING = 2 << 12;
|
private static final int GROUPING = 2 << 12;
|
||||||
|
private static final int FORCE_COUNT = 2 << 13;
|
||||||
|
|
||||||
private static final String[] TABLE_ALIASES = new String[16];
|
private static final String[] TABLE_ALIASES = new String[16];
|
||||||
private static final String[] ORDER_ALIASES = new String[16];
|
private static final String[] ORDER_ALIASES = new String[16];
|
||||||
|
@ -128,6 +129,7 @@ public class SelectImpl
|
||||||
private int _nullIds = 0;
|
private int _nullIds = 0;
|
||||||
private int _orders = 0;
|
private int _orders = 0;
|
||||||
private int _placeholders = 0;
|
private int _placeholders = 0;
|
||||||
|
private int _expectedResultCount = 0;
|
||||||
|
|
||||||
// query clauses
|
// query clauses
|
||||||
private SQLBuffer _ordering = null;
|
private SQLBuffer _ordering = null;
|
||||||
|
@ -154,9 +156,6 @@ public class SelectImpl
|
||||||
private SelectImpl _from = null;
|
private SelectImpl _from = null;
|
||||||
private SelectImpl _outer = null;
|
private SelectImpl _outer = null;
|
||||||
|
|
||||||
private int expectedResultCount = 0;
|
|
||||||
private boolean force = false;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Helper method to return the proper table alias for the given alias index.
|
* Helper method to return the proper table alias for the given alias index.
|
||||||
*/
|
*/
|
||||||
|
@ -245,6 +244,22 @@ public class SelectImpl
|
||||||
_flags &= ~LRS;
|
_flags &= ~LRS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int getExpectedResultCount() {
|
||||||
|
// if the count isn't forced and we have to-many eager joins that could
|
||||||
|
// throw the count off, don't pay attention to it
|
||||||
|
if ((_flags & FORCE_COUNT) == 0 && hasEagerJoin(true))
|
||||||
|
return 0;
|
||||||
|
return _expectedResultCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setExpectedResultCount(int expectedResultCount, boolean force) {
|
||||||
|
_expectedResultCount = expectedResultCount;
|
||||||
|
if (force)
|
||||||
|
_flags |= FORCE_COUNT;
|
||||||
|
else
|
||||||
|
_flags &= ~FORCE_COUNT;
|
||||||
|
}
|
||||||
|
|
||||||
public int getJoinSyntax() {
|
public int getJoinSyntax() {
|
||||||
return _joinSyntax;
|
return _joinSyntax;
|
||||||
}
|
}
|
||||||
|
@ -307,20 +322,6 @@ public class SelectImpl
|
||||||
JDBCFetchConfiguration fetch, int lockLevel)
|
JDBCFetchConfiguration fetch, int lockLevel)
|
||||||
throws SQLException {
|
throws SQLException {
|
||||||
boolean forUpdate = false;
|
boolean forUpdate = false;
|
||||||
|
|
||||||
// ExpectedResultCount = 1 and force means that it is internally
|
|
||||||
// generated value for getSingleResult,single valued relationship.
|
|
||||||
// We need to check if there are any eager joins in the select if
|
|
||||||
// there are then the optimize for 1 row clause is not generated
|
|
||||||
// else we do. if !force then it is set by the user through hint
|
|
||||||
// and we do not check the eager joins
|
|
||||||
if (this.expectedResultCount == 1 && force ) {
|
|
||||||
if (this.hasEagerJoin(true))
|
|
||||||
this.setExpectedResultCount(0,false);
|
|
||||||
else
|
|
||||||
this.setExpectedResultCount(1,false);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!isAggregate() && _grouping == null) {
|
if (!isAggregate() && _grouping == null) {
|
||||||
JDBCLockManager lm = store.getLockManager();
|
JDBCLockManager lm = store.getLockManager();
|
||||||
if (lm != null)
|
if (lm != null)
|
||||||
|
@ -1503,6 +1504,7 @@ public class SelectImpl
|
||||||
sel._flags &= ~LRS;
|
sel._flags &= ~LRS;
|
||||||
sel._flags &= ~EAGER_TO_ONE;
|
sel._flags &= ~EAGER_TO_ONE;
|
||||||
sel._flags &= ~EAGER_TO_MANY;
|
sel._flags &= ~EAGER_TO_MANY;
|
||||||
|
sel._flags &= ~FORCE_COUNT;
|
||||||
sel._joinSyntax = _joinSyntax;
|
sel._joinSyntax = _joinSyntax;
|
||||||
if (_aliases != null)
|
if (_aliases != null)
|
||||||
sel._aliases = new HashMap(_aliases);
|
sel._aliases = new HashMap(_aliases);
|
||||||
|
@ -1548,6 +1550,7 @@ public class SelectImpl
|
||||||
for (int i = 0; i < sels; i++) {
|
for (int i = 0; i < sels; i++) {
|
||||||
sel = (SelectImpl) whereClone(1);
|
sel = (SelectImpl) whereClone(1);
|
||||||
sel._flags = _flags;
|
sel._flags = _flags;
|
||||||
|
sel._expectedResultCount = _expectedResultCount;
|
||||||
sel._selects.addAll(_selects);
|
sel._selects.addAll(_selects);
|
||||||
if (_ordering != null)
|
if (_ordering != null)
|
||||||
sel._ordering = new SQLBuffer(_ordering);
|
sel._ordering = new SQLBuffer(_ordering);
|
||||||
|
@ -2816,20 +2819,6 @@ public class SelectImpl
|
||||||
_idents = null;
|
_idents = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getExpectedResultCount() {
|
|
||||||
return expectedResultCount;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setExpectedResultCount(int expectedResultCount,
|
|
||||||
boolean force) {
|
|
||||||
this.expectedResultCount = expectedResultCount;
|
|
||||||
this.force = force;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isExpRsltCntForced() {
|
|
||||||
return force;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -15,10 +15,13 @@
|
||||||
*/
|
*/
|
||||||
package org.apache.openjpa.kernel;
|
package org.apache.openjpa.kernel;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Standard query hint keys.
|
||||||
|
*/
|
||||||
public interface QueryHints {
|
public interface QueryHints {
|
||||||
|
|
||||||
/** Hint to specify the number of rows for the optimize
|
/**
|
||||||
* clause for DB2
|
* Hint to specify the number of rows to optimize for.
|
||||||
*/
|
*/
|
||||||
public static final String HINT_RESULT_COUNT =
|
public static final String HINT_RESULT_COUNT =
|
||||||
"openjpa.hint.OptimizeResultCount";
|
"openjpa.hint.OptimizeResultCount";
|
||||||
|
|
|
@ -1273,14 +1273,17 @@ public class QueryImpl
|
||||||
boolean next = rop.next();
|
boolean next = rop.next();
|
||||||
|
|
||||||
// extract single result; throw an exception if multiple results
|
// extract single result; throw an exception if multiple results
|
||||||
// match and not constrainted by range, as per spec
|
// match and not constrainted by range, or if a unique query with
|
||||||
|
// no results
|
||||||
Object single = null;
|
Object single = null;
|
||||||
if (next) {
|
if (next) {
|
||||||
single = rop.getResultObject();
|
single = rop.getResultObject();
|
||||||
if (range.end != range.start + 1 && rop.next())
|
if (range.end != range.start + 1 && rop.next())
|
||||||
throw new InvalidStateException(_loc.get("not-unique",
|
throw new InvalidStateException(_loc.get("not-unique",
|
||||||
_class, _query));
|
_class, _query));
|
||||||
}
|
} else if (_unique == Boolean.TRUE)
|
||||||
|
throw new InvalidStateException(_loc.get("no-result",
|
||||||
|
_class, _query));
|
||||||
|
|
||||||
// if unique set to false, use collection
|
// if unique set to false, use collection
|
||||||
if (_unique == Boolean.FALSE) {
|
if (_unique == Boolean.FALSE) {
|
||||||
|
@ -1290,10 +1293,6 @@ public class QueryImpl
|
||||||
return Arrays.asList(new Object[]{ single });
|
return Arrays.asList(new Object[]{ single });
|
||||||
}
|
}
|
||||||
|
|
||||||
if (single == null)
|
|
||||||
throw new InvalidStateException(_loc.get("is-null",
|
|
||||||
_class, _query));
|
|
||||||
|
|
||||||
// return single result
|
// return single result
|
||||||
return single;
|
return single;
|
||||||
} finally {
|
} finally {
|
||||||
|
|
|
@ -259,7 +259,7 @@ executing-query-with-params: Executing query: [{0}] with parameters: {1}
|
||||||
not-unique: The query on candidate type "{0}" with filter "{1}" was \
|
not-unique: The query on candidate type "{0}" with filter "{1}" was \
|
||||||
configured to have a unique result, but more than one instance matched \
|
configured to have a unique result, but more than one instance matched \
|
||||||
the query.
|
the query.
|
||||||
is-null: The query on candidate type "{0}" with filter "{1}" was \
|
no-result: The query on candidate type "{0}" with filter "{1}" was \
|
||||||
configured to have a unique result, but no instance matched \
|
configured to have a unique result, but no instance matched \
|
||||||
the query.
|
the query.
|
||||||
serialized: Queries that have been serialized do not support this operation.
|
serialized: Queries that have been serialized do not support this operation.
|
||||||
|
|
|
@ -279,12 +279,12 @@ public class QueryImpl
|
||||||
*/
|
*/
|
||||||
public Object getSingleResult() {
|
public Object getSingleResult() {
|
||||||
_em.assertNotCloseInvoked();
|
_em.assertNotCloseInvoked();
|
||||||
// Indicate that this query returns single result.Later copied into
|
// temporarily set query to unique so that a single result is validated
|
||||||
// select.expectedResultCount
|
// and returned; unset again in case the user executes query again
|
||||||
|
// via getResultList
|
||||||
_query.setUnique(true);
|
_query.setUnique(true);
|
||||||
try {
|
try {
|
||||||
Object ob = execute();
|
return execute();
|
||||||
return ob;
|
|
||||||
} finally {
|
} finally {
|
||||||
_query.setUnique(false);
|
_query.setUnique(false);
|
||||||
}
|
}
|
||||||
|
@ -367,16 +367,17 @@ public class QueryImpl
|
||||||
Filters.hintToSetter(getFetchPlan(), k, value);
|
Filters.hintToSetter(getFetchPlan(), k, value);
|
||||||
} else if (k.startsWith("hint.")) {
|
} else if (k.startsWith("hint.")) {
|
||||||
if ("hint.OptimizeResultCount".equals(k)) {
|
if ("hint.OptimizeResultCount".equals(k)) {
|
||||||
if ((!(value instanceof String)&&! (value instanceof Integer))
|
if (value instanceof String) {
|
||||||
|| (value instanceof String &&(Integer.parseInt
|
try {
|
||||||
((String)value)< 0))||
|
value = new Integer((String) value);
|
||||||
((value instanceof Integer)
|
} catch (NumberFormatException nfe) {
|
||||||
&& (((Integer)value).intValue()<0)))
|
}
|
||||||
|
}
|
||||||
|
if (!(value instanceof Number)
|
||||||
|
|| ((Number) value).intValue() < 0)
|
||||||
throw new ArgumentException(_loc.get
|
throw new ArgumentException(_loc.get
|
||||||
("bad-hint-value", key),
|
("bad-query-hint-value", key, value), null, null,
|
||||||
null, null, false);
|
false);
|
||||||
if (value instanceof String)
|
|
||||||
value = new Integer((String)value);
|
|
||||||
}
|
}
|
||||||
_query.getFetchConfiguration().setHint(key, value);
|
_query.getFetchConfiguration().setHint(key, value);
|
||||||
}
|
}
|
||||||
|
@ -384,12 +385,7 @@ public class QueryImpl
|
||||||
throw new ArgumentException(_loc.get("bad-query-hint", key),
|
throw new ArgumentException(_loc.get("bad-query-hint", key),
|
||||||
null, null, false);
|
null, null, false);
|
||||||
return this;
|
return this;
|
||||||
}
|
} catch (Exception e) {
|
||||||
catch (NumberFormatException e1) {
|
|
||||||
throw new ArgumentException(_loc.get("bad-hint-value", key),
|
|
||||||
null, null, false);
|
|
||||||
}
|
|
||||||
catch (Exception e) {
|
|
||||||
throw PersistenceExceptions.toPersistenceException(e);
|
throw PersistenceExceptions.toPersistenceException(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -64,6 +64,7 @@ mult-results: Query returned multiple results: "{0}".
|
||||||
no-pos-named-params-mix: Cannot mix named and positional parameters in query \
|
no-pos-named-params-mix: Cannot mix named and positional parameters in query \
|
||||||
"{0}".
|
"{0}".
|
||||||
bad-query-hint: "{0}" is not a recognized query hint.
|
bad-query-hint: "{0}" is not a recognized query hint.
|
||||||
|
bad-query-hint-value: Invalid value specified for query hint "{0}": {1}
|
||||||
detached: Cannot perform this operation on detached entity "{0}".
|
detached: Cannot perform this operation on detached entity "{0}".
|
||||||
removed: Cannot perform this operation on removed entity "{0}".
|
removed: Cannot perform this operation on removed entity "{0}".
|
||||||
bad-alias: There is no known entity class for entity name "{0}". It is \
|
bad-alias: There is no known entity class for entity name "{0}". It is \
|
||||||
|
|
Loading…
Reference in New Issue