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;
+        }
+        
+    }
 }


Reply via email to