summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--django/db/backends/postgresql/base.py7
-rw-r--r--django/db/backends/postgresql_psycopg2/base.py7
-rw-r--r--tests/regressiontests/backends/models.py18
-rw-r--r--tests/regressiontests/backends/tests.py46
4 files changed, 72 insertions, 6 deletions
diff --git a/django/db/backends/postgresql/base.py b/django/db/backends/postgresql/base.py
index 5e47a37d3f..12631785bc 100644
--- a/django/db/backends/postgresql/base.py
+++ b/django/db/backends/postgresql/base.py
@@ -153,6 +153,13 @@ class DatabaseWrapper(BaseDatabaseWrapper):
cursor.execute("SET client_encoding to 'UNICODE'")
return UnicodeCursorWrapper(cursor, 'utf-8')
+ def _commit(self):
+ if self.connection is not None:
+ try:
+ return self.connection.commit()
+ except Database.IntegrityError, e:
+ raise utils.IntegrityError, utils.IntegrityError(*tuple(e)), sys.exc_info()[2]
+
def typecast_string(s):
"""
Cast all returned strings to unicode strings.
diff --git a/django/db/backends/postgresql_psycopg2/base.py b/django/db/backends/postgresql_psycopg2/base.py
index 9e5fb53d56..71ec58153a 100644
--- a/django/db/backends/postgresql_psycopg2/base.py
+++ b/django/db/backends/postgresql_psycopg2/base.py
@@ -192,3 +192,10 @@ class DatabaseWrapper(BaseDatabaseWrapper):
finally:
self.isolation_level = level
self.features.uses_savepoints = bool(level)
+
+ def _commit(self):
+ if self.connection is not None:
+ try:
+ return self.connection.commit()
+ except Database.IntegrityError, e:
+ raise utils.IntegrityError, utils.IntegrityError(*tuple(e)), sys.exc_info()[2]
diff --git a/tests/regressiontests/backends/models.py b/tests/regressiontests/backends/models.py
index 3ad4a60c02..89e3fd27ff 100644
--- a/tests/regressiontests/backends/models.py
+++ b/tests/regressiontests/backends/models.py
@@ -1,8 +1,7 @@
from django.contrib.contenttypes import generic
from django.contrib.contenttypes.models import ContentType
-from django.conf import settings
from django.db import models
-from django.db import connection, DEFAULT_DB_ALIAS
+from django.db import connection
class Square(models.Model):
@@ -55,3 +54,18 @@ class Post(models.Model):
db_table = 'CaseSensitive_Post'
+class Reporter(models.Model):
+ first_name = models.CharField(max_length=30)
+ last_name = models.CharField(max_length=30)
+
+ 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
diff --git a/tests/regressiontests/backends/tests.py b/tests/regressiontests/backends/tests.py
index c5d13285d3..e457629880 100644
--- a/tests/regressiontests/backends/tests.py
+++ b/tests/regressiontests/backends/tests.py
@@ -2,13 +2,11 @@
# Unit and doctests for specific database backends.
import datetime
-from django.conf import settings
-from django.core import management
from django.core.management.color import no_style
-from django.db import backend, connection, connections, DEFAULT_DB_ALIAS
+from django.db import backend, connection, connections, DEFAULT_DB_ALIAS, IntegrityError
from django.db.backends.signals import connection_created
from django.db.backends.postgresql import version as pg_version
-from django.test import TestCase, skipUnlessDBFeature
+from django.test import TestCase, skipUnlessDBFeature, TransactionTestCase
from django.utils import unittest
from regressiontests.backends import models
@@ -225,3 +223,43 @@ class BackendTestCase(TestCase):
self.assertEqual(list(cursor.fetchmany(2)), [(u'Jane', u'Doe'), (u'John', u'Doe')])
self.assertEqual(list(cursor.fetchall()), [(u'Mary', u'Agnelline'), (u'Peter', u'Parker')])
+
+# We don't make these tests conditional because that means we would need to
+# check and differentiate between:
+# * MySQL+InnoDB, MySQL+MYISAM (something we currently can't do).
+# * if sqlite3 (if/once we get #14204 fixed) has referential integrity turned
+# on or not, something that would be controlled by runtime support and user
+# preference.
+# verify if its type is django.database.db.IntegrityError.
+
+class FkConstraintsTests(TransactionTestCase):
+
+ def setUp(self):
+ # Create a Reporter.
+ self.r = models.Reporter.objects.create(first_name='John', last_name='Smith')
+
+ def test_integrity_checks_on_creation(self):
+ """
+ Try to create a model instance that violates a FK constraint. If it
+ fails it should fail with IntegrityError.
+ """
+ a = models.Article(headline="This is a test", pub_date=datetime.datetime(2005, 7, 27), reporter_id=30)
+ try:
+ a.save()
+ except IntegrityError:
+ pass
+
+ def test_integrity_checks_on_update(self):
+ """
+ Try to update a model instance introducing a FK constraint violation.
+ If it fails it should fail with IntegrityError.
+ """
+ # Create an Article.
+ models.Article.objects.create(headline="Test article", pub_date=datetime.datetime(2010, 9, 4), reporter=self.r)
+ # Retrive it from the DB
+ a = models.Article.objects.get(headline="Test article")
+ a.reporter_id = 30
+ try:
+ a.save()
+ except IntegrityError:
+ pass