Django

Code

Ticket #463: mysql_trunk_rev2360-1.diff

File mysql_trunk_rev2360-1.diff, 3.7 kB (added by greg@abbas.no-spam.org, 3 years ago)

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

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

    old new  
    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("`"):