{-# LANGUAGE AllowAmbiguousTypes #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE FunctionalDependencies #-}
{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE UndecidableInstances #-}
module Database.Bolt.Extras.DSL.Typed.Parameters
where
import Control.Monad.IO.Class (MonadIO)
import Data.Kind (Type)
import qualified Data.Map.Strict as Map
import Data.Text (Text, pack)
import Database.Bolt (BoltActionT, IsValue (..), Record, Value, queryP)
import GHC.Stack (HasCallStack)
import GHC.TypeLits (Symbol)
import Database.Bolt.Extras.DSL.Internal.Executer (formQuery)
import Database.Bolt.Extras.DSL.Internal.Language (CypherDSL)
import Database.Bolt.Extras.DSL.Typed.Types (SymbolS (..))
newtype CypherDSLParams (params :: [(Symbol, Type)]) (a :: Type)
= CypherDSLParams (CypherDSL a)
class QueryWithParams (params :: [(Symbol, Type)]) (m :: Type -> Type) fun | params m -> fun where
collectParams :: HasCallStack => CypherDSL () -> [(Text, Value)] -> fun
instance MonadIO m => QueryWithParams '[] m (BoltActionT m [Record]) where
collectParams :: HasCallStack =>
CypherDSL () -> [(Text, Value)] -> BoltActionT m [Record]
collectParams CypherDSL ()
dsl [(Text, Value)]
params = forall (m :: * -> *).
(MonadIO m, HasCallStack) =>
Text -> Record -> BoltActionT m [Record]
queryP (CypherDSL () -> Text
formQuery CypherDSL ()
dsl) forall a b. (a -> b) -> a -> b
$ forall k a. Ord k => [(k, a)] -> Map k a
Map.fromList [(Text, Value)]
params
instance (IsValue typ, QueryWithParams rest m fun)
=> QueryWithParams ('(field, typ) ': rest) m ((SymbolS field, typ) -> fun)
where
collectParams :: HasCallStack =>
CypherDSL () -> [(Text, Value)] -> (SymbolS field, typ) -> fun
collectParams CypherDSL ()
dsl [(Text, Value)]
params (SymbolS String
s, typ
a) = forall (params :: [(Symbol, *)]) (m :: * -> *) fun.
(QueryWithParams params m fun, HasCallStack) =>
CypherDSL () -> [(Text, Value)] -> fun
collectParams @rest @m CypherDSL ()
dsl ((String -> Text
pack String
s, forall a. (IsValue a, HasCallStack) => a -> Value
toValue typ
a) forall a. a -> [a] -> [a]
: [(Text, Value)]
params)
queryWithParams
:: forall params m fun
. MonadIO m
=> QueryWithParams params m fun
=> HasCallStack
=> CypherDSLParams params ()
-> fun
queryWithParams :: forall (params :: [(Symbol, *)]) (m :: * -> *) fun.
(MonadIO m, QueryWithParams params m fun, HasCallStack) =>
CypherDSLParams params () -> fun
queryWithParams (CypherDSLParams CypherDSL ()
dsl) = forall (params :: [(Symbol, *)]) (m :: * -> *) fun.
(QueryWithParams params m fun, HasCallStack) =>
CypherDSL () -> [(Text, Value)] -> fun
collectParams @params @m CypherDSL ()
dsl []