Search code examples
databasehaskellyesodpersistentesqueleto

Running join on Maybe Relation


I have a model

Assignment
   blah Text
   ....

and a model

File
    assignmentId AssignmentId Maybe
    ...

and I want to get all the files associated with an assignment in a join query. I have tried Esqueleto and runJoin with selectOneMany but haven't had any luck, so I am considering not using a join, or using rawSql. That really doesn't seem like a good idea, but I can't figure this out. Is there any support for that feature?


Solution

  • Update, working example:

    {-# LANGUAGE PackageImports, OverloadedStrings, ConstraintKinds #-}
    module Handler.HTest where
    
    import Import
    import "esqueleto" Database.Esqueleto as Esql
    import "monad-logger" Control.Monad.Logger (MonadLogger)
    import "resourcet" Control.Monad.Trans.Resource (MonadResourceBase)
    import qualified Data.List as L
    
    getFilesByAssignment :: (PersistQuery (SqlPersist m), MonadLogger m
                                                      , MonadResourceBase m) =>
                            Text -> SqlPersist m [Entity File]
    getFilesByAssignment myAssign = do
      result <- select $
            from $ \(assign `InnerJoin` file) -> do
              on (just (assign ^. AssignmentId)
                Esql.==. file ^. FileAssignmentId)
              where_ (assign ^. AssignmentBlah Esql.==. val myAssign)
              return (assign, file)
    
      return $ map snd (result :: [(Entity Assignment, Entity File)])
    
    (.$) = flip ($)
    
    getTestR :: Handler RepHtml
    getTestR = do
           entFiles <- runDB $ getFilesByAssignment "test"
           defaultLayout $ do
                   setTitle "Test page"
                   entFiles .$ map (show . unKey . entityKey)
                            .$ L.intercalate ", "
                            .$ toHtml
                            .$ toWidget