haskellesqueleto

Outer Joins with Esqueleto


I am a bit confused about how outer joins work with esqueleto.

I have created the following query (simplified):

select $ from $ \(rep `LeftOuterJoin` event) -> do
          on (rep ^. RepAtomId  ==. event   ^. EventAtomId )
          where_ (rep ^. RepAtomId  ==. val aid)
          return $ (rep, event ^. EventSeconds)

As far as I know, on the SQL-side, this query will search for reps that may have an associated event. If they do not have an associated event, the event fields (like EventSeconds) will be "null". On the Haskell side, these should be translated into Maybe Seconds (well, ints, but you get the idea).

So what actually happens when I run this query and there is nothing to adjoin to my rep relation? How do I deconstruct the tuple to stick a default in?

Currently, I have something along the lines of:

case listToMaybe lrep of
  Just ( entityVal -> rep
       , unValue -> seconds
       ) -> do stuff

(Note that I have ViewPatterns turned on here). This type checks. But it fails if I use (?.) and (fromMaybe 3600) . unValue in the pattern analysis.


Solution

  • I was able to fix this by adding a 'just' in the right place:

    select $ from $ \(rep `LeftOuterJoin` event) -> do
             on (just (rep ^. RepAtomId)  ==. event  ?. EventAtomId )
             where_ (rep ^. RepAtomId  ==. val aid)
             return $ (rep, event ?. EventSeconds)
    
    case listToMaybe lrep of
      Just ( entityVal -> rep
           , (fromMaybe 3600) . unValue -> seconds
           ) -> do stuff
    

    The idea being that (event) does have a Maybe-like type (I'm not sure what it's type is, but I know it has an embedded Maybe). So when I was comparing to the rep, I was comparing a (Maybe a) to an a. 'just' wrapped the a into a (Maybe a), without having to deconstruct the intermediate type.