mysql-simple 0.2.0.2 → 0.2.1.0
raw patch · 2 files changed
+109/−28 lines, 2 filesPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
+ Database.MySQL.Simple: fold :: (QueryParams q, QueryResults r) => Connection -> Query -> q -> a -> (a -> r -> IO a) -> IO a
+ Database.MySQL.Simple: fold_ :: QueryResults r => Connection -> Query -> a -> (a -> r -> IO a) -> IO a
+ Database.MySQL.Simple: forEach :: (QueryParams q, QueryResults r) => Connection -> Query -> q -> (r -> IO ()) -> IO ()
+ Database.MySQL.Simple: forEach_ :: QueryResults r => Connection -> Query -> (r -> IO ()) -> IO ()
Files
- Database/MySQL/Simple.hs +108/−27
- mysql-simple.cabal +1/−1
Database/MySQL/Simple.hs view
@@ -60,6 +60,11 @@ -- * Queries that return results , query , query_+ -- * Queries that stream results+ , fold+ , fold_+ , forEach+ , forEach_ -- * Statements that do not return results , execute , execute_@@ -78,14 +83,15 @@ import Blaze.ByteString.Builder (Builder, fromByteString, toByteString) import Blaze.ByteString.Builder.Char8 (fromChar) import Control.Applicative ((<$>), pure)-import Control.Exception (Exception, onException, throw)+import Control.Exception (Exception, bracket, onException, throw, throwIO) import Control.Monad.Fix (fix) import Data.ByteString (ByteString) import Data.Int (Int64) import Data.List (intersperse) import Data.Monoid (mappend, mconcat) import Data.Typeable (Typeable)-import Database.MySQL.Base (Connection)+import Database.MySQL.Base (Connection, Result)+import Database.MySQL.Base.Types (Field) import Database.MySQL.Simple.Param (Action(..), inQuotes) import Database.MySQL.Simple.QueryParams (QueryParams(..)) import Database.MySQL.Simple.QueryResults (QueryResults(..))@@ -182,13 +188,13 @@ execute :: (QueryParams q) => Connection -> Query -> q -> IO Int64 execute conn template qs = do Base.query conn =<< formatQuery conn template qs- finishExecute template conn+ finishExecute conn template -- | A version of 'execute' that does not perform query substitution. execute_ :: Connection -> Query -> IO Int64 execute_ conn q@(Query stmt) = do Base.query conn stmt- finishExecute q conn+ finishExecute conn q -- | Execute a multi-row @INSERT@, @UPDATE@, or other SQL query that is not -- expected to return results.@@ -200,21 +206,22 @@ executeMany _ _ [] = return 0 executeMany conn q qs = do Base.query conn =<< formatMany conn q qs- finishExecute q conn+ finishExecute conn q -finishExecute :: Query -> Connection -> IO Int64-finishExecute q conn = do+finishExecute :: Connection -> Query -> IO Int64+finishExecute conn q = do ncols <- Base.fieldCount (Left conn) if ncols /= 0- then throw $ QueryError ("execute resulted in " ++ show ncols ++- "-column result") q+ then throwIO $ QueryError ("execute resulted in " ++ show ncols +++ "-column result") q else Base.affectedRows conn -- | Perform a @SELECT@ or other SQL query that is expected to return--- results.+-- results. All results are retrieved and converted before this+-- function returns. ----- All results are retrieved and converted before this function--- returns.+-- When processing large results, this function will consume a lot of+-- client-side memory. Consider using 'fold' instead. -- -- Exceptions that may be thrown: --@@ -228,28 +235,102 @@ => Connection -> Query -> q -> IO [r] query conn template qs = do Base.query conn =<< formatQuery conn template qs- finishQuery template conn+ finishQuery conn template -- | A version of 'query' that does not perform query substitution. query_ :: (QueryResults r) => Connection -> Query -> IO [r] query_ conn q@(Query que) = do Base.query conn que- finishQuery q conn+ finishQuery conn q -finishQuery :: (QueryResults r) => Query -> Connection -> IO [r]-finishQuery q conn = do- r <- Base.storeResult conn+-- | Perform a @SELECT@ or other SQL query that is expected to return+-- results. Results are streamed incrementally from the server, and+-- consumed via a left fold.+--+-- The result consumer must be carefully written to execute+-- quickly. If the consumer is slow, server resources will be tied up,+-- and other clients may not be able to update the tables from which+-- the results are being streamed.+--+-- When dealing with small results, it may be simpler (and perhaps+-- faster) to use 'query' instead.+--+-- This fold is /not/ strict. The stream consumer is responsible for+-- forcing the evaluation of its result to avoid space leaks.+--+-- Exceptions that may be thrown:+--+-- * 'FormatError': the query string could not be formatted correctly.+--+-- * 'QueryError': the result contains no columns (i.e. you should be+-- using 'execute' instead of 'query').+--+-- * 'ResultError': result conversion failed.+fold :: (QueryParams q, QueryResults r) =>+ Connection+ -> Query -- ^ Query template.+ -> q -- ^ Query parameters.+ -> a -- ^ Initial state for result consumer.+ -> (a -> r -> IO a) -- ^ Result consumer.+ -> IO a+fold conn template qs z f = do+ Base.query conn =<< formatQuery conn template qs+ finishFold conn template z f++-- | A version of 'fold' that does not perform query substitution.+fold_ :: (QueryResults r) =>+ Connection+ -> Query -- ^ Query.+ -> a -- ^ Initial state for result consumer.+ -> (a -> r -> IO a) -- ^ Result consumer.+ -> IO a+fold_ conn q@(Query que) z f = do+ Base.query conn que+ finishFold conn q z f++-- | A version of 'fold' that does not transform a state value.+forEach :: (QueryParams q, QueryResults r) =>+ Connection+ -> Query -- ^ Query template.+ -> q -- ^ Query parameters.+ -> (r -> IO ()) -- ^ Result consumer.+ -> IO ()+forEach conn template qs = fold conn template qs () . const+{-# INLINE forEach #-}++-- | A version of 'forEach' that does not perform query substitution.+forEach_ :: (QueryResults r) =>+ Connection+ -> Query -- ^ Query template.+ -> (r -> IO ()) -- ^ Result consumer.+ -> IO ()+forEach_ conn template = fold_ conn template () . const+{-# INLINE forEach_ #-}++finishQuery :: (QueryResults r) => Connection -> Query -> IO [r]+finishQuery conn q = withResult (Base.storeResult conn) q $ \r fs ->+ flip fix [] $ \loop acc -> do+ row <- Base.fetchRow r+ case row of+ [] -> return (reverse acc)+ _ -> let !c = convertResults fs row+ in loop (c:acc)++finishFold :: (QueryResults r) =>+ Connection -> Query -> a -> (a -> r -> IO a) -> IO a+finishFold conn q z0 f = withResult (Base.useResult conn) q $ \r fs ->+ flip fix z0 $ \loop z -> do+ row <- Base.fetchRow r+ case row of+ [] -> return z+ _ -> (f z $! convertResults fs row) >>= loop++withResult :: (IO Result) -> Query -> (Result -> [Field] -> IO a) -> IO a+withResult fetchResult q act = bracket fetchResult Base.freeResult $ \r -> do ncols <- Base.fieldCount (Right r) if ncols == 0- then throw $ QueryError "query resulted in zero-column result" q- else do- fs <- Base.fetchFields r- flip fix [] $ \loop acc -> do- row <- Base.fetchRow r- case row of- [] -> return (reverse acc)- _ -> let !c = convertResults fs row- in loop (c:acc)+ then throwIO $ QueryError "query resulted in zero-column result" q+ else act r =<< Base.fetchFields r -- | Execute an action inside a SQL transaction. --@@ -263,7 +344,7 @@ -- 'Base.rollback', then the exception will be rethrown. withTransaction :: Connection -> IO a -> IO a withTransaction conn act = do- execute_ conn "start transaction"+ _ <- execute_ conn "start transaction" r <- act `onException` Base.rollback conn Base.commit conn return r
mysql-simple.cabal view
@@ -1,5 +1,5 @@ name: mysql-simple-version: 0.2.0.2+version: 0.2.1.0 homepage: https://github.com/mailrank/mysql-simple bug-reports: https://github.com/mailrank/mysql-simple/issues synopsis: A mid-level MySQL client library.