[migration] Test and fix case of addition of an attribute with some serialized constraint
authorSylvain Thénault <sylvain.thenault@logilab.fr>
Fri, 08 Jul 2016 10:17:14 +0200
changeset 11415 f87da59faea1
parent 11414 69ea7be0373a
child 11416 9c2fbb872e91
[migration] Test and fix case of addition of an attribute with some serialized constraint It was crashing on attempt to remove an unexisting constraint. This code may be removed safely as it's expected to be handled by the constraint removal hook. Notice that adding a vocabulary on shortpara makes yams change the varchar max size. This is arguable but not the point of this test, so simply adapt the max size defined in the schema coherently so we don't have to bother with that at this point.
cubicweb/hooks/syncschema.py
cubicweb/server/test/data-migractions/migratedapp/schema.py
cubicweb/server/test/unittest_migractions.py
--- a/cubicweb/hooks/syncschema.py	Thu Jul 07 14:10:45 2016 +0200
+++ b/cubicweb/hooks/syncschema.py	Fri Jul 08 10:17:14 2016 +0200
@@ -803,14 +803,19 @@
         elif cstrtype == 'UniqueConstraint' and oldcstr is None:
             syssource.update_rdef_unique(cnx, rdef)
             self.unique_changed = True
-        if cstrtype in ('BoundaryConstraint', 'IntervalBoundConstraint', 'StaticVocabularyConstraint'):
+        if cstrtype in ('BoundaryConstraint',
+                        'IntervalBoundConstraint',
+                        'StaticVocabularyConstraint'):
+            cstrname, check = y2sql.check_constraint(rdef, newcstr, syssource.dbhelper,
+                                                     prefix=SQL_PREFIX)
+            # oldcstr is the new constraint when the attribute is being added in the same
+            # transaction or when constraint value is updated. So we've to take care...
             if oldcstr is not None:
                 oldcstrname = 'cstr' + md5((rdef.subject.type + rdef.rtype.type + cstrtype +
-                                            (self.oldcstr.serialize() or '')).encode('ascii')).hexdigest()
-                cnx.system_sql('ALTER TABLE %s%s DROP CONSTRAINT %s' %
-                               (SQL_PREFIX, rdef.subject.type, oldcstrname))
-            cstrname, check = y2sql.check_constraint(rdef, newcstr, syssource.dbhelper,
-                                                     prefix=SQL_PREFIX)
+                                            (self.oldcstr.serialize() or '')).encode('utf-8')).hexdigest()
+                if oldcstrname != cstrname:
+                    cnx.system_sql('ALTER TABLE %s%s DROP CONSTRAINT %s'
+                                   % (SQL_PREFIX, rdef.subject.type, oldcstrname))
             cnx.system_sql('ALTER TABLE %s%s ADD CONSTRAINT %s CHECK(%s)' %
                            (SQL_PREFIX, rdef.subject.type, cstrname, check))
 
--- a/cubicweb/server/test/data-migractions/migratedapp/schema.py	Thu Jul 07 14:10:45 2016 +0200
+++ b/cubicweb/server/test/data-migractions/migratedapp/schema.py	Fri Jul 08 10:17:14 2016 +0200
@@ -87,7 +87,7 @@
     mydate = Date(default='TODAY')
     oldstyledefaultdate = Date(default='2013/01/01')
     newstyledefaultdate = Date(default=dt.date(2013, 1, 1))
-    shortpara = String(maxsize=64, default='hop')
+    shortpara = String(maxsize=11, default='hop', vocabulary=['hop', 'hop hop', 'hop hop hop'])
     ecrit_par = SubjectRelation('Personne', constraints=[RQLConstraint('S concerne A, O concerne A')])
     attachment = SubjectRelation('File')
 
--- a/cubicweb/server/test/unittest_migractions.py	Thu Jul 07 14:10:45 2016 +0200
+++ b/cubicweb/server/test/unittest_migractions.py	Fri Jul 08 10:17:14 2016 +0200
@@ -192,11 +192,14 @@
             self.assertEqual(self.schema['shortpara'].objects(), ('String', ))
             # test created column is actually a varchar(64)
             fields = self.table_schema(mh, '%sNote' % SQL_PREFIX)
-            self.assertEqual(fields['%sshortpara' % SQL_PREFIX], ('character varying', 64))
+            self.assertEqual(fields['%sshortpara' % SQL_PREFIX], ('character varying', 11))
             # test default value set on existing entities
             self.assertEqual(cnx.execute('Note X').get_entity(0, 0).shortpara, 'hop')
             # test default value set for next entities
-            self.assertEqual(cnx.create_entity('Note', shortpara=u'hophop').shortpara, u'hophop')
+            self.assertEqual(cnx.create_entity('Note', shortpara=u'hop hop').shortpara, u'hop hop')
+            # serialized constraint added
+            constraints = self.table_constraints(mh, 'cw_Personne')
+            self.assertEqual(len(constraints), 1, constraints)
 
     def test_add_attribute_unique(self):
         with self.mh() as (cnx, mh):