hooks/syncschema.py
changeset 2841 107ba1c45227
parent 2835 04034421b072
child 2847 c2ee28f4d4b1
equal deleted inserted replaced
2840:06daf13195d4 2841:107ba1c45227
   451         rdef = self.entity.reverse_constrained_by[0]
   451         rdef = self.entity.reverse_constrained_by[0]
   452         session = self.session
   452         session = self.session
   453         # when the relation is added in the same transaction, the constraint
   453         # when the relation is added in the same transaction, the constraint
   454         # object is created by the operation adding the attribute or relation,
   454         # object is created by the operation adding the attribute or relation,
   455         # so there is nothing to do here
   455         # so there is nothing to do here
   456         if rdef.eid in session.transaction_data.get('neweids', ()):
   456         if session.added_in_transaction(rdef.eid):
   457             return
   457             return
   458         subjtype, rtype, objtype = session.schema.schema_by_eid(rdef.eid)
   458         subjtype, rtype, objtype = session.schema.schema_by_eid(rdef.eid)
   459         cstrtype = self.entity.type
   459         cstrtype = self.entity.type
   460         oldcstr = rtype.constraint_by_type(subjtype, objtype, cstrtype)
   460         oldcstr = rtype.constraint_by_type(subjtype, objtype, cstrtype)
   461         newcstr = CONSTRAINTS[cstrtype].deserialize(self.entity.value)
   461         newcstr = CONSTRAINTS[cstrtype].deserialize(self.entity.value)
   600     def precommit_event(self):
   600     def precommit_event(self):
   601         rdef = self.entity.reverse_constrained_by[0]
   601         rdef = self.entity.reverse_constrained_by[0]
   602         # when the relation is added in the same transaction, the constraint
   602         # when the relation is added in the same transaction, the constraint
   603         # object is created by the operation adding the attribute or relation,
   603         # object is created by the operation adding the attribute or relation,
   604         # so there is nothing to do here
   604         # so there is nothing to do here
   605         if rdef.eid in self.session.transaction_data.get('neweids', ()):
   605         if session.added_in_transaction(rdef.eid):
   606             self.cancelled = True
   606             self.cancelled = True
   607             return
   607             return
   608         subjtype, rtype, objtype = self.session.schema.schema_by_eid(rdef.eid)
   608         subjtype, rtype, objtype = self.session.schema.schema_by_eid(rdef.eid)
   609         self.prepare_constraints(subjtype, rtype, objtype)
   609         self.prepare_constraints(subjtype, rtype, objtype)
   610         cstrtype = self.entity.type
   610         cstrtype = self.entity.type
   727                 self.perm, erschema.type, self.expr)
   727                 self.perm, erschema.type, self.expr)
   728             return
   728             return
   729         erschema.set_rqlexprs(self.perm, rqlexprs)
   729         erschema.set_rqlexprs(self.perm, rqlexprs)
   730 
   730 
   731 
   731 
   732 # deletion hooks ###############################################################
   732 class SyncSchemaHook(hook.Hook):
   733 
   733     __abstract__ = True
   734 class DelCWETypeHook(hook.Hook):
   734     category = 'syncschema'
       
   735 
       
   736 # CWEType hooks ################################################################
       
   737 
       
   738 class DelCWETypeHook(SyncSchemaHook):
   735     """before deleting a CWEType entity:
   739     """before deleting a CWEType entity:
   736     * check that we don't remove a core entity type
   740     * check that we don't remove a core entity type
   737     * cascade to delete related CWAttribute and CWRelation entities
   741     * cascade to delete related CWAttribute and CWRelation entities
   738     * instantiate an operation to delete the entity type on commit
   742     * instantiate an operation to delete the entity type on commit
   739     """
   743     """
   740     __id__ = 'syncdelcwetype'
   744     __id__ = 'syncdelcwetype'
   741     __select__ = hook.Hook.__select__ & entity_implements('CWEType')
   745     __select__ = SyncSchemaHook.__select__ & entity_implements('CWEType')
   742     category = 'syncschema'
       
   743     events = ('before_delete_entity',)
   746     events = ('before_delete_entity',)
   744 
   747 
   745     def __call__(self):
   748     def __call__(self):
   746         # final entities can't be deleted, don't care about that
   749         # final entities can't be deleted, don't care about that
   747         name = self.entity.name
   750         name = self.entity.name
   829             if newname.lower() != oldname.lower():
   832             if newname.lower() != oldname.lower():
   830                 SourceDbCWETypeRename(self.cw_req, oldname=oldname, newname=newname)
   833                 SourceDbCWETypeRename(self.cw_req, oldname=oldname, newname=newname)
   831                 MemSchemaCWETypeRename(self.cw_req, oldname=oldname, newname=newname)
   834                 MemSchemaCWETypeRename(self.cw_req, oldname=oldname, newname=newname)
   832             entity['name'] = newname
   835             entity['name'] = newname
   833 
   836 
   834 class DelCWRTypeHook(hook.Hook):
   837 
       
   838 # CWRType hooks ################################################################
       
   839 
       
   840 class DelCWRTypeHook(SyncSchemaHook):
   835     """before deleting a CWRType entity:
   841     """before deleting a CWRType entity:
   836     * check that we don't remove a core relation type
   842     * check that we don't remove a core relation type
   837     * cascade to delete related CWAttribute and CWRelation entities
   843     * cascade to delete related CWAttribute and CWRelation entities
   838     * instantiate an operation to delete the relation type on commit
   844     * instantiate an operation to delete the relation type on commit
   839     """
   845     """
   840     __id__ = 'syncdelcwrtype'
   846     __id__ = 'syncdelcwrtype'
   841     __select__ = hook.Hook.__select__ & entity_implements('CWRType')
   847     __select__ = SyncSchemaHook.__select__ & entity_implements('CWRType')
   842     category = 'syncschema'
       
   843     events = ('before_delete_entity',)
   848     events = ('before_delete_entity',)
       
   849 
   844     def __call__(self):
   850     def __call__(self):
   845         name = self.entity.name
   851         name = self.entity.name
   846         if name in CORE_ETYPES:
   852         if name in CORE_ETYPES:
   847             raise ValidationError(self.entity.eid, {None: self.cw_req._('can\'t be deleted')})
   853             raise ValidationError(self.entity.eid, {None: self.cw_req._('can\'t be deleted')})
   848         # delete relation definitions using this relation type
   854         # delete relation definitions using this relation type
   898             MemSchemaCWRTypeUpdate(self.cw_req, rschema=rschema, values=newvalues)
   904             MemSchemaCWRTypeUpdate(self.cw_req, rschema=rschema, values=newvalues)
   899             SourceDbCWRTypeUpdate(self.cw_req, rschema=rschema, values=newvalues,
   905             SourceDbCWRTypeUpdate(self.cw_req, rschema=rschema, values=newvalues,
   900                                   entity=entity)
   906                                   entity=entity)
   901 
   907 
   902 
   908 
   903 
   909 # relation_type hooks ##########################################################
   904 class AfterDelRelationTypeHook(hook.Hook):
   910 
       
   911 class AfterDelRelationTypeHook(SyncSchemaHook):
   905     """before deleting a CWAttribute or CWRelation entity:
   912     """before deleting a CWAttribute or CWRelation entity:
   906     * if this is a final or inlined relation definition, instantiate an
   913     * if this is a final or inlined relation definition, instantiate an
   907       operation to drop necessary column, else if this is the last instance
   914       operation to drop necessary column, else if this is the last instance
   908       of a non final relation, instantiate an operation to drop necessary
   915       of a non final relation, instantiate an operation to drop necessary
   909       table
   916       table
   910     * instantiate an operation to delete the relation definition on commit
   917     * instantiate an operation to delete the relation definition on commit
   911     * delete the associated relation type when necessary
   918     * delete the associated relation type when necessary
   912     """
   919     """
   913     __id__ = 'syncdelrelationtype'
   920     __id__ = 'syncdelrelationtype'
   914     __select__ = hook.Hook.__select__ & hook.match_rtype('relation_type')
   921     __select__ = SyncSchemaHook.__select__ & hook.match_rtype('relation_type')
   915     category = 'syncschema'
       
   916     events = ('after_delete_relation',)
   922     events = ('after_delete_relation',)
   917 
   923 
   918     def __call__(self):
   924     def __call__(self):
   919         session = self.cw_req
   925         session = self.cw_req
   920         subjschema, rschema, objschema = session.schema.schema_by_eid(self.eidfrom)
   926         subjschema, rschema, objschema = session.schema.schema_by_eid(self.eidfrom)
   952         if lastrel and not rteid in pendings:
   958         if lastrel and not rteid in pendings:
   953             execute('DELETE CWRType X WHERE X eid %(x)s', {'x': rteid}, 'x')
   959             execute('DELETE CWRType X WHERE X eid %(x)s', {'x': rteid}, 'x')
   954         MemSchemaRDefDel(session, (subjschema, rschema, objschema))
   960         MemSchemaRDefDel(session, (subjschema, rschema, objschema))
   955 
   961 
   956 
   962 
   957 class AfterAddCWAttributeHook(hook.Hook):
   963 # CWAttribute / CWRelation hooks ###############################################
       
   964 
       
   965 class AfterAddCWAttributeHook(SyncSchemaHook):
   958     __id__ = 'syncaddcwattribute'
   966     __id__ = 'syncaddcwattribute'
   959     __select__ = hook.Hook.__select__ & entity_implements('CWAttribute')
   967     __select__ = SyncSchemaHook.__select__ & entity_implements('CWAttribute')
   960     category = 'syncschema'
       
   961     events = ('after_add_entity',)
   968     events = ('after_add_entity',)
   962 
   969 
   963     def __call__(self):
   970     def __call__(self):
   964         SourceDbCWAttributeAdd(self.cw_req, entity=self.entity)
   971         SourceDbCWAttributeAdd(self.cw_req, entity=self.entity)
   965 
   972 
   966 
   973 
   967 class AfterAddCWRelationHook(AfterAddCWAttributeHook):
   974 class AfterAddCWRelationHook(AfterAddCWAttributeHook):
   968     __id__ = 'syncaddcwrelation'
   975     __id__ = 'syncaddcwrelation'
   969     __select__ = hook.Hook.__select__ & entity_implements('CWRelation')
   976     __select__ = SyncSchemaHook.__select__ & entity_implements('CWRelation')
   970 
   977 
   971     def __call__(self):
   978     def __call__(self):
   972         SourceDbCWRelationAdd(self.cw_req, entity=self.entity)
   979         SourceDbCWRelationAdd(self.cw_req, entity=self.entity)
   973 
   980 
   974 
   981 
   975 class AfterUpdateCWRDefHook(hook.Hook):
   982 class AfterUpdateCWRDefHook(SyncSchemaHook):
   976     __id__ = 'syncaddcwattribute'
   983     __id__ = 'syncaddcwattribute'
   977     __select__ = hook.Hook.__select__ & entity_implements('CWAttribute', 'CWRelation')
   984     __select__ = SyncSchemaHook.__select__ & entity_implements('CWAttribute',
   978     category = 'syncschema'
   985                                                                'CWRelation')
   979     events = ('after_update_entity',)
   986     events = ('after_update_entity',)
   980 
   987 
   981     def __call__(self):
   988     def __call__(self):
   982         entity = self.entity
   989         entity = self.entity
   983         if entity.eid in self.cw_req.transaction_data.get('pendingeids', ()):
   990         if self.cw_req.deleted_in_transaction(entity.eid):
   984             return
   991             return
   985         desttype = entity.otype.name
   992         desttype = entity.otype.name
   986         rschema = self.cw_req.schema[entity.rtype.name]
   993         rschema = self.cw_req.schema[entity.rtype.name]
   987         newvalues = {}
   994         newvalues = {}
   988         for prop in rschema.rproperty_defs(desttype):
   995         for prop in rschema.rproperty_defs(desttype):
  1000                                rschema=rschema, values=newvalues)
  1007                                rschema=rschema, values=newvalues)
  1001 
  1008 
  1002 
  1009 
  1003 # constraints synchronization hooks ############################################
  1010 # constraints synchronization hooks ############################################
  1004 
  1011 
  1005 class AfterAddCWConstraintHook(hook.Hook):
  1012 class AfterAddCWConstraintHook(SyncSchemaHook):
  1006     __id__ = 'syncaddcwconstraint'
  1013     __id__ = 'syncaddcwconstraint'
  1007     __select__ = hook.Hook.__select__ & entity_implements('CWConstraint')
  1014     __select__ = SyncSchemaHook.__select__ & entity_implements('CWConstraint')
  1008     category = 'syncschema'
       
  1009     events = ('after_add_entity', 'after_update_entity')
  1015     events = ('after_add_entity', 'after_update_entity')
  1010 
  1016 
  1011     def __call__(self):
  1017     def __call__(self):
  1012         MemSchemaCWConstraintAdd(self.cw_req, entity=self.entity)
  1018         MemSchemaCWConstraintAdd(self.cw_req, entity=self.entity)
  1013         SourceDbCWConstraintAdd(self.cw_req, entity=self.entity)
  1019         SourceDbCWConstraintAdd(self.cw_req, entity=self.entity)
  1014 
  1020 
  1015 
  1021 
  1016 class AfterAddConstrainedByHook(hook.Hook):
  1022 class AfterAddConstrainedByHook(SyncSchemaHook):
  1017     __id__ = 'syncdelconstrainedby'
  1023     __id__ = 'syncdelconstrainedby'
  1018     __select__ = hook.Hook.__select__ & hook.match_rtype('constrainted_by')
  1024     __select__ = SyncSchemaHook.__select__ & hook.match_rtype('constrainted_by')
  1019     category = 'syncschema'
       
  1020     events = ('after_add_relation',)
  1025     events = ('after_add_relation',)
  1021 
  1026 
  1022     def __call__(self):
  1027     def __call__(self):
  1023         if self.eidfrom in self.cw_req.transaction_data.get('neweids', ()):
  1028         if self.cw_req.added_in_transaction(self.eidfrom):
  1024             self.cw_req.transaction_data.setdefault(self.eidfrom, []).append(self.eidto)
  1029             self.cw_req.transaction_data.setdefault(self.eidfrom, []).append(self.eidto)
  1025 
  1030 
  1026 
  1031 
  1027 class BeforeDeleteConstrainedByHook(AfterAddConstrainedByHook):
  1032 class BeforeDeleteConstrainedByHook(AfterAddConstrainedByHook):
  1028     __id__ = 'syncdelconstrainedby'
  1033     __id__ = 'syncdelconstrainedby'
  1029     events = ('before_delete_relation',)
  1034     events = ('before_delete_relation',)
  1030 
  1035 
  1031     def __call__(self):
  1036     def __call__(self):
  1032         if self.eidfrom in self.cw_req.transaction_data.get('pendingeids', ()):
  1037         if self.cw_req.deleted_in_transaction(self.eidfrom):
  1033             return
  1038             return
  1034         schema = self.cw_req.schema
  1039         schema = self.cw_req.schema
  1035         entity = self.cw_req.entity_from_eid(self.eidto)
  1040         entity = self.cw_req.entity_from_eid(self.eidto)
  1036         subjtype, rtype, objtype = schema.schema_by_eid(self.eidfrom)
  1041         subjtype, rtype, objtype = schema.schema_by_eid(self.eidfrom)
  1037         try:
  1042         try:
  1047 
  1052 
  1048 
  1053 
  1049 # permissions synchronization hooks ############################################
  1054 # permissions synchronization hooks ############################################
  1050 
  1055 
  1051 
  1056 
  1052 class AfterAddPermissionHook(hook.Hook):
  1057 class AfterAddPermissionHook(SyncSchemaHook):
  1053     """added entity/relation *_permission, need to update schema"""
  1058     """added entity/relation *_permission, need to update schema"""
  1054     __id__ = 'syncaddperm'
  1059     __id__ = 'syncaddperm'
  1055     __select__ = hook.Hook.__select__ & hook.match_rtype(
  1060     __select__ = SyncSchemaHook.__select__ & hook.match_rtype(
  1056         'read_permission', 'add_permission', 'delete_permission',
  1061         'read_permission', 'add_permission', 'delete_permission',
  1057         'update_permission')
  1062         'update_permission')
  1058     category = 'syncschema'
       
  1059     events = ('after_add_relation',)
  1063     events = ('after_add_relation',)
  1060 
  1064 
  1061     def __call__(self):
  1065     def __call__(self):
  1062         perm = self.rtype.split('_', 1)[0]
  1066         perm = self.rtype.split('_', 1)[0]
  1063         if self.cw_req.describe(self.eidto)[0] == 'CWGroup':
  1067         if self.cw_req.describe(self.eidto)[0] == 'CWGroup':
  1074     """
  1078     """
  1075     __id__ = 'syncdelperm'
  1079     __id__ = 'syncdelperm'
  1076     events = ('before_delete_relation',)
  1080     events = ('before_delete_relation',)
  1077 
  1081 
  1078     def __call__(self):
  1082     def __call__(self):
  1079         if self.eidfrom in self.cw_req.transaction_data.get('pendingeids', ()):
  1083         if self.cw_req.deleted_in_transaction(self.eidfrom):
  1080             return
  1084             return
  1081         perm = self.rtype.split('_', 1)[0]
  1085         perm = self.rtype.split('_', 1)[0]
  1082         if self.cw_req.describe(self.eidto)[0] == 'CWGroup':
  1086         if self.cw_req.describe(self.eidto)[0] == 'CWGroup':
  1083             MemSchemaPermCWGroupDel(self.cw_req, perm, self.eidfrom, self.eidto)
  1087             MemSchemaPermCWGroupDel(self.cw_req, perm, self.eidfrom, self.eidto)
  1084         else: # RQLExpression
  1088         else: # RQLExpression
  1085             expr = self.cw_req.entity_from_eid(self.eidto).expression
  1089             expr = self.cw_req.entity_from_eid(self.eidto).expression
  1086             MemSchemaPermRQLExpressionDel(self.cw_req, perm, self.eidfrom, expr)
  1090             MemSchemaPermRQLExpressionDel(self.cw_req, perm, self.eidfrom, expr)
  1087 
  1091 
  1088 
  1092 
  1089 
  1093 
  1090 class ModifySpecializesHook(hook.Hook):
  1094 class ModifySpecializesHook(SyncSchemaHook):
  1091     __id__ = 'syncspecializes'
  1095     __id__ = 'syncspecializes'
  1092     __select__ = hook.Hook.__select__ & hook.match_rtype('specializes')
  1096     __select__ = SyncSchemaHook.__select__ & hook.match_rtype('specializes')
  1093     category = 'syncschema'
       
  1094     events = ('after_add_relation', 'after_delete_relation')
  1097     events = ('after_add_relation', 'after_delete_relation')
  1095 
  1098 
  1096     def __call__(self):
  1099     def __call__(self):
  1097         # registering a schema operation will trigger a call to
  1100         # registering a schema operation will trigger a call to
  1098         # repo.set_schema() on commit which will in turn rebuild
  1101         # repo.set_schema() on commit which will in turn rebuild