4

Esqueleto (バージョン 2.1.2.1) で内部結合の行をカウントしようとしています。残念ながら、私のコードはコンパイルされず、その理由がわかりません。これを行う方法の次の例を見ましたが、何が間違っているのかわかりませんでした: example1example2

私のスキーマは次のようになります(簡略化):

User
Game
  state
Player
  user UserId Maybe
  game GameId

ユーザーはサイトに登録してゲームをプレイできます。登録しなくても遊べます。したがって、別のテーブルがありますPlayer。ゲームには状態があります。Ongoing、または何らかの形のゲームオーバーになる可能性があります。ユーザーがプレイしている進行中のゲームをすべて数えたいと思います。

次の SQL クエリは、これをうまく実行します (userId が 1 に固定されている場合)。

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

ただし、次の Esqueleto クエリはコンパイルされません。

[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

エラーメッセージは次のようになります。

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 }

ただし、を削除すると、まったく同じクエリが機能します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)

私は何を間違っていますか?

4

1 に答える 1

1

上記の Esqueleto コードが正しいことがわかりました。エラーはコードの別の部分にあり、制限がないために型があいまいになりました。

于 2015-02-27T23:09:46.557 に答える