You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cayenne.apache.org by aa...@apache.org on 2008/12/01 10:58:20 UTC

svn commit: r722018 - in /cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src: main/java/org/apache/cayenne/access/ main/java/org/apache/cayenne/access/jdbc/ main/java/org/apache/cayenne/access/util/ test/java/org/apache/cayenne/access/ test/ja...

Author: aadamchik
Date: Mon Dec  1 01:58:11 2008
New Revision: 722018

URL: http://svn.apache.org/viewvc?rev=722018&view=rev
Log:
CAY-1140 Store ObjEntity name in the DataRow

Changing ResultIterator to return an Object for each row to push down the logic of determining the result structure
from DataDomain level to the JDBC level

Added:
    cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/jdbc/CompoundRowReader.java
    cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/jdbc/EntityRowReader.java
    cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/jdbc/ScalarRowReader.java
Modified:
    cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/DataDomainFlushObserver.java
    cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/DataDomainQueryAction.java
    cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/DataPort.java
    cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/IncrementalFaultList.java
    cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/ResultIterator.java
    cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/TransactionResultIteratorDecorator.java
    cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/jdbc/BaseSQLAction.java
    cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/jdbc/JDBCResultIterator.java
    cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/jdbc/LimitResultIterator.java
    cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/jdbc/SQLTemplateAction.java
    cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/jdbc/SelectAction.java
    cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/util/DistinctResultIterator.java
    cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/access/DataContextSQLTemplateTest.java
    cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/access/DataContextTest.java
    cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/access/jdbc/JDBCResultIteratorTest.java

Modified: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/DataDomainFlushObserver.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/DataDomainFlushObserver.java?rev=722018&r1=722017&r2=722018&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/DataDomainFlushObserver.java (original)
+++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/DataDomainFlushObserver.java Mon Dec  1 01:58:11 2008
@@ -59,7 +59,7 @@
         // read and close the iterator before doing anything else
         List<DataRow> keys;
         try {
-            keys = keysIterator.dataRows(true);
+            keys = keysIterator.allRows(true);
         }
         catch (CayenneException ex) {
             throw new CayenneRuntimeException("Error reading primary key", Util

Modified: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/DataDomainQueryAction.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/DataDomainQueryAction.java?rev=722018&r1=722017&r2=722018&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/DataDomainQueryAction.java (original)
+++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/DataDomainQueryAction.java Mon Dec  1 01:58:11 2008
@@ -530,7 +530,7 @@
     public void nextGeneratedDataRows(Query query, ResultIterator keysIterator) {
         if (keysIterator != null) {
             try {
-                nextDataRows(query, keysIterator.dataRows(true));
+                nextDataRows(query, keysIterator.allRows(true));
             }
             catch (CayenneException ex) {
                 // don't throw here....

Modified: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/DataPort.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/DataPort.java?rev=722018&r1=722017&r2=722018&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/DataPort.java (original)
+++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/DataPort.java Mon Dec  1 01:58:11 2008
@@ -27,6 +27,7 @@
 import java.util.Map;
 
 import org.apache.cayenne.CayenneException;
+import org.apache.cayenne.DataRow;
 import org.apache.cayenne.access.util.IteratedSelectObserver;
 import org.apache.cayenne.map.DbEntity;
 import org.apache.cayenne.query.InsertBatchQuery;
@@ -228,7 +229,7 @@
 
                     currentRow++;
 
-                    Map<String, Object> nextRow = result.nextDataRow();
+                    Map<String, Object> nextRow = (DataRow) result.nextRow();
                     insert.add(nextRow);
                 }
 

Modified: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/IncrementalFaultList.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/IncrementalFaultList.java?rev=722018&r1=722017&r2=722018&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/IncrementalFaultList.java (original)
+++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/IncrementalFaultList.java Mon Dec  1 01:58:11 2008
@@ -218,13 +218,13 @@
             ResultIterator it = dataContext.performIteratedQuery(query);
             try {
 
-                rowWidth = it.getDataRowWidth();
+                rowWidth = it.getResultSetWidth();
 
                 // resolve first page if we can
                 if (resolvesFirstPage) {
                     // read first page completely, the rest as ObjectIds
                     for (int i = 0; i < pageSize && it.hasNextRow(); i++) {
-                        elementsList.add(it.nextDataRow());
+                        elementsList.add(it.nextRow());
                         lastResolved++;
                     }
 

Modified: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/ResultIterator.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/ResultIterator.java?rev=722018&r1=722017&r2=722018&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/ResultIterator.java (original)
+++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/ResultIterator.java Mon Dec  1 01:58:11 2008
@@ -31,16 +31,30 @@
  * execution. Usually a ResultIterator is supported by an open java.sql.ResultSet,
  * therefore most of the methods would throw checked exceptions. ResultIterators must be
  * explicitly closed when the user is done working with them.
+ * <p>
+ * Result "rows", depending on the query, may be represented as scalar values, DataRows,
+ * or Object[] arrays containing a mix of scalars and DataRows.
+ * </p>
  */
 public interface ResultIterator {
 
     /**
      * Returns all unread data rows from ResultSet and closes this iterator if asked to do
      * so.
+     * 
+     * @deprecated since 3.0 use {@link #allRows(boolean)}.
      */
     List<DataRow> dataRows(boolean close) throws CayenneException;
 
     /**
+     * Returns all yet unread rows from ResultSet and closes this iterator if asked to do
+     * so.
+     * 
+     * @since 3.0
+     */
+    List allRows(boolean close) throws CayenneException;
+
+    /**
      * Returns true if there is at least one more record that can be read from the
      * iterator.
      */
@@ -48,10 +62,20 @@
 
     /**
      * Returns the next result row as a Map.
+     * 
+     * @deprecated since 3.0 use {@link #nextRow()}.
      */
     Map<String, Object> nextDataRow() throws CayenneException;
 
     /**
+     * Returns the next result row that is, depending on the query, may be a scalar value,
+     * a DataRow, or an Object[] array containing a mix of scalars and DataRows.
+     * 
+     * @since 3.0
+     */
+    Object nextRow() throws CayenneException;
+
+    /**
      * Returns a map of ObjectId values from the next result row. Primary key columns are
      * determined from the provided DbEntity.
      * 
@@ -72,10 +96,17 @@
 
     /**
      * Skips current data row instead of reading it.
+     * 
+     * @deprecated since 3.0 use {@link #skipRow()} instead.
      */
     void skipDataRow() throws CayenneException;
 
     /**
+     * @since 3.0
+     */
+    void skipRow() throws CayenneException;
+
+    /**
      * Closes ResultIterator and associated ResultSet. This method must be called
      * explicitly when the user is finished processing the records. Otherwise unused
      * database resources will not be released properly.
@@ -86,6 +117,14 @@
      * Returns the number of columns in the result row.
      * 
      * @since 1.0.6
+     * @deprecated since 3.0 in favor of {@link #getResultSetWidth()}.
      */
     int getDataRowWidth();
+
+    /**
+     * Returns a number of columns in the underlying ResultSet.
+     * 
+     * @since 3.0
+     */
+    int getResultSetWidth();
 }

Modified: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/TransactionResultIteratorDecorator.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/TransactionResultIteratorDecorator.java?rev=722018&r1=722017&r2=722018&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/TransactionResultIteratorDecorator.java (original)
+++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/TransactionResultIteratorDecorator.java Mon Dec  1 01:58:11 2008
@@ -60,18 +60,28 @@
             throw new CayenneException(e);
         }
         finally {
-            if(Transaction.getThreadTransaction() == tx) {
+            if (Transaction.getThreadTransaction() == tx) {
                 Transaction.bindThreadTransaction(null);
             }
         }
     }
 
+    /**
+     * @deprecated since 3.0 in favor of {@link #allRows(boolean)}.
+     */
     public List dataRows(boolean close) throws CayenneException {
-        List<Map> list = new ArrayList<Map>();
+        return allRows(close);
+    }
+
+    /**
+     * @since 3.0
+     */
+    public List allRows(boolean close) throws CayenneException {
+        List list = new ArrayList<Object>();
 
         try {
             while (hasNextRow()) {
-                list.add(nextDataRow());
+                list.add(nextRow());
             }
         }
         finally {
@@ -83,25 +93,45 @@
         return list;
     }
 
+    /**
+     * @deprecated since 3.0
+     */
     public int getDataRowWidth() {
         return result.getDataRowWidth();
     }
+    
+    /**
+     * @since 3.0
+     */
+    public int getResultSetWidth() {
+        return result.getResultSetWidth();
+    }
 
     public boolean hasNextRow() throws CayenneException {
         return result.hasNextRow();
     }
 
-    public Map nextDataRow() throws CayenneException {
+    /**
+     * @deprecated since 3.0 in favor of {@link #nextRow()}.
+     */
+    public Map<String, Object> nextDataRow() throws CayenneException {
         return result.nextDataRow();
     }
 
     /**
+     * @since 3.0
+     */
+    public Object nextRow() throws CayenneException {
+        return result.nextRow();
+    }
+
+    /**
      * @deprecated since 3.0 in favor of {@link #nextId(DbEntity)}.
      */
     public Map nextObjectId(DbEntity entity) throws CayenneException {
         return result.nextObjectId(entity);
     }
-    
+
     /**
      * @since 3.0
      */
@@ -109,7 +139,17 @@
         return result.nextId();
     }
 
+    /**
+     * @deprecated since 3.0 in favor of {@link #skipRow()}.
+     */
     public void skipDataRow() throws CayenneException {
         result.skipDataRow();
     }
+
+    /**
+     * @since 3.0
+     */
+    public void skipRow() throws CayenneException {
+        result.skipRow();
+    }
 }

Modified: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/jdbc/BaseSQLAction.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/jdbc/BaseSQLAction.java?rev=722018&r1=722017&r2=722018&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/jdbc/BaseSQLAction.java (original)
+++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/jdbc/BaseSQLAction.java Mon Dec  1 01:58:11 2008
@@ -82,7 +82,7 @@
                 metadata.getFetchLimit());
 
         if (!delegate.isIteratedResult()) {
-            List<DataRow> resultRows = it.dataRows(false);
+            List<DataRow> resultRows = it.allRows(false);
             QueryLogger
                     .logSelectCount(resultRows.size(), System.currentTimeMillis() - t1);
 

Added: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/jdbc/CompoundRowReader.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/jdbc/CompoundRowReader.java?rev=722018&view=auto
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/jdbc/CompoundRowReader.java (added)
+++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/jdbc/CompoundRowReader.java Mon Dec  1 01:58:11 2008
@@ -0,0 +1,59 @@
+/*****************************************************************
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you 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.cayenne.access.jdbc;
+
+import java.sql.ResultSet;
+
+import org.apache.cayenne.CayenneException;
+
+/**
+ * A row reader for complex result sets resolved as object arrays.
+ * 
+ * @since 3.0
+ */
+class CompoundRowReader implements RowReader<Object[]> {
+
+    private RowReader<?>[] readers;
+
+    CompoundRowReader(int width) {
+        this.readers = new RowReader[width];
+    }
+
+    void addRowReader(int pos, RowReader<?> reader) {
+        this.readers[pos] = reader;
+    }
+
+    public Object[] readRow(ResultSet resultSet) throws CayenneException {
+
+        int width = readers.length;
+        Object[] row = new Object[width];
+
+        for (int i = 0; i < width; i++) {
+            row[i] = readers[i].readRow(resultSet);
+        }
+
+        return row;
+    }
+
+    public void setPostProcessor(DataRowPostProcessor postProcessor) {
+        for (RowReader<?> reader : readers) {
+            reader.setPostProcessor(postProcessor);
+        }
+    }
+}

Added: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/jdbc/EntityRowReader.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/jdbc/EntityRowReader.java?rev=722018&view=auto
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/jdbc/EntityRowReader.java (added)
+++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/jdbc/EntityRowReader.java Mon Dec  1 01:58:11 2008
@@ -0,0 +1,92 @@
+/*****************************************************************
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you 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.cayenne.access.jdbc;
+
+import java.sql.ResultSet;
+import java.util.Map;
+
+import org.apache.cayenne.CayenneException;
+import org.apache.cayenne.DataRow;
+import org.apache.cayenne.query.EntityResult;
+import org.apache.cayenne.query.QueryMetadata;
+import org.apache.cayenne.util.Util;
+
+/**
+ * @since 3.0
+ */
+class EntityRowReader extends BaseRowReader<DataRow> {
+
+    private int[] valueIndices;
+    private int mapCapacity;
+
+    EntityRowReader(RowDescriptor descriptor, QueryMetadata queryMetadata,
+            EntityResult entityResult) {
+        super(descriptor, queryMetadata);
+
+        Map<String, String> fields = entityResult.getDbFields();
+
+        this.mapCapacity = (int) Math.ceil((fields.size()) / 0.75);
+        this.valueIndices = new int[fields.size()];
+
+        ColumnDescriptor[] columns = descriptor.getColumns();
+        for (int i = 0, j = 0; i < columns.length; i++) {
+            if (fields.containsKey(columns[i].getName())) {
+                valueIndices[j++] = i;
+            }
+        }
+
+    }
+
+    @Override
+    public DataRow readRow(ResultSet resultSet) throws CayenneException {
+        
+        try {
+            DataRow idRow = new DataRow(mapCapacity);
+            idRow.setEntityName(entityName);
+            int len = valueIndices.length;
+
+            for (int i = 0; i < len; i++) {
+
+                // dereference column index
+                int index = valueIndices[i];
+
+                // note: jdbc column indexes start from 1, not 0 as in arrays
+                Object val = converters[index].materializeObject(
+                        resultSet,
+                        index + 1,
+                        types[index]);
+                idRow.put(labels[index], val);
+            }
+
+            if (postProcessor != null) {
+                postProcessor.postprocessRow(resultSet, idRow);
+            }
+
+            return idRow;
+        }
+        catch (CayenneException cex) {
+            // rethrow unmodified
+            throw cex;
+        }
+        catch (Exception otherex) {
+            throw new CayenneException("Exception materializing id column.", Util
+                    .unwindException(otherex));
+        }
+    }
+}

Modified: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/jdbc/JDBCResultIterator.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/jdbc/JDBCResultIterator.java?rev=722018&r1=722017&r2=722018&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/jdbc/JDBCResultIterator.java (original)
+++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/jdbc/JDBCResultIterator.java Mon Dec  1 01:58:11 2008
@@ -28,10 +28,13 @@
 import java.util.Map;
 
 import org.apache.cayenne.CayenneException;
+import org.apache.cayenne.CayenneRuntimeException;
 import org.apache.cayenne.DataRow;
 import org.apache.cayenne.access.ResultIterator;
 import org.apache.cayenne.map.DbEntity;
+import org.apache.cayenne.query.EntityResult;
 import org.apache.cayenne.query.QueryMetadata;
+import org.apache.cayenne.query.SQLResultSetMapping;
 
 /**
  * A ResultIterator over the underlying JDBC ResultSet.
@@ -56,7 +59,7 @@
     protected boolean nextRow;
 
     private DataRowPostProcessor postProcessor;
-    private RowReader<DataRow> rowReader;
+    private RowReader<?> rowReader;
     private RowReader<Object> idRowReader;
 
     /**
@@ -84,10 +87,65 @@
     /**
      * RowReader factory method.
      */
-    private RowReader<DataRow> createRowReader(
+    private RowReader<?> createRowReader(
+            RowDescriptor descriptor,
+            QueryMetadata queryMetadata) {
+
+        SQLResultSetMapping rsMapping = queryMetadata.getResultSetMapping();
+        if (rsMapping != null) {
+
+            List<?> resultDescriptors = rsMapping.getResultDescriptors();
+            int resultWidth = resultDescriptors.size();
+
+            if (resultWidth == 0) {
+                throw new CayenneRuntimeException("Empty result descriptor");
+            }
+            else if (resultWidth == 1) {
+                return createSegmentRowReader(
+                        descriptor,
+                        queryMetadata,
+                        resultDescriptors.get(0));
+            }
+            else {
+                CompoundRowReader reader = new CompoundRowReader(resultWidth);
+                for (int i = 0; i < resultWidth; i++) {
+                    reader.addRowReader(i, createSegmentRowReader(
+                            descriptor,
+                            queryMetadata,
+                            resultDescriptors.get(i)));
+                }
+
+                return reader;
+            }
+        }
+        else {
+            return createFullRowReader(descriptor, queryMetadata);
+        }
+    }
+
+    private RowReader<?> createSegmentRowReader(
+            RowDescriptor descriptor,
+            QueryMetadata queryMetadata,
+            Object segmentDescriptor) {
+
+        if (segmentDescriptor instanceof String) {
+            return new ScalarRowReader(descriptor, (String) segmentDescriptor);
+        }
+        else if (segmentDescriptor instanceof EntityResult) {
+            return new EntityRowReader(
+                    descriptor,
+                    queryMetadata,
+                    (EntityResult) segmentDescriptor);
+        }
+        else {
+            throw new IllegalArgumentException(
+                    "Expected either String or Entity Result: " + segmentDescriptor);
+        }
+    }
+
+    private RowReader<?> createFullRowReader(
             RowDescriptor descriptor,
             QueryMetadata queryMetadata) {
-        
         if (queryMetadata.getClassDescriptor() != null
                 && queryMetadata.getClassDescriptor().getEntityInheritanceTree() != null) {
             return new InheritanceAwareRowReader(descriptor, queryMetadata);
@@ -95,18 +153,26 @@
         else {
             return new FullRowReader(descriptor, queryMetadata);
         }
-
     }
 
     /**
      * Returns all unread data rows from ResultSet, closing this iterator if needed.
+     * 
+     * @deprecated since 3.0
      */
     public List<DataRow> dataRows(boolean close) throws CayenneException {
-        List<DataRow> list = new ArrayList<DataRow>();
+        return allRows(close);
+    }
+
+    /**
+     * @since 3.0
+     */
+    public List allRows(boolean close) throws CayenneException {
+        List<Object> list = new ArrayList<Object>();
 
         try {
             while (hasNextRow()) {
-                list.add((DataRow) nextDataRow());
+                list.add(nextRow());
             }
         }
         finally {
@@ -128,17 +194,23 @@
 
     /**
      * Returns the next result row as a Map.
+     * 
+     * @deprecated since 3.0
      */
     public Map<String, Object> nextDataRow() throws CayenneException {
+        return (DataRow) nextRow();
+    }
+
+    /**
+     * @since 3.0
+     */
+    public Object nextRow() throws CayenneException {
         if (!hasNextRow()) {
             throw new CayenneException(
                     "An attempt to read uninitialized row or past the end of the iterator.");
         }
 
-        // read
-        Map<String, Object> row = readDataRow();
-
-        // rewind
+        Object row = rowReader.readRow(resultSet);
         checkNextRow();
         return row;
     }
@@ -194,7 +266,17 @@
         return id;
     }
 
+    /**
+     * @deprecated since 3.0
+     */
     public void skipDataRow() throws CayenneException {
+        skipRow();
+    }
+
+    /**
+     * @since 3.0
+     */
+    public void skipRow() throws CayenneException {
         if (!hasNextRow()) {
             throw new CayenneException(
                     "An attempt to read uninitialized row or past the end of the iterator.");
@@ -255,8 +337,17 @@
 
     /**
      * Returns the number of columns in the result row.
+     * 
+     * @deprecated since 3.0
      */
     public int getDataRowWidth() {
+        return getResultSetWidth();
+    }
+
+    /**
+     * @since 3.0
+     */
+    public int getResultSetWidth() {
         return rowDescriptor.getWidth();
     }
 
@@ -278,9 +369,11 @@
 
     /**
      * Reads a row from the internal ResultSet at the current cursor position.
+     * 
+     * @deprecated since 3.0. Internal rowReader is used to read individual rows.
      */
     protected Map<String, Object> readDataRow() throws CayenneException {
-        return rowReader.readRow(resultSet);
+        return (DataRow) rowReader.readRow(resultSet);
     }
 
     /**

Modified: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/jdbc/LimitResultIterator.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/jdbc/LimitResultIterator.java?rev=722018&r1=722017&r2=722018&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/jdbc/LimitResultIterator.java (original)
+++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/jdbc/LimitResultIterator.java Mon Dec  1 01:58:11 2008
@@ -19,13 +19,12 @@
 package org.apache.cayenne.access.jdbc;
 
 import java.util.ArrayList;
-
 import java.util.List;
 import java.util.Map;
 
 import org.apache.cayenne.CayenneException;
+import org.apache.cayenne.DataRow;
 import org.apache.cayenne.access.ResultIterator;
-
 import org.apache.cayenne.map.DbEntity;
 
 /**
@@ -59,7 +58,7 @@
 
     private void checkOffset() throws CayenneException {
         for (int i = 0; i < offset && wrappedIterator.hasNextRow(); i++) {
-            wrappedIterator.nextDataRow();
+            wrappedIterator.nextRow();
         }
     }
 
@@ -71,24 +70,29 @@
             nextRow = true;
             fetchedSoFar++;
         }
-
-    }
-
-    private Map<String, Object> readDataRow() throws CayenneException {
-        return wrappedIterator.nextDataRow();
     }
 
     public void close() throws CayenneException {
         wrappedIterator.close();
     }
 
+    /**
+     * @deprecated since 3.0
+     */
     public List dataRows(boolean close) throws CayenneException {
+        return allRows(close);
+    }
 
-        List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();
+    /**
+     * @since 3.0
+     */
+    public List allRows(boolean close) throws CayenneException {
+
+        List<Object> list = new ArrayList<Object>();
 
         try {
             while (this.hasNextRow()) {
-                list.add(this.nextDataRow());
+                list.add(this.nextRow());
             }
         }
         finally {
@@ -100,22 +104,42 @@
         return list;
     }
 
+    /**
+     * @deprecated since 3.0
+     */
     public int getDataRowWidth() {
         return wrappedIterator.getDataRowWidth();
     }
+    
+    /**
+     * @since 3.0
+     */
+    public int getResultSetWidth() {
+        return wrappedIterator.getResultSetWidth();
+    }
 
     public boolean hasNextRow() throws CayenneException {
         return nextRow;
     }
 
+    /**
+     * @deprecated since 3.0
+     */
     public Map<String, Object> nextDataRow() throws CayenneException {
+        return (DataRow) nextRow();
+    }
+
+    /**
+     * @since 3.0
+     */
+    public Object nextRow() throws CayenneException {
         if (!hasNextRow()) {
             throw new CayenneException(
                     "An attempt to read uninitialized row or past the end of the iterator.");
         }
-        Map<String, Object> row = readDataRow();
-        checkNextRow();
 
+        Object row = wrappedIterator.nextRow();
+        checkNextRow();
         return row;
     }
 
@@ -145,10 +169,20 @@
         return nextDataObjectIds;
     }
 
+    /**
+     * @deprecated since 3.0 in favor of {@link #skipRow()}.
+     */
     public void skipDataRow() throws CayenneException {
         wrappedIterator.skipDataRow();
     }
 
+    /**
+     * @since 3.0
+     */
+    public void skipRow() throws CayenneException {
+        wrappedIterator.skipRow();
+    }
+
     void checkNextId() throws CayenneException {
         nextRow = false;
         if (wrappedIterator.hasNextRow()) {
@@ -174,5 +208,4 @@
             nextDataObjectIds = next;
         }
     }
-
 }

Modified: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/jdbc/SQLTemplateAction.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/jdbc/SQLTemplateAction.java?rev=722018&r1=722017&r2=722018&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/jdbc/SQLTemplateAction.java (original)
+++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/jdbc/SQLTemplateAction.java Mon Dec  1 01:58:11 2008
@@ -231,7 +231,7 @@
                 .getFetchLimit());
 
         if (!iteratedResult) {
-            List<DataRow> resultRows = it.dataRows(false);
+            List<DataRow> resultRows = it.allRows(false);
             QueryLogger.logSelectCount(resultRows.size(), System.currentTimeMillis()
                     - startTime);
 

Added: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/jdbc/ScalarRowReader.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/jdbc/ScalarRowReader.java?rev=722018&view=auto
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/jdbc/ScalarRowReader.java (added)
+++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/jdbc/ScalarRowReader.java Mon Dec  1 01:58:11 2008
@@ -0,0 +1,67 @@
+/*****************************************************************
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you 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.cayenne.access.jdbc;
+
+import java.sql.ResultSet;
+
+import org.apache.cayenne.CayenneException;
+import org.apache.cayenne.access.types.ExtendedType;
+import org.apache.cayenne.util.Util;
+
+/**
+ * @since 3.0
+ */
+class ScalarRowReader implements RowReader<Object> {
+
+    private ExtendedType converter;
+    private int index;
+    private int type;
+
+    ScalarRowReader(RowDescriptor descriptor, String columnName) {
+        ColumnDescriptor[] columns = descriptor.getColumns();
+        for (int i = 0; i < columns.length; i++) {
+            if (columnName.equals(columns[i].getLabel())) {
+
+                this.converter = descriptor.getConverters()[i];
+                this.type = columns[i].getJdbcType();
+                this.index = i + 1;
+
+                break;
+            }
+        }
+    }
+
+    public Object readRow(ResultSet resultSet) throws CayenneException {
+        try {
+            return converter.materializeObject(resultSet, index, type);
+        }
+        catch (CayenneException cex) {
+            // rethrow unmodified
+            throw cex;
+        }
+        catch (Exception otherex) {
+            throw new CayenneException("Exception materializing column.", Util
+                    .unwindException(otherex));
+        }
+    }
+
+    public void setPostProcessor(DataRowPostProcessor postProcessor) {
+        // noop
+    }
+}

Modified: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/jdbc/SelectAction.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/jdbc/SelectAction.java?rev=722018&r1=722017&r2=722018&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/jdbc/SelectAction.java (original)
+++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/jdbc/SelectAction.java Mon Dec  1 01:58:11 2008
@@ -134,8 +134,8 @@
         }
 
         // wrap iterator in a fetch limit checker ... there are a few cases when in-memory
-        // fetch limit is a noop, however in a geberal case this is needed, as teh SQL
-        // result count does not directly correspind to the number of objects returned
+        // fetch limit is a noop, however in a general case this is needed, as the SQL
+        // result count does not directly correspond to the number of objects returned
         // from Cayenne.
 
         int fetchLimit = query.getFetchLimit();
@@ -150,7 +150,7 @@
         if (!observer.isIteratedResult()) {
             // note that we don't need to close ResultIterator
             // since "dataRows" will do it internally
-            List<DataRow> resultRows = it.dataRows(true);
+            List<DataRow> resultRows = it.allRows(true);
             QueryLogger
                     .logSelectCount(resultRows.size(), System.currentTimeMillis() - t1);
 

Modified: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/util/DistinctResultIterator.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/util/DistinctResultIterator.java?rev=722018&r1=722017&r2=722018&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/util/DistinctResultIterator.java (original)
+++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/util/DistinctResultIterator.java Mon Dec  1 01:58:11 2008
@@ -28,6 +28,7 @@
 import java.util.Set;
 
 import org.apache.cayenne.CayenneException;
+import org.apache.cayenne.DataRow;
 import org.apache.cayenne.access.ResultIterator;
 import org.apache.cayenne.map.DbAttribute;
 import org.apache.cayenne.map.DbEntity;
@@ -46,7 +47,7 @@
 
     protected ResultIterator wrappedIterator;
     protected Set<Map<String, Object>> fetchedIds;
-    protected Map<String, Object> nextDataRow;
+    protected Object nextDataRow;
     protected DbEntity defaultEntity;
     protected boolean compareFullRows;
 
@@ -85,13 +86,22 @@
 
     /**
      * Returns all data rows.
+     * 
+     * @deprecated since 3.0
      */
     public List dataRows(boolean close) throws CayenneException {
-        List<Map> list = new ArrayList<Map>();
+        return allRows(close);
+    }
+
+    /**
+     * @since 3.0
+     */
+    public List allRows(boolean close) throws CayenneException {
+        List<Object> list = new ArrayList<Object>();
 
         try {
             while (this.hasNextRow()) {
-                list.add(this.nextDataRow());
+                list.add(nextRow());
             }
             return list;
         }
@@ -102,21 +112,35 @@
         }
     }
 
+    /**
+     * @deprecated since 3.0
+     */
     public int getDataRowWidth() {
         return wrappedIterator.getDataRowWidth();
     }
+    
+    public int getResultSetWidth() {
+        return wrappedIterator.getResultSetWidth();
+    }
 
     public boolean hasNextRow() throws CayenneException {
         return nextDataRow != null;
     }
 
+    /**
+     * @deprecated since 3.0
+     */
     public Map nextDataRow() throws CayenneException {
+        return (DataRow) nextRow();
+    }
+
+    public Object nextRow() throws CayenneException {
         if (!hasNextRow()) {
             throw new CayenneException(
                     "An attempt to read uninitialized row or past the end of the iterator.");
         }
 
-        Map<String, Object> row = nextDataRow;
+        Object row = nextDataRow;
         checkNextRow();
         return row;
     }
@@ -133,7 +157,7 @@
                     "An attempt to read uninitialized row or past the end of the iterator.");
         }
 
-        Map<String, Object> row = nextDataRow;
+        DataRow row = (DataRow) nextDataRow;
 
         // if we were previously reading full rows, we need to strip extra keys...
         if (!readingIds) {
@@ -162,7 +186,12 @@
                     "An attempt to read uninitialized row or past the end of the iterator.");
         }
 
-        Map<String, Object> row = nextDataRow;
+        if (!(nextDataRow instanceof DataRow)) {
+            throw new IllegalStateException(
+                    "A query is not fetching DataRows. Can't call 'nextId'");
+        }
+
+        DataRow row = (DataRow) nextDataRow;
 
         checkNextId(defaultEntity);
 
@@ -171,7 +200,17 @@
         return row.get(defaultEntity.getPrimaryKeys().iterator().next().getName());
     }
 
+    /**
+     * @deprecated since 3.0
+     */
     public void skipDataRow() throws CayenneException {
+        skipRow();
+    }
+
+    /**
+     * @since 3.0
+     */
+    public void skipRow() throws CayenneException {
         if (!hasNextRow()) {
             throw new CayenneException(
                     "An attempt to read uninitialized row or past the end of the iterator.");
@@ -203,7 +242,7 @@
 
         nextDataRow = null;
         while (wrappedIterator.hasNextRow()) {
-            Map<String, Object> next = wrappedIterator.nextDataRow();
+            DataRow next = (DataRow) wrappedIterator.nextRow();
 
             if (fetchedIds.add(next)) {
                 this.nextDataRow = next;
@@ -216,7 +255,7 @@
 
         nextDataRow = null;
         while (wrappedIterator.hasNextRow()) {
-            Map<String, Object> next = wrappedIterator.nextDataRow();
+            DataRow next = (DataRow) wrappedIterator.nextRow();
 
             // create id map...
             // TODO: this can be optimized by creating an array with id keys

Modified: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/access/DataContextSQLTemplateTest.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/access/DataContextSQLTemplateTest.java?rev=722018&r1=722017&r2=722018&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/access/DataContextSQLTemplateTest.java (original)
+++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/access/DataContextSQLTemplateTest.java Mon Dec  1 01:58:11 2008
@@ -525,7 +525,7 @@
             while (it.hasNextRow()) {
                 i++;
 
-                Map row = it.nextDataRow();
+                DataRow row = (DataRow) it.nextRow();
                 assertEquals(3, row.size());
                 assertEquals(33000l + i, row.get("ARTIST_ID"));
             }

Modified: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/access/DataContextTest.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/access/DataContextTest.java?rev=722018&r1=722017&r2=722018&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/access/DataContextTest.java (original)
+++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/access/DataContextTest.java Mon Dec  1 01:58:11 2008
@@ -416,7 +416,7 @@
         try {
             int count = 0;
             while (it.hasNextRow()) {
-                it.nextDataRow();
+                it.nextRow();
                 count++;
             }
 
@@ -437,7 +437,7 @@
 
         try {
             while (it.hasNextRow()) {
-                DataRow row = (DataRow) it.nextDataRow();
+                DataRow row = (DataRow) it.nextRow();
 
                 // try instantiating an object and fetching its relationships
                 Artist artist = (Artist) context.objectFromDataRow(

Modified: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/access/jdbc/JDBCResultIteratorTest.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/access/jdbc/JDBCResultIteratorTest.java?rev=722018&r1=722017&r2=722018&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/access/jdbc/JDBCResultIteratorTest.java (original)
+++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/access/jdbc/JDBCResultIteratorTest.java Mon Dec  1 01:58:11 2008
@@ -25,6 +25,7 @@
 
 import junit.framework.TestCase;
 
+import org.apache.cayenne.DataRow;
 import org.apache.cayenne.access.types.ExtendedTypeMap;
 import org.apache.cayenne.query.MockQueryMetadata;
 
@@ -49,7 +50,7 @@
     public void testNextDataRow() throws Exception {
         JDBCResultIterator it = makeIterator();
 
-        Map row = it.nextDataRow();
+        DataRow row = (DataRow) it.nextRow();
 
         assertNotNull(row);
         assertEquals(1, row.size());