Index: src/MTXSQLite3Storage.m ================================================================== --- src/MTXSQLite3Storage.m +++ src/MTXSQLite3Storage.m @@ -26,10 +26,13 @@ @implementation MTXSQLite3Storage { SL3Connection *_conn; SL3PreparedStatement *_nextBatchSetStatement, *_nextBatchGetStatement; + SL3PreparedStatement *_joinedRoomsAddStatement; + SL3PreparedStatement *_joinedRoomsRemoveStatement; + SL3PreparedStatement *_joinedRoomsGetStatement; } + (instancetype)storageWithPath: (OFString *)path { return [[[self alloc] initWithPath: path] autorelease]; @@ -53,10 +56,22 @@ @" $device_id, $next_batch\n" @")"] retain]; _nextBatchGetStatement = [[_conn prepareStatement: @"SELECT next_batch FROM next_batch\n" @"WHERE device_id=$device_id"] retain]; + _joinedRoomsAddStatement = [[_conn prepareStatement: + @"INSERT INTO joined_rooms (\n" + @" user_id, room_id\n" + @") VALUES (\n" + @" $user_id, $room_id\n" + @")"] retain]; + _joinedRoomsRemoveStatement = [[_conn prepareStatement: + @"DELETE FROM joined_rooms\n" + @"WHERE user_id=$user_id AND room_id=$room_id"] retain]; + _joinedRoomsGetStatement = [[_conn prepareStatement: + @"SELECT room_id FROM joined_rooms\n" + @"WHERE user_id=$user_id"] retain]; objc_autoreleasePoolPop(pool); } @catch (id e) { [self release]; @throw e; @@ -67,21 +82,30 @@ - (void)dealloc { [_nextBatchSetStatement release]; [_nextBatchGetStatement release]; + [_joinedRoomsAddStatement release]; + [_joinedRoomsRemoveStatement release]; + [_joinedRoomsGetStatement release]; [_conn release]; [super dealloc]; } - (void)createTables { - [_conn executeStatement: @"CREATE TABLE IF NOT EXISTS next_batch (\n" - @" device_id TEXT PRIMARY KEY,\n" - @" next_batch TEXT\n" - @")"]; + [_conn executeStatement: + @"CREATE TABLE IF NOT EXISTS next_batch (\n" + @" device_id TEXT PRIMARY KEY,\n" + @" next_batch TEXT\n" + @");\n" + @"CREATE TABLE IF NOT EXISTS joined_rooms (\n" + @" user_id TEXT,\n" + @" room_id TEXT,\n" + @" PRIMARY KEY (user_id, room_id)\n" + @");"]; } - (void)transactionWithBlock: (mtx_storage_transaction_block_t)block { [_conn transactionWithBlock: block]; @@ -113,12 +137,61 @@ if (![_nextBatchGetStatement step]) return nil; OFString *nextBatch = - [[_nextBatchGetStatement rowDictionary][@"next_batch"] retain]; + [_nextBatchGetStatement.rowDictionary[@"next_batch"] retain]; objc_autoreleasePoolPop(pool); return [nextBatch autorelease]; } + +- (void)addJoinedRoom: (OFString *)roomID + forUser: (OFString *)userID +{ + void *pool = objc_autoreleasePoolPush(); + + [_joinedRoomsAddStatement reset]; + [_joinedRoomsAddStatement bindWithDictionary: @{ + @"$room_id": roomID, + @"$user_id": userID + }]; + [_joinedRoomsAddStatement step]; + + objc_autoreleasePoolPop(pool); +} + +- (void)removeJoinedRoom: (OFString *)roomID + forUser: (OFString *)userID +{ + void *pool = objc_autoreleasePoolPush(); + + [_joinedRoomsRemoveStatement reset]; + [_joinedRoomsRemoveStatement bindWithDictionary: @{ + @"$room_id": roomID, + @"$user_id": userID + }]; + [_joinedRoomsRemoveStatement step]; + + objc_autoreleasePoolPop(pool); +} + +- (OFArray *)joinedRoomsForUser: (OFString *)userID +{ + OFMutableArray *joinedRooms = [OFMutableArray array]; + void *pool = objc_autoreleasePoolPush(); + + [_joinedRoomsGetStatement reset]; + [_joinedRoomsGetStatement bindWithDictionary: @{ + @"$user_id": userID + }]; + + while ([_joinedRoomsGetStatement step]) + [joinedRooms addObject: + _joinedRoomsGetStatement.rowDictionary[@"room_id"]]; + + objc_autoreleasePoolPop(pool); + + return [joinedRooms autorelease]; +} @end Index: src/MTXStorage.h ================================================================== --- src/MTXStorage.h +++ src/MTXStorage.h @@ -56,8 +56,36 @@ * @param deviceID The device ID for which to return the next batch * @return The next batch for the specified device, or `nil` if none is * available. */ - (nullable OFString *)nextBatchForDeviceID: (OFString *)deviceID; + +/** + * @brief Adds the specified room ID to the list of joined rooms for the + * specified user ID. + * + * @param roomID The room ID to add to the list of joined rooms + * @param userID The user ID for which to add the room + */ +- (void)addJoinedRoom: (OFString *)roomID + forUser: (OFString *)userID; + +/** + * @brief Removes the specified room ID to the list of joined rooms for the + * specified user ID. + * + * @param roomID The room ID to add to the list of joined rooms + * @param userID The user ID for which to add the room + */ +- (void)removeJoinedRoom: (OFString *)roomID + forUser: (OFString *)userID; + +/** + * @brief Returns the joined room IDs for the specified user ID. + * + * @param userID The user ID for which to return the joined rooms + * @return The joined room IDs for the specified user ID + */ +- (OFArray *)joinedRoomsForUser: (OFString *)userID; @end OF_ASSUME_NONNULL_END