You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@openjpa.apache.org by aw...@apache.org on 2007/03/28 19:43:36 UTC

svn commit: r523425 - in /incubator/openjpa/trunk: openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/ openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/ openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/ openjpa-kernel/src/mai...

Author: awhite
Date: Wed Mar 28 10:43:35 2007
New Revision: 523425

URL: http://svn.apache.org/viewvc?view=rev&rev=523425
Log:
Cleanup and fixes to changes for OPENJPA-168.


Modified:
    incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/JDBCStoreManager.java
    incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/JDBCStoreQuery.java
    incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/LRSProxyMap.java
    incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/RelationFieldStrategy.java
    incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/DB2Dictionary.java
    incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/LogicalUnion.java
    incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/SelectExecutor.java
    incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/SelectImpl.java
    incubator/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/QueryHints.java   (contents, props changed)
    incubator/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/QueryImpl.java
    incubator/openjpa/trunk/openjpa-kernel/src/main/resources/org/apache/openjpa/kernel/localizer.properties
    incubator/openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/QueryImpl.java
    incubator/openjpa/trunk/openjpa-persistence/src/main/resources/org/apache/openjpa/persistence/localizer.properties

Modified: incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/JDBCStoreManager.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/JDBCStoreManager.java?view=diff&rev=523425&r1=523424&r2=523425
==============================================================================
--- incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/JDBCStoreManager.java (original)
+++ incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/JDBCStoreManager.java Wed Mar 28 10:43:35 2007
@@ -43,7 +43,6 @@
 import org.apache.openjpa.jdbc.sql.SQLFactory;
 import org.apache.openjpa.jdbc.sql.Select;
 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.kernel.FetchConfiguration;
 import org.apache.openjpa.kernel.LockManager;
@@ -363,17 +362,14 @@
      * null if there is no data in the current fetch groups to select.
      */
     private Result getInitializeStateResult(OpenJPAStateManager sm,
-            ClassMapping mapping, JDBCFetchConfiguration fetch, int subs)
-    throws SQLException {
+        ClassMapping mapping, JDBCFetchConfiguration fetch, int subs)
+        throws SQLException {
         Select sel = _sql.newSelect();
         if (!select(sel, mapping, subs, sm, null, fetch,
-                JDBCFetchConfiguration.EAGER_JOIN, true, false))
+            JDBCFetchConfiguration.EAGER_JOIN, true, false))
             return null;
         sel.wherePrimaryKey(sm.getObjectId(), mapping, this);
-        // Set the expectedResultCount for the select as 1 as a single
-        // object is being loaded. force = true is an indicator that it is 
-        // internally generated value
-        sel.setExpectedResultCount(1,true);
+        sel.setExpectedResultCount(1, false);
         return sel.execute(this, fetch);
     }
 
@@ -389,7 +385,7 @@
             JDBCFetchConfiguration.EAGER_JOIN);
 
         Union union = _sql.newUnion(mappings.length);
-        union.setExpectedResultCount(1,true);
+        union.setExpectedResultCount(1, false);
         if (fetch.getSubclassFetchMode(mapping) != fetch.EAGER_JOIN)
             union.abortUnion();
         union.select(new Union.Selector() {

Modified: incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/JDBCStoreQuery.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/JDBCStoreQuery.java?view=diff&rev=523425&r1=523424&r2=523425
==============================================================================
--- incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/JDBCStoreQuery.java (original)
+++ incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/JDBCStoreQuery.java Wed Mar 28 10:43:35 2007
@@ -310,32 +310,25 @@
         List selMappings, boolean subclasses, BitSet subclassBits,
         BitSet nextBits, ExpressionFactory[] facts, QueryExpressions[] exps,
         QueryExpressionsState[] states, ExpContext ctx, int subclassMode) {
+        Number optHint = (Number) ctx.fetch.getHint
+            (QueryHints.HINT_RESULT_COUNT);
         ClassMapping[] verts;
         boolean unionable = true;
         Select sel;
-        Object optHint = null;
         for (int i = 0; i < mappings.length; i++) {
             // determine vertical mappings to select separately
             verts = getVerticalMappings(mappings[i], subclasses, exps[i],
                 subclassMode);
             if (verts.length == 1 && subclasses)
                 subclassBits.set(sels.size());
+
             // create criteria select and clone for each vert mapping
             sel = ((JDBCExpressionFactory) facts[i]).getSelectConstructor().
                 evaluate(ctx, null, null, exps[i], states[i]);
-            // It means it is coming from getSingleResult so set the 
-            // expectedResultCount to 1.force = true indicates that this is 
-            // internally generated value
-            if (this.ctx.isUnique())
-                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);
-            }
+            if (optHint != null)
+               sel.setExpectedResultCount(optHint.intValue(), true);
+            else if (this.ctx.isUnique())
+                sel.setExpectedResultCount(1, false);
             for (int j = 0; j < verts.length; j++) {
                 selMappings.add(verts[j]);
                 if (j == verts.length - 1) {

Modified: incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/LRSProxyMap.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/LRSProxyMap.java?view=diff&rev=523425&r1=523424&r2=523425
==============================================================================
--- incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/LRSProxyMap.java (original)
+++ incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/LRSProxyMap.java Wed Mar 28 10:43:35 2007
@@ -236,9 +236,8 @@
         final JDBCFetchConfiguration fetch = store.getFetchConfiguration();
         final ClassMapping[] clss = _strat.getIndependentValueMappings(true);
         final Joins[] resJoins = new Joins[Math.max(1, clss.length)];
-        Union union = store.getSQLFactory().newUnion
-            (Math.max(1, clss.length));
-        union.setExpectedResultCount(1,true);
+        Union union = store.getSQLFactory().newUnion(Math.max(1, clss.length));
+        union.setExpectedResultCount(1, false);
         if (fetch.getSubclassFetchMode(_strat.getFieldMapping().
             getElementMapping().getTypeMapping())
             != JDBCFetchConfiguration.EAGER_JOIN)

Modified: incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/RelationFieldStrategy.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/RelationFieldStrategy.java?view=diff&rev=523425&r1=523424&r2=523425
==============================================================================
--- incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/RelationFieldStrategy.java (original)
+++ incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/RelationFieldStrategy.java Wed Mar 28 10:43:35 2007
@@ -578,7 +578,7 @@
         // back to our fk table if not an inverse mapping (in which case we
         // can just make sure the inverse cols == our pk values)
         Union union = store.getSQLFactory().newUnion(rels.length);
-        union.setExpectedResultCount(1,true);
+        union.setExpectedResultCount(1, false);
         if (fetch.getSubclassFetchMode(field.getTypeMapping())
             != JDBCFetchConfiguration.EAGER_JOIN)
             union.abortUnion();

Modified: incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/DB2Dictionary.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/DB2Dictionary.java?view=diff&rev=523425&r1=523424&r2=523425
==============================================================================
--- incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/DB2Dictionary.java (original)
+++ incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/DB2Dictionary.java Wed Mar 28 10:43:35 2007
@@ -28,9 +28,10 @@
  */
 public class DB2Dictionary
     extends AbstractDB2Dictionary {
-    // variables to support optimize clause
+
     public String optimizeClause = "optimize for";
     public String rowClause = "row";
+
     public DB2Dictionary() {
         platform = "DB2";
         validationSQL = "SELECT DISTINCT(CURRENT TIMESTAMP) FROM "
@@ -197,60 +198,13 @@
         }
     }
     
-    /** 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,
-            JDBCFetchConfiguration fetch) {
-        sel.addJoinClassConditions();
-        boolean update = forUpdate && sel.getFromSelect() == null;
-        SQLBuffer select = getSelects(sel, false, update);
-        SQLBuffer ordering = null;
-        if (!sel.isAggregate() || sel.getGrouping() != null)
-            ordering = sel.getOrdering();
-        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());
+        JDBCFetchConfiguration fetch) {
+        SQLBuffer buf = super.toSelect(sel, forUpdate, fetch); 
+        if (sel.getExpectedResultCount() > 0)
+            buf.append(" ").append(optimizeClause).append(" ").
+                append(String.valueOf(sel.getExpectedResultCount())).
+                append(" ").append(rowClause);
+        return buf;
     }
 }

Modified: incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/LogicalUnion.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/LogicalUnion.java?view=diff&rev=523425&r1=523424&r2=523425
==============================================================================
--- incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/LogicalUnion.java (original)
+++ incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/LogicalUnion.java Wed Mar 28 10:43:35 2007
@@ -47,8 +47,7 @@
 
     private static final Localizer _loc = Localizer.forPackage
         (LogicalUnion.class);
-    protected int expectedResultCount = 0;
-    protected boolean force = false;
+
     protected final UnionSelect[] sels;
     protected final DBDictionary dict;
     protected final ClassMapping[] mappings;
@@ -157,6 +156,16 @@
             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() {
         return sels[0].getJoinSyntax();
     }
@@ -208,13 +217,9 @@
             return res;
         }
 
-        if (this.getExpectedResultCount()== 1) {
+        if (getExpectedResultCount() == 1) {
             AbstractResult res;
             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,
                     lockLevel);
                 res.setBaseMapping(mappings[i]);
@@ -302,8 +307,6 @@
         protected final int pos;
         protected int orders = 0;
         protected List orderIdxs = null;
-        protected int expectedResultCount = 0;
-        protected boolean force = false;
        
         public UnionSelect(SelectImpl sel, int pos) {
             this.sel = sel;
@@ -839,17 +842,12 @@
         }
 
         public int getExpectedResultCount() {
-            return expectedResultCount;
+            return sel.getExpectedResultCount();
         }
 
-        public void setExpectedResultCount(int expectedResultCount,
-                boolean force) {
-            this.expectedResultCount = expectedResultCount;
-            this.force = force;
-        }
-        
-        public boolean isExpRsltCntForced() {
-            return force;
+        public void setExpectedResultCount(int expectedResultCount, 
+            boolean force) {
+            sel.setExpectedResultCount(expectedResultCount, force);
         }
     }
 
@@ -930,19 +928,5 @@
             }
             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;
     }
 }

Modified: incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/SelectExecutor.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/SelectExecutor.java?view=diff&rev=523425&r1=523424&r2=523425
==============================================================================
--- incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/SelectExecutor.java (original)
+++ incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/SelectExecutor.java Wed Mar 28 10:43:35 2007
@@ -78,6 +78,19 @@
      * result set.
      */
     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
@@ -119,21 +132,4 @@
     public Result execute(JDBCStore store, JDBCFetchConfiguration fetch,
         int lockLevel)
         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();
 }

Modified: incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/SelectImpl.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/SelectImpl.java?view=diff&rev=523425&r1=523424&r2=523425
==============================================================================
--- incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/SelectImpl.java (original)
+++ incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/SelectImpl.java Wed Mar 28 10:43:35 2007
@@ -82,6 +82,7 @@
     private static final int EAGER_TO_MANY = 2 << 10;
     private static final int RECORD_ORDERED = 2 << 11;
     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[] ORDER_ALIASES = new String[16];
@@ -128,6 +129,7 @@
     private int _nullIds = 0;
     private int _orders = 0;
     private int _placeholders = 0;
+    private int _expectedResultCount = 0;
 
     // query clauses
     private SQLBuffer _ordering = null;
@@ -153,9 +155,6 @@
     // from select if this select selects from a tmp table created by another
     private SelectImpl _from = 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.
@@ -245,6 +244,22 @@
             _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() {
         return _joinSyntax;
     }
@@ -307,20 +322,6 @@
         JDBCFetchConfiguration fetch, int lockLevel)
         throws SQLException {
         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) {
             JDBCLockManager lm = store.getLockManager();
             if (lm != null)
@@ -1503,6 +1504,7 @@
             sel._flags &= ~LRS;
             sel._flags &= ~EAGER_TO_ONE;
             sel._flags &= ~EAGER_TO_MANY;
+            sel._flags &= ~FORCE_COUNT;
             sel._joinSyntax = _joinSyntax;
             if (_aliases != null)
                 sel._aliases = new HashMap(_aliases);
@@ -1548,6 +1550,7 @@
         for (int i = 0; i < sels; i++) {
             sel = (SelectImpl) whereClone(1);
             sel._flags = _flags;
+            sel._expectedResultCount = _expectedResultCount;
             sel._selects.addAll(_selects);
             if (_ordering != null)
                 sel._ordering = new SQLBuffer(_ordering);
@@ -2815,20 +2818,6 @@
             _selectAs = 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;
     }
 }
 

Modified: incubator/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/QueryHints.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/QueryHints.java?view=diff&rev=523425&r1=523424&r2=523425
==============================================================================
--- incubator/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/QueryHints.java (original)
+++ incubator/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/QueryHints.java Wed Mar 28 10:43:35 2007
@@ -1,25 +1,28 @@
-/*
- * Copyright 2006 The Apache Software Foundation.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.openjpa.kernel;
-
-public interface QueryHints {
-    
-    /** Hint to specify the number of rows for the optimize
-     * clause for DB2
-     */
-    public static final String HINT_RESULT_COUNT =
-        "openjpa.hint.OptimizeResultCount";
-}
+/*
+ * Copyright 2006 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.openjpa.kernel;
+
+/**
+ * Standard query hint keys.
+ */
+public interface QueryHints {
+    
+    /** 
+     * Hint to specify the number of rows to optimize for.
+     */
+    public static final String HINT_RESULT_COUNT =
+        "openjpa.hint.OptimizeResultCount";
+}

Propchange: incubator/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/QueryHints.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: incubator/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/QueryImpl.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/QueryImpl.java?view=diff&rev=523425&r1=523424&r2=523425
==============================================================================
--- incubator/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/QueryImpl.java (original)
+++ incubator/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/QueryImpl.java Wed Mar 28 10:43:35 2007
@@ -1273,14 +1273,17 @@
             boolean next = rop.next();
 
             // 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;
             if (next) {
                 single = rop.getResultObject();
                 if (range.end != range.start + 1 && rop.next())
                     throw new InvalidStateException(_loc.get("not-unique",
                         _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 == Boolean.FALSE) {
@@ -1289,10 +1292,6 @@
                 // Collections.singletonList is JDK 1.3, so...
                 return Arrays.asList(new Object[]{ single });
             }
-             
-            if (single == null)
-                throw new InvalidStateException(_loc.get("is-null",
-                        _class, _query));
             
             // return single result
             return single;

Modified: incubator/openjpa/trunk/openjpa-kernel/src/main/resources/org/apache/openjpa/kernel/localizer.properties
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-kernel/src/main/resources/org/apache/openjpa/kernel/localizer.properties?view=diff&rev=523425&r1=523424&r2=523425
==============================================================================
--- incubator/openjpa/trunk/openjpa-kernel/src/main/resources/org/apache/openjpa/kernel/localizer.properties (original)
+++ incubator/openjpa/trunk/openjpa-kernel/src/main/resources/org/apache/openjpa/kernel/localizer.properties Wed Mar 28 10:43:35 2007
@@ -259,7 +259,7 @@
 not-unique: The query on candidate type "{0}" with filter "{1}" was \
 	configured to have a unique result, but more than one instance matched \
 	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 \
 	the query.
 serialized: Queries that have been serialized do not support this operation.

Modified: incubator/openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/QueryImpl.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/QueryImpl.java?view=diff&rev=523425&r1=523424&r2=523425
==============================================================================
--- incubator/openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/QueryImpl.java (original)
+++ incubator/openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/QueryImpl.java Wed Mar 28 10:43:35 2007
@@ -279,12 +279,12 @@
      */
     public Object getSingleResult() {
         _em.assertNotCloseInvoked();
-        // Indicate that this query returns single result.Later copied into
-        // select.expectedResultCount
+        // temporarily set query to unique so that a single result is validated
+        // and returned; unset again in case the user executes query again
+        // via getResultList
         _query.setUnique(true);
         try {
-            Object ob = execute();
-            return ob;
+            return execute();
         } finally {
             _query.setUnique(false);
         }
@@ -367,16 +367,17 @@
                 Filters.hintToSetter(getFetchPlan(), k, value);
             } else if (k.startsWith("hint.")) {
                 if ("hint.OptimizeResultCount".equals(k)) {
-                    if ((!(value instanceof String)&&! (value instanceof Integer))
-                            || (value instanceof String &&(Integer.parseInt
-                                    ((String)value)< 0))||
-                                    ((value instanceof Integer)
-                                            && (((Integer)value).intValue()<0)))
+                    if (value instanceof String) {
+                        try {
+                            value = new Integer((String) value);
+                        } catch (NumberFormatException nfe) {
+                        }
+                    }
+                    if (!(value instanceof Number) 
+                        || ((Number) value).intValue() < 0)
                         throw new ArgumentException(_loc.get
-                                ("bad-hint-value", key),
-                                null, null, false);
-                    if (value instanceof String)
-                        value = new Integer((String)value);
+                            ("bad-query-hint-value", key, value), null, null, 
+                            false);
                 }
                 _query.getFetchConfiguration().setHint(key, value);
             }
@@ -384,12 +385,7 @@
                 throw new ArgumentException(_loc.get("bad-query-hint", key),
                     null, null, false);
             return this;
-        }
-         catch (NumberFormatException e1) {
-            throw new ArgumentException(_loc.get("bad-hint-value", key),
-                    null, null, false); 
-        }
-         catch (Exception e) {
+        } catch (Exception e) {
             throw PersistenceExceptions.toPersistenceException(e);
         }
     }

Modified: incubator/openjpa/trunk/openjpa-persistence/src/main/resources/org/apache/openjpa/persistence/localizer.properties
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-persistence/src/main/resources/org/apache/openjpa/persistence/localizer.properties?view=diff&rev=523425&r1=523424&r2=523425
==============================================================================
--- incubator/openjpa/trunk/openjpa-persistence/src/main/resources/org/apache/openjpa/persistence/localizer.properties (original)
+++ incubator/openjpa/trunk/openjpa-persistence/src/main/resources/org/apache/openjpa/persistence/localizer.properties Wed Mar 28 10:43:35 2007
@@ -64,6 +64,7 @@
 no-pos-named-params-mix: Cannot mix named and positional parameters in query \
 	"{0}".
 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}".
 removed: Cannot perform this operation on removed entity "{0}".
 bad-alias: There is no known entity class for entity name "{0}".  It is \