hooks/syncschema.py
changeset 2847 c2ee28f4d4b1
parent 2841 107ba1c45227
child 2882 d7f0646c65f7
equal deleted inserted replaced
2846:e71d6a585b83 2847:c2ee28f4d4b1
   747 
   747 
   748     def __call__(self):
   748     def __call__(self):
   749         # final entities can't be deleted, don't care about that
   749         # final entities can't be deleted, don't care about that
   750         name = self.entity.name
   750         name = self.entity.name
   751         if name in CORE_ETYPES:
   751         if name in CORE_ETYPES:
   752             raise ValidationError(self.entity.eid, {None: self.cw_req._('can\'t be deleted')})
   752             raise ValidationError(self.entity.eid, {None: self._cw._('can\'t be deleted')})
   753         # delete every entities of this type
   753         # delete every entities of this type
   754         self.cw_req.unsafe_execute('DELETE %s X' % name)
   754         self._cw.unsafe_execute('DELETE %s X' % name)
   755         DropTable(self.cw_req, table=SQL_PREFIX + name)
   755         DropTable(self._cw, table=SQL_PREFIX + name)
   756         MemSchemaCWETypeDel(self.cw_req, name)
   756         MemSchemaCWETypeDel(self._cw, name)
   757 
   757 
   758 
   758 
   759 class AfterDelCWETypeHook(DelCWETypeHook):
   759 class AfterDelCWETypeHook(DelCWETypeHook):
   760     __id__ = 'wfcleanup'
   760     __id__ = 'wfcleanup'
   761     events = ('after_delete_entity',)
   761     events = ('after_delete_entity',)
   762 
   762 
   763     def __call__(self):
   763     def __call__(self):
   764         # workflow cleanup
   764         # workflow cleanup
   765         self.cw_req.execute('DELETE State X WHERE NOT X state_of Y')
   765         self._cw.execute('DELETE State X WHERE NOT X state_of Y')
   766         self.cw_req.execute('DELETE Transition X WHERE NOT X transition_of Y')
   766         self._cw.execute('DELETE Transition X WHERE NOT X transition_of Y')
   767 
   767 
   768 
   768 
   769 class AfterAddCWETypeHook(DelCWETypeHook):
   769 class AfterAddCWETypeHook(DelCWETypeHook):
   770     """after adding a CWEType entity:
   770     """after adding a CWEType entity:
   771     * create the necessary table
   771     * create the necessary table
   780 
   780 
   781     def __call__(self):
   781     def __call__(self):
   782         entity = self.entity
   782         entity = self.entity
   783         if entity.get('final'):
   783         if entity.get('final'):
   784             return
   784             return
   785         schema = self.cw_req.schema
   785         schema = self._cw.schema
   786         name = entity['name']
   786         name = entity['name']
   787         etype = EntityType(name=name, description=entity.get('description'),
   787         etype = EntityType(name=name, description=entity.get('description'),
   788                            meta=entity.get('meta')) # don't care about final
   788                            meta=entity.get('meta')) # don't care about final
   789         # fake we add it to the schema now to get a correctly initialized schema
   789         # fake we add it to the schema now to get a correctly initialized schema
   790         # but remove it before doing anything more dangerous...
   790         # but remove it before doing anything more dangerous...
   791         schema = self.cw_req.schema
   791         schema = self._cw.schema
   792         eschema = schema.add_entity_type(etype)
   792         eschema = schema.add_entity_type(etype)
   793         eschema.set_default_groups()
   793         eschema.set_default_groups()
   794         # generate table sql and rql to add metadata
   794         # generate table sql and rql to add metadata
   795         tablesql = eschema2sql(self.cw_req.pool.source('system').dbhelper, eschema,
   795         tablesql = eschema2sql(self._cw.pool.source('system').dbhelper, eschema,
   796                                prefix=SQL_PREFIX)
   796                                prefix=SQL_PREFIX)
   797         relrqls = []
   797         relrqls = []
   798         for rtype in (META_RTYPES - VIRTUAL_RTYPES):
   798         for rtype in (META_RTYPES - VIRTUAL_RTYPES):
   799             rschema = schema[rtype]
   799             rschema = schema[rtype]
   800             sampletype = rschema.subjects()[0]
   800             sampletype = rschema.subjects()[0]
   804         # now remove it !
   804         # now remove it !
   805         schema.del_entity_type(name)
   805         schema.del_entity_type(name)
   806         # create the necessary table
   806         # create the necessary table
   807         for sql in tablesql.split(';'):
   807         for sql in tablesql.split(';'):
   808             if sql.strip():
   808             if sql.strip():
   809                 self.cw_req.system_sql(sql)
   809                 self._cw.system_sql(sql)
   810         # register operation to modify the schema on commit
   810         # register operation to modify the schema on commit
   811         # this have to be done before adding other relations definitions
   811         # this have to be done before adding other relations definitions
   812         # or permission settings
   812         # or permission settings
   813         etype.eid = entity.eid
   813         etype.eid = entity.eid
   814         MemSchemaCWETypeAdd(self.cw_req, etype)
   814         MemSchemaCWETypeAdd(self._cw, etype)
   815         # add meta relations
   815         # add meta relations
   816         for rql, kwargs in relrqls:
   816         for rql, kwargs in relrqls:
   817             self.cw_req.execute(rql, kwargs)
   817             self._cw.execute(rql, kwargs)
   818 
   818 
   819 
   819 
   820 class BeforeUpdateCWETypeHook(DelCWETypeHook):
   820 class BeforeUpdateCWETypeHook(DelCWETypeHook):
   821     """check name change, handle final"""
   821     """check name change, handle final"""
   822     __id__ = 'syncupdatecwetype'
   822     __id__ = 'syncupdatecwetype'
   823     events = ('before_update_entity',)
   823     events = ('before_update_entity',)
   824 
   824 
   825     def __call__(self):
   825     def __call__(self):
   826         entity = self.entity
   826         entity = self.entity
   827         check_valid_changes(self.cw_req, entity, ro_attrs=('final',))
   827         check_valid_changes(self._cw, entity, ro_attrs=('final',))
   828         # don't use getattr(entity, attr), we would get the modified value if any
   828         # don't use getattr(entity, attr), we would get the modified value if any
   829         if 'name' in entity.edited_attributes:
   829         if 'name' in entity.edited_attributes:
   830             newname = entity.pop('name')
   830             newname = entity.pop('name')
   831             oldname = entity.name
   831             oldname = entity.name
   832             if newname.lower() != oldname.lower():
   832             if newname.lower() != oldname.lower():
   833                 SourceDbCWETypeRename(self.cw_req, oldname=oldname, newname=newname)
   833                 SourceDbCWETypeRename(self._cw, oldname=oldname, newname=newname)
   834                 MemSchemaCWETypeRename(self.cw_req, oldname=oldname, newname=newname)
   834                 MemSchemaCWETypeRename(self._cw, oldname=oldname, newname=newname)
   835             entity['name'] = newname
   835             entity['name'] = newname
   836 
   836 
   837 
   837 
   838 # CWRType hooks ################################################################
   838 # CWRType hooks ################################################################
   839 
   839 
   848     events = ('before_delete_entity',)
   848     events = ('before_delete_entity',)
   849 
   849 
   850     def __call__(self):
   850     def __call__(self):
   851         name = self.entity.name
   851         name = self.entity.name
   852         if name in CORE_ETYPES:
   852         if name in CORE_ETYPES:
   853             raise ValidationError(self.entity.eid, {None: self.cw_req._('can\'t be deleted')})
   853             raise ValidationError(self.entity.eid, {None: self._cw._('can\'t be deleted')})
   854         # delete relation definitions using this relation type
   854         # delete relation definitions using this relation type
   855         self.cw_req.execute('DELETE CWAttribute X WHERE X relation_type Y, Y eid %(x)s',
   855         self._cw.execute('DELETE CWAttribute X WHERE X relation_type Y, Y eid %(x)s',
   856                         {'x': self.entity.eid})
   856                         {'x': self.entity.eid})
   857         self.cw_req.execute('DELETE CWRelation X WHERE X relation_type Y, Y eid %(x)s',
   857         self._cw.execute('DELETE CWRelation X WHERE X relation_type Y, Y eid %(x)s',
   858                         {'x': self.entity.eid})
   858                         {'x': self.entity.eid})
   859         MemSchemaCWRTypeDel(self.cw_req, name)
   859         MemSchemaCWRTypeDel(self._cw, name)
   860 
   860 
   861 
   861 
   862 class AfterAddCWRTypeHook(DelCWRTypeHook):
   862 class AfterAddCWRTypeHook(DelCWRTypeHook):
   863     """after a CWRType entity has been added:
   863     """after a CWRType entity has been added:
   864     * register an operation to add the relation type to the instance's
   864     * register an operation to add the relation type to the instance's
   875                              description=entity.get('description'),
   875                              description=entity.get('description'),
   876                              meta=entity.get('meta', False),
   876                              meta=entity.get('meta', False),
   877                              inlined=entity.get('inlined', False),
   877                              inlined=entity.get('inlined', False),
   878                              symetric=entity.get('symetric', False),
   878                              symetric=entity.get('symetric', False),
   879                              eid=entity.eid)
   879                              eid=entity.eid)
   880         MemSchemaCWRTypeAdd(self.cw_req, rtype)
   880         MemSchemaCWRTypeAdd(self._cw, rtype)
   881 
   881 
   882 
   882 
   883 class BeforeUpdateCWRTypeHook(DelCWRTypeHook):
   883 class BeforeUpdateCWRTypeHook(DelCWRTypeHook):
   884     """check name change, handle final"""
   884     """check name change, handle final"""
   885     __id__ = 'checkupdatecwrtype'
   885     __id__ = 'checkupdatecwrtype'
   886     events = ('before_update_entity',)
   886     events = ('before_update_entity',)
   887 
   887 
   888     def __call__(self):
   888     def __call__(self):
   889         check_valid_changes(self.cw_req, self.entity)
   889         check_valid_changes(self._cw, self.entity)
   890 
   890 
   891 
   891 
   892 class AfterUpdateCWRTypeHook(DelCWRTypeHook):
   892 class AfterUpdateCWRTypeHook(DelCWRTypeHook):
   893     __id__ = 'syncupdatecwrtype'
   893     __id__ = 'syncupdatecwrtype'
   894     events = ('after_update_entity',)
   894     events = ('after_update_entity',)
   895 
   895 
   896     def __call__(self):
   896     def __call__(self):
   897         entity = self.entity
   897         entity = self.entity
   898         rschema = self.cw_req.schema.rschema(entity.name)
   898         rschema = self._cw.schema.rschema(entity.name)
   899         newvalues = {}
   899         newvalues = {}
   900         for prop in ('meta', 'symetric', 'inlined'):
   900         for prop in ('meta', 'symetric', 'inlined'):
   901             if prop in entity:
   901             if prop in entity:
   902                 newvalues[prop] = entity[prop]
   902                 newvalues[prop] = entity[prop]
   903         if newvalues:
   903         if newvalues:
   904             MemSchemaCWRTypeUpdate(self.cw_req, rschema=rschema, values=newvalues)
   904             MemSchemaCWRTypeUpdate(self._cw, rschema=rschema, values=newvalues)
   905             SourceDbCWRTypeUpdate(self.cw_req, rschema=rschema, values=newvalues,
   905             SourceDbCWRTypeUpdate(self._cw, rschema=rschema, values=newvalues,
   906                                   entity=entity)
   906                                   entity=entity)
   907 
   907 
   908 
   908 
   909 # relation_type hooks ##########################################################
   909 # relation_type hooks ##########################################################
   910 
   910 
   920     __id__ = 'syncdelrelationtype'
   920     __id__ = 'syncdelrelationtype'
   921     __select__ = SyncSchemaHook.__select__ & hook.match_rtype('relation_type')
   921     __select__ = SyncSchemaHook.__select__ & hook.match_rtype('relation_type')
   922     events = ('after_delete_relation',)
   922     events = ('after_delete_relation',)
   923 
   923 
   924     def __call__(self):
   924     def __call__(self):
   925         session = self.cw_req
   925         session = self._cw
   926         subjschema, rschema, objschema = session.schema.schema_by_eid(self.eidfrom)
   926         subjschema, rschema, objschema = session.schema.schema_by_eid(self.eidfrom)
   927         pendings = session.transaction_data.get('pendingeids', ())
   927         pendings = session.transaction_data.get('pendingeids', ())
   928         # first delete existing relation if necessary
   928         # first delete existing relation if necessary
   929         if rschema.is_final():
   929         if rschema.is_final():
   930             rdeftype = 'CWAttribute'
   930             rdeftype = 'CWAttribute'
   966     __id__ = 'syncaddcwattribute'
   966     __id__ = 'syncaddcwattribute'
   967     __select__ = SyncSchemaHook.__select__ & entity_implements('CWAttribute')
   967     __select__ = SyncSchemaHook.__select__ & entity_implements('CWAttribute')
   968     events = ('after_add_entity',)
   968     events = ('after_add_entity',)
   969 
   969 
   970     def __call__(self):
   970     def __call__(self):
   971         SourceDbCWAttributeAdd(self.cw_req, entity=self.entity)
   971         SourceDbCWAttributeAdd(self._cw, entity=self.entity)
   972 
   972 
   973 
   973 
   974 class AfterAddCWRelationHook(AfterAddCWAttributeHook):
   974 class AfterAddCWRelationHook(AfterAddCWAttributeHook):
   975     __id__ = 'syncaddcwrelation'
   975     __id__ = 'syncaddcwrelation'
   976     __select__ = SyncSchemaHook.__select__ & entity_implements('CWRelation')
   976     __select__ = SyncSchemaHook.__select__ & entity_implements('CWRelation')
   977 
   977 
   978     def __call__(self):
   978     def __call__(self):
   979         SourceDbCWRelationAdd(self.cw_req, entity=self.entity)
   979         SourceDbCWRelationAdd(self._cw, entity=self.entity)
   980 
   980 
   981 
   981 
   982 class AfterUpdateCWRDefHook(SyncSchemaHook):
   982 class AfterUpdateCWRDefHook(SyncSchemaHook):
   983     __id__ = 'syncaddcwattribute'
   983     __id__ = 'syncaddcwattribute'
   984     __select__ = SyncSchemaHook.__select__ & entity_implements('CWAttribute',
   984     __select__ = SyncSchemaHook.__select__ & entity_implements('CWAttribute',
   985                                                                'CWRelation')
   985                                                                'CWRelation')
   986     events = ('after_update_entity',)
   986     events = ('after_update_entity',)
   987 
   987 
   988     def __call__(self):
   988     def __call__(self):
   989         entity = self.entity
   989         entity = self.entity
   990         if self.cw_req.deleted_in_transaction(entity.eid):
   990         if self._cw.deleted_in_transaction(entity.eid):
   991             return
   991             return
   992         desttype = entity.otype.name
   992         desttype = entity.otype.name
   993         rschema = self.cw_req.schema[entity.rtype.name]
   993         rschema = self._cw.schema[entity.rtype.name]
   994         newvalues = {}
   994         newvalues = {}
   995         for prop in rschema.rproperty_defs(desttype):
   995         for prop in rschema.rproperty_defs(desttype):
   996             if prop == 'constraints':
   996             if prop == 'constraints':
   997                 continue
   997                 continue
   998             if prop == 'order':
   998             if prop == 'order':
   999                 prop = 'ordernum'
   999                 prop = 'ordernum'
  1000             if prop in entity.edited_attributes:
  1000             if prop in entity.edited_attributes:
  1001                 newvalues[prop] = entity[prop]
  1001                 newvalues[prop] = entity[prop]
  1002         if newvalues:
  1002         if newvalues:
  1003             subjtype = entity.stype.name
  1003             subjtype = entity.stype.name
  1004             MemSchemaRDefUpdate(self.cw_req, kobj=(subjtype, desttype),
  1004             MemSchemaRDefUpdate(self._cw, kobj=(subjtype, desttype),
  1005                                 rschema=rschema, values=newvalues)
  1005                                 rschema=rschema, values=newvalues)
  1006             SourceDbRDefUpdate(self.cw_req, kobj=(subjtype, desttype),
  1006             SourceDbRDefUpdate(self._cw, kobj=(subjtype, desttype),
  1007                                rschema=rschema, values=newvalues)
  1007                                rschema=rschema, values=newvalues)
  1008 
  1008 
  1009 
  1009 
  1010 # constraints synchronization hooks ############################################
  1010 # constraints synchronization hooks ############################################
  1011 
  1011 
  1013     __id__ = 'syncaddcwconstraint'
  1013     __id__ = 'syncaddcwconstraint'
  1014     __select__ = SyncSchemaHook.__select__ & entity_implements('CWConstraint')
  1014     __select__ = SyncSchemaHook.__select__ & entity_implements('CWConstraint')
  1015     events = ('after_add_entity', 'after_update_entity')
  1015     events = ('after_add_entity', 'after_update_entity')
  1016 
  1016 
  1017     def __call__(self):
  1017     def __call__(self):
  1018         MemSchemaCWConstraintAdd(self.cw_req, entity=self.entity)
  1018         MemSchemaCWConstraintAdd(self._cw, entity=self.entity)
  1019         SourceDbCWConstraintAdd(self.cw_req, entity=self.entity)
  1019         SourceDbCWConstraintAdd(self._cw, entity=self.entity)
  1020 
  1020 
  1021 
  1021 
  1022 class AfterAddConstrainedByHook(SyncSchemaHook):
  1022 class AfterAddConstrainedByHook(SyncSchemaHook):
  1023     __id__ = 'syncdelconstrainedby'
  1023     __id__ = 'syncdelconstrainedby'
  1024     __select__ = SyncSchemaHook.__select__ & hook.match_rtype('constrainted_by')
  1024     __select__ = SyncSchemaHook.__select__ & hook.match_rtype('constrainted_by')
  1025     events = ('after_add_relation',)
  1025     events = ('after_add_relation',)
  1026 
  1026 
  1027     def __call__(self):
  1027     def __call__(self):
  1028         if self.cw_req.added_in_transaction(self.eidfrom):
  1028         if self._cw.added_in_transaction(self.eidfrom):
  1029             self.cw_req.transaction_data.setdefault(self.eidfrom, []).append(self.eidto)
  1029             self._cw.transaction_data.setdefault(self.eidfrom, []).append(self.eidto)
  1030 
  1030 
  1031 
  1031 
  1032 class BeforeDeleteConstrainedByHook(AfterAddConstrainedByHook):
  1032 class BeforeDeleteConstrainedByHook(AfterAddConstrainedByHook):
  1033     __id__ = 'syncdelconstrainedby'
  1033     __id__ = 'syncdelconstrainedby'
  1034     events = ('before_delete_relation',)
  1034     events = ('before_delete_relation',)
  1035 
  1035 
  1036     def __call__(self):
  1036     def __call__(self):
  1037         if self.cw_req.deleted_in_transaction(self.eidfrom):
  1037         if self._cw.deleted_in_transaction(self.eidfrom):
  1038             return
  1038             return
  1039         schema = self.cw_req.schema
  1039         schema = self._cw.schema
  1040         entity = self.cw_req.entity_from_eid(self.eidto)
  1040         entity = self._cw.entity_from_eid(self.eidto)
  1041         subjtype, rtype, objtype = schema.schema_by_eid(self.eidfrom)
  1041         subjtype, rtype, objtype = schema.schema_by_eid(self.eidfrom)
  1042         try:
  1042         try:
  1043             cstr = rtype.constraint_by_type(subjtype, objtype,
  1043             cstr = rtype.constraint_by_type(subjtype, objtype,
  1044                                             entity.cstrtype[0].name)
  1044                                             entity.cstrtype[0].name)
  1045         except IndexError:
  1045         except IndexError:
  1046             self.cw_req.critical('constraint type no more accessible')
  1046             self._cw.critical('constraint type no more accessible')
  1047         else:
  1047         else:
  1048             SourceDbCWConstraintDel(self.cw_req, subjtype=subjtype, rtype=rtype,
  1048             SourceDbCWConstraintDel(self._cw, subjtype=subjtype, rtype=rtype,
  1049                                     objtype=objtype, cstr=cstr)
  1049                                     objtype=objtype, cstr=cstr)
  1050             MemSchemaCWConstraintDel(self.cw_req, subjtype=subjtype, rtype=rtype,
  1050             MemSchemaCWConstraintDel(self._cw, subjtype=subjtype, rtype=rtype,
  1051                                      objtype=objtype, cstr=cstr)
  1051                                      objtype=objtype, cstr=cstr)
  1052 
  1052 
  1053 
  1053 
  1054 # permissions synchronization hooks ############################################
  1054 # permissions synchronization hooks ############################################
  1055 
  1055 
  1062         'update_permission')
  1062         'update_permission')
  1063     events = ('after_add_relation',)
  1063     events = ('after_add_relation',)
  1064 
  1064 
  1065     def __call__(self):
  1065     def __call__(self):
  1066         perm = self.rtype.split('_', 1)[0]
  1066         perm = self.rtype.split('_', 1)[0]
  1067         if self.cw_req.describe(self.eidto)[0] == 'CWGroup':
  1067         if self._cw.describe(self.eidto)[0] == 'CWGroup':
  1068             MemSchemaPermCWGroupAdd(self.cw_req, perm, self.eidfrom, self.eidto)
  1068             MemSchemaPermCWGroupAdd(self._cw, perm, self.eidfrom, self.eidto)
  1069         else: # RQLExpression
  1069         else: # RQLExpression
  1070             expr = self.cw_req.entity_from_eid(self.eidto).expression
  1070             expr = self._cw.entity_from_eid(self.eidto).expression
  1071             MemSchemaPermRQLExpressionAdd(self.cw_req, perm, self.eidfrom, expr)
  1071             MemSchemaPermRQLExpressionAdd(self._cw, perm, self.eidfrom, expr)
  1072 
  1072 
  1073 
  1073 
  1074 class BeforeDelPermissionHook(AfterAddPermissionHook):
  1074 class BeforeDelPermissionHook(AfterAddPermissionHook):
  1075     """delete entity/relation *_permission, need to update schema
  1075     """delete entity/relation *_permission, need to update schema
  1076 
  1076 
  1078     """
  1078     """
  1079     __id__ = 'syncdelperm'
  1079     __id__ = 'syncdelperm'
  1080     events = ('before_delete_relation',)
  1080     events = ('before_delete_relation',)
  1081 
  1081 
  1082     def __call__(self):
  1082     def __call__(self):
  1083         if self.cw_req.deleted_in_transaction(self.eidfrom):
  1083         if self._cw.deleted_in_transaction(self.eidfrom):
  1084             return
  1084             return
  1085         perm = self.rtype.split('_', 1)[0]
  1085         perm = self.rtype.split('_', 1)[0]
  1086         if self.cw_req.describe(self.eidto)[0] == 'CWGroup':
  1086         if self._cw.describe(self.eidto)[0] == 'CWGroup':
  1087             MemSchemaPermCWGroupDel(self.cw_req, perm, self.eidfrom, self.eidto)
  1087             MemSchemaPermCWGroupDel(self._cw, perm, self.eidfrom, self.eidto)
  1088         else: # RQLExpression
  1088         else: # RQLExpression
  1089             expr = self.cw_req.entity_from_eid(self.eidto).expression
  1089             expr = self._cw.entity_from_eid(self.eidto).expression
  1090             MemSchemaPermRQLExpressionDel(self.cw_req, perm, self.eidfrom, expr)
  1090             MemSchemaPermRQLExpressionDel(self._cw, perm, self.eidfrom, expr)
  1091 
  1091 
  1092 
  1092 
  1093 
  1093 
  1094 class ModifySpecializesHook(SyncSchemaHook):
  1094 class ModifySpecializesHook(SyncSchemaHook):
  1095     __id__ = 'syncspecializes'
  1095     __id__ = 'syncspecializes'
  1098 
  1098 
  1099     def __call__(self):
  1099     def __call__(self):
  1100         # registering a schema operation will trigger a call to
  1100         # registering a schema operation will trigger a call to
  1101         # repo.set_schema() on commit which will in turn rebuild
  1101         # repo.set_schema() on commit which will in turn rebuild
  1102         # infered relation definitions
  1102         # infered relation definitions
  1103         MemSchemaNotifyChanges(self.cw_req)
  1103         MemSchemaNotifyChanges(self._cw)