Ticket #463: mysql_trunk_rev2360-1.diff

File mysql_trunk_rev2360-1.diff, 3.7 KB (added by greg@…, 9 years ago)

Patch for trunk 2360, using thread-local storage and python 2.3 support

  • django/core/db/backends/mysql.py

     
    1010from MySQLdb.converters import conversions
    1111from MySQLdb.constants import FIELD_TYPE
    1212import types
     13import threading
    1314
    1415DatabaseError = Database.DatabaseError
    1516
     
    4748        else:
    4849            return getattr(self.cursor, attr)
    4950
     51class ThreadLocal:
     52    def __getattr__(self, key):
     53        threadkey = 'ThreadLocal_%s' % (id(self),)
     54        thread = threading.currentThread()
     55        try:
     56            local = getattr(thread, threadkey)
     57            return local[key]
     58        except AttributeError:
     59            raise AttributeError(key)
     60        except KeyError:
     61            raise AttributeError(key)
     62
     63    def __setattr__(self, key, value):
     64        threadkey = 'ThreadLocal_%s' % (id(self),)
     65        thread = threading.currentThread()
     66        try:
     67            local = getattr(thread, threadkey)
     68        except AttributeError:
     69            local = {}
     70            setattr(thread, threadkey, local)
     71        local[key] = value
     72
     73    def __delattr__(self, key):
     74        threadkey = 'ThreadLocal_%s' % (id(self),)
     75        thread = threading.currentThread()
     76        try:
     77            local = getattr(thread, threadkey)
     78            del local[key]
     79        except AttributeError:
     80            raise AttributeError(key)
     81        except KeyError:
     82            raise AttributeError(key)
     83
    5084class DatabaseWrapper:
    5185    def __init__(self):
    52         self.connection = None
    5386        self.queries = []
     87        if hasattr(threading, 'local'):
     88            # threading.local is available in Python 2.4 and later
     89            self.threadlocal = threading.local()
     90        else:
     91            # workaround for Python 2.3 and earlier
     92            self.threadlocal = ThreadLocal()
    5493
    5594    def cursor(self):
    5695        from django.conf.settings import DATABASE_USER, DATABASE_NAME, DATABASE_HOST, DATABASE_PORT, DATABASE_PASSWORD, DEBUG
    57         if self.connection is None:
     96        conn = getattr(self.threadlocal, 'connection', None)
     97        if conn is None:
    5898            kwargs = {
    5999                'user': DATABASE_USER,
    60100                'db': DATABASE_NAME,
     
    64104            }
    65105            if DATABASE_PORT:
    66106                kwargs['port'] = DATABASE_PORT
    67             self.connection = Database.connect(**kwargs)
    68         cursor = self.connection.cursor()
    69         if self.connection.get_server_info() >= '4.1':
     107            conn = self.threadlocal.connection = Database.connect(**kwargs)
     108        else:
     109            conn.ping()
     110        cursor = conn.cursor()
     111        if conn.get_server_info() >= '4.1':
    70112            cursor.execute("SET NAMES utf8")
    71113        if DEBUG:
    72114            return base.CursorDebugWrapper(MysqlDebugWrapper(cursor), self)
    73115        return cursor
    74116
    75117    def commit(self):
    76         self.connection.commit()
     118        conn = getattr(self.threadlocal, 'connection', None)
     119        if conn is not None:
     120            conn.commit()
    77121
    78122    def rollback(self):
    79         if self.connection:
     123        conn = getattr(self.threadlocal, 'connection', None)
     124        if conn is not None:
    80125            try:
    81                 self.connection.rollback()
     126                conn.rollback()
    82127            except Database.NotSupportedError:
    83128                pass
    84129
    85130    def close(self):
    86         if self.connection is not None:
    87             self.connection.close()
    88             self.connection = None
     131        conn = getattr(self.threadlocal, 'connection', None)
     132        if conn is not None:
     133            conn.close()
     134            self.threadlocal.connection = None
    89135
    90136    def quote_name(self, name):
    91137        if name.startswith("`") and name.endswith("`"):
Back to Top