Author: mtredinnick
Date: 2008-08-28 23:30:07 -0500 (Thu, 28 Aug 2008)
New Revision: 8692

Modified:
   django/trunk/django/db/backends/mysql/base.py
Log:
Fixed #8575 -- Catch one particular instance of OperationalError in MySQL 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.


Modified: django/trunk/django/db/backends/mysql/base.py
===================================================================
--- django/trunk/django/db/backends/mysql/base.py       2008-08-29 02:40:56 UTC 
(rev 8691)
+++ django/trunk/django/db/backends/mysql/base.py       2008-08-29 04:30:07 UTC 
(rev 8692)
@@ -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
@@ -207,7 +249,7 @@
                 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):


--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups 
"Django updates" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at 
http://groups.google.com/group/django-updates?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to