summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMariusz Felisiak <felisiak.mariusz@gmail.com>2021-06-10 09:39:08 +0200
committerMariusz Felisiak <felisiak.mariusz@gmail.com>2021-06-10 20:03:43 +0200
commitfa0433d05f213afe4c67055006320f7aba4c8108 (patch)
tree895cee75aa1ed87bff36fdec0642c8662d147469
parent57bc16b38ec75fc96829f912d57a58d8c6358e8f (diff)
downloaddjango-fa0433d05f213afe4c67055006320f7aba4c8108.tar.gz
Fixed #32832 -- Fixed adding BLOB/TEXT nullable field with default on MySQL 8.0.13+.
Regression in d4ac23bee1c84d8e4610350202ac068fc90f38c0. Thanks Omkar Deshpande for the report.
-rw-r--r--django/db/backends/base/schema.py11
-rw-r--r--docs/releases/3.2.5.txt4
-rw-r--r--tests/schema/tests.py27
3 files changed, 40 insertions, 2 deletions
diff --git a/django/db/backends/base/schema.py b/django/db/backends/base/schema.py
index c409464eca..8050441414 100644
--- a/django/db/backends/base/schema.py
+++ b/django/db/backends/base/schema.py
@@ -225,7 +225,14 @@ class BaseDatabaseSchemaEditor:
# Work out nullability
null = field.null
# 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:
default_value = self.effective_default(field)
column_default = ' DEFAULT ' + self._column_default_sql(field)
@@ -515,7 +522,7 @@ class BaseDatabaseSchemaEditor:
self.execute(sql, params)
# Drop the default if we need to
# (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)
sql = self.sql_alter_column % {
"table": self.quote_name(model._meta.db_table),
diff --git a/docs/releases/3.2.5.txt b/docs/releases/3.2.5.txt
index f426d437ee..05d824fc25 100644
--- a/docs/releases/3.2.5.txt
+++ b/docs/releases/3.2.5.txt
@@ -16,3 +16,7 @@ Bugfixes
* 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
(: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`).
diff --git a/tests/schema/tests.py b/tests/schema/tests.py
index eb9be178db..0e88bfdbd1 100644
--- a/tests/schema/tests.py
+++ b/tests/schema/tests.py
@@ -3387,6 +3387,33 @@ class SchemaTests(TransactionTestCase):
if connection.features.can_introspect_default:
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):
# Create the table
with connection.schema_editor() as editor: