Fixed #32503 -- Fixed altering BLOB/TEXT field to non-nullable with default on MySQL 8.0.13+.

MySQL 8.0.13+ supports defaults for BLOB/TEXT but not in the
ALTER COLUMN statement.

Regression in 6b16c91157.

Thanks Matt Westcott for the report.
This commit is contained in:
Yuekui Li 2021-05-19 16:30:15 -07:00 committed by Mariusz Felisiak
parent 7cca22964c
commit 5e04e84d67
4 changed files with 25 additions and 1 deletions

View File

@ -266,6 +266,13 @@ class BaseDatabaseSchemaEditor:
"""
return False
def skip_default_on_alter(self, field):
"""
Some backends don't accept default values for certain columns types
(i.e. MySQL longtext and longblob) in the ALTER COLUMN statement.
"""
return False
def prepare_default(self, value):
"""
Only used for backends which have requires_literal_defaults feature
@ -721,7 +728,7 @@ class BaseDatabaseSchemaEditor:
old_default = self.effective_default(old_field)
new_default = self.effective_default(new_field)
if (
not self.skip_default(new_field) and
not self.skip_default_on_alter(new_field) and
old_default != new_default and
new_default is not None
):

View File

@ -68,6 +68,13 @@ class DatabaseSchemaEditor(BaseDatabaseSchemaEditor):
return self._is_limited_data_type(field)
return False
def skip_default_on_alter(self, field):
if self._is_limited_data_type(field) and not self.connection.mysql_is_mariadb:
# MySQL doesn't support defaults for BLOB and TEXT in the
# ALTER COLUMN statement.
return True
return False
@property
def _supports_limited_data_type_defaults(self):
# MariaDB >= 10.2.1 and MySQL >= 8.0.13 supports defaults for BLOB

View File

@ -158,6 +158,7 @@ class IntegerPK(models.Model):
class Note(models.Model):
info = models.TextField()
address = models.TextField(null=True)
class Meta:
apps = new_apps

View File

@ -778,6 +778,15 @@ class SchemaTests(TransactionTestCase):
with connection.schema_editor() as editor:
editor.alter_field(Note, old_field, new_field, strict=True)
def test_alter_text_field_to_not_null_with_default_value(self):
with connection.schema_editor() as editor:
editor.create_model(Note)
old_field = Note._meta.get_field('address')
new_field = TextField(blank=True, default='', null=False)
new_field.set_attributes_from_name('address')
with connection.schema_editor() as editor:
editor.alter_field(Note, old_field, new_field, strict=True)
@skipUnlessDBFeature('can_defer_constraint_checks', 'can_rollback_ddl')
def test_alter_fk_checks_deferred_constraints(self):
"""