diff --git a/AUTHORS b/AUTHORS index 628fc6426c..36f1f5d492 100644 --- a/AUTHORS +++ b/AUTHORS @@ -243,6 +243,7 @@ answer newbie questions, and generally made Django that much better: Dmitri Fedortchenko Dmitry Jemerov dne@mayonnaise.net + Dolan Antenucci Donald Harvey Donald Stufft Don Spaulding diff --git a/django/db/backends/postgresql/schema.py b/django/db/backends/postgresql/schema.py index f0df8ad570..3319ee09a9 100644 --- a/django/db/backends/postgresql/schema.py +++ b/django/db/backends/postgresql/schema.py @@ -11,6 +11,7 @@ class DatabaseSchemaEditor(BaseDatabaseSchemaEditor): sql_create_sequence = "CREATE SEQUENCE %(sequence)s" sql_delete_sequence = "DROP SEQUENCE IF EXISTS %(sequence)s CASCADE" sql_set_sequence_max = "SELECT setval('%(sequence)s', MAX(%(column)s)) FROM %(table)s" + sql_set_sequence_owner = 'ALTER SEQUENCE %(sequence)s OWNED BY %(table)s.%(column)s' sql_create_index = "CREATE INDEX %(name)s ON %(table)s%(using)s (%(columns)s)%(extra)s%(condition)s" sql_delete_index = "DROP INDEX IF EXISTS %(name)s" @@ -101,6 +102,14 @@ class DatabaseSchemaEditor(BaseDatabaseSchemaEditor): }, [], ), + ( + self.sql_set_sequence_owner % { + 'table': self.quote_name(table), + 'column': self.quote_name(column), + 'sequence': self.quote_name(sequence_name), + }, + [], + ), ], ) else: diff --git a/tests/schema/tests.py b/tests/schema/tests.py index 45befa4e38..0533b32859 100644 --- a/tests/schema/tests.py +++ b/tests/schema/tests.py @@ -4,6 +4,7 @@ import unittest from copy import copy from unittest import mock +from django.core.management.color import no_style from django.db import ( DatabaseError, IntegrityError, OperationalError, connection, ) @@ -1103,6 +1104,28 @@ class SchemaTests(TransactionTestCase): Author.objects.create(name='Foo') Author.objects.create(name='Bar') + def test_alter_autofield_pk_to_bigautofield_pk_sequence_owner(self): + """ + Converting an implicit PK to BigAutoField(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 = BigAutoField(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