简体   繁体   English

用esqueleto计数行

[英]Counting rows with esqueleto

I am trying to count the rows of an inner-join with Esqueleto (version 2.1.2.1). 我正在尝试计算Esqueleto(版本2.1.2.1)的内部联接的行。 Unfortunately, my code doesn't compile and I don't understand why. 不幸的是,我的代码无法编译,我也不明白为什么。 I looked at the following examples of how to do this but couldn't figure out what I'm doing wrong: example1 , example2 . 我查看了以下示例,了解如何执行此操作,但无法弄清自己做错了什么: example1example2

My schema looks like this (simplified): 我的架构如下所示(简化):

User
Game
  state
Player
  user UserId Maybe
  game GameId

Users can register on the site to play games. 用户可以在该网站上注册玩游戏。 You can also play without registering. 您也可以不注册而玩。 Hence, there is a separate table Player . 因此,有一个单独的表Player A game has a state. 游戏具有状态。 It can be Ongoing , or some form of game-over. 它可以是Ongoing中或某种形式的游戏结束。 I now want to count all ongoing games that a user is playing in. 我现在要计算用户正在玩的所有正在进行的游戏。

The following SQL-query does that just fine (for a fixed userId of 1): 下面的SQL查询可以很好地做到这一点(对于固定的用户标识1):

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

However, the following Esqueleto query does not compile: 但是,以下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

The error message reads like this: 错误消息如下所示:

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 }

However, the exact same query works if I remove the countRows . 但是,如果删除countRows ,则完全相同的查询有效。 Ie the following code compiles and does what I want it to do. 即下面的代码可以编译并执行我想要的操作。

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)

What am I doing wrong? 我究竟做错了什么?

It turns out that the Esqueleto code above is correct. 事实证明,上面的Esqueleto代码是正确的。 The error was in another part of the code where a lack of restrictions caused type-ambiguity. 错误发生在代码的另一部分,其中缺少限制导致类型歧义。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM