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 |