Fixed #32832 -- Fixed adding BLOB/TEXT nullable field with default on MySQL 8.0.13+.
Regression in d4ac23bee1
.
Thanks Omkar Deshpande for the report.
This commit is contained in:
parent
57bc16b38e
commit
fa0433d05f
|
@ -225,7 +225,14 @@ class BaseDatabaseSchemaEditor:
|
||||||
# Work out nullability
|
# Work out nullability
|
||||||
null = field.null
|
null = field.null
|
||||||
# If we were told to include a default value, do so
|
# If we were told to include a default value, do so
|
||||||
include_default = include_default and not self.skip_default(field)
|
include_default = (
|
||||||
|
include_default and
|
||||||
|
not self.skip_default(field) and
|
||||||
|
# Don't include a default value if it's a nullable field and the
|
||||||
|
# default cannot be dropped in the ALTER COLUMN statement (e.g.
|
||||||
|
# MySQL longtext and longblob).
|
||||||
|
not (null and self.skip_default_on_alter(field))
|
||||||
|
)
|
||||||
if include_default:
|
if include_default:
|
||||||
default_value = self.effective_default(field)
|
default_value = self.effective_default(field)
|
||||||
column_default = ' DEFAULT ' + self._column_default_sql(field)
|
column_default = ' DEFAULT ' + self._column_default_sql(field)
|
||||||
|
@ -515,7 +522,7 @@ class BaseDatabaseSchemaEditor:
|
||||||
self.execute(sql, params)
|
self.execute(sql, params)
|
||||||
# Drop the default if we need to
|
# Drop the default if we need to
|
||||||
# (Django usually does not use in-database defaults)
|
# (Django usually does not use in-database defaults)
|
||||||
if not self.skip_default(field) and self.effective_default(field) is not None:
|
if not self.skip_default_on_alter(field) and self.effective_default(field) is not None:
|
||||||
changes_sql, params = self._alter_column_default_sql(model, None, field, drop=True)
|
changes_sql, params = self._alter_column_default_sql(model, None, field, drop=True)
|
||||||
sql = self.sql_alter_column % {
|
sql = self.sql_alter_column % {
|
||||||
"table": self.quote_name(model._meta.db_table),
|
"table": self.quote_name(model._meta.db_table),
|
||||||
|
|
|
@ -16,3 +16,7 @@ Bugfixes
|
||||||
* Fixed a bug in Django 3.2 that caused a migration crash on MySQL 8.0.13+ when
|
* Fixed a bug in Django 3.2 that caused a migration crash on MySQL 8.0.13+ when
|
||||||
altering ``BinaryField``, ``JSONField``, or ``TextField`` to non-nullable
|
altering ``BinaryField``, ``JSONField``, or ``TextField`` to non-nullable
|
||||||
(:ticket:`32503`).
|
(:ticket:`32503`).
|
||||||
|
|
||||||
|
* Fixed a regression in Django 3.2 that caused a migration crash on MySQL
|
||||||
|
8.0.13+ when adding nullable ``BinaryField``, ``JSONField``, or ``TextField``
|
||||||
|
with a default value (:ticket:`32832`).
|
||||||
|
|
|
@ -3387,6 +3387,33 @@ class SchemaTests(TransactionTestCase):
|
||||||
if connection.features.can_introspect_default:
|
if connection.features.can_introspect_default:
|
||||||
self.assertIn(field.default, ['NULL', None])
|
self.assertIn(field.default, ['NULL', None])
|
||||||
|
|
||||||
|
def test_add_textfield_default_nullable(self):
|
||||||
|
with connection.schema_editor() as editor:
|
||||||
|
editor.create_model(Author)
|
||||||
|
# Add new nullable TextField with a default.
|
||||||
|
new_field = TextField(blank=True, null=True, default='text')
|
||||||
|
new_field.set_attributes_from_name('description')
|
||||||
|
with connection.schema_editor() as editor:
|
||||||
|
editor.add_field(Author, new_field)
|
||||||
|
Author.objects.create(name='Anonymous1')
|
||||||
|
with connection.cursor() as cursor:
|
||||||
|
cursor.execute('SELECT description FROM schema_author;')
|
||||||
|
item = cursor.fetchall()[0]
|
||||||
|
self.assertIsNone(item[0])
|
||||||
|
field = next(
|
||||||
|
f
|
||||||
|
for f in connection.introspection.get_table_description(
|
||||||
|
cursor,
|
||||||
|
'schema_author',
|
||||||
|
)
|
||||||
|
if f.name == 'description'
|
||||||
|
)
|
||||||
|
# Field is still nullable.
|
||||||
|
self.assertTrue(field.null_ok)
|
||||||
|
# The database default is no longer set.
|
||||||
|
if connection.features.can_introspect_default:
|
||||||
|
self.assertIn(field.default, ['NULL', None])
|
||||||
|
|
||||||
def test_alter_field_default_dropped(self):
|
def test_alter_field_default_dropped(self):
|
||||||
# Create the table
|
# Create the table
|
||||||
with connection.schema_editor() as editor:
|
with connection.schema_editor() as editor:
|
||||||
|
|
Loading…
Reference in New Issue