Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

Fixed #8575 -- Catch one particular instance of OperationalError in M…

…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...
commit 90279aeaf07222dd7388956bfd465d30365087a5 1 parent 54f41e3
Malcolm Tredinnick authored August 29, 2008

Showing 1 changed file with 43 additions and 1 deletion. Show diff stats Hide diff stats

  1. 44  django/db/backends/mysql/base.py
44  django/db/backends/mysql/base.py
@@ -65,6 +65,48 @@
65 65
 # standard util.CursorDebugWrapper can be used. Also, using sql_mode
66 66
 # TRADITIONAL will automatically cause most warnings to be treated as errors.
67 67
 
  68
+class CursorWrapper(object):
  69
+    """
  70
+    A thin wrapper around MySQLdb's normal cursor class so that we can catch
  71
+    particular exception instances and reraise them with the right types.
  72
+
  73
+    Implemented as a wrapper, rather than a subclass, so that we aren't stuck
  74
+    to the particular underlying representation returned by Connection.cursor().
  75
+    """
  76
+    codes_for_integrityerror = (1048,)
  77
+
  78
+    def __init__(self, cursor):
  79
+        self.cursor = cursor
  80
+
  81
+    def execute(self, query, args=None):
  82
+        try:
  83
+            return self.cursor.execute(query, args)
  84
+        except Database.OperationalError, e:
  85
+            # Map some error codes to IntegrityError, since they seem to be
  86
+            # misclassified and Django would prefer the more logical place.
  87
+            if e[0] in self.codes_for_integrityerror:
  88
+                raise Database.IntegrityError(tuple(e))
  89
+            raise
  90
+
  91
+    def executemany(self, query, args):
  92
+        try:
  93
+            return self.cursor.executemany(query, args)
  94
+        except Database.OperationalError, e:
  95
+            # Map some error codes to IntegrityError, since they seem to be
  96
+            # misclassified and Django would prefer the more logical place.
  97
+            if e[0] in self.codes_for_integrityerror:
  98
+                raise Database.IntegrityError(tuple(e))
  99
+            raise
  100
+
  101
+    def __getattr__(self, attr):
  102
+        if attr in self.__dict__:
  103
+            return self.__dict__[attr]
  104
+        else:
  105
+            return getattr(self.cursor, attr)
  106
+
  107
+    def __iter__(self):
  108
+        return iter(self.cursor)
  109
+
68 110
 class DatabaseFeatures(BaseDatabaseFeatures):
69 111
     empty_fetchmany_value = ()
70 112
     update_can_self_select = False
@@ -207,7 +249,7 @@ def _cursor(self, settings):
207 249
                 kwargs['port'] = int(settings.DATABASE_PORT)
208 250
             kwargs.update(self.options)
209 251
             self.connection = Database.connect(**kwargs)
210  
-        cursor = self.connection.cursor()
  252
+        cursor = CursorWrapper(self.connection.cursor())
211 253
         return cursor
212 254
 
213 255
     def _rollback(self):

0 notes on commit 90279ae

Please sign in to comment.
Something went wrong with that request. Please try again.