[schema sync] test and fix bug when updating multiple constraint for the same rdef in the same transaction stable
authorSylvain Thénault <sylvain.thenault@logilab.fr>
Wed, 17 Mar 2010 09:21:13 +0100
branchstable
changeset 4927 19fd1952ad63
parent 4926 626d31035662
child 4928 cbca73dc9753
[schema sync] test and fix bug when updating multiple constraint for the same rdef in the same transaction
hooks/syncschema.py
hooks/test/unittest_syncschema.py
--- a/hooks/syncschema.py	Wed Mar 17 09:19:02 2010 +0100
+++ b/hooks/syncschema.py	Wed Mar 17 09:21:13 2010 +0100
@@ -187,11 +187,12 @@
         # every schema operation is triggering a schema update
         MemSchemaNotifyChanges(session)
 
-    def prepare_constraints(self, subjtype, rtype, objtype):
-        rdef = rtype.rdef(subjtype, objtype)
-        constraints = rdef.constraints
-        self.constraints = list(constraints)
-        rdef.constraints = self.constraints
+    def prepare_constraints(self, rdef):
+        # if constraints is already a list, reuse it (we're updating multiple
+        # constraints of the same rdef in the same transactions
+        if not isinstance(rdef.constraints, list):
+            rdef.constraints = list(rdef.constraints)
+        self.constraints = rdef.constraints
 
 
 class MemSchemaEarlyOperation(MemSchemaOperation):
@@ -665,8 +666,8 @@
             self.cancelled = True
             return
         rdef = self.session.vreg.schema.schema_by_eid(rdef.eid)
+        self.prepare_constraints(rdef)
         subjtype, rtype, objtype = rdef.as_triple()
-        self.prepare_constraints(subjtype, rtype, objtype)
         cstrtype = self.entity.type
         self.cstr = rtype.rdef(subjtype, objtype).constraint_by_type(cstrtype)
         self.newcstr = CONSTRAINTS[cstrtype].deserialize(self.entity.value)
@@ -688,7 +689,7 @@
     """
     rtype = subjtype = objtype = None # make pylint happy
     def precommit_event(self):
-        self.prepare_constraints(self.subjtype, self.rtype, self.objtype)
+        self.prepare_constraints(self.rdef)
 
     def commit_event(self):
         self.constraints.remove(self.cstr)
@@ -1085,11 +1086,9 @@
         except IndexError:
             self._cw.critical('constraint type no more accessible')
         else:
-            subjtype, rtype, objtype = rdef.as_triple()
-            SourceDbCWConstraintDel(self._cw, subjtype=subjtype, rtype=rtype,
-                                    objtype=objtype, cstr=cstr)
-            MemSchemaCWConstraintDel(self._cw, subjtype=subjtype, rtype=rtype,
-                                     objtype=objtype, cstr=cstr)
+            SourceDbCWConstraintDel(self._cw, cstr=cstr,
+                                    subjtype=rdef.subject, rtype=rdef.rtype)
+            MemSchemaCWConstraintDel(self._cw, rdef=rdef, cstr=cstr)
 
 
 # permissions synchronization hooks ############################################
--- a/hooks/test/unittest_syncschema.py	Wed Mar 17 09:19:02 2010 +0100
+++ b/hooks/test/unittest_syncschema.py	Wed Mar 17 09:21:13 2010 +0100
@@ -308,3 +308,17 @@
         rset = req.execute('Any X WHERE X has_text "rick.roll"')
         self.assertIn(req.user.eid, [item[0] for item in rset])
 
+    def test_update_constraint(self):
+        rdef = self.schema['Transition'].rdef('type')
+        cstr = rdef.constraint_by_type('StaticVocabularyConstraint')
+        if not getattr(cstr, 'eid', None):
+            self.skip('start me alone') # bug in schema reloading, constraint's eid not restored
+        self.execute('SET X value %(v)s WHERE X eid %(x)s',
+                     {'x': cstr.eid, 'v': u"u'normal', u'auto', u'new'"}, 'x')
+        self.execute('INSERT CWConstraint X: X value %(value)s, X cstrtype CT, EDEF constrained_by X '
+                     'WHERE CT name %(ct)s, EDEF eid %(x)s',
+                     {'ct': 'SizeConstraint', 'value': u'max=10', 'x': rdef.eid}, 'x')
+        self.commit()
+        cstr = rdef.constraint_by_type('StaticVocabularyConstraint')
+        self.assertEquals(cstr.values, (u'normal', u'auto', u'new'))
+        self.execute('INSERT Transition T: T name "hop", T type "new"')