persistent-mtl 0.2.2.0 → 0.3.0.0
raw patch · 6 files changed
+73/−1 lines, 6 filesdep +esqueletoPVP ok
version bump matches the API change (PVP)
Dependencies added: esqueleto
API changes (from Hackage documentation)
+ Database.Persist.Monad.Shim: unsafeLiftSql :: MonadSqlQuery m => Text -> (forall m2. MonadIO m2 => SqlPersistT m2 a) -> m a
+ Database.Persist.Monad.SqlQueryRep: [UnsafeLiftSql] :: Text -> (forall m. MonadIO m => SqlPersistT m a) -> SqlQueryRep Void a
+ Database.Persist.Monad.TestUtils: [UnsafeLiftSql] :: Text -> (forall m. MonadIO m => SqlPersistT m a) -> SqlQueryRep Void a
Files
- CHANGELOG.md +4/−0
- persistent-mtl.cabal +3/−1
- src/Database/Persist/Monad/Shim.hs +17/−0
- src/Database/Persist/Monad/SqlQueryRep.hs +8/−0
- test/Integration.hs +22/−0
- test/TestUtils/Esqueleto.hs +19/−0
CHANGELOG.md view
@@ -1,5 +1,9 @@ # Unreleased +# 0.3.0.0++* Add `unsafeLiftSql` ([#38](https://github.com/brandonchinn178/persistent-mtl/pull/38))+ # 0.2.2.0 * Fix for persistent 2.13
persistent-mtl.cabal view
@@ -5,7 +5,7 @@ -- see: https://github.com/sol/hpack name: persistent-mtl-version: 0.2.2.0+version: 0.3.0.0 synopsis: Monad transformer for the persistent API description: A monad transformer and mtl-style type class for using the persistent API directly in your monad transformer stack.@@ -69,6 +69,7 @@ MockSqlQueryT SqlQueryRepTest TestUtils.DB+ TestUtils.Esqueleto TestUtils.Match Paths_persistent_mtl hs-source-dirs:@@ -79,6 +80,7 @@ , bytestring , conduit , containers+ , esqueleto , monad-logger , persistent , persistent-mtl
src/Database/Persist/Monad/Shim.hs view
@@ -13,6 +13,7 @@ {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE GADTs #-} {-# LANGUAGE PatternSynonyms #-}+{-# LANGUAGE RankNTypes #-} module Database.Persist.Monad.Shim where @@ -515,6 +516,22 @@ => IsolationLevel -> m () transactionUndoWithIsolation a1 = runQueryRep $ TransactionUndoWithIsolation a1 #endif++-- | Lift an arbitrary 'SqlPersistT' action into 'MonadSqlQuery'.+--+-- This is unsafe because the action may be rerun. This function should+-- primarily be used to interop with other libraries built on top of+-- persistent.+--+-- Example usage:+--+-- @+-- -- | Run an esqueleto select.+-- select :: (MonadSqlQuery m, E.SqlSelect a r) => E.SqlQuery a -> m [r]+-- select q = unsafeLiftSql "esqueleto-select" (E.select q)+-- @+unsafeLiftSql :: MonadSqlQuery m => Text -> (forall m2. MonadIO m2 => SqlPersistT m2 a) -> m a+unsafeLiftSql label action = runQueryRep $ UnsafeLiftSql label action {- Helpers -}
src/Database/Persist/Monad/SqlQueryRep.hs view
@@ -15,6 +15,7 @@ {-# LANGUAGE GADTs #-} {-# LANGUAGE LambdaCase #-} {-# LANGUAGE PatternSynonyms #-}+{-# LANGUAGE RankNTypes #-} {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE TypeApplications #-} @@ -31,6 +32,7 @@ import Data.Map (Map) import Data.Proxy (Proxy(..)) import Data.Text (Text)+import qualified Data.Text as Text import Data.Typeable (Typeable, eqT, typeRep, (:~:)(..)) import Data.Void (Void) import Database.Persist.Sql as Persist hiding (pattern Update)@@ -440,6 +442,10 @@ => IsolationLevel -> SqlQueryRep Void () #endif + -- | Constructor for lifting an arbitrary SqlPersistT action into SqlQueryRep.+ UnsafeLiftSql+ :: Text -> (forall m. MonadIO m => Persist.SqlPersistT m a) -> SqlQueryRep Void a+ instance Typeable record => Show (SqlQueryRep record a) where show = \case Get{} -> "Get{..}" ++ record@@ -546,6 +552,7 @@ #if MIN_VERSION_persistent(2,9,0) TransactionUndoWithIsolation{} -> "TransactionUndoWithIsolation{..}" ++ record #endif+ UnsafeLiftSql label _ -> "UnsafeLiftSql{" ++ Text.unpack label ++ "}" where record = case recordTypeRep of Just recordType -> "<" ++ show recordType ++ ">"@@ -662,3 +669,4 @@ #if MIN_VERSION_persistent(2,9,0) TransactionUndoWithIsolation a1 -> Persist.transactionUndoWithIsolation a1 #endif+ UnsafeLiftSql _ action -> action
test/Integration.hs view
@@ -15,6 +15,11 @@ import Data.Text (Text) import qualified Data.Text as Text import Data.Typeable (Typeable)+#if MIN_VERSION_esqueleto(3,5,0)+import qualified Database.Esqueleto.Experimental as E+#else+import qualified Database.Esqueleto as E+#endif import Database.Persist.Sql ( Entity(..) , Migration@@ -48,6 +53,7 @@ import Database.Persist.Monad import Example import TestUtils.DB (BackendType(..), allBackendTypes)+import TestUtils.Esqueleto (esqueletoSelect) import TestUtils.Match (Match(..), (@?~)) tests :: TestTree@@ -59,6 +65,7 @@ [ testWithTransaction backendType , testComposability backendType , testPersistentAPI backendType+ , testInterop backendType ] testWithTransaction :: BackendType -> TestTree@@ -820,6 +827,21 @@ getPeopleNames result @?= [] #endif+ ]++testInterop :: BackendType -> TestTree+testInterop backendType = testGroup "Interop with third-party Persistent libraries"+ [ testCase "unsafeLiftSql" $ do+ let alice = person "Alice"+ result <- runTestApp backendType $ do+ insert_ alice+ esqueletoSelect $+#if MIN_VERSION_esqueleto(3,5,0)+ E.from $ E.table @Person+#else+ E.from $ \p -> return p+#endif+ result @?= [Entity 1 alice] ] {- Persistent helpers -}
+ test/TestUtils/Esqueleto.hs view
@@ -0,0 +1,19 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE OverloadedStrings #-}++module TestUtils.Esqueleto+ ( esqueletoSelect+ ) where++#if MIN_VERSION_esqueleto(3,5,0)+import qualified Database.Esqueleto.Experimental as E+import qualified Database.Esqueleto.Internal.Internal as E+#else+import qualified Database.Esqueleto as E+import qualified Database.Esqueleto.Internal.Sql as E+#endif++import Database.Persist.Monad (MonadSqlQuery, unsafeLiftSql)++esqueletoSelect :: (MonadSqlQuery m, E.SqlSelect a r) => E.SqlQuery a -> m [r]+esqueletoSelect q = unsafeLiftSql "esqueleto-select" (E.select q)