#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.