From f944cb3d3bc17a97216f8990ff3bb4bee14b6f6b Mon Sep 17 00:00:00 2001
From: Dolan Antenucci <antenucci.d@gmail.com>
Date: Tue, 19 Mar 2019 13:28:47 -0600
Subject: [PATCH] Fixed #30266 -- Kept a sequence owner when altering an
 AutoField/BigAutoField on PostgreSQL.

---
 AUTHORS                                 |  1 +
 django/db/backends/postgresql/schema.py |  9 +++++++++
 tests/schema/tests.py                   | 23 +++++++++++++++++++++++
 3 files changed, 33 insertions(+)

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 <zeraien@gmail.com>
     Dmitry Jemerov <intelliyole@gmail.com>
     dne@mayonnaise.net
+    Dolan Antenucci <antenucci.d@gmail.com>
     Donald Harvey <donald@donaldharvey.co.uk>
     Donald Stufft <donald@stufft.io>
     Don Spaulding <donspauldingii@gmail.com>
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