summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMariusz Felisiak <felisiak.mariusz@gmail.com>2022-09-29 13:20:14 +0200
committerMariusz Felisiak <felisiak.mariusz@gmail.com>2022-09-29 13:20:55 +0200
commit97353bc64baca2affe6be6a0c4e5c3cc1de496ec (patch)
tree1ec025ab460a3aadc97be1a3679eb8909485688a
parent7607fc8990ec61b51d4a3baf0be51c28fa5f4605 (diff)
[4.1.x] Fixed #34058 -- Changed sequence types when altering pre-Django 4.1 auto fields on PostgreSQL.
Thanks Anders Kaseorg for the report. Thanks Florian Apolloner for pair programming. Regression in 2eea361eff58dd98c409c5227064b901f41bd0d6. Backport of 19e6efa50b603af325e7f62058364f278596758f from main
-rw-r--r--django/db/backends/postgresql/schema.py25
-rw-r--r--docs/releases/4.1.2.txt4
-rw-r--r--tests/schema/tests.py35
3 files changed, 63 insertions, 1 deletions
diff --git a/django/db/backends/postgresql/schema.py b/django/db/backends/postgresql/schema.py
index 4d88af0408..fa6e0a8ebf 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 = (
@@ -183,6 +183,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 434bc5f587..57b0b6c6e8 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 bb8c923c1e..e6cdf563f4 100644
--- a/tests/schema/tests.py
+++ b/tests/schema/tests.py
@@ -1785,6 +1785,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