How can I compose Database.Esqueleto queries in a modular way such that after defining a \"base\" query and the corresponding result set, I can restrict the result set by ad
For LIMIT
and COUNT
, hammar's answer is entirely correct so I'll not delve into them. I'll just reiterate that once you use select
you'll not be able to change the query in any way again.
For JOIN
s, currently you are not able to do a INNER JOIN
with a query that was defined in a different from
(nor (FULL|LEFT|RIGHT) OUTER JOIN
s). However, you can do implicit joins. For example, if you have defined:
baseQuery =
from $ \(p `InnerJoin` b) -> do
on (p ^. PersonId ==. b ^. BlogPostAuthorId)
where_ (p ^. PersonName `like` val "J%")
return (p, b)
Then you may just say:
commentsQuery =
from $ \c -> do
(p, b) <- baseQuery
where_ (b ^. BlogPostId ==. c ^. CommentBlogPostId)
return (p, b, c)
Esqueleto then will generate something along the lines of:
SELECT ...
FROM Comment, Person INNER JOIN BlogPost
ON Person.id = BlogPost.authorId
WHERE Person.name LIKE "J%"
AND BlogPost.id = Comment.blogPostId
Not pretty but gets the job done for INNER JOIN
s. If you need to do a OUTER JOIN
then you'll have to refactor your code so that all the OUTER JOIN
s are in the same from
(note that you can do an implicit join between OUTER JOIN
s just fine).