@@ -53,7 +53,7 @@ import qualified GHC.Generics as GHC
5353import Data.Int (Int64)
5454import Data.ByteString.Char8 (pack)
5555import GHC.Generics (Generic)
56−import Data.Aeson
56+import Data.Aeson hiding (Null)
5757import Servant.Docs
5858import Data.Proxy
5959import Data.Vector (Vector, toList, fromList)
@@ -61,6 +61,7 @@ import Data.Text (Text)
6161import Data.Channel.NamedChannel
6262import Data.Channel.AnonymousChannel
6363import Data.Maybe (fromMaybe)
64+import Squeal.PostgreSQL.Render
6465
6566-- MARK: Documentation
6667
@@ -81,7 +82,12 @@ postViewT te = from $ subquery (postsQ te `As` #posts) &
8182 innerJoin (table #postElements)
8283 (#posts ! #postRowId .== #postElements ! #rowElementId)
8384
84−getPostQ :: TableEndo Schema params _ 'Ungrouped -> TableEndo Schema params _ 'Ungrouped -> Query Schema params (RowPG PostRowResponse)
85+getPostQ
86+ :: TableEndo Schema params _ 'Ungrouped
87+ -- ^ PostRowResponse endo
88+ -> TableEndo Schema params _ 'Ungrouped
89+ -- ^ PostRow endo
90+ -> Query Schema params (RowPG PostRowResponse)
8591getPostQ oTe te = select (
8692 #posts ! #postRowId :*
8793 #posts ! #postRowAuthorId :*
@@ -142,21 +148,26 @@ getAllUsersQ = selectStar $ from $ table #users
142148getPostsByIdQ :: [PostId] -> Maybe (Query Schema '[] (RowPG PostRowResponse))
143149getPostsByIdQ pIds = case idsToColumn pIds of
144150 Just idQ -> Just $ selectDotStar #posts $ from (subquery (idQ `As` #ids) &
145− innerJoin (subquery $ getPostQ id id `As` #posts)
151+ innerJoin (subquery $ getPostQ (orderBy [#posts ! #postRowId & Desc] . orderBy [#postElements ! #rowElementOrd & Asc]) id `As` #posts)
146152 (#ids ! #id .== #posts ! #postRowId))
147153 Nothing -> Nothing
148154
149155
150156type Limit = Word64
151157
152−getLastNPostsQ :: Limit -> Query Schema params (RowPG PostRowResponse)
153−getLastNPostsQ lim = getPostQ
154− (limit lim . orderBy [#posts ! #postRowUpdateTime & Desc]) id
158+isNotFalse
159+ :: Expression schema from grouping params ('Null ty)
160+ -- ^ possibly @NULL@
161+ -> Condition schema from grouping params
162+isNotFalse x = UnsafeExpression $ renderExpression x <+> "IS NOT FALSE"
155163
156−getLastNPostsForUserQ :: Limit -> Query Schema (TuplePG (Only UserId)) (RowPG PostRowResponse)
157−getLastNPostsForUserQ lim = getPostQ
158− (limit lim . orderBy [#posts ! #postRowUpdateTime & Desc])
159− (where_ $ #postRowAuthorId .== param @1)
164+getLastPostsQ :: TableEndo _ _ _ _ -> Limit -> Query Schema ('Null (PG Int64) ': params) (RowPG PostRowResponse)
165+getLastPostsQ te lim = getPostQ
166+ (orderBy [#posts ! #postRowId & Desc] . orderBy [#postElements ! #rowElementOrd & Asc])
167+ (limit lim . te . where_ (isNotFalse $ #posts ! #postRowId .< param @1) . orderBy [#posts ! #postRowId & Desc])
168+
169+getLastNPostsForUserQ :: Limit -> Query Schema (TuplePG (Maybe PostId, UserId)) (RowPG PostRowResponse)
170+getLastNPostsForUserQ = getLastPostsQ $ where_ (#posts ! #postRowAuthorId .== param @2)
160171
161172createPostRowQ :: Manipulation Schema (TuplePG (UserId, Vector Text)) (RowPG (Only PostId))
162173createPostRowQ = insertRow #posts
@@ -214,10 +225,17 @@ updateNamedChannelQ = update_ #channels
214225 )
215226 (#namedChannelFullOwner .== param @2 .&& #namedChannelFullId .== param @1)
216227
217−
218−getChannelPostsQ :: Limit -> [UserId] -> Vector Text -> Query Schema '[] (RowPG PostRowResponse)
228+getChannelPostsQ
229+ :: Limit
230+ -> [UserId]
231+ -> Vector Text
232+ -> Query
233+ Schema
234+ (TuplePG (Only (Maybe PostId))) -- ^ post id from which to start
235+ (RowPG PostRowResponse)
219236getChannelPostsQ lim uIds tags = selectStar $ from (subquery $ postsQ' `As` #bar) &
220− orderBy [#postRowUpdateTime & Desc] & limit lim
237+ where_ ( isNotFalse $ #postRowId .< param @1) &
238+ orderBy [#postRowId & Desc] . orderBy [#rowElementOrd & Asc] & limit lim
221239 where
222240 unionWithUsers = case idsToColumn uIds of
223241 Just uIdsQ -> selectDotStar #posts' (from $ subquery (uIdsQ `As` #uIds) &
@@ -280,10 +298,11 @@ verifiedUsers uIds =
280298
281299-- MARK: FrontEnd functions
282300
283−getPostsForUser :: Word64 -> UserId -> StaticPQ (Maybe (ResponseWithUsers [Post]))
284−getPostsForUser lim uId = do
285− postRows <- runQueryParams (getLastNPostsForUserQ lim) (Only uId) >>= getRows
286− rowsToPosts postRows `liftMaybe` wrapIntoResponse
301+-- Nothing <=> no user
302+getPostsForUser :: Maybe PostId -> Limit -> UserId -> StaticPQ (Maybe (ResponseWithUsers [Post]))
303+getPostsForUser pId lim uId = do
304+ postRows <- runQueryParams (getLastNPostsForUserQ lim) (pId, uId) >>= getRows
305+ wrapIntoResponse (fromMaybe [] . rowsToPosts $ postRows)
287306
288307getPosts :: [PostId] -> StaticPQ (Maybe (ResponseWithUsers [Post]))
289308getPosts pId =
@@ -293,9 +312,9 @@ getPosts pId =
293312 rowsToPosts postRows `liftMaybe` wrapIntoResponse
294313 Nothing -> return Nothing
295314
296−getLastPosts :: Word64 -> StaticPQ (Maybe (ResponseWithUsers [Post]))
297−getLastPosts n = do
298− postRows <- runQuery (getLastNPostsQ n) >>= getRows
315+getLastPosts :: Maybe PostId -> Limit -> StaticPQ (Maybe (ResponseWithUsers [Post]))
316+getLastPosts pId lim = do
317+ postRows <- runQueryParams (getLastPostsQ id lim) (Only pId) >>= getRows
299318 rowsToPosts postRows `liftMaybe` wrapIntoResponse
300319
301320getUser :: UserId -> StaticPQ User
@@ -329,16 +348,16 @@ updateChannel uId req = commitedTransactionallyUpdate $ do
329348 _ <- manipulateParams updateNamedChannelQ $ addUserToChannelUpdate uId (req {namedChannelPeopleIds = uIds})
330349 return ()
331350
332−getChannelPosts :: UserId -> Limit -> NamedChannelId -> StaticPQ (ResponseWithUsers [Post])
333−getChannelPosts uId lim cId = do
351+getChannelPosts :: UserId -> Maybe PostId -> Limit -> NamedChannelId -> StaticPQ (ResponseWithUsers [Post])
352+getChannelPosts uId pId lim cId = do
334353 channel <- getChannelForUser uId cId
335− postRows <- runQuery (getChannelPostsQ lim (toList $ namedChannelFullPeopleIds channel) (namedChannelFullTags channel))
354+ postRows <- runQueryParams (getChannelPostsQ lim (toList $ namedChannelFullPeopleIds channel) (namedChannelFullTags channel)) (Only pId)
336355 >>= getRows
337356 fmap (fromMaybe $ ResponseWithUsers mempty mempty) $ rowsToPosts postRows `liftMaybe` wrapIntoResponse
338357
339−getAnonymousChannelPosts :: Limit -> AnonymousChannel -> StaticPQ (ResponseWithUsers [Post])
340−getAnonymousChannelPosts lim (AnonymousChannel tags people) = do
341− postRows <- runQuery (getChannelPostsQ lim people tags) >>= getRows
358+getAnonymousChannelPosts :: Maybe PostId -> Limit -> AnonymousChannel -> StaticPQ (ResponseWithUsers [Post])
359+getAnonymousChannelPosts pId lim (AnonymousChannel tags people) = do
360+ postRows <- runQueryParams (getChannelPostsQ lim people tags) (Only pId) >>= getRows
342361 fmap (fromMaybe $ ResponseWithUsers mempty mempty) $ rowsToPosts postRows `liftMaybe` wrapIntoResponse
343362
344363getAllChannels :: UserId -> StaticPQ [NamedChannel UserId]