#29575: MySQL error code 1062 (duplicate entry for key) raises
MySQLdb.IntegrityError, not django.db.IntegrityError
------------------------------------------+------------------------
               Reporter:  Simon Willison  |          Owner:  nobody
                   Type:  Uncategorized   |         Status:  new
              Component:  Uncategorized   |        Version:  2.0
               Severity:  Normal          |       Keywords:
           Triage Stage:  Unreviewed      |      Has patch:  0
    Needs documentation:  0               |    Needs tests:  0
Patch needs improvement:  0               |  Easy pickings:  0
                  UI/UX:  0               |
------------------------------------------+------------------------
 If you have a UNIQUE KEY on a MySQL table and you attempt to create a
 duplicate row, Django raises an IntegrityError... but it's a
 `MySQLdb.IntegrityError`, not a `django.db.IntegrityError`.

 For example, consider a user model with an other_system_id column that is
 created as a unique key - a model that looks something like this:

 {{{
 class User(models.Model):
     other_system_id = models.CharField(max_length=32, unique=True)
 }}}

 If you create a row with other_system_id="142" and then try to create a
 duplicate, this happens:

 {{{
 In [4]: try:
    ...:     u = User.objects.create(other_system_id="142")
    ...: except Exception as e:
    ...:     print(e, e.__class__)
    ...:
 (IntegrityError(1062, "Duplicate entry '142' for key 'other_system_id='"),
 <class '_mysql_exceptions.IntegrityError'>)
 }}}

 Note that this is NOT a `django.db.IntegrityError` - it's a
 `MySQLdb.IntegrityError`. This is confusing (we just spent a while
 debugging this, since as far as we could tell an IntegrityError was being
 raised but not caught).

 It looks to me like the fix for this would be to add code 1062 ("Duplicate
 entry for key") to the `codes_for_integrityerror` set in the MySQLdb
 backend:
 
https://github.com/django/django/blob/dd82f3327124fd2762cf6df2ac8c6380772bf127/django/db/backends/mysql/base.py#L60-L63

 Until 11 months ago that set contained just 1048 ("Column cannot be null")
 - then in
 
https://github.com/django/django/commit/dd82f3327124fd2762cf6df2ac8c6380772bf127
 we added 1690, ("BIGINT UNSIGNED value is out of range") to fix #27979

 Is there any reason we shouldn't also catch 1062 ("Duplicate entry for
 key") and convert that into a `django.db.IntegrityError` exception?

-- 
Ticket URL: <https://code.djangoproject.com/ticket/29575>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.

-- 
You received this message because you are subscribed to the Google Groups 
"Django updates" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To post to this group, send email to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-updates/049.280b9e55b7808512b9d339ebc89bb866%40djangoproject.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to