# HG changeset patch # User Sylvain Thénault # Date 1409204669 -7200 # Node ID f4a3ee05cf9d77497722631d05af8bc45c4f87f7 # Parent 5531f5577b50b846bd7d0d8fbbc61b12f6aa10d4 [CWEP002 migration] support sync_schema_props_perms for computed relations diff -r 5531f5577b50 -r f4a3ee05cf9d hooks/syncschema.py --- a/hooks/syncschema.py Thu Aug 28 08:02:15 2014 +0200 +++ b/hooks/syncschema.py Thu Aug 28 07:44:29 2014 +0200 @@ -389,6 +389,21 @@ # XXX revert changes on database +class CWComputedRTypeUpdateOp(MemSchemaOperation): + """actually update some properties of a computed relation definition""" + rschema = entity = rule = None # make pylint happy + old_rule = None + + def precommit_event(self): + # update the in-memory schema first + self.old_rule = self.rschema.rule + self.rschema.rule = self.rule + + def revertprecommit_event(self): + # revert changes on in memory schema + self.rschema.rule = self.old_rule + + class CWAttributeAddOp(MemSchemaOperation): """an attribute relation (CWAttribute) has been added: * add the necessary column @@ -1046,6 +1061,23 @@ values=newvalues) +class BeforeUpdateCWComputedRTypeHook(SyncSchemaHook): + """check name change, handle final""" + __regid__ = 'syncupdatecwcomputedrtype' + __select__ = SyncSchemaHook.__select__ & is_instance('CWComputedRType') + events = ('before_update_entity',) + + def __call__(self): + entity = self.entity + check_valid_changes(self._cw, entity) + if 'rule' in entity.cw_edited: + old, new = entity.cw_edited.oldnewvalue('rule') + if old != new: + rschema = self._cw.vreg.schema.rschema(entity.name) + CWComputedRTypeUpdateOp(self._cw, rschema=rschema, + entity=entity, rule=new) + + class AfterDelRelationTypeHook(SyncSchemaHook): """before deleting a CWAttribute or CWRelation entity: * if this is a final or inlined relation definition, instantiate an diff -r 5531f5577b50 -r f4a3ee05cf9d server/migractions.py --- a/server/migractions.py Thu Aug 28 08:02:15 2014 +0200 +++ b/server/migractions.py Thu Aug 28 07:44:29 2014 +0200 @@ -579,6 +579,9 @@ """ subjtype, objtype = str(subjtype), str(objtype) rschema = self.fs_schema.rschema(rtype) + if rschema.rule: + raise ExecutionError('Cannot synchronize a relation definition for a ' + 'computed relation (%s)' % rschema) reporschema = self.repo.schema.rschema(rschema) if (subjtype, rschema, objtype) in self._synchronized: return diff -r 5531f5577b50 -r f4a3ee05cf9d server/schemaserial.py --- a/server/schemaserial.py Thu Aug 28 08:02:15 2014 +0200 +++ b/server/schemaserial.py Thu Aug 28 07:44:29 2014 +0200 @@ -615,9 +615,13 @@ yield 'SET %s WHERE X eid %%(x)s' % ','.join(relations), values def updaterschema2rql(rschema, eid): - relations, values = rschema_relations_values(rschema) - values['x'] = eid - yield 'SET %s WHERE X eid %%(x)s' % ','.join(relations), values + if rschema.rule: + yield ('SET X rule %(r)s WHERE X eid %(x)s', + {'x': eid, 'r': unicode(rschema.rule)}) + else: + relations, values = rschema_relations_values(rschema) + values['x'] = eid + yield 'SET %s WHERE X eid %%(x)s' % ','.join(relations), values def updaterdef2rql(rdef, eid): relations, values = _rdef_values(rdef) diff -r 5531f5577b50 -r f4a3ee05cf9d server/test/datacomputed/migratedapp/schema.py --- a/server/test/datacomputed/migratedapp/schema.py Thu Aug 28 08:02:15 2014 +0200 +++ b/server/test/datacomputed/migratedapp/schema.py Thu Aug 28 07:44:29 2014 +0200 @@ -49,3 +49,6 @@ subject = 'Note' object = 'Employee' + +class whatever(ComputedRelation): + rule = 'S employees E, O associates E' diff -r 5531f5577b50 -r f4a3ee05cf9d server/test/datacomputed/schema.py --- a/server/test/datacomputed/schema.py Thu Aug 28 08:02:15 2014 +0200 +++ b/server/test/datacomputed/schema.py Thu Aug 28 07:44:29 2014 +0200 @@ -48,3 +48,7 @@ class notes(ComputedRelation): rule = 'S employees E, O concerns E' + + +class whatever(ComputedRelation): + rule = 'S employees E, O concerns E' diff -r 5531f5577b50 -r f4a3ee05cf9d server/test/unittest_migractions.py --- a/server/test/unittest_migractions.py Thu Aug 28 08:02:15 2014 +0200 +++ b/server/test/unittest_migractions.py Thu Aug 28 07:44:29 2014 +0200 @@ -735,6 +735,26 @@ mh.cmd_drop_relation_type('notes') self.assertNotIn('notes', self.schema) + def test_computed_relation_sync_schema_props_perms(self): + self.assertIn('whatever', self.schema) + with self.mh() as (cnx, mh): + mh.cmd_sync_schema_props_perms('whatever') + self.assertEqual(self.schema['whatever'].rule, + 'S employees E, O associates E') + self.assertEqual(self.schema['whatever'].objects(), ('Company',)) + self.assertEqual(self.schema['whatever'].subjects(), ('Company',)) + self.assertFalse(self.table_sql(mh, 'whatever_relation')) + + def test_computed_relation_sync_schema_props_perms_on_rdef(self): + self.assertIn('whatever', self.schema) + with self.mh() as (cnx, mh): + with self.assertRaises(ExecutionError) as exc: + mh.cmd_sync_schema_props_perms( + ('Company', 'whatever', 'Person')) + self.assertEqual(str(exc.exception), + 'Cannot synchronize a relation definition for a computed ' + 'relation (whatever)') + if __name__ == '__main__': unittest_main()