def _get_thread_summaries_txn( txn: LoggingTransaction, ) -> Tuple[Dict[str, int], Dict[str, str]]: # Fetch the count of threaded events and the latest event ID. # TODO Should this only allow m.room.message events. if isinstance(self.database_engine, PostgresEngine): # The `DISTINCT ON` clause will pick the *first* row it encounters, # so ordering by topological ordering + stream ordering desc will # ensure we get the latest event in the thread. sql = """ SELECT DISTINCT ON (parent.event_id) parent.event_id, child.event_id FROM events AS child INNER JOIN event_relations USING (event_id) INNER JOIN events AS parent ON parent.event_id = relates_to_id AND parent.room_id = child.room_id WHERE %s AND relation_type = ? ORDER BY parent.event_id, child.topological_ordering DESC, child.stream_ordering DESC """ else: # SQLite uses a simplified query which returns all entries for a # thread. The first result for each thread is chosen to and subsequent # results for a thread are ignored. sql = """ SELECT parent.event_id, child.event_id FROM events AS child INNER JOIN event_relations USING (event_id) INNER JOIN events AS parent ON parent.event_id = relates_to_id AND parent.room_id = child.room_id WHERE %s AND relation_type = ? ORDER BY child.topological_ordering DESC, child.stream_ordering DESC """ clause, args = make_in_list_sql_clause(txn.database_engine, "relates_to_id", event_ids) args.append(RelationTypes.THREAD) txn.execute(sql % (clause, ), args) latest_event_ids = {} for parent_event_id, child_event_id in txn: # Only consider the latest threaded reply (by topological ordering). if parent_event_id not in latest_event_ids: latest_event_ids[parent_event_id] = child_event_id # If no threads were found, bail. if not latest_event_ids: return {}, latest_event_ids # Fetch the number of threaded replies. sql = """ SELECT parent.event_id, COUNT(child.event_id) FROM events AS child INNER JOIN event_relations USING (event_id) INNER JOIN events AS parent ON parent.event_id = relates_to_id AND parent.room_id = child.room_id WHERE %s AND relation_type = ? GROUP BY parent.event_id """ # Regenerate the arguments since only threads found above could # possibly have any replies. clause, args = make_in_list_sql_clause(txn.database_engine, "relates_to_id", latest_event_ids.keys()) args.append(RelationTypes.THREAD) txn.execute(sql % (clause, ), args) counts = dict(cast(List[Tuple[str, int]], txn.fetchall())) return counts, latest_event_ids
def _delete_staging_area(txn: LoggingTransaction) -> None: txn.execute("DROP TABLE IF EXISTS " + TEMP_TABLE + "_rooms") txn.execute("DROP TABLE IF EXISTS " + TEMP_TABLE + "_users") txn.execute("DROP TABLE IF EXISTS " + TEMP_TABLE + "_position")
def _get_aggregation_groups_for_users_txn( txn: LoggingTransaction, ) -> Dict[Tuple[str, str], int]: txn.execute(sql, args + [limit]) return {(row[0], row[1]): row[2] for row in txn}