From 3fcc965de704ee1d3662da3b6c2a1a514931b1c4 Mon Sep 17 00:00:00 2001 From: Matt Parsons Date: Thu, 16 Jan 2020 10:03:53 -0700 Subject: [PATCH] Group by documentation (#170) * Group by documentation --- changelog.md | 6 ++++++ esqueleto.cabal | 2 +- src/Database/Esqueleto.hs | 3 ++- src/Database/Esqueleto/Internal/Internal.hs | 19 +++++++++++++++++++ test/Common/Test.hs | 14 ++++++++++++++ 5 files changed, 42 insertions(+), 2 deletions(-) diff --git a/changelog.md b/changelog.md index 134f4ec..7fb7592 100644 --- a/changelog.md +++ b/changelog.md @@ -1,3 +1,9 @@ +3.3.1.1 +======== + +- @parsonsmatt + - [#170](https://github.com/bitemyapp/esqueleto/pull/170) Add documentation to `groupBy` to explain tuple nesting. + 3.3.1 ======== diff --git a/esqueleto.cabal b/esqueleto.cabal index e4c0b82..c785ae6 100644 --- a/esqueleto.cabal +++ b/esqueleto.cabal @@ -1,7 +1,7 @@ cabal-version: 1.12 name: esqueleto -version: 3.3.1 +version: 3.3.1.1 synopsis: Type-safe EDSL for SQL queries on persistent backends. description: @esqueleto@ is a bare bones, type-safe EDSL for SQL queries that works with unmodified @persistent@ SQL backends. Its language closely resembles SQL, so you don't have to learn new concepts, just new syntax, and it's fairly easy to predict the generated SQL and optimize it for your backend. Most kinds of errors committed when writing SQL are caught as compile-time errors---although it is possible to write type-checked @esqueleto@ queries that fail at runtime. . diff --git a/src/Database/Esqueleto.hs b/src/Database/Esqueleto.hs index 8616815..4b074d9 100644 --- a/src/Database/Esqueleto.hs +++ b/src/Database/Esqueleto.hs @@ -453,7 +453,8 @@ deleteKey = Database.Persist.delete -- 'where_' (foo '^.' FooParentId '==.' 'val' parentId) -- 'pure' (foo, bar) -- @ --- /Since: 3.1.2/ +-- +-- @since 3.1.2 associateJoin :: forall e1 e0 . Ord (Key e0) diff --git a/src/Database/Esqueleto/Internal/Internal.hs b/src/Database/Esqueleto/Internal/Internal.hs index f36f467..1559f5d 100644 --- a/src/Database/Esqueleto/Internal/Internal.hs +++ b/src/Database/Esqueleto/Internal/Internal.hs @@ -213,6 +213,25 @@ on expr = Q $ W.tell mempty { sdFromClause = [OnClause expr] } -- print name -- print (count :: Int) -- @ +-- +-- === Need more columns? +-- +-- The 'ToSomeValues' class is defined for 'SqlExpr' and tuples of 'SqlExpr's. +-- We only have definitions for up to 8 elements in a tuple right now, so it's +-- possible that you may need to have more than 8 elements. +-- +-- For example, consider a query with a 'groupBy' call like this: +-- +-- @ +-- groupBy (e0, e1, e2, e3, e4, e5, e6, e7) +-- @ +-- +-- This is the biggest you can get with a single tuple. However, you can easily +-- nest the tuples to add more: +-- +-- @ +-- groupBy ((e0, e1, e2, e3, e4, e5, e6, e7), e8, e9) +-- @ groupBy :: (ToSomeValues a) => a -> SqlQuery () groupBy expr = Q $ W.tell mempty { sdGroupByClause = GroupBy $ toSomeValues expr } diff --git a/test/Common/Test.hs b/test/Common/Test.hs index b9e71bf..4ca1c1f 100644 --- a/test/Common/Test.hs +++ b/test/Common/Test.hs @@ -1355,6 +1355,20 @@ testUpdate run = do liftIO $ ret `shouldMatchList` [ (Value l3k, Value 7) , (Value l1k, Value 3) ] + it "GROUP BY works with nested tuples" $ do + run $ do + l1k <- insert l1 + l3k <- insert l3 + mapM_ (\k -> insert $ Deed k l1k) (map show [1..3 :: Int]) + + mapM_ (\k -> insert $ Deed k l3k) (map show [4..10 :: Int]) + + (ret :: [(Value (Key Lord), Value Int)]) <- select $ from $ + \ ( lord `InnerJoin` deed ) -> do + on $ lord ^. LordId ==. deed ^. DeedOwnerId + groupBy ((lord ^. LordId, lord ^. LordDogs), deed ^. DeedContract) + return (lord ^. LordId, count $ deed ^. DeedId) + liftIO $ length ret `shouldBe` 10 it "GROUP BY works with HAVING" $ run $ do p1k <- insert p1