612 with self._storage_handler(entity, 'added'): |
612 with self._storage_handler(entity, 'added'): |
613 attrs = self.preprocess_entity(entity) |
613 attrs = self.preprocess_entity(entity) |
614 sql = self.sqlgen.insert(SQL_PREFIX + entity.cw_etype, attrs) |
614 sql = self.sqlgen.insert(SQL_PREFIX + entity.cw_etype, attrs) |
615 self.doexec(cnx, sql, attrs) |
615 self.doexec(cnx, sql, attrs) |
616 if cnx.ertype_supports_undo(entity.cw_etype): |
616 if cnx.ertype_supports_undo(entity.cw_etype): |
617 self._record_tx_action(cnx, 'tx_entity_actions', 'C', |
617 self._record_tx_action(cnx, 'tx_entity_actions', u'C', |
618 etype=entity.cw_etype, eid=entity.eid) |
618 etype=unicode(entity.cw_etype), eid=entity.eid) |
619 |
619 |
620 def update_entity(self, cnx, entity): |
620 def update_entity(self, cnx, entity): |
621 """replace an entity in the source""" |
621 """replace an entity in the source""" |
622 with self._storage_handler(entity, 'updated'): |
622 with self._storage_handler(entity, 'updated'): |
623 attrs = self.preprocess_entity(entity) |
623 attrs = self.preprocess_entity(entity) |
624 if cnx.ertype_supports_undo(entity.cw_etype): |
624 if cnx.ertype_supports_undo(entity.cw_etype): |
625 changes = self._save_attrs(cnx, entity, attrs) |
625 changes = self._save_attrs(cnx, entity, attrs) |
626 self._record_tx_action(cnx, 'tx_entity_actions', 'U', |
626 self._record_tx_action(cnx, 'tx_entity_actions', u'U', |
627 etype=entity.cw_etype, eid=entity.eid, |
627 etype=unicode(entity.cw_etype), eid=entity.eid, |
628 changes=self._binary(dumps(changes))) |
628 changes=self._binary(dumps(changes))) |
629 sql = self.sqlgen.update(SQL_PREFIX + entity.cw_etype, attrs, |
629 sql = self.sqlgen.update(SQL_PREFIX + entity.cw_etype, attrs, |
630 ['cw_eid']) |
630 ['cw_eid']) |
631 self.doexec(cnx, sql, attrs) |
631 self.doexec(cnx, sql, attrs) |
632 |
632 |
636 if cnx.ertype_supports_undo(entity.cw_etype): |
636 if cnx.ertype_supports_undo(entity.cw_etype): |
637 attrs = [SQL_PREFIX + r.type |
637 attrs = [SQL_PREFIX + r.type |
638 for r in entity.e_schema.subject_relations() |
638 for r in entity.e_schema.subject_relations() |
639 if (r.final or r.inlined) and not r in VIRTUAL_RTYPES] |
639 if (r.final or r.inlined) and not r in VIRTUAL_RTYPES] |
640 changes = self._save_attrs(cnx, entity, attrs) |
640 changes = self._save_attrs(cnx, entity, attrs) |
641 self._record_tx_action(cnx, 'tx_entity_actions', 'D', |
641 self._record_tx_action(cnx, 'tx_entity_actions', u'D', |
642 etype=entity.cw_etype, eid=entity.eid, |
642 etype=unicode(entity.cw_etype), eid=entity.eid, |
643 changes=self._binary(dumps(changes))) |
643 changes=self._binary(dumps(changes))) |
644 attrs = {'cw_eid': entity.eid} |
644 attrs = {'cw_eid': entity.eid} |
645 sql = self.sqlgen.delete(SQL_PREFIX + entity.cw_etype, attrs) |
645 sql = self.sqlgen.delete(SQL_PREFIX + entity.cw_etype, attrs) |
646 self.doexec(cnx, sql, attrs) |
646 self.doexec(cnx, sql, attrs) |
647 |
647 |
648 def add_relation(self, cnx, subject, rtype, object, inlined=False): |
648 def add_relation(self, cnx, subject, rtype, object, inlined=False): |
649 """add a relation to the source""" |
649 """add a relation to the source""" |
650 self._add_relations(cnx, rtype, [(subject, object)], inlined) |
650 self._add_relations(cnx, rtype, [(subject, object)], inlined) |
651 if cnx.ertype_supports_undo(rtype): |
651 if cnx.ertype_supports_undo(rtype): |
652 self._record_tx_action(cnx, 'tx_relation_actions', 'A', |
652 self._record_tx_action(cnx, 'tx_relation_actions', u'A', |
653 eid_from=subject, rtype=rtype, eid_to=object) |
653 eid_from=subject, rtype=unicode(rtype), eid_to=object) |
654 |
654 |
655 def add_relations(self, cnx, rtype, subj_obj_list, inlined=False): |
655 def add_relations(self, cnx, rtype, subj_obj_list, inlined=False): |
656 """add a relations to the source""" |
656 """add a relations to the source""" |
657 self._add_relations(cnx, rtype, subj_obj_list, inlined) |
657 self._add_relations(cnx, rtype, subj_obj_list, inlined) |
658 if cnx.ertype_supports_undo(rtype): |
658 if cnx.ertype_supports_undo(rtype): |
659 for subject, object in subj_obj_list: |
659 for subject, object in subj_obj_list: |
660 self._record_tx_action(cnx, 'tx_relation_actions', 'A', |
660 self._record_tx_action(cnx, 'tx_relation_actions', u'A', |
661 eid_from=subject, rtype=rtype, eid_to=object) |
661 eid_from=subject, rtype=unicode(rtype), eid_to=object) |
662 |
662 |
663 def _add_relations(self, cnx, rtype, subj_obj_list, inlined=False): |
663 def _add_relations(self, cnx, rtype, subj_obj_list, inlined=False): |
664 """add a relation to the source""" |
664 """add a relation to the source""" |
665 sql = [] |
665 sql = [] |
666 if inlined is False: |
666 if inlined is False: |
687 def delete_relation(self, cnx, subject, rtype, object): |
687 def delete_relation(self, cnx, subject, rtype, object): |
688 """delete a relation from the source""" |
688 """delete a relation from the source""" |
689 rschema = self.schema.rschema(rtype) |
689 rschema = self.schema.rschema(rtype) |
690 self._delete_relation(cnx, subject, rtype, object, rschema.inlined) |
690 self._delete_relation(cnx, subject, rtype, object, rschema.inlined) |
691 if cnx.ertype_supports_undo(rtype): |
691 if cnx.ertype_supports_undo(rtype): |
692 self._record_tx_action(cnx, 'tx_relation_actions', 'R', |
692 self._record_tx_action(cnx, 'tx_relation_actions', u'R', |
693 eid_from=subject, rtype=rtype, eid_to=object) |
693 eid_from=subject, rtype=unicode(rtype), eid_to=object) |
694 |
694 |
695 def _delete_relation(self, cnx, subject, rtype, object, inlined=False): |
695 def _delete_relation(self, cnx, subject, rtype, object, inlined=False): |
696 """delete a relation from the source""" |
696 """delete a relation from the source""" |
697 if inlined: |
697 if inlined: |
698 table = SQL_PREFIX + cnx.entity_metas(subject)['type'] |
698 table = SQL_PREFIX + cnx.entity_metas(subject)['type'] |
975 if key == 'etype': |
975 if key == 'etype': |
976 # filtering on etype implies filtering on entity actions |
976 # filtering on etype implies filtering on entity actions |
977 # only, and with no eid specified |
977 # only, and with no eid specified |
978 assert actionfilters.get('action', 'C') in 'CUD' |
978 assert actionfilters.get('action', 'C') in 'CUD' |
979 assert not 'eid' in actionfilters |
979 assert not 'eid' in actionfilters |
980 tearestr['etype'] = val |
980 tearestr['etype'] = unicode(val) |
981 elif key == 'eid': |
981 elif key == 'eid': |
982 # eid filter may apply to 'eid' of tx_entity_actions or to |
982 # eid filter may apply to 'eid' of tx_entity_actions or to |
983 # 'eid_from' OR 'eid_to' of tx_relation_actions |
983 # 'eid_from' OR 'eid_to' of tx_relation_actions |
984 if actionfilters.get('action', 'C') in 'CUD': |
984 if actionfilters.get('action', 'C') in 'CUD': |
985 tearestr['eid'] = val |
985 tearestr['eid'] = val |
986 if actionfilters.get('action', 'A') in 'AR': |
986 if actionfilters.get('action', 'A') in 'AR': |
987 trarestr['eid_from'] = val |
987 trarestr['eid_from'] = val |
988 trarestr['eid_to'] = val |
988 trarestr['eid_to'] = val |
989 elif key == 'action': |
989 elif key == 'action': |
990 if val in 'CUD': |
990 if val in 'CUD': |
991 tearestr['txa_action'] = val |
991 tearestr['txa_action'] = unicode(val) |
992 else: |
992 else: |
993 assert val in 'AR' |
993 assert val in 'AR' |
994 trarestr['txa_action'] = val |
994 trarestr['txa_action'] = unicode(val) |
995 else: |
995 else: |
996 raise AssertionError('unknow filter %s' % key) |
996 raise AssertionError('unknow filter %s' % key) |
997 assert trarestr or tearestr, "can't only filter on 'public'" |
997 assert trarestr or tearestr, "can't only filter on 'public'" |
998 subqsqls = [] |
998 subqsqls = [] |
999 # append subqueries to the original query, using EXISTS() |
999 # append subqueries to the original query, using EXISTS() |
1024 # turn results into transaction objects |
1024 # turn results into transaction objects |
1025 return [tx.Transaction(*args) for args in cu.fetchall()] |
1025 return [tx.Transaction(*args) for args in cu.fetchall()] |
1026 |
1026 |
1027 def tx_info(self, cnx, txuuid): |
1027 def tx_info(self, cnx, txuuid): |
1028 """See :class:`cubicweb.repoapi.ClientConnection.transaction_info`""" |
1028 """See :class:`cubicweb.repoapi.ClientConnection.transaction_info`""" |
1029 return tx.Transaction(txuuid, *self._tx_info(cnx, txuuid)) |
1029 return tx.Transaction(txuuid, *self._tx_info(cnx, unicode(txuuid))) |
1030 |
1030 |
1031 def tx_actions(self, cnx, txuuid, public): |
1031 def tx_actions(self, cnx, txuuid, public): |
1032 """See :class:`cubicweb.repoapi.ClientConnection.transaction_actions`""" |
1032 """See :class:`cubicweb.repoapi.ClientConnection.transaction_actions`""" |
|
1033 txuuid = unicode(txuuid) |
1033 self._tx_info(cnx, txuuid) |
1034 self._tx_info(cnx, txuuid) |
1034 restr = {'tx_uuid': txuuid} |
1035 restr = {'tx_uuid': txuuid} |
1035 if public: |
1036 if public: |
1036 restr['txa_public'] = True |
1037 restr['txa_public'] = True |
1037 # XXX use generator to avoid loading everything in memory? |
1038 # XXX use generator to avoid loading everything in memory? |