Author: ppoddar
Date: Mon Mar 15 21:07:14 2010
New Revision: 923441
URL: http://svn.apache.org/viewvc?rev=923441&view=rev
Log:
OPENJPA-1575: Detect parametrized fields in a query expression to exclude
queries from cache that use parameters for externized fields.
Modified:
openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/PreparedQueryImpl.java
openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/QueryImpl.java
openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/QueryExpressions.java
Modified:
openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/PreparedQueryImpl.java
URL:
http://svn.apache.org/viewvc/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/PreparedQueryImpl.java?rev=923441&r1=923440&r2=923441&view=diff
==============================================================================
---
openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/PreparedQueryImpl.java
(original)
+++
openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/PreparedQueryImpl.java
Mon Mar 15 21:07:14 2010
@@ -45,6 +45,7 @@ import org.apache.openjpa.kernel.exps.Qu
import org.apache.openjpa.lib.rop.RangeResultObjectProvider;
import org.apache.openjpa.lib.rop.ResultList;
import org.apache.openjpa.lib.util.Localizer;
+import org.apache.openjpa.meta.FieldMetaData;
import org.apache.openjpa.util.ImplHelper;
import org.apache.openjpa.util.InternalException;
import org.apache.openjpa.util.UserException;
@@ -202,6 +203,11 @@ public class PreparedQueryImpl implement
if (executor instanceof StoreQuery.Executor == false)
return new Object[]{null, _loc.get("exclude-not-executor")};
_exps = ((StoreQuery.Executor)executor).getQueryExpressions();
+ for (int i = 0; i < _exps.length; i++) {
+ if (isUsingExternalizedParameter(_exps[i])) {
+ return new Object[]{null,
_loc.get("exclude-externalized-param", provider.getClass().getName())};
+ }
+ }
if (_exps[0].projections.length == 0) {
_projTypes = StoreQuery.EMPTY_CLASSES;
} else {
@@ -235,6 +241,20 @@ public class PreparedQueryImpl implement
return null;
}
+ private boolean isUsingExternalizedParameter(QueryExpressions exp) {
+ if (exp == null)
+ return false;
+ List<FieldMetaData> fmds = exp.getParameterizedFields();
+ if (fmds == null || fmds.isEmpty())
+ return false;
+ for (FieldMetaData fmd : fmds) {
+ if (fmd.isExternalized())
+ return true;
+ }
+ return false;
+ }
+
+
/**
* Merge the given user parameters with its own parameter. The given map
* must be compatible with the user parameters extracted during
Modified:
openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/QueryImpl.java
URL:
http://svn.apache.org/viewvc/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/QueryImpl.java?rev=923441&r1=923440&r2=923441&view=diff
==============================================================================
---
openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/QueryImpl.java
(original)
+++
openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/QueryImpl.java
Mon Mar 15 21:07:14 2010
@@ -45,6 +45,7 @@ import org.apache.openjpa.kernel.exps.Qu
import org.apache.openjpa.kernel.exps.Val;
import org.apache.openjpa.lib.log.Log;
import org.apache.openjpa.lib.rop.EagerResultList;
+import org.apache.openjpa.lib.rop.ListResultList;
import org.apache.openjpa.lib.rop.MergedResultObjectProvider;
import org.apache.openjpa.lib.rop.RangeResultObjectProvider;
import org.apache.openjpa.lib.rop.ResultList;
@@ -1240,10 +1241,17 @@ public class QueryImpl
boolean detach = (_broker.getAutoDetach() &
AutoDetach.DETACH_NONTXREAD) > 0 && !_broker.isActive();
boolean lrs = range.lrs && !ex.isAggregate(q) && !ex.hasGrouping(q);
- ResultList<?> res = (!detach && lrs) ? _fc.newResultList(rop)
- : new EagerResultList(rop);
- res.setUserObject(new Object[]{rop,ex});
- _resultLists.add(decorateResultList(res));
+ ResultList<?> res = new ListResultList(Collections.emptyList());
+ try {
+ res = (!detach && lrs) ? _fc.newResultList(rop) : new
EagerResultList(rop);
+ res.setUserObject(new Object[]{rop,ex});
+ _resultLists.add(decorateResultList(res));
+ } catch (OpenJPAException e) {
+ if (e.getFailedObject() == null) {
+ e.setFailedObject(getQueryString());
+ }
+ throw e;
+ }
return res;
}
@@ -1758,7 +1766,7 @@ public class QueryImpl
for (Object expected : paramTypes.keySet()) {
if (!params.containsKey(expected))
throw new UserException(_loc.get("unbound-params",
- expected, params.keySet()));
+ expected, paramTypes.keySet()));
}
Iterator<Map.Entry<Object, Class<?>>> itr =
paramTypes.entrySet().iterator();
Modified:
openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/QueryExpressions.java
URL:
http://svn.apache.org/viewvc/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/QueryExpressions.java?rev=923441&r1=923440&r2=923441&view=diff
==============================================================================
---
openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/QueryExpressions.java
(original)
+++
openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/QueryExpressions.java
Mon Mar 15 21:07:14 2010
@@ -19,12 +19,13 @@
package org.apache.openjpa.kernel.exps;
import java.io.Serializable;
+import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedHashMap;
+import java.util.List;
import java.util.Map;
import java.util.Stack;
-import org.apache.commons.collections.map.LinkedMap;
import org.apache.openjpa.kernel.QueryOperations;
import org.apache.openjpa.kernel.ResultShape;
import org.apache.openjpa.kernel.StoreQuery;
@@ -48,7 +49,7 @@ public class QueryExpressions
public static final int DISTINCT_TRUE = 2 << 1;
public static final int DISTINCT_FALSE = 2 << 2;
public static final Value[] EMPTY_VALUES = new Value[0];
-
+
/**
* Map of {...@link FieldMetaData},{...@link Value} for update statements.
*/
@@ -109,6 +110,15 @@ public class QueryExpressions
public boolean isDistinct() {
return distinct != DISTINCT_FALSE;
}
+
+ /**
+ * Gets the fields that are bound to parameters.
+ *
+ * @return empty if the query has no filtering condition or no parameters.
+ */
+ public List<FieldMetaData> getParameterizedFields() {
+ return ParameterExpressionVisitor.collectParameterizedFields(filter);
+ }
/**
* Add an update.
@@ -155,4 +165,38 @@ public class QueryExpressions
_sub = null;
}
}
+
+ /**
+ * Visits the expression tree to find the parameter nodes.
+ * @author Pinaki Poddar
+ *
+ */
+ private static class ParameterExpressionVisitor extends
AbstractExpressionVisitor {
+ private FieldMetaData _parameterized;
+ private List<FieldMetaData> _collected = new
ArrayList<FieldMetaData>();
+ /**
+ * Enters the current node.
+ */
+ public void enter(Value val) {
+ if (val instanceof Parameter) {
+ if (_parameterized != null) {
+ _collected.add(_parameterized);
+ }
+ } else if (val instanceof Path) {
+ _parameterized = ((Path)val).last();
+ } else {
+ _parameterized = null;
+ }
+ }
+
+ public static List<FieldMetaData>
collectParameterizedFields(Expression e) {
+ if (e == null) {
+ return Collections.emptyList();
+ }
+ ParameterExpressionVisitor visitor = new
ParameterExpressionVisitor();
+ e.acceptVisit(visitor);
+ return visitor._collected;
+ }
+
+ }
}