Ticket #13742: 0001-implement-savepoints-for-sqlite3.patch

File 0001-implement-savepoints-for-sqlite3.patch, 4.0 KB (added by Tay Ray Chuan, 14 years ago)
  • django/db/backends/sqlite3/base.py

    From 62dc2e4829fe0b947b88f14fb9098935d05c5475 Mon Sep 17 00:00:00 2001
    From: Tay Ray Chuan <rctay89@gmail.com>
    Date: Sat, 12 Jun 2010 00:00:34 +0800
    Subject: [PATCH] implement savepoints for sqlite3
    
    ---
     django/db/backends/sqlite3/base.py |   39 ++++++++++++++++++++++++++++++++++++
     1 files changed, 39 insertions(+), 0 deletions(-)
    
    diff --git a/django/db/backends/sqlite3/base.py b/django/db/backends/sqlite3/base.py
    index bc97f5c..c57df14 100644
    a b if Database.version_info >= (2,4,1):  
    5454    Database.register_adapter(str, lambda s:s.decode('utf-8'))
    5555    Database.register_adapter(SafeString, lambda s:s.decode('utf-8'))
    5656
     57uses_savepoints = False
     58if Database.sqlite_version_info >= (3,6,8):
     59    uses_savepoints = True
     60
    5761class DatabaseFeatures(BaseDatabaseFeatures):
    5862    # SQLite cannot handle us only partially reading from a cursor's result set
    5963    # and then writing the same rows to the database in another cursor. This
    6064    # setting ensures we always read result sets fully into memory all in one
    6165    # go.
    6266    can_use_chunked_reads = False
     67    uses_savepoints = uses_savepoints
    6368
    6469class DatabaseOperations(BaseDatabaseOperations):
    6570    def date_extract_sql(self, lookup_type, field_name):
    class DatabaseOperations(BaseDatabaseOperations):  
    9095    def no_limit_value(self):
    9196        return -1
    9297
     98    def savepoint_create_sql(self, sid):
     99        return "SAVEPOINT " + self.quote_name(sid)
     100
     101    def savepoint_rollback_sql(self, sid):
     102        return "ROLLBACK TO SAVEPOINT " + self.quote_name(sid)
     103
     104    def savepoint_commit_sql(self, sid):
     105        return "RELEASE SAVEPOINT " + self.quote_name(sid)
     106
    93107    def sql_flush(self, style, tables, sequences):
    94108        # NB: The generated SQL below is specific to SQLite
    95109        # Note: The DELETE FROM... SQL generated below works for SQLite databases
    class DatabaseWrapper(BaseDatabaseWrapper):  
    160174        self.introspection = DatabaseIntrospection(self)
    161175        self.validation = BaseDatabaseValidation(self)
    162176
     177        if Database.sqlite_version_info >= (3,6,8):
     178            self.features.uses_savepoints = True
     179        self._default_isolation_level = None
     180
    163181    def _cursor(self):
    164182        if self.connection is None:
    165183            settings_dict = self.settings_dict
    class DatabaseWrapper(BaseDatabaseWrapper):  
    172190            }
    173191            kwargs.update(settings_dict['OPTIONS'])
    174192            self.connection = Database.connect(**kwargs)
     193            self._default_isolation_level = self.connection.isolation_level
    175194            # Register extract, date_trunc, and regexp functions.
    176195            self.connection.create_function("django_extract", 2, _sqlite_extract)
    177196            self.connection.create_function("django_date_trunc", 2, _sqlite_date_trunc)
    class DatabaseWrapper(BaseDatabaseWrapper):  
    179198            connection_created.send(sender=self.__class__)
    180199        return self.connection.cursor(factory=SQLiteCursorWrapper)
    181200
     201    def _enter_transaction_management(self, managed):
     202        """
     203        If savepoints are allowed, switch the isolation_level to None.
     204
     205        However, this implies autocommits, so begin a transaction explicitly -
     206        django assumes non-autocommits.
     207        """
     208        if managed and self.features.uses_savepoints:
     209            cursor = self._cursor()
     210            cursor.connection.isolation_level = None
     211            cursor.execute('BEGIN TRANSACTION')
     212
     213    def _leave_transaction_management(self, managed):
     214        """
     215        If savepoints are allowed, we're now in autocommit mode - switch the
     216        isolation_level back to the default one.
     217        """
     218        if managed and self.features.uses_savepoints and self.connection.isolation_level is None:
     219            self.connection.isolation_level = self._default_isolation_level
     220
    182221    def close(self):
    183222        # If database is in memory, closing the connection destroys the
    184223        # database. To prevent accidental data loss, ignore close requests on
Back to Top