Ticket #17956: explicit_cursor_closing.patch

File explicit_cursor_closing.patch, 3.0 KB (added by Vsevolod Novikov, 13 years ago)

Patch for django 1.3.1.final to close opened cursors explicitly

  • django/db/models/sql/compiler.py

    old new  
    738738            return cursor
    739739        if result_type == SINGLE:
    740740            if self.query.ordering_aliases:
    741                 return cursor.fetchone()[:-len(self.query.ordering_aliases)]
    742             return cursor.fetchone()
     741                r = cursor.fetchone()[:-len(self.query.ordering_aliases)]
     742            else:
     743                r = cursor.fetchone()
     744            cursor.close()
     745            return r
    743746
    744747        # The MULTI case.
    745748        if self.query.ordering_aliases:
    746749            result = order_modified_iter(cursor, len(self.query.ordering_aliases),
    747750                    self.connection.features.empty_fetchmany_value)
    748751        else:
    749             result = iter((lambda: cursor.fetchmany(GET_ITERATOR_CHUNK_SIZE)),
     752            result = not_modified_iter(cursor,
    750753                    self.connection.features.empty_fetchmany_value)
     754
    751755        if not self.connection.features.can_use_chunked_reads:
    752756            # If we are using non-chunked reads, we return the same data
    753757            # structure as normally, but ensure it is all read into memory
     
    789793    def execute_sql(self, return_id=False):
    790794        self.return_id = return_id
    791795        cursor = super(SQLInsertCompiler, self).execute_sql(None)
    792         if not (return_id and cursor):
     796        if not cursor:
    793797            return
    794         if self.connection.features.can_return_id_from_insert:
    795             return self.connection.ops.fetch_returned_insert_id(cursor)
    796         return self.connection.ops.last_insert_id(cursor,
    797                 self.query.model._meta.db_table, self.query.model._meta.pk.column)
     798        r = None
     799        if return_id:
     800            if self.connection.features.can_return_id_from_insert:
     801                r = self.connection.ops.fetch_returned_insert_id(cursor)
     802            else:
     803                r = self.connection.ops.last_insert_id(cursor,
     804                    self.query.model._meta.db_table, self.query.model._meta.pk.column)
     805        cursor.close()
     806        return r
    798807
    799808
    800809class SQLDeleteCompiler(SQLCompiler):
     
    869878        cursor = super(SQLUpdateCompiler, self).execute_sql(result_type)
    870879        rows = cursor and cursor.rowcount or 0
    871880        is_empty = cursor is None
     881        if cursor:
     882            cursor.close()
    872883        del cursor
    873884        for query in self.query.get_related_updates():
    874885            aux_rows = query.get_compiler(self.using).execute_sql(result_type)
     
    980991    for rows in iter((lambda: cursor.fetchmany(GET_ITERATOR_CHUNK_SIZE)),
    981992            sentinel):
    982993        yield [r[:-trim] for r in rows]
     994    cursor.close()
     995
     996def not_modified_iter(cursor, sentinel):
     997    """
     998    Yields blocks of rows from a cursor. We use this iterator in usual
     999    case - just to close the cursor at appropriate time.
     1000    """
     1001    for rows in iter((lambda: cursor.fetchmany(GET_ITERATOR_CHUNK_SIZE)),
     1002            sentinel):
     1003        yield [r[:] for r in rows]
     1004    cursor.close()
Back to Top