polysemy-db-0.0.1.0: lib/Polysemy/Db/Interpreter/Query.hs
module Polysemy.Db.Interpreter.Query where
import Conc (interpretAtomic)
import qualified Data.Map.Strict as Map
import Lens.Micro.Extras (view)
import qualified Sqel.Data.Uid as Uid
import Sqel.Data.Uid (Uid (Uid))
import qualified Polysemy.Db.Data.DbError as DbError
import Polysemy.Db.Data.DbError (DbError)
import Polysemy.Db.Effect.Query (Query (..))
import qualified Polysemy.Db.Effect.Store as Store
import Polysemy.Db.Effect.Store (Store)
import Polysemy.Db.Interpreter.Store (PureStore (PureStore), interpretStoreConc)
class QueryCheckResult f where
queryCheckResult :: [a] -> Either DbError (f a)
instance QueryCheckResult Maybe where
queryCheckResult = \case
[] -> Right Nothing
[a] -> Right (Just a)
_ -> Left (DbError.Query "Multiple matches for single-result query")
instance QueryCheckResult [] where
queryCheckResult = Right
interpretQueryConst ::
Ord q =>
QueryCheckResult f =>
Map q [d] ->
InterpreterFor (Query q (f d) !! DbError) r
interpretQueryConst store =
interpretResumable \case
Query params ->
stopEither (queryCheckResult (fromMaybe [] (Map.lookup params store)))
interpretQueryAtomicState ::
∀ i a d q f r .
Member (AtomicState (PureStore i a)) r =>
QueryCheckResult f =>
(q -> Uid i a -> Maybe d) ->
InterpreterFor (Query q (f d) !! DbError) r
interpretQueryAtomicState match =
interpretResumable \case
Query q ->
stopEither =<< atomicGets (queryCheckResult . mapMaybe (match q) . Map.elems . view #records)
interpretQueryConc ::
Ord i =>
QueryCheckResult f =>
Member (Embed IO) r =>
(q -> Uid i a -> Maybe d) ->
[Uid i a] ->
InterpreterFor (Query q (f d) !! DbError) r
interpretQueryConc match initial =
interpretAtomic (PureStore (Map.fromList (initial <&> \ a@(Uid i _) -> (i, a)))) .
interpretQueryAtomicState match .
raiseUnder
interpretQueryStoreConc ::
Ord i =>
Show i =>
QueryCheckResult f =>
Member (Embed IO) r =>
(q -> Uid i a -> Maybe d) ->
[Uid i a] ->
InterpretersFor [Query q (f d) !! DbError, Store i a !! DbError, AtomicState (PureStore i a)] r
interpretQueryStoreConc match initial =
interpretStoreConc (PureStore (Map.fromList (initial <&> \ a@(Uid i _) -> (i, a)))) .
interpretQueryAtomicState match
interpretQueryStoreAny ::
∀ q d i e r .
Member (Store i d !! e) r =>
(q -> d -> Bool) ->
InterpreterFor (Query q Bool !! e) r
interpretQueryStoreAny match =
interpretResumable \case
Query q ->
any (match q . Uid.payload) <$> restop Store.fetchAll