diff --git a/django/db/backends/__init__.py b/django/db/backends/__init__.py
index ebe8875..a94a2f7 100644
a
|
b
|
class BaseDatabaseOperations(object):
|
762 | 762 | # need not necessarily be implemented using "LIKE" in the backend. |
763 | 763 | prep_for_iexact_query = prep_for_like_query |
764 | 764 | |
| 765 | def validate_autopk_value(self, value): |
| 766 | """ |
| 767 | Certain backends does not accept certain values for primary key |
| 768 | (for example zero in MySQL). It raises ValueError if value is invalid |
| 769 | otherwise it returns validated value. |
| 770 | """ |
| 771 | return value |
| 772 | |
765 | 773 | def value_to_db_date(self, value): |
766 | 774 | """ |
767 | 775 | Transform a date value to an object compatible with what is expected |
diff --git a/django/db/backends/mysql/base.py b/django/db/backends/mysql/base.py
index 830808b..4791699 100644
a
|
b
|
class DatabaseOperations(BaseDatabaseOperations):
|
257 | 257 | else: |
258 | 258 | return [] |
259 | 259 | |
| 260 | def validate_autopk_value(self, value): |
| 261 | if value == 0: |
| 262 | raise ValueError('The database backend does not accept %s as a ' |
| 263 | 'value for AutoField.' % (value,)) |
| 264 | return value |
| 265 | |
260 | 266 | def value_to_db_datetime(self, value): |
261 | 267 | if value is None: |
262 | 268 | return None |
diff --git a/django/db/models/fields/__init__.py b/django/db/models/fields/__init__.py
index 22546c2..f85ce4b 100644
a
|
b
|
class AutoField(Field):
|
531 | 531 | def validate(self, value, model_instance): |
532 | 532 | pass |
533 | 533 | |
| 534 | def get_db_prep_value(self, value, connection, prepared=False): |
| 535 | if not prepared: |
| 536 | value = self.get_prep_value(value) |
| 537 | value = connection.ops.validate_autopk_value(value) |
| 538 | return value |
| 539 | |
534 | 540 | def get_prep_value(self, value): |
535 | 541 | if value is None: |
536 | 542 | return None |
diff --git a/tests/regressiontests/backends/tests.py b/tests/regressiontests/backends/tests.py
index cfb662e..54d7003 100644
a
|
b
|
from django.db import (backend, connection, connections, DEFAULT_DB_ALIAS,
|
13 | 13 | from django.db.backends.signals import connection_created |
14 | 14 | from django.db.backends.postgresql_psycopg2 import version as pg_version |
15 | 15 | from django.db.utils import ConnectionHandler, DatabaseError, load_backend |
16 | | from django.test import TestCase, skipUnlessDBFeature, TransactionTestCase |
| 16 | from django.test import (TestCase, skipUnlessDBFeature, skipIfDBFeature, |
| 17 | TransactionTestCase) |
17 | 18 | from django.test.utils import override_settings |
18 | 19 | from django.utils import unittest |
19 | | |
20 | 20 | from . import models |
21 | 21 | |
22 | 22 | |
… |
… |
class BackendLoadingTests(TestCase):
|
618 | 618 | self.assertRaisesRegexp(ImproperlyConfigured, |
619 | 619 | "Try using django.db.backends.sqlite3 instead", |
620 | 620 | load_backend, 'sqlite3') |
| 621 | |
| 622 | |
| 623 | class MySQLPKZeroTests(TestCase): |
| 624 | """ |
| 625 | Zero as id for AutoField should raise exception in MySQL, because MySQL |
| 626 | does not allow zero for automatic primary key. |
| 627 | """ |
| 628 | |
| 629 | @skipIfDBFeature('allows_primary_key_0') |
| 630 | def test_zero_as_autoval(self): |
| 631 | with self.assertRaises(ValueError): |
| 632 | models.Square.objects.create(id=0, root=0, square=1) |
| 633 | No newline at end of file |
diff --git a/tests/regressiontests/bulk_create/tests.py b/tests/regressiontests/bulk_create/tests.py
index 0fa142b..7cd51f4 100644
a
|
b
|
from __future__ import with_statement, absolute_import
|
2 | 2 | |
3 | 3 | from operator import attrgetter |
4 | 4 | |
5 | | from django.test import TestCase, skipUnlessDBFeature |
| 5 | from django.test import TestCase, skipIfDBFeature, skipUnlessDBFeature |
6 | 6 | |
7 | 7 | from .models import Country, Restaurant, Pizzeria, State |
8 | 8 | |
… |
… |
class BulkCreateTests(TestCase):
|
56 | 56 | ]) |
57 | 57 | self.assertQuerysetEqual(State.objects.order_by("two_letter_code"), [ |
58 | 58 | "CA", "IL", "ME", "NY", |
59 | | ], attrgetter("two_letter_code")) |
60 | | No newline at end of file |
| 59 | ], attrgetter("two_letter_code")) |
| 60 | |
| 61 | @skipIfDBFeature('allows_primary_key_0') |
| 62 | def test_zero_as_autoval(self): |
| 63 | """ |
| 64 | Zero as id for AutoField should raise exception in MySQL, because MySQL |
| 65 | does not allow zero for automatic primary key. |
| 66 | """ |
| 67 | |
| 68 | valid_country = Country(name='Germany', iso_two_letter='DE') |
| 69 | invalid_country = Country(id=0, name='Poland', iso_two_letter='PL') |
| 70 | with self.assertRaises(ValueError): |
| 71 | Country.objects.bulk_create([valid_country, invalid_country]) |
| 72 | No newline at end of file |