diff --git a/django/db/backends/postgresql/schema.py b/django/db/backends/postgresql/schema.py index 98af3195702..d512ecefb61 100644 --- a/django/db/backends/postgresql/schema.py +++ b/django/db/backends/postgresql/schema.py @@ -13,7 +13,7 @@ class DatabaseSchemaEditor(BaseDatabaseSchemaEditor): "UPDATE %(table)s SET %(column)s = %(default)s WHERE %(column)s IS NULL" "; SET CONSTRAINTS ALL IMMEDIATE" ) - + sql_alter_sequence_type = "ALTER SEQUENCE IF EXISTS %(sequence)s AS %(type)s" sql_delete_sequence = "DROP SEQUENCE IF EXISTS %(sequence)s CASCADE" sql_create_index = ( @@ -208,6 +208,29 @@ class DatabaseSchemaEditor(BaseDatabaseSchemaEditor): [], ), ] + elif new_is_auto and old_is_auto and old_internal_type != new_internal_type: + fragment, _ = super()._alter_column_type_sql( + model, old_field, new_field, new_type + ) + column = strip_quotes(new_field.column) + sequence_name = f"{table}_{column}_seq" + db_types = { + "AutoField": "integer", + "BigAutoField": "bigint", + "SmallAutoField": "smallint", + } + return fragment, [ + # Alter the sequence type if exists (Django 4.1+ identity + # columns don't have it). + ( + self.sql_alter_sequence_type + % { + "sequence": self.quote_name(sequence_name), + "type": db_types[new_internal_type], + }, + [], + ), + ] else: return super()._alter_column_type_sql(model, old_field, new_field, new_type) diff --git a/docs/releases/4.1.2.txt b/docs/releases/4.1.2.txt index 434bc5f587b..57b0b6c6e80 100644 --- a/docs/releases/4.1.2.txt +++ b/docs/releases/4.1.2.txt @@ -35,3 +35,7 @@ Bugfixes * Fixed a regression in Django 4.1 where the ``--debug-mode`` argument to ``test`` did not work when running parallel tests with the ``multiprocessing`` start method ``spawn`` (:ticket:`34010`). + +* Fixed a regression in Django 4.1 that didn't alter a sequence type when + altering type of pre-Django 4.1 serial columns on PostgreSQL + (:ticket:`34058`). diff --git a/tests/schema/tests.py b/tests/schema/tests.py index aaf6dff2ff8..32dde9aaed3 100644 --- a/tests/schema/tests.py +++ b/tests/schema/tests.py @@ -1873,6 +1873,41 @@ class SchemaTests(TransactionTestCase): with connection.schema_editor() as editor: editor.alter_field(SmallIntegerPK, old_field, new_field, strict=True) + @isolate_apps("schema") + @unittest.skipUnless(connection.vendor == "postgresql", "PostgreSQL specific") + def test_alter_serial_auto_field_to_bigautofield(self): + class SerialAutoField(Model): + id = SmallAutoField(primary_key=True) + + class Meta: + app_label = "schema" + + table = SerialAutoField._meta.db_table + column = SerialAutoField._meta.get_field("id").column + with connection.cursor() as cursor: + cursor.execute( + f'CREATE TABLE "{table}" ' + f'("{column}" smallserial NOT NULL PRIMARY KEY)' + ) + try: + old_field = SerialAutoField._meta.get_field("id") + new_field = BigAutoField(primary_key=True) + new_field.model = SerialAutoField + new_field.set_attributes_from_name("id") + with connection.schema_editor() as editor: + editor.alter_field(SerialAutoField, old_field, new_field, strict=True) + with connection.cursor() as cursor: + cursor.execute( + "SELECT data_type FROM pg_sequences WHERE sequencename = %s", + [f"{table}_{column}_seq"], + ) + row = cursor.fetchone() + sequence_data_type = row[0] if row and row[0] else None + self.assertEqual(sequence_data_type, "bigint") + finally: + with connection.cursor() as cursor: + cursor.execute(f'DROP TABLE "{table}"') + def test_alter_int_pk_to_int_unique(self): """ Should be able to rename an IntegerField(primary_key=True) to