diff options
Diffstat (limited to 'store')
-rw-r--r-- | store/sql_post_store.go | 98 | ||||
-rw-r--r-- | store/sql_post_store_test.go | 105 | ||||
-rw-r--r-- | store/store.go | 2 |
3 files changed, 205 insertions, 0 deletions
diff --git a/store/sql_post_store.go b/store/sql_post_store.go index de8c4f356..fdae20f60 100644 --- a/store/sql_post_store.go +++ b/store/sql_post_store.go @@ -332,6 +332,104 @@ func (s SqlPostStore) GetPostsSince(channelId string, time int64) StoreChannel { return storeChannel } +func (s SqlPostStore) GetPostsBefore(channelId string, postId string, numPosts int, offset int) StoreChannel { + return s.getPostsAround(channelId, postId, numPosts, offset, true) +} + +func (s SqlPostStore) GetPostsAfter(channelId string, postId string, numPosts int, offset int) StoreChannel { + return s.getPostsAround(channelId, postId, numPosts, offset, false) +} + +func (s SqlPostStore) getPostsAround(channelId string, postId string, numPosts int, offset int, before bool) StoreChannel { + storeChannel := make(StoreChannel) + + go func() { + result := StoreResult{} + + var direction string + var sort string + if before { + direction = "<" + sort = "DESC" + } else { + direction = ">" + sort = "ASC" + } + + var posts []*model.Post + var parents []*model.Post + _, err1 := s.GetReplica().Select(&posts, + `(SELECT + * + FROM + Posts + WHERE + (CreateAt `+direction+` (SELECT CreateAt FROM Posts WHERE Id = :PostId) + AND ChannelId = :ChannelId + AND DeleteAt = 0) + ORDER BY CreateAt `+sort+` + LIMIT :NumPosts + OFFSET :Offset)`, + map[string]interface{}{"ChannelId": channelId, "PostId": postId, "NumPosts": numPosts, "Offset": offset}) + _, err2 := s.GetReplica().Select(&parents, + `(SELECT + * + FROM + Posts + WHERE + Id + IN + (SELECT * FROM (SELECT + RootId + FROM + Posts + WHERE + (CreateAt `+direction+` (SELECT CreateAt FROM Posts WHERE Id = :PostId) + AND ChannelId = :ChannelId + AND DeleteAt = 0) + ORDER BY CreateAt `+sort+` + LIMIT :NumPosts + OFFSET :Offset) + temp_tab)) + ORDER BY CreateAt DESC`, + map[string]interface{}{"ChannelId": channelId, "PostId": postId, "NumPosts": numPosts, "Offset": offset}) + + if err1 != nil { + result.Err = model.NewAppError("SqlPostStore.GetPostContext", "We couldn't get the posts for the channel", "channelId="+channelId+err1.Error()) + } else if err2 != nil { + result.Err = model.NewAppError("SqlPostStore.GetPostContext", "We couldn't get the parent posts for the channel", "channelId="+channelId+err2.Error()) + } else { + + list := &model.PostList{Order: make([]string, 0, len(posts))} + + // We need to flip the order if we selected backwards + if before { + for _, p := range posts { + list.AddPost(p) + list.AddOrder(p.Id) + } + } else { + l := len(posts) + for i := range posts { + list.AddPost(posts[l-i-1]) + list.AddOrder(posts[l-i-1].Id) + } + } + + for _, p := range parents { + list.AddPost(p) + } + + result.Data = list + } + + storeChannel <- result + close(storeChannel) + }() + + return storeChannel +} + func (s SqlPostStore) getRootPosts(channelId string, offset int, limit int) StoreChannel { storeChannel := make(StoreChannel) diff --git a/store/sql_post_store_test.go b/store/sql_post_store_test.go index 0980b1a11..fe7195a54 100644 --- a/store/sql_post_store_test.go +++ b/store/sql_post_store_test.go @@ -383,6 +383,111 @@ func TestPostStoreGetPostsWtihDetails(t *testing.T) { } } +func TestPostStoreGetPostsBeforeAfter(t *testing.T) { + Setup() + o0 := &model.Post{} + o0.ChannelId = model.NewId() + o0.UserId = model.NewId() + o0.Message = "a" + model.NewId() + "b" + o0 = (<-store.Post().Save(o0)).Data.(*model.Post) + time.Sleep(2 * time.Millisecond) + + o1 := &model.Post{} + o1.ChannelId = model.NewId() + o1.UserId = model.NewId() + o1.Message = "a" + model.NewId() + "b" + o1 = (<-store.Post().Save(o1)).Data.(*model.Post) + time.Sleep(2 * time.Millisecond) + + o2 := &model.Post{} + o2.ChannelId = o1.ChannelId + o2.UserId = model.NewId() + o2.Message = "a" + model.NewId() + "b" + o2.ParentId = o1.Id + o2.RootId = o1.Id + o2 = (<-store.Post().Save(o2)).Data.(*model.Post) + time.Sleep(2 * time.Millisecond) + + o2a := &model.Post{} + o2a.ChannelId = o1.ChannelId + o2a.UserId = model.NewId() + o2a.Message = "a" + model.NewId() + "b" + o2a.ParentId = o1.Id + o2a.RootId = o1.Id + o2a = (<-store.Post().Save(o2a)).Data.(*model.Post) + time.Sleep(2 * time.Millisecond) + + o3 := &model.Post{} + o3.ChannelId = o1.ChannelId + o3.UserId = model.NewId() + o3.Message = "a" + model.NewId() + "b" + o3.ParentId = o1.Id + o3.RootId = o1.Id + o3 = (<-store.Post().Save(o3)).Data.(*model.Post) + time.Sleep(2 * time.Millisecond) + + o4 := &model.Post{} + o4.ChannelId = o1.ChannelId + o4.UserId = model.NewId() + o4.Message = "a" + model.NewId() + "b" + o4 = (<-store.Post().Save(o4)).Data.(*model.Post) + time.Sleep(2 * time.Millisecond) + + o5 := &model.Post{} + o5.ChannelId = o1.ChannelId + o5.UserId = model.NewId() + o5.Message = "a" + model.NewId() + "b" + o5.ParentId = o4.Id + o5.RootId = o4.Id + o5 = (<-store.Post().Save(o5)).Data.(*model.Post) + + r1 := (<-store.Post().GetPostsBefore(o1.ChannelId, o1.Id, 4, 0)).Data.(*model.PostList) + + if len(r1.Posts) != 0 { + t.Fatal("Wrong size") + } + + r2 := (<-store.Post().GetPostsAfter(o1.ChannelId, o1.Id, 4, 0)).Data.(*model.PostList) + + if r2.Order[0] != o4.Id { + t.Fatal("invalid order") + } + + if r2.Order[1] != o3.Id { + t.Fatal("invalid order") + } + + if r2.Order[2] != o2a.Id { + t.Fatal("invalid order") + } + + if r2.Order[3] != o2.Id { + t.Fatal("invalid order") + } + + if len(r2.Posts) != 5 { + t.Fatal("wrong size") + } + + r3 := (<-store.Post().GetPostsBefore(o3.ChannelId, o3.Id, 2, 0)).Data.(*model.PostList) + + if r3.Order[0] != o2a.Id { + t.Fatal("invalid order") + } + + if r3.Order[1] != o2.Id { + t.Fatal("invalid order") + } + + if len(r3.Posts) != 3 { + t.Fatal("wrong size") + } + + if r3.Posts[o1.Id].Message != o1.Message { + t.Fatal("Missing parent") + } +} + func TestPostStoreGetPostsSince(t *testing.T) { Setup() o0 := &model.Post{} diff --git a/store/store.go b/store/store.go index 53a6e053b..ce4d90883 100644 --- a/store/store.go +++ b/store/store.go @@ -86,6 +86,8 @@ type PostStore interface { Get(id string) StoreChannel Delete(postId string, time int64) StoreChannel GetPosts(channelId string, offset int, limit int) StoreChannel + GetPostsBefore(channelId string, postId string, numPosts int, offset int) StoreChannel + GetPostsAfter(channelId string, postId string, numPosts int, offset int) StoreChannel GetPostsSince(channelId string, time int64) StoreChannel GetEtag(channelId string) StoreChannel Search(teamId string, userId string, params *model.SearchParams) StoreChannel |