{-# LANGUAGE RankNTypes #-} module Pipes.SQLite ( -- * Producers - turn a query into a stream of results query, query_, queryNamed, eachRow, -- * Consumers - execute a statement using upstream values as bound parameters execute, executeNamed ) where import Pipes as P import Pipes.Safe as PS import qualified Database.SQLite.Simple as SQL import Control.Monad (forever) -- | Run a parameterless query and yield each parsed row in the result. query_ :: (MonadSafe m, SQL.FromRow a) => SQL.Connection -> SQL.Query -> Producer' a m () query_ conn q = bracketIO (SQL.openStatement conn q) SQL.closeStatement eachRow -- | Run a query with parameters and yield each parsed row in the result. query :: (MonadSafe m, SQL.FromRow a, SQL.ToRow params) => SQL.Connection -> SQL.Query -> params -> Producer' a m () query conn q p = bracketIO open' SQL.closeStatement eachRow where open' = do s <- SQL.openStatement conn q SQL.bind s p return s -- | Run a query with named parameters and yield each parsed row in the result. queryNamed :: (MonadSafe m, SQL.FromRow a) => SQL.Connection -> SQL.Query -> [SQL.NamedParam] -> Producer' a m () queryNamed conn q ns = bracketIO open' SQL.closeStatement eachRow where open' = do s <- SQL.openStatement conn q SQL.bindNamed s ns return s -- | Executes the SQL statment by binding each value provided by each upstream yield. execute :: (MonadIO m, SQL.ToRow q) => SQL.Connection -> SQL.Query -> Consumer' q m b execute conn q = writeEach where writeEach = forever $ do v <- await liftIO $ SQL.execute conn q v -- | Executes the SQL statement with the set of bound parameters provided by each upstream yield. executeNamed :: MonadIO m => SQL.Connection -> SQL.Query -> Consumer' [SQL.NamedParam] m b executeNamed conn q = forever $ do v <- await liftIO $ SQL.executeNamed conn q v -- | Yields each row in the given Statement. It is assumed that the statement has already been opened. eachRow :: (MonadIO m, SQL.FromRow a) => SQL.Statement -> Producer' a m () eachRow s = do v <- liftIO (SQL.nextRow s) case v of Just z -> yield z >> eachRow s Nothing -> return () -- | Bracket a MonadSafe action with IO. bracketIO :: MonadSafe m => IO a -> (a -> IO a1) -> (a -> m c) -> m c bracketIO a b = PS.bracket (liftIO a) (liftIO . b)