#33583: Inconsistency: sqlmigrate reports a broken migration but migrate applies
them
-------------------------------------+-------------------------------------
               Reporter:  Amin Shah  |          Owner:  nobody
  Gilani                             |
                   Type:  Bug        |         Status:  new
              Component:             |        Version:  3.2
  Uncategorized                      |       Keywords:  sqlmigrate,
               Severity:  Normal     |  migrate, squash
           Triage Stage:             |      Has patch:  0
  Unreviewed                         |
    Needs documentation:  0          |    Needs tests:  0
Patch needs improvement:  0          |  Easy pickings:  0
                  UI/UX:  0          |
-------------------------------------+-------------------------------------
 Hello,

 This is my first bug report here so please ask for any additional details
 you need. I would also appreciate a workaround. If it is obvious, it
 escapes me.

 == Summary

 When an app is renamed with its migrations including a `replaces`
 reference to the old app and migration name (such as by squashing
 migrations), the behavior between `migrate` and `sqlmigrate` becomes
 inconsistent. `migrate` happily applies all migrations, but `sqlmigrate`
 reports an error.

 == Other information:

 * This bug was first observed in v3.2, but my demo shows it also affects
 v4.0.3.
 * This bug affects installations using the [https://github.com/python-
 social-auth/social-app-django social-app-django] package, which renamed
 its app multiple times,
 * I have a demo available [https://github.com/amingilani/django-bug-PoC
 here].

 == Steps to reproduce:

 **Step 1:** Create a migration file, in an app and then rename the app and
 migration. This will result in a migration similar to this:


 {{{#!python

 # alpha/migrations/0001_initial.py
 class Migration(migrations.Migration):

     replaces = [
         ('first', '0001_initial'),
     ]


 }}}

 **Step 2:** Ensure you have migrations in another app, with the first
 migration the second app referencing the old migration:

 {{{#!python

 class Migration(migrations.Migration):

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

 }}}

 **Step 3:** Note that `migrate` will happily apply all migrations:

   {{{#!shell
 python3 manage.py migrate
 Operations to perform:
   Apply all migrations: admin, alpha, auth, beta, contenttypes, sessions
 Running migrations:
   Applying contenttypes.0001_initial... OK
   Applying auth.0001_initial... OK
   Applying admin.0001_initial... OK
   Applying admin.0002_logentry_remove_auto_add... OK
   Applying admin.0003_logentry_add_action_flag_choices... OK
   Applying alpha.0001_initial... OK
   Applying contenttypes.0002_remove_content_type_name... OK
   Applying auth.0002_alter_permission_name_max_length... OK
   Applying auth.0003_alter_user_email_max_length... OK
   Applying auth.0004_alter_user_username_opts... OK
   Applying auth.0005_alter_user_last_login_null... OK
   Applying auth.0006_require_contenttypes_0002... OK
   Applying auth.0007_alter_validators_add_error_messages... OK
   Applying auth.0008_alter_user_username_max_length... OK
   Applying auth.0009_alter_user_last_name_max_length... OK
   Applying auth.0010_alter_group_name_max_length... OK
   Applying auth.0011_update_proxy_permissions... OK
   Applying auth.0012_alter_user_first_name_max_length... OK
   Applying beta.0001_initial... OK
   Applying beta.0002_auto_20220318_0245... OK
   Applying beta.0003_auto_20220318_0247... OK
   Applying sessions.0001_initial... OK
   }}}

 **Step 4:** However, `sqlmigrate` will raise an error:

  {{{#!shell
 python3 manage.py sqlmigrate beta 0003
 Traceback (most recent call last):
   File "/Users/amin/sandbox/mysite/manage.py", line 22, in <module>
     main()
   File "/Users/amin/sandbox/mysite/manage.py", line 18, in main
     execute_from_command_line(sys.argv)
   File "/usr/local/lib/python3.9/site-
 packages/django/core/management/__init__.py", line 446, in
 execute_from_command_line
     utility.execute()
   File "/usr/local/lib/python3.9/site-
 packages/django/core/management/__init__.py", line 440, in execute
     self.fetch_command(subcommand).run_from_argv(self.argv)
   File "/usr/local/lib/python3.9/site-
 packages/django/core/management/base.py", line 414, in run_from_argv
     self.execute(*args, **cmd_options)
   File "/usr/local/lib/python3.9/site-
 packages/django/core/management/commands/sqlmigrate.py", line 38, in
 execute
     return super().execute(*args, **options)
   File "/usr/local/lib/python3.9/site-
 packages/django/core/management/base.py", line 460, in execute
     output = self.handle(*args, **options)
   File "/usr/local/lib/python3.9/site-
 packages/django/core/management/commands/sqlmigrate.py", line 46, in
 handle
     loader = MigrationLoader(connection, replace_migrations=False)
   File "/usr/local/lib/python3.9/site-
 packages/django/db/migrations/loader.py", line 58, in __init__
     self.build_graph()
   File "/usr/local/lib/python3.9/site-
 packages/django/db/migrations/loader.py", line 276, in build_graph
     self.graph.validate_consistency()
   File "/usr/local/lib/python3.9/site-
 packages/django/db/migrations/graph.py", line 198, in validate_consistency
     [n.raise_error() for n in self.node_map.values() if isinstance(n,
 DummyNode)]
   File "/usr/local/lib/python3.9/site-
 packages/django/db/migrations/graph.py", line 198, in <listcomp>
     [n.raise_error() for n in self.node_map.values() if isinstance(n,
 DummyNode)]
   File "/usr/local/lib/python3.9/site-
 packages/django/db/migrations/graph.py", line 60, in raise_error
     raise NodeNotFoundError(self.error_message, self.key,
 origin=self.origin)
 django.db.migrations.exceptions.NodeNotFoundError: Migration
 beta.0001_initial dependencies reference nonexistent parent node ('first',
 '0001_initial')
  }}}


 **Note:** I have a demo available to try [https://github.com/amingilani
 /django-bug-PoC here].

-- 
Ticket URL: <https://code.djangoproject.com/ticket/33583>
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/0107017f9b04f939-0ea8561c-ea47-40cc-9654-b18e15a11eb4-000000%40eu-central-1.amazonses.com.

Reply via email to