server/migractions.py
changeset 9375 8e88576787c3
parent 9255 46f41c3e1443
child 9402 2c48c091b6a2
child 9421 6b673cb4d3b6
--- a/server/migractions.py	Tue Jan 07 17:45:48 2014 +0100
+++ b/server/migractions.py	Wed Jan 08 12:09:44 2014 +0100
@@ -44,7 +44,7 @@
 from logilab.common.decorators import cached, clear_cache
 
 from yams.constraints import SizeConstraint
-from yams.schema2sql import eschema2sql, rschema2sql
+from yams.schema2sql import eschema2sql, rschema2sql, unique_index_name
 from yams.schema import RelationDefinitionSchema
 
 from cubicweb import CW_SOFTWARE_ROOT, AuthenticationError, ExecutionError
@@ -559,39 +559,41 @@
                         self._synchronize_rdef_schema(subj, rschema, obj,
                                                       syncprops=syncprops, syncperms=syncperms)
         if syncprops: # need to process __unique_together__ after rdefs were processed
-            repo_unique_together = set([frozenset(ut)
-                                        for ut in repoeschema._unique_together])
-            unique_together = set([frozenset(ut)
-                                   for ut in eschema._unique_together])
-            for ut in repo_unique_together - unique_together:
-                restrictions = []
-                substs = {'x': repoeschema.eid}
-                for i, col in enumerate(ut):
-                    restrictions.append('C relations T%(i)d, '
-                                       'T%(i)d name %%(T%(i)d)s' % {'i': i})
-                    substs['T%d'%i] = col
-                self.rqlexec('DELETE CWUniqueTogetherConstraint C '
-                             'WHERE C constraint_of E, '
-                             '      E eid %%(x)s,'
-                             '      %s' % ', '.join(restrictions),
-                             substs)
-            def possible_unique_constraint(ut):
-                for name in ut:
+            # mappings from constraint name to columns
+            # filesystem (fs) and repository (repo) wise
+            fs = {}
+            repo = {}
+            for cols in eschema._unique_together or ():
+                fs[unique_index_name(repoeschema, cols)] = sorted(cols)
+            schemaentity = self.session.entity_from_eid(repoeschema.eid)
+            for entity in schemaentity.related('constraint_of', 'object',
+                                               targettypes=('CWUniqueTogetherConstraint',)).entities():
+                repo[entity.name] = sorted(rel.name for rel in entity.relations)
+            added = set(fs) - set(repo)
+            removed = set(repo) - set(fs)
+
+            for name in removed:
+                self.rqlexec('DELETE CWUniqueTogetherConstraint C WHERE C name %(name)s',
+                             {'name': name})
+
+            def possible_unique_constraint(cols):
+                for name in cols:
                     rschema = repoeschema.subjrels.get(name)
                     if rschema is None:
                         print 'dont add %s unique constraint on %s, missing %s' % (
-                            ','.join(ut), eschema, name)
+                            ','.join(cols), eschema, name)
                         return False
                     if not (rschema.final or rschema.inlined):
-                        (eschema, name)
                         print 'dont add %s unique constraint on %s, %s is neither final nor inlined' % (
-                            ','.join(ut), eschema, name)
+                            ','.join(cols), eschema, name)
                         return False
                 return True
-            for ut in unique_together - repo_unique_together:
-                if possible_unique_constraint(ut):
-                    rql, substs = ss.uniquetogether2rql(eschema, ut)
+
+            for name in added:
+                if possible_unique_constraint(fs[name]):
+                    rql, substs = ss._uniquetogether2rql(eschema, fs[name])
                     substs['x'] = repoeschema.eid
+                    substs['name'] = name
                     self.rqlexec(rql, substs)
 
     def _synchronize_rdef_schema(self, subjtype, rtype, objtype,