#14223: Inconsistent exception raising on DB integrity errors
---------------------------------------------------+------------------------
          Reporter:  ramiro                        |         Owner:  ramiro     
                
            Status:  assigned                      |     Milestone:             
                
         Component:  Database layer (models, ORM)  |       Version:  SVN        
                
        Resolution:                                |      Keywords:  
integrityerror backends orm
             Stage:  Accepted                      |     Has_patch:  1          
                
        Needs_docs:  0                             |   Needs_tests:  0          
                
Needs_better_patch:  0                             |  
---------------------------------------------------+------------------------
Old description:

> It seems we aren't capturing the `<db api driver module>.IntegrityError`
> exceptions raised when `connection.commit() is executed` in the same way
> we do in `execute()`.
>
> Found this while creating tests to verify FK constraint in sqlite
> (#14304). My `assertRaises(django.db.[utils.]IntegrityError, ...)`
> weren't being triggered and printing the exception type shows `<class
> 'pysqlite2.dbapi2.IntegrityError'>`. Same thing happens now with postgres
> (see below).
>
> The `DatabaseError` and `IntegrityError` unification was introduced in
> r12352, if this is confirmed as an issue it wouldn't be a regression in
> 1.2, but a 1.2 feature introduced in an incomplete fashion.
>
> The two files pasted at the end form a small test case. When run under
> postgres you see:
>
> {{{
> ======================================================================
> ERROR: Try to create a model instance that violates a FK constraint.
> Should fail
> ----------------------------------------------------------------------
> Traceback (most recent call last):
>   File
> "/home/r/django/sqlite_fk2/tests/regressiontests/fk_constraints/tests.py",
> line 22, in test_integrity_checks_on_creation
>     a.save()
>   File "/home/r/django/sqlite_fk2/django/db/models/base.py", line 434, in
> save
>     self.save_base(using=using, force_insert=force_insert,
> force_update=force_update)
>   File "/home/r/django/sqlite_fk2/django/db/models/base.py", line 534, in
> save_base
>     transaction.commit_unless_managed(using=using)
>   File "/home/r/django/sqlite_fk2/django/db/transaction.py", line 175, in
> commit_unless_managed
>     connection._commit()
>   File "/home/r/django/sqlite_fk2/django/db/backends/__init__.py", line
> 32, in _commit
>     return self.connection.commit()
> IntegrityError: insert or update on table "fk_constraints_article"
> violates foreign key constraint "fk_constraints_article_reporter_id_fkey"
> DETAIL:  Key (reporter_id)=(30) is not present in table
> "fk_constraints_reporter".
>
> <class 'psycopg2.IntegrityError'>
> }}}
>
> {{{
> #!python
> # models.py
> from django.db import models
>
> class Reporter(models.Model):
>     first_name = models.CharField(max_length=30)
>     last_name = models.CharField(max_length=30)
>     email = models.EmailField()
>
>     def __unicode__(self):
>         return u"%s %s" % (self.first_name, self.last_name)
>
> class Article(models.Model):
>     headline = models.CharField(max_length=100)
>     pub_date = models.DateField()
>     reporter = models.ForeignKey(Reporter)
>
>     def __unicode__(self):
>         return self.headline
>
>     class Meta:
>         ordering = ('headline',)
> }}}
>
> {{{
> #!python
> # tests.py
> from datetime import datetime
>
> from django.db import utils
> from django.test import TransactionTestCase
>
> from models import Reporter, Article
>
> import sys
>
> class FkConstraintsTest(TransactionTestCase):
>
>     def setUp(self):
>         # Create a Reporter.
>         self.r = Reporter.objects.create(first_name='John',
> last_name='Smith', email='[email protected]')
>         #self.r2 = Reporterobjects.create(first_name='Paul',
> last_name='Jones', email='[email protected]')
>
>     def test_integrity_checks_on_creation(self):
>         """Try to create a model instance that violates a FK constraint.
> Should fail"""
>         a = Article(headline="This is a test", pub_date=datetime(2005, 7,
> 27), reporter_id=30)
>         #self.assertRaises(utils.IntegrityError, a.save)
>         try:
>             a.save()
>         except Exception, e:
>             print >>sys.stderr, type(e)
>             raise
>
>     def test_integrity_checks_on_update(self):
>         """Try to update a model instance introducing a FK constraint
> violation. Should fail"""
>         # Create an Article.
>         Article.objects.create(headline="Test article",
> pub_date=datetime(2010, 9, 4), reporter=self.r)
>         # Retrive it from the DB
>         a = Article.objects.get(headline="Test article")
>         a.reporter_id = 30
>         #self.assertRaises(utils.IntegrityError, a.save)
>         try:
>             a.save()
>         except Exception, e:
>             print >>sys.stderr, type(e)
>             raise
> }}}

New description:

 It seems we aren't capturing the `<db api driver module>.IntegrityError`
 exceptions raised when `connection.commit() is executed` in the same way
 we do in `execute()`.

 Found this while creating tests to verify FK constraint in sqlite
 (#14204). My `assertRaises(django.db.[utils.]IntegrityError, ...)` weren't
 being triggered and printing the exception type shows `<class
 'pysqlite2.dbapi2.IntegrityError'>`. Same thing happens now with postgres
 (see below).

 The `DatabaseError` and `IntegrityError` unification was introduced in
 r12352, if this is confirmed as an issue it wouldn't be a regression in
 1.2, but a 1.2 feature introduced in an incomplete fashion.

 The two files pasted at the end form a small test case. When run under
 postgres you see:

 {{{
 ======================================================================
 ERROR: Try to create a model instance that violates a FK constraint.
 Should fail
 ----------------------------------------------------------------------
 Traceback (most recent call last):
   File
 "/home/r/django/sqlite_fk2/tests/regressiontests/fk_constraints/tests.py",
 line 22, in test_integrity_checks_on_creation
     a.save()
   File "/home/r/django/sqlite_fk2/django/db/models/base.py", line 434, in
 save
     self.save_base(using=using, force_insert=force_insert,
 force_update=force_update)
   File "/home/r/django/sqlite_fk2/django/db/models/base.py", line 534, in
 save_base
     transaction.commit_unless_managed(using=using)
   File "/home/r/django/sqlite_fk2/django/db/transaction.py", line 175, in
 commit_unless_managed
     connection._commit()
   File "/home/r/django/sqlite_fk2/django/db/backends/__init__.py", line
 32, in _commit
     return self.connection.commit()
 IntegrityError: insert or update on table "fk_constraints_article"
 violates foreign key constraint "fk_constraints_article_reporter_id_fkey"
 DETAIL:  Key (reporter_id)=(30) is not present in table
 "fk_constraints_reporter".

 <class 'psycopg2.IntegrityError'>
 }}}

 {{{
 #!python
 # models.py
 from django.db import models

 class Reporter(models.Model):
     first_name = models.CharField(max_length=30)
     last_name = models.CharField(max_length=30)
     email = models.EmailField()

     def __unicode__(self):
         return u"%s %s" % (self.first_name, self.last_name)

 class Article(models.Model):
     headline = models.CharField(max_length=100)
     pub_date = models.DateField()
     reporter = models.ForeignKey(Reporter)

     def __unicode__(self):
         return self.headline

     class Meta:
         ordering = ('headline',)
 }}}

 {{{
 #!python
 # tests.py
 from datetime import datetime

 from django.db import utils
 from django.test import TransactionTestCase

 from models import Reporter, Article

 import sys

 class FkConstraintsTest(TransactionTestCase):

     def setUp(self):
         # Create a Reporter.
         self.r = Reporter.objects.create(first_name='John',
 last_name='Smith', email='[email protected]')
         #self.r2 = Reporterobjects.create(first_name='Paul',
 last_name='Jones', email='[email protected]')

     def test_integrity_checks_on_creation(self):
         """Try to create a model instance that violates a FK constraint.
 Should fail"""
         a = Article(headline="This is a test", pub_date=datetime(2005, 7,
 27), reporter_id=30)
         #self.assertRaises(utils.IntegrityError, a.save)
         try:
             a.save()
         except Exception, e:
             print >>sys.stderr, type(e)
             raise

     def test_integrity_checks_on_update(self):
         """Try to update a model instance introducing a FK constraint
 violation. Should fail"""
         # Create an Article.
         Article.objects.create(headline="Test article",
 pub_date=datetime(2010, 9, 4), reporter=self.r)
         # Retrive it from the DB
         a = Article.objects.get(headline="Test article")
         a.reporter_id = 30
         #self.assertRaises(utils.IntegrityError, a.save)
         try:
             a.save()
         except Exception, e:
             print >>sys.stderr, type(e)
             raise
 }}}

-- 
Ticket URL: <http://code.djangoproject.com/ticket/14223#comment:3>
Django <http://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 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