# HG changeset patch # User Sylvain Thénault # Date 1467965834 -7200 # Node ID d41832121b2979396a9417739f92a713439546e8 # Parent f5a4e14d1dd218db095034a82919a4a8ae7c6ca7 [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. Grafted from f87da59faea1 in default branch. diff -r f5a4e14d1dd2 -r d41832121b29 cubicweb/hooks/syncschema.py --- a/cubicweb/hooks/syncschema.py Thu Sep 08 11:40:50 2016 +0200 +++ b/cubicweb/hooks/syncschema.py Fri Jul 08 10:17:14 2016 +0200 @@ -809,14 +809,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.subject, rdef.object, rdef.rtype.type, + 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.subject, rdef.object, rdef.rtype.type, - 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)) diff -r f5a4e14d1dd2 -r d41832121b29 cubicweb/server/test/data-migractions/migratedapp/schema.py --- a/cubicweb/server/test/data-migractions/migratedapp/schema.py Thu Sep 08 11:40:50 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') diff -r f5a4e14d1dd2 -r d41832121b29 cubicweb/server/test/unittest_migractions.py --- a/cubicweb/server/test/unittest_migractions.py Thu Sep 08 11:40:50 2016 +0200 +++ b/cubicweb/server/test/unittest_migractions.py Fri Jul 08 10:17:14 2016 +0200 @@ -183,11 +183,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):