--- 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
--- 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
--- 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)
--- 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'
--- 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'
--- 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()