Opened 5 years ago

Last modified 3 weeks ago

#31834 assigned Bug

Cannot sqlmigrate on Django migrations that change unique_together

Reported by: Brіаn Lаі Owned by: Bishnu Bhattarai
Component: Migrations Version: 3.0
Severity: Normal Keywords: sqlmigrate
Cc: Triage Stage: Accepted
Has patch: yes Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description (last modified by Brіаn Lаі)

Somewhat similar to #26624, but forward sqlmigrate, reproduced on Django 3.0.8 and Postgres 10.x.

If a model has a unique_together of

unique_together = [
    (a, b)
]

and it becomes

unique_together = [
    (a, b, c)
]

, although the makemigrations command successfully generates a new migration with the corresponding AlterUniqueTogether() operation, the migration cannot be inspected with the sqlmigrate command.

Reproduce bug with the following (the project may also be attached)

class Model1(models.Model):
    id = models.IntegerField(primary_key=True)
    name = models.CharField(max_length=255, unique=True)


class Model2(models.Model):
    id = models.IntegerField(primary_key=True)
    link_id = models.CharField(max_length=255)
    settings = models.ForeignKey(Model1, on_delete=models.CASCADE)


class Model3(models.Model):
    id = models.IntegerField(primary_key=True)
    order = models.IntegerField()
    model_2 = models.ForeignKey(Model2, on_delete=models.CASCADE)
    direct = models.BooleanField(default=True)

    class Meta:
        unique_together = [
            ('model_2', 'order')
            # To get the bug, change this to ('model_2', 'order', 'direct') and sqlmigrate the migration that this creates.
        ]

The error shown in the terminal is:

Traceback (most recent call last):
  File "manage.py", line 22, in <module>
    execute_from_command_line(sys.argv)
  File "/lib/python3.6/site-packages/django/core/management/__init__.py", line 401, in execute_from_command_line
    utility.execute()
  File "/lib/python3.6/site-packages/django/core/management/__init__.py", line 395, in execute
    self.fetch_command(subcommand).run_from_argv(self.argv)
  File "/lib/python3.6/site-packages/django/core/management/base.py", line 328, in run_from_argv
    self.execute(*args, **cmd_options)
  File "/lib/python3.6/site-packages/django/core/management/commands/sqlmigrate.py", line 30, in execute
    return super().execute(*args, **options)
  File "/lib/python3.6/site-packages/django/core/management/base.py", line 369, in execute
    output = self.handle(*args, **options)
  File "/lib/python3.6/site-packages/django/core/management/commands/sqlmigrate.py", line 65, in handle
    sql_statements = executor.collect_sql(plan)
  File "/lib/python3.6/site-packages/django/db/migrations/executor.py", line 225, in collect_sql
    state = migration.apply(state, schema_editor, collect_sql=True)
  File "/lib/python3.6/site-packages/django/db/migrations/migration.py", line 124, in apply
    operation.database_forwards(self.app_label, schema_editor, old_state, project_state)
  File "/lib/python3.6/site-packages/django/db/migrations/operations/models.py", line 525, in database_forwards
    getattr(new_model._meta, self.option_name, set()),
  File "/lib/python3.6/site-packages/django/db/backends/base/schema.py", line 380, in alter_unique_together
    self._delete_composed_index(model, fields, {'unique': True}, self.sql_delete_unique)
  File "/lib/python3.6/site-packages/django/db/backends/base/schema.py", line 414, in _delete_composed_index
    ", ".join(columns),
ValueError: Found wrong number (0) of constraints for bar_model3(model_2, order)

Attachments (1)

foo.tar.gz (5.8 KB ) - added by Brіаn Lаі 5 years ago.
Bug demo project

Download all attachments as: .zip

Change History (9)

by Brіаn Lаі, 5 years ago

Attachment: foo.tar.gz added

Bug demo project

comment:1 by Brіаn Lаі, 5 years ago

Description: modified (diff)

comment:2 by Brіаn Lаі, 5 years ago

Description: modified (diff)

comment:3 by Mariusz Felisiak, 5 years ago

Component: Database layer (models, ORM)Migrations
Resolution: duplicate
Status: newclosed

I think we can mark this as a duplicate of #26624, because they have the same cause. In both scenarios a constraint doesn't exist in the database and cannot be introspected, sqlmigrate works properly if you first apply a migration which adds a constraint.

comment:4 by Brіаn Lаі, 5 years ago

I guess so. However you choose to triage and/or fix the item, I hope I am providing additional context by saying this bug can be reproduced with SQLite, whereas #26624 claims they could not.

comment:5 by Jacob Walls, 8 weeks ago

Resolution: duplicate
Status: closednew
Triage Stage: UnreviewedAccepted

#26624 was wontfix'ed by scoping it to the deprecated index_together, but since this report is for unique_together, it should be valid now.

comment:6 by Bishnu Bhattarai, 3 weeks ago

Owner: changed from nobody to Bishnu Bhattarai
Status: newassigned

I am interested in this ticket, I want to assign this ticket myself.

comment:7 by Bishnu Bhattarai, 3 weeks ago

I have created a PR for this issue and have fixed from manual testing,

But writing test case for this type of fix looks a bit complicated, Could you please provide me some example of test case for sqlmigrate and in which file is the best place to keep this test.
here is the PR https://github.com/django/django/pull/19590

comment:8 by Bishnu Bhattarai, 3 weeks ago

Has patch: set
Note: See TracTickets for help on using tickets.
Back to Top