Database.Esqueletoクエリをモジュール式で構成するにはどうすれば "ベース"クエリとそれに対応する結果セットを定義した後で追加の内部結合を追加して結果セットを制限できるどこの表現。Database.Esqueletoクエリの作成、条件付き結合とカウント
また、エンティティ(またはフィールドタプル)のリストを返すベースクエリを、ベースクエリがそのまま実行されるのではなく結果セットをカウントするクエリに変換するにはどうすればよいですか?LIMITおよびオフセット。
the Yesod Bookから採用されている次の誤ったHaskellコードスニペットが、私が目指していることをうまく説明してくれるでしょう。ドキュメントとselect
の種類を見ると
{-# 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()
ギャップを埋めて決定的な答えを与えることに感謝します。 – Tero
'commentsQuery'では' from'を使う前に 'baseQuery'を使うこともできます。 –
また、無効なSQLをもたらすesqueletoクエリをバグとして報告し、その根を調査することができます。あなたが見た人は、知られているが固定されていないバグである '()'の扱いと関係があります。回避策として、 'return(val True)'のようなことをすることができます。 –