Jak mogę skompilować zapytania Database.Esqueleto w sposób modułowy tak, że po zdefiniowaniu zapytania "podstawowego" i odpowiedniego zestawu wyników mogę ograniczyć zestaw wyników przez dodanie dodatkowych wewnętrznych sprzężeń i gdzie wyrażenia.Komponowanie zapytań SQL, warunkowe łączenie i liczenie
Ponadto, w jaki sposób mogę przekonwertować zapytanie podstawowe, które zwraca listę elementów (lub krotek pól) do zapytania, które zlicza zestaw wyników, ponieważ zapytanie podstawowe nie jest wykonywane jako takie, ale zmodyfikowana wersja z LIMITem i OFFSET.
Poniższy niepoprawny fragment kodu Haskella przyjęty z the Yesod Book powinien, mam nadzieję, wyjaśnić, do czego dążę.
{-# LANGUAGE QuasiQuotes, TemplateHaskell, TypeFamilies, OverloadedStrings #-}
{-# LANGUAGE GADTs, FlexibleContexts #-}
import qualified Database.Persist as P
import qualified Database.Persist.Sqlite as PS
import Database.Persist.TH
import Control.Monad.IO.Class (liftIO)
import Data.Conduit
import Control.Monad.Logger
import Database.Esqueleto
import Control.Applicative
share [mkPersist sqlSettings, mkMigrate "migrateAll"] [persistLowerCase|
Person
name String
age Int Maybe
deriving Show
BlogPost
title String
authorId PersonId
deriving Show
Comment
comment String
blogPostId BlogPostId
|]
main :: IO()
main = runStdoutLoggingT $ runResourceT $ PS.withSqliteConn ":memory:" $ PS.runSqlConn $ do
runMigration migrateAll
johnId <- P.insert $ Person "John Doe" $ Just 35
janeId <- P.insert $ Person "Jane Doe" Nothing
jackId <- P.insert $ Person "Jack Black" $ Just 45
jillId <- P.insert $ Person "Jill Black" Nothing
blogPostId <- P.insert $ BlogPost "My fr1st p0st" johnId
P.insert $ BlogPost "One more for good measure" johnId
P.insert $ BlogPost "Jane's" janeId
P.insert $ Comment "great!" blogPostId
let baseQuery = select $ from $ \(p `InnerJoin` b) -> do
on (p ^. PersonId ==. b ^. BlogPostAuthorId)
where_ (p ^. PersonName `like` (val "J%"))
return (p,b)
-- Does not compile
let baseQueryLimited = (,) <$> baseQuery <*> (limit 2)
-- Does not compile
let countingQuery = (,) <$> baseQuery <*> (return countRows)
-- Results in invalid SQL
let commentsQuery = (,) <$> baseQuery
<*> (select $ from $ \(b `InnerJoin` c) -> do
on (b ^. BlogPostId ==. c ^. CommentBlogPostId)
return())
somePosts <- baseQueryLimited
count <- countingQuery
withComments <- commentsQuery
liftIO $ print somePosts
liftIO $ print ((head count) :: Value Int)
liftIO $ print withComments
return()
Dzięki za wypełnienie luk i udzielenie jednoznacznej odpowiedzi. – Tero
Należy również zauważyć, że w 'commentQuery' można również użyć' baseQuery' przed użyciem 'od' po prostu dobrze. –
Proszę również zgłosić jako błąd zapytanie esqueleto, które skutkuje nieprawidłowym SQL, abyśmy mogli zbadać jego korzenie. Ten, który widziałeś, ma związek z traktowaniem '()', znanego, ale nie naprawionego błędu.Jako obejście można zrobić coś takiego jak 'return (val True)'. –