server/migractions.py
changeset 10651 9ca33768473c
parent 10591 8e46ed1a0b8a
parent 10646 45671fb330f5
child 10662 10942ed172de
equal deleted inserted replaced
10622:3cc6154b94a3 10651:9ca33768473c
    59 from cubicweb.server import hook, schemaserial as ss
    59 from cubicweb.server import hook, schemaserial as ss
    60 from cubicweb.server.schema2sql import eschema2sql, rschema2sql, unique_index_name
    60 from cubicweb.server.schema2sql import eschema2sql, rschema2sql, unique_index_name
    61 from cubicweb.server.utils import manager_userpasswd
    61 from cubicweb.server.utils import manager_userpasswd
    62 from cubicweb.server.sqlutils import sqlexec, SQL_PREFIX
    62 from cubicweb.server.sqlutils import sqlexec, SQL_PREFIX
    63 
    63 
    64 
       
    65 def mock_object(**params):
       
    66     return type('Mock', (), params)()
       
    67 
    64 
    68 class ClearGroupMap(hook.Hook):
    65 class ClearGroupMap(hook.Hook):
    69     __regid__ = 'cw.migration.clear_group_mapping'
    66     __regid__ = 'cw.migration.clear_group_mapping'
    70     __select__ = hook.Hook.__select__ & is_instance('CWGroup')
    67     __select__ = hook.Hook.__select__ & is_instance('CWGroup')
    71     events = ('after_add_entity', 'after_update_entity',)
    68     events = ('after_add_entity', 'after_update_entity',)
   449         physical schema changes should be handled by repository's schema hooks
   446         physical schema changes should be handled by repository's schema hooks
   450         """
   447         """
   451         rtype = str(rtype)
   448         rtype = str(rtype)
   452         if rtype in self._synchronized:
   449         if rtype in self._synchronized:
   453             return
   450             return
   454         self._synchronized.add(rtype)
   451         if syncrdefs and syncperms and syncprops:
       
   452             self._synchronized.add(rtype)
   455         rschema = self.fs_schema.rschema(rtype)
   453         rschema = self.fs_schema.rschema(rtype)
   456         reporschema = self.repo.schema.rschema(rtype)
   454         reporschema = self.repo.schema.rschema(rtype)
   457         if syncprops:
   455         if syncprops:
   458             assert reporschema.eid, reporschema
   456             assert reporschema.eid, reporschema
   459             self.rqlexecall(ss.updaterschema2rql(rschema, reporschema.eid),
   457             self.rqlexecall(ss.updaterschema2rql(rschema, reporschema.eid),
   480         * permissions if `syncperms`
   478         * permissions if `syncperms`
   481         """
   479         """
   482         etype = str(etype)
   480         etype = str(etype)
   483         if etype in self._synchronized:
   481         if etype in self._synchronized:
   484             return
   482             return
   485         self._synchronized.add(etype)
   483         if syncrdefs and syncperms and syncprops:
       
   484             self._synchronized.add(etype)
   486         repoeschema = self.repo.schema.eschema(etype)
   485         repoeschema = self.repo.schema.eschema(etype)
   487         try:
   486         try:
   488             eschema = self.fs_schema.eschema(etype)
   487             eschema = self.fs_schema.eschema(etype)
   489         except KeyError:
   488         except KeyError:
   490             return # XXX somewhat unexpected, no?...
   489             return # XXX somewhat unexpected, no?...
   578             raise ExecutionError('Cannot synchronize a relation definition for a '
   577             raise ExecutionError('Cannot synchronize a relation definition for a '
   579                                  'computed relation (%s)' % rschema)
   578                                  'computed relation (%s)' % rschema)
   580         reporschema = self.repo.schema.rschema(rschema)
   579         reporschema = self.repo.schema.rschema(rschema)
   581         if (subjtype, rschema, objtype) in self._synchronized:
   580         if (subjtype, rschema, objtype) in self._synchronized:
   582             return
   581             return
   583         self._synchronized.add((subjtype, rschema, objtype))
   582         if syncperms and syncprops:
   584         if rschema.symmetric:
   583             self._synchronized.add((subjtype, rschema, objtype))
   585             self._synchronized.add((objtype, rschema, subjtype))
   584             if rschema.symmetric:
       
   585                 self._synchronized.add((objtype, rschema, subjtype))
   586         rdef = rschema.rdef(subjtype, objtype)
   586         rdef = rschema.rdef(subjtype, objtype)
   587         if rdef.infered:
   587         if rdef.infered:
   588             return # don't try to synchronize infered relation defs
   588             return # don't try to synchronize infered relation defs
   589         repordef = reporschema.rdef(subjtype, objtype)
   589         repordef = reporschema.rdef(subjtype, objtype)
   590         confirm = self.verbosity >= 2
   590         confirm = self.verbosity >= 2
  1074         """
  1074         """
  1075         if oldname in self.fs_schema and not force:
  1075         if oldname in self.fs_schema and not force:
  1076             if not self.confirm('Relation %s is still present in the filesystem schema,'
  1076             if not self.confirm('Relation %s is still present in the filesystem schema,'
  1077                                 ' do you really want to drop it?' % oldname,
  1077                                 ' do you really want to drop it?' % oldname,
  1078                                 default='n'):
  1078                                 default='n'):
  1079                 raise SystemExit(1)
  1079                 return
  1080         self.cmd_add_relation_type(newname, commit=True)
  1080         self.cmd_add_relation_type(newname, commit=True)
  1081         self.rqlexec('SET X %s Y WHERE X %s Y' % (newname, oldname),
  1081         if not self.repo.schema[oldname].rule:
  1082                      ask_confirm=self.verbosity>=2)
  1082             self.rqlexec('SET X %s Y WHERE X %s Y' % (newname, oldname),
       
  1083                          ask_confirm=self.verbosity>=2)
  1083         self.cmd_drop_relation_type(oldname, commit=commit)
  1084         self.cmd_drop_relation_type(oldname, commit=commit)
  1084 
  1085 
  1085     def cmd_add_relation_definition(self, subjtype, rtype, objtype, commit=True):
  1086     def cmd_add_relation_definition(self, subjtype, rtype, objtype, commit=True):
  1086         """register a new relation definition, from its definition found in the
  1087         """register a new relation definition, from its definition found in the
  1087         schema definition file
  1088         schema definition file
  1474         * only works when the old type can be changed to the new type by the
  1475         * only works when the old type can be changed to the new type by the
  1475           underlying rdbms (eg using ALTER TABLE)
  1476           underlying rdbms (eg using ALTER TABLE)
  1476         * the actual schema won't be updated until next startup
  1477         * the actual schema won't be updated until next startup
  1477         """
  1478         """
  1478         rschema = self.repo.schema.rschema(attr)
  1479         rschema = self.repo.schema.rschema(attr)
  1479         oldtype = rschema.objects(etype)[0]
  1480         oldschema = rschema.objects(etype)[0]
  1480         rdefeid = rschema.rdef(etype, oldtype).eid
  1481         rdef = rschema.rdef(etype, oldschema)
  1481         allownull = rschema.rdef(etype, oldtype).cardinality[0] != '1'
       
  1482         sql = ("UPDATE cw_CWAttribute "
  1482         sql = ("UPDATE cw_CWAttribute "
  1483                "SET cw_to_entity=(SELECT cw_eid FROM cw_CWEType WHERE cw_name='%s')"
  1483                "SET cw_to_entity=(SELECT cw_eid FROM cw_CWEType WHERE cw_name='%s')"
  1484                "WHERE cw_eid=%s") % (newtype, rdefeid)
  1484                "WHERE cw_eid=%s") % (newtype, rdef.eid)
  1485         self.sqlexec(sql, ask_confirm=False)
  1485         self.sqlexec(sql, ask_confirm=False)
  1486         dbhelper = self.repo.system_source.dbhelper
  1486         dbhelper = self.repo.system_source.dbhelper
  1487         sqltype = dbhelper.TYPE_MAPPING[newtype]
  1487         sqltype = dbhelper.TYPE_MAPPING[newtype]
  1488         cursor = self.cnx.cnxset.cu
  1488         cursor = self.cnx.cnxset.cu
  1489         dbhelper.change_col_type(cursor, 'cw_%s'  % etype, 'cw_%s' % attr, sqltype, allownull)
  1489         allownull = rdef.cardinality[0] != '1'
       
  1490         dbhelper.change_col_type(cursor, 'cw_%s' % etype, 'cw_%s' % attr, sqltype, allownull)
  1490         if commit:
  1491         if commit:
  1491             self.commit()
  1492             self.commit()
       
  1493             # manually update live schema
       
  1494             eschema = self.repo.schema[etype]
       
  1495             rschema._subj_schemas[eschema].remove(oldschema)
       
  1496             rschema._obj_schemas[oldschema].remove(eschema)
       
  1497             newschema = self.repo.schema[newtype]
       
  1498             rschema._update(eschema, newschema)
       
  1499             rdef.object = newschema
       
  1500             del rschema.rdefs[(eschema, oldschema)]
       
  1501             rschema.rdefs[(eschema, newschema)] = rdef
  1492 
  1502 
  1493     def cmd_add_entity_type_table(self, etype, commit=True):
  1503     def cmd_add_entity_type_table(self, etype, commit=True):
  1494         """low level method to create the sql table for an existing entity.
  1504         """low level method to create the sql table for an existing entity.
  1495         This may be useful on accidental desync between the repository schema
  1505         This may be useful on accidental desync between the repository schema
  1496         and a sql database
  1506         and a sql database