[migration] fix change_attribute_type to update the live schema
authorSylvain Thénault <sylvain.thenault@logilab.fr>
Tue, 29 Sep 2015 12:09:04 +0200
changeset 10645 57c60a96de70
parent 10644 c43e5dc41f8b
child 10646 45671fb330f5
[migration] fix change_attribute_type to update the live schema Closes #7170830
server/migractions.py
server/test/data-migractions/migratedapp/schema.py
server/test/unittest_migractions.py
--- a/server/migractions.py	Fri Jul 24 09:57:08 2015 +0200
+++ b/server/migractions.py	Tue Sep 29 12:09:04 2015 +0200
@@ -1477,19 +1477,28 @@
         * the actual schema won't be updated until next startup
         """
         rschema = self.repo.schema.rschema(attr)
-        oldtype = rschema.objects(etype)[0]
-        rdefeid = rschema.rdef(etype, oldtype).eid
-        allownull = rschema.rdef(etype, oldtype).cardinality[0] != '1'
+        oldschema = rschema.objects(etype)[0]
+        rdef = rschema.rdef(etype, oldschema)
         sql = ("UPDATE cw_CWAttribute "
                "SET cw_to_entity=(SELECT cw_eid FROM cw_CWEType WHERE cw_name='%s')"
-               "WHERE cw_eid=%s") % (newtype, rdefeid)
+               "WHERE cw_eid=%s") % (newtype, rdef.eid)
         self.sqlexec(sql, ask_confirm=False)
         dbhelper = self.repo.system_source.dbhelper
         sqltype = dbhelper.TYPE_MAPPING[newtype]
         cursor = self.cnx.cnxset.cu
-        dbhelper.change_col_type(cursor, 'cw_%s'  % etype, 'cw_%s' % attr, sqltype, allownull)
+        allownull = rdef.cardinality[0] != '1'
+        dbhelper.change_col_type(cursor, 'cw_%s' % etype, 'cw_%s' % attr, sqltype, allownull)
         if commit:
             self.commit()
+            # manually update live schema
+            eschema = self.repo.schema[etype]
+            rschema._subj_schemas[eschema].remove(oldschema)
+            rschema._obj_schemas[oldschema].remove(eschema)
+            newschema = self.repo.schema[newtype]
+            rschema._update(eschema, newschema)
+            rdef.object = newschema
+            del rschema.rdefs[(eschema, oldschema)]
+            rschema.rdefs[(eschema, newschema)] = rdef
 
     def cmd_add_entity_type_table(self, etype, commit=True):
         """low level method to create the sql table for an existing entity.
--- a/server/test/data-migractions/migratedapp/schema.py	Fri Jul 24 09:57:08 2015 +0200
+++ b/server/test/data-migractions/migratedapp/schema.py	Tue Sep 29 12:09:04 2015 +0200
@@ -19,7 +19,7 @@
 import datetime as dt
 from yams.buildobjs import (EntityType, RelationType, RelationDefinition,
                             SubjectRelation, Bytes,
-                            RichString, String, Int, Boolean, Datetime, Date)
+                            RichString, String, Int, Boolean, Datetime, Date, Float)
 from yams.constraints import SizeConstraint, UniqueConstraint
 from cubicweb.schema import (WorkflowableEntityType, RQLConstraint,
                              RQLVocabularyConstraint,
@@ -49,7 +49,7 @@
         }
     nom  = String(maxsize=64, fulltextindexed=True)
     web  = String(maxsize=128)
-    tel  = Int()
+    tel  = Float()
     fax  = Int()
     rncs = String(maxsize=128)
     ad1  = String(maxsize=128)
--- a/server/test/unittest_migractions.py	Fri Jul 24 09:57:08 2015 +0200
+++ b/server/test/unittest_migractions.py	Tue Sep 29 12:09:04 2015 +0200
@@ -704,6 +704,18 @@
             mh.cmd_add_relation_type('same_as')
             self.assertTrue(self.table_sql(mh, 'same_as_relation'))
 
+    def test_change_attribute_type(self):
+        with self.mh() as (cnx, mh):
+            mh.cmd_create_entity('Societe', tel=1)
+            mh.commit()
+            mh.change_attribute_type('Societe', 'tel', 'Float')
+            self.assertNotIn(('Societe', 'Int'), self.schema['tel'].rdefs)
+            self.assertIn(('Societe', 'Float'), self.schema['tel'].rdefs)
+            self.assertEqual(self.schema['tel'].rdefs[('Societe', 'Float')].object, 'Float')
+            tel = mh.rqlexec('Any T WHERE X tel T')[0][0]
+            self.assertEqual(tel, 1.0)
+            self.assertIsInstance(tel, float)
+
 
 class MigrationCommandsComputedTC(MigrationTC):
     """ Unit tests for computed relations and attributes