From 1b3a949ba26ca8fefde7fa224e11c4aadbbdd724 Mon Sep 17 00:00:00 2001 From: Mariusz Felisiak Date: Fri, 29 Apr 2022 21:43:55 +0200 Subject: [PATCH] Refs #33671 -- Fixed migrations crash when adding collation to a primary key on Oracle. --- django/db/backends/oracle/schema.py | 8 ++++++++ tests/schema/tests.py | 25 +++++++++++++++++++++++++ 2 files changed, 33 insertions(+) diff --git a/django/db/backends/oracle/schema.py b/django/db/backends/oracle/schema.py index d6b04fe9a1..f2a5099110 100644 --- a/django/db/backends/oracle/schema.py +++ b/django/db/backends/oracle/schema.py @@ -91,6 +91,14 @@ class DatabaseSchemaEditor(BaseDatabaseSchemaEditor): elif "ORA-30673" in description and old_field.primary_key: self._delete_primary_key(model, strict=True) self._alter_field_type_workaround(model, old_field, new_field) + # If a collation is changing on a primary key, drop the primary key + # first. + elif "ORA-43923" in description and old_field.primary_key: + self._delete_primary_key(model, strict=True) + self.alter_field(model, old_field, new_field, strict) + # Restore a primary key, if needed. + if new_field.primary_key: + self.execute(self._create_primary_key_sql(model, new_field)) else: raise diff --git a/tests/schema/tests.py b/tests/schema/tests.py index 3fe41f5336..2d12796cbd 100644 --- a/tests/schema/tests.py +++ b/tests/schema/tests.py @@ -4608,6 +4608,31 @@ class SchemaTests(TransactionTestCase): editor.alter_field(Author, new_field, old_field, strict=True) self.assertIsNone(self.get_column_collation(Author._meta.db_table, "name")) + @skipUnlessDBFeature("supports_collation_on_charfield") + def test_alter_primary_key_db_collation(self): + collation = connection.features.test_collations.get("non_default") + if not collation: + self.skipTest("Language collations are not supported.") + + with connection.schema_editor() as editor: + editor.create_model(Thing) + + old_field = Thing._meta.get_field("when") + new_field = CharField(max_length=1, db_collation=collation, primary_key=True) + new_field.set_attributes_from_name("when") + new_field.model = Thing + with connection.schema_editor() as editor: + editor.alter_field(Thing, old_field, new_field, strict=True) + self.assertEqual(self.get_primary_key(Thing._meta.db_table), "when") + self.assertEqual( + self.get_column_collation(Thing._meta.db_table, "when"), + collation, + ) + with connection.schema_editor() as editor: + editor.alter_field(Thing, new_field, old_field, strict=True) + self.assertEqual(self.get_primary_key(Thing._meta.db_table), "when") + self.assertIsNone(self.get_column_collation(Thing._meta.db_table, "when")) + @skipUnlessDBFeature( "supports_collation_on_charfield", "supports_collation_on_textfield" )