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.py16
-rw-r--r--tests/regressiontests/backends/tests.py50
4 files changed, 75 insertions, 5 deletions
diff --git a/django/db/backends/postgresql/base.py b/django/db/backends/postgresql/base.py
index f84ad1da61..5f4d791f02 100644
--- a/django/db/backends/postgresql/base.py
+++ b/django/db/backends/postgresql/base.py
@@ -150,6 +150,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 ce4e48330e..c9f1af1669 100644
--- a/django/db/backends/postgresql_psycopg2/base.py
+++ b/django/db/backends/postgresql_psycopg2/base.py
@@ -189,3 +189,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 4ab00414db..ea7ff96b91 100644
--- a/tests/regressiontests/backends/models.py
+++ b/tests/regressiontests/backends/models.py
@@ -1,5 +1,4 @@
from django.db import models
-from django.db import connection
class Square(models.Model):
root = models.IntegerField()
@@ -21,3 +20,18 @@ class SchoolClass(models.Model):
last_updated = models.DateTimeField()
+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 d955a098af..005fc4d86e 100644
--- a/tests/regressiontests/backends/tests.py
+++ b/tests/regressiontests/backends/tests.py
@@ -1,13 +1,15 @@
# -*- coding: utf-8 -*-
# Unit and doctests for specific database backends.
import datetime
-import models
import unittest
-from django.db import backend, connection, DEFAULT_DB_ALIAS
+
+from django.conf import settings
+from django.db import backend, connection, DEFAULT_DB_ALIAS, IntegrityError
from django.db.backends.signals import connection_created
from django.db.backends.postgresql import version as pg_version
-from django.conf import settings
-from django.test import TestCase
+from django.test import TestCase, TransactionTestCase
+
+import models
class Callproc(unittest.TestCase):
@@ -141,6 +143,46 @@ class BackendTestCase(TestCase):
cursor.executemany(query, [])
self.assertEqual(models.Square.objects.count(), 11)
+
+# 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
def test_unicode_fetches(self):
#6254: fetchone, fetchmany, fetchall return strings as unicode objects
qn = connection.ops.quote_name