#23906: "ValueError: Found wrong number (0) of constraints" when migrating
backwards with from alter_unique_together migration.
-------------------------+-------------------------------------------------
     Reporter:           |      Owner:  nobody
  liavkoren              |     Status:  new
         Type:  Bug      |    Version:  1.7
    Component:           |   Keywords:  alter_unique_together migrations
  Migrations             |  constraints valueError
     Severity:  Normal   |  Has patch:  0
 Triage Stage:           |      UI/UX:  0
  Unreviewed             |
Easy pickings:  0        |
-------------------------+-------------------------------------------------
 We have a database that was created with django 1.6 and south. We've
 subsequently upgraded to 1.7.0, removed our south migrations and created
 django-migrations.

 One of our models contains a unique_together constraint that includes four
 of its attributes. When I attempt to backwards migrate the app containing
 this model I get "ValueError: Found wrong number (0) of constraints for
 foo_model(foo, bar, baz, quux)".

 I haven't been able to replicate this error by creating a test model -- it
 seems possible that this may be related to models created in django
 1.6/south and then migrated backwards in 1.7.

 The problem seems to be in django.db.backends.schema._contraint_names,
 which is supposed to return a list of relevant constrains for a set of
 columns.

 In order to do this, it is comparing an input set of columns against the
 result returned from a call to
 BaseDatabaseSchemaEditor.connection.introspection.get_constraints and
 filtering the results. The first test in the filter loop is:

 {{{#!python
     if column_names is None or column_names == infodict['columns']:
 }}}
 which is failing because it involves a comparison of lists which are in
 different orders:

 {{{#!python
 (Pdb++) column_names
 [u'foo', u'bar', u'baz', u'quux']
 (Pdb++) infodict['columns']
 [u'baz', u'bar', u'quux', u'foo']
 (Pdb++) infodict['columns'] == column_names
 False
 (Pdb++) sorted(infodict['columns']) == sorted(column_names)
 True
 }}}

 I have been able to fix this and migrate backwards by changing the
 django.db.backends.schema.BaseDatabaseSchemaEditor._constraint_names
 method to compare sets rather than lists:

 {{{#!python
     def _constraint_names(self, model, column_names=None, unique=None,
 primary_key=None, index=None, foreign_key=None, check=None):
         """
         Returns all constraint names matching the columns and conditions
         """
         # column_names = list(column_names) if column_names else None
         column_names = set(column_names) if column_names else None
         with self.connection.cursor() as cursor:
             constraints =
 self.connection.introspection.get_constraints(cursor,
 model._meta.db_table)
         result = []
         for name, infodict in constraints.items():
             # if column_names is None or column_names ==
 infodict['columns']:
             if column_names is None or column_names ==
 set(infodict['columns']):
                 if unique is not None and infodict['unique'] != unique:
                     continue
                 if primary_key is not None and infodict['primary_key'] !=
 primary_key:
                     continue
                 if index is not None and infodict['index'] != index:
                     continue
                 if check is not None and infodict['check'] != check:
                     continue
                 if foreign_key is not None and not
 infodict['foreign_key']:
                     continue
                 result.append(name)
         return result
 }}}

 I'm happy to submit a PR and tests for this issue, but I expect it's going
 to be non-trivial to reproduce.

--
Ticket URL: <https://code.djangoproject.com/ticket/23906>
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 django-updates+unsubscr...@googlegroups.com.
To post to this group, send email to django-updates@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-updates/052.385d768e46fca5dab0a268a933bad8fe%40djangoproject.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to