Fixed #23738 -- Allowed migrating from NULL to NOT NULL with the same default value
Thanks to Andrey Antukh for the report.
This commit is contained in:
parent
ed2f96819c
commit
715ccfde24
|
@ -607,7 +607,7 @@ class BaseDatabaseSchemaEditor(object):
|
||||||
# directly run a (NOT) NULL alteration
|
# directly run a (NOT) NULL alteration
|
||||||
actions = actions + null_actions
|
actions = actions + null_actions
|
||||||
# Combine actions together if we can (e.g. postgres)
|
# Combine actions together if we can (e.g. postgres)
|
||||||
if self.connection.features.supports_combined_alters:
|
if self.connection.features.supports_combined_alters and actions:
|
||||||
sql, params = tuple(zip(*actions))
|
sql, params = tuple(zip(*actions))
|
||||||
actions = [(", ".join(sql), reduce(operator.add, params))]
|
actions = [(", ".join(sql), reduce(operator.add, params))]
|
||||||
# Apply those actions
|
# Apply those actions
|
||||||
|
|
|
@ -37,3 +37,6 @@ Bugfixes
|
||||||
|
|
||||||
* Added support for transactional spatial metadata initialization on
|
* Added support for transactional spatial metadata initialization on
|
||||||
SpatiaLite 4.1+ (:ticket:`23152`).
|
SpatiaLite 4.1+ (:ticket:`23152`).
|
||||||
|
|
||||||
|
* Fixed a migration crash that prevented changing a nullable field with a
|
||||||
|
default to non-nullable with the same default (:ticket:`23738`).
|
||||||
|
|
|
@ -17,6 +17,14 @@ class Author(models.Model):
|
||||||
apps = new_apps
|
apps = new_apps
|
||||||
|
|
||||||
|
|
||||||
|
class AuthorWithDefaultHeight(models.Model):
|
||||||
|
name = models.CharField(max_length=255)
|
||||||
|
height = models.PositiveIntegerField(null=True, blank=True, default=42)
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
apps = new_apps
|
||||||
|
|
||||||
|
|
||||||
class AuthorWithM2M(models.Model):
|
class AuthorWithM2M(models.Model):
|
||||||
name = models.CharField(max_length=255)
|
name = models.CharField(max_length=255)
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,7 @@ from django.db.models.fields import (BinaryField, BooleanField, CharField, Integ
|
||||||
PositiveIntegerField, SlugField, TextField)
|
PositiveIntegerField, SlugField, TextField)
|
||||||
from django.db.models.fields.related import ManyToManyField, ForeignKey
|
from django.db.models.fields.related import ManyToManyField, ForeignKey
|
||||||
from django.db.transaction import atomic
|
from django.db.transaction import atomic
|
||||||
from .models import (Author, AuthorWithM2M, Book, BookWithLongName,
|
from .models import (Author, AuthorWithDefaultHeight, AuthorWithM2M, Book, BookWithLongName,
|
||||||
BookWithSlug, BookWithM2M, Tag, TagIndexed, TagM2MTest, TagUniqueRename,
|
BookWithSlug, BookWithM2M, Tag, TagIndexed, TagM2MTest, TagUniqueRename,
|
||||||
UniqueTest, Thing, TagThrough, BookWithM2MThrough, AuthorTag, AuthorWithM2MThrough,
|
UniqueTest, Thing, TagThrough, BookWithM2MThrough, AuthorTag, AuthorWithM2MThrough,
|
||||||
AuthorWithEvenLongerName, BookWeak)
|
AuthorWithEvenLongerName, BookWeak)
|
||||||
|
@ -448,6 +448,31 @@ class SchemaTests(TransactionTestCase):
|
||||||
self.assertEqual(Author.objects.get(name='Not null author').height, 12)
|
self.assertEqual(Author.objects.get(name='Not null author').height, 12)
|
||||||
self.assertEqual(Author.objects.get(name='Null author').height, 42)
|
self.assertEqual(Author.objects.get(name='Null author').height, 42)
|
||||||
|
|
||||||
|
@unittest.skipUnless(connection.features.supports_combined_alters, "No combined ALTER support")
|
||||||
|
def test_alter_null_to_not_null_keeping_default(self):
|
||||||
|
"""
|
||||||
|
#23738 - Can change a nullable field with default to non-nullable
|
||||||
|
with the same default.
|
||||||
|
"""
|
||||||
|
# Create the table
|
||||||
|
with connection.schema_editor() as editor:
|
||||||
|
editor.create_model(AuthorWithDefaultHeight)
|
||||||
|
# Ensure the field is right to begin with
|
||||||
|
columns = self.column_classes(AuthorWithDefaultHeight)
|
||||||
|
self.assertTrue(columns['height'][1][6])
|
||||||
|
# Alter the height field to NOT NULL keeping the previous default
|
||||||
|
new_field = PositiveIntegerField(default=42)
|
||||||
|
new_field.set_attributes_from_name("height")
|
||||||
|
with connection.schema_editor() as editor:
|
||||||
|
editor.alter_field(
|
||||||
|
AuthorWithDefaultHeight,
|
||||||
|
AuthorWithDefaultHeight._meta.get_field_by_name("height")[0],
|
||||||
|
new_field,
|
||||||
|
)
|
||||||
|
# Ensure the field is right afterwards
|
||||||
|
columns = self.column_classes(AuthorWithDefaultHeight)
|
||||||
|
self.assertFalse(columns['height'][1][6])
|
||||||
|
|
||||||
@unittest.skipUnless(connection.features.supports_foreign_keys, "No FK support")
|
@unittest.skipUnless(connection.features.supports_foreign_keys, "No FK support")
|
||||||
def test_alter_fk(self):
|
def test_alter_fk(self):
|
||||||
"""
|
"""
|
||||||
|
|
Loading…
Reference in New Issue