diff options
| author | Nick Pope <nick.pope@flightdataservices.com> | 2019-07-26 22:05:22 +0100 |
|---|---|---|
| committer | Mariusz Felisiak <felisiak.mariusz@gmail.com> | 2019-08-02 11:39:01 +0200 |
| commit | 194d1dfc186cc8d2b35dabf64f3ed38b757cbd98 (patch) | |
| tree | 51ffabb34edc5b191ce8079c9149b77c88c2749e /tests | |
| parent | 955b382600e4626265cc20e5773bdbcfd01fc4af (diff) | |
Fixed #30661 -- Added models.SmallAutoField.
Diffstat (limited to 'tests')
| -rw-r--r-- | tests/db_functions/comparison/test_cast.py | 1 | ||||
| -rw-r--r-- | tests/introspection/models.py | 5 | ||||
| -rw-r--r-- | tests/introspection/tests.py | 13 | ||||
| -rw-r--r-- | tests/many_to_one/models.py | 6 | ||||
| -rw-r--r-- | tests/many_to_one/tests.py | 14 | ||||
| -rw-r--r-- | tests/migrations/test_operations.py | 48 | ||||
| -rw-r--r-- | tests/schema/tests.py | 47 |
7 files changed, 120 insertions, 14 deletions
diff --git a/tests/db_functions/comparison/test_cast.py b/tests/db_functions/comparison/test_cast.py index c5698d6d0e..988eaa4dad 100644 --- a/tests/db_functions/comparison/test_cast.py +++ b/tests/db_functions/comparison/test_cast.py @@ -55,6 +55,7 @@ class CastTests(TestCase): for field_class in ( models.AutoField, models.BigAutoField, + models.SmallAutoField, models.IntegerField, models.BigIntegerField, models.SmallIntegerField, diff --git a/tests/introspection/models.py b/tests/introspection/models.py index fa663de2fd..d069c5820e 100644 --- a/tests/introspection/models.py +++ b/tests/introspection/models.py @@ -9,6 +9,11 @@ class City(models.Model): return self.name +class Country(models.Model): + id = models.SmallAutoField(primary_key=True) + name = models.CharField(max_length=50) + + class District(models.Model): city = models.ForeignKey(City, models.CASCADE, primary_key=True) name = models.CharField(max_length=50) diff --git a/tests/introspection/tests.py b/tests/introspection/tests.py index 7edb01a4b7..4a7ce11e7a 100644 --- a/tests/introspection/tests.py +++ b/tests/introspection/tests.py @@ -5,7 +5,9 @@ from django.db.models import Index from django.db.utils import DatabaseError from django.test import TransactionTestCase, skipUnlessDBFeature -from .models import Article, ArticleReporter, City, Comment, District, Reporter +from .models import ( + Article, ArticleReporter, City, Comment, Country, District, Reporter, +) class IntrospectionTests(TransactionTestCase): @@ -115,6 +117,15 @@ class IntrospectionTests(TransactionTestCase): [connection.introspection.get_field_type(r[1], r) for r in desc], ) + @skipUnlessDBFeature('can_introspect_autofield') + def test_smallautofield(self): + with connection.cursor() as cursor: + desc = connection.introspection.get_table_description(cursor, Country._meta.db_table) + self.assertIn( + connection.features.introspected_small_auto_field_type, + [connection.introspection.get_field_type(r[1], r) for r in desc], + ) + # Regression test for #9991 - 'real' types in postgres @skipUnlessDBFeature('has_real_datatype') def test_postgresql_real_type(self): diff --git a/tests/many_to_one/models.py b/tests/many_to_one/models.py index 6230129bbd..6e00fb18fa 100644 --- a/tests/many_to_one/models.py +++ b/tests/many_to_one/models.py @@ -27,8 +27,14 @@ class Article(models.Model): return self.headline +class Country(models.Model): + id = models.SmallAutoField(primary_key=True) + name = models.CharField(max_length=50) + + class City(models.Model): id = models.BigAutoField(primary_key=True) + country = models.ForeignKey(Country, models.CASCADE, related_name='cities', null=True) name = models.CharField(max_length=50) def __str__(self): diff --git a/tests/many_to_one/tests.py b/tests/many_to_one/tests.py index e3121a7701..a926574b15 100644 --- a/tests/many_to_one/tests.py +++ b/tests/many_to_one/tests.py @@ -8,8 +8,9 @@ from django.test import TestCase from django.utils.translation import gettext_lazy from .models import ( - Article, Category, Child, ChildNullableParent, City, District, First, - Parent, Record, Relation, Reporter, School, Student, Third, ToFieldChild, + Article, Category, Child, ChildNullableParent, City, Country, District, + First, Parent, Record, Relation, Reporter, School, Student, Third, + ToFieldChild, ) @@ -576,6 +577,15 @@ class ManyToOneTests(TestCase): District.objects.create(city=ny, name='Brooklyn') District.objects.create(city=ny, name='Manhattan') + def test_fk_to_smallautofield(self): + us = Country.objects.create(name='United States') + City.objects.create(country=us, name='Chicago') + City.objects.create(country=us, name='New York') + + uk = Country.objects.create(name='United Kingdom', id=2 ** 11) + City.objects.create(country=uk, name='London') + City.objects.create(country=uk, name='Edinburgh') + def test_multiple_foreignkeys(self): # Test of multiple ForeignKeys to the same model (bug #7125). c1 = Category.objects.create(name='First') diff --git a/tests/migrations/test_operations.py b/tests/migrations/test_operations.py index 3b2129a933..3c321d4cb4 100644 --- a/tests/migrations/test_operations.py +++ b/tests/migrations/test_operations.py @@ -2651,9 +2651,13 @@ class OperationTests(OperationTestBase): fill_data.state_forwards("fill_data", new_state) fill_data.database_forwards("fill_data", editor, project_state, new_state) - def test_autofield_foreignfield_growth(self): + def _test_autofield_foreignfield_growth(self, source_field, target_field, target_value): """ - A field may be migrated from AutoField to BigAutoField. + A field may be migrated in the following ways: + + - AutoField to BigAutoField + - SmallAutoField to AutoField + - SmallAutoField to BigAutoField """ def create_initial_data(models, schema_editor): Article = models.get_model("test_article", "Article") @@ -2665,14 +2669,14 @@ class OperationTests(OperationTestBase): def create_big_data(models, schema_editor): Article = models.get_model("test_article", "Article") Blog = models.get_model("test_blog", "Blog") - blog2 = Blog.objects.create(name="Frameworks", id=2 ** 33) + blog2 = Blog.objects.create(name="Frameworks", id=target_value) Article.objects.create(name="Django", blog=blog2) - Article.objects.create(id=2 ** 33, name="Django2", blog=blog2) + Article.objects.create(id=target_value, name="Django2", blog=blog2) create_blog = migrations.CreateModel( "Blog", [ - ("id", models.AutoField(primary_key=True)), + ("id", source_field(primary_key=True)), ("name", models.CharField(max_length=100)), ], options={}, @@ -2680,7 +2684,7 @@ class OperationTests(OperationTestBase): create_article = migrations.CreateModel( "Article", [ - ("id", models.AutoField(primary_key=True)), + ("id", source_field(primary_key=True)), ("blog", models.ForeignKey(to="test_blog.Blog", on_delete=models.CASCADE)), ("name", models.CharField(max_length=100)), ("data", models.TextField(default="")), @@ -2690,8 +2694,8 @@ class OperationTests(OperationTestBase): fill_initial_data = migrations.RunPython(create_initial_data, create_initial_data) fill_big_data = migrations.RunPython(create_big_data, create_big_data) - grow_article_id = migrations.AlterField("Article", "id", models.BigAutoField(primary_key=True)) - grow_blog_id = migrations.AlterField("Blog", "id", models.BigAutoField(primary_key=True)) + grow_article_id = migrations.AlterField('Article', 'id', target_field(primary_key=True)) + grow_blog_id = migrations.AlterField('Blog', 'id', target_field(primary_key=True)) project_state = ProjectState() new_state = project_state.clone() @@ -2719,7 +2723,7 @@ class OperationTests(OperationTestBase): state = new_state.clone() article = state.apps.get_model("test_article.Article") - self.assertIsInstance(article._meta.pk, models.BigAutoField) + self.assertIsInstance(article._meta.pk, target_field) project_state = new_state new_state = new_state.clone() @@ -2729,7 +2733,7 @@ class OperationTests(OperationTestBase): state = new_state.clone() blog = state.apps.get_model("test_blog.Blog") - self.assertIsInstance(blog._meta.pk, models.BigAutoField) + self.assertIsInstance(blog._meta.pk, target_field) project_state = new_state new_state = new_state.clone() @@ -2737,6 +2741,30 @@ class OperationTests(OperationTestBase): fill_big_data.state_forwards("fill_big_data", new_state) fill_big_data.database_forwards("fill_big_data", editor, project_state, new_state) + def test_autofield__bigautofield_foreignfield_growth(self): + """A field may be migrated from AutoField to BigAutoField.""" + self._test_autofield_foreignfield_growth( + models.AutoField, + models.BigAutoField, + 2 ** 33, + ) + + def test_smallfield_autofield_foreignfield_growth(self): + """A field may be migrated from SmallAutoField to AutoField.""" + self._test_autofield_foreignfield_growth( + models.SmallAutoField, + models.AutoField, + 2 ** 22, + ) + + def test_smallfield_bigautofield_foreignfield_growth(self): + """A field may be migrated from SmallAutoField to BigAutoField.""" + self._test_autofield_foreignfield_growth( + models.SmallAutoField, + models.BigAutoField, + 2 ** 33, + ) + def test_run_python_noop(self): """ #24098 - Tests no-op RunPython operations. diff --git a/tests/schema/tests.py b/tests/schema/tests.py index a765528d50..7276912c71 100644 --- a/tests/schema/tests.py +++ b/tests/schema/tests.py @@ -14,7 +14,8 @@ from django.db.models.deletion import CASCADE, PROTECT from django.db.models.fields import ( AutoField, BigAutoField, BigIntegerField, BinaryField, BooleanField, CharField, DateField, DateTimeField, IntegerField, PositiveIntegerField, - SlugField, TextField, TimeField, UUIDField, + SlugField, SmallAutoField, SmallIntegerField, TextField, TimeField, + UUIDField, ) from django.db.models.fields.related import ( ForeignKey, ForeignObject, ManyToManyField, OneToOneField, @@ -1179,6 +1180,28 @@ class SchemaTests(TransactionTestCase): # Fail on PostgreSQL if sequence is missing an owner. self.assertIsNotNone(Author.objects.create(name='Bar')) + def test_alter_autofield_pk_to_smallautofield_pk_sequence_owner(self): + """ + Converting an implicit PK to SmallAutoField(primary_key=True) should + keep a sequence owner on PostgreSQL. + """ + with connection.schema_editor() as editor: + editor.create_model(Author) + old_field = Author._meta.get_field('id') + new_field = SmallAutoField(primary_key=True) + new_field.set_attributes_from_name('id') + new_field.model = Author + with connection.schema_editor() as editor: + editor.alter_field(Author, old_field, new_field, strict=True) + + Author.objects.create(name='Foo', pk=1) + with connection.cursor() as cursor: + sequence_reset_sqls = connection.ops.sequence_reset_sql(no_style(), [Author]) + if sequence_reset_sqls: + cursor.execute(sequence_reset_sqls[0]) + # Fail on PostgreSQL if sequence is missing an owner. + self.assertIsNotNone(Author.objects.create(name='Bar')) + def test_alter_int_pk_to_autofield_pk(self): """ Should be able to rename an IntegerField(primary_key=True) to @@ -1211,6 +1234,28 @@ class SchemaTests(TransactionTestCase): with connection.schema_editor() as editor: editor.alter_field(IntegerPK, old_field, new_field, strict=True) + @isolate_apps('schema') + def test_alter_smallint_pk_to_smallautofield_pk(self): + """ + Should be able to rename an SmallIntegerField(primary_key=True) to + SmallAutoField(primary_key=True). + """ + class SmallIntegerPK(Model): + i = SmallIntegerField(primary_key=True) + + class Meta: + app_label = 'schema' + + with connection.schema_editor() as editor: + editor.create_model(SmallIntegerPK) + self.isolated_local_models = [SmallIntegerPK] + old_field = SmallIntegerPK._meta.get_field('i') + new_field = SmallAutoField(primary_key=True) + new_field.model = SmallIntegerPK + new_field.set_attributes_from_name('i') + with connection.schema_editor() as editor: + editor.alter_field(SmallIntegerPK, old_field, new_field, strict=True) + def test_alter_int_pk_to_int_unique(self): """ Should be able to rename an IntegerField(primary_key=True) to |
