Ticket #15119: 15119-1.diff

File 15119-1.diff, 8.7 KB (added by Ramiro Morales, 12 years ago)
  • django/db/backends/mysql/base.py

    diff -r 7ff5d18dc66d django/db/backends/mysql/base.py
    a b  
    4747# It's impossible to import datetime_or_None directly from MySQLdb.times
    4848datetime_or_None = conversions[FIELD_TYPE.DATETIME]
    4949
     50RETRIES = 1
     51
    5052def datetime_or_None_with_timezone_support(value):
    5153    dt = datetime_or_None(value)
    5254    # Confirm that dt is naive before overwriting its tzinfo.
     
    9294    """
    9395    codes_for_integrityerror = (1048,)
    9496
    95     def __init__(self, cursor):
     97    def __init__(self, cursor, conn):
    9698        self.cursor = cursor
     99        self.django_conn = conn
    97100
    98101    def execute(self, query, args=None):
    99         try:
    100             return self.cursor.execute(query, args)
    101         except Database.IntegrityError, e:
    102             raise utils.IntegrityError, utils.IntegrityError(*tuple(e)), sys.exc_info()[2]
    103         except Database.OperationalError, e:
    104             # Map some error codes to IntegrityError, since they seem to be
    105             # misclassified and Django would prefer the more logical place.
    106             if e[0] in self.codes_for_integrityerror:
     102        attempt = 0
     103        while True:
     104            try:
     105                return self.cursor.execute(query, args)
     106            except Database.IntegrityError, e:
    107107                raise utils.IntegrityError, utils.IntegrityError(*tuple(e)), sys.exc_info()[2]
    108             raise utils.DatabaseError, utils.DatabaseError(*tuple(e)), sys.exc_info()[2]
    109         except Database.DatabaseError, e:
    110             raise utils.DatabaseError, utils.DatabaseError(*tuple(e)), sys.exc_info()[2]
     108            except Database.OperationalError, e:
     109                # Map some error codes to IntegrityError, since they seem to be
     110                # misclassified and Django would prefer the more logical place.
     111                if e[0] in self.codes_for_integrityerror:
     112                    raise utils.IntegrityError, utils.IntegrityError(*tuple(e)), sys.exc_info()[2]
     113                #raise utils.DatabaseError, utils.DatabaseError(*tuple(e)), sys.exc_info()[2]
     114                if attempt < RETRIES:
     115                    attempt += 1
     116                    self.django_conn.reconnect()
     117                else:
     118                    raise utils.DatabaseError, utils.DatabaseError(*tuple(e)), sys.exc_info()[2]
     119            except Database.DatabaseError, e:
     120                raise utils.DatabaseError, utils.DatabaseError(*tuple(e)), sys.exc_info()[2]
     121            else:
     122                break
    111123
    112124    def executemany(self, query, args):
    113         try:
    114             return self.cursor.executemany(query, args)
    115         except Database.IntegrityError, e:
    116             raise utils.IntegrityError, utils.IntegrityError(*tuple(e)), sys.exc_info()[2]
    117         except Database.OperationalError, e:
    118             # Map some error codes to IntegrityError, since they seem to be
    119             # misclassified and Django would prefer the more logical place.
    120             if e[0] in self.codes_for_integrityerror:
     125        attempt = 0
     126        while True:
     127            try:
     128                return self.cursor.executemany(query, args)
     129            except Database.IntegrityError, e:
    121130                raise utils.IntegrityError, utils.IntegrityError(*tuple(e)), sys.exc_info()[2]
    122             raise utils.DatabaseError, utils.DatabaseError(*tuple(e)), sys.exc_info()[2]
    123         except Database.DatabaseError, e:
    124             raise utils.DatabaseError, utils.DatabaseError(*tuple(e)), sys.exc_info()[2]
     131            except Database.OperationalError, e:
     132                # Map some error codes to IntegrityError, since they seem to be
     133                # misclassified and Django would prefer the more logical place.
     134                if e[0] in self.codes_for_integrityerror:
     135                    raise utils.IntegrityError, utils.IntegrityError(*tuple(e)), sys.exc_info()[2]
     136                #raise utils.DatabaseError, utils.DatabaseError(*tuple(e)), sys.exc_info()[2]
     137                if attempt < RETRIES:
     138                    attempt += 1
     139                    self.django_conn.reconnect()
     140                else:
     141                    raise utils.DatabaseError, utils.DatabaseError(*tuple(e)), sys.exc_info()[2]
     142            except Database.DatabaseError, e:
     143                raise utils.DatabaseError, utils.DatabaseError(*tuple(e)), sys.exc_info()[2]
     144            else:
     145                break
    125146
    126147    def __getattr__(self, attr):
    127148        if attr in self.__dict__:
     
    344365                self.connection = None
    345366        return False
    346367
     368    def reconnect(self):
     369        """Connects or reconnects to the MySQL server"""
     370        kwargs = {
     371            'conv': django_conversions,
     372            'charset': 'utf8',
     373            'use_unicode': True,
     374        }
     375        settings_dict = self.settings_dict
     376        if settings_dict['USER']:
     377            kwargs['user'] = settings_dict['USER']
     378        if settings_dict['NAME']:
     379            kwargs['db'] = settings_dict['NAME']
     380        if settings_dict['PASSWORD']:
     381            kwargs['passwd'] = settings_dict['PASSWORD']
     382        if settings_dict['HOST'].startswith('/'):
     383            kwargs['unix_socket'] = settings_dict['HOST']
     384        elif settings_dict['HOST']:
     385            kwargs['host'] = settings_dict['HOST']
     386        if settings_dict['PORT']:
     387            kwargs['port'] = int(settings_dict['PORT'])
     388        # We need the number of potentially affected rows after an
     389        # "UPDATE", not the number of changed rows.
     390        kwargs['client_flag'] = CLIENT.FOUND_ROWS
     391        kwargs.update(settings_dict['OPTIONS'])
     392        self.connection = Database.connect(**kwargs)
     393        self.connection.encoders[SafeUnicode] = self.connection.encoders[unicode]
     394        self.connection.encoders[SafeString] = self.connection.encoders[str]
     395        self.features.uses_savepoints = \
     396            self.get_server_version() >= (5, 0, 3)
     397        connection_created.send(sender=self.__class__, connection=self)
     398
    347399    def _cursor(self):
    348         new_connection = False
    349         if not self._valid_connection():
    350             new_connection = True
    351             kwargs = {
    352                 'conv': django_conversions,
    353                 'charset': 'utf8',
    354                 'use_unicode': True,
    355             }
    356             settings_dict = self.settings_dict
    357             if settings_dict['USER']:
    358                 kwargs['user'] = settings_dict['USER']
    359             if settings_dict['NAME']:
    360                 kwargs['db'] = settings_dict['NAME']
    361             if settings_dict['PASSWORD']:
    362                 kwargs['passwd'] = settings_dict['PASSWORD']
    363             if settings_dict['HOST'].startswith('/'):
    364                 kwargs['unix_socket'] = settings_dict['HOST']
    365             elif settings_dict['HOST']:
    366                 kwargs['host'] = settings_dict['HOST']
    367             if settings_dict['PORT']:
    368                 kwargs['port'] = int(settings_dict['PORT'])
    369             # We need the number of potentially affected rows after an
    370             # "UPDATE", not the number of changed rows.
    371             kwargs['client_flag'] = CLIENT.FOUND_ROWS
    372             kwargs.update(settings_dict['OPTIONS'])
    373             self.connection = Database.connect(**kwargs)
    374             self.connection.encoders[SafeUnicode] = self.connection.encoders[unicode]
    375             self.connection.encoders[SafeString] = self.connection.encoders[str]
    376             self.features.uses_savepoints = \
    377                 self.get_server_version() >= (5, 0, 3)
    378             connection_created.send(sender=self.__class__, connection=self)
    379         cursor = self.connection.cursor()
    380         if new_connection:
    381             # SQL_AUTO_IS_NULL in MySQL controls whether an AUTO_INCREMENT column
    382             # on a recently-inserted row will return when the field is tested for
    383             # NULL.  Disabling this value brings this aspect of MySQL in line with
    384             # SQL standards.
    385             cursor.execute('SET SQL_AUTO_IS_NULL = 0')
    386         return CursorWrapper(cursor)
     400        attempt = 0
     401        while True:
     402            try:
     403                cursor = self.connection.cursor()
     404            except (AttributeError, Database.OperationalError), e:
     405                if attempt < RETRIES:
     406                    attempt += 1
     407                    self.reconnect()
     408                else:
     409                    raise e
     410            else:
     411                # SQL_AUTO_IS_NULL in MySQL controls whether an AUTO_INCREMENT column
     412                # on a recently-inserted row will return when the field is tested for
     413                # NULL.  Disabling this value brings this aspect of MySQL in line with
     414                # SQL standards.
     415                cursor.execute('SET SQL_AUTO_IS_NULL = 0')
     416                break
     417        return CursorWrapper(cursor, self)
    387418
    388419    def _rollback(self):
    389420        try:
Back to Top