server/repository.py
changeset 6225 a176e68b7d0d
parent 6142 8bc6eac1fac1
parent 6211 e9d125fd1465
child 6279 42079f752a9c
equal deleted inserted replaced
6182:30de0be8f895 6225:a176e68b7d0d
    48 
    48 
    49 from cubicweb import (CW_SOFTWARE_ROOT, CW_MIGRATION_MAP, QueryError,
    49 from cubicweb import (CW_SOFTWARE_ROOT, CW_MIGRATION_MAP, QueryError,
    50                       UnknownEid, AuthenticationError, ExecutionError,
    50                       UnknownEid, AuthenticationError, ExecutionError,
    51                       ETypeNotSupportedBySources, MultiSourcesError,
    51                       ETypeNotSupportedBySources, MultiSourcesError,
    52                       BadConnectionId, Unauthorized, ValidationError,
    52                       BadConnectionId, Unauthorized, ValidationError,
    53                       RepositoryError, typed_eid, onevent)
    53                       RepositoryError, UniqueTogetherError, typed_eid, onevent)
    54 from cubicweb import cwvreg, schema, server
    54 from cubicweb import cwvreg, schema, server
    55 from cubicweb.server import utils, hook, pool, querier, sources
    55 from cubicweb.server import utils, hook, pool, querier, sources
    56 from cubicweb.server.session import Session, InternalSession, InternalManager, \
    56 from cubicweb.server.session import Session, InternalSession, InternalManager, \
    57      security_enabled
    57      security_enabled
    58 from cubicweb.server.ssplanner import EditedEntity
    58 from cubicweb.server.ssplanner import EditedEntity
    59 
       
    60 
    59 
    61 def del_existing_rel_if_needed(session, eidfrom, rtype, eidto):
    60 def del_existing_rel_if_needed(session, eidfrom, rtype, eidto):
    62     """delete existing relation when adding a new one if card is 1 or ?
    61     """delete existing relation when adding a new one if card is 1 or ?
    63 
    62 
    64     have to be done once the new relation has been inserted to avoid having
    63     have to be done once the new relation has been inserted to avoid having
    80     # same transaction where the entity is being created. This never occurs from
    79     # same transaction where the entity is being created. This never occurs from
    81     # the web interface but may occurs during test or dbapi connection (though
    80     # the web interface but may occurs during test or dbapi connection (though
    82     # not expected for this).  So: don't do it, we pretend to ensure repository
    81     # not expected for this).  So: don't do it, we pretend to ensure repository
    83     # consistency.
    82     # consistency.
    84     #
    83     #
    85     # XXX we don't want read permissions to be applied but we want delete
    84     # notes:
    86     # permission to be checked
    85     # * inlined relations will be implicitly deleted for the subject entity
    87     rschema = session.repo.schema.rschema(rtype)
    86     # * we don't want read permissions to be applied but we want delete
    88     if card[0] in '1?':
    87     #   permission to be checked
    89         if not rschema.inlined: # inlined relations will be implicitly deleted
    88     if card[0] in '1?' and not session.repo.schema.rschema(rtype).inlined:
    90             with security_enabled(session, read=False):
    89         with security_enabled(session, read=False):
    91                 session.execute('DELETE X %s Y WHERE X eid %%(x)s, '
    90             session.execute('DELETE X %s Y WHERE X eid %%(x)s, '
    92                                 'NOT Y eid %%(y)s' % rtype,
    91                             'NOT Y eid %%(y)s' % rtype,
    93                                 {'x': eidfrom, 'y': eidto})
    92                                 {'x': eidfrom, 'y': eidto})
    94     if card[1] in '1?':
    93     if card[1] in '1?':
    95         with security_enabled(session, read=False):
    94         with security_enabled(session, read=False):
    96             session.execute('DELETE X %s Y WHERE Y eid %%(y)s, '
    95             session.execute('DELETE X %s Y WHERE Y eid %%(y)s, '
    97                             'NOT X eid %%(x)s' % rtype,
    96                             'NOT X eid %%(x)s' % rtype,
  1068             if not rschema.final: # inlined relation
  1067             if not rschema.final: # inlined relation
  1069                 relations.append((attr, edited[attr]))
  1068                 relations.append((attr, edited[attr]))
  1070         edited.set_defaults()
  1069         edited.set_defaults()
  1071         if session.is_hook_category_activated('integrity'):
  1070         if session.is_hook_category_activated('integrity'):
  1072             edited.check(creation=True)
  1071             edited.check(creation=True)
  1073         source.add_entity(session, entity)
  1072         try:
       
  1073             source.add_entity(session, entity)
       
  1074         except UniqueTogetherError, exc:
       
  1075             etype, rtypes = exc.args
       
  1076             problems = {}
       
  1077             for col in rtypes:
       
  1078                 problems[col] = session._('violates unique_together constraints (%s)') % (','.join(rtypes))
       
  1079             raise ValidationError(entity.eid, problems)
       
  1080         self.add_info(session, entity, source, extid, complete=False)
  1074         edited.saved = True
  1081         edited.saved = True
  1075         self.add_info(session, entity, source, extid, complete=False)
       
  1076         entity._cw_is_saved = True # entity has an eid and is saved
       
  1077         # prefill entity relation caches
  1082         # prefill entity relation caches
  1078         for rschema in eschema.subject_relations():
  1083         for rschema in eschema.subject_relations():
  1079             rtype = str(rschema)
  1084             rtype = str(rschema)
  1080             if rtype in schema.VIRTUAL_RTYPES:
  1085             if rtype in schema.VIRTUAL_RTYPES:
  1081                 continue
  1086                 continue
  1087         for rschema in eschema.object_relations():
  1092         for rschema in eschema.object_relations():
  1088             rtype = str(rschema)
  1093             rtype = str(rschema)
  1089             if rtype in schema.VIRTUAL_RTYPES:
  1094             if rtype in schema.VIRTUAL_RTYPES:
  1090                 continue
  1095                 continue
  1091             entity.cw_set_relation_cache(rtype, 'object', session.empty_rset())
  1096             entity.cw_set_relation_cache(rtype, 'object', session.empty_rset())
  1092         # set inline relation cache before call to after_add_entity
  1097         # set inlined relation cache before call to after_add_entity
  1093         for attr, value in relations:
  1098         for attr, value in relations:
  1094             session.update_rel_cache_add(entity.eid, attr, value)
  1099             session.update_rel_cache_add(entity.eid, attr, value)
       
  1100             del_existing_rel_if_needed(session, entity.eid, attr, value)
  1095         # trigger after_add_entity after after_add_relation
  1101         # trigger after_add_entity after after_add_relation
  1096         if source.should_call_hooks:
  1102         if source.should_call_hooks:
  1097             self.hm.call_hooks('after_add_entity', session, entity=entity)
  1103             self.hm.call_hooks('after_add_entity', session, entity=entity)
  1098             # call hooks for inlined relations
  1104             # call hooks for inlined relations
  1099             for attr, value in relations:
  1105             for attr, value in relations:
  1140                                           eidfrom=entity.eid, rtype=attr,
  1146                                           eidfrom=entity.eid, rtype=attr,
  1141                                           eidto=previous_value)
  1147                                           eidto=previous_value)
  1142                     relations.append((attr, edited[attr], previous_value))
  1148                     relations.append((attr, edited[attr], previous_value))
  1143             if source.should_call_hooks:
  1149             if source.should_call_hooks:
  1144                 # call hooks for inlined relations
  1150                 # call hooks for inlined relations
  1145                 for attr, value, _ in relations:
  1151                 for attr, value, _t in relations:
  1146                     hm.call_hooks('before_add_relation', session,
  1152                     hm.call_hooks('before_add_relation', session,
  1147                                   eidfrom=entity.eid, rtype=attr, eidto=value)
  1153                                   eidfrom=entity.eid, rtype=attr, eidto=value)
  1148                 if not only_inline_rels:
  1154                 if not only_inline_rels:
  1149                     hm.call_hooks('before_update_entity', session, entity=entity)
  1155                     hm.call_hooks('before_update_entity', session, entity=entity)
  1150             if session.is_hook_category_activated('integrity'):
  1156             if session.is_hook_category_activated('integrity'):
  1151                 edited.check()
  1157                 edited.check()
  1152             source.update_entity(session, entity)
  1158             try:
  1153             edited.saved = True
  1159                 source.update_entity(session, entity)
       
  1160                 edited.saved = True
       
  1161             except UniqueTogetherError, exc:
       
  1162                 etype, rtypes = exc.args
       
  1163                 problems = {}
       
  1164                 for col in rtypes:
       
  1165                     problems[col] = session._('violates unique_together constraints (%s)') % (','.join(rtypes))
       
  1166                 raise ValidationError(entity.eid, problems)
  1154             self.system_source.update_info(session, entity, need_fti_update)
  1167             self.system_source.update_info(session, entity, need_fti_update)
  1155             if source.should_call_hooks:
  1168             if source.should_call_hooks:
  1156                 if not only_inline_rels:
  1169                 if not only_inline_rels:
  1157                     hm.call_hooks('after_update_entity', session, entity=entity)
  1170                     hm.call_hooks('after_update_entity', session, entity=entity)
  1158                 for attr, value, prevvalue in relations:
  1171                 for attr, value, prevvalue in relations: