首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >用esqueleto数行

用esqueleto数行
EN

Stack Overflow用户
提问于 2015-02-02 08:50:03
回答 1查看 780关注 0票数 4

我正在尝试计算Esqueleto内部连接的行数(版本2.1.2.1)。不幸的是,我的代码没有编译,我也不明白为什么。我看了以下如何做这件事的例子,但不知道我做错了什么:example1example2

我的模式看起来如下(简化):

代码语言:javascript
复制
User
Game
  state
Player
  user UserId Maybe
  game GameId

用户可以在网站上注册玩游戏。你也可以在不注册的情况下玩。因此,有一个单独的表Player。游戏是有状态的。可以是Ongoing,也可以是某种形式的游戏结束。现在我想数一数用户正在玩的所有正在进行的游戏。

下面的SQL-查询可以做到这一点(对于固定的userId为1):

代码语言:javascript
复制
SELECT COUNT (*)
FROM Player INNER JOIN Game
ON Player.game = Game.id
WHERE Player.user = 1 AND game.state = "Ongoing"

但是,以下Esqueleto查询没有编译:

代码语言:javascript
复制
[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

错误消息如下所示:

代码语言:javascript
复制
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,则完全相同的查询工作。也就是说,下面的代码编译并执行我希望它做的事情。

代码语言:javascript
复制
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)

我做错了什么?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2015-02-27 23:09:46

事实证明,上面的Esqueleto代码是正确的。错误发生在代码的另一部分,在代码中,缺乏限制会导致类型模糊。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/28273922

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档