Composing Database.Esqueleto queries, conditional joins and counting

前端 未结 2 1147
忘掉有多难
忘掉有多难 2021-01-04 12:03

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

2条回答
  •  走了就别回头了
    2021-01-04 12:17

    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 JOINs, 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 JOINs). 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 JOINs. If you need to do a OUTER JOIN then you'll have to refactor your code so that all the OUTER JOINs are in the same from (note that you can do an implicit join between OUTER JOINs just fine).

提交回复
热议问题