Navigation Menu

Skip to content

Commit

Permalink
Fixed #8575 -- Catch one particular instance of OperationalError in M…
Browse files Browse the repository at this point in the history
…ySQL and

convert it to an IntegrityError, which seems like the more natural case (and is
consistent with other backends). This makes exception handling in Django much
easier.

The solution is extensible for any other error codes we may wish to add going
forwards.


git-svn-id: http://code.djangoproject.com/svn/django/trunk@8692 bcc190cf-cafb-0310-a4f2-bffc1f526a37
  • Loading branch information
malcolmt committed Aug 29, 2008
1 parent 54f41e3 commit 90279ae
Showing 1 changed file with 43 additions and 1 deletion.
44 changes: 43 additions & 1 deletion django/db/backends/mysql/base.py
Expand Up @@ -65,6 +65,48 @@
# standard util.CursorDebugWrapper can be used. Also, using sql_mode
# TRADITIONAL will automatically cause most warnings to be treated as errors.

class CursorWrapper(object):
"""
A thin wrapper around MySQLdb's normal cursor class so that we can catch
particular exception instances and reraise them with the right types.
Implemented as a wrapper, rather than a subclass, so that we aren't stuck
to the particular underlying representation returned by Connection.cursor().
"""
codes_for_integrityerror = (1048,)

def __init__(self, cursor):
self.cursor = cursor

def execute(self, query, args=None):
try:
return self.cursor.execute(query, args)
except Database.OperationalError, e:
# Map some error codes to IntegrityError, since they seem to be
# misclassified and Django would prefer the more logical place.
if e[0] in self.codes_for_integrityerror:
raise Database.IntegrityError(tuple(e))
raise

def executemany(self, query, args):
try:
return self.cursor.executemany(query, args)
except Database.OperationalError, e:
# Map some error codes to IntegrityError, since they seem to be
# misclassified and Django would prefer the more logical place.
if e[0] in self.codes_for_integrityerror:
raise Database.IntegrityError(tuple(e))
raise

def __getattr__(self, attr):
if attr in self.__dict__:
return self.__dict__[attr]
else:
return getattr(self.cursor, attr)

def __iter__(self):
return iter(self.cursor)

class DatabaseFeatures(BaseDatabaseFeatures):
empty_fetchmany_value = ()
update_can_self_select = False
Expand Down Expand Up @@ -207,7 +249,7 @@ def _cursor(self, settings):
kwargs['port'] = int(settings.DATABASE_PORT)
kwargs.update(self.options)
self.connection = Database.connect(**kwargs)
cursor = self.connection.cursor()
cursor = CursorWrapper(self.connection.cursor())
return cursor

def _rollback(self):
Expand Down

0 comments on commit 90279ae

Please sign in to comment.