@@ -122,7 +122,7 @@ import Data.ByteString.Builder
122 ( Builder, byteString, char8, intDec )
122 ( Builder, byteString, char8, intDec )
123import Control.Applicative ((<$>))
123import Control.Applicative ((<$>))
124import Control.Exception as E
124import Control.Exception as E
125−import Control.Monad (foldM, unless, when, forM_)
125+import Control.Monad (unless)
126import Data.ByteString (ByteString)
126import Data.ByteString (ByteString)
127import Data.Int (Int64)
127import Data.Int (Int64)
128import Data.List (intersperse)
128import Data.List (intersperse)
@@ -142,7 +142,6 @@ import qualified Database.PostgreSQL.LibPQ as PQ
142import qualified Data.ByteString.Char8 as B
142import qualified Data.ByteString.Char8 as B
143import Control.Monad.Trans.Reader
143import Control.Monad.Trans.Reader
144import Control.Monad.Trans.State.Strict
144import Control.Monad.Trans.State.Strict
145−import qualified Control.Monad.Trans.State.Strict as SL
146import Control.Monad.IO.Class (liftIO)
145import Control.Monad.IO.Class (liftIO)
@@ -581,22 +580,26 @@ doFold FoldOptions{..} parser conn _template q a0 f = do
581 <> byteString " FROM "
580 <> byteString " FROM "
582 <> byteString name
581 <> byteString name
584− loop = do
583+ loop a = do
585 result <- liftIO (exec conn q)
584 result <- liftIO (exec conn q)
586 status <- liftIO (PQ.resultStatus result)
585 status <- liftIO (PQ.resultStatus result)
587 case status of
586 case status of
588 PQ.TuplesOk -> do
587 PQ.TuplesOk -> do
589 nrows <- liftIO (PQ.ntuples result)
588 nrows <- liftIO (PQ.ntuples result)
590 ncols <- liftIO (PQ.nfields result)
589 ncols <- liftIO (PQ.nfields result)
591− when (nrows > 0) $ do
590+ if nrows > 0
592− forM_ [0..(nrows-1)] $ \row -> do
591+ then do
593− x <- liftIO (getRowWith parser row ncols conn (Query q) result)
592+ a' <- innerLoop 0 nrows ncols result a
595− a' <- liftIO (f a x)
598 _ -> liftIO (throwResultError "fold" result status)
595 _ -> liftIO (throwResultError "fold" result status)
596+ innerLoop row nrows ncols result a
598+ x <- getRowWith parser row ncols conn result
600+ innerLoop (row+1) nrows ncols result a'
601+ | otherwise = return a
599− in SL.execStateT loop a0
602+ in loop a0
601-- FIXME: choose the Automatic chunkSize more intelligently
604-- FIXME: choose the Automatic chunkSize more intelligently
602-- One possibility is to use the type of the results, although this
605-- One possibility is to use the type of the results, although this
@@ -670,7 +673,7 @@ finishQueryWith parser conn q result = do
670 nrows <- PQ.ntuples result
673 nrows <- PQ.ntuples result
671 ncols <- PQ.nfields result
674 ncols <- PQ.nfields result
672 forM' 0 (nrows-1) $ \row ->
675 forM' 0 (nrows-1) $ \row ->
673− getRowWith parser row ncols conn q result
676+ getRowWith parser row ncols conn result
674 PQ.CopyOut ->
677 PQ.CopyOut ->
675 throwIO $ QueryError "query: COPY TO is not supported" q
678 throwIO $ QueryError "query: COPY TO is not supported" q
676 PQ.CopyIn ->
679 PQ.CopyIn ->
@@ -679,8 +682,8 @@ finishQueryWith parser conn q result = do
679 PQ.NonfatalError -> throwResultError "query" result status
682 PQ.NonfatalError -> throwResultError "query" result status
680 PQ.FatalError -> throwResultError "query" result status
683 PQ.FatalError -> throwResultError "query" result status
682−getRowWith :: RowParser r -> PQ.Row -> PQ.Column -> Connection -> Query -> PQ.Result -> IO r
685+getRowWith :: RowParser r -> PQ.Row -> PQ.Column -> Connection -> PQ.Result -> IO r
683−getRowWith parser row ncols conn q result = do
686+getRowWith parser row ncols conn result = do
684 let rw = Row row result
687 let rw = Row row result
685 let unCol (PQ.Col x) = fromIntegral x :: Int
688 let unCol (PQ.Col x) = fromIntegral x :: Int
686 okvc <- runConversion (runStateT (runReaderT (unRP parser) rw) 0) conn
689 okvc <- runConversion (runStateT (runReaderT (unRP parser) rw) 0) conn