esqueleto 1.4.2 → 1.4.3
raw patch · 5 files changed
+80/−15 lines, 5 filesPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
+ Database.Esqueleto: coalesce :: (Esqueleto query expr backend, PersistField a) => [expr (Value (Maybe a))] -> expr (Value (Maybe a))
+ Database.Esqueleto: coalesceDefault :: (Esqueleto query expr backend, PersistField a) => [expr (Value (Maybe a))] -> expr (Value a) -> expr (Value a)
+ Database.Esqueleto.Internal.Language: coalesce :: (Esqueleto query expr backend, PersistField a) => [expr (Value (Maybe a))] -> expr (Value (Maybe a))
+ Database.Esqueleto.Internal.Language: coalesceDefault :: (Esqueleto query expr backend, PersistField a) => [expr (Value (Maybe a))] -> expr (Value a) -> expr (Value a)
Files
- esqueleto.cabal +1/−1
- src/Database/Esqueleto.hs +1/−0
- src/Database/Esqueleto/Internal/Language.hs +16/−0
- src/Database/Esqueleto/Internal/Sql.hs +3/−0
- test/Test.hs +59/−14
esqueleto.cabal view
@@ -1,5 +1,5 @@ name: esqueleto-version: 1.4.2+version: 1.4.3 synopsis: Type-safe EDSL for SQL queries on persistent backends. homepage: https://github.com/prowdsponsor/esqueleto license: BSD3
src/Database/Esqueleto.hs view
@@ -45,6 +45,7 @@ , (+.), (-.), (/.), (*.) , random_, round_, ceiling_, floor_ , min_, max_, sum_, avg_+ , coalesce, coalesceDefault , like, (%), concat_, (++.) , subList_select, subList_selectDistinct, valList , in_, notIn, exists, notExists
src/Database/Esqueleto/Internal/Language.hs view
@@ -253,6 +253,22 @@ max_ :: (PersistField a) => expr (Value a) -> expr (Value (Maybe a)) avg_ :: (PersistField a, PersistField b) => expr (Value a) -> expr (Value (Maybe b)) + -- | @COALESCE@ function. Evaluates the arguments in order and+ -- returns the value of the first non-NULL expression, or NULL+ -- (Nothing) otherwise. Some RDBMSs (such as SQLite) require+ -- at least two arguments; please refer to the appropriate+ -- documentation.+ --+ -- /Since: 1.4.3/+ coalesce :: PersistField a => [expr (Value (Maybe a))] -> expr (Value (Maybe a))++ -- | Like @coalesce@, but takes a non-nullable expression+ -- placed at the end of the expression list, which guarantees+ -- a non-NULL result.+ --+ -- /Since: 1.4.3/+ coalesceDefault :: PersistField a => [expr (Value (Maybe a))] -> expr (Value a) -> expr (Value a)+ -- | @LIKE@ operator. like :: (PersistField s, IsString s) => expr (Value s) -> expr (Value s) -> expr (Value Bool) -- | The string @'%'@. May be useful while using 'like' and
src/Database/Esqueleto/Internal/Sql.hs view
@@ -373,6 +373,9 @@ min_ = unsafeSqlFunction "MIN" max_ = unsafeSqlFunction "MAX" + coalesce = unsafeSqlFunction "COALESCE"+ coalesceDefault exprs = unsafeSqlFunction "COALESCE" . (exprs ++) . return . just+ like = unsafeSqlBinOp " LIKE " (%) = unsafeSqlValue "'%'" concat_ = unsafeSqlFunction "CONCAT"
test/Test.hs view
@@ -15,6 +15,7 @@ module Main (main) where import Control.Applicative ((<$>))+import Control.Exception (IOException) import Control.Monad (replicateM, replicateM_) import Control.Monad.IO.Class (MonadIO(liftIO)) import Control.Monad.Logger (MonadLogger(..), runStderrLoggingT, runNoLoggingT)@@ -45,6 +46,8 @@ Person name String age Int Maybe+ weight Int Maybe+ favNum Int deriving Eq Show BlogPost title String@@ -63,10 +66,11 @@ main :: IO () main = do- let p1 = Person "John" (Just 36)- p2 = Person "Rachel" Nothing- p3 = Person "Mike" (Just 17)- p4 = Person "Livia" (Just 17)+ let p1 = Person "John" (Just 36) Nothing 1+ p2 = Person "Rachel" Nothing (Just 37) 2+ p3 = Person "Mike" (Just 17) Nothing 3+ p4 = Person "Livia" (Just 17) (Just 18) 4+ p5 = Person "Mitch" Nothing Nothing 5 hspec $ do describe "select" $ do it "works for a single value" $@@ -560,6 +564,47 @@ return title liftIO $ ret `shouldBe` [ Value t1, Value t2, Value t3 ] + describe "coalesce/coalesceDefault" $ do+ it "works on a simple example" $+ run $ do+ mapM_ insert' [p1, p2, p3, p4, p5]+ ret1 <- select $+ from $ \p -> do+ orderBy [asc (p ^. PersonId)]+ return (coalesce [p ^. PersonAge, p ^. PersonWeight])+ liftIO $ ret1 `shouldBe` [ Value (Just (36 :: Int))+ , Value (Just 37)+ , Value (Just 17)+ , Value (Just 17)+ , Value Nothing+ ]++ ret2 <- select $+ from $ \p -> do+ orderBy [asc (p ^. PersonId)]+ return (coalesceDefault [p ^. PersonAge, p ^. PersonWeight] (p ^. PersonFavNum))+ liftIO $ ret2 `shouldBe` [ Value (36 :: Int)+ , Value 37+ , Value 17+ , Value 17+ , Value 5+ ]++#if defined(WITH_POSTGRESQL) || defined(WITH_MYSQL)+ it "works on PostgreSQL and MySQL with <2 arguments" $+ run $ do+ _ :: [Value (Maybe Int)] <- select $+ from $ \p -> do+ return (coalesce [p ^. PersonAge])+ return True+#else+ it "throws an exception on SQLite with <2 arguments" $+ run (select $+ from $ \p -> do+ return (coalesce [p ^. PersonAge]) :: SqlQuery (SqlExpr (Value (Maybe Int)))+ ) `shouldThrow` (\(_ :: IOException) -> True)+#endif+ describe "text functions" $ it "like, (%) and (++.) work on a simple example" $ run $ do@@ -620,21 +665,21 @@ -- matched rows, not actually changed rows. #if defined(WITH_POSTGRESQL) liftIO $ n `shouldBe` 2- liftIO $ ret `shouldBe` [ Entity p1k (Person anon (Just 73))- , Entity p2k (Person anon Nothing)+ liftIO $ ret `shouldBe` [ Entity p1k (Person anon (Just 73) Nothing 1)+ , Entity p2k (Person anon Nothing (Just 37) 2) , Entity p3k p3 ] -- MySQL: nulls appear first, and update returns actual number -- of changed rows #elif defined(WITH_MYSQL) liftIO $ n `shouldBe` 1- liftIO $ ret `shouldBe` [ Entity p2k (Person anon Nothing)- , Entity p1k (Person anon (Just 73))+ liftIO $ ret `shouldBe` [ Entity p2k (Person anon Nothing (Just 37) 2)+ , Entity p1k (Person anon (Just 73) Nothing 1) , Entity p3k p3 ] #else -- SQLite: nulls appear first, update returns matched rows. liftIO $ n `shouldBe` 2- liftIO $ ret `shouldBe` [ Entity p2k (Person anon Nothing)- , Entity p1k (Person anon (Just 73))+ liftIO $ ret `shouldBe` [ Entity p2k (Person anon Nothing (Just 37) 2)+ , Entity p1k (Person anon (Just 73) Nothing 1) , Entity p3k p3 ] #endif @@ -803,10 +848,10 @@ _ <- insert p2 _ <- insert p3 _ <- insert p4- _ <- insert $ Person "Jane" Nothing- _ <- insert $ Person "Mark" Nothing- _ <- insert $ Person "Sarah" Nothing- insert $ Person "Paul" Nothing+ _ <- insert $ Person "Jane" Nothing Nothing 0+ _ <- insert $ Person "Mark" Nothing Nothing 0+ _ <- insert $ Person "Sarah" Nothing Nothing 0+ insert $ Person "Paul" Nothing Nothing 0 ret1 <- fmap (map unValue) $ select $ from $ \p -> do orderBy [rand] return (p ^. PersonId)