#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 [email protected].
To post to this group, send email to [email protected].
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