Index: lib/sqlalchemy/engine/base.py
===================================================================
--- lib/sqlalchemy/engine/base.py	(revision 2247)
+++ lib/sqlalchemy/engine/base.py	(working copy)
@@ -563,27 +563,12 @@
             self.rowcount = executioncontext.get_rowcount(cursor)
         else:
             self.rowcount = cursor.rowcount
+        self.typemap = typemap
         self.__key_cache = {}
         self.__echo = engine.echo == 'debug'
-        metadata = cursor.description
         self.props = {}
         self.keys = []
-        i = 0
-        if metadata is not None:
-            for item in metadata:
-                # sqlite possibly prepending table name to colnames so strip
-                colname = item[0].split('.')[-1].lower()
-                if typemap is not None:
-                    rec = (typemap.get(colname, types.NULLTYPE), i)
-                else:
-                    rec = (types.NULLTYPE, i)
-                if rec[0] is None:
-                    raise DBAPIError("None for metadata " + colname)
-                if self.props.setdefault(colname, rec) is not rec:
-                    self.props[colname] = (ResultProxy.AmbiguousColumn(colname), 0)
-                self.keys.append(colname)
-                self.props[i] = rec
-                i+=1
+        self._build_props(self.cursor.description)
     def _executioncontext(self):
         try:
             return self.__executioncontext
@@ -604,6 +589,23 @@
             if self.connection.should_close_with_result and self.dialect.supports_autoclose_results:
                 self.connection.close()
 
+    def _build_props(self, metadata):
+        if metadata is not None:
+            for i, item in enumerate(metadata):
+                # sqlite possibly prepending table name to colnames so strip
+                colname = item[0].split('.')[-1].lower()
+                if self.typemap is not None:
+                    rec = (self.typemap.get(colname, types.NULLTYPE), i)
+                else:
+                    rec = (types.NULLTYPE, i)
+                if rec[0] is None:
+                    raise DBAPIError("None for metadata " + colname)
+                if self.props.setdefault(colname, rec) is not rec:
+                    self.props[colname] = (ResultProxy.AmbiguousColumn(colname), 0)
+                self.keys.append(colname)
+                self.props[i] = rec
+            self.typemap = None
+
     def _convert_key(self, key):
         """given a key, which could be a ColumnElement, string, etc., matches it to the 
         appropriate key we got from the result set's metadata; then cache it locally for quick re-access."""
@@ -690,6 +692,8 @@
         l = []
         for row in self.cursor.fetchall():
             l.append(RowProxy(self, row))
+        if not self.props:
+            self._build_props(self.cursor.description)
         self.close()
         return l
             
@@ -702,6 +706,8 @@
         l = []
         for row in rows:
             l.append(RowProxy(self, row))
+        if not self.props:
+            self._build_props(self.cursor.description)
         if len(l) == 0:
             self.close()
         return l
@@ -709,6 +715,8 @@
     def fetchone(self):
         """fetch one row, just like DBAPI cursor.fetchone()."""
         row = self.cursor.fetchone()
+        if not self.props:
+            self._build_props(self.cursor.description)
         if row is not None:
             return RowProxy(self, row)
         else:
@@ -722,6 +730,8 @@
         """fetch the first column of the first row, and close the result set."""
         row = self.cursor.fetchone()
         try:
+            if not self.props:
+                self._build_props(self.cursor.description)
             if row is not None:
                 return RowProxy(self, row)[0]
             else:
