esqueleto 1.0.3 → 1.0.5
raw patch · 5 files changed
+69/−18 lines, 5 filesdep ~persistentPVP: major bump suggested
API removals or changes: PVP suggests a major version bump
Dependency ranges changed: persistent
API changes (from Hackage documentation)
+ Database.Esqueleto: count :: (Esqueleto query expr backend, Num a) => expr (Value typ) -> expr (Value a)
+ Database.Esqueleto: deleteCount :: (MonadLogger m, MonadResourceBase m) => SqlQuery () -> SqlPersist m Int64
+ Database.Esqueleto: updateCount :: (MonadLogger m, MonadResourceBase m, SqlEntity val) => (SqlExpr (Entity val) -> SqlQuery ()) -> SqlPersist m Int64
+ Database.Esqueleto.Internal.Language: count :: (Esqueleto query expr backend, Num a) => expr (Value typ) -> expr (Value a)
+ Database.Esqueleto.Internal.Sql: deleteCount :: (MonadLogger m, MonadResourceBase m) => SqlQuery () -> SqlPersist m Int64
+ Database.Esqueleto.Internal.Sql: updateCount :: (MonadLogger m, MonadResourceBase m, SqlEntity val) => (SqlExpr (Entity val) -> SqlQuery ()) -> SqlPersist m Int64
- Database.Esqueleto.Internal.Sql: rawExecute :: (MonadLogger m, MonadResourceBase m) => Mode -> SqlQuery () -> SqlPersist m ()
+ Database.Esqueleto.Internal.Sql: rawExecute :: (MonadLogger m, MonadResourceBase m) => Mode -> SqlQuery () -> SqlPersist m Int64
Files
- esqueleto.cabal +2/−2
- src/Database/Esqueleto.hs +3/−1
- src/Database/Esqueleto/Internal/Language.hs +3/−0
- src/Database/Esqueleto/Internal/Sql.hs +27/−6
- test/Test.hs +34/−9
esqueleto.cabal view
@@ -1,5 +1,5 @@ name: esqueleto-version: 1.0.3+version: 1.0.5 synopsis: Bare bones, type-safe EDSL for SQL queries on persistent backends. homepage: https://github.com/meteficha/esqueleto license: BSD3@@ -55,7 +55,7 @@ build-depends: base >= 4.5 && < 4.7 , text == 0.11.*- , persistent == 1.1.*+ , persistent >= 1.1.5 && < 1.2 , transformers >= 0.2 , unordered-containers >= 0.2
src/Database/Esqueleto.hs view
@@ -20,7 +20,7 @@ -- * @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_, (++.)@@ -48,7 +48,9 @@ , selectSource , selectDistinctSource , delete+ , deleteCount , update+ , updateCount -- * Helpers , valkey
src/Database/Esqueleto/Internal/Language.hs view
@@ -207,6 +207,9 @@ -- | @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)
src/Database/Esqueleto/Internal/Sql.hs view
@@ -20,7 +20,9 @@ , selectDistinct , selectDistinctSource , delete+ , deleteCount , update+ , updateCount -- * The guts , unsafeSqlBinOp , unsafeSqlValue@@ -38,7 +40,7 @@ import Control.Applicative (Applicative(..), (<$>), (<$)) import Control.Arrow ((***), first) import Control.Exception (throw, throwIO)-import Control.Monad ((>=>), ap, MonadPlus(..))+import Control.Monad ((>=>), ap, void, MonadPlus(..)) import Control.Monad.IO.Class (MonadIO(..)) import Control.Monad.Logger (MonadLogger) import Control.Monad.Trans.Class (lift)@@ -49,7 +51,7 @@ import Database.Persist.EntityDef import Database.Persist.GenericSql import Database.Persist.GenericSql.Internal (Connection(escapeName, noLimit))-import Database.Persist.GenericSql.Raw (execute, SqlBackend, withStmt)+import Database.Persist.GenericSql.Raw (executeCount, SqlBackend, withStmt) import Database.Persist.Store hiding (delete) import qualified Control.Monad.Trans.Reader as R import qualified Control.Monad.Trans.State as S@@ -304,6 +306,8 @@ 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, vals) not_ (ERaw p f) = ERaw Never $ \conn -> let (b, vals) = f conn in ("NOT " <> parensM p b, vals)@@ -589,10 +593,10 @@ , MonadResourceBase m ) => Mode -> SqlQuery ()- -> SqlPersist m ()+ -> SqlPersist m Int64 rawExecute mode query = do conn <- SqlPersist R.ask- uncurry execute $+ uncurry executeCount $ first builderToText $ toRawSql mode conn query @@ -623,9 +627,17 @@ , MonadResourceBase m ) => SqlQuery () -> SqlPersist m ()-delete = rawExecute DELETE+delete = void . deleteCount +-- | Same as 'delete', but returns the number of rows affected.+deleteCount :: ( MonadLogger m+ , MonadResourceBase m )+ => SqlQuery ()+ -> SqlPersist m Int64+deleteCount = rawExecute DELETE++ -- | Execute an @esqueleto@ @UPDATE@ query inside @persistent@'s -- 'SqlPersist' monad. Note that currently there are no type -- checks for statements that should not appear on a @UPDATE@@@ -643,7 +655,16 @@ , SqlEntity val ) => (SqlExpr (Entity val) -> SqlQuery ()) -> SqlPersist m ()-update = rawExecute UPDATE . from+update = void . updateCount+++-- | Same as 'update', but returns the number of rows affected.+updateCount :: ( MonadLogger m+ , MonadResourceBase m+ , SqlEntity val )+ => (SqlExpr (Entity val) -> SqlQuery ())+ -> SqlPersist m Int64+updateCount = rawExecute UPDATE . from ----------------------------------------------------------------------
test/Test.hs view
@@ -434,19 +434,22 @@ p1e <- insert' p1 p2e <- insert' p2 p3e <- insert' p3- ret1 <- select $- from $ \p -> do- orderBy [asc (p ^. PersonName)]- return p+ let getAll = select $+ from $ \p -> do+ orderBy [asc (p ^. PersonName)]+ return p+ ret1 <- getAll liftIO $ ret1 `shouldBe` [ p1e, p3e, p2e ] () <- delete $ from $ \p -> where_ (p ^. PersonName ==. val (personName p1))- ret2 <- select $- from $ \p -> do- orderBy [asc (p ^. PersonName)]- return p+ ret2 <- getAll liftIO $ ret2 `shouldBe` [ p3e, p2e ]+ n <- deleteCount $+ from $ \p ->+ return ((p :: SqlExpr (Entity Person)) `seq` ())+ ret3 <- getAll+ liftIO $ (n, ret3) `shouldBe` (2, []) describe "update" $ do it "works on a simple example" $@@ -459,12 +462,16 @@ set p [ PersonName =. val anon , PersonAge *=. just (val 2) ] where_ (p ^. PersonName !=. val "Mike")+ n <- updateCount $ \p -> do+ set p [ PersonAge +=. just (val 1) ]+ where_ (p ^. PersonName !=. val "Mike") ret <- select $ from $ \p -> do orderBy [ asc (p ^. PersonName), asc (p ^. PersonAge) ] return p+ liftIO $ n `shouldBe` 2 liftIO $ ret `shouldBe` [ Entity p2k (Person anon Nothing)- , Entity p1k (Person anon (Just 72))+ , Entity p1k (Person anon (Just 73)) , Entity p3k p3 ] it "works with a subexpression having COUNT(*)" $@@ -487,6 +494,24 @@ liftIO $ ret `shouldBe` [ Entity p1k p1 { personAge = Just 3 } , 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" $