Index: django/db/models/sql/compiler.py
===================================================================
--- django/db/models/sql/compiler.py	(revision 15147)
+++ django/db/models/sql/compiler.py	(working copy)
@@ -13,6 +13,7 @@
         self.connection = connection
         self.using = using
         self.quote_cache = {}
+        self.iter_cursor_map = {}
 
     def pre_sql_setup(self):
         """
@@ -677,7 +676,8 @@
         resolve_columns = hasattr(self, 'resolve_columns')
         fields = None
         has_aggregate_select = bool(self.query.aggregate_select)
-        for rows in self.execute_sql(MULTI):
+        cursor_iter = self.execute_sql(MULTI)
+        for rows in cursor_iter:
             for row in rows:
                 if resolve_columns:
                     if fields is None:
@@ -707,6 +707,11 @@
                     ]) + tuple(row[aggregate_end:])
 
                 yield row
+        # iteration over cursor is completed.
+        # it's now save to close the cursor and remove it from the lookup dict
+        if cursor_iter in self.iter_cursor_map:
+            self.iter_cursor_map[cursor_iter].close()
+            del self.iter_cursor_map[cursor_iter]
 
     def execute_sql(self, result_type=MULTI):
         """
@@ -734,12 +739,17 @@
         cursor = self.connection.cursor()
         cursor.execute(sql, params)
 
+        # close cursors for single results.
         if not result_type:
             return cursor
         if result_type == SINGLE:
             if self.query.ordering_aliases:
-                return cursor.fetchone()[:-len(self.query.ordering_aliases)]
-            return cursor.fetchone()
+                temp_result = cursor.fetchone()[:-len(self.query.ordering_aliases)]
+                cursor.close() 
+                return temp_result
+            temp_result = cursor.fetchone()
+            cursor.close() 
+            return temp_result
 
         # The MULTI case.
         if self.query.ordering_aliases:
@@ -748,14 +758,18 @@
         else:
             result = iter((lambda: cursor.fetchmany(GET_ITERATOR_CHUNK_SIZE)),
                     self.connection.features.empty_fetchmany_value)
+        # store iterator only if we use chunks
+        if self.connection.features.can_use_chunked_reads:
+            self.iter_cursor_map[result] = cursor
         if not self.connection.features.can_use_chunked_reads:
             # If we are using non-chunked reads, we return the same data
             # structure as normally, but ensure it is all read into memory
             # before going any further.
-            return list(result)
+            temp_ressult = list(result)
+            cursor.close()
+            return temp_result
         return result
 
-
 class SQLInsertCompiler(SQLCompiler):
     def placeholder(self, field, val):
         if field is None:
