Index: src/cayenne/java/org/objectstyle/cayenne/access/IncrementalFaultList.java
===================================================================
RCS file: /cvsroot/cayenne/cayenne/src/cayenne/java/org/objectstyle/cayenne/access/IncrementalFaultList.java,v
retrieving revision 1.25
diff -w -u -r1.25 IncrementalFaultList.java
--- src/cayenne/java/org/objectstyle/cayenne/access/IncrementalFaultList.java	27 Jul 2003 15:15:39 -0000	1.25
+++ src/cayenne/java/org/objectstyle/cayenne/access/IncrementalFaultList.java	26 Sep 2003 18:07:51 -0000
..-62,6 +62,7 @@
 import java.util.List;
 import java.util.ListIterator;
 import java.util.Map;
+import java.util.NoSuchElementException;
 
 import org.objectstyle.cayenne.CayenneException;
 import org.objectstyle.cayenne.CayenneRuntimeException;
..-97,6 +98,16 @@
     protected SelectQuery internalQuery;
     protected int unfetchedObjects;
 
+    /** size fetches will be limited to in order to avoid where clause limitations */
+    protected int fetchSize = 10000;
+    // Don't confuse this with the JDBC ResultSet fetch size setting - this controls
+    // the where clause generation that is necessary to fetch specific records a page
+    // at a time.  Some JDBC Drivers/Databases may have limits on statement length
+    // or complexity of the where clause - e.g., PostgreSQL having a default limit of 10,000
+    // nested expressions.
+    //
+    // TODO: make configurable?
+    
     /**
      * Creates a new list copying settings from another list.
      * Elements WILL NOT be copied or fetched.
..-106,6 +117,7 @@
         this.internalQuery = list.internalQuery;
         this.dataContext = list.dataContext;
         this.rootEntity = list.rootEntity;
+        this.fetchSize = list.fetchSize;
         elements = Collections.synchronizedList(new ArrayList());
     }
 
..-240,12 +252,19 @@
                 return;
             }
 
+            // fetch the range of objects in fetchSize chunks
+            List objects = new ArrayList(1);
+            int fetchBegin = 0;
+            for (int fetchEnd = Math.min(quals.size(), fetchSize); fetchBegin < quals.size(); fetchEnd += Math.min(fetchSize, (quals.size()-fetchEnd)))
+            {
             SelectQuery query =
                 new SelectQuery(
                     rootEntity.getName(),
-                    ExpressionFactory.joinExp(Expression.OR, quals));
+                        ExpressionFactory.joinExp(Expression.OR, quals.subList(fetchBegin, fetchEnd)));
 
-            List objects = dataContext.performQuery(query);
+                objects.addAll(dataContext.performQuery(query));
+                fetchBegin = fetchEnd;                
+            }
 
             // sanity check - database data may have changed
             if (objects.size() < ids.size()) {
..-335,6 +354,18 @@
     }
 
     /**
+     * Get the upper bound on the number of records to resolve in one round
+     * trip to the database.  This setting governs the size/complexity of 
+     * the where clause generated to retrieve the next page of records.  
+     * If the fetch size is less than the page size, then multiple fetches 
+     * will be made to resolve a page.
+     *..eturn int
+     */
+    public int getFetchSize() {
+        return fetchSize;
+    }
+
+    /**
      * Returns the dataContext.
      *..eturn DataContext
      */
..-351,30 +382,157 @@
     }
 
     /**
-     * This method would resolve all unresolved objects and then return
-     * a list iterator over an internal list.
+     * Returns a list iterator for this list. DataObjects are resolved a page 
+     * (according to getPageSize()) at a time as necessary - when retrieved 
+     * with next() or previous().
      */
     public ListIterator listIterator() {
-        resolveAll();
-        return elements.listIterator();
+        // by virtue of get(index)'s implementation, resolution of ids into 
+        // objects will occur on pageSize boundaries as necessary.
+        return new ListIterator() {
+            int listIndex = 0;
+            
+            public void add(Object o) {
+                throw new UnsupportedOperationException(
+                            "add operation not supported");
+            }
+            
+            public boolean hasNext() {
+                return (listIndex < elements.size());
+            }
+            
+            public boolean hasPrevious() {
+                return (listIndex > 0);
+            }
+            
+            public Object next() {
+                if (listIndex >= elements.size()) 
+                    throw new NoSuchElementException(
+                                "at the end of the list");
+                    
+                return get(listIndex++);
+            }
+            
+            public int nextIndex() {
+                return listIndex;
+            }
+            
+            public Object previous() {
+                if (listIndex < 1)
+                    throw new NoSuchElementException(
+                                "at the beginning of the list");
+                
+                return get(--listIndex);
+            }
+            
+            public int previousIndex() {
+                return (listIndex - 1);
+            }
+            
+            public void remove() {
+                throw new UnsupportedOperationException(
+                            "remove operation not supported");             
+            }
+            
+            public void set(Object o) {
+                throw new UnsupportedOperationException(
+                            "set operation not supported");
+            }
+        };
     }
 
     /**
-     * This method would resolve all unresolved objects and then return
-     * a list iterator over an internal list.
+     * Returns a list iterator of the elements in this list (in proper 
+     * sequence), starting at the specified position in this list. The 
+     * specified index indicates the first element that would be returned 
+     * by an initial call to the next method. An initial call to the 
+     * previous method would return the element with the specified index 
+     * minus one. 
+     * 
+     * DataObjects are resolved a page (according to getPageSize()) at a 
+     * time as necessary - when retrieved with next() or previous().
      */
-    public ListIterator listIterator(int index) {
-        resolveAll();
-        return elements.listIterator(index);
+    public ListIterator listIterator(final int index) {
+        // by virtue of get(index)'s implementation, resolution of ids into 
+        // objects will occur on pageSize boundaries as necessary.
+        return new ListIterator() {
+            int listIndex = index;
+            
+            public void add(Object o) {
+                throw new UnsupportedOperationException(
+                            "add operation not supported");
+            }
+            
+            public boolean hasNext() {
+                return (listIndex < elements.size());
+            }
+            
+            public boolean hasPrevious() {
+                return (listIndex > 0);
+            }
+            
+            public Object next() {
+                if (listIndex >= elements.size()) 
+                    throw new NoSuchElementException(
+                                "at the end of the list");
+                    
+                return get(listIndex++);
+            }
+            
+            public int nextIndex() {
+                return listIndex;
+            }
+            
+            public Object previous() {
+                if (listIndex < 1)
+                    throw new NoSuchElementException(
+                                "at the beginning of the list");
+                
+                return get(--listIndex);
+            }
+            
+            public int previousIndex() {
+                return (listIndex - 1);
+            }
+            
+            public void remove() {
+                throw new UnsupportedOperationException(
+                            "remove operation not supported");             
+            }
+            
+            public void set(Object o) {
+                throw new UnsupportedOperationException(
+                            "set operation not supported");
+            }
+        };        
     }
 
     /**
-     * This method would resolve all unresolved objects and then return
-     * an iterator over an internal list.
+     * Return an iterator for this list. DataObjects are resolved a page 
+     * (according to getPageSize()) at a time as necessary - when retrieved 
+     * with next().
      */
     public Iterator iterator() {
-        resolveAll();
-        return elements.iterator();
+        // by virtue of get(index)'s implementation, resolution of ids into 
+        // objects will occur on pageSize boundaries as necessary.
+        return new Iterator() {
+            int listIndex = 0;
+
+            public boolean hasNext() {
+                return (listIndex < elements.size());                
+            }
+            
+            public Object next() {
+                if (listIndex >= elements.size())
+                    throw new NoSuchElementException("no more elements");
+                    
+                return get(listIndex++); 
+            }
+            
+            public void remove() { 
+                throw new UnsupportedOperationException("remove not supported.");
+            }
+        };
     }
 
     /**