@@ -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