openjpa-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From awh...@apache.org
Subject svn commit: r443519 - in /incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps: PCPath.java SelectConstructor.java
Date Thu, 14 Sep 2006 23:41:31 GMT
Author: awhite
Date: Thu Sep 14 16:41:30 2006
New Revision: 443519

URL: http://svn.apache.org/viewvc?view=rev&rev=443519
Log:
Don't use a subselect for non-distinct projections of DISTINCT_AUTO queries 
with to-many joins in their filter if the projections are all for variable 
paths.  (As opposed to candidate path projections, where the subselect is 
necessary to filter out duplicates caused by relational joins).


Modified:
    incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/PCPath.java
    incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/SelectConstructor.java

Modified: incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/PCPath.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/PCPath.java?view=diff&rev=443519&r1=443518&r2=443519
==============================================================================
--- incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/PCPath.java
(original)
+++ incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/PCPath.java
Thu Sep 14 16:41:30 2006
@@ -130,6 +130,13 @@
     }
 
     /**
+     * Return whether this is a path involving a variable.
+     */
+    public boolean isVariablePath() {
+        return _type != PATH;
+    }
+
+    /**
      * If this path is part of a contains clause, then alias it to the
      * proper contains id before initialization.
      */

Modified: incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/SelectConstructor.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/SelectConstructor.java?view=diff&rev=443519&r1=443518&r2=443519
==============================================================================
--- incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/SelectConstructor.java
(original)
+++ incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/SelectConstructor.java
Thu Sep 14 16:41:30 2006
@@ -25,8 +25,11 @@
 import org.apache.openjpa.jdbc.sql.Joins;
 import org.apache.openjpa.jdbc.sql.SQLBuffer;
 import org.apache.openjpa.jdbc.sql.Select;
+import org.apache.openjpa.kernel.exps.AbstractExpressionVisitor;
+import org.apache.openjpa.kernel.exps.Constant;
 import org.apache.openjpa.kernel.exps.Expression;
 import org.apache.openjpa.kernel.exps.QueryExpressions;
+import org.apache.openjpa.kernel.exps.Value;
 
 /**
  * Turns parsed queries into selects.
@@ -120,8 +123,7 @@
             else if ((exps.distinct & exps.DISTINCT_FALSE) != 0)
                 sel.setDistinct(false);
         } else if (exps.projections.length > 0) {
-            if (!sel.isDistinct() && (exps.distinct & exps.DISTINCT_TRUE) !=
0)
-            {
+            if (!sel.isDistinct() && (exps.distinct & exps.DISTINCT_TRUE) !=
0){
                 // if the select is not distinct but the query is, force
                 // the select to be distinct
                 sel.setDistinct(true);
@@ -133,8 +135,11 @@
                 // get unique candidate values) and needed field values and
                 // applies the where conditions; the outer select applies
                 // ordering, grouping, etc
-                if (exps.isAggregate() 
-                    || (exps.distinct & exps.DISTINCT_TRUE) == 0) {
+                boolean agg = exps.isAggregate();
+                boolean candidate = ProjectionExpressionVisitor.
+                    hasCandidateProjections(exps.projections);
+                if (agg || (candidate 
+                    && (exps.distinct & exps.DISTINCT_TRUE) == 0)) {
                     DBDictionary dict = ctx.store.getDBDictionary();
                     dict.assertSupport(dict.supportsSubselect,
                         "SupportsSubselect");
@@ -142,10 +147,16 @@
                     Select inner = sel;
                     sel = ctx.store.getSQLFactory().newSelect();
                     sel.setParent(parent, alias);
-                    sel.setDistinct(exps.isAggregate()
+                    sel.setDistinct(agg
                         && (exps.distinct & exps.DISTINCT_TRUE) != 0);
                     sel.setFromSelect(inner);
-                }
+
+                // auto-distincting happens to get unique candidate instances
+                // back; don't auto-distinct if the user isn't selecting 
+                // candidate data
+                } else if (!candidate 
+                    && (exps.distinct & exps.DISTINCT_TRUE) == 0) 
+                    sel.setDistinct(false);
             }
         }
         return sel;
@@ -293,6 +304,39 @@
             ctx.store.loadSubclasses(mapping);
             mapping.getDiscriminator().addClassConditions((inner != null) 
                 ? inner : sel, subclasses, joins);
+        }
+    }
+
+    /**
+     * Used to check whether a query's result projections are on the candidate.
+     */
+    private static class ProjectionExpressionVisitor
+        extends AbstractExpressionVisitor {
+
+        private boolean _candidate = false;
+        private int _level = 0;
+
+        public static boolean hasCandidateProjections(Value[] projs) {
+            ProjectionExpressionVisitor v = new ProjectionExpressionVisitor();
+            for (int i = 0; i < projs.length; i++) {
+                projs[i].acceptVisit(v);
+                if (v._candidate)
+                    return true;
+            }
+            return false;
+        }
+
+        public void enter(Value val) {
+            if (!_candidate) {
+                _candidate = (_level == 0 && val instanceof Constant)
+                    || (val instanceof PCPath 
+                    && !((PCPath) val).isVariablePath());
+            }
+            _level++;
+        }
+
+        public void exit(Value val) {
+            _level--;
         }
     }
 }



Mime
View raw message