Handling List-types with Esqueleto

SqlListHaskellEsqueleto

Sql Problem Overview


I have data types defined as:

data ComitteeView = CommitteeView { committeeId :: CommitteeId
                                  , committeeMembers :: [Person] 
                                  }

data CommitteesView = CommitteesView { committeeView :: [CommitteeView] }

Now, as it stands, I have a Persistent model defined as:

Person
  name  Text

Committee
  name  Text

CommitteePerson
  personId    PersonId
  committeeId CommitteeId

I can pretty easily create a query to populate a CommitteeView, using Esqueleto. It would go something like this:

getCommitteeView cid = 
  CommitteeView <$> runDB $ 
    select $
      from (person `InnerJoin` pxc `InnerJoin` committee) -> do
        on  (committee ^. CommitteeId ==. pxc ^. CommitteePersonCommitteeId)
        on  (person ^. PersonId       ==. pxc ^. CommitteePersonPersonId)
        where_ (committee ^. CommitteePersonCommitteeId ==. val cid)
        return person

Now, consider the problem of populating CommitteesView. In principle, we get enough data to populate by running subquery in the above query. Okay, fair enough. Now how can I use "group by Haskell-list" like group by in SQL? How can I fold rows so that I can end up with a list of lists of people?

I get the impression that esqueleto can't handle the case as such (i.e., it doesn't have a combinator that would do it). And my underlying database obviously doesn't support Haskell lists as a column. But, surely, I can't be the only person to face this issue. What is an effective strategy? Folding an n-list of lists into a n-list? Or running n+1 queries? Are there any other options?

Sql Solutions


Solution 1 - Sql

Esqueleto is NOT meant to handle list of sublists (multidimensional list) out of the box yet! Data.List.groupBy that 'cdk' advised to you can group only list itself, but not what you was asking for.

For your case I would insistently advise you to use a classic SQL queries. You can run n+1 queries, but do that only if it is rare and not often usable function, that for example prepares cached data (based on your variables names I suppose that it may not be heavy used and it worth a try). For heavy usage you should consider using classic SQL without any doubt.

If you will go to https://github.com/prowdsponsor/esqueleto you will find that:

> Not all SQL features are available, but most of them can be easily > added (especially functions).

so you can try to ask for a new feature. Good luck!

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionnomenView Question on Stackoverflow
Solution 1 - SqlKainaxView Answer on Stackoverflow