Fixed #33057 -- Fixed recreation of foreign key constraints in m2m tables when altering type of referenced primary key on Oracle.

This commit is contained in:
Mariusz Felisiak 2021-08-31 13:43:10 +02:00 committed by GitHub
parent b667ac24ea
commit 1eb3f500a4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 36 additions and 1 deletions

View File

@ -3,7 +3,9 @@ import datetime
import re import re
from django.db import DatabaseError from django.db import DatabaseError
from django.db.backends.base.schema import BaseDatabaseSchemaEditor from django.db.backends.base.schema import (
BaseDatabaseSchemaEditor, _related_non_m2m_objects,
)
class DatabaseSchemaEditor(BaseDatabaseSchemaEditor): class DatabaseSchemaEditor(BaseDatabaseSchemaEditor):
@ -124,6 +126,17 @@ class DatabaseSchemaEditor(BaseDatabaseSchemaEditor):
self.remove_field(model, old_field) self.remove_field(model, old_field)
# Rename and possibly make the new field NOT NULL # Rename and possibly make the new field NOT NULL
super().alter_field(model, new_temp_field, new_field) super().alter_field(model, new_temp_field, new_field)
# Recreate foreign key (if necessary) because the old field is not
# passed to the alter_field() and data types of new_temp_field and
# new_field always match.
new_type = new_field.db_type(self.connection)
if (
(old_field.primary_key and new_field.primary_key) or
(old_field.unique and new_field.unique)
) and old_type != new_type:
for _, rel in _related_non_m2m_objects(new_temp_field, new_field):
if rel.field.db_constraint:
self.execute(self._create_fk_sql(rel.related_model, rel.field, '_fk'))
def _alter_column_type_sql(self, model, old_field, new_field, new_type): def _alter_column_type_sql(self, model, old_field, new_field, new_type):
auto_field_types = {'AutoField', 'BigAutoField', 'SmallAutoField'} auto_field_types = {'AutoField', 'BigAutoField', 'SmallAutoField'}

View File

@ -1500,10 +1500,32 @@ class OperationTests(OperationTestBase):
with connection.schema_editor() as editor: with connection.schema_editor() as editor:
operation.database_forwards("test_alflpkfk", editor, project_state, new_state) operation.database_forwards("test_alflpkfk", editor, project_state, new_state)
assertIdTypeEqualsFkType() assertIdTypeEqualsFkType()
if connection.features.supports_foreign_keys:
self.assertFKExists(
'test_alflpkfk_pony_stables',
['pony_id'],
('test_alflpkfk_pony', 'id'),
)
self.assertFKExists(
'test_alflpkfk_stable_ponies',
['pony_id'],
('test_alflpkfk_pony', 'id'),
)
# And test reversal # And test reversal
with connection.schema_editor() as editor: with connection.schema_editor() as editor:
operation.database_backwards("test_alflpkfk", editor, new_state, project_state) operation.database_backwards("test_alflpkfk", editor, new_state, project_state)
assertIdTypeEqualsFkType() assertIdTypeEqualsFkType()
if connection.features.supports_foreign_keys:
self.assertFKExists(
'test_alflpkfk_pony_stables',
['pony_id'],
('test_alflpkfk_pony', 'id'),
)
self.assertFKExists(
'test_alflpkfk_stable_ponies',
['pony_id'],
('test_alflpkfk_pony', 'id'),
)
def test_alter_field_pk_mti_fk(self): def test_alter_field_pk_mti_fk(self):
app_label = 'test_alflpkmtifk' app_label = 'test_alflpkmtifk'