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 |