{-# LANGUAGE CPP #-}
{-# LANGUAGE OverloadedStrings #-}
module Effectful.Opaleye.Count
(
opaleyeAddCounting
, withCounts
, module PostgreSQL.Count
)
where
import Data.Map (Map)
import qualified Data.Map as Map
import qualified Data.Text as T
import Effectful
import Effectful.Dispatch.Dynamic
import Effectful.Opaleye.Effect
import Effectful.State.Static.Shared
import Numeric.Natural
import qualified Opaleye as O
import qualified Opaleye.Internal.PrimQuery as O (TableIdentifier (..))
import qualified Opaleye.Internal.Table as O
import PostgreSQL.Count
#if !MIN_VERSION_effectful_core(2,5,1)
import Control.Monad (when)
import Effectful.Dispatch.Static
import Effectful.Internal.Env
import Effectful.Internal.Monad
import GHC.Stack
#endif
opaleyeAddCounting ::
forall a es.
(HasCallStack, State SQLOperationCounts :> es) =>
Eff (Opaleye : es) a ->
Eff (Opaleye : es) a
opaleyeAddCounting :: forall a (es :: [Effect]).
(HasCallStack, State SQLOperationCounts :> es) =>
Eff (Opaleye : es) a -> Eff (Opaleye : es) a
opaleyeAddCounting = EffectHandler Opaleye (Opaleye : es)
-> Eff (Opaleye : es) a -> Eff (Opaleye : es) a
forall (e :: Effect) (es :: [Effect]) a.
(DispatchOf e ~ 'Dynamic, e :> es) =>
EffectHandler e es -> Eff es a -> Eff es a
interpose (EffectHandler Opaleye (Opaleye : es)
-> Eff (Opaleye : es) a -> Eff (Opaleye : es) a)
-> EffectHandler Opaleye (Opaleye : es)
-> Eff (Opaleye : es) a
-> Eff (Opaleye : es) a
forall a b. (a -> b) -> a -> b
$ \LocalEnv localEs (Opaleye : es)
env Opaleye (Eff localEs) a
op -> do
Opaleye (Eff localEs) a -> Eff (Opaleye : es) ()
forall b (localEs :: [Effect]).
Opaleye (Eff localEs) b -> Eff (Opaleye : es) ()
incrementOp Opaleye (Eff localEs) a
op
LocalEnv localEs (Opaleye : es)
-> Opaleye (Eff localEs) a -> Eff (Opaleye : es) a
forall (e :: Effect) (es :: [Effect]) (localEs :: [Effect])
(handlerEs :: [Effect]) a.
(HasCallStack, DispatchOf e ~ 'Dynamic, e :> es, e :> localEs) =>
LocalEnv localEs handlerEs -> e (Eff localEs) a -> Eff es a
passthrough LocalEnv localEs (Opaleye : es)
env Opaleye (Eff localEs) a
op
where
incrementOp :: forall b localEs. Opaleye (Eff localEs) b -> Eff (Opaleye : es) ()
incrementOp :: forall b (localEs :: [Effect]).
Opaleye (Eff localEs) b -> Eff (Opaleye : es) ()
incrementOp = \case
RunSelectExplicit {} -> Eff (Opaleye : es) ()
incrementSelect
RunSelectFoldExplicit {} -> Eff (Opaleye : es) ()
incrementSelect
RunInsert Insert b
ins -> TableName -> Eff (Opaleye : es) ()
forall {es :: [Effect]}.
(State SQLOperationCounts :> es) =>
TableName -> Eff es ()
incrementInsert (TableName -> Eff (Opaleye : es) ())
-> TableName -> Eff (Opaleye : es) ()
forall a b. (a -> b) -> a -> b
$ Insert b -> TableName
forall haskells. Insert haskells -> TableName
insertTableName Insert b
ins
RunDelete Delete b
del -> TableName -> Eff (Opaleye : es) ()
forall {es :: [Effect]}.
(State SQLOperationCounts :> es) =>
TableName -> Eff es ()
incrementDelete (TableName -> Eff (Opaleye : es) ())
-> TableName -> Eff (Opaleye : es) ()
forall a b. (a -> b) -> a -> b
$ Delete b -> TableName
forall haskells. Delete haskells -> TableName
deleteTableName Delete b
del
RunUpdate Update b
upd -> TableName -> Eff (Opaleye : es) ()
forall {es :: [Effect]}.
(State SQLOperationCounts :> es) =>
TableName -> Eff es ()
incrementUpdate (TableName -> Eff (Opaleye : es) ())
-> TableName -> Eff (Opaleye : es) ()
forall a b. (a -> b) -> a -> b
$ Update b -> TableName
forall haskells. Update haskells -> TableName
updateTableName Update b
upd
incrementMap :: TableName -> Map TableName Natural -> Map TableName Natural
incrementMap :: TableName -> Map TableName Natural -> Map TableName Natural
incrementMap = (Maybe Natural -> Maybe Natural)
-> TableName -> Map TableName Natural -> Map TableName Natural
forall k a.
Ord k =>
(Maybe a -> Maybe a) -> k -> Map k a -> Map k a
Map.alter (Natural -> Maybe Natural
forall a. a -> Maybe a
Just (Natural -> Maybe Natural)
-> (Maybe Natural -> Natural) -> Maybe Natural -> Maybe Natural
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Natural -> (Natural -> Natural) -> Maybe Natural -> Natural
forall b a. b -> (a -> b) -> Maybe a -> b
maybe Natural
1 Natural -> Natural
forall a. Enum a => a -> a
succ)
incrementSelect :: Eff (Opaleye : es) ()
incrementSelect = (SQLOperationCounts -> SQLOperationCounts) -> Eff (Opaleye : es) ()
forall s (es :: [Effect]). (State s :> es) => (s -> s) -> Eff es ()
modify ((SQLOperationCounts -> SQLOperationCounts)
-> Eff (Opaleye : es) ())
-> (SQLOperationCounts -> SQLOperationCounts)
-> Eff (Opaleye : es) ()
forall a b. (a -> b) -> a -> b
$ \SQLOperationCounts
counts ->
SQLOperationCounts
counts {sqlSelects = succ $ sqlSelects counts}
incrementInsert :: TableName -> Eff es ()
incrementInsert TableName
name = (SQLOperationCounts -> SQLOperationCounts) -> Eff es ()
forall s (es :: [Effect]). (State s :> es) => (s -> s) -> Eff es ()
modify ((SQLOperationCounts -> SQLOperationCounts) -> Eff es ())
-> (SQLOperationCounts -> SQLOperationCounts) -> Eff es ()
forall a b. (a -> b) -> a -> b
$ \SQLOperationCounts
counts ->
SQLOperationCounts
counts {sqlInserts = incrementMap name $ sqlInserts counts}
incrementUpdate :: TableName -> Eff es ()
incrementUpdate TableName
name = (SQLOperationCounts -> SQLOperationCounts) -> Eff es ()
forall s (es :: [Effect]). (State s :> es) => (s -> s) -> Eff es ()
modify ((SQLOperationCounts -> SQLOperationCounts) -> Eff es ())
-> (SQLOperationCounts -> SQLOperationCounts) -> Eff es ()
forall a b. (a -> b) -> a -> b
$ \SQLOperationCounts
counts ->
SQLOperationCounts
counts {sqlUpdates = incrementMap name $ sqlUpdates counts}
incrementDelete :: TableName -> Eff es ()
incrementDelete TableName
name = (SQLOperationCounts -> SQLOperationCounts) -> Eff es ()
forall s (es :: [Effect]). (State s :> es) => (s -> s) -> Eff es ()
modify ((SQLOperationCounts -> SQLOperationCounts) -> Eff es ())
-> (SQLOperationCounts -> SQLOperationCounts) -> Eff es ()
forall a b. (a -> b) -> a -> b
$ \SQLOperationCounts
counts ->
SQLOperationCounts
counts {sqlDeletes = incrementMap name $ sqlDeletes counts}
withCounts ::
(State SQLOperationCounts :> es) =>
Eff es a ->
Eff es (SQLOperationCounts, a)
withCounts :: forall (es :: [Effect]) a.
(State SQLOperationCounts :> es) =>
Eff es a -> Eff es (SQLOperationCounts, a)
withCounts Eff es a
eff = do
SQLOperationCounts
countsBefore <- Eff es SQLOperationCounts
forall s (es :: [Effect]). (State s :> es) => Eff es s
get
a
res <- Eff es a
eff
SQLOperationCounts
countsAfter <- Eff es SQLOperationCounts
forall s (es :: [Effect]). (State s :> es) => Eff es s
get
(SQLOperationCounts, a) -> Eff es (SQLOperationCounts, a)
forall a. a -> Eff es a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (SQLOperationCounts
countsAfter SQLOperationCounts -> SQLOperationCounts -> SQLOperationCounts
`subtractCounts` SQLOperationCounts
countsBefore, a
res)
#if !MIN_VERSION_effectful_core(2,5,1)
passthrough ::
(HasCallStack, DispatchOf e ~ Dynamic, e :> es, e :> localEs) =>
LocalEnv localEs handlerEs ->
e (Eff localEs) a ->
Eff es a
passthrough :: forall (e :: Effect) (es :: [Effect]) (localEs :: [Effect])
(handlerEs :: [Effect]) a.
(HasCallStack, DispatchOf e ~ 'Dynamic, e :> es, e :> localEs) =>
LocalEnv localEs handlerEs -> e (Eff localEs) a -> Eff es a
passthrough (LocalEnv Env localEs
les) e (Eff localEs) a
op = (Env es -> IO a) -> Eff es a
forall (es :: [Effect]) a. (Env es -> IO a) -> Eff es a
unsafeEff ((Env es -> IO a) -> Eff es a) -> (Env es -> IO a) -> Eff es a
forall a b. (a -> b) -> a -> b
$ \Env es
es -> do
Handler Env handlerEs
handlerEs EffectHandler e handlerEs
handler <- Env es -> IO (EffectRep (DispatchOf e) e)
forall (e :: Effect) (es :: [Effect]).
(e :> es) =>
Env es -> IO (EffectRep (DispatchOf e) e)
getEnv Env es
es
Bool -> IO () -> IO ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (Env localEs -> IORef' Storage
forall (es :: [Effect]). Env es -> IORef' Storage
envStorage Env localEs
les IORef' Storage -> IORef' Storage -> Bool
forall a. Eq a => a -> a -> Bool
/= Env handlerEs -> IORef' Storage
forall (es :: [Effect]). Env es -> IORef' Storage
envStorage Env handlerEs
handlerEs) (IO () -> IO ()) -> IO () -> IO ()
forall a b. (a -> b) -> a -> b
$ do
[Char] -> IO ()
forall a. HasCallStack => [Char] -> a
error [Char]
"les and handlerEs point to different Storages"
Eff handlerEs a -> Env handlerEs -> IO a
forall (es :: [Effect]) a. Eff es a -> Env es -> IO a
unEff ((HasCallStack =>
LocalEnv localEs handlerEs -> e (Eff localEs) a -> Eff handlerEs a)
-> LocalEnv localEs handlerEs
-> e (Eff localEs) a
-> Eff handlerEs a
forall a. HasCallStack => (HasCallStack => a) -> a
withFrozenCallStack HasCallStack =>
LocalEnv localEs handlerEs -> e (Eff localEs) a -> Eff handlerEs a
LocalEnv localEs handlerEs -> e (Eff localEs) a -> Eff handlerEs a
EffectHandler e handlerEs
handler (Env localEs -> LocalEnv localEs handlerEs
forall (localEs :: [Effect]) (handlerEs :: [Effect]).
Env localEs -> LocalEnv localEs handlerEs
LocalEnv Env localEs
les) e (Eff localEs) a
op) Env handlerEs
handlerEs
{-# NOINLINE passthrough #-}
#endif
tableIdentifierToTableName :: O.TableIdentifier -> TableName
tableIdentifierToTableName :: TableIdentifier -> TableName
tableIdentifierToTableName (O.TableIdentifier Maybe [Char]
mSchema [Char]
table) =
Maybe Text -> Text -> TableName
TableName ([Char] -> Text
T.pack ([Char] -> Text) -> Maybe [Char] -> Maybe Text
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Maybe [Char]
mSchema) ([Char] -> Text
T.pack [Char]
table)
insertTableName :: O.Insert haskells -> TableName
insertTableName :: forall haskells. Insert haskells -> TableName
insertTableName (O.Insert Table fieldsW fieldsR
table [fieldsW]
_ Returning fieldsR haskells
_ Maybe OnConflict
_) =
TableIdentifier -> TableName
tableIdentifierToTableName (TableIdentifier -> TableName)
-> (Table fieldsW fieldsR -> TableIdentifier)
-> Table fieldsW fieldsR
-> TableName
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Table fieldsW fieldsR -> TableIdentifier
forall writeColumns viewColumns.
Table writeColumns viewColumns -> TableIdentifier
O.tableIdentifier (Table fieldsW fieldsR -> TableName)
-> Table fieldsW fieldsR -> TableName
forall a b. (a -> b) -> a -> b
$ Table fieldsW fieldsR
table
updateTableName :: O.Update haskells -> TableName
updateTableName :: forall haskells. Update haskells -> TableName
updateTableName (O.Update Table fieldsW fieldsR
table fieldsR -> fieldsW
_ fieldsR -> Field SqlBool
_ Returning fieldsR haskells
_) =
TableIdentifier -> TableName
tableIdentifierToTableName (TableIdentifier -> TableName)
-> (Table fieldsW fieldsR -> TableIdentifier)
-> Table fieldsW fieldsR
-> TableName
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Table fieldsW fieldsR -> TableIdentifier
forall writeColumns viewColumns.
Table writeColumns viewColumns -> TableIdentifier
O.tableIdentifier (Table fieldsW fieldsR -> TableName)
-> Table fieldsW fieldsR -> TableName
forall a b. (a -> b) -> a -> b
$ Table fieldsW fieldsR
table
deleteTableName :: O.Delete haskells -> TableName
deleteTableName :: forall haskells. Delete haskells -> TableName
deleteTableName (O.Delete Table fieldsW fieldsR
table fieldsR -> Field SqlBool
_ Returning fieldsR haskells
_) =
TableIdentifier -> TableName
tableIdentifierToTableName (TableIdentifier -> TableName)
-> (Table fieldsW fieldsR -> TableIdentifier)
-> Table fieldsW fieldsR
-> TableName
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Table fieldsW fieldsR -> TableIdentifier
forall writeColumns viewColumns.
Table writeColumns viewColumns -> TableIdentifier
O.tableIdentifier (Table fieldsW fieldsR -> TableName)
-> Table fieldsW fieldsR -> TableName
forall a b. (a -> b) -> a -> b
$ Table fieldsW fieldsR
table