module Database.Bolt.Connection where import Database.Bolt.Connection.Pipe import Database.Bolt.Connection.Instances import Database.Bolt.Connection.Type import Database.Bolt.Value.Type import Database.Bolt.Record import Control.Monad (when) import Control.Monad.IO.Class (MonadIO (..)) import Control.Monad.Trans.Reader (ReaderT (..), ask, runReaderT) import Data.Text (Text) import Data.Map.Strict (Map, empty) -- |Monad Transformer to do all BOLT actions in type BoltActionT = ReaderT Pipe -- |Runs BOLT action on selected pipe run :: Pipe -> BoltActionT m a -> m a run = flip runReaderT -- |Runs Cypher query with parameters and returns list of obtained 'Record's queryP :: MonadIO m => Text -> Map Text Value -> BoltActionT m [Record] queryP cypher params = pullRequests >>= toRecords where pullRequests :: MonadIO m => BoltActionT m [Response] pullRequests = do pipe <- ask let request = RequestRun cypher params flush pipe request status <- fetch pipe if isSuccess status then do flush pipe RequestPullAll (status:) <$> pullRest pipe else do ackFailure pipe return [status] pullRest :: MonadIO m => Pipe -> m [Response] pullRest pipe = do resp <- fetch pipe if isSuccess resp then return [resp] else (resp:) <$> pullRest pipe -- |Runs Cypher query and returns list of obtained 'Record's query :: MonadIO m => Text -> BoltActionT m [Record] query cypher = queryP cypher empty -- |Runs Cypher query with parameters and ignores response queryP_ :: MonadIO m => Text -> Map Text Value -> BoltActionT m () queryP_ cypher params = do pipe <- ask flush pipe $ RequestRun cypher params status <- fetch pipe when (isFailure status) $ do ackFailure pipe mkFailure status when (isSuccess status) $ discardAll pipe -- |Runs Cypher query and ignores response query_ :: MonadIO m => Text -> BoltActionT m () query_ cypher = queryP_ cypher empty