2015-02-02 2 views
4

Esqueleto (버전 2.1.2.1)로 내부 조인의 행 수를 계산하려고합니다. 불행히도, 내 코드가 컴파일되지 않고 이유를 이해할 수 없습니다. 나는 이것을하는 방법에 대한 다음 예제를 보았지만 내가 잘못하고있는 것을 이해할 수 없었다 : example1, example2.esqueleto로 행 계산하기

내 스키마이 (간체)과 같습니다

User 
Game 
    state 
Player 
    user UserId Maybe 
    game GameId 

사용자는 게임을 할 수있는 사이트에 등록 할 수 있습니다. 등록하지 않고도 재생할 수 있습니다. 따라서 별도의 테이블 Player이 있습니다. 게임에 상태가 있습니다. Ongoing 또는 게임 오버의 일부 형태 일 수 있습니다. 지금은 사용자가 재생되어 진행중인 모든 게임을 계산 할

다음 SQL 쿼리는 않습니다 (1의 고정 userId를위한) 잘 :. 그러나

SELECT COUNT (*) 
FROM Player INNER JOIN Game 
ON Player.game = Game.id 
WHERE Player.user = 1 AND game.state = "Ongoing" 

, 다음 Esqueleto 쿼리 컴파일되지 않습니다 :

Handler/ListUserGames.hs:25:23: 
    No instance for (E.SqlSelect (expr0 (E.Value a0)) r0) 
     arising from a use of ‘E.select’ 
    The type variables ‘r0’, ‘expr0’, ‘a0’ are ambiguous 
    Note: there are several potential instances: 
     instance (E.SqlSelect a ra, E.SqlSelect b rb) => 
       E.SqlSelect (a, b) (ra, rb) 
     -- Defined in ‘Database.Esqueleto.Internal.Sql’ 
     instance (E.SqlSelect a ra, E.SqlSelect b rb, E.SqlSelect c rc) => 
       E.SqlSelect (a, b, c) (ra, rb, rc) 
     -- Defined in ‘Database.Esqueleto.Internal.Sql’ 
     instance (E.SqlSelect a ra, E.SqlSelect b rb, E.SqlSelect c rc, 
       E.SqlSelect d rd) => 
       E.SqlSelect (a, b, c, d) (ra, rb, rc, rd) 
     -- Defined in ‘Database.Esqueleto.Internal.Sql’ 
     ...plus 13 others 
    In the expression: E.select 
    In the second argument of ‘($)’, namely 
     ‘E.select 
     $ E.from 
     $ \ (player `E.InnerJoin` game) 
      -> do { E.on $ player ^. PlayerGame E.==. game ^. GameId; 
        E.where_ 
        $ player ^. PlayerUser E.==. E.just (E.val userId) 
         E.&&. game ^. GameState E.==. E.val MyGame.Ongoing; 
        .... }’ 
    In a stmt of a 'do' block: 
     [count1] <- runDB 
        $ E.select 
        $ E.from 
         $ \ (player `E.InnerJoin` game) 
          -> do { E.on $ player ^. PlayerGame E.==. game ^. GameId; 
            E.where_ 
            $ player ^. PlayerUser E.==. E.just (E.val userId) 
            E.&&. game ^. GameState E.==. E.val MyGame.Ongoing; 
            .... } 

Handler/ListUserGames.hs:32:32: 
    No instance for (E.Esqueleto query0 expr0 backend0) 
     arising from a use of ‘E.countRows’ 
    The type variables ‘query0’, ‘expr0’, ‘backend0’ are ambiguous 
    Note: there is a potential instance available: 
     instance E.Esqueleto E.SqlQuery E.SqlExpr SqlBackend 
     -- Defined in ‘Database.Esqueleto.Internal.Sql’ 
    In the first argument of ‘return’, namely ‘E.countRows’ 
    In a stmt of a 'do' block: return E.countRows 
    In the expression: 
     do { E.on $ player ^. PlayerGame E.==. game ^. GameId; 
      E.where_ 
      $ player ^. PlayerUser E.==. E.just (E.val userId) 
      E.&&. game ^. GameState E.==. E.val MyGame.Ongoing; 
      return (game, player); 
      return E.countRows } 

하우 :

[count1] <- runDB $ E.select         -- Line 25 
        $ E.from $ \(player `E.InnerJoin` game) -> do 
         E.on $ player^.PlayerGame E.==. game^.GameId 
         E.where_ $ 
          player^.PlayerUser E.==. E.just (E.val userId) E.&&. 
          game^.GameState E.==. E.val MyGame.Ongoing 
         return (game, player) 
         return E.countRows      -- Line 32 

오류 메시지는 다음과 같이 읽는다 ver, 정확히 동일한 쿼리는 countRows을 제거하면 작동합니다. 나는. 다음 코드는 컴파일하고 내가 원하는 것을 수행합니다.

ongoing <- runDB $ E.select 
       $ E.from $ \(player `E.InnerJoin` game) -> do 
        E.on $ player^.PlayerGame E.==. game^.GameId 
        E.where_ $ 
         player^.PlayerUser E.==. E.just (E.val userId) E.&&. 
         game^.GameState E.==. E.val MyGame.Ongoing 
        E.orderBy [E.desc $ game^.GameLastActionTime] 
        E.limit pagelen 
        E.offset $ max 0 $ (page1 - 1) * pagelen 
        return (game, player) 

내가 뭘 잘못하고 있니?

답변

1

위의 Esqueleto 코드가 정확한 것으로 밝혀졌습니다. 이 오류는 제한 사항이 부족하여 유형 모호성이 발생하는 코드의 다른 부분에서 발생했습니다.

+0

유형 모호성은 무엇입니까? 나는이 같은 문제가 있지만 여분의 제한을 추가 할 곳을 모른다. – Agumander

+2

@Agumander 오랜 시간이 지났지 만 나는 정확히 그 문제가 무엇인지 기억하지 못한다. 그러나 코드를 살펴보면 패턴 바인딩에서'count1'을'E.Value count1'로 변경하면 도움이 될 것입니다. – Lemming

+2

이것은 획기적인 결과를 가져 왔습니다! 내 경우에는 나중에 표시하기 위해 [E.Value (count1 :: Int)]을 추가로 지정했습니다. 고맙습니다! – Agumander