diff --git a/synapse/api/events/__init__.py b/synapse/api/events/__init__.py index f95468fc65..5f300de108 100644 --- a/synapse/api/events/__init__.py +++ b/synapse/api/events/__init__.py @@ -157,7 +157,12 @@ class SynapseEvent(JsonEncodedObject): class SynapseStateEvent(SynapseEvent): - def __init__(self, **kwargs): + + valid_keys = SynapseEvent.valid_keys + [ + "prev_content", + ] + + def __init__(self, **kwargs): if "state_key" not in kwargs: kwargs["state_key"] = "" super(SynapseStateEvent, self).__init__(**kwargs) diff --git a/synapse/storage/__init__.py b/synapse/storage/__init__.py index d97014f4da..81c3c94b2e 100644 --- a/synapse/storage/__init__.py +++ b/synapse/storage/__init__.py @@ -81,7 +81,7 @@ class DataStore(RoomMemberStore, RoomStore, defer.returnValue(latest) @defer.inlineCallbacks - def get_event(self, event_id): + def get_event(self, event_id, allow_none=False): events_dict = yield self._simple_select_one( "events", {"event_id": event_id}, @@ -92,8 +92,12 @@ class DataStore(RoomMemberStore, RoomStore, "content", "unrecognized_keys" ], + allow_none=allow_none, ) + if not events_dict: + defer.returnValue(None) + event = self._parse_event_from_row(events_dict) defer.returnValue(event) @@ -220,7 +224,8 @@ class DataStore(RoomMemberStore, RoomStore, results = yield self._execute_and_decode(sql, *args) - defer.returnValue([self._parse_event_from_row(r) for r in results]) + events = yield self._parse_events(results) + defer.returnValue(events) @defer.inlineCallbacks def _get_min_token(self): diff --git a/synapse/storage/_base.py b/synapse/storage/_base.py index bae50e7d1f..8037225079 100644 --- a/synapse/storage/_base.py +++ b/synapse/storage/_base.py @@ -312,6 +312,25 @@ class SQLBaseStore(object): **d ) + def _parse_events(self, rows): + return self._db_pool.runInteraction(self._parse_events_txn, rows) + + def _parse_events_txn(self, txn, rows): + events = [self._parse_event_from_row(r) for r in rows] + + sql = "SELECT * FROM events WHERE event_id = ?" + + for ev in events: + if hasattr(ev, "prev_state"): + # Load previous state_content. + # TODO: Should we be pulling this out above? + cursor = txn.execute(sql, (ev.prev_state,)) + prevs = self.cursor_to_dict(cursor) + if prevs: + prev = self._parse_event_from_row(prevs[0]) + ev.prev_content = prev.content + + return events class Table(object): """ A base class used to store information about a particular table. diff --git a/synapse/storage/roommember.py b/synapse/storage/roommember.py index 75c9a60101..9a393e2568 100644 --- a/synapse/storage/roommember.py +++ b/synapse/storage/roommember.py @@ -88,7 +88,7 @@ class RoomMemberStore(SQLBaseStore): txn.execute(sql, (user_id, room_id)) rows = self.cursor_to_dict(txn) if rows: - return self._parse_event_from_row(rows[0]) + return self._parse_events_txn(txn, rows)[0] else: return None @@ -161,7 +161,7 @@ class RoomMemberStore(SQLBaseStore): # logger.debug("_get_members_query Got rows %s", rows) - results = [self._parse_event_from_row(r) for r in rows] + results = yield self._parse_events(rows) defer.returnValue(results) @defer.inlineCallbacks diff --git a/synapse/storage/stream.py b/synapse/storage/stream.py index 2cb0067a67..aff6dc9855 100644 --- a/synapse/storage/stream.py +++ b/synapse/storage/stream.py @@ -188,7 +188,7 @@ class StreamStore(SQLBaseStore): user_id, user_id, from_id, to_id ) - ret = [self._parse_event_from_row(r) for r in rows] + ret = yield self._parse_events(rows) if rows: key = "s%d" % max([r["stream_ordering"] for r in rows]) @@ -243,9 +243,11 @@ class StreamStore(SQLBaseStore): # TODO (erikj): We should work out what to do here instead. next_token = to_key if to_key else from_key + events = yield self._parse_events(rows) + defer.returnValue( ( - [self._parse_event_from_row(r) for r in rows], + events, next_token ) ) @@ -277,12 +279,11 @@ class StreamStore(SQLBaseStore): else: token = (end_token, end_token) - defer.returnValue( - ( - [self._parse_event_from_row(r) for r in rows], - token - ) - ) + events = yield self._parse_events(rows) + + ret = (events, token) + + defer.returnValue(ret) def get_room_events_max_id(self): return self._db_pool.runInteraction(self._get_room_events_max_id_txn)