Merge pull request #28 from bitemyapp/fix-group-by-composite-key

Fixing composite key support for group by
This commit is contained in:
Chris Allen 2017-05-25 11:51:56 -05:00 committed by GitHub
commit ee4d0d5e35
6 changed files with 74 additions and 6 deletions

20
.editorconfig Normal file
View File

@ -0,0 +1,20 @@
# http://editorconfig.org
root = true
[Makefile]
indent_style = tabs
indent_size = 8
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
[*.{hs,md,php}]
indent_style = space
indent_size = 2
tab_width = 2
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
max_line_length = 80

View File

@ -5,3 +5,12 @@ build-7.10:
build-8.0: build-8.0:
STACK_YAML="stack-8.0.yaml" stack build STACK_YAML="stack-8.0.yaml" stack build
ghci:
stack ghci
test:
stack test
test-ghci:
stack ghci esqueleto:test:test

View File

@ -76,7 +76,6 @@ import qualified Data.Text.Lazy.Builder as TLB
import Database.Esqueleto.Internal.Language import Database.Esqueleto.Internal.Language
-- | SQL backend for @esqueleto@ using 'SqlPersistT'. -- | SQL backend for @esqueleto@ using 'SqlPersistT'.
newtype SqlQuery a = newtype SqlQuery a =
Q { unQ :: W.WriterT SideData (S.State IdentState) a } Q { unQ :: W.WriterT SideData (S.State IdentState) a }
@ -1099,13 +1098,19 @@ makeGroupBy :: IdentInfo -> GroupByClause -> (TLB.Builder, [PersistValue])
makeGroupBy _ (GroupBy []) = (mempty, []) makeGroupBy _ (GroupBy []) = (mempty, [])
makeGroupBy info (GroupBy fields) = first ("\nGROUP BY " <>) build makeGroupBy info (GroupBy fields) = first ("\nGROUP BY " <>) build
where where
build = uncommas' $ map (\(SomeValue (ERaw _ f)) -> f info) fields build :: (TLB.Builder, [PersistValue])
build = uncommas' $ map match fields
match :: SomeValue SqlExpr -> (TLB.Builder, [PersistValue])
match (SomeValue (ERaw _ f)) = f info
match (SomeValue (ECompositeKey f)) = (mconcat $ f info, mempty)
makeHaving :: IdentInfo -> WhereClause -> (TLB.Builder, [PersistValue]) makeHaving :: IdentInfo -> WhereClause -> (TLB.Builder, [PersistValue])
makeHaving _ NoWhere = mempty makeHaving _ NoWhere = mempty
makeHaving info (Where (ERaw _ f)) = first ("\nHAVING " <>) (f info) makeHaving info (Where (ERaw _ f)) = first ("\nHAVING " <>) (f info)
makeHaving _ (Where (ECompositeKey _ )) = unexpectedCompositeKeyError "makeHaving" makeHaving _ (Where (ECompositeKey _)) = unexpectedCompositeKeyError "makeHaving"
-- makeHaving, makeWhere and makeOrderBy
makeOrderBy :: IdentInfo -> [OrderByClause] -> (TLB.Builder, [PersistValue]) makeOrderBy :: IdentInfo -> [OrderByClause] -> (TLB.Builder, [PersistValue])
makeOrderBy _ [] = mempty makeOrderBy _ [] = mempty
makeOrderBy info os = first ("\nORDER BY " <>) . uncommas' $ concatMap mk os makeOrderBy info os = first ("\nORDER BY " <>) . uncommas' $ concatMap mk os

View File

@ -1,6 +1,6 @@
# resolver: nightly-2017-01-10 # resolver: nightly-2017-01-10
resolver: lts-7.16 resolver: lts-8.8
compiler: ghc-8.0.2 # compiler: ghc-8.0.2
packages: packages:
- '.' - '.'

View File

@ -1 +1 @@
stack-7.10.yaml stack-8.0.yaml

View File

@ -69,6 +69,19 @@ share [mkPersist sqlSettings, mkMigrate "migrateAll"] [persistUpperCase|
title String title String
authorId PersonId authorId PersonId
deriving Eq Show deriving Eq Show
Lord
county String
dogs Int Maybe
Primary county
deriving Show
Deed
contract String
ownerId LordId
Primary contract
deriving Show
Follow Follow
follower PersonId follower PersonId
followed PersonId followed PersonId
@ -129,6 +142,10 @@ main = do
p3 = Person "Mike" (Just 17) Nothing 3 p3 = Person "Mike" (Just 17) Nothing 3
p4 = Person "Livia" (Just 17) (Just 18) 4 p4 = Person "Livia" (Just 17) (Just 18) 4
p5 = Person "Mitch" Nothing Nothing 5 p5 = Person "Mitch" Nothing Nothing 5
l1 = Lord "Cornwall" (Just 36)
l2 = Lord "Dorset" Nothing
l3 = Lord "Chester" (Just 17)
hspec $ do hspec $ do
describe "select" $ do describe "select" $ do
it "works for a single value" $ it "works for a single value" $
@ -1069,6 +1086,23 @@ main = do
, (Entity p1k p1, Value 3) , (Entity p1k p1, Value 3)
, (Entity p3k p3, Value 7) ] , (Entity p3k p3, Value 7) ]
it "GROUP BY works with COUNT and InnerJoin" $
run $ do
l1k <- insert l1
l2k <- insert l2
l3k <- insert l3
mapM_ (\k -> insert $ Deed k l1k) (map show [1..3])
mapM_ (\k -> insert $ Deed k l3k) (map show [4..10])
(ret :: [(Value (Key Lord), Value Int)]) <- select $ from $
\ ( lord `InnerJoin` deed ) -> do
on $ lord ^. LordId ==. deed ^. DeedOwnerId
groupBy (lord ^. LordId)
return (lord ^. LordId, count $ deed ^. DeedId)
liftIO $ ret `shouldBe` [ (Value l3k, Value 7)
, (Value l1k, Value 3) ]
it "GROUP BY works with HAVING" $ it "GROUP BY works with HAVING" $
run $ do run $ do
p1k <- insert p1 p1k <- insert p1