#32503: AlterField migration to TextField with default fails on MySQL 8.0.13+
-----------------------------------------+------------------------
               Reporter:  Matt Westcott  |          Owner:  nobody
                   Type:  Bug            |         Status:  new
              Component:  Migrations     |        Version:  3.0
               Severity:  Normal         |       Keywords:
           Triage Stage:  Unreviewed     |      Has patch:  0
    Needs documentation:  0              |    Needs tests:  0
Patch needs improvement:  0              |  Easy pickings:  0
                  UI/UX:  0              |
-----------------------------------------+------------------------
 On MySQL 8.0.23 with mysqlclient==2.0.3, running a migration with an
 AlterField operation that changes a field to a TextField with a default
 value fails with the error: `MySQLdb._exceptions.OperationalError: (1101,
 "BLOB, TEXT, GEOMETRY or JSON column 'body' can't have a default value")`.

 To reproduce:

 On a fresh project configured with a MySQL 8.0.23 database, add a `base`
 app with the following definition in models.py:

 {{{
 from django.db import models

 class Article(models.Model):
     body = models.CharField(max_length=255, null=True, blank=True)
 }}}

 Run `./manage.py makemigrations`

 Edit models.py to

 {{{
 from django.db import models

 class Article(models.Model):
     body = models.TextField(blank=True)
 }}}

 and re-run `./manage.py makemigrations`, entering `""` as the default when
 prompted. This should generate the migration:

 {{{
 from django.db import migrations, models


 class Migration(migrations.Migration):

     dependencies = [
         ('base', '0001_initial'),
     ]

     operations = [
         migrations.AlterField(
             model_name='article',
             name='body',
             field=models.TextField(blank=True, default=''),
             preserve_default=False,
         ),
     ]
 }}}

 `./manage.py migrate` then fails with the output:

 {{{
 System check identified some issues:

 WARNINGS:
 base.Article: (models.W042) Auto-created primary key used when not
 defining a primary key type, by default 'django.db.models.AutoField'.
         HINT: Configure the DEFAULT_AUTO_FIELD setting or the
 BaseConfig.default_auto_field attribute to point to a subclass of
 AutoField, e.g. 'django.db.models.BigAutoField'.
 Operations to perform:
   Apply all migrations: admin, auth, base, contenttypes, sessions
 Running migrations:
   Applying base.0001_initial... OK
   Applying base.0002_auto_20210303_1601...Traceback (most recent call
 last):
   File "/vagrant/libs/django/django/db/backends/utils.py", line 84, in
 _execute
     return self.cursor.execute(sql, params)
   File "/vagrant/libs/django/django/db/backends/mysql/base.py", line 73,
 in execute
     return self.cursor.execute(query, args)
   File "/home/vagrant/.virtualenvs/wagtailmysql/lib/python3.6/site-
 packages/MySQLdb/cursors.py", line 206, in execute
     res = self._query(query)
   File "/home/vagrant/.virtualenvs/wagtailmysql/lib/python3.6/site-
 packages/MySQLdb/cursors.py", line 319, in _query
     db.query(q)
   File "/home/vagrant/.virtualenvs/wagtailmysql/lib/python3.6/site-
 packages/MySQLdb/connections.py", line 259, in query
     _mysql.connection.query(self, query)
 MySQLdb._exceptions.OperationalError: (1101, "BLOB, TEXT, GEOMETRY or JSON
 column 'body' can't have a default value")

 The above exception was the direct cause of the following exception:

 Traceback (most recent call last):
   File "./manage.py", line 21, in <module>
     main()
   File "./manage.py", line 17, in main
     execute_from_command_line(sys.argv)
   File "/vagrant/libs/django/django/core/management/__init__.py", line
 419, in execute_from_command_line
     utility.execute()
   File "/vagrant/libs/django/django/core/management/__init__.py", line
 413, in execute
     self.fetch_command(subcommand).run_from_argv(self.argv)
   File "/vagrant/libs/django/django/core/management/base.py", line 354, in
 run_from_argv
     self.execute(*args, **cmd_options)
   File "/vagrant/libs/django/django/core/management/base.py", line 398, in
 execute
     output = self.handle(*args, **options)
   File "/vagrant/libs/django/django/core/management/base.py", line 89, in
 wrapped
     res = handle_func(*args, **kwargs)
   File "/vagrant/libs/django/django/core/management/commands/migrate.py",
 line 246, in handle
     fake_initial=fake_initial,
   File "/vagrant/libs/django/django/db/migrations/executor.py", line 117,
 in migrate
     state = self._migrate_all_forwards(state, plan, full_plan, fake=fake,
 fake_initial=fake_initial)
   File "/vagrant/libs/django/django/db/migrations/executor.py", line 147,
 in _migrate_all_forwards
     state = self.apply_migration(state, migration, fake=fake,
 fake_initial=fake_initial)
   File "/vagrant/libs/django/django/db/migrations/executor.py", line 227,
 in apply_migration
     state = migration.apply(state, schema_editor)
   File "/vagrant/libs/django/django/db/migrations/migration.py", line 126,
 in apply
     operation.database_forwards(self.app_label, schema_editor, old_state,
 project_state)
   File "/vagrant/libs/django/django/db/migrations/operations/fields.py",
 line 244, in database_forwards
     schema_editor.alter_field(from_model, from_field, to_field)
   File "/vagrant/libs/django/django/db/backends/base/schema.py", line 595,
 in alter_field
     old_db_params, new_db_params, strict)
   File "/vagrant/libs/django/django/db/backends/base/schema.py", line 756,
 in _alter_field
     params,
   File "/vagrant/libs/django/django/db/backends/base/schema.py", line 145,
 in execute
     cursor.execute(sql, params)
   File "/vagrant/libs/django/django/db/backends/utils.py", line 98, in
 execute
     return super().execute(sql, params)
   File "/vagrant/libs/django/django/db/backends/utils.py", line 66, in
 execute
     return self._execute_with_wrappers(sql, params, many=False,
 executor=self._execute)
   File "/vagrant/libs/django/django/db/backends/utils.py", line 75, in
 _execute_with_wrappers
     return executor(sql, params, many, context)
   File "/vagrant/libs/django/django/db/backends/utils.py", line 84, in
 _execute
     return self.cursor.execute(sql, params)
   File "/vagrant/libs/django/django/db/utils.py", line 90, in __exit__
     raise dj_exc_value.with_traceback(traceback) from exc_value
   File "/vagrant/libs/django/django/db/backends/utils.py", line 84, in
 _execute
     return self.cursor.execute(sql, params)
   File "/vagrant/libs/django/django/db/backends/mysql/base.py", line 73,
 in execute
     return self.cursor.execute(query, args)
   File "/home/vagrant/.virtualenvs/wagtailmysql/lib/python3.6/site-
 packages/MySQLdb/cursors.py", line 206, in execute
     res = self._query(query)
   File "/home/vagrant/.virtualenvs/wagtailmysql/lib/python3.6/site-
 packages/MySQLdb/cursors.py", line 319, in _query
     db.query(q)
   File "/home/vagrant/.virtualenvs/wagtailmysql/lib/python3.6/site-
 packages/MySQLdb/connections.py", line 259, in query
     _mysql.connection.query(self, query)
 django.db.utils.OperationalError: (1101, "BLOB, TEXT, GEOMETRY or JSON
 column 'body' can't have a default value")
 }}}

 Bisecting shows that this error was introduced in
 
https://github.com/django/django/commit/6b16c91157512587017e9178d066ed1a683e7795
 - presumably prior to this the default was simply being ignored on MySQL.

-- 
Ticket URL: <https://code.djangoproject.com/ticket/32503>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.

-- 
You received this message because you are subscribed to the Google Groups 
"Django updates" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-updates/049.ff94b3acb880f66af2ed6554d1f28dd2%40djangoproject.com.

Reply via email to