Esqueleto (バージョン 2.1.2.1) で内部結合の行をカウントしようとしています。残念ながら、私のコードはコンパイルされず、その理由がわかりません。これを行う方法の次の例を見ましたが、何が間違っているのかわかりませんでした: example1、example2。
私のスキーマは次のようになります(簡略化):
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)
私は何を間違っていますか?