db-ojb-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From arm...@apache.org
Subject svn commit: r513569 [1/2] - in /db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker: ./ accesslayer/ accesslayer/sql/ core/ metadata/ platforms/ query/
Date Fri, 02 Mar 2007 00:58:57 GMT
Author: arminw
Date: Thu Mar  1 16:58:55 2007
New Revision: 513569

URL: http://svn.apache.org/viewvc?view=rev&rev=513569
Log:
add support for database dependent LIMIT/OFFSET queries

Modified:
    db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/PersistenceBroker.java
    db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/accesslayer/ChainingIterator.java
    db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/accesslayer/JdbcAccessImpl.java
    db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/accesslayer/OJBIterator.java
    db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/accesslayer/PagingIterator.java
    db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/accesslayer/RsIterator.java
    db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/accesslayer/StatementManager.java
    db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/accesslayer/sql/SqlSelectStatement.java
    db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/core/DelegatingPersistenceBroker.java
    db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/core/PersistenceBrokerBean.java
    db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/core/PersistenceBrokerImpl.java
    db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/metadata/JdbcConnectionDescriptor.java
    db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/platforms/Platform.java
    db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/platforms/PlatformDb2Impl.java
    db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/platforms/PlatformDefaultImpl.java
    db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/platforms/PlatformHsqldbImpl.java
    db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/platforms/PlatformMsSQLServerImpl.java
    db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/platforms/PlatformMySQLImpl.java
    db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/platforms/PlatformOracleImpl.java
    db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/platforms/PlatformPostgreSQLImpl.java
    db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/platforms/PlatformSapdbImpl.java
    db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/query/AbstractQueryImpl.java
    db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/query/Query.java
    db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/query/QueryByCriteria.java

Modified: db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/PersistenceBroker.java
URL: http://svn.apache.org/viewvc/db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/PersistenceBroker.java?view=diff&rev=513569&r1=513568&r2=513569
==============================================================================
--- db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/PersistenceBroker.java (original)
+++ db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/PersistenceBroker.java Thu Mar  1 16:58:55 2007
@@ -322,6 +322,18 @@
      *
      * @param obj The object to store
      * @param modification Specifies what operation to perform (for generating optimized SQL)
+     * @param ignoreReferences If set <em>true</em> OJB will ignore all referenced objects
+     * and only insert/update the fields of the object.
+     */
+    public void store(Object obj,
+                      ObjectModification modification, boolean ignoreReferences) throws PersistenceBrokerException;
+
+    /**
+     * Makes the given object persistent in the underlying persistence system.
+     * This is usually done by issuing an INSERT ... or UPDATE ...  in an RDBMS.
+     *
+     * @param obj The object to store
+     * @param modification Specifies what operation to perform (for generating optimized SQL)
      */
     public void store(Object obj,
                       ObjectModification modification) throws PersistenceBrokerException;

Modified: db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/accesslayer/ChainingIterator.java
URL: http://svn.apache.org/viewvc/db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/accesslayer/ChainingIterator.java?view=diff&rev=513569&r1=513568&r2=513569
==============================================================================
--- db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/accesslayer/ChainingIterator.java (original)
+++ db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/accesslayer/ChainingIterator.java Thu Mar  1 16:58:55 2007
@@ -18,12 +18,11 @@
 import java.util.ArrayList;
 import java.util.Iterator;
 import java.util.List;
+import java.util.Collection;
 
 import org.apache.ojb.broker.PersistenceBrokerException;
 
 /**
- * @author matthew.baird (mattbaird@yahoo.com)
- *
  * The ChainingIterator is an extent aware Iterator.
  *
  * How the ChainingIterator works:
@@ -53,8 +52,6 @@
     private int m_activeIteratorIndex = 0;
     private int m_fullSize = -1;
     private int m_currentCursorPosition = 0;
-    /** if true do not fire PBLifeCycleEvent. */
-    private boolean disableLifeCycleEvents = false;
 
     /**
      * Constructor for ChainingIterator.
@@ -67,9 +64,9 @@
     /**
      * Constructor for ChainingIterator.
      */
-    public ChainingIterator(List iterators)
+    public ChainingIterator(Collection ojbIterators)
     {
-        Iterator checkIterator = iterators.iterator();
+        Iterator checkIterator = ojbIterators.iterator();
         OJBIterator temp;
 
         /**
@@ -131,6 +128,65 @@
         return size();
     }
 
+    protected OJBIterator getActiveIterator()
+    {
+        OJBIterator result;
+        if(m_activeIterator == null)
+        {
+            if(m_rsIterators.size() > 0)
+            {
+                result = (OJBIterator) m_rsIterators.get(0);
+            }
+            else
+            {
+                result = OJBIterator.EMPTY_ITERATOR;
+            }
+        }
+        else
+        {
+            result = m_activeIterator;
+        }
+        return result;
+    }
+
+    protected OJBIterator getIterator(int index)
+    {
+        return (OJBIterator) m_rsIterators.get(index);
+    }
+
+    protected OJBIterator setActiveIterator(int iteratorNumber)
+    {
+        m_activeIterator = getIterator(iteratorNumber);
+        m_activeIteratorIndex = iteratorNumber;
+        return m_activeIterator;
+    }
+
+    protected boolean setActiveAbsolute(int row)
+    {
+        OJBIterator it = getActiveIterator();
+        boolean result = it.absolute(row);
+        if(result)
+        {
+            if(row > 0) m_currentCursorPosition = row;
+            else
+            {
+                m_currentCursorPosition = it.size() + 1 + row;
+            }
+        }
+        return result;
+    }
+
+    protected boolean setActiveRelative(int row)
+    {
+        OJBIterator it = getActiveIterator();
+        boolean result = it.relative(row);
+        if(result)
+        {
+            m_currentCursorPosition += row;
+        }
+        return result;
+    }
+
     /**
      * the absolute and relative calls are the trickiest parts. We have to
      * move across cursor boundaries potentially.
@@ -143,74 +199,65 @@
      */
     public boolean absolute(int row) throws PersistenceBrokerException
     {
-        // 1. handle the special cases first.
+        // 1. handle the special cases first
         if (row == 0)
         {
             return true;
         }
-
         if (row == 1)
         {
-            m_activeIteratorIndex = 0;
-            m_activeIterator = (OJBIterator) m_rsIterators.get(m_activeIteratorIndex);
-            m_activeIterator.absolute(1);
-            return true;
+            setActiveIterator(0);
+            return setActiveAbsolute(1);
         }
         if (row == -1)
         {
-            m_activeIteratorIndex = m_rsIterators.size();
-            m_activeIterator = (OJBIterator) m_rsIterators.get(m_activeIteratorIndex);
-            m_activeIterator.absolute(-1);
-            return true;
+            setActiveIterator(m_rsIterators.size() - 1);
+            return setActiveAbsolute(-1);
         }
-
-        // now do the real work.
-        boolean movedToAbsolute = false;
+        // 2. now do the real work
         boolean retval = false;
-        setNextIterator();
-
         // row is positive, so index from beginning.
         if (row > 0)
         {
             int sizeCount = 0;
-            Iterator it = m_rsIterators.iterator();
-            OJBIterator temp = null;
-            while (it.hasNext() && !movedToAbsolute)
+            OJBIterator temp;
+            for(int i = 0; i < m_rsIterators.size(); i++)
+            //while (it.hasNext() && !movedToAbsolute)
             {
-                temp = (OJBIterator) it.next();
-                if (temp.size() < row)
+                temp = getIterator(i);
+                int tempMax = temp.size();
+                if(sizeCount + tempMax < row)
                 {
-                    sizeCount += temp.size();
+                    sizeCount += tempMax;
                 }
                 else
                 {
-                    // move to the offset - sizecount
-                    m_currentCursorPosition = row - sizeCount;
-                    retval = temp.absolute(m_currentCursorPosition);
-                    movedToAbsolute = true;
+                    setActiveIterator(i);
+                    retval = setActiveAbsolute(row - sizeCount);
+                    break;
                 }
             }
 
         }
-
         // row is negative, so index from end
         else if (row < 0)
         {
             int sizeCount = 0;
-            OJBIterator temp = null;
-            for (int i = m_rsIterators.size(); ((i >= 0) && !movedToAbsolute); i--)
+            int rowAbs = Math.abs(row);
+            OJBIterator temp;
+            for (int i = m_rsIterators.size() - 1; i >= 0; i--)
             {
-                temp = (OJBIterator) m_rsIterators.get(i);
-                if (temp.size() < row)
+                temp = getIterator(i);
+                int tempMax = temp.size();
+                if (sizeCount + tempMax < rowAbs)
                 {
                     sizeCount += temp.size();
                 }
                 else
                 {
-                    // move to the offset - sizecount
-                    m_currentCursorPosition = row + sizeCount;
-                    retval = temp.absolute(m_currentCursorPosition);
-                    movedToAbsolute = true;
+                    setActiveIterator(i);
+                    retval = setActiveAbsolute(row + sizeCount);
+                    break;
                 }
             }
         }
@@ -235,46 +282,79 @@
      */
     public boolean relative(int row) throws PersistenceBrokerException
     {
+        // 1. handle the special cases first.
         if (row == 0)
         {
             return true;
         }
-
-        boolean movedToRelative = false;
+        // 2. now do the real work.
         boolean retval = false;
-        setNextIterator();
-
+        OJBIterator it = getActiveIterator();
+        // positive shift
         if (row > 0)
         {
             // special case checking for the iterator we're currently in
             // (since it isn't positioned on the boundary potentially)
-            if (row > (m_activeIterator.size() - m_currentCursorPosition))
+            if (row > (it.size() - m_currentCursorPosition))
             {
                 // the relative position lies over the border of the
                 // current iterator.
 
                 // starting position counter should be set to whatever we have left in
                 // active iterator.
-                int positionCounter = m_activeIterator.size() - m_currentCursorPosition;
-                for (int i = m_activeIteratorIndex + 1; ((i < m_rsIterators.size()) && !movedToRelative); i++)
+                int positionCounter = it.size() - m_currentCursorPosition;
+                for (int i = m_activeIteratorIndex + 1; i < m_rsIterators.size(); i++)
                 {
-                    m_activeIteratorIndex = i;
-                    m_currentCursorPosition = 0;
-                    m_activeIterator = (OJBIterator) m_rsIterators.get(m_activeIteratorIndex);
-                    if (!((row - positionCounter) > m_activeIterator.size()))
+                    OJBIterator temp = getIterator(i);
+                    if ((row - positionCounter) > temp.size())
+                    {
+                        positionCounter += temp.size();
+                    }
+                    else
                     {
                         // the relative position requested is within this iterator.
-                        m_currentCursorPosition = row - positionCounter;
-                        retval = m_activeIterator.relative(m_currentCursorPosition);
-                        movedToRelative = true;
+                        setActiveIterator(i);
+                        retval = setActiveRelative(row - positionCounter);
+                        break;
                     }
                 }
             }
             else
             {
                 // the relative position lays within the current iterator.
-                retval = m_activeIterator.relative(row);
-                movedToRelative = true;
+               retval = setActiveRelative(row);
+            }
+        }
+        else // negative shift
+        {
+            int rowAbs = Math.abs(row);
+            if(m_currentCursorPosition < rowAbs)
+            {
+                // the relative position lies over the border of the
+                // current iterator.
+
+                // starting position counter should be set to whatever we have left in
+                // active iterator.
+                int positionCounter = m_currentCursorPosition;
+                for (int i = m_activeIteratorIndex - 1; i > -1; i--)
+                {
+                    OJBIterator temp = getIterator(i);
+                    if ((rowAbs - positionCounter) > temp.size())
+                    {
+                        positionCounter += temp.size();
+                    }
+                    else
+                    {
+                        // the relative position requested is within this iterator.
+                        setActiveIterator(i);
+                        retval = setActiveRelative(row + positionCounter);
+                        break;
+                    }
+                }
+            }
+            else
+            {
+                retval = setActiveRelative(row);
             }
         }
 
@@ -367,8 +447,6 @@
 
     /**
      * Answer true if an Iterator for a Table is already available
-     * @param aTable
-     * @return
      */
     public boolean containsIteratorForTable(String aTable)
     {

Modified: db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/accesslayer/JdbcAccessImpl.java
URL: http://svn.apache.org/viewvc/db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/accesslayer/JdbcAccessImpl.java?view=diff&rev=513569&r1=513568&r2=513569
==============================================================================
--- db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/accesslayer/JdbcAccessImpl.java (original)
+++ db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/accesslayer/JdbcAccessImpl.java Thu Mar  1 16:58:55 2007
@@ -19,6 +19,7 @@
 import java.sql.PreparedStatement;
 import java.sql.ResultSet;
 import java.sql.SQLException;
+import java.sql.Statement;
 import java.util.HashMap;
 import java.util.Iterator;
 import java.util.Map;
@@ -215,7 +216,7 @@
             if (logger.isDebugEnabled()) logger.debug("executeInsert: " + stmt);
             stmt.executeUpdate();
             // after insert read and assign identity columns
-            postSequenceProcess(cld, obj);
+            postSequenceProcess(stmt, cld, obj);
 
             // Harvest any return values.
             harvestReturnValues(cld.getInsertProcedure(), obj, stmt);
@@ -252,6 +253,16 @@
             logger.debug("executeQuery: " + query);
         }
         /*
+        arminw:
+        we need platform dependent information below, so we have to pre-process the
+        query object, this can cause twice invocation of method Query.preprocess
+        because in class PersistencebrokerImpl#getRsIteratorFromQuery this method
+        is called too
+        TODO: fix twice call of method Query.preprocess if possible
+        */
+        query.preprocess(broker);
+
+        /*
 		 * MBAIRD: we should create a scrollable resultset if the start at
 		 * index or end at index is set
 		 */
@@ -807,11 +818,11 @@
         }
     }
 
-    protected void postSequenceProcess(final ClassDescriptor cld, final Object target) throws SequenceManagerException
+    protected void postSequenceProcess(final Statement stmt, final ClassDescriptor cld, final Object target) throws SequenceManagerException
     {
         // post insert sequence manager call, e.g. to lookup identity column PK value
         // from DB and set PK in persistent object
-        broker.serviceSequenceManager().afterStore(this, cld, target);
+        broker.serviceSequenceManager().afterStore(this, stmt, cld, target);
     }
 
     /**

Modified: db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/accesslayer/OJBIterator.java
URL: http://svn.apache.org/viewvc/db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/accesslayer/OJBIterator.java?view=diff&rev=513569&r1=513568&r2=513569
==============================================================================
--- db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/accesslayer/OJBIterator.java (original)
+++ db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/accesslayer/OJBIterator.java Thu Mar  1 16:58:55 2007
@@ -39,13 +39,27 @@
 public interface OJBIterator extends Iterator
 {
     /**
+     * Returns the size of the iterator in consideration of limit-seetings
+     * (see {@link org.apache.ojb.broker.query.Query#setStartAtIndex(int)}
+     * and {@link org.apache.ojb.broker.query.Query#setEndAtIndex(int)}) of the
+     * underlying {@link org.apache.ojb.broker.query.Query}.
+     * <br/>
+     * This may differ from the result of method {@link #fullSize()}.
+     *
      * @return the size of the iterator, aka the number of rows in this iterator.
      */
     int size() throws PersistenceBrokerException;
 
     /**
-     * @return the unlimited size of the iterator,
-     * fullSize() may differ from size() for PagingIterator
+     * Returns the full size of the iterator.
+     *
+     * @return the unlimited size of the iterator, this may differ from {@link #size()}
+     *         dependent of the used implementation - e.g. if
+     *         {@link org.apache.ojb.broker.query.Query#setStartAtIndex(int)}
+     *         and {@link org.apache.ojb.broker.query.Query#setEndAtIndex(int)} is used in the
+     *         underlying {@link org.apache.ojb.broker.query.Query} but the used database does not
+     *         support native LIMIT/OFFSET, thus {@link #fullSize()} will return the full iterator size and
+     *         {@link #size()} take care of limit boundaries.
      */
     int fullSize() throws PersistenceBrokerException;
 
@@ -53,14 +67,17 @@
      * Moves the cursor to the given row number in the iterator.
      * If the row number is positive, the cursor moves to the given row number with
      * respect to the beginning of the iterator. The first row is row 1, the second is row 2, and so on.
+     *
      * @param row the row to move to in this iterator, by absolute number
      */
     boolean absolute(int row) throws PersistenceBrokerException;
 
     /**
-     * Moves the cursor a relative number of rows, either positive or negative. Attempting to move beyond the first/last
-     * row in the iterator positions the cursor before/after the the first/last row. Calling relative(0) is valid,
+     * Moves the cursor a relative number of rows, either positive or negative.
+     * Attempting to move beyond the first/last row in the iterator positions the
+     * cursor before/after the first/last row. Calling relative(0) is valid,
      * but does not change the cursor position.
+     *
      * @param row the row to move to in this iterator, by relative number
      */
     boolean relative(int row) throws PersistenceBrokerException;
@@ -72,9 +89,56 @@
      * this method will be called implicitely.
      */
     public void releaseDbResources();
-    
+
     /**
-     * Do not fire any PBLifeCycleEvent when reading next item. 
+     * Do not fire any PBLifeCycleEvent when reading next item.
      */
     public void disableLifeCycleEvents();
+
+    /**
+     * A NOOP implementation of this interface.
+     */
+    public static final OJBIterator EMPTY_ITERATOR = new OJBIterator(){
+        public boolean absolute(int row) throws PersistenceBrokerException
+        {
+            return false;
+        }
+
+        public void disableLifeCycleEvents()
+        {
+        }
+
+        public int fullSize() throws PersistenceBrokerException
+        {
+            return 0;
+        }
+
+        public boolean relative(int row) throws PersistenceBrokerException
+        {
+            return false;
+        }
+
+        public void releaseDbResources()
+        {
+        }
+
+        public int size() throws PersistenceBrokerException
+        {
+            return 0;
+        }
+
+        public boolean hasNext()
+        {
+            return false;
+        }
+
+        public Object next()
+        {
+            return null;
+        }
+
+        public void remove()
+        {
+        }
+    };
 }

Modified: db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/accesslayer/PagingIterator.java
URL: http://svn.apache.org/viewvc/db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/accesslayer/PagingIterator.java?view=diff&rev=513569&r1=513568&r2=513569
==============================================================================
--- db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/accesslayer/PagingIterator.java (original)
+++ db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/accesslayer/PagingIterator.java Thu Mar  1 16:58:55 2007
@@ -16,6 +16,8 @@
  */
 
 import org.apache.ojb.broker.PersistenceBrokerException;
+import org.apache.ojb.broker.util.logging.Logger;
+import org.apache.ojb.broker.util.logging.LoggerFactory;
 import org.apache.ojb.broker.query.Query;
 
 /**
@@ -26,17 +28,18 @@
  * startAt = 1, endAt = 11 returns rows 1 to 11 if available
  * if endAt == Query.NO_END_AT_INDEX endAt is set to the last available row
  * 
- * @author <a href="mailto:jbraeuchi@gmx.ch">Jakob Braeuchi</a>
  * @version $Id$
  */
 public class PagingIterator implements OJBIterator
 {
+    private Logger log = LoggerFactory.getLogger(PagingIterator.class);
     private final OJBIterator m_iterator;
     private int m_startAt;
     private int m_endAt;
-    private int m_rowLimit;
+    private int m_rowLimitSize;
     private int m_fullSize;
-    private int m_currentCursorPosition; // position of the wrapped iterator
+    // position of the wrapped iterator
+    private int m_currentCursorPosition;
 
     /**
      * Constructor 
@@ -47,36 +50,29 @@
     public PagingIterator(OJBIterator anIterator, int startAt, int endAt)
     {
         super();
-
-        if (endAt != Query.NO_START_AT_INDEX && startAt > endAt)
+        if (endAt != Query.NO_END_AT_INDEX && startAt > endAt)
         {
             throw new PersistenceBrokerException("startAt must be less than endAt.");
         }
 
-        m_iterator = anIterator;
-        m_fullSize = m_iterator.size();
-
-        if (startAt == Query.NO_START_AT_INDEX)
-        {
-            m_startAt = 1;
-        }
-        else
-        {
-            m_startAt = startAt;
-        }
-
-        if (endAt == Query.NO_END_AT_INDEX)
-        {
-            m_endAt = m_fullSize;
+        m_fullSize = anIterator.size();
+        m_startAt = (startAt == Query.NO_START_AT_INDEX ? 1 : startAt);
+        m_endAt = (endAt == Query.NO_END_AT_INDEX || endAt > m_fullSize ? m_fullSize : endAt);
+        m_rowLimitSize = Math.max(0, m_endAt - m_startAt + 1);
+        m_currentCursorPosition = m_startAt;
+        if(m_startAt > m_endAt || m_startAt > m_fullSize)
+        {
+            log.warn("Index out of bound, Query.startAt=" + m_startAt
+                    + " and Query.endAt=" + m_endAt + " doesn't match results");
+            m_iterator = OJBIterator.EMPTY_ITERATOR;
+            m_rowLimitSize = 0;
+            m_fullSize = 0;
+            anIterator.releaseDbResources();
         }
         else
         {
-            m_endAt = Math.min(endAt, m_fullSize);
+            m_iterator = anIterator;
         }
-        
-        m_rowLimit = Math.max(0, m_endAt - m_startAt + 1);
-        m_currentCursorPosition = m_startAt - 1;
-
         m_iterator.absolute(m_currentCursorPosition);
     }
 
@@ -85,13 +81,13 @@
 	 */
     public int size() throws PersistenceBrokerException
     {
-        if (m_fullSize < m_rowLimit)
+        if (m_fullSize < m_rowLimitSize)
         {
             return m_fullSize;
         }
         else
         {
-            return m_rowLimit;
+            return m_rowLimitSize;
         }
     }
 
@@ -108,20 +104,23 @@
 	 */
     public boolean absolute(int row) throws PersistenceBrokerException
     {
-        int newPosition = (m_startAt - 1) + row;
-        
-        if (newPosition < m_startAt)
+        boolean result = false;
+        int newPosition = 0;
+        if(row > 0)
+        {
+            newPosition = m_startAt - 1 + row;
+            result = m_iterator.absolute(newPosition);
+        }
+        else if(row < 0)
         {
-            newPosition = Math.max(m_endAt + row, m_startAt - 1);
+            newPosition = m_endAt + 1 + row;
+            result = m_iterator.absolute(newPosition);
         }
-        
-        if (newPosition > m_endAt)
+        if(result)
         {
-            newPosition = m_endAt;
+            m_currentCursorPosition = newPosition;
         }
-        
-        m_currentCursorPosition = newPosition;
-        return m_iterator.absolute(newPosition);
+        return result;
     }
 
     /**
@@ -129,7 +128,30 @@
 	 */
     public boolean relative(int row) throws PersistenceBrokerException
     {
-        return absolute(m_currentCursorPosition - (m_startAt - 1) + row);
+        boolean result = false;
+        if(row > 0)
+        {
+            if(row <= m_endAt - m_currentCursorPosition)
+            {
+                result = m_iterator.relative(row);
+                if(result)
+                {
+                    m_currentCursorPosition += row;
+                }
+            }
+        }
+        else if(row < 0)
+        {
+            if(Math.abs(row) <= m_currentCursorPosition - m_startAt)
+            {
+                result = m_iterator.relative(row);
+                if(result)
+                {
+                    m_currentCursorPosition += row;
+                }
+            }
+        }
+        return result;
     }
 
     /**
@@ -153,16 +175,12 @@
 	 */
     public boolean hasNext()
     {
-        if (m_currentCursorPosition < m_endAt)
-        {
-            return true;
-        }
-        else
+        boolean result = m_currentCursorPosition <= m_endAt && m_iterator.hasNext();
+        if(!result)
         {
             releaseDbResources();
-            return false;
         }
-
+        return result;
     }
 
     /**

Modified: db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/accesslayer/RsIterator.java
URL: http://svn.apache.org/viewvc/db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/accesslayer/RsIterator.java?view=diff&rev=513569&r1=513568&r2=513569
==============================================================================
--- db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/accesslayer/RsIterator.java (original)
+++ db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/accesslayer/RsIterator.java Thu Mar  1 16:58:55 2007
@@ -70,10 +70,6 @@
  * It will NOT work with JDBC 1.0 Drivers (e.g. SUN's JdbcOdbcDriver) If you
  * are forced to use such a driver, you can use code from the 0.1.30 release.
  * </p>
- * @author <a href="mailto:thma@apache.org">Thomas Mahler <a>
- * @author <a href="mailto:mattbaird@yahoo.com">Matthew Baird <a>- added the
- *         support for extents mapped to single table - added the .size
- *         functionality - added cursor control
  *
  * @version $Id$
  */
@@ -233,6 +229,7 @@
             {
                 setHasCalledCheck(true);
                 setHasNext(getRsAndStmt().m_rs.next());
+                m_current_row++;
                 if (!getHasNext())
                 {
                     autoReleaseDbResources();
@@ -278,7 +275,7 @@
             if (getHasNext())
             {
                 Object obj = getObjectFromResultSet();
-                m_current_row++;
+                //m_current_row++;
 
                 // Invoke events on PersistenceBrokerAware instances and listeners
                 // set target object
@@ -566,8 +563,7 @@
     {
         if (!JDBCSupportAssessed)
         {
-            if (getConnectionDescriptor().getJdbcLevel() >= 2.0)
-                advancedJDBCSupport = true;
+            advancedJDBCSupport = getConnectionDescriptor().getJdbcLevel() >= 2.0;
             JDBCSupportAssessed = true;
         }
         return advancedJDBCSupport;
@@ -618,7 +614,6 @@
         {
             rsStmt.close();
         }
-
         return count;
     }
 
@@ -727,38 +722,47 @@
     private boolean absoluteBasic(int row)
     {
         boolean retval = false;
-        
-        if (row > m_current_row)
+        if(row == -1)
         {
-            try
+            int size = size();
+            if(getQueryObject().usePaging())
             {
-                while (m_current_row < row && getRsAndStmt().m_rs.next())
+                int span = getQueryObject().getEndIndex() + 1 - getQueryObject().getStartIndex();
+                if(span < size)
                 {
-                    m_current_row++;
+                    size = span;
                 }
-                if (m_current_row == row)
-                {
-                    retval = true;
-                }
-                else
+            }
+            row = size;
+        }
+        if (row > m_current_row)
+        {
+            try
+            {
+                retval = true;
+                while (m_current_row < row && retval)
                 {
-                    setHasCalledCheck(true);
-                    setHasNext(false);
-                    retval = false;
-                    autoReleaseDbResources();
+                    retval = getRsAndStmt().m_rs.next();
+                    if(retval) m_current_row++;
+                    else break;
                 }
+                setHasCalledCheck(true);
+                setHasNext(retval);
+                if(!retval) autoReleaseDbResources();
+                System.out.println("result: " + getRsAndStmt().m_rs.getString(1) +", "+ getRsAndStmt().m_rs.getString("Lagerbestand"));
             }
             catch (Exception ex)
             {
                 setHasCalledCheck(true);
                 setHasNext(false);
                 retval = false;
+                autoReleaseDbResources();
             }
         }
         else
         {
-            logger.info("Your driver does not support advanced JDBC Functionality, " +
-                    "you cannot call absolute() with a position < current");
+            logger.warn("Your driver does not support advanced JDBC Functionality, " +
+                    "you cannot call absolute() with a 'position' < 'current'");
         }
         return retval;
     }
@@ -770,21 +774,26 @@
     private boolean absoluteAdvanced(int row)
     {
         boolean retval = false;
-        
         try
         {
             if (getRsAndStmt().m_rs != null)
             {
-                if (row == 0)
+                if(row == 1 || row == 0)
+                {
+                    retval = getRsAndStmt().m_rs.first();
+                    //retval = getRsAndStmt().m_rs.absolute(1);
+                }
+                else if (row == -1)
                 {
-                    getRsAndStmt().m_rs.beforeFirst();
+                    retval = getRsAndStmt().m_rs.last();
                 }
                 else
                 {
-                    retval = getRsAndStmt().m_rs.absolute(row);                        
+                    retval = getRsAndStmt().m_rs.absolute(row);
                 }
-                m_current_row = row;
-                setHasCalledCheck(false);
+                if(retval) m_current_row = row;
+                setHasCalledCheck(retval);
+                setHasNext(retval);
             }
         }
         catch (SQLException e)
@@ -829,7 +838,8 @@
             }
             else
             {
-                logger.info("Your driver does not support advanced JDBC Functionality, you cannot call relative() with a negative value");
+                logger.warn("Your driver does not support advanced JDBC Functionality, you cannot call" +
+                        " relative() with a negative value");
             }
         }
         return retval;

Modified: db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/accesslayer/StatementManager.java
URL: http://svn.apache.org/viewvc/db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/accesslayer/StatementManager.java?view=diff&rev=513569&r1=513568&r2=513569
==============================================================================
--- db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/accesslayer/StatementManager.java (original)
+++ db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/accesslayer/StatementManager.java Thu Mar  1 16:58:55 2007
@@ -20,6 +20,7 @@
 import java.sql.ResultSet;
 import java.sql.SQLException;
 import java.sql.Statement;
+import java.sql.Types;
 import java.util.Collection;
 import java.util.Enumeration;
 import java.util.Iterator;
@@ -44,6 +45,7 @@
 import org.apache.ojb.broker.query.Query;
 import org.apache.ojb.broker.query.SelectionCriteria;
 import org.apache.ojb.broker.query.SqlCriteria;
+import org.apache.ojb.broker.query.AbstractQueryImpl;
 import org.apache.ojb.broker.util.logging.Logger;
 import org.apache.ojb.broker.util.logging.LoggerFactory;
 
@@ -325,13 +327,43 @@
      */
     public int bindStatement(PreparedStatement stmt, Query query, ClassDescriptor cld, int param) throws SQLException
     {
-        int result;
+        int result = param;
+        //TODO: rework limit/offset support, avoid this cast
+        int[] limitValues = ((AbstractQueryImpl) query).getLimitValues();
+        boolean limitOrOffset = query.usePaging() && limitValues.length > 0;
+        if(limitOrOffset)
+        {
+            if(m_platform.limitAfterSelect())
+            {
+                for(int i = 0; i < limitValues.length; i++)
+                {
+                    int limitValue = limitValues[i];
+                    m_platform.setObjectForStatement(stmt, result, new Integer(limitValue), Types.INTEGER);
+                    ++result;
+                }
+            }
 
-        result = bindStatement(stmt, query.getCriteria(), cld, param);
-        result = bindStatement(stmt, query.getHavingCriteria(), cld, result);
+            result = bindStatement(stmt, query.getCriteria(), cld, result);
+            result = bindStatement(stmt, query.getHavingCriteria(), cld, result);
 
+            if(!m_platform.limitAfterSelect())
+            {
+                for(int i = 0; i < limitValues.length; i++)
+                {
+                    int limitValue = limitValues[i];
+                    m_platform.setObjectForStatement(stmt, result, new Integer(limitValue), Types.INTEGER);
+                    ++result;
+                }
+            }
+        }
+        else
+        {
+            result = bindStatement(stmt, query.getCriteria(), cld, result);
+            result = bindStatement(stmt, query.getHavingCriteria(), cld, result);
+        }
         return result;
     }
+
 
     /**
      * bind a Query based Select Statement

Modified: db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/accesslayer/sql/SqlSelectStatement.java
URL: http://svn.apache.org/viewvc/db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/accesslayer/sql/SqlSelectStatement.java?view=diff&rev=513569&r1=513568&r2=513569
==============================================================================
--- db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/accesslayer/sql/SqlSelectStatement.java (original)
+++ db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/accesslayer/sql/SqlSelectStatement.java Thu Mar  1 16:58:55 2007
@@ -15,12 +15,12 @@
  * limitations under the License.
  */
 
+import java.lang.ref.WeakReference;
 import java.util.ArrayList;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
-import java.lang.ref.WeakReference;
 
 import org.apache.commons.collections.set.ListOrderedSet;
 import org.apache.ojb.broker.metadata.ClassDescriptor;
@@ -377,16 +377,30 @@
              ((ReportQueryByCriteria) query).setAttributeFieldDescriptors(m_attrToFld);
         }
 
-        if(query.isSelectForUpdate())
-        {
-            stmt.append(getPlatform().getSelectForUpdateClause());
-        }
+        stmt = prepareLimitAndOffset(stmt);
+
+        appendSelectForUpdate(stmt);
+
         if(query.getQueryAffix() != null)
         {
             stmt.append(" ").append(query.getQueryAffix());
         }
 
         return stmt.toString();
+    }
+
+    protected StringBuffer prepareLimitAndOffset(StringBuffer stmt)
+    {
+        //TODO: Rework this section
+        return getQuery().prepareLimitAndOffset(stmt);
+    }
+
+    protected void appendSelectForUpdate(StringBuffer stmt)
+    {
+        if(getQuery().isSelectForUpdate())
+        {
+            stmt.append(getPlatform().getSelectForUpdateClause());
+        }
     }
 
 /*

Modified: db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/core/DelegatingPersistenceBroker.java
URL: http://svn.apache.org/viewvc/db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/core/DelegatingPersistenceBroker.java?view=diff&rev=513569&r1=513568&r2=513569
==============================================================================
--- db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/core/DelegatingPersistenceBroker.java (original)
+++ db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/core/DelegatingPersistenceBroker.java Thu Mar  1 16:58:55 2007
@@ -220,12 +220,17 @@
 		getBroker().delete(obj);
 	}
 
-	public void store(Object obj) throws PersistenceBrokerException
+    public void store(Object obj, ObjectModification modification, boolean ignoreReferences) throws PersistenceBrokerException
+    {
+        getBroker().store(obj, modification, ignoreReferences);
+    }
+
+    public void store(Object obj) throws PersistenceBrokerException
 	{
 		getBroker().store(obj);
 	}
 
-	public void store(Object obj,
+    public void store(Object obj,
 					  ObjectModification modification) throws PersistenceBrokerException
 	{
 		getBroker().store(obj, modification);

Modified: db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/core/PersistenceBrokerBean.java
URL: http://svn.apache.org/viewvc/db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/core/PersistenceBrokerBean.java?view=diff&rev=513569&r1=513568&r2=513569
==============================================================================
--- db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/core/PersistenceBrokerBean.java (original)
+++ db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/core/PersistenceBrokerBean.java Thu Mar  1 16:58:55 2007
@@ -311,7 +311,17 @@
 		return getBroker().getPKEnumerationByQuery(PrimaryKeyClass, query);
 	}
 
-	/**
+    /**
+	 * @ejb:interface-method
+	 * @see org.apache.ojb.broker.PersistenceBroker#store(Object, ObjectModification)
+	 */
+	public void store(Object obj, ObjectModification modification, boolean ignoreReferences)
+			throws PersistenceBrokerException
+	{
+		getBroker().store(obj, modification, ignoreReferences);
+	}
+
+    /**
 	 * @ejb:interface-method
 	 * @see org.apache.ojb.broker.PersistenceBroker#store(Object, ObjectModification)
 	 */

Modified: db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/core/PersistenceBrokerImpl.java
URL: http://svn.apache.org/viewvc/db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/core/PersistenceBrokerImpl.java?view=diff&rev=513569&r1=513568&r2=513569
==============================================================================
--- db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/core/PersistenceBrokerImpl.java (original)
+++ db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/core/PersistenceBrokerImpl.java Thu Mar  1 16:58:55 2007
@@ -19,6 +19,7 @@
 import java.util.Collection;
 import java.util.Collections;
 import java.util.Enumeration;
+import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Iterator;
 import java.util.List;
@@ -74,6 +75,7 @@
 import org.apache.ojb.broker.metadata.ObjectReferenceDescriptor;
 import org.apache.ojb.broker.metadata.SequenceDescriptor;
 import org.apache.ojb.broker.metadata.fieldaccess.PersistentField;
+import org.apache.ojb.broker.platforms.Platform;
 import org.apache.ojb.broker.query.Query;
 import org.apache.ojb.broker.query.QueryByIdentity;
 import org.apache.ojb.broker.query.QueryBySQL;
@@ -85,9 +87,9 @@
 import org.apache.ojb.broker.util.configuration.ConfigurationException;
 import org.apache.ojb.broker.util.logging.Logger;
 import org.apache.ojb.broker.util.logging.LoggerFactory;
+import org.apache.ojb.broker.util.sequence.PerFieldManager;
 import org.apache.ojb.broker.util.sequence.SequenceManager;
 import org.apache.ojb.broker.util.sequence.SequenceManagerHelper;
-import org.apache.ojb.broker.util.sequence.PerFieldManager;
 
 /**
  * The PersistenceBrokerImpl is an implementation of the PersistenceBroker
@@ -1728,25 +1730,6 @@
         return getIteratorFromQuery(query, cld);
     }
 
-    /**
-     * Get an extent aware Iterator based on the Query
-     *
-     * @param query
-     * @param cld the ClassDescriptor
-     * @return OJBIterator
-     */
-    protected OJBIterator getIteratorFromQuery(Query query, ClassDescriptor cld) throws PersistenceBrokerException
-    {
-        RsIteratorFactory factory = RsIteratorFactoryImpl.getInstance();
-        OJBIterator result = getRsIteratorFromQuery(query, cld, factory);
-
-        if (query.usePaging())
-        {
-            result = new PagingIterator(result, query.getStartAtIndex(), query.getEndAtIndex());
-        }
-        return result;
-    }
-
     public Object getObjectByIdentity(Identity id) throws PersistenceBrokerException
     {
         objectCache.enableMaterializationCache();
@@ -1927,16 +1910,13 @@
         return new PkEnumeration(query, cld, primaryKeyClass, this);
     }
 
-    /**
-     * Makes object obj persistent in the underlying persistence system.
-     * E.G. by INSERT INTO ... or UPDATE ...  in an RDBMS.
-     * The ObjectModification parameter can be used to determine whether INSERT or update is to be used.
-     * This functionality is typically called from transaction managers, that
-     * track which objects have to be stored. If the object is an unmaterialized
-     * proxy the method return immediately.
-     */
     public void store(Object obj, ObjectModification mod) throws PersistenceBrokerException
     {
+        store(obj, mod, false);
+    }
+    
+    public void store(Object obj, ObjectModification mod, boolean ignoreReferences) throws PersistenceBrokerException
+    {
         obj = extractObjectToStore(obj);
         // null for unmaterialized Proxy
         if (obj == null)
@@ -1950,11 +1930,11 @@
         // select flag for insert / update selection by checking the ObjectModification
         if (mod.needsInsert())
         {
-            store(obj, oid, cld, true);
+            store(obj, oid, cld, true, ignoreReferences);
         }
         else if (mod.needsUpdate())
         {
-            store(obj, oid, cld, false);
+            store(obj, oid, cld, false, ignoreReferences);
         }
         /*
         arminw
@@ -2185,6 +2165,32 @@
     }
 
     /**
+     * Get an extent aware Iterator based on the ReportQuery
+     *
+     * @param query
+     * @param cld
+     * @return OJBIterator
+     */
+    protected OJBIterator getReportQueryIteratorFromQuery(Query query, ClassDescriptor cld) throws PersistenceBrokerException
+    {
+        RsIteratorFactory factory = ReportRsIteratorFactoryImpl.getInstance();
+        return getRsIteratorFromQuery(query, cld, factory);
+    }
+
+    /**
+     * Get an extent aware Iterator based on the Query
+     *
+     * @param query
+     * @param cld the ClassDescriptor
+     * @return OJBIterator
+     */
+    protected OJBIterator getIteratorFromQuery(Query query, ClassDescriptor cld) throws PersistenceBrokerException
+    {
+        RsIteratorFactory factory = RsIteratorFactoryImpl.getInstance();
+        return getRsIteratorFromQuery(query, cld, factory);
+    }
+
+    /**
      * Get an extent aware RsIterator based on the Query
      *
      * @param query
@@ -2195,74 +2201,101 @@
     private OJBIterator getRsIteratorFromQuery(Query query, ClassDescriptor cld, RsIteratorFactory factory)
         throws PersistenceBrokerException
     {
-        query.setFetchSize(1);
+        // arminw: we use iterator for all kind of query, so I think
+        // this setting doesn't make sense and will override user settings
+        //query.setFetchSize(1);
+        /*
+        arminw:
+        we need platform dependent information below, so we have to pre-process the
+        query object, this will cause twice invocation of method Query.preprocess
+        because in class JdbcAccess this method is called too
+        TODO: fix twice call of method Query.preprocess if possible
+        */
         query.preprocess(this);
+        OJBIterator result;
 
         if (query instanceof QueryBySQL)
         {
             if(logger.isDebugEnabled()) logger.debug("Creating SQL-RsIterator for class ["+cld.getClassNameOfObject()+"]");
-            return factory.createRsIterator((QueryBySQL) query, cld, this);
+            result = factory.createRsIterator((QueryBySQL) query, cld, this);
+            result = wrapWithPagingIteratorIfNeeded(result, query);
         }
-
-        if (!cld.isExtent() || !query.getWithExtents())
+        else if (!cld.isExtent() || !query.getWithExtents())
         {
             // no extents just use the plain vanilla RsIterator
             if(logger.isDebugEnabled()) logger.debug("Creating RsIterator for class ["+cld.getClassNameOfObject()+"]");
-
-            return factory.createRsIterator(query, cld, this);
-        }
-
-        if(logger.isDebugEnabled()) logger.debug("Creating ChainingIterator for class ["+cld.getClassNameOfObject()+"]");
-
-        ChainingIterator chainingIter = new ChainingIterator();
-
-        // BRJ: add base class iterator
-        if (!cld.isInterface())
-        {
-            if(logger.isDebugEnabled()) logger.debug("Adding RsIterator for class ["+cld.getClassNameOfObject()+"] to ChainingIterator");
-
-            chainingIter.addIterator(factory.createRsIterator(query, cld, this));
+            result = factory.createRsIterator(query, cld, this);
+            result = wrapWithPagingIteratorIfNeeded(result, query);
         }
-
-        Iterator extents = getDescriptorRepository().getAllConcreteSubclassDescriptors(cld).iterator();
-        while (extents.hasNext())
+        else
         {
-            ClassDescriptor extCld = (ClassDescriptor) extents.next();
-
-            // read same table only once
-            if (chainingIter.containsIteratorForTable(extCld.getFullTableName()))
-            {
-                if(logger.isDebugEnabled()) logger.debug("Skipping class ["+extCld.getClassNameOfObject()+"]");
+            HashMap iteratorMap = new HashMap();
+            if(logger.isDebugEnabled()) logger.debug("ChainingIterator for class ["+cld.getClassNameOfObject()+"]");
+            // BRJ: add base class iterator
+            if (!cld.isInterface())
+            {
+                if(logger.isDebugEnabled()) logger.debug("ChainingIterator: Adding RsIterator for class ["+cld.getClassNameOfObject()+"] to ChainingIterator");
+                OJBIterator tmp = factory.createRsIterator(query, cld, this);
+                iteratorMap.put(cld.getFullTableName() ,wrapWithPagingIteratorIfNeeded(tmp, query));
             }
-            else
+
+            Iterator extents = getDescriptorRepository().getAllConcreteSubclassDescriptors(cld).iterator();
+            while (extents.hasNext())
             {
-                if(logger.isDebugEnabled()) logger.debug("Adding RsIterator of class ["+extCld.getClassNameOfObject()+"] to ChainingIterator");
+                ClassDescriptor extCld = (ClassDescriptor) extents.next();
+
+                // read same table only once
+                if (iteratorMap.containsKey(extCld.getFullTableName()))
+                {
+                    if(logger.isDebugEnabled()) logger.debug("ChainingIterator: Skipping class ["+extCld.getClassNameOfObject()+"]");
+                }
+                else
+                {
+                    if(logger.isDebugEnabled()) logger.debug("ChainingIterator: Adding RsIterator of class ["+extCld.getClassNameOfObject()+"] to ChainingIterator");
 
-                // add the iterator to the chaining iterator.
-                chainingIter.addIterator(factory.createRsIterator(query, extCld, this));
+                    // add the iterator to the chaining iterator.
+                    OJBIterator tmp = factory.createRsIterator(query, extCld, this);
+                    iteratorMap.put(extCld.getFullTableName() ,wrapWithPagingIteratorIfNeeded(tmp, query));
+                }
             }
+            result = new ChainingIterator(iteratorMap.values());
         }
-
-        return chainingIter;
+        return result;
     }
 
     /**
-     * Get an extent aware Iterator based on the ReportQuery
+     * If native paging (LIMIT and/or LIMIT OFFSET) is not supported by the current
+     * database, wrap the current OJBIterator with a paging wrapper.
      *
-     * @param query
-     * @param cld
-     * @return OJBIterator
+     * @param iter The normal iterator.
+     * @param query The query.
+     * @return A paging capable iterator or the specified iterator if native paging
+     * is supported.
      */
-    private OJBIterator getReportQueryIteratorFromQuery(Query query, ClassDescriptor cld) throws PersistenceBrokerException
+    protected OJBIterator wrapWithPagingIteratorIfNeeded(OJBIterator iter, Query query)
     {
-        RsIteratorFactory factory = ReportRsIteratorFactoryImpl.getInstance();
-        OJBIterator result = getRsIteratorFromQuery(query, cld, factory);
-
-        if (query.usePaging())
+        OJBIterator result = iter;
+        boolean isNativeLimitOffset = serviceConnectionManager().getConnectionDescriptor().isNativeLimitOffset();
+        if(query.usePaging())
         {
-            result = new PagingIterator(result, query.getStartAtIndex(), query.getEndAtIndex());
+            Platform platform = serviceConnectionManager().getSupportedPlatform();
+            // limit offset needed, full paging
+            if(query.hasOffset())
+            {
+                if(!isNativeLimitOffset || !platform.supportsOffset())
+                {
+                    result = new PagingIterator(iter, query.getStartAtIndex(), query.getEndAtIndex());
+                }
+            }
+            // only limit
+            else if (query.hasLimit())
+            {
+                if(!isNativeLimitOffset || !platform.supportsLimit())
+                {
+                    result = new PagingIterator(iter, query.getStartAtIndex(), query.getEndAtIndex());
+                }
+            }
         }
-
         return result;
     }
 
@@ -2373,8 +2406,6 @@
             {
                 return getProxyFactory().createProxy(baseClassForProxy,handler);
             }
-
-
         }
         catch (Exception ex)
         {

Modified: db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/metadata/JdbcConnectionDescriptor.java
URL: http://svn.apache.org/viewvc/db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/metadata/JdbcConnectionDescriptor.java?view=diff&rev=513569&r1=513568&r2=513569
==============================================================================
--- db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/metadata/JdbcConnectionDescriptor.java (original)
+++ db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/metadata/JdbcConnectionDescriptor.java Thu Mar  1 16:58:55 2007
@@ -25,6 +25,7 @@
 import org.apache.ojb.broker.platforms.Platform;
 import org.apache.ojb.broker.platforms.PlatformFactory;
 import org.apache.ojb.broker.util.XmlHelper;
+import org.apache.ojb.broker.util.ConvertHelper;
 import org.apache.ojb.broker.util.logging.Logger;
 import org.apache.ojb.broker.util.logging.LoggerFactory;
 
@@ -42,6 +43,7 @@
     public static final int AUTO_COMMIT_IGNORE_STATE = 0;
     public static final int AUTO_COMMIT_SET_TRUE_AND_TEMPORARY_FALSE = 1;
     public static final int AUTO_COMMIT_SET_FALSE = 2;
+    protected static final String ATTRIBUTE_NATIVE_LIMIT_OFFSET = "nativeLimitOffset";
 
     private String m_jcdAlias;
     private String m_Dbms;
@@ -58,6 +60,7 @@
     private boolean defaultConnection = false;
     private int useAutoCommit = AUTO_COMMIT_SET_TRUE_AND_TEMPORARY_FALSE;
     private boolean ignoreAutoCommitExceptions = false;
+    private Boolean nativeLimitOffset;
     private PBKey pbKey;
     private ConnectionPoolDescriptor cpd;
     private SequenceDescriptor sequenceDescriptor;
@@ -415,6 +418,42 @@
     	m_batchMode = flag;
     }
 
+    /**
+     * Get the query limit/offset mode. If set <em>true</em> OJB use the native database specific
+     * LIMIT and OFFSET arguments for limit and paging queries (if it's supported by the DB and
+     * OJB's {@link Platform} implementation class). If set <em>false</em> OJB simulate limit
+     * and paging by a specific result set iterator (this can result in bad performance on big
+     * result sets).
+     *
+     * @return The current used limit and paging mode.
+     */
+    public boolean isNativeLimitOffset()
+    {
+        if(nativeLimitOffset == null)
+        {
+            nativeLimitOffset = ConvertHelper.toBoolean(getAttribute(ATTRIBUTE_NATIVE_LIMIT_OFFSET));
+            // by default we support native limit/paging
+            if(nativeLimitOffset == null)
+            {
+                nativeLimitOffset = Boolean.TRUE;
+            }
+        }
+        return nativeLimitOffset.booleanValue();
+    }
+
+    /**
+     * Sets the query limit/paging mode - see {@link #isNativeLimitOffset()}.
+     *
+     * @param nativeLimitOffset The limit paging mode.
+     */
+    public void setNativeLimitOffset(boolean nativeLimitOffset)
+    {
+        this.nativeLimitOffset = nativeLimitOffset ? Boolean.TRUE : Boolean.FALSE;
+    }
+
+    /**
+     * Returns the associated {@link org.apache.ojb.broker.platforms.Platform}.
+     */
     public Platform getPlatform()
     {
         // no need to synchronize, dosen't matter if we use different instances

Modified: db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/platforms/Platform.java
URL: http://svn.apache.org/viewvc/db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/platforms/Platform.java?view=diff&rev=513569&r1=513568&r2=513569
==============================================================================
--- db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/platforms/Platform.java (original)
+++ db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/platforms/Platform.java Thu Mar  1 16:58:55 2007
@@ -18,6 +18,7 @@
 import org.apache.ojb.broker.metadata.JdbcConnectionDescriptor;
 import org.apache.ojb.broker.metadata.FieldDescriptor;
 import org.apache.ojb.broker.query.LikeCriteria;
+import org.apache.ojb.broker.query.Query;
 
 import java.sql.CallableStatement;
 import java.sql.Connection;
@@ -34,7 +35,6 @@
  * each jdbc-connection-descriptor entry in the repository file.
  *
  * @version $Id$
- * @author	 Thomas Mahler
  */
 public interface Platform
 {
@@ -224,33 +224,80 @@
      */
     String getLastInsertIdentityQuery(String tableName);
 
+
+    //===================================================================
+    // Limit and paging methods
+    //===================================================================
+
+    /**
+     * Answer <em>true</em> if LIMIT or equivalent is supported.
+     */
+    boolean supportsLimit();
+
+    /**
+     * Add the LIMIT to the SQL.
+     */
+    StringBuffer addLimitSql(Query query, StringBuffer anSqlString);
+
+    /**
+     * Answer <em>true</em> if LIMIT OFFSET or equivalent is supported.
+     */
+    boolean supportsOffset();
+
+    /**
+     * Add the LIMIT with LIMIT OFFSET to the SQL.
+     */
+    StringBuffer addPagingSql(Query query, StringBuffer anSqlString);
+
+    /**
+     * Builds the platform dependend LIMIT OFFSET value of the
+     * {@link org.apache.ojb.broker.query.Query#getStartAtIndex()} value
+     * (Note: take care of include/exclude boundary conditions).
+     *
+     * @param query The query.
+     * @return The platform dependend limit offset value.
+     */
+    int buildOffset(Query query);
+
     /**
-     * Answer true if LIMIT or equivalent is supported
-     * <b> SQL-Paging is not yet supported </b>
+     * Builds the platform dependend LIMIT value of the
+     * {@link org.apache.ojb.broker.query.Query#getEndAtIndex()} value
+     * (Note: take care of include/exclude boundary conditions).
+     *
+     * @param query The query.
+     * @return The platform dependend limit value.
      */
-    boolean supportsPaging();
+    int buildLimit(Query query);
 
     /**
-     * Add the LIMIT or equivalent to the SQL 
-     * <b> SQL-Paging is not yet supported </b>
+     * Returns the order of the LIMIT and OFFSET value setting
+     * in the LIMIT/OFFSET clause (e.g. in "LIMIT ?, ?").
+     * If <em>true</em> the limit argument have to be set before the offset
+     * argument. If <em>false</em> the reverse order is mandatory.
+     *
+     * @return The order of the LIMIT/OFFSET values.
      */
-    void addPagingSql(StringBuffer anSqlString);
+    boolean limitBeforeOffset();
 
     /**
-     * Answer true if the LIMIT parameters are bound before the query parameters
-     * <b> SQL-Paging is not yet supported </b>
+     * Returns <em>true</em> if the LIMIT/OFFSET clause is added after the
+     * SELECT-expression (e.g. "SELECT TOP n ..."). If <em>false</em> the
+     * LIMIT/OFFSET clause is added after the ORDER BY clause (e.g. "SELECT ... ORDER BY 1 LIMIT n,m").
      */
-    boolean bindPagingParametersFirst();
+    boolean limitAfterSelect();
 
     /**
-     * Bind the Paging Parameters
-     * <b> SQL-Paging is not yet supported </b>
-     * @param ps
-     * @param index parameter index
-     * @param startAt
-     * @param endAt
+     * If <em>true</em> the LIMIT/OFFSET values will be embedded in
+     * the limit/paging SQL-query when calling {@link #addLimitSql(org.apache.ojb.broker.query.Query, StringBuffer)}
+     * or {@link #addPagingSql(org.apache.ojb.broker.query.Query, StringBuffer)}. If <em>false</em> prepared statement
+     * paceholder "?" are used in these methods and OJB have bind the values.
+     *
+     * @return Whether or not the LIMIT/OFFSET values will be embedded in the SQL-query.
      */
-    int bindPagingParameters(PreparedStatement ps, int index, int startAt, int endAt) throws SQLException;
+    boolean limitOffsetValuesEmbedded();
+
+    //===================================================================
+
 
     /**
      * Whether the platform supports a COUNT DISTINCT across multiple columns.
@@ -326,4 +373,20 @@
      * @return The post prepared column value.
      */
     public Object postPrepareReadInValue(FieldDescriptor fld, Object value);
+
+    /**
+     * If <em>true</em> auto-generated keys can be retrieved after a statement
+     * has been executed.
+     */
+    boolean supportsGetGeneratedKeys();
+
+    /**
+     * Show same behavior as <em>Statement.getGeneratedKeys()</em> - JDBC quotation:
+     * <br/>
+     * "Retrieves any auto-generated keys created as a result of executing this Statement object.
+     * If this Statement object did not generate any keys, an empty ResultSet object is returned."
+     * @param stmt
+     * @return The generated keys.
+     */
+    ResultSet getGeneratedKeys(Statement stmt) throws SQLException;
 }

Modified: db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/platforms/PlatformDb2Impl.java
URL: http://svn.apache.org/viewvc/db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/platforms/PlatformDb2Impl.java?view=diff&rev=513569&r1=513568&r2=513569
==============================================================================
--- db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/platforms/PlatformDb2Impl.java (original)
+++ db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/platforms/PlatformDb2Impl.java Thu Mar  1 16:58:55 2007
@@ -22,6 +22,7 @@
 
 import org.apache.ojb.broker.util.sequence.SequenceManagerHelper;
 import org.apache.ojb.broker.metadata.JdbcConnectionDescriptor;
+import org.apache.ojb.broker.query.Query;
 
 /**
  * This class extends <code>PlatformDefaultImpl</code> and defines specific
@@ -260,5 +261,77 @@
         // work with DB2 Z/os v7 (reported on user-list) thus rollback to
         // 
         return "select IDENTITY_VAL_LOCAL() from sysibm.sysdummy1";
+    }
+
+
+
+    public boolean supportsLimit()
+    {
+        return true;
+    }
+
+    public StringBuffer addLimitSql(Query query, StringBuffer anSqlString)
+    {
+        /*
+        see http://troels.arvin.dk/db/rdbms/
+        "When doing casual work, it's often easier to use DB2's non-standard
+        SELECT ... FETCH FIRST n ROWS ONLY construct."
+        Seems parameter marker '?' are not allowed.
+        */
+        return anSqlString
+                .append(" FETCH FIRST ")
+                .append(buildLimit(query))
+                .append(" ROWS ONLY");
+    }
+
+    public boolean supportsOffset()
+    {
+        return false;
+    }
+
+    public StringBuffer addPagingSql(Query query, StringBuffer anSqlString)
+    {
+        // TODO: native paging support
+        // not supported
+        throw new UnsupportedOperationException("OFFSET is not supported by this platform" +
+                " implementation class (" + this.getClass().getName() +
+                "), please disable the native limit/offset flag in the" +
+                " connection metadata mapping file using attribute 'nativeLimitOffset'" +
+                " then OJB will use specific paging/limit result set iterator to simulate it!");
+    }
+
+    public int buildLimit(Query query)
+    {
+        int result = 0;
+        if(query.hasLimit())
+        {
+            return query.getEndAtIndex();
+        }
+        else if(query.hasOffset())
+        {
+            return MAX_LIMIT_VALUE;
+        }
+        return result;
+    }
+
+    public int buildOffset(Query query)
+    {
+        return query.getStartAtIndex();
+    }
+
+    public boolean limitOffsetValuesEmbedded()
+    {
+        // parameter marker '?' are not allowed, we embed limit/offset values
+        return true;
+    }
+
+    public boolean limitBeforeOffset()
+    {
+        return false;
+    }
+
+    public boolean limitAfterSelect()
+    {
+        return false;
     }
 }

Modified: db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/platforms/PlatformDefaultImpl.java
URL: http://svn.apache.org/viewvc/db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/platforms/PlatformDefaultImpl.java?view=diff&rev=513569&r1=513568&r2=513569
==============================================================================
--- db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/platforms/PlatformDefaultImpl.java (original)
+++ db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/platforms/PlatformDefaultImpl.java Thu Mar  1 16:58:55 2007
@@ -36,6 +36,7 @@
 import org.apache.ojb.broker.metadata.FieldDescriptor;
 import org.apache.ojb.broker.metadata.JdbcConnectionDescriptor;
 import org.apache.ojb.broker.query.LikeCriteria;
+import org.apache.ojb.broker.query.Query;
 import org.apache.ojb.broker.util.SqlHelper;
 import org.apache.ojb.broker.util.logging.Logger;
 import org.apache.ojb.broker.util.logging.LoggerFactory;
@@ -54,14 +55,23 @@
     private static final String INITIALIZATION_CHECK_AUTOCOMMIT = "initializationCheck";
     private static final String FALSE_STR = "false";
 
+    /**
+     * Doesn't make sense to use the maximal possible integer as maximal limit value,
+     * thus OJB use '900000000'. Don't use Integer.MAX because not all DB INTEGER
+     * data type support it.
+     */
+    protected static final int MAX_LIMIT_VALUE = 900000000;
+
     protected boolean m_batchUpdatesChecked = false;
     protected boolean m_supportsBatchUpdates = false;
-    protected Boolean locatorsUpdateCopy;
+    private Boolean locatorsUpdateCopy;
+    private Boolean supportsGetGeneratedKeys;
     protected JdbcConnectionDescriptor jcd;
 
     public PlatformDefaultImpl(JdbcConnectionDescriptor jcd)
     {
         this.jcd = jcd;
+
     }
 
     public boolean supportsBatchOperations()
@@ -98,6 +108,40 @@
         }
     }
 
+    /**
+     * Sets platform information for if the jdbc driver/db combo support
+     * get auto-generated keys. Will only be checked once.
+     *
+     * @param conn
+     */
+    protected void checkForGetGeneratedKeys(Connection conn)
+    {
+        if(supportsGetGeneratedKeys == null)
+        {
+            try
+            {
+//#ifdef JDBC30
+
+                DatabaseMetaData meta = conn.getMetaData();
+                boolean result = meta.supportsGetGeneratedKeys();
+
+//#else
+
+/*
+                boolean result = false;
+*/
+
+//#endif
+                supportsGetGeneratedKeys = result ? Boolean.TRUE : Boolean.FALSE;
+            }
+            catch(Exception e)
+            {
+                log.warn("Get auto-generated keys support check failed", e);
+                supportsGetGeneratedKeys = Boolean.FALSE;
+            }
+        }
+    }
+
     public void afterStatementCreate(Statement stmt) throws PlatformException
     {
         //noop
@@ -164,6 +208,7 @@
     public void initializeJdbcConnection(Connection conn) throws PlatformException
     {
         if(jcd.getBatchMode()) checkForBatchSupport(conn);
+        checkForGetGeneratedKeys(conn);
 
         switch(jcd.getUseAutoCommit())
         {
@@ -499,42 +544,76 @@
         throw new UnsupportedOperationException("This feature is not supported by this implementation");
     }
 
-    /**
-     * @see org.apache.ojb.broker.platforms.Platform#addPagingSql(java.lang.StringBuffer)
-     */
-    public void addPagingSql(StringBuffer anSqlString)
+
+
+    public boolean supportsLimit()
     {
-        // do nothing
+        return false;
     }
 
-    /**
-     * @see org.apache.ojb.broker.platforms.Platform#bindPagingParametersFirst()
-     */
-    public boolean bindPagingParametersFirst()
+    public StringBuffer addLimitSql(Query query, StringBuffer anSqlString)
+    {
+        // not supported
+        throw new UnsupportedOperationException("LIMIT/OFFSET is not supported by this platform" +
+                " implementation class (" + this.getClass().getName() +
+                "), please disable the native limit/offset flag in the" +
+                " connection metadata mapping file using attribute 'nativeLimitOffset'" +
+                " then OJB will use specific paging/limit result set iterator to simulate it!");
+    }
+
+    public boolean supportsOffset()
     {
         return false;
     }
 
-    /**
-     * @see org.apache.ojb.broker.platforms.Platform#supportsPaging()
-     */
-    public boolean supportsPaging()
+    public StringBuffer addPagingSql(Query query, StringBuffer anSqlString)
+    {
+        // not supported
+        throw new UnsupportedOperationException("LIMIT/OFFSET is not supported by this platform" +
+                " implementation class (" + this.getClass().getName() +
+                "), please disable the native limit/offset flag in the" +
+                " connection metadata mapping file using attribute 'nativeLimitOffset'" +
+                " then OJB will use specific paging/limit result set iterator to simulate it!");
+    }
+
+    public int buildOffset(Query query)
+    {
+        // if start index not set return 0
+        return query.hasOffset() ? query.getStartAtIndex() - 1 : 0;
+    }
+
+    public int buildLimit(Query query)
+    {
+        if(query.hasLimit())
+        {
+            return query.getEndAtIndex() - (query.getStartAtIndex() > 0 ? query.getStartAtIndex() - 1 : 0);
+        } // offset set without limit, we return all rows starting with the offset
+        else if(query.hasOffset())
+        {
+            return MAX_LIMIT_VALUE;
+        }
+        else
+        {
+            return 0;
+        }
+    }
+
+    public boolean limitBeforeOffset()
     {
         return false;
     }
 
-    /**
-     * @see org.apache.ojb.broker.platforms.Platform#bindPagingParameters(java.sql.PreparedStatement, int, int, int)
-     */
-    public int bindPagingParameters(PreparedStatement ps, int index, int startAt, int endAt) throws SQLException
+    public boolean limitAfterSelect()
     {
-        ps.setInt(index, startAt - 1);              // zero based start
-        index++;
-        ps.setInt(index, endAt - (startAt - 1));    // number of rows to fetch
-        index++;
-        return index;
+        return false;
     }
 
+    public boolean limitOffsetValuesEmbedded()
+    {
+        return false;
+    }
+
+
     /**
      * Answer the Character for Concatenation
      */
@@ -702,4 +781,28 @@
     {
         return value;
     }
+
+    public boolean supportsGetGeneratedKeys()
+    {
+        return supportsGetGeneratedKeys != null && supportsGetGeneratedKeys.booleanValue();
+    }
+
+    public ResultSet getGeneratedKeys(Statement stmt) throws SQLException
+    {
+
+//#ifdef JDBC30
+   
+        return stmt.getGeneratedKeys();
+
+//#else
+
+/*
+        // not supported
+        throw new UnsupportedOperationException("Not supported in used JDBC-specification version");
+*/
+
+//#endif
+
+    }
+    
 }

Modified: db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/platforms/PlatformHsqldbImpl.java
URL: http://svn.apache.org/viewvc/db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/platforms/PlatformHsqldbImpl.java?view=diff&rev=513569&r1=513568&r2=513569
==============================================================================
--- db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/platforms/PlatformHsqldbImpl.java (original)
+++ db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/platforms/PlatformHsqldbImpl.java Thu Mar  1 16:58:55 2007
@@ -19,6 +19,7 @@
 
 import org.apache.ojb.broker.util.sequence.SequenceManagerHelper;
 import org.apache.ojb.broker.metadata.JdbcConnectionDescriptor;
+import org.apache.ojb.broker.query.Query;
 
 /**
  * This class extends <code>PlatformDefaultImpl</code> and defines specific
@@ -88,26 +89,29 @@
         return LAST_INSERT;
     }
 
-    /* (non-Javadoc)
-    * @see org.apache.ojb.broker.platforms.Platform#addPagingSql(java.lang.StringBuffer)
-    */
-    public void addPagingSql(StringBuffer anSqlString)
+
+
+    public boolean supportsLimit()
     {
-        anSqlString.insert(6, " LIMIT ? ? ");
+        return true;
     }
 
-    /* (non-Javadoc)
-     * @see org.apache.ojb.broker.platforms.Platform#bindPagingParametersFirst()
-     */
-    public boolean bindPagingParametersFirst()
+    public StringBuffer addLimitSql(Query query, StringBuffer anSqlString)
+    {
+        return anSqlString.append(" LIMIT ?");
+    }
+
+    public boolean supportsOffset()
     {
         return true;
     }
 
-    /* (non-Javadoc)
-     * @see org.apache.ojb.broker.platforms.Platform#supportsPaging()
-     */
-    public boolean supportsPaging()
+    public StringBuffer addPagingSql(Query query, StringBuffer anSqlString)
+    {
+        return anSqlString.append(" LIMIT ? OFFSET ?");
+    }
+
+    public boolean limitBeforeOffset()
     {
         return true;
     }
@@ -116,6 +120,8 @@
     {
         return false;
     }
+
+    
 
     public String createSequenceQuery(String sequenceName, Properties prop)
     {

Modified: db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/platforms/PlatformMsSQLServerImpl.java
URL: http://svn.apache.org/viewvc/db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/platforms/PlatformMsSQLServerImpl.java?view=diff&rev=513569&r1=513568&r2=513569
==============================================================================
--- db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/platforms/PlatformMsSQLServerImpl.java (original)
+++ db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/platforms/PlatformMsSQLServerImpl.java Thu Mar  1 16:58:55 2007
@@ -21,6 +21,8 @@
 import java.sql.SQLException;
 
 import org.apache.ojb.broker.metadata.JdbcConnectionDescriptor;
+import org.apache.ojb.broker.query.Query;
+import org.apache.commons.lang.StringUtils;
 
 /**
  * This class extends <code>PlatformDefaultImpl</code> and defines specific behavior for the
@@ -93,5 +95,71 @@
     protected String getQuotedName(String aString)
     {
         return '[' + aString + ']';
+    }
+
+
+
+    public boolean supportsLimit()
+    {
+        return true;
+    }
+
+    public StringBuffer addLimitSql(Query query, StringBuffer anSqlString)
+    {
+        /*
+         See http://troels.arvin.dk/db/rdbms/#select-top-n-standard
+         SELECT TOP 3 WITH TIES * FROM person ORDER BY age ASC
+        */
+        return new StringBuffer(StringUtils.replace(anSqlString.toString(), "SELECT", "SELECT TOP ?", 1));
+    }
+
+    public boolean supportsOffset()
+    {
+        return true;
+    }
+
+    public StringBuffer addPagingSql(Query query, StringBuffer anSqlString)
+    {
+        /*
+        See http://troels.arvin.dk/db/rdbms/#select-top-n-standard
+        SELECT * FROM (
+            SELECT TOP n * FROM (
+                SELECT TOP z columns      -- (z=n+skip)
+                FROM tablename ORDER BY key ASC)
+            AS FOO ORDER BY key DESC -- ('FOO' may be anything)
+        ) AS BAR ORDER BY key ASC    -- ('BAR' may be anything)
+        */
+        StringBuffer tmp = new StringBuffer(StringUtils.replace(
+                anSqlString.toString(), "SELECT", "SELECT * FROM ( SELECT TOP ? * FROM ( SELECT TOP ?", 1));
+        return tmp.append(") AS FOO ORDER BY key DESC ) AS BAR ORDER BY key ASC");
+    }
+
+    public int buildLimit(Query query)
+    {
+        int result = 0;
+        if(query.hasLimit())
+        {
+            return query.getEndAtIndex();
+        }
+        else if(query.hasOffset())
+        {
+            return MAX_LIMIT_VALUE;
+        }
+        return result;
+    }
+
+    public int buildOffset(Query query)
+    {
+        return super.buildOffset(query);
+    }
+
+    public boolean limitBeforeOffset()
+    {
+        return false;
+    }
+
+    public boolean limitAfterSelect()
+    {
+        return true;
     }
 }

Modified: db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/platforms/PlatformMySQLImpl.java
URL: http://svn.apache.org/viewvc/db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/platforms/PlatformMySQLImpl.java?view=diff&rev=513569&r1=513568&r2=513569
==============================================================================
--- db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/platforms/PlatformMySQLImpl.java (original)
+++ db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/platforms/PlatformMySQLImpl.java Thu Mar  1 16:58:55 2007
@@ -26,6 +26,7 @@
 import java.sql.Connection;
 
 import org.apache.ojb.broker.query.LikeCriteria;
+import org.apache.ojb.broker.query.Query;
 import org.apache.ojb.broker.metadata.FieldDescriptor;
 import org.apache.ojb.broker.metadata.JdbcConnectionDescriptor;
 import org.apache.commons.lang.SerializationUtils;
@@ -140,24 +141,34 @@
         return LAST_INSERT + tableName + LIMIT;
     }
 
-    /*
-	 * (non-Javadoc)
-	 * 
-	 * @see org.apache.ojb.broker.platforms.Platform#addPagingSql(java.lang.StringBuffer)
-	 */
-    public void addPagingSql(StringBuffer anSqlString)
+    public boolean supportsLimit()
     {
-        anSqlString.append(" LIMIT ?,?");
+        return true;
     }
 
-    /*
-	 * (non-Javadoc)
-	 * 
-	 * @see org.apache.ojb.broker.platforms.Platform#supportsPaging()
-	 */
-    public boolean supportsPaging()
+    public StringBuffer addLimitSql(Query query, StringBuffer anSqlString)
+    {
+        return anSqlString.append(" LIMIT ?");
+    }
+
+    public boolean supportsOffset()
     {
         return true;
+    }
+
+    public StringBuffer addPagingSql(Query query, StringBuffer anSqlString)
+    {
+        return anSqlString.append(" LIMIT ?, ?");
+    }
+
+    public boolean limitAfterSelect()
+    {
+        return false;
+    }
+
+    public boolean limitBeforeOffset()
+    {
+        return false;
     }
 
     /**



---------------------------------------------------------------------
To unsubscribe, e-mail: ojb-dev-unsubscribe@db.apache.org
For additional commands, e-mail: ojb-dev-help@db.apache.org


Mime
View raw message