module Database.Persist.Class.PersistStore
( HasPersistBackend (..)
, liftPersist
, PersistStore (..)
, getJust
, belongsTo
, belongsToJust
, insertEntity
, ToBackendKey(..)
) where
import qualified Data.Text as T
import Control.Monad.IO.Class (MonadIO, liftIO)
import Control.Exception.Lifted (throwIO)
import Control.Monad.Trans.Reader (ReaderT)
import Control.Monad.Reader (MonadReader (ask), runReaderT)
import Database.Persist.Class.PersistEntity
import Database.Persist.Class.PersistField
import Database.Persist.Types
import qualified Data.Aeson as A
class HasPersistBackend env backend | env -> backend where
persistBackend :: env -> backend
liftPersist :: (MonadReader env m, HasPersistBackend env backend, MonadIO m)
=> ReaderT backend IO a
-> m a
liftPersist f = do
env <- ask
liftIO $ runReaderT f (persistBackend env)
class ( PersistEntity record
, PersistEntityBackend record ~ backend
, PersistStore backend
) => ToBackendKey backend record where
toBackendKey :: Key record -> BackendKey backend
fromBackendKey :: BackendKey backend -> Key record
class
( Show (BackendKey backend), Read (BackendKey backend)
, Eq (BackendKey backend), Ord (BackendKey backend)
, PersistField (BackendKey backend), A.ToJSON (BackendKey backend), A.FromJSON (BackendKey backend)
) => PersistStore backend where
data BackendKey backend
get :: (MonadIO m, backend ~ PersistEntityBackend val, PersistEntity val)
=> Key val -> ReaderT backend m (Maybe val)
insert :: (MonadIO m, backend ~ PersistEntityBackend val, PersistEntity val)
=> val -> ReaderT backend m (Key val)
insert_ :: (MonadIO m, backend ~ PersistEntityBackend val, PersistEntity val)
=> val -> ReaderT backend m ()
insert_ val = insert val >> return ()
insertMany :: (MonadIO m, backend ~ PersistEntityBackend val, PersistEntity val)
=> [val] -> ReaderT backend m [Key val]
insertMany = mapM insert
insertMany_ :: (MonadIO m, backend ~ PersistEntityBackend val, PersistEntity val)
=> [val] -> ReaderT backend m ()
insertMany_ x = insertMany x >> return ()
insertEntityMany :: (MonadIO m, backend ~ PersistEntityBackend val, PersistEntity val)
=> [Entity val] -> ReaderT backend m ()
insertEntityMany = mapM_ (\(Entity k record) -> insertKey k record)
insertKey :: (MonadIO m, backend ~ PersistEntityBackend val, PersistEntity val)
=> Key val -> val -> ReaderT backend m ()
repsert :: (MonadIO m, backend ~ PersistEntityBackend val, PersistEntity val)
=> Key val -> val -> ReaderT backend m ()
replace :: (MonadIO m, backend ~ PersistEntityBackend val, PersistEntity val)
=> Key val -> val -> ReaderT backend m ()
delete :: (MonadIO m, backend ~ PersistEntityBackend val, PersistEntity val)
=> Key val -> ReaderT backend m ()
update :: (MonadIO m, PersistEntity val, backend ~ PersistEntityBackend val)
=> Key val -> [Update val] -> ReaderT backend m ()
updateGet :: (MonadIO m, PersistEntity val, backend ~ PersistEntityBackend val)
=> Key val -> [Update val] -> ReaderT backend m val
updateGet key ups = do
update key ups
get key >>= maybe (liftIO $ throwIO $ KeyNotFound $ show key) return
getJust :: ( PersistStore backend
, PersistEntity val
, Show (Key val)
, backend ~ PersistEntityBackend val
, MonadIO m
) => Key val -> ReaderT backend m val
getJust key = get key >>= maybe
(liftIO $ throwIO $ PersistForeignConstraintUnmet $ T.pack $ show key)
return
belongsTo ::
( PersistStore backend
, PersistEntity ent1
, PersistEntity ent2
, backend ~ PersistEntityBackend ent2
, MonadIO m
) => (ent1 -> Maybe (Key ent2)) -> ent1 -> ReaderT backend m (Maybe ent2)
belongsTo foreignKeyField model = case foreignKeyField model of
Nothing -> return Nothing
Just f -> get f
belongsToJust ::
( PersistStore backend
, PersistEntity ent1
, PersistEntity ent2
, backend ~ PersistEntityBackend ent2
, MonadIO m
)
=> (ent1 -> Key ent2) -> ent1 -> ReaderT backend m ent2
belongsToJust getForeignKey model = getJust $ getForeignKey model
insertEntity ::
( PersistStore backend
, PersistEntity e
, backend ~ PersistEntityBackend e
, MonadIO m
) => e -> ReaderT backend m (Entity e)
insertEntity e = do
eid <- insert e
return $ Entity eid e