From 088970940359997d603fa9a02a5660eda42b46b0 Mon Sep 17 00:00:00 2001 From: Mitsutoshi Aoe Date: Thu, 7 Mar 2013 20:04:43 +0900 Subject: [PATCH 1/2] Add support for COUNT(expr) --- src/Database/Esqueleto.hs | 2 +- src/Database/Esqueleto/Internal/Language.hs | 3 +++ src/Database/Esqueleto/Internal/Sql.hs | 2 ++ test/Test.hs | 18 ++++++++++++++++++ 4 files changed, 24 insertions(+), 1 deletion(-) diff --git a/src/Database/Esqueleto.hs b/src/Database/Esqueleto.hs index fc8b021..5900c5d 100644 --- a/src/Database/Esqueleto.hs +++ b/src/Database/Esqueleto.hs @@ -20,7 +20,7 @@ module Database.Esqueleto -- * @esqueleto@'s Language Esqueleto( where_, on, groupBy, orderBy, asc, desc, limit, offset , sub_select, sub_selectDistinct, (^.), (?.) - , val, isNothing, just, nothing, countRows, not_ + , val, isNothing, just, nothing, countRows, count, not_ , (==.), (>=.), (>.), (<=.), (<.), (!=.), (&&.), (||.) , (+.), (-.), (/.), (*.) , like, (%), concat_, (++.) diff --git a/src/Database/Esqueleto/Internal/Language.hs b/src/Database/Esqueleto/Internal/Language.hs index 7e54fd7..c6305b3 100644 --- a/src/Database/Esqueleto/Internal/Language.hs +++ b/src/Database/Esqueleto/Internal/Language.hs @@ -207,6 +207,9 @@ class (Functor query, Applicative query, Monad query) => -- | @COUNT(*)@ value. countRows :: Num a => expr (Value a) + -- | @COUNT@. + count :: (Num a) => expr (Value typ) -> expr (Value a) + not_ :: expr (Value Bool) -> expr (Value Bool) (==.) :: PersistField typ => expr (Value typ) -> expr (Value typ) -> expr (Value Bool) diff --git a/src/Database/Esqueleto/Internal/Sql.hs b/src/Database/Esqueleto/Internal/Sql.hs index 28ea389..02cd4dc 100644 --- a/src/Database/Esqueleto/Internal/Sql.hs +++ b/src/Database/Esqueleto/Internal/Sql.hs @@ -306,6 +306,8 @@ instance Esqueleto SqlQuery SqlExpr SqlBackend where just (ERaw p f) = ERaw p f nothing = unsafeSqlValue "NULL" countRows = unsafeSqlValue "COUNT(*)" + count (ERaw _ f) = ERaw Never $ \conn -> let (b, _vals) = f conn + in ("COUNT" <> parens b, []) not_ (ERaw p f) = ERaw Never $ \conn -> let (b, vals) = f conn in ("NOT " <> parensM p b, vals) diff --git a/test/Test.hs b/test/Test.hs index 532b434..bfde6c8 100644 --- a/test/Test.hs +++ b/test/Test.hs @@ -495,6 +495,24 @@ main = do , Entity p3k p3 { personAge = Just 7 } , Entity p2k p2 { personAge = Just 0 } ] + it "GROUP BY works with COUNT" $ + run $ do + p1k <- insert p1 + p2k <- insert p2 + p3k <- insert p3 + replicateM_ 3 (insert $ BlogPost "" p1k) + replicateM_ 7 (insert $ BlogPost "" p3k) + ret <- select $ + from $ \(p `LeftOuterJoin` b) -> do + on (p ^. PersonId ==. b ^. BlogPostAuthorId) + groupBy (p ^. PersonId) + let cnt = count (b ^. BlogPostId) + orderBy [ asc cnt ] + return (p, cnt) + liftIO $ ret `shouldBe` [ (Entity p2k p2, Value (0 :: Int)) + , (Entity p1k p1, Value 3) + , (Entity p3k p3, Value 7) ] + describe "lists of values" $ do it "IN works for valList" $ run $ do From b6fe3c0bb6b4b76b51ec5f4770c90d74fa2202b8 Mon Sep 17 00:00:00 2001 From: Mitsutoshi Aoe Date: Fri, 8 Mar 2013 10:09:30 +0900 Subject: [PATCH 2/2] Do not discard vals in count --- src/Database/Esqueleto/Internal/Sql.hs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Database/Esqueleto/Internal/Sql.hs b/src/Database/Esqueleto/Internal/Sql.hs index 02cd4dc..8dd64f4 100644 --- a/src/Database/Esqueleto/Internal/Sql.hs +++ b/src/Database/Esqueleto/Internal/Sql.hs @@ -306,8 +306,8 @@ instance Esqueleto SqlQuery SqlExpr SqlBackend where just (ERaw p f) = ERaw p f nothing = unsafeSqlValue "NULL" countRows = unsafeSqlValue "COUNT(*)" - count (ERaw _ f) = ERaw Never $ \conn -> let (b, _vals) = f conn - in ("COUNT" <> parens b, []) + count (ERaw _ f) = ERaw Never $ \conn -> let (b, vals) = f conn + in ("COUNT" <> parens b, vals) not_ (ERaw p f) = ERaw Never $ \conn -> let (b, vals) = f conn in ("NOT " <> parensM p b, vals)