"기본"쿼리와 해당 결과 집합을 정의한 후에 내부 조인을 추가하고 여기서 표현.Database.Esqueleto 쿼리, 조건부 조인 및 카운팅 작성
또한 기본 쿼리가 실행되지 않았으므로 결과 집합을 계산하는 쿼리로 엔티티 (또는 필드 튜플) 목록을 반환하는 기본 쿼리를 변환 할 수는 있지만 수정 된 버전은 LIMIT 및 OFFSET.
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)'와 같은 것을 할 수 있습니다. –