Fixed #29496 -- Fixed crash on Oracle when converting a non-unique field to primary key.
Thanks Tim Graham for the review.
This commit is contained in:
parent
e95008f241
commit
6dd4edb1b4
|
@ -539,7 +539,7 @@ class BaseDatabaseSchemaEditor:
|
||||||
fks_dropped.add((old_field.column,))
|
fks_dropped.add((old_field.column,))
|
||||||
self.execute(self._delete_constraint_sql(self.sql_delete_fk, model, fk_name))
|
self.execute(self._delete_constraint_sql(self.sql_delete_fk, model, fk_name))
|
||||||
# Has unique been removed?
|
# Has unique been removed?
|
||||||
if old_field.unique and (not new_field.unique or (not old_field.primary_key and new_field.primary_key)):
|
if old_field.unique and (not new_field.unique or self._field_became_primary_key(old_field, new_field)):
|
||||||
# Find the unique constraint for this field
|
# Find the unique constraint for this field
|
||||||
constraint_names = self._constraint_names(model, [old_field.column], unique=True, primary_key=False)
|
constraint_names = self._constraint_names(model, [old_field.column], unique=True, primary_key=False)
|
||||||
if strict and len(constraint_names) != 1:
|
if strict and len(constraint_names) != 1:
|
||||||
|
@ -689,9 +689,7 @@ class BaseDatabaseSchemaEditor:
|
||||||
if old_field.primary_key and not new_field.primary_key:
|
if old_field.primary_key and not new_field.primary_key:
|
||||||
self._delete_primary_key(model, strict)
|
self._delete_primary_key(model, strict)
|
||||||
# Added a unique?
|
# Added a unique?
|
||||||
if (not old_field.unique and new_field.unique) or (
|
if self._unique_should_be_added(old_field, new_field):
|
||||||
old_field.primary_key and not new_field.primary_key and new_field.unique
|
|
||||||
):
|
|
||||||
self.execute(self._create_unique_sql(model, [new_field.column]))
|
self.execute(self._create_unique_sql(model, [new_field.column]))
|
||||||
# Added an index? Add an index if db_index switched to True or a unique
|
# Added an index? Add an index if db_index switched to True or a unique
|
||||||
# constraint will no longer be used in lieu of an index. The following
|
# constraint will no longer be used in lieu of an index. The following
|
||||||
|
@ -710,7 +708,7 @@ class BaseDatabaseSchemaEditor:
|
||||||
if old_field.primary_key and new_field.primary_key and old_type != new_type:
|
if old_field.primary_key and new_field.primary_key and old_type != new_type:
|
||||||
rels_to_update.extend(_related_non_m2m_objects(old_field, new_field))
|
rels_to_update.extend(_related_non_m2m_objects(old_field, new_field))
|
||||||
# Changed to become primary key?
|
# Changed to become primary key?
|
||||||
if not old_field.primary_key and new_field.primary_key:
|
if self._field_became_primary_key(old_field, new_field):
|
||||||
# Make the new one
|
# Make the new one
|
||||||
self.execute(
|
self.execute(
|
||||||
self.sql_create_pk % {
|
self.sql_create_pk % {
|
||||||
|
@ -966,6 +964,14 @@ class BaseDatabaseSchemaEditor:
|
||||||
def _field_should_be_indexed(self, model, field):
|
def _field_should_be_indexed(self, model, field):
|
||||||
return field.db_index and not field.unique
|
return field.db_index and not field.unique
|
||||||
|
|
||||||
|
def _field_became_primary_key(self, old_field, new_field):
|
||||||
|
return not old_field.primary_key and new_field.primary_key
|
||||||
|
|
||||||
|
def _unique_should_be_added(self, old_field, new_field):
|
||||||
|
return (not old_field.unique and new_field.unique) or (
|
||||||
|
old_field.primary_key and not new_field.primary_key and new_field.unique
|
||||||
|
)
|
||||||
|
|
||||||
def _rename_field_sql(self, table, old_field, new_field, new_type):
|
def _rename_field_sql(self, table, old_field, new_field, new_type):
|
||||||
return self.sql_rename_column % {
|
return self.sql_rename_column % {
|
||||||
"table": self.quote_name(table),
|
"table": self.quote_name(table),
|
||||||
|
|
|
@ -144,6 +144,12 @@ class DatabaseSchemaEditor(BaseDatabaseSchemaEditor):
|
||||||
return False
|
return False
|
||||||
return create_index
|
return create_index
|
||||||
|
|
||||||
|
def _unique_should_be_added(self, old_field, new_field):
|
||||||
|
return (
|
||||||
|
super()._unique_should_be_added(old_field, new_field) and
|
||||||
|
not self._field_became_primary_key(old_field, new_field)
|
||||||
|
)
|
||||||
|
|
||||||
def _is_identity_column(self, table_name, column_name):
|
def _is_identity_column(self, table_name, column_name):
|
||||||
with self.connection.cursor() as cursor:
|
with self.connection.cursor() as cursor:
|
||||||
cursor.execute("""
|
cursor.execute("""
|
||||||
|
|
|
@ -12,6 +12,7 @@ class Author(models.Model):
|
||||||
name = models.CharField(max_length=255)
|
name = models.CharField(max_length=255)
|
||||||
height = models.PositiveIntegerField(null=True, blank=True)
|
height = models.PositiveIntegerField(null=True, blank=True)
|
||||||
weight = models.IntegerField(null=True, blank=True)
|
weight = models.IntegerField(null=True, blank=True)
|
||||||
|
uuid = models.UUIDField(null=True)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
apps = new_apps
|
apps = new_apps
|
||||||
|
|
|
@ -12,7 +12,7 @@ from django.db.models.deletion import CASCADE, PROTECT
|
||||||
from django.db.models.fields import (
|
from django.db.models.fields import (
|
||||||
AutoField, BigAutoField, BigIntegerField, BinaryField, BooleanField,
|
AutoField, BigAutoField, BigIntegerField, BinaryField, BooleanField,
|
||||||
CharField, DateField, DateTimeField, IntegerField, PositiveIntegerField,
|
CharField, DateField, DateTimeField, IntegerField, PositiveIntegerField,
|
||||||
SlugField, TextField, TimeField,
|
SlugField, TextField, TimeField, UUIDField,
|
||||||
)
|
)
|
||||||
from django.db.models.fields.related import (
|
from django.db.models.fields.related import (
|
||||||
ForeignKey, ForeignObject, ManyToManyField, OneToOneField,
|
ForeignKey, ForeignObject, ManyToManyField, OneToOneField,
|
||||||
|
@ -603,6 +603,19 @@ class SchemaTests(TransactionTestCase):
|
||||||
with connection.schema_editor() as editor:
|
with connection.schema_editor() as editor:
|
||||||
editor.alter_field(Author, old_field, new_field, strict=True)
|
editor.alter_field(Author, old_field, new_field, strict=True)
|
||||||
|
|
||||||
|
def test_alter_not_unique_field_to_primary_key(self):
|
||||||
|
# Create the table.
|
||||||
|
with connection.schema_editor() as editor:
|
||||||
|
editor.create_model(Author)
|
||||||
|
# Change UUIDField to primary key.
|
||||||
|
old_field = Author._meta.get_field('uuid')
|
||||||
|
new_field = UUIDField(primary_key=True)
|
||||||
|
new_field.set_attributes_from_name('uuid')
|
||||||
|
new_field.model = Author
|
||||||
|
with connection.schema_editor() as editor:
|
||||||
|
editor.remove_field(Author, Author._meta.get_field('id'))
|
||||||
|
editor.alter_field(Author, old_field, new_field, strict=True)
|
||||||
|
|
||||||
def test_alter_text_field(self):
|
def test_alter_text_field(self):
|
||||||
# Regression for "BLOB/TEXT column 'info' can't have a default value")
|
# Regression for "BLOB/TEXT column 'info' can't have a default value")
|
||||||
# on MySQL.
|
# on MySQL.
|
||||||
|
|
Loading…
Reference in New Issue